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