Subversion Repositories Kolibri OS

Rev

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