Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  TMS320C67xx code generator for TCC
  3.  *
  4.  *  Copyright (c) 2001, 2002 Fabrice Bellard
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. //#define ASSEMBLY_LISTING_C67
  22.  
  23. /* number of available registers */
  24. #define NB_REGS            24
  25.  
  26. /* a register can belong to several classes. The classes must be
  27.    sorted from more general to more precise (see gv2() code which does
  28.    assumptions on it). */
  29. #define RC_INT     0x0001       /* generic integer register */
  30. #define RC_FLOAT   0x0002       /* generic float register */
  31. #define RC_EAX     0x0004
  32. #define RC_ST0     0x0008
  33. #define RC_ECX     0x0010
  34. #define RC_EDX     0x0020
  35. #define RC_INT_BSIDE  0x00000040        /* generic integer register  on b side */
  36. #define RC_C67_A4     0x00000100
  37. #define RC_C67_A5     0x00000200
  38. #define RC_C67_B4     0x00000400
  39. #define RC_C67_B5     0x00000800
  40. #define RC_C67_A6     0x00001000
  41. #define RC_C67_A7     0x00002000
  42. #define RC_C67_B6     0x00004000
  43. #define RC_C67_B7     0x00008000
  44. #define RC_C67_A8     0x00010000
  45. #define RC_C67_A9     0x00020000
  46. #define RC_C67_B8     0x00040000
  47. #define RC_C67_B9     0x00080000
  48. #define RC_C67_A10    0x00100000
  49. #define RC_C67_A11    0x00200000
  50. #define RC_C67_B10    0x00400000
  51. #define RC_C67_B11    0x00800000
  52. #define RC_C67_A12    0x01000000
  53. #define RC_C67_A13    0x02000000
  54. #define RC_C67_B12    0x04000000
  55. #define RC_C67_B13    0x08000000
  56. #define RC_IRET    RC_C67_A4    /* function return: integer register */
  57. #define RC_LRET    RC_C67_A5    /* function return: second integer register */
  58. #define RC_FRET    RC_C67_A4    /* function return: float register */
  59.  
  60. /* pretty names for the registers */
  61. enum {
  62.     TREG_EAX = 0,               // really A2
  63.     TREG_ECX,                   // really A3
  64.     TREG_EDX,                   // really B0
  65.     TREG_ST0,                   // really B1
  66.     TREG_C67_A4,
  67.     TREG_C67_A5,
  68.     TREG_C67_B4,
  69.     TREG_C67_B5,
  70.     TREG_C67_A6,
  71.     TREG_C67_A7,
  72.     TREG_C67_B6,
  73.     TREG_C67_B7,
  74.     TREG_C67_A8,
  75.     TREG_C67_A9,
  76.     TREG_C67_B8,
  77.     TREG_C67_B9,
  78.     TREG_C67_A10,
  79.     TREG_C67_A11,
  80.     TREG_C67_B10,
  81.     TREG_C67_B11,
  82.     TREG_C67_A12,
  83.     TREG_C67_A13,
  84.     TREG_C67_B12,
  85.     TREG_C67_B13,
  86. };
  87.  
  88. int reg_classes[NB_REGS] = {
  89.                                                 /* eax */ RC_INT | RC_FLOAT | RC_EAX,
  90.                                                 // only allow even regs for floats (allow for doubles)
  91.     /* ecx */ RC_INT | RC_ECX,
  92.                                                                 /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
  93.                                                                 // only allow even regs for floats (allow for doubles)
  94.     /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
  95.     /* A4  */ RC_C67_A4,
  96.     /* A5  */ RC_C67_A5,
  97.     /* B4  */ RC_C67_B4,
  98.     /* B5  */ RC_C67_B5,
  99.     /* A6  */ RC_C67_A6,
  100.     /* A7  */ RC_C67_A7,
  101.     /* B6  */ RC_C67_B6,
  102.     /* B7  */ RC_C67_B7,
  103.     /* A8  */ RC_C67_A8,
  104.     /* A9  */ RC_C67_A9,
  105.     /* B8  */ RC_C67_B8,
  106.     /* B9  */ RC_C67_B9,
  107.     /* A10  */ RC_C67_A10,
  108.     /* A11  */ RC_C67_A11,
  109.     /* B10  */ RC_C67_B10,
  110.     /* B11  */ RC_C67_B11,
  111.     /* A12  */ RC_C67_A10,
  112.     /* A13  */ RC_C67_A11,
  113.     /* B12  */ RC_C67_B10,
  114.     /* B13  */ RC_C67_B11
  115. };
  116.  
  117. /* return registers for function */
  118. #define REG_IRET TREG_C67_A4    /* single word int return register */
  119. #define REG_LRET TREG_C67_A5    /* second word return register (for long long) */
  120. #define REG_FRET TREG_C67_A4    /* float return register */
  121.  
  122.  
  123. #define ALWAYS_ASSERT(x) \
  124. do {\
  125.    if (!(x))\
  126.        error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
  127. } while (0)
  128.  
  129. // although tcc thinks it is passing parameters on the stack,
  130. // the C67 really passes up to the first 10 params in special
  131. // regs or regs pairs (for 64 bit params).  So keep track of
  132. // the stack offsets so we can translate to the appropriate
  133. // reg (pair)
  134.  
  135.  
  136. #define NoCallArgsPassedOnStack 10
  137. int NoOfCurFuncArgs;
  138. int TranslateStackToReg[NoCallArgsPassedOnStack];
  139. int ParamLocOnStack[NoCallArgsPassedOnStack];
  140. int TotalBytesPushedOnStack;
  141.  
  142. /* defined if function parameters must be evaluated in reverse order */
  143.  
  144. //#define INVERT_FUNC_PARAMS
  145.  
  146. /* defined if structures are passed as pointers. Otherwise structures
  147.    are directly pushed on stack. */
  148. //#define FUNC_STRUCT_PARAM_AS_PTR
  149.  
  150. /* pointer size, in bytes */
  151. #define PTR_SIZE 4
  152.  
  153. /* long double size and alignment, in bytes */
  154. #define LDOUBLE_SIZE  12
  155. #define LDOUBLE_ALIGN 4
  156. /* maximum alignment (for aligned attribute support) */
  157. #define MAX_ALIGN     8
  158.  
  159. /******************************************************/
  160. /* ELF defines */
  161.  
  162. #define EM_TCC_TARGET EM_C60
  163.  
  164. /* relocation type for 32 bit data relocation */
  165. #define R_DATA_32   R_C60_32
  166. #define R_JMP_SLOT  R_C60_JMP_SLOT
  167. #define R_COPY      R_C60_COPY
  168.  
  169. #define ELF_START_ADDR 0x00000400
  170. #define ELF_PAGE_SIZE  0x1000
  171.  
  172. /******************************************************/
  173.  
  174. static unsigned long func_sub_sp_offset;
  175. static int func_ret_sub;
  176.  
  177.  
  178. static BOOL C67_invert_test;
  179. static int C67_compare_reg;
  180.  
  181. #ifdef ASSEMBLY_LISTING_C67
  182. FILE *f = NULL;
  183. #endif
  184.  
  185.  
  186. void C67_g(int c)
  187. {
  188.     int ind1;
  189.  
  190. #ifdef ASSEMBLY_LISTING_C67
  191.     fprintf(f, " %08X", c);
  192. #endif
  193.     ind1 = ind + 4;
  194.     if (ind1 > (int) cur_text_section->data_allocated)
  195.         section_realloc(cur_text_section, ind1);
  196.     cur_text_section->data[ind] = c & 0xff;
  197.     cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
  198.     cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
  199.     cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
  200.     ind = ind1;
  201. }
  202.  
  203.  
  204. /* output a symbol and patch all calls to it */
  205. void gsym_addr(int t, int a)
  206. {
  207.     int n, *ptr;
  208.     while (t) {
  209.         ptr = (int *) (cur_text_section->data + t);
  210.         {
  211.             Sym *sym;
  212.  
  213.             // extract 32 bit address from MVKH/MVKL
  214.             n = ((*ptr >> 7) & 0xffff);
  215.             n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
  216.  
  217.             // define a label that will be relocated
  218.  
  219.             sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
  220.             greloc(cur_text_section, sym, t, R_C60LO16);
  221.             greloc(cur_text_section, sym, t + 4, R_C60HI16);
  222.  
  223.             // clear out where the pointer was
  224.  
  225.             *ptr &= ~(0xffff << 7);
  226.             *(ptr + 1) &= ~(0xffff << 7);
  227.         }
  228.         t = n;
  229.     }
  230. }
  231.  
  232. void gsym(int t)
  233. {
  234.     gsym_addr(t, ind);
  235. }
  236.  
  237. // these are regs that tcc doesn't really know about,
  238. // but asign them unique values so the mapping routines
  239. // can distinquish them
  240.  
  241. #define C67_A0 105
  242. #define C67_SP 106
  243. #define C67_B3 107
  244. #define C67_FP 108
  245. #define C67_B2 109
  246. #define C67_CREG_ZERO -1        // Special code for no condition reg test
  247.  
  248.  
  249. int ConvertRegToRegClass(int r)
  250. {
  251.     // only works for A4-B13
  252.  
  253.     return RC_C67_A4 << (r - TREG_C67_A4);
  254. }
  255.  
  256.  
  257. // map TCC reg to C67 reg number
  258.  
  259. int C67_map_regn(int r)
  260. {
  261.     if (r == 0)                 // normal tcc regs
  262.         return 0x2;             // A2
  263.     else if (r == 1)            // normal tcc regs
  264.         return 3;               // A3
  265.     else if (r == 2)            // normal tcc regs
  266.         return 0;               // B0
  267.     else if (r == 3)            // normal tcc regs
  268.         return 1;               // B1
  269.     else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)     // these form a pattern of alt pairs
  270.         return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
  271.     else if (r == C67_A0)
  272.         return 0;               // set to A0 (offset reg)
  273.     else if (r == C67_B2)
  274.         return 2;               // set to B2 (offset reg)
  275.     else if (r == C67_B3)
  276.         return 3;               // set to B3 (return address reg)
  277.     else if (r == C67_SP)
  278.         return 15;              // set to SP (B15) (offset reg)
  279.     else if (r == C67_FP)
  280.         return 15;              // set to FP (A15) (offset reg)
  281.     else if (r == C67_CREG_ZERO)
  282.         return 0;               // Special code for no condition reg test
  283.     else
  284.         ALWAYS_ASSERT(FALSE);
  285.  
  286.     return 0;
  287. }
  288.  
  289. // mapping from tcc reg number to
  290. // C67 register to condition code field
  291. //
  292. // valid condition code regs are:
  293. //
  294. // tcc reg 2 ->B0 -> 1
  295. // tcc reg 3 ->B1 -> 2
  296. // tcc reg 0 -> A2 -> 5
  297. // tcc reg 1 -> A3 -> X
  298. // tcc reg      B2 -> 3
  299.  
  300. int C67_map_regc(int r)
  301. {
  302.     if (r == 0)                 // normal tcc regs
  303.         return 0x5;
  304.     else if (r == 2)            // normal tcc regs
  305.         return 0x1;
  306.     else if (r == 3)            // normal tcc regs
  307.         return 0x2;
  308.     else if (r == C67_B2)       // normal tcc regs
  309.         return 0x3;
  310.     else if (r == C67_CREG_ZERO)
  311.         return 0;               // Special code for no condition reg test
  312.     else
  313.         ALWAYS_ASSERT(FALSE);
  314.  
  315.     return 0;
  316. }
  317.  
  318.  
  319. // map TCC reg to C67 reg side A or B
  320.  
  321. int C67_map_regs(int r)
  322. {
  323.     if (r == 0)                 // normal tcc regs
  324.         return 0x0;
  325.     else if (r == 1)            // normal tcc regs
  326.         return 0x0;
  327.     else if (r == 2)            // normal tcc regs
  328.         return 0x1;
  329.     else if (r == 3)            // normal tcc regs
  330.         return 0x1;
  331.     else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)     // these form a pattern of alt pairs
  332.         return (r & 2) >> 1;
  333.     else if (r == C67_A0)
  334.         return 0;               // set to A side
  335.     else if (r == C67_B2)
  336.         return 1;               // set to B side
  337.     else if (r == C67_B3)
  338.         return 1;               // set to B side
  339.     else if (r == C67_SP)
  340.         return 0x1;             // set to SP (B15) B side
  341.     else if (r == C67_FP)
  342.         return 0x0;             // set to FP (A15) A side
  343.     else
  344.         ALWAYS_ASSERT(FALSE);
  345.  
  346.     return 0;
  347. }
  348.  
  349. int C67_map_S12(char *s)
  350. {
  351.     if (strstr(s, ".S1") != NULL)
  352.         return 0;
  353.     else if (strcmp(s, ".S2"))
  354.         return 1;
  355.     else
  356.         ALWAYS_ASSERT(FALSE);
  357.  
  358.     return 0;
  359. }
  360.  
  361. int C67_map_D12(char *s)
  362. {
  363.     if (strstr(s, ".D1") != NULL)
  364.         return 0;
  365.     else if (strcmp(s, ".D2"))
  366.         return 1;
  367.     else
  368.         ALWAYS_ASSERT(FALSE);
  369.  
  370.     return 0;
  371. }
  372.  
  373.  
  374.  
  375. void C67_asm(char *s, int a, int b, int c)
  376. {
  377.     BOOL xpath;
  378.  
  379. #ifdef ASSEMBLY_LISTING_C67
  380.     if (!f) {
  381.         f = fopen("TCC67_out.txt", "wt");
  382.     }
  383.     fprintf(f, "%04X ", ind);
  384. #endif
  385.  
  386.     if (strstr(s, "MVKL") == s) {
  387.         C67_g((C67_map_regn(b) << 23) |
  388.               ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
  389.     } else if (strstr(s, "MVKH") == s) {
  390.         C67_g((C67_map_regn(b) << 23) |
  391.               (((a >> 16) & 0xffff) << 7) |
  392.               (0x1a << 2) | (C67_map_regs(b) << 1));
  393.     } else if (strstr(s, "STW.D SP POST DEC") == s) {
  394.         C67_g((C67_map_regn(a) << 23) | //src
  395.               (15 << 18) |      //SP B15
  396.               (2 << 13) |       //ucst5 (must keep 8 byte boundary !!)
  397.               (0xa << 9) |      //mode a = post dec ucst
  398.               (0 << 8) |        //r (LDDW bit 0)
  399.               (1 << 7) |        //y D1/D2 use B side
  400.               (7 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  401.               (1 << 2) |        //opcode
  402.               (C67_map_regs(a) << 1) |  //side of src
  403.               (0 << 0));        //parallel
  404.     } else if (strstr(s, "STB.D *+SP[A0]") == s) {
  405.         C67_g((C67_map_regn(a) << 23) | //src
  406.               (15 << 18) |      //base reg A15
  407.               (0 << 13) |       //offset reg A0
  408.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  409.               (0 << 8) |        //r (LDDW bit 0)
  410.               (0 << 7) |        //y D1/D2 A side
  411.               (3 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  412.               (1 << 2) |        //opcode
  413.               (C67_map_regs(a) << 1) |  //side of src
  414.               (0 << 0));        //parallel
  415.     } else if (strstr(s, "STH.D *+SP[A0]") == s) {
  416.         C67_g((C67_map_regn(a) << 23) | //src
  417.               (15 << 18) |      //base reg A15
  418.               (0 << 13) |       //offset reg A0
  419.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  420.               (0 << 8) |        //r (LDDW bit 0)
  421.               (0 << 7) |        //y D1/D2 A side
  422.               (5 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  423.               (1 << 2) |        //opcode
  424.               (C67_map_regs(a) << 1) |  //side of src
  425.               (0 << 0));        //parallel
  426.     } else if (strstr(s, "STB.D *+SP[A0]") == s) {
  427.         C67_g((C67_map_regn(a) << 23) | //src
  428.               (15 << 18) |      //base reg A15
  429.               (0 << 13) |       //offset reg A0
  430.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  431.               (0 << 8) |        //r (LDDW bit 0)
  432.               (0 << 7) |        //y D1/D2 A side
  433.               (3 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  434.               (1 << 2) |        //opcode
  435.               (C67_map_regs(a) << 1) |  //side of src
  436.               (0 << 0));        //parallel
  437.     } else if (strstr(s, "STH.D *+SP[A0]") == s) {
  438.         C67_g((C67_map_regn(a) << 23) | //src
  439.               (15 << 18) |      //base reg A15
  440.               (0 << 13) |       //offset reg A0
  441.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  442.               (0 << 8) |        //r (LDDW bit 0)
  443.               (0 << 7) |        //y D1/D2 A side
  444.               (5 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  445.               (1 << 2) |        //opcode
  446.               (C67_map_regs(a) << 1) |  //side of src
  447.               (0 << 0));        //parallel
  448.     } else if (strstr(s, "STW.D *+SP[A0]") == s) {
  449.         C67_g((C67_map_regn(a) << 23) | //src
  450.               (15 << 18) |      //base reg A15
  451.               (0 << 13) |       //offset reg A0
  452.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  453.               (0 << 8) |        //r (LDDW bit 0)
  454.               (0 << 7) |        //y D1/D2 A side
  455.               (7 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  456.               (1 << 2) |        //opcode
  457.               (C67_map_regs(a) << 1) |  //side of src
  458.               (0 << 0));        //parallel
  459.     } else if (strstr(s, "STW.D *") == s) {
  460.         C67_g((C67_map_regn(a) << 23) | //src
  461.               (C67_map_regn(b) << 18) | //base reg A0
  462.               (0 << 13) |       //cst5
  463.               (1 << 9) |        //mode 1 = pos cst offset
  464.               (0 << 8) |        //r (LDDW bit 0)
  465.               (C67_map_regs(b) << 7) |  //y D1/D2 base reg side
  466.               (7 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  467.               (1 << 2) |        //opcode
  468.               (C67_map_regs(a) << 1) |  //side of src
  469.               (0 << 0));        //parallel
  470.     } else if (strstr(s, "STH.D *") == s) {
  471.         C67_g((C67_map_regn(a) << 23) | //src
  472.               (C67_map_regn(b) << 18) | //base reg A0
  473.               (0 << 13) |       //cst5
  474.               (1 << 9) |        //mode 1 = pos cst offset
  475.               (0 << 8) |        //r (LDDW bit 0)
  476.               (C67_map_regs(b) << 7) |  //y D1/D2 base reg side
  477.               (5 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  478.               (1 << 2) |        //opcode
  479.               (C67_map_regs(a) << 1) |  //side of src
  480.               (0 << 0));        //parallel
  481.     } else if (strstr(s, "STB.D *") == s) {
  482.         C67_g((C67_map_regn(a) << 23) | //src
  483.               (C67_map_regn(b) << 18) | //base reg A0
  484.               (0 << 13) |       //cst5
  485.               (1 << 9) |        //mode 1 = pos cst offset
  486.               (0 << 8) |        //r (LDDW bit 0)
  487.               (C67_map_regs(b) << 7) |  //y D1/D2 base reg side
  488.               (3 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  489.               (1 << 2) |        //opcode
  490.               (C67_map_regs(a) << 1) |  //side of src
  491.               (0 << 0));        //parallel
  492.     } else if (strstr(s, "STW.D +*") == s) {
  493.         ALWAYS_ASSERT(c < 32);
  494.         C67_g((C67_map_regn(a) << 23) | //src
  495.               (C67_map_regn(b) << 18) | //base reg A0
  496.               (c << 13) |       //cst5
  497.               (1 << 9) |        //mode 1 = pos cst offset
  498.               (0 << 8) |        //r (LDDW bit 0)
  499.               (C67_map_regs(b) << 7) |  //y D1/D2 base reg side
  500.               (7 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  501.               (1 << 2) |        //opcode
  502.               (C67_map_regs(a) << 1) |  //side of src
  503.               (0 << 0));        //parallel
  504.     } else if (strstr(s, "LDW.D SP PRE INC") == s) {
  505.         C67_g((C67_map_regn(a) << 23) | //dst
  506.               (15 << 18) |      //base reg B15
  507.               (2 << 13) |       //ucst5 (must keep 8 byte boundary)
  508.               (9 << 9) |        //mode 9 = pre inc ucst5
  509.               (0 << 8) |        //r (LDDW bit 0)
  510.               (1 << 7) |        //y D1/D2  B side
  511.               (6 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  512.               (1 << 2) |        //opcode
  513.               (C67_map_regs(a) << 1) |  //side of dst
  514.               (0 << 0));        //parallel
  515.     } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
  516.         C67_g((C67_map_regn(a) << 23) | //dst
  517.               (15 << 18) |      //base reg B15
  518.               (1 << 13) |       //ucst5 (must keep 8 byte boundary)
  519.               (9 << 9) |        //mode 9 = pre inc ucst5
  520.               (1 << 8) |        //r (LDDW bit 1)
  521.               (1 << 7) |        //y D1/D2  B side
  522.               (6 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  523.               (1 << 2) |        //opcode
  524.               (C67_map_regs(a) << 1) |  //side of dst
  525.               (0 << 0));        //parallel
  526.     } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
  527.         C67_g((C67_map_regn(a) << 23) | //dst
  528.               (15 << 18) |      //base reg A15
  529.               (0 << 13) |       //offset reg A0
  530.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  531.               (0 << 8) |        //r (LDDW bit 0)
  532.               (0 << 7) |        //y D1/D2  A side
  533.               (6 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  534.               (1 << 2) |        //opcode
  535.               (C67_map_regs(a) << 1) |  //side of dst
  536.               (0 << 0));        //parallel
  537.     } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
  538.         C67_g((C67_map_regn(a) << 23) | //dst
  539.               (15 << 18) |      //base reg A15
  540.               (0 << 13) |       //offset reg A0
  541.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  542.               (1 << 8) |        //r (LDDW bit 1)
  543.               (0 << 7) |        //y D1/D2  A side
  544.               (6 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  545.               (1 << 2) |        //opcode
  546.               (C67_map_regs(a) << 1) |  //side of dst
  547.               (0 << 0));        //parallel
  548.     } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
  549.         C67_g((C67_map_regn(a) << 23) | //dst
  550.               (15 << 18) |      //base reg A15
  551.               (0 << 13) |       //offset reg A0
  552.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  553.               (0 << 8) |        //r (LDDW bit 0)
  554.               (0 << 7) |        //y D1/D2  A side
  555.               (4 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  556.               (1 << 2) |        //opcode
  557.               (C67_map_regs(a) << 1) |  //side of dst
  558.               (0 << 0));        //parallel
  559.     } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
  560.         C67_g((C67_map_regn(a) << 23) | //dst
  561.               (15 << 18) |      //base reg A15
  562.               (0 << 13) |       //offset reg A0
  563.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  564.               (0 << 8) |        //r (LDDW bit 0)
  565.               (0 << 7) |        //y D1/D2  A side
  566.               (2 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  567.               (1 << 2) |        //opcode
  568.               (C67_map_regs(a) << 1) |  //side of dst
  569.               (0 << 0));        //parallel
  570.     } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
  571.         C67_g((C67_map_regn(a) << 23) | //dst
  572.               (15 << 18) |      //base reg A15
  573.               (0 << 13) |       //offset reg A0
  574.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  575.               (0 << 8) |        //r (LDDW bit 0)
  576.               (0 << 7) |        //y D1/D2  A side
  577.               (0 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  578.               (1 << 2) |        //opcode
  579.               (C67_map_regs(a) << 1) |  //side of dst
  580.               (0 << 0));        //parallel
  581.     } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
  582.         C67_g((C67_map_regn(a) << 23) | //dst
  583.               (15 << 18) |      //base reg A15
  584.               (0 << 13) |       //offset reg A0
  585.               (5 << 9) |        //mode 5 = pos offset, base reg + off reg
  586.               (0 << 8) |        //r (LDDW bit 0)
  587.               (0 << 7) |        //y D1/D2  A side
  588.               (1 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  589.               (1 << 2) |        //opcode
  590.               (C67_map_regs(a) << 1) |  //side of dst
  591.               (0 << 0));        //parallel
  592.     } else if (strstr(s, "LDW.D *") == s) {
  593.         C67_g((C67_map_regn(b) << 23) | //dst
  594.               (C67_map_regn(a) << 18) | //base reg A15
  595.               (0 << 13) |       //cst5
  596.               (1 << 9) |        //mode 1 = pos cst offset
  597.               (0 << 8) |        //r (LDDW bit 0)
  598.               (C67_map_regs(a) << 7) |  //y D1/D2  src side
  599.               (6 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  600.               (1 << 2) |        //opcode
  601.               (C67_map_regs(b) << 1) |  //side of dst
  602.               (0 << 0));        //parallel
  603.     } else if (strstr(s, "LDDW.D *") == s) {
  604.         C67_g((C67_map_regn(b) << 23) | //dst
  605.               (C67_map_regn(a) << 18) | //base reg A15
  606.               (0 << 13) |       //cst5
  607.               (1 << 9) |        //mode 1 = pos cst offset
  608.               (1 << 8) |        //r (LDDW bit 1)
  609.               (C67_map_regs(a) << 7) |  //y D1/D2  src side
  610.               (6 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  611.               (1 << 2) |        //opcode
  612.               (C67_map_regs(b) << 1) |  //side of dst
  613.               (0 << 0));        //parallel
  614.     } else if (strstr(s, "LDH.D *") == s) {
  615.         C67_g((C67_map_regn(b) << 23) | //dst
  616.               (C67_map_regn(a) << 18) | //base reg A15
  617.               (0 << 13) |       //cst5
  618.               (1 << 9) |        //mode 1 = pos cst offset
  619.               (0 << 8) |        //r (LDDW bit 0)
  620.               (C67_map_regs(a) << 7) |  //y D1/D2  src side
  621.               (4 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  622.               (1 << 2) |        //opcode
  623.               (C67_map_regs(b) << 1) |  //side of dst
  624.               (0 << 0));        //parallel
  625.     } else if (strstr(s, "LDB.D *") == s) {
  626.         C67_g((C67_map_regn(b) << 23) | //dst
  627.               (C67_map_regn(a) << 18) | //base reg A15
  628.               (0 << 13) |       //cst5
  629.               (1 << 9) |        //mode 1 = pos cst offset
  630.               (0 << 8) |        //r (LDDW bit 0)
  631.               (C67_map_regs(a) << 7) |  //y D1/D2  src side
  632.               (2 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  633.               (1 << 2) |        //opcode
  634.               (C67_map_regs(b) << 1) |  //side of dst
  635.               (0 << 0));        //parallel
  636.     } else if (strstr(s, "LDHU.D *") == s) {
  637.         C67_g((C67_map_regn(b) << 23) | //dst
  638.               (C67_map_regn(a) << 18) | //base reg A15
  639.               (0 << 13) |       //cst5
  640.               (1 << 9) |        //mode 1 = pos cst offset
  641.               (0 << 8) |        //r (LDDW bit 0)
  642.               (C67_map_regs(a) << 7) |  //y D1/D2  src side
  643.               (0 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  644.               (1 << 2) |        //opcode
  645.               (C67_map_regs(b) << 1) |  //side of dst
  646.               (0 << 0));        //parallel
  647.     } else if (strstr(s, "LDBU.D *") == s) {
  648.         C67_g((C67_map_regn(b) << 23) | //dst
  649.               (C67_map_regn(a) << 18) | //base reg A15
  650.               (0 << 13) |       //cst5
  651.               (1 << 9) |        //mode 1 = pos cst offset
  652.               (0 << 8) |        //r (LDDW bit 0)
  653.               (C67_map_regs(a) << 7) |  //y D1/D2  src side
  654.               (1 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  655.               (1 << 2) |        //opcode
  656.               (C67_map_regs(b) << 1) |  //side of dst
  657.               (0 << 0));        //parallel
  658.     } else if (strstr(s, "LDW.D +*") == s) {
  659.         C67_g((C67_map_regn(b) << 23) | //dst
  660.               (C67_map_regn(a) << 18) | //base reg A15
  661.               (1 << 13) |       //cst5
  662.               (1 << 9) |        //mode 1 = pos cst offset
  663.               (0 << 8) |        //r (LDDW bit 0)
  664.               (C67_map_regs(a) << 7) |  //y D1/D2  src side
  665.               (6 << 4) |        //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
  666.               (1 << 2) |        //opcode
  667.               (C67_map_regs(b) << 1) |  //side of dst
  668.               (0 << 0));        //parallel
  669.     } else if (strstr(s, "CMPLTSP") == s) {
  670.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  671.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  672.  
  673.         C67_g((C67_map_regn(c) << 23) | //dst
  674.               (C67_map_regn(b) << 18) | //src2
  675.               (C67_map_regn(a) << 13) | //src1
  676.               (xpath << 12) |   //x use cross path for src2
  677.               (0x3a << 6) |     //opcode
  678.               (0x8 << 2) |      //opcode fixed
  679.               (C67_map_regs(c) << 1) |  //side for reg c
  680.               (0 << 0));        //parallel
  681.     } else if (strstr(s, "CMPGTSP") == s) {
  682.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  683.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  684.  
  685.         C67_g((C67_map_regn(c) << 23) | //dst
  686.               (C67_map_regn(b) << 18) | //src2
  687.               (C67_map_regn(a) << 13) | //src1
  688.               (xpath << 12) |   //x use cross path for src2
  689.               (0x39 << 6) |     //opcode
  690.               (0x8 << 2) |      //opcode fixed
  691.               (C67_map_regs(c) << 1) |  //side for reg c
  692.               (0 << 0));        //parallel
  693.     } else if (strstr(s, "CMPEQSP") == s) {
  694.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  695.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  696.  
  697.         C67_g((C67_map_regn(c) << 23) | //dst
  698.               (C67_map_regn(b) << 18) | //src2
  699.               (C67_map_regn(a) << 13) | //src1
  700.               (xpath << 12) |   //x use cross path for src2
  701.               (0x38 << 6) |     //opcode
  702.               (0x8 << 2) |      //opcode fixed
  703.               (C67_map_regs(c) << 1) |  //side for reg c
  704.               (0 << 0));        //parallel
  705.     }
  706.  
  707.     else if (strstr(s, "CMPLTDP") == s) {
  708.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  709.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  710.  
  711.         C67_g((C67_map_regn(c) << 23) | //dst
  712.               (C67_map_regn(b) << 18) | //src2
  713.               (C67_map_regn(a) << 13) | //src1
  714.               (xpath << 12) |   //x use cross path for src2
  715.               (0x2a << 6) |     //opcode
  716.               (0x8 << 2) |      //opcode fixed
  717.               (C67_map_regs(c) << 1) |  //side for reg c
  718.               (0 << 0));        //parallel
  719.     } else if (strstr(s, "CMPGTDP") == s) {
  720.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  721.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  722.  
  723.         C67_g((C67_map_regn(c) << 23) | //dst
  724.               (C67_map_regn(b) << 18) | //src2
  725.               (C67_map_regn(a) << 13) | //src1
  726.               (xpath << 12) |   //x use cross path for src2
  727.               (0x29 << 6) |     //opcode
  728.               (0x8 << 2) |      //opcode fixed
  729.               (C67_map_regs(c) << 1) |  //side for reg c
  730.               (0 << 0));        //parallel
  731.     } else if (strstr(s, "CMPEQDP") == s) {
  732.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  733.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  734.  
  735.         C67_g((C67_map_regn(c) << 23) | //dst
  736.               (C67_map_regn(b) << 18) | //src2
  737.               (C67_map_regn(a) << 13) | //src1
  738.               (xpath << 12) |   //x use cross path for src2
  739.               (0x28 << 6) |     //opcode
  740.               (0x8 << 2) |      //opcode fixed
  741.               (C67_map_regs(c) << 1) |  //side for reg c
  742.               (0 << 0));        //parallel
  743.     } else if (strstr(s, "CMPLT") == s) {
  744.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  745.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  746.  
  747.         C67_g((C67_map_regn(c) << 23) | //dst
  748.               (C67_map_regn(b) << 18) | //src2
  749.               (C67_map_regn(a) << 13) | //src1
  750.               (xpath << 12) |   //x use cross path for src2
  751.               (0x57 << 5) |     //opcode
  752.               (0x6 << 2) |      //opcode fixed
  753.               (C67_map_regs(c) << 1) |  //side for reg c
  754.               (0 << 0));        //parallel
  755.     } else if (strstr(s, "CMPGT") == s) {
  756.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  757.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  758.  
  759.         C67_g((C67_map_regn(c) << 23) | //dst
  760.               (C67_map_regn(b) << 18) | //src2
  761.               (C67_map_regn(a) << 13) | //src1
  762.               (xpath << 12) |   //x use cross path for src2
  763.               (0x47 << 5) |     //opcode
  764.               (0x6 << 2) |      //opcode fixed
  765.               (C67_map_regs(c) << 1) |  //side for reg c
  766.               (0 << 0));        //parallel
  767.     } else if (strstr(s, "CMPEQ") == s) {
  768.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  769.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  770.  
  771.         C67_g((C67_map_regn(c) << 23) | //dst
  772.               (C67_map_regn(b) << 18) | //src2
  773.               (C67_map_regn(a) << 13) | //src1
  774.               (xpath << 12) |   //x use cross path for src2
  775.               (0x53 << 5) |     //opcode
  776.               (0x6 << 2) |      //opcode fixed
  777.               (C67_map_regs(c) << 1) |  //side for reg c
  778.               (0 << 0));        //parallel
  779.     } else if (strstr(s, "CMPLTU") == s) {
  780.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  781.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  782.  
  783.         C67_g((C67_map_regn(c) << 23) | //dst
  784.               (C67_map_regn(b) << 18) | //src2
  785.               (C67_map_regn(a) << 13) | //src1
  786.               (xpath << 12) |   //x use cross path for src2
  787.               (0x5f << 5) |     //opcode
  788.               (0x6 << 2) |      //opcode fixed
  789.               (C67_map_regs(c) << 1) |  //side for reg c
  790.               (0 << 0));        //parallel
  791.     } else if (strstr(s, "CMPGTU") == s) {
  792.         xpath = C67_map_regs(a) ^ C67_map_regs(b);
  793.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  794.  
  795.         C67_g((C67_map_regn(c) << 23) | //dst
  796.               (C67_map_regn(b) << 18) | //src2
  797.               (C67_map_regn(a) << 13) | //src1
  798.               (xpath << 12) |   //x use cross path for src2
  799.               (0x4f << 5) |     //opcode
  800.               (0x6 << 2) |      //opcode fixed
  801.               (C67_map_regs(c) << 1) |  //side for reg c
  802.               (0 << 0));        //parallel
  803.     } else if (strstr(s, "B DISP") == s) {
  804.         C67_g((0 << 29) |       //creg
  805.               (0 << 28) |       //z
  806.               (a << 7) |        //cnst
  807.               (0x4 << 2) |      //opcode fixed
  808.               (0 << 1) |        //S0/S1
  809.               (0 << 0));        //parallel
  810.     } else if (strstr(s, "B.") == s) {
  811.         xpath = C67_map_regs(c) ^ 1;
  812.  
  813.         C67_g((C67_map_regc(b) << 29) | //creg
  814.               (a << 28) |       //inv
  815.               (0 << 23) |       //dst
  816.               (C67_map_regn(c) << 18) | //src2
  817.               (0 << 13) |       //
  818.               (xpath << 12) |   //x cross path if !B side
  819.               (0xd << 6) |      //opcode
  820.               (0x8 << 2) |      //opcode fixed
  821.               (1 << 1) |        //must be S2
  822.               (0 << 0));        //parallel
  823.     } else if (strstr(s, "MV.L") == s) {
  824.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  825.  
  826.         C67_g((0 << 29) |       //creg
  827.               (0 << 28) |       //inv
  828.               (C67_map_regn(c) << 23) | //dst
  829.               (C67_map_regn(b) << 18) | //src2
  830.               (0 << 13) |       //src1 (cst5)
  831.               (xpath << 12) |   //x cross path if opposite sides
  832.               (0x2 << 5) |      //opcode
  833.               (0x6 << 2) |      //opcode fixed
  834.               (C67_map_regs(c) << 1) |  //side of dest
  835.               (0 << 0));        //parallel
  836.     } else if (strstr(s, "SPTRUNC.L") == s) {
  837.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  838.  
  839.         C67_g((0 << 29) |       //creg
  840.               (0 << 28) |       //inv
  841.               (C67_map_regn(c) << 23) | //dst
  842.               (C67_map_regn(b) << 18) | //src2
  843.               (0 << 13) |       //src1 NA
  844.               (xpath << 12) |   //x cross path if opposite sides
  845.               (0xb << 5) |      //opcode
  846.               (0x6 << 2) |      //opcode fixed
  847.               (C67_map_regs(c) << 1) |  //side of dest
  848.               (0 << 0));        //parallel
  849.     } else if (strstr(s, "DPTRUNC.L") == s) {
  850.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  851.  
  852.         C67_g((0 << 29) |       //creg
  853.               (0 << 28) |       //inv
  854.               (C67_map_regn(c) << 23) | //dst
  855.               ((C67_map_regn(b) + 1) << 18) |   //src2   WEIRD CPU must specify odd reg for some reason
  856.               (0 << 13) |       //src1 NA
  857.               (xpath << 12) |   //x cross path if opposite sides
  858.               (0x1 << 5) |      //opcode
  859.               (0x6 << 2) |      //opcode fixed
  860.               (C67_map_regs(c) << 1) |  //side of dest
  861.               (0 << 0));        //parallel
  862.     } else if (strstr(s, "INTSP.L") == s) {
  863.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  864.  
  865.         C67_g((0 << 29) |       //creg
  866.               (0 << 28) |       //inv
  867.               (C67_map_regn(c) << 23) | //dst
  868.               (C67_map_regn(b) << 18) | //src2  
  869.               (0 << 13) |       //src1 NA
  870.               (xpath << 12) |   //x cross path if opposite sides
  871.               (0x4a << 5) |     //opcode
  872.               (0x6 << 2) |      //opcode fixed
  873.               (C67_map_regs(c) << 1) |  //side of dest
  874.               (0 << 0));        //parallel
  875.     } else if (strstr(s, "INTSPU.L") == s) {
  876.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  877.  
  878.         C67_g((0 << 29) |       //creg
  879.               (0 << 28) |       //inv
  880.               (C67_map_regn(c) << 23) | //dst
  881.               (C67_map_regn(b) << 18) | //src2  
  882.               (0 << 13) |       //src1 NA
  883.               (xpath << 12) |   //x cross path if opposite sides
  884.               (0x49 << 5) |     //opcode
  885.               (0x6 << 2) |      //opcode fixed
  886.               (C67_map_regs(c) << 1) |  //side of dest
  887.               (0 << 0));        //parallel
  888.     } else if (strstr(s, "INTDP.L") == s) {
  889.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  890.  
  891.         C67_g((0 << 29) |       //creg
  892.               (0 << 28) |       //inv
  893.               (C67_map_regn(c) << 23) | //dst
  894.               (C67_map_regn(b) << 18) | //src2  
  895.               (0 << 13) |       //src1 NA
  896.               (xpath << 12) |   //x cross path if opposite sides
  897.               (0x39 << 5) |     //opcode
  898.               (0x6 << 2) |      //opcode fixed
  899.               (C67_map_regs(c) << 1) |  //side of dest
  900.               (0 << 0));        //parallel
  901.     } else if (strstr(s, "INTDPU.L") == s) {
  902.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  903.  
  904.         C67_g((0 << 29) |       //creg
  905.               (0 << 28) |       //inv
  906.               (C67_map_regn(c) << 23) | //dst
  907.               ((C67_map_regn(b) + 1) << 18) |   //src2   WEIRD CPU must specify odd reg for some reason
  908.               (0 << 13) |       //src1 NA
  909.               (xpath << 12) |   //x cross path if opposite sides
  910.               (0x3b << 5) |     //opcode
  911.               (0x6 << 2) |      //opcode fixed
  912.               (C67_map_regs(c) << 1) |  //side of dest
  913.               (0 << 0));        //parallel
  914.     } else if (strstr(s, "SPDP.L") == s) {
  915.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  916.  
  917.         C67_g((0 << 29) |       //creg
  918.               (0 << 28) |       //inv
  919.               (C67_map_regn(c) << 23) | //dst
  920.               (C67_map_regn(b) << 18) | //src2
  921.               (0 << 13) |       //src1 NA
  922.               (xpath << 12) |   //x cross path if opposite sides
  923.               (0x2 << 6) |      //opcode
  924.               (0x8 << 2) |      //opcode fixed
  925.               (C67_map_regs(c) << 1) |  //side of dest
  926.               (0 << 0));        //parallel
  927.     } else if (strstr(s, "DPSP.L") == s) {
  928.         ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
  929.  
  930.         C67_g((0 << 29) |       //creg
  931.               (0 << 28) |       //inv
  932.               (C67_map_regn(c) << 23) | //dst
  933.               ((C67_map_regn(b) + 1) << 18) |   //src2 WEIRD CPU must specify odd reg for some reason
  934.               (0 << 13) |       //src1 NA
  935.               (0 << 12) |       //x cross path if opposite sides
  936.               (0x9 << 5) |      //opcode
  937.               (0x6 << 2) |      //opcode fixed
  938.               (C67_map_regs(c) << 1) |  //side of dest
  939.               (0 << 0));        //parallel
  940.     } else if (strstr(s, "ADD.L") == s) {
  941.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  942.  
  943.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  944.  
  945.         C67_g((0 << 29) |       //creg
  946.               (0 << 28) |       //inv
  947.               (C67_map_regn(c) << 23) | //dst
  948.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  949.               (C67_map_regn(a) << 13) | //src1
  950.               (xpath << 12) |   //x cross path if opposite sides
  951.               (0x3 << 5) |      //opcode
  952.               (0x6 << 2) |      //opcode fixed
  953.               (C67_map_regs(c) << 1) |  //side of dest
  954.               (0 << 0));        //parallel
  955.     } else if (strstr(s, "SUB.L") == s) {
  956.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  957.  
  958.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  959.  
  960.         C67_g((0 << 29) |       //creg
  961.               (0 << 28) |       //inv
  962.               (C67_map_regn(c) << 23) | //dst
  963.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  964.               (C67_map_regn(a) << 13) | //src1
  965.               (xpath << 12) |   //x cross path if opposite sides
  966.               (0x7 << 5) |      //opcode
  967.               (0x6 << 2) |      //opcode fixed
  968.               (C67_map_regs(c) << 1) |  //side of dest
  969.               (0 << 0));        //parallel
  970.     } else if (strstr(s, "OR.L") == s) {
  971.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  972.  
  973.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  974.  
  975.         C67_g((0 << 29) |       //creg
  976.               (0 << 28) |       //inv
  977.               (C67_map_regn(c) << 23) | //dst
  978.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  979.               (C67_map_regn(a) << 13) | //src1
  980.               (xpath << 12) |   //x cross path if opposite sides
  981.               (0x7f << 5) |     //opcode
  982.               (0x6 << 2) |      //opcode fixed
  983.               (C67_map_regs(c) << 1) |  //side of dest
  984.               (0 << 0));        //parallel
  985.     } else if (strstr(s, "AND.L") == s) {
  986.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  987.  
  988.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  989.  
  990.         C67_g((0 << 29) |       //creg
  991.               (0 << 28) |       //inv
  992.               (C67_map_regn(c) << 23) | //dst
  993.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  994.               (C67_map_regn(a) << 13) | //src1
  995.               (xpath << 12) |   //x cross path if opposite sides
  996.               (0x7b << 5) |     //opcode
  997.               (0x6 << 2) |      //opcode fixed
  998.               (C67_map_regs(c) << 1) |  //side of dest
  999.               (0 << 0));        //parallel
  1000.     } else if (strstr(s, "XOR.L") == s) {
  1001.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1002.  
  1003.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1004.  
  1005.         C67_g((0 << 29) |       //creg
  1006.               (0 << 28) |       //inv
  1007.               (C67_map_regn(c) << 23) | //dst
  1008.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  1009.               (C67_map_regn(a) << 13) | //src1
  1010.               (xpath << 12) |   //x cross path if opposite sides
  1011.               (0x6f << 5) |     //opcode
  1012.               (0x6 << 2) |      //opcode fixed
  1013.               (C67_map_regs(c) << 1) |  //side of dest
  1014.               (0 << 0));        //parallel
  1015.     } else if (strstr(s, "ADDSP.L") == s) {
  1016.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1017.  
  1018.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1019.  
  1020.         C67_g((0 << 29) |       //creg
  1021.               (0 << 28) |       //inv
  1022.               (C67_map_regn(c) << 23) | //dst
  1023.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  1024.               (C67_map_regn(a) << 13) | //src1
  1025.               (xpath << 12) |   //x cross path if opposite sides
  1026.               (0x10 << 5) |     //opcode
  1027.               (0x6 << 2) |      //opcode fixed
  1028.               (C67_map_regs(c) << 1) |  //side of dest
  1029.               (0 << 0));        //parallel
  1030.     } else if (strstr(s, "ADDDP.L") == s) {
  1031.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1032.  
  1033.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1034.  
  1035.         C67_g((0 << 29) |       //creg
  1036.               (0 << 28) |       //inv
  1037.               (C67_map_regn(c) << 23) | //dst
  1038.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  1039.               (C67_map_regn(a) << 13) | //src1
  1040.               (xpath << 12) |   //x cross path if opposite sides
  1041.               (0x18 << 5) |     //opcode
  1042.               (0x6 << 2) |      //opcode fixed
  1043.               (C67_map_regs(c) << 1) |  //side of dest
  1044.               (0 << 0));        //parallel
  1045.     } else if (strstr(s, "SUBSP.L") == s) {
  1046.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1047.  
  1048.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1049.  
  1050.         C67_g((0 << 29) |       //creg
  1051.               (0 << 28) |       //inv
  1052.               (C67_map_regn(c) << 23) | //dst
  1053.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  1054.               (C67_map_regn(a) << 13) | //src1
  1055.               (xpath << 12) |   //x cross path if opposite sides
  1056.               (0x11 << 5) |     //opcode
  1057.               (0x6 << 2) |      //opcode fixed
  1058.               (C67_map_regs(c) << 1) |  //side of dest
  1059.               (0 << 0));        //parallel
  1060.     } else if (strstr(s, "SUBDP.L") == s) {
  1061.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1062.  
  1063.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1064.  
  1065.         C67_g((0 << 29) |       //creg
  1066.               (0 << 28) |       //inv
  1067.               (C67_map_regn(c) << 23) | //dst
  1068.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  1069.               (C67_map_regn(a) << 13) | //src1
  1070.               (xpath << 12) |   //x cross path if opposite sides
  1071.               (0x19 << 5) |     //opcode
  1072.               (0x6 << 2) |      //opcode fixed
  1073.               (C67_map_regs(c) << 1) |  //side of dest
  1074.               (0 << 0));        //parallel
  1075.     } else if (strstr(s, "MPYSP.M") == s) {
  1076.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1077.  
  1078.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1079.  
  1080.         C67_g((0 << 29) |       //creg
  1081.               (0 << 28) |       //inv
  1082.               (C67_map_regn(c) << 23) | //dst
  1083.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  1084.               (C67_map_regn(a) << 13) | //src1
  1085.               (xpath << 12) |   //x cross path if opposite sides
  1086.               (0x1c << 7) |     //opcode
  1087.               (0x0 << 2) |      //opcode fixed
  1088.               (C67_map_regs(c) << 1) |  //side of dest
  1089.               (0 << 0));        //parallel
  1090.     } else if (strstr(s, "MPYDP.M") == s) {
  1091.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1092.  
  1093.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1094.  
  1095.         C67_g((0 << 29) |       //creg
  1096.               (0 << 28) |       //inv
  1097.               (C67_map_regn(c) << 23) | //dst
  1098.               (C67_map_regn(b) << 18) | //src2 (possible x path)
  1099.               (C67_map_regn(a) << 13) | //src1
  1100.               (xpath << 12) |   //x cross path if opposite sides
  1101.               (0x0e << 7) |     //opcode
  1102.               (0x0 << 2) |      //opcode fixed
  1103.               (C67_map_regs(c) << 1) |  //side of dest
  1104.               (0 << 0));        //parallel
  1105.     } else if (strstr(s, "MPYI.M") == s) {
  1106.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1107.  
  1108.         ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
  1109.  
  1110.         C67_g((0 << 29) |       //creg
  1111.               (0 << 28) |       //inv
  1112.               (C67_map_regn(c) << 23) | //dst
  1113.               (C67_map_regn(b) << 18) | //src2
  1114.               (C67_map_regn(a) << 13) | //src1 (cst5)
  1115.               (xpath << 12) |   //x cross path if opposite sides
  1116.               (0x4 << 7) |      //opcode
  1117.               (0x0 << 2) |      //opcode fixed
  1118.               (C67_map_regs(c) << 1) |  //side of dest
  1119.               (0 << 0));        //parallel
  1120.     } else if (strstr(s, "SHR.S") == s) {
  1121.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1122.  
  1123.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  1124.  
  1125.         C67_g((0 << 29) |       //creg
  1126.               (0 << 28) |       //inv
  1127.               (C67_map_regn(c) << 23) | //dst
  1128.               (C67_map_regn(b) << 18) | //src2
  1129.               (C67_map_regn(a) << 13) | //src1
  1130.               (xpath << 12) |   //x cross path if opposite sides
  1131.               (0x37 << 6) |     //opcode
  1132.               (0x8 << 2) |      //opcode fixed
  1133.               (C67_map_regs(c) << 1) |  //side of dest
  1134.               (0 << 0));        //parallel
  1135.     } else if (strstr(s, "SHRU.S") == s) {
  1136.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1137.  
  1138.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  1139.  
  1140.         C67_g((0 << 29) |       //creg
  1141.               (0 << 28) |       //inv
  1142.               (C67_map_regn(c) << 23) | //dst
  1143.               (C67_map_regn(b) << 18) | //src2
  1144.               (C67_map_regn(a) << 13) | //src1
  1145.               (xpath << 12) |   //x cross path if opposite sides
  1146.               (0x27 << 6) |     //opcode
  1147.               (0x8 << 2) |      //opcode fixed
  1148.               (C67_map_regs(c) << 1) |  //side of dest
  1149.               (0 << 0));        //parallel
  1150.     } else if (strstr(s, "SHL.S") == s) {
  1151.         xpath = C67_map_regs(b) ^ C67_map_regs(c);
  1152.  
  1153.         ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
  1154.  
  1155.         C67_g((0 << 29) |       //creg
  1156.               (0 << 28) |       //inv
  1157.               (C67_map_regn(c) << 23) | //dst
  1158.               (C67_map_regn(b) << 18) | //src2
  1159.               (C67_map_regn(a) << 13) | //src1
  1160.               (xpath << 12) |   //x cross path if opposite sides
  1161.               (0x33 << 6) |     //opcode
  1162.               (0x8 << 2) |      //opcode fixed
  1163.               (C67_map_regs(c) << 1) |  //side of dest
  1164.               (0 << 0));        //parallel
  1165.     } else if (strstr(s, "||ADDK") == s) {
  1166.         xpath = 0;              // no xpath required just use the side of the src/dst
  1167.  
  1168.         C67_g((0 << 29) |       //creg
  1169.               (0 << 28) |       //inv
  1170.               (C67_map_regn(b) << 23) | //dst
  1171.               (a << 07) |       //scst16
  1172.               (0x14 << 2) |     //opcode fixed
  1173.               (C67_map_regs(b) << 1) |  //side of dst
  1174.               (1 << 0));        //parallel
  1175.     } else if (strstr(s, "ADDK") == s) {
  1176.         xpath = 0;              // no xpath required just use the side of the src/dst
  1177.  
  1178.         C67_g((0 << 29) |       //creg
  1179.               (0 << 28) |       //inv
  1180.               (C67_map_regn(b) << 23) | //dst
  1181.               (a << 07) |       //scst16
  1182.               (0x14 << 2) |     //opcode fixed
  1183.               (C67_map_regs(b) << 1) |  //side of dst
  1184.               (0 << 0));        //parallel
  1185.     } else if (strstr(s, "NOP") == s) {
  1186.         C67_g(((a - 1) << 13) | //no of cycles
  1187.               (0 << 0));        //parallel
  1188.     } else
  1189.         ALWAYS_ASSERT(FALSE);
  1190.  
  1191. #ifdef ASSEMBLY_LISTING_C67
  1192.     fprintf(f, " %s %d %d %d\n", s, a, b, c);
  1193. #endif
  1194.  
  1195. }
  1196.  
  1197. //r=reg to load, fr=from reg, symbol for relocation, constant
  1198.  
  1199. void C67_MVKL(int r, int fc)
  1200. {
  1201.     C67_asm("MVKL.", fc, r, 0);
  1202. }
  1203.  
  1204. void C67_MVKH(int r, int fc)
  1205. {
  1206.     C67_asm("MVKH.", fc, r, 0);
  1207. }
  1208.  
  1209. void C67_STB_SP_A0(int r)
  1210. {
  1211.     C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB  r,*+SP[A0]
  1212. }
  1213.  
  1214. void C67_STH_SP_A0(int r)
  1215. {
  1216.     C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH  r,*+SP[A0]
  1217. }
  1218.  
  1219. void C67_STW_SP_A0(int r)
  1220. {
  1221.     C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW  r,*+SP[A0]
  1222. }
  1223.  
  1224. void C67_STB_PTR(int r, int r2)
  1225. {
  1226.     C67_asm("STB.D *", r, r2, 0);       // STB  r, *r2
  1227. }
  1228.  
  1229. void C67_STH_PTR(int r, int r2)
  1230. {
  1231.     C67_asm("STH.D *", r, r2, 0);       // STH  r, *r2
  1232. }
  1233.  
  1234. void C67_STW_PTR(int r, int r2)
  1235. {
  1236.     C67_asm("STW.D *", r, r2, 0);       // STW  r, *r2
  1237. }
  1238.  
  1239. void C67_STW_PTR_PRE_INC(int r, int r2, int n)
  1240. {
  1241.     C67_asm("STW.D +*", r, r2, n);      // STW  r, *+r2
  1242. }
  1243.  
  1244. void C67_PUSH(int r)
  1245. {
  1246.     C67_asm("STW.D SP POST DEC", r, 0, 0);      // STW  r,*SP--
  1247. }
  1248.  
  1249. void C67_LDW_SP_A0(int r)
  1250. {
  1251.     C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW  *+SP[A0],r
  1252. }
  1253.  
  1254. void C67_LDDW_SP_A0(int r)
  1255. {
  1256.     C67_asm("LDDW.D *+SP[A0]", r, 0, 0);        // LDDW  *+SP[A0],r
  1257. }
  1258.  
  1259. void C67_LDH_SP_A0(int r)
  1260. {
  1261.     C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH  *+SP[A0],r
  1262. }
  1263.  
  1264. void C67_LDB_SP_A0(int r)
  1265. {
  1266.     C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB  *+SP[A0],r
  1267. }
  1268.  
  1269. void C67_LDHU_SP_A0(int r)
  1270. {
  1271.     C67_asm("LDHU.D *+SP[A0]", r, 0, 0);        // LDHU  *+SP[A0],r
  1272. }
  1273.  
  1274. void C67_LDBU_SP_A0(int r)
  1275. {
  1276.     C67_asm("LDBU.D *+SP[A0]", r, 0, 0);        // LDBU  *+SP[A0],r
  1277. }
  1278.  
  1279. void C67_LDW_PTR(int r, int r2)
  1280. {
  1281.     C67_asm("LDW.D *", r, r2, 0);       // LDW  *r,r2
  1282. }
  1283.  
  1284. void C67_LDDW_PTR(int r, int r2)
  1285. {
  1286.     C67_asm("LDDW.D *", r, r2, 0);      // LDDW  *r,r2
  1287. }
  1288.  
  1289. void C67_LDH_PTR(int r, int r2)
  1290. {
  1291.     C67_asm("LDH.D *", r, r2, 0);       // LDH  *r,r2
  1292. }
  1293.  
  1294. void C67_LDB_PTR(int r, int r2)
  1295. {
  1296.     C67_asm("LDB.D *", r, r2, 0);       // LDB  *r,r2
  1297. }
  1298.  
  1299. void C67_LDHU_PTR(int r, int r2)
  1300. {
  1301.     C67_asm("LDHU.D *", r, r2, 0);      // LDHU  *r,r2
  1302. }
  1303.  
  1304. void C67_LDBU_PTR(int r, int r2)
  1305. {
  1306.     C67_asm("LDBU.D *", r, r2, 0);      // LDBU  *r,r2
  1307. }
  1308.  
  1309. void C67_LDW_PTR_PRE_INC(int r, int r2)
  1310. {
  1311.     C67_asm("LDW.D +*", r, r2, 0);      // LDW  *+r,r2
  1312. }
  1313.  
  1314. void C67_POP(int r)
  1315. {
  1316.     C67_asm("LDW.D SP PRE INC", r, 0, 0);       // LDW  *++SP,r
  1317. }
  1318.  
  1319. void C67_POP_DW(int r)
  1320. {
  1321.     C67_asm("LDDW.D SP PRE INC", r, 0, 0);      // LDDW  *++SP,r
  1322. }
  1323.  
  1324. void C67_CMPLT(int s1, int s2, int dst)
  1325. {
  1326.     C67_asm("CMPLT.L1", s1, s2, dst);
  1327. }
  1328.  
  1329. void C67_CMPGT(int s1, int s2, int dst)
  1330. {
  1331.     C67_asm("CMPGT.L1", s1, s2, dst);
  1332. }
  1333.  
  1334. void C67_CMPEQ(int s1, int s2, int dst)
  1335. {
  1336.     C67_asm("CMPEQ.L1", s1, s2, dst);
  1337. }
  1338.  
  1339. void C67_CMPLTU(int s1, int s2, int dst)
  1340. {
  1341.     C67_asm("CMPLTU.L1", s1, s2, dst);
  1342. }
  1343.  
  1344. void C67_CMPGTU(int s1, int s2, int dst)
  1345. {
  1346.     C67_asm("CMPGTU.L1", s1, s2, dst);
  1347. }
  1348.  
  1349.  
  1350. void C67_CMPLTSP(int s1, int s2, int dst)
  1351. {
  1352.     C67_asm("CMPLTSP.S1", s1, s2, dst);
  1353. }
  1354.  
  1355. void C67_CMPGTSP(int s1, int s2, int dst)
  1356. {
  1357.     C67_asm("CMPGTSP.S1", s1, s2, dst);
  1358. }
  1359.  
  1360. void C67_CMPEQSP(int s1, int s2, int dst)
  1361. {
  1362.     C67_asm("CMPEQSP.S1", s1, s2, dst);
  1363. }
  1364.  
  1365. void C67_CMPLTDP(int s1, int s2, int dst)
  1366. {
  1367.     C67_asm("CMPLTDP.S1", s1, s2, dst);
  1368. }
  1369.  
  1370. void C67_CMPGTDP(int s1, int s2, int dst)
  1371. {
  1372.     C67_asm("CMPGTDP.S1", s1, s2, dst);
  1373. }
  1374.  
  1375. void C67_CMPEQDP(int s1, int s2, int dst)
  1376. {
  1377.     C67_asm("CMPEQDP.S1", s1, s2, dst);
  1378. }
  1379.  
  1380.  
  1381. void C67_IREG_B_REG(int inv, int r1, int r2)    // [!R] B  r2
  1382. {
  1383.     C67_asm("B.S2", inv, r1, r2);
  1384. }
  1385.  
  1386.  
  1387. // call with how many 32 bit words to skip
  1388. // (0 would branch to the branch instruction)
  1389.  
  1390. void C67_B_DISP(int disp)       //  B  +2  Branch with constant displacement
  1391. {
  1392.     // Branch point is relative to the 8 word fetch packet
  1393.     //
  1394.     // we will assume the text section always starts on an 8 word (32 byte boundary)
  1395.     //
  1396.     // so add in how many words into the fetch packet the branch is
  1397.  
  1398.  
  1399.     C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
  1400. }
  1401.  
  1402. void C67_NOP(int n)
  1403. {
  1404.     C67_asm("NOP", n, 0, 0);
  1405. }
  1406.  
  1407. void C67_ADDK(int n, int r)
  1408. {
  1409.     ALWAYS_ASSERT(abs(n) < 32767);
  1410.  
  1411.     C67_asm("ADDK", n, r, 0);
  1412. }
  1413.  
  1414. void C67_ADDK_PARALLEL(int n, int r)
  1415. {
  1416.     ALWAYS_ASSERT(abs(n) < 32767);
  1417.  
  1418.     C67_asm("||ADDK", n, r, 0);
  1419. }
  1420.  
  1421. void C67_Adjust_ADDK(int *inst, int n)
  1422. {
  1423.     ALWAYS_ASSERT(abs(n) < 32767);
  1424.  
  1425.     *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
  1426. }
  1427.  
  1428. void C67_MV(int r, int v)
  1429. {
  1430.     C67_asm("MV.L", 0, r, v);
  1431. }
  1432.  
  1433.  
  1434. void C67_DPTRUNC(int r, int v)
  1435. {
  1436.     C67_asm("DPTRUNC.L", 0, r, v);
  1437. }
  1438.  
  1439. void C67_SPTRUNC(int r, int v)
  1440. {
  1441.     C67_asm("SPTRUNC.L", 0, r, v);
  1442. }
  1443.  
  1444. void C67_INTSP(int r, int v)
  1445. {
  1446.     C67_asm("INTSP.L", 0, r, v);
  1447. }
  1448.  
  1449. void C67_INTDP(int r, int v)
  1450. {
  1451.     C67_asm("INTDP.L", 0, r, v);
  1452. }
  1453.  
  1454. void C67_INTSPU(int r, int v)
  1455. {
  1456.     C67_asm("INTSPU.L", 0, r, v);
  1457. }
  1458.  
  1459. void C67_INTDPU(int r, int v)
  1460. {
  1461.     C67_asm("INTDPU.L", 0, r, v);
  1462. }
  1463.  
  1464. void C67_SPDP(int r, int v)
  1465. {
  1466.     C67_asm("SPDP.L", 0, r, v);
  1467. }
  1468.  
  1469. void C67_DPSP(int r, int v)     // note regs must be on the same side
  1470. {
  1471.     C67_asm("DPSP.L", 0, r, v);
  1472. }
  1473.  
  1474. void C67_ADD(int r, int v)
  1475. {
  1476.     C67_asm("ADD.L", v, r, v);
  1477. }
  1478.  
  1479. void C67_SUB(int r, int v)
  1480. {
  1481.     C67_asm("SUB.L", v, r, v);
  1482. }
  1483.  
  1484. void C67_AND(int r, int v)
  1485. {
  1486.     C67_asm("AND.L", v, r, v);
  1487. }
  1488.  
  1489. void C67_OR(int r, int v)
  1490. {
  1491.     C67_asm("OR.L", v, r, v);
  1492. }
  1493.  
  1494. void C67_XOR(int r, int v)
  1495. {
  1496.     C67_asm("XOR.L", v, r, v);
  1497. }
  1498.  
  1499. void C67_ADDSP(int r, int v)
  1500. {
  1501.     C67_asm("ADDSP.L", v, r, v);
  1502. }
  1503.  
  1504. void C67_SUBSP(int r, int v)
  1505. {
  1506.     C67_asm("SUBSP.L", v, r, v);
  1507. }
  1508.  
  1509. void C67_MPYSP(int r, int v)
  1510. {
  1511.     C67_asm("MPYSP.M", v, r, v);
  1512. }
  1513.  
  1514. void C67_ADDDP(int r, int v)
  1515. {
  1516.     C67_asm("ADDDP.L", v, r, v);
  1517. }
  1518.  
  1519. void C67_SUBDP(int r, int v)
  1520. {
  1521.     C67_asm("SUBDP.L", v, r, v);
  1522. }
  1523.  
  1524. void C67_MPYDP(int r, int v)
  1525. {
  1526.     C67_asm("MPYDP.M", v, r, v);
  1527. }
  1528.  
  1529. void C67_MPYI(int r, int v)
  1530. {
  1531.     C67_asm("MPYI.M", v, r, v);
  1532. }
  1533.  
  1534. void C67_SHL(int r, int v)
  1535. {
  1536.     C67_asm("SHL.S", r, v, v);
  1537. }
  1538.  
  1539. void C67_SHRU(int r, int v)
  1540. {
  1541.     C67_asm("SHRU.S", r, v, v);
  1542. }
  1543.  
  1544. void C67_SHR(int r, int v)
  1545. {
  1546.     C67_asm("SHR.S", r, v, v);
  1547. }
  1548.  
  1549.  
  1550.  
  1551. /* load 'r' from value 'sv' */
  1552. void load(int r, SValue * sv)
  1553. {
  1554.     int v, t, ft, fc, fr, size = 0, element;
  1555.     BOOL Unsigned = false;
  1556.     SValue v1;
  1557.  
  1558.     fr = sv->r;
  1559.     ft = sv->type.t;
  1560.     fc = sv->c.ul;
  1561.  
  1562.     v = fr & VT_VALMASK;
  1563.     if (fr & VT_LVAL) {
  1564.         if (v == VT_LLOCAL) {
  1565.             v1.type.t = VT_INT;
  1566.             v1.r = VT_LOCAL | VT_LVAL;
  1567.             v1.c.ul = fc;
  1568.             load(r, &v1);
  1569.             fr = r;
  1570.         } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
  1571.             error("long double not supported");
  1572.         } else if ((ft & VT_TYPE) == VT_BYTE) {
  1573.             size = 1;
  1574.         } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
  1575.             size = 1;
  1576.             Unsigned = TRUE;
  1577.         } else if ((ft & VT_TYPE) == VT_SHORT) {
  1578.             size = 2;
  1579.         } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
  1580.             size = 2;
  1581.             Unsigned = TRUE;
  1582.         } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
  1583.             size = 8;
  1584.         } else {
  1585.             size = 4;
  1586.         }
  1587.  
  1588.         // check if fc is a positive reference on the stack,
  1589.         // if it is tcc is referencing what it thinks is a parameter
  1590.         // on the stack, so check if it is really in a register.
  1591.  
  1592.  
  1593.         if (v == VT_LOCAL && fc > 0) {
  1594.             int stack_pos = 8;
  1595.  
  1596.             for (t = 0; t < NoCallArgsPassedOnStack; t++) {
  1597.                 if (fc == stack_pos)
  1598.                     break;
  1599.  
  1600.                 stack_pos += TranslateStackToReg[t];
  1601.             }
  1602.  
  1603.             // param has been pushed on stack, get it like a local var
  1604.  
  1605.             fc = ParamLocOnStack[t] - 8;
  1606.         }
  1607.  
  1608.         if ((fr & VT_VALMASK) < VT_CONST)       // check for pure indirect
  1609.         {
  1610.             if (size == 1) {
  1611.                 if (Unsigned)
  1612.                     C67_LDBU_PTR(v, r); // LDBU  *v,r
  1613.                 else
  1614.                     C67_LDB_PTR(v, r);  // LDB  *v,r
  1615.             } else if (size == 2) {
  1616.                 if (Unsigned)
  1617.                     C67_LDHU_PTR(v, r); // LDHU  *v,r
  1618.                 else
  1619.                     C67_LDH_PTR(v, r);  // LDH  *v,r
  1620.             } else if (size == 4) {
  1621.                 C67_LDW_PTR(v, r);      // LDW  *v,r
  1622.             } else if (size == 8) {
  1623.                 C67_LDDW_PTR(v, r);     // LDDW  *v,r
  1624.             }
  1625.  
  1626.             C67_NOP(4);         // NOP 4
  1627.             return;
  1628.         } else if (fr & VT_SYM) {
  1629.             greloc(cur_text_section, sv->sym, ind, R_C60LO16);  // rem the inst need to be patched
  1630.             greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
  1631.  
  1632.  
  1633.             C67_MVKL(C67_A0, fc);       //r=reg to load,  constant
  1634.             C67_MVKH(C67_A0, fc);       //r=reg to load,  constant
  1635.  
  1636.  
  1637.             if (size == 1) {
  1638.                 if (Unsigned)
  1639.                     C67_LDBU_PTR(C67_A0, r);    // LDBU  *A0,r
  1640.                 else
  1641.                     C67_LDB_PTR(C67_A0, r);     // LDB  *A0,r
  1642.             } else if (size == 2) {
  1643.                 if (Unsigned)
  1644.                     C67_LDHU_PTR(C67_A0, r);    // LDHU  *A0,r
  1645.                 else
  1646.                     C67_LDH_PTR(C67_A0, r);     // LDH  *A0,r
  1647.             } else if (size == 4) {
  1648.                 C67_LDW_PTR(C67_A0, r); // LDW  *A0,r
  1649.             } else if (size == 8) {
  1650.                 C67_LDDW_PTR(C67_A0, r);        // LDDW  *A0,r
  1651.             }
  1652.  
  1653.             C67_NOP(4);         // NOP 4
  1654.             return;
  1655.         } else {
  1656.             element = size;
  1657.  
  1658.             // divide offset in bytes to create element index
  1659.             C67_MVKL(C67_A0, (fc / element) + 8 / element);     //r=reg to load,  constant
  1660.             C67_MVKH(C67_A0, (fc / element) + 8 / element);     //r=reg to load,  constant
  1661.  
  1662.             if (size == 1) {
  1663.                 if (Unsigned)
  1664.                     C67_LDBU_SP_A0(r);  // LDBU  r, SP[A0]
  1665.                 else
  1666.                     C67_LDB_SP_A0(r);   // LDB  r, SP[A0]
  1667.             } else if (size == 2) {
  1668.                 if (Unsigned)
  1669.                     C67_LDHU_SP_A0(r);  // LDHU  r, SP[A0]
  1670.                 else
  1671.                     C67_LDH_SP_A0(r);   // LDH  r, SP[A0]
  1672.             } else if (size == 4) {
  1673.                 C67_LDW_SP_A0(r);       // LDW  r, SP[A0]
  1674.             } else if (size == 8) {
  1675.                 C67_LDDW_SP_A0(r);      // LDDW  r, SP[A0]
  1676.             }
  1677.  
  1678.  
  1679.             C67_NOP(4);         // NOP 4
  1680.             return;
  1681.         }
  1682.     } else {
  1683.         if (v == VT_CONST) {
  1684.             if (fr & VT_SYM) {
  1685.                 greloc(cur_text_section, sv->sym, ind, R_C60LO16);      // rem the inst need to be patched
  1686.                 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
  1687.             }
  1688.             C67_MVKL(r, fc);    //r=reg to load, constant
  1689.             C67_MVKH(r, fc);    //r=reg to load, constant
  1690.         } else if (v == VT_LOCAL) {
  1691.             C67_MVKL(r, fc + 8);        //r=reg to load, constant C67 stack points to next free
  1692.             C67_MVKH(r, fc + 8);        //r=reg to load, constant
  1693.             C67_ADD(C67_FP, r); // MV v,r   v -> r
  1694.         } else if (v == VT_CMP) {
  1695.             C67_MV(C67_compare_reg, r); // MV v,r   v -> r
  1696.         } else if (v == VT_JMP || v == VT_JMPI) {
  1697.             t = v & 1;
  1698.             C67_B_DISP(4);      //  Branch with constant displacement, skip over this branch, load, nop, load
  1699.             C67_MVKL(r, t);     //  r=reg to load, 0 or 1 (do this while branching)
  1700.             C67_NOP(4);         //  NOP 4
  1701.             gsym(fc);           //  modifies other branches to branch here
  1702.             C67_MVKL(r, t ^ 1); //  r=reg to load, 0 or 1
  1703.         } else if (v != r) {
  1704.             C67_MV(v, r);       // MV v,r   v -> r
  1705.  
  1706.             if ((ft & VT_BTYPE) == VT_DOUBLE)
  1707.                 C67_MV(v + 1, r + 1);   // MV v,r   v -> r
  1708.         }
  1709.     }
  1710. }
  1711.  
  1712.  
  1713. /* store register 'r' in lvalue 'v' */
  1714. void store(int r, SValue * v)
  1715. {
  1716.     int fr, bt, ft, fc, size, t, element;
  1717.  
  1718.     ft = v->type.t;
  1719.     fc = v->c.ul;
  1720.     fr = v->r & VT_VALMASK;
  1721.     bt = ft & VT_BTYPE;
  1722.     /* XXX: incorrect if float reg to reg */
  1723.  
  1724.     if (bt == VT_LDOUBLE) {
  1725.         error("long double not supported");
  1726.     } else {
  1727.         if (bt == VT_SHORT)
  1728.             size = 2;
  1729.         else if (bt == VT_BYTE)
  1730.             size = 1;
  1731.         else if (bt == VT_DOUBLE)
  1732.             size = 8;
  1733.         else
  1734.             size = 4;
  1735.  
  1736.         if ((v->r & VT_VALMASK) == VT_CONST) {
  1737.             /* constant memory reference */
  1738.  
  1739.             if (v->r & VT_SYM) {
  1740.                 greloc(cur_text_section, v->sym, ind, R_C60LO16);       // rem the inst need to be patched
  1741.                 greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
  1742.             }
  1743.             C67_MVKL(C67_A0, fc);       //r=reg to load,  constant
  1744.             C67_MVKH(C67_A0, fc);       //r=reg to load,  constant
  1745.  
  1746.             if (size == 1)
  1747.                 C67_STB_PTR(r, C67_A0); // STB  r, *A0
  1748.             else if (size == 2)
  1749.                 C67_STH_PTR(r, C67_A0); // STH  r, *A0
  1750.             else if (size == 4 || size == 8)
  1751.                 C67_STW_PTR(r, C67_A0); // STW  r, *A0
  1752.  
  1753.             if (size == 8)
  1754.                 C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1);  // STW  r, *+A0[1]
  1755.         } else if ((v->r & VT_VALMASK) == VT_LOCAL) {
  1756.             // check case of storing to passed argument that
  1757.             // tcc thinks is on the stack but for C67 is
  1758.             // passed as a reg.  However it may have been
  1759.             // saved to the stack, if that reg was required
  1760.             // for a call to a child function
  1761.  
  1762.             if (fc > 0)         // argument ??
  1763.             {
  1764.                 // walk through sizes and figure which param
  1765.  
  1766.                 int stack_pos = 8;
  1767.  
  1768.                 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
  1769.                     if (fc == stack_pos)
  1770.                         break;
  1771.  
  1772.                     stack_pos += TranslateStackToReg[t];
  1773.                 }
  1774.  
  1775.                 // param has been pushed on stack, get it like a local var
  1776.                 fc = ParamLocOnStack[t] - 8;
  1777.             }
  1778.  
  1779.             if (size == 8)
  1780.                 element = 4;
  1781.             else
  1782.                 element = size;
  1783.  
  1784.             // divide offset in bytes to create word index
  1785.             C67_MVKL(C67_A0, (fc / element) + 8 / element);     //r=reg to load,  constant
  1786.             C67_MVKH(C67_A0, (fc / element) + 8 / element);     //r=reg to load,  constant
  1787.  
  1788.  
  1789.  
  1790.             if (size == 1)
  1791.                 C67_STB_SP_A0(r);       // STB  r, SP[A0]
  1792.             else if (size == 2)
  1793.                 C67_STH_SP_A0(r);       // STH  r, SP[A0]
  1794.             else if (size == 4 || size == 8)
  1795.                 C67_STW_SP_A0(r);       // STW  r, SP[A0]
  1796.  
  1797.             if (size == 8) {
  1798.                 C67_ADDK(1, C67_A0);    //  ADDK 1,A0
  1799.                 C67_STW_SP_A0(r + 1);   //  STW  r, SP[A0]
  1800.             }
  1801.         } else {
  1802.             if (size == 1)
  1803.                 C67_STB_PTR(r, fr);     // STB  r, *fr
  1804.             else if (size == 2)
  1805.                 C67_STH_PTR(r, fr);     // STH  r, *fr
  1806.             else if (size == 4 || size == 8)
  1807.                 C67_STW_PTR(r, fr);     // STW  r, *fr
  1808.  
  1809.             if (size == 8) {
  1810.                 C67_STW_PTR_PRE_INC(r + 1, fr, 1);      // STW  r, *+fr[1]
  1811.             }
  1812.         }
  1813.     }
  1814. }
  1815.  
  1816. /* 'is_jmp' is '1' if it is a jump */
  1817. static void gcall_or_jmp(int is_jmp)
  1818. {
  1819.     int r;
  1820.     Sym *sym;
  1821.  
  1822.     if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
  1823.         /* constant case */
  1824.         if (vtop->r & VT_SYM) {
  1825.             /* relocation case */
  1826.  
  1827.             // get add into A0, then start the jump B3
  1828.  
  1829.             greloc(cur_text_section, vtop->sym, ind, R_C60LO16);        // rem the inst need to be patched
  1830.             greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
  1831.  
  1832.             C67_MVKL(C67_A0, 0);        //r=reg to load, constant
  1833.             C67_MVKH(C67_A0, 0);        //r=reg to load, constant
  1834.             C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);   //  B.S2x  A0
  1835.  
  1836.             if (is_jmp) {
  1837.                 C67_NOP(5);     // simple jump, just put NOP
  1838.             } else {
  1839.                 // Call, must load return address into B3 during delay slots
  1840.  
  1841.                 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);   // symbol for return address
  1842.                 greloc(cur_text_section, sym, ind, R_C60LO16);  // rem the inst need to be patched
  1843.                 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
  1844.                 C67_MVKL(C67_B3, 0);    //r=reg to load, constant
  1845.                 C67_MVKH(C67_B3, 0);    //r=reg to load, constant
  1846.                 C67_NOP(3);     // put remaining NOPs
  1847.             }
  1848.         } else {
  1849.             /* put an empty PC32 relocation */
  1850.             ALWAYS_ASSERT(FALSE);
  1851.         }
  1852.     } else {
  1853.         /* otherwise, indirect call */
  1854.         r = gv(RC_INT);
  1855.         C67_IREG_B_REG(0, C67_CREG_ZERO, r);    //  B.S2x  r
  1856.  
  1857.         if (is_jmp) {
  1858.             C67_NOP(5);         // simple jump, just put NOP
  1859.         } else {
  1860.             // Call, must load return address into B3 during delay slots
  1861.  
  1862.             sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);       // symbol for return address
  1863.             greloc(cur_text_section, sym, ind, R_C60LO16);      // rem the inst need to be patched
  1864.             greloc(cur_text_section, sym, ind + 4, R_C60HI16);
  1865.             C67_MVKL(C67_B3, 0);        //r=reg to load, constant
  1866.             C67_MVKH(C67_B3, 0);        //r=reg to load, constant
  1867.             C67_NOP(3);         // put remaining NOPs
  1868.         }
  1869.     }
  1870. }
  1871.  
  1872. /* generate function call with address in (vtop->t, vtop->c) and free function
  1873.    context. Stack entry is popped */
  1874. void gfunc_call(int nb_args)
  1875. {
  1876.     int i, r, size = 0;
  1877.     int args_sizes[NoCallArgsPassedOnStack];
  1878.  
  1879.     if (nb_args > NoCallArgsPassedOnStack) {
  1880.         error("more than 10 function params not currently supported");
  1881.         // handle more than 10, put some on the stack
  1882.     }
  1883.  
  1884.     for (i = 0; i < nb_args; i++) {
  1885.         if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
  1886.             ALWAYS_ASSERT(FALSE);
  1887.         } else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
  1888.             ALWAYS_ASSERT(FALSE);
  1889.         } else {
  1890.             /* simple type (currently always same size) */
  1891.             /* XXX: implicit cast ? */
  1892.  
  1893.  
  1894.             if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
  1895.                 error("long long not supported");
  1896.             } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
  1897.                 error("long double not supported");
  1898.             } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
  1899.                 size = 8;
  1900.             } else {
  1901.                 size = 4;
  1902.             }
  1903.  
  1904.             // put the parameter into the corresponding reg (pair)
  1905.  
  1906.             r = gv(RC_C67_A4 << (2 * i));
  1907.  
  1908.             // must put on stack because with 1 pass compiler , no way to tell
  1909.             // if an up coming nested call might overwrite these regs
  1910.  
  1911.             C67_PUSH(r);
  1912.  
  1913.             if (size == 8) {
  1914.                 C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3);  // STW  r, *+SP[3] (go back and put the other)
  1915.             }
  1916.             args_sizes[i] = size;
  1917.         }
  1918.         vtop--;
  1919.     }
  1920.     // POP all the params on the stack into registers for the
  1921.     // immediate call (in reverse order)
  1922.  
  1923.     for (i = nb_args - 1; i >= 0; i--) {
  1924.  
  1925.         if (args_sizes[i] == 8)
  1926.             C67_POP_DW(TREG_C67_A4 + i * 2);
  1927.         else
  1928.             C67_POP(TREG_C67_A4 + i * 2);
  1929.     }
  1930.     gcall_or_jmp(0);
  1931.     vtop--;
  1932. }
  1933.  
  1934.  
  1935. // to be compatible with Code Composer for the C67
  1936. // the first 10 parameters must be passed in registers
  1937. // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
  1938. // ending with B12:B13.
  1939. //
  1940. // When a call is made, if the caller has its parameters
  1941. // in regs A4-B13 these must be saved before/as the call
  1942. // parameters are loaded and restored upon return (or if/when needed).
  1943.  
  1944. /* generate function prolog of type 't' */
  1945. void gfunc_prolog(CType * func_type)
  1946. {
  1947.     int addr, align, size, func_call, i;
  1948.     Sym *sym;
  1949.     CType *type;
  1950.  
  1951.     sym = func_type->ref;
  1952.     func_call = sym->r;
  1953.     addr = 8;
  1954.     /* if the function returns a structure, then add an
  1955.        implicit pointer parameter */
  1956.     func_vt = sym->type;
  1957.     if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
  1958.         func_vc = addr;
  1959.         addr += 4;
  1960.     }
  1961.  
  1962.     NoOfCurFuncArgs = 0;
  1963.  
  1964.     /* define parameters */
  1965.     while ((sym = sym->next) != NULL) {
  1966.         type = &sym->type;
  1967.         sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
  1968.         size = type_size(type, &align);
  1969.         size = (size + 3) & ~3;
  1970.  
  1971.         // keep track of size of arguments so
  1972.         // we can translate where tcc thinks they
  1973.         // are on the stack into the appropriate reg
  1974.  
  1975.         TranslateStackToReg[NoOfCurFuncArgs] = size;
  1976.         NoOfCurFuncArgs++;
  1977.  
  1978. #ifdef FUNC_STRUCT_PARAM_AS_PTR
  1979.         /* structs are passed as pointer */
  1980.         if ((type->t & VT_BTYPE) == VT_STRUCT) {
  1981.             size = 4;
  1982.         }
  1983. #endif
  1984.         addr += size;
  1985.     }
  1986.     func_ret_sub = 0;
  1987.     /* pascal type call ? */
  1988.     if (func_call == FUNC_STDCALL)
  1989.         func_ret_sub = addr - 8;
  1990.  
  1991.     C67_MV(C67_FP, C67_A0);     //  move FP -> A0
  1992.     C67_MV(C67_SP, C67_FP);     //  move SP -> FP
  1993.  
  1994.     // place all the args passed in regs onto the stack
  1995.  
  1996.     loc = 0;
  1997.     for (i = 0; i < NoOfCurFuncArgs; i++) {
  1998.  
  1999.         ParamLocOnStack[i] = loc;       // remember where the param is
  2000.         loc += -8;
  2001.  
  2002.         C67_PUSH(TREG_C67_A4 + i * 2);
  2003.  
  2004.         if (TranslateStackToReg[i] == 8) {
  2005.             C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3);    // STW  r, *+SP[1] (go back and put the other)
  2006.         }
  2007.     }
  2008.  
  2009.     TotalBytesPushedOnStack = -loc;
  2010.  
  2011.     func_sub_sp_offset = ind;   // remember where we put the stack instruction
  2012.     C67_ADDK(0, C67_SP);        //  ADDK.L2 loc,SP  (just put zero temporarily)
  2013.  
  2014.     C67_PUSH(C67_A0);
  2015.     C67_PUSH(C67_B3);
  2016. }
  2017.  
  2018. /* generate function epilog */
  2019. void gfunc_epilog(void)
  2020. {
  2021.     {
  2022.         int local = (-loc + 7) & -8;    // stack must stay aligned to 8 bytes for LDDW instr
  2023.         C67_POP(C67_B3);
  2024.         C67_NOP(4);             // NOP wait for load
  2025.         C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3);       //  B.S2  B3
  2026.         C67_POP(C67_FP);
  2027.         C67_ADDK(local, C67_SP);        //  ADDK.L2 loc,SP  
  2028.         C67_Adjust_ADDK((int *) (cur_text_section->data +
  2029.                                  func_sub_sp_offset),
  2030.                         -local + TotalBytesPushedOnStack);
  2031.         C67_NOP(3);             // NOP
  2032.     }
  2033. }
  2034.  
  2035. /* generate a jump to a label */
  2036. int gjmp(int t)
  2037. {
  2038.     int ind1 = ind;
  2039.  
  2040.     C67_MVKL(C67_A0, t);        //r=reg to load,  constant
  2041.     C67_MVKH(C67_A0, t);        //r=reg to load,  constant
  2042.     C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);   // [!R] B.S2x  A0
  2043.     C67_NOP(5);
  2044.     return ind1;
  2045. }
  2046.  
  2047. /* generate a jump to a fixed address */
  2048. void gjmp_addr(int a)
  2049. {
  2050.     Sym *sym;
  2051.     // I guess this routine is used for relative short
  2052.     // local jumps, for now just handle it as the general
  2053.     // case
  2054.  
  2055.     // define a label that will be relocated
  2056.  
  2057.     sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
  2058.     greloc(cur_text_section, sym, ind, R_C60LO16);
  2059.     greloc(cur_text_section, sym, ind + 4, R_C60HI16);
  2060.  
  2061.     gjmp(0);                    // place a zero there later the symbol will be added to it
  2062. }
  2063.  
  2064. /* generate a test. set 'inv' to invert test. Stack entry is popped */
  2065. int gtst(int inv, int t)
  2066. {
  2067.     int ind1, n;
  2068.     int v, *p;
  2069.  
  2070.     v = vtop->r & VT_VALMASK;
  2071.     if (v == VT_CMP) {
  2072.         /* fast case : can jump directly since flags are set */
  2073.         // C67 uses B2 sort of as flags register
  2074.         ind1 = ind;
  2075.         C67_MVKL(C67_A0, t);    //r=reg to load, constant
  2076.         C67_MVKH(C67_A0, t);    //r=reg to load, constant
  2077.  
  2078.         if (C67_compare_reg != TREG_EAX &&      // check if not already in a conditional test reg
  2079.             C67_compare_reg != TREG_EDX &&
  2080.             C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
  2081.             C67_MV(C67_compare_reg, C67_B2);
  2082.             C67_compare_reg = C67_B2;
  2083.         }
  2084.  
  2085.         C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x  A0
  2086.         C67_NOP(5);
  2087.         t = ind1;               //return where we need to patch
  2088.  
  2089.     } else if (v == VT_JMP || v == VT_JMPI) {
  2090.         /* && or || optimization */
  2091.         if ((v & 1) == inv) {
  2092.             /* insert vtop->c jump list in t */
  2093.             p = &vtop->c.i;
  2094.  
  2095.             // I guess the idea is to traverse to the
  2096.             // null at the end of the list and store t
  2097.             // there
  2098.  
  2099.             n = *p;
  2100.             while (n != 0) {
  2101.                 p = (int *) (cur_text_section->data + n);
  2102.  
  2103.                 // extract 32 bit address from MVKH/MVKL
  2104.                 n = ((*p >> 7) & 0xffff);
  2105.                 n |= ((*(p + 1) >> 7) & 0xffff) << 16;
  2106.             }
  2107.             *p |= (t & 0xffff) << 7;
  2108.             *(p + 1) |= ((t >> 16) & 0xffff) << 7;
  2109.             t = vtop->c.i;
  2110.  
  2111.         } else {
  2112.             t = gjmp(t);
  2113.             gsym(vtop->c.i);
  2114.         }
  2115.     } else {
  2116.         if (is_float(vtop->type.t)) {
  2117.             vpushi(0);
  2118.             gen_op(TOK_NE);
  2119.         }
  2120.         if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
  2121.             /* constant jmp optimization */
  2122.             if ((vtop->c.i != 0) != inv)
  2123.                 t = gjmp(t);
  2124.         } else {
  2125.             // I think we need to get the value on the stack
  2126.             // into a register, test it, and generate a branch
  2127.             // return the address of the branch, so it can be
  2128.             // later patched
  2129.  
  2130.             v = gv(RC_INT);     // get value into a reg
  2131.             ind1 = ind;
  2132.             C67_MVKL(C67_A0, t);        //r=reg to load, constant
  2133.             C67_MVKH(C67_A0, t);        //r=reg to load, constant
  2134.  
  2135.             if (v != TREG_EAX &&        // check if not already in a conditional test reg
  2136.                 v != TREG_EDX && v != TREG_ST0 && v != C67_B2) {
  2137.                 C67_MV(v, C67_B2);
  2138.                 v = C67_B2;
  2139.             }
  2140.  
  2141.             C67_IREG_B_REG(inv, v, C67_A0);     // [!R] B.S2x  A0
  2142.             C67_NOP(5);
  2143.             t = ind1;           //return where we need to patch
  2144.             ind1 = ind;
  2145.         }
  2146.     }
  2147.     vtop--;
  2148.     return t;
  2149. }
  2150.  
  2151. /* generate an integer binary operation */
  2152. void gen_opi(int op)
  2153. {
  2154.     int r, fr, opc, t;
  2155.  
  2156.     switch (op) {
  2157.     case '+':
  2158.     case TOK_ADDC1:             /* add with carry generation */
  2159.         opc = 0;
  2160.       gen_op8:
  2161.  
  2162.  
  2163. // C67 can't do const compares, must load into a reg
  2164. // so just go to gv2 directly - tktk
  2165.  
  2166.  
  2167.  
  2168.         if (op >= TOK_ULT && op <= TOK_GT)
  2169.             gv2(RC_INT_BSIDE, RC_INT);  // make sure r (src1) is on the B Side of CPU
  2170.         else
  2171.             gv2(RC_INT, RC_INT);
  2172.  
  2173.         r = vtop[-1].r;
  2174.         fr = vtop[0].r;
  2175.  
  2176.         C67_compare_reg = C67_B2;
  2177.  
  2178.  
  2179.         if (op == TOK_LT) {
  2180.             C67_CMPLT(r, fr, C67_B2);
  2181.             C67_invert_test = false;
  2182.         } else if (op == TOK_GE) {
  2183.             C67_CMPLT(r, fr, C67_B2);
  2184.             C67_invert_test = true;
  2185.         } else if (op == TOK_GT) {
  2186.             C67_CMPGT(r, fr, C67_B2);
  2187.             C67_invert_test = false;
  2188.         } else if (op == TOK_LE) {
  2189.             C67_CMPGT(r, fr, C67_B2);
  2190.             C67_invert_test = true;
  2191.         } else if (op == TOK_EQ) {
  2192.             C67_CMPEQ(r, fr, C67_B2);
  2193.             C67_invert_test = false;
  2194.         } else if (op == TOK_NE) {
  2195.             C67_CMPEQ(r, fr, C67_B2);
  2196.             C67_invert_test = true;
  2197.         } else if (op == TOK_ULT) {
  2198.             C67_CMPLTU(r, fr, C67_B2);
  2199.             C67_invert_test = false;
  2200.         } else if (op == TOK_UGE) {
  2201.             C67_CMPLTU(r, fr, C67_B2);
  2202.             C67_invert_test = true;
  2203.         } else if (op == TOK_UGT) {
  2204.             C67_CMPGTU(r, fr, C67_B2);
  2205.             C67_invert_test = false;
  2206.         } else if (op == TOK_ULE) {
  2207.             C67_CMPGTU(r, fr, C67_B2);
  2208.             C67_invert_test = true;
  2209.         } else if (op == '+')
  2210.             C67_ADD(fr, r);     // ADD  r,fr,r
  2211.         else if (op == '-')
  2212.             C67_SUB(fr, r);     // SUB  r,fr,r
  2213.         else if (op == '&')
  2214.             C67_AND(fr, r);     // AND  r,fr,r
  2215.         else if (op == '|')
  2216.             C67_OR(fr, r);      // OR  r,fr,r
  2217.         else if (op == '^')
  2218.             C67_XOR(fr, r);     // XOR  r,fr,r
  2219.         else
  2220.             ALWAYS_ASSERT(FALSE);
  2221.  
  2222.         vtop--;
  2223.         if (op >= TOK_ULT && op <= TOK_GT) {
  2224.             vtop->r = VT_CMP;
  2225.             vtop->c.i = op;
  2226.         }
  2227.         break;
  2228.     case '-':
  2229.     case TOK_SUBC1:             /* sub with carry generation */
  2230.         opc = 5;
  2231.         goto gen_op8;
  2232.     case TOK_ADDC2:             /* add with carry use */
  2233.         opc = 2;
  2234.         goto gen_op8;
  2235.     case TOK_SUBC2:             /* sub with carry use */
  2236.         opc = 3;
  2237.         goto gen_op8;
  2238.     case '&':
  2239.         opc = 4;
  2240.         goto gen_op8;
  2241.     case '^':
  2242.         opc = 6;
  2243.         goto gen_op8;
  2244.     case '|':
  2245.         opc = 1;
  2246.         goto gen_op8;
  2247.     case '*':
  2248.     case TOK_UMULL:
  2249.         gv2(RC_INT, RC_INT);
  2250.         r = vtop[-1].r;
  2251.         fr = vtop[0].r;
  2252.         vtop--;
  2253.         C67_MPYI(fr, r);        // 32 bit bultiply  fr,r,fr
  2254.         C67_NOP(8);             // NOP 8 for worst case
  2255.         break;
  2256.     case TOK_SHL:
  2257.         gv2(RC_INT_BSIDE, RC_INT_BSIDE);        // shift amount must be on same side as dst
  2258.         r = vtop[-1].r;
  2259.         fr = vtop[0].r;
  2260.         vtop--;
  2261.         C67_SHL(fr, r);         // arithmetic/logical shift
  2262.         break;
  2263.  
  2264.     case TOK_SHR:
  2265.         gv2(RC_INT_BSIDE, RC_INT_BSIDE);        // shift amount must be on same side as dst
  2266.         r = vtop[-1].r;
  2267.         fr = vtop[0].r;
  2268.         vtop--;
  2269.         C67_SHRU(fr, r);        // logical shift
  2270.         break;
  2271.  
  2272.     case TOK_SAR:
  2273.         gv2(RC_INT_BSIDE, RC_INT_BSIDE);        // shift amount must be on same side as dst
  2274.         r = vtop[-1].r;
  2275.         fr = vtop[0].r;
  2276.         vtop--;
  2277.         C67_SHR(fr, r);         // arithmetic shift
  2278.         break;
  2279.  
  2280.     case '/':
  2281.         t = TOK__divi;
  2282.       call_func:
  2283.         vswap();
  2284.         /* call generic idiv function */
  2285.         vpush_global_sym(&func_old_type, t);
  2286.         vrott(3);
  2287.         gfunc_call(2);
  2288.         vpushi(0);
  2289.         vtop->r = REG_IRET;
  2290.         vtop->r2 = VT_CONST;
  2291.         break;
  2292.     case TOK_UDIV:
  2293.     case TOK_PDIV:
  2294.         t = TOK__divu;
  2295.         goto call_func;
  2296.     case '%':
  2297.         t = TOK__remi;
  2298.         goto call_func;
  2299.     case TOK_UMOD:
  2300.         t = TOK__remu;
  2301.         goto call_func;
  2302.  
  2303.     default:
  2304.         opc = 7;
  2305.         goto gen_op8;
  2306.     }
  2307. }
  2308.  
  2309. /* generate a floating point operation 'v = t1 op t2' instruction. The
  2310.    two operands are guaranted to have the same floating point type */
  2311. /* XXX: need to use ST1 too */
  2312. void gen_opf(int op)
  2313. {
  2314.     int ft, fc, fr, r;
  2315.  
  2316.     if (op >= TOK_ULT && op <= TOK_GT)
  2317.         gv2(RC_EDX, RC_EAX);    // make sure src2 is on b side
  2318.     else
  2319.         gv2(RC_FLOAT, RC_FLOAT);        // make sure src2 is on b side
  2320.  
  2321.     ft = vtop->type.t;
  2322.     fc = vtop->c.ul;
  2323.     r = vtop->r;
  2324.     fr = vtop[-1].r;
  2325.  
  2326.  
  2327.     if ((ft & VT_BTYPE) == VT_LDOUBLE)
  2328.         error("long doubles not supported");
  2329.  
  2330.     if (op >= TOK_ULT && op <= TOK_GT) {
  2331.  
  2332.         r = vtop[-1].r;
  2333.         fr = vtop[0].r;
  2334.  
  2335.         C67_compare_reg = C67_B2;
  2336.  
  2337.         if (op == TOK_LT) {
  2338.             if ((ft & VT_BTYPE) == VT_DOUBLE)
  2339.                 C67_CMPLTDP(r, fr, C67_B2);
  2340.             else
  2341.                 C67_CMPLTSP(r, fr, C67_B2);
  2342.  
  2343.             C67_invert_test = false;
  2344.         } else if (op == TOK_GE) {
  2345.             if ((ft & VT_BTYPE) == VT_DOUBLE)
  2346.                 C67_CMPLTDP(r, fr, C67_B2);
  2347.             else
  2348.                 C67_CMPLTSP(r, fr, C67_B2);
  2349.  
  2350.             C67_invert_test = true;
  2351.         } else if (op == TOK_GT) {
  2352.             if ((ft & VT_BTYPE) == VT_DOUBLE)
  2353.                 C67_CMPGTDP(r, fr, C67_B2);
  2354.             else
  2355.                 C67_CMPGTSP(r, fr, C67_B2);
  2356.  
  2357.             C67_invert_test = false;
  2358.         } else if (op == TOK_LE) {
  2359.             if ((ft & VT_BTYPE) == VT_DOUBLE)
  2360.                 C67_CMPGTDP(r, fr, C67_B2);
  2361.             else
  2362.                 C67_CMPGTSP(r, fr, C67_B2);
  2363.  
  2364.             C67_invert_test = true;
  2365.         } else if (op == TOK_EQ) {
  2366.             if ((ft & VT_BTYPE) == VT_DOUBLE)
  2367.                 C67_CMPEQDP(r, fr, C67_B2);
  2368.             else
  2369.                 C67_CMPEQSP(r, fr, C67_B2);
  2370.  
  2371.             C67_invert_test = false;
  2372.         } else if (op == TOK_NE) {
  2373.             if ((ft & VT_BTYPE) == VT_DOUBLE)
  2374.                 C67_CMPEQDP(r, fr, C67_B2);
  2375.             else
  2376.                 C67_CMPEQSP(r, fr, C67_B2);
  2377.  
  2378.             C67_invert_test = true;
  2379.         } else {
  2380.             ALWAYS_ASSERT(FALSE);
  2381.         }
  2382.         vtop->r = VT_CMP;       // tell TCC that result is in "flags" actually B2
  2383.     } else {
  2384.         if (op == '+') {
  2385.             if ((ft & VT_BTYPE) == VT_DOUBLE) {
  2386.                 C67_ADDDP(r, fr);       // ADD  fr,r,fr
  2387.                 C67_NOP(6);
  2388.             } else {
  2389.                 C67_ADDSP(r, fr);       // ADD  fr,r,fr
  2390.                 C67_NOP(3);
  2391.             }
  2392.             vtop--;
  2393.         } else if (op == '-') {
  2394.             if ((ft & VT_BTYPE) == VT_DOUBLE) {
  2395.                 C67_SUBDP(r, fr);       // SUB  fr,r,fr
  2396.                 C67_NOP(6);
  2397.             } else {
  2398.                 C67_SUBSP(r, fr);       // SUB  fr,r,fr
  2399.                 C67_NOP(3);
  2400.             }
  2401.             vtop--;
  2402.         } else if (op == '*') {
  2403.             if ((ft & VT_BTYPE) == VT_DOUBLE) {
  2404.                 C67_MPYDP(r, fr);       // MPY  fr,r,fr
  2405.                 C67_NOP(9);
  2406.             } else {
  2407.                 C67_MPYSP(r, fr);       // MPY  fr,r,fr
  2408.                 C67_NOP(3);
  2409.             }
  2410.             vtop--;
  2411.         } else if (op == '/') {
  2412.             if ((ft & VT_BTYPE) == VT_DOUBLE) {
  2413.                 // must call intrinsic DP floating point divide
  2414.                 vswap();
  2415.                 /* call generic idiv function */
  2416.                 vpush_global_sym(&func_old_type, TOK__divd);
  2417.                 vrott(3);
  2418.                 gfunc_call(2);
  2419.                 vpushi(0);
  2420.                 vtop->r = REG_FRET;
  2421.                 vtop->r2 = REG_LRET;
  2422.  
  2423.             } else {
  2424.                 // must call intrinsic SP floating point divide
  2425.                 vswap();
  2426.                 /* call generic idiv function */
  2427.                 vpush_global_sym(&func_old_type, TOK__divf);
  2428.                 vrott(3);
  2429.                 gfunc_call(2);
  2430.                 vpushi(0);
  2431.                 vtop->r = REG_FRET;
  2432.                 vtop->r2 = VT_CONST;
  2433.             }
  2434.         } else
  2435.             ALWAYS_ASSERT(FALSE);
  2436.  
  2437.  
  2438.     }
  2439. }
  2440.  
  2441.  
  2442. /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
  2443.    and 'long long' cases. */
  2444. void gen_cvt_itof(int t)
  2445. {
  2446.     int r;
  2447.  
  2448.     gv(RC_INT);
  2449.     r = vtop->r;
  2450.  
  2451.     if ((t & VT_BTYPE) == VT_DOUBLE) {
  2452.         if (t & VT_UNSIGNED)
  2453.             C67_INTDPU(r, r);
  2454.         else
  2455.             C67_INTDP(r, r);
  2456.  
  2457.         C67_NOP(4);
  2458.         vtop->type.t = VT_DOUBLE;
  2459.     } else {
  2460.         if (t & VT_UNSIGNED)
  2461.             C67_INTSPU(r, r);
  2462.         else
  2463.             C67_INTSP(r, r);
  2464.         C67_NOP(3);
  2465.         vtop->type.t = VT_FLOAT;
  2466.     }
  2467.  
  2468. }
  2469.  
  2470. /* convert fp to int 't' type */
  2471. /* XXX: handle long long case */
  2472. void gen_cvt_ftoi(int t)
  2473. {
  2474.     int r;
  2475.  
  2476.     gv(RC_FLOAT);
  2477.     r = vtop->r;
  2478.  
  2479.     if (t != VT_INT)
  2480.         error("long long not supported");
  2481.     else {
  2482.         if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
  2483.             C67_DPTRUNC(r, r);
  2484.             C67_NOP(3);
  2485.         } else {
  2486.             C67_SPTRUNC(r, r);
  2487.             C67_NOP(3);
  2488.         }
  2489.  
  2490.         vtop->type.t = VT_INT;
  2491.  
  2492.     }
  2493. }
  2494.  
  2495. /* convert from one floating point type to another */
  2496. void gen_cvt_ftof(int t)
  2497. {
  2498.     int r, r2;
  2499.  
  2500.     if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
  2501.         (t & VT_BTYPE) == VT_FLOAT) {
  2502.         // convert double to float
  2503.  
  2504.         gv(RC_FLOAT);           // get it in a register pair
  2505.  
  2506.         r = vtop->r;
  2507.  
  2508.         C67_DPSP(r, r);         // convert it to SP same register
  2509.         C67_NOP(3);
  2510.  
  2511.         vtop->type.t = VT_FLOAT;
  2512.         vtop->r2 = VT_CONST;    // set this as unused
  2513.     } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
  2514.                (t & VT_BTYPE) == VT_DOUBLE) {
  2515.         // convert float to double
  2516.  
  2517.         gv(RC_FLOAT);           // get it in a register
  2518.  
  2519.         r = vtop->r;
  2520.  
  2521.         if (r == TREG_EAX) {    // make sure the paired reg is avail
  2522.             r2 = get_reg(RC_ECX);
  2523.         } else if (r == TREG_EDX) {
  2524.             r2 = get_reg(RC_ST0);
  2525.         } else {
  2526.             ALWAYS_ASSERT(FALSE);
  2527.             r2 = 0; /* avoid warning */
  2528.         }
  2529.  
  2530.         C67_SPDP(r, r);         // convert it to DP same register
  2531.         C67_NOP(1);
  2532.  
  2533.         vtop->type.t = VT_DOUBLE;
  2534.         vtop->r2 = r2;          // set this as unused
  2535.     } else {
  2536.         ALWAYS_ASSERT(FALSE);
  2537.     }
  2538. }
  2539.  
  2540. /* computed goto support */
  2541. void ggoto(void)
  2542. {
  2543.     gcall_or_jmp(1);
  2544.     vtop--;
  2545. }
  2546.  
  2547. /* end of X86 code generator */
  2548. /*************************************************************/
  2549.