Fixed compilation error in i386-asm.c
[tinycc/kirr.git] / c67-gen.c
blob88224fd5ed2ffa0fee62de80f78c5f34e36f6c84
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 const 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_DATA_PTR R_C60_32
167 #define R_JMP_SLOT R_C60_JMP_SLOT
168 #define R_COPY R_C60_COPY
170 #define ELF_START_ADDR 0x00000400
171 #define ELF_PAGE_SIZE 0x1000
173 /******************************************************/
175 static unsigned long func_sub_sp_offset;
176 static int func_ret_sub;
179 static BOOL C67_invert_test;
180 static int C67_compare_reg;
182 #ifdef ASSEMBLY_LISTING_C67
183 FILE *f = NULL;
184 #endif
187 void C67_g(int c)
189 int ind1;
191 #ifdef ASSEMBLY_LISTING_C67
192 fprintf(f, " %08X", c);
193 #endif
194 ind1 = ind + 4;
195 if (ind1 > (int) cur_text_section->data_allocated)
196 section_realloc(cur_text_section, ind1);
197 cur_text_section->data[ind] = c & 0xff;
198 cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
199 cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
200 cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
201 ind = ind1;
205 /* output a symbol and patch all calls to it */
206 void gsym_addr(int t, int a)
208 int n, *ptr;
209 while (t) {
210 ptr = (int *) (cur_text_section->data + t);
212 Sym *sym;
214 // extract 32 bit address from MVKH/MVKL
215 n = ((*ptr >> 7) & 0xffff);
216 n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
218 // define a label that will be relocated
220 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
221 greloc(cur_text_section, sym, t, R_C60LO16);
222 greloc(cur_text_section, sym, t + 4, R_C60HI16);
224 // clear out where the pointer was
226 *ptr &= ~(0xffff << 7);
227 *(ptr + 1) &= ~(0xffff << 7);
229 t = n;
233 void gsym(int t)
235 gsym_addr(t, ind);
238 // these are regs that tcc doesn't really know about,
239 // but asign them unique values so the mapping routines
240 // can distinquish them
242 #define C67_A0 105
243 #define C67_SP 106
244 #define C67_B3 107
245 #define C67_FP 108
246 #define C67_B2 109
247 #define C67_CREG_ZERO -1 // Special code for no condition reg test
250 int ConvertRegToRegClass(int r)
252 // only works for A4-B13
254 return RC_C67_A4 << (r - TREG_C67_A4);
258 // map TCC reg to C67 reg number
260 int C67_map_regn(int r)
262 if (r == 0) // normal tcc regs
263 return 0x2; // A2
264 else if (r == 1) // normal tcc regs
265 return 3; // A3
266 else if (r == 2) // normal tcc regs
267 return 0; // B0
268 else if (r == 3) // normal tcc regs
269 return 1; // B1
270 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
271 return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
272 else if (r == C67_A0)
273 return 0; // set to A0 (offset reg)
274 else if (r == C67_B2)
275 return 2; // set to B2 (offset reg)
276 else if (r == C67_B3)
277 return 3; // set to B3 (return address reg)
278 else if (r == C67_SP)
279 return 15; // set to SP (B15) (offset reg)
280 else if (r == C67_FP)
281 return 15; // set to FP (A15) (offset reg)
282 else if (r == C67_CREG_ZERO)
283 return 0; // Special code for no condition reg test
284 else
285 ALWAYS_ASSERT(FALSE);
287 return 0;
290 // mapping from tcc reg number to
291 // C67 register to condition code field
293 // valid condition code regs are:
295 // tcc reg 2 ->B0 -> 1
296 // tcc reg 3 ->B1 -> 2
297 // tcc reg 0 -> A2 -> 5
298 // tcc reg 1 -> A3 -> X
299 // tcc reg B2 -> 3
301 int C67_map_regc(int r)
303 if (r == 0) // normal tcc regs
304 return 0x5;
305 else if (r == 2) // normal tcc regs
306 return 0x1;
307 else if (r == 3) // normal tcc regs
308 return 0x2;
309 else if (r == C67_B2) // normal tcc regs
310 return 0x3;
311 else if (r == C67_CREG_ZERO)
312 return 0; // Special code for no condition reg test
313 else
314 ALWAYS_ASSERT(FALSE);
316 return 0;
320 // map TCC reg to C67 reg side A or B
322 int C67_map_regs(int r)
324 if (r == 0) // normal tcc regs
325 return 0x0;
326 else if (r == 1) // normal tcc regs
327 return 0x0;
328 else if (r == 2) // normal tcc regs
329 return 0x1;
330 else if (r == 3) // normal tcc regs
331 return 0x1;
332 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
333 return (r & 2) >> 1;
334 else if (r == C67_A0)
335 return 0; // set to A side
336 else if (r == C67_B2)
337 return 1; // set to B side
338 else if (r == C67_B3)
339 return 1; // set to B side
340 else if (r == C67_SP)
341 return 0x1; // set to SP (B15) B side
342 else if (r == C67_FP)
343 return 0x0; // set to FP (A15) A side
344 else
345 ALWAYS_ASSERT(FALSE);
347 return 0;
350 int C67_map_S12(char *s)
352 if (strstr(s, ".S1") != NULL)
353 return 0;
354 else if (strcmp(s, ".S2"))
355 return 1;
356 else
357 ALWAYS_ASSERT(FALSE);
359 return 0;
362 int C67_map_D12(char *s)
364 if (strstr(s, ".D1") != NULL)
365 return 0;
366 else if (strcmp(s, ".D2"))
367 return 1;
368 else
369 ALWAYS_ASSERT(FALSE);
371 return 0;
376 void C67_asm(char *s, int a, int b, int c)
378 BOOL xpath;
380 #ifdef ASSEMBLY_LISTING_C67
381 if (!f) {
382 f = fopen("TCC67_out.txt", "wt");
384 fprintf(f, "%04X ", ind);
385 #endif
387 if (strstr(s, "MVKL") == s) {
388 C67_g((C67_map_regn(b) << 23) |
389 ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
390 } else if (strstr(s, "MVKH") == s) {
391 C67_g((C67_map_regn(b) << 23) |
392 (((a >> 16) & 0xffff) << 7) |
393 (0x1a << 2) | (C67_map_regs(b) << 1));
394 } else if (strstr(s, "STW.D SP POST DEC") == s) {
395 C67_g((C67_map_regn(a) << 23) | //src
396 (15 << 18) | //SP B15
397 (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
398 (0xa << 9) | //mode a = post dec ucst
399 (0 << 8) | //r (LDDW bit 0)
400 (1 << 7) | //y D1/D2 use B side
401 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
402 (1 << 2) | //opcode
403 (C67_map_regs(a) << 1) | //side of src
404 (0 << 0)); //parallel
405 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
406 C67_g((C67_map_regn(a) << 23) | //src
407 (15 << 18) | //base reg A15
408 (0 << 13) | //offset reg A0
409 (5 << 9) | //mode 5 = pos offset, base reg + off reg
410 (0 << 8) | //r (LDDW bit 0)
411 (0 << 7) | //y D1/D2 A side
412 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
413 (1 << 2) | //opcode
414 (C67_map_regs(a) << 1) | //side of src
415 (0 << 0)); //parallel
416 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
417 C67_g((C67_map_regn(a) << 23) | //src
418 (15 << 18) | //base reg A15
419 (0 << 13) | //offset reg A0
420 (5 << 9) | //mode 5 = pos offset, base reg + off reg
421 (0 << 8) | //r (LDDW bit 0)
422 (0 << 7) | //y D1/D2 A side
423 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
424 (1 << 2) | //opcode
425 (C67_map_regs(a) << 1) | //side of src
426 (0 << 0)); //parallel
427 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
428 C67_g((C67_map_regn(a) << 23) | //src
429 (15 << 18) | //base reg A15
430 (0 << 13) | //offset reg A0
431 (5 << 9) | //mode 5 = pos offset, base reg + off reg
432 (0 << 8) | //r (LDDW bit 0)
433 (0 << 7) | //y D1/D2 A side
434 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
435 (1 << 2) | //opcode
436 (C67_map_regs(a) << 1) | //side of src
437 (0 << 0)); //parallel
438 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
439 C67_g((C67_map_regn(a) << 23) | //src
440 (15 << 18) | //base reg A15
441 (0 << 13) | //offset reg A0
442 (5 << 9) | //mode 5 = pos offset, base reg + off reg
443 (0 << 8) | //r (LDDW bit 0)
444 (0 << 7) | //y D1/D2 A side
445 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
446 (1 << 2) | //opcode
447 (C67_map_regs(a) << 1) | //side of src
448 (0 << 0)); //parallel
449 } else if (strstr(s, "STW.D *+SP[A0]") == s) {
450 C67_g((C67_map_regn(a) << 23) | //src
451 (15 << 18) | //base reg A15
452 (0 << 13) | //offset reg A0
453 (5 << 9) | //mode 5 = pos offset, base reg + off reg
454 (0 << 8) | //r (LDDW bit 0)
455 (0 << 7) | //y D1/D2 A side
456 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
457 (1 << 2) | //opcode
458 (C67_map_regs(a) << 1) | //side of src
459 (0 << 0)); //parallel
460 } else if (strstr(s, "STW.D *") == s) {
461 C67_g((C67_map_regn(a) << 23) | //src
462 (C67_map_regn(b) << 18) | //base reg A0
463 (0 << 13) | //cst5
464 (1 << 9) | //mode 1 = pos cst offset
465 (0 << 8) | //r (LDDW bit 0)
466 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
467 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
468 (1 << 2) | //opcode
469 (C67_map_regs(a) << 1) | //side of src
470 (0 << 0)); //parallel
471 } else if (strstr(s, "STH.D *") == s) {
472 C67_g((C67_map_regn(a) << 23) | //src
473 (C67_map_regn(b) << 18) | //base reg A0
474 (0 << 13) | //cst5
475 (1 << 9) | //mode 1 = pos cst offset
476 (0 << 8) | //r (LDDW bit 0)
477 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
478 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
479 (1 << 2) | //opcode
480 (C67_map_regs(a) << 1) | //side of src
481 (0 << 0)); //parallel
482 } else if (strstr(s, "STB.D *") == s) {
483 C67_g((C67_map_regn(a) << 23) | //src
484 (C67_map_regn(b) << 18) | //base reg A0
485 (0 << 13) | //cst5
486 (1 << 9) | //mode 1 = pos cst offset
487 (0 << 8) | //r (LDDW bit 0)
488 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
489 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
490 (1 << 2) | //opcode
491 (C67_map_regs(a) << 1) | //side of src
492 (0 << 0)); //parallel
493 } else if (strstr(s, "STW.D +*") == s) {
494 ALWAYS_ASSERT(c < 32);
495 C67_g((C67_map_regn(a) << 23) | //src
496 (C67_map_regn(b) << 18) | //base reg A0
497 (c << 13) | //cst5
498 (1 << 9) | //mode 1 = pos cst offset
499 (0 << 8) | //r (LDDW bit 0)
500 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
501 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
502 (1 << 2) | //opcode
503 (C67_map_regs(a) << 1) | //side of src
504 (0 << 0)); //parallel
505 } else if (strstr(s, "LDW.D SP PRE INC") == s) {
506 C67_g((C67_map_regn(a) << 23) | //dst
507 (15 << 18) | //base reg B15
508 (2 << 13) | //ucst5 (must keep 8 byte boundary)
509 (9 << 9) | //mode 9 = pre inc ucst5
510 (0 << 8) | //r (LDDW bit 0)
511 (1 << 7) | //y D1/D2 B side
512 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
513 (1 << 2) | //opcode
514 (C67_map_regs(a) << 1) | //side of dst
515 (0 << 0)); //parallel
516 } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
517 C67_g((C67_map_regn(a) << 23) | //dst
518 (15 << 18) | //base reg B15
519 (1 << 13) | //ucst5 (must keep 8 byte boundary)
520 (9 << 9) | //mode 9 = pre inc ucst5
521 (1 << 8) | //r (LDDW bit 1)
522 (1 << 7) | //y D1/D2 B side
523 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
524 (1 << 2) | //opcode
525 (C67_map_regs(a) << 1) | //side of dst
526 (0 << 0)); //parallel
527 } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
528 C67_g((C67_map_regn(a) << 23) | //dst
529 (15 << 18) | //base reg A15
530 (0 << 13) | //offset reg A0
531 (5 << 9) | //mode 5 = pos offset, base reg + off reg
532 (0 << 8) | //r (LDDW bit 0)
533 (0 << 7) | //y D1/D2 A side
534 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
535 (1 << 2) | //opcode
536 (C67_map_regs(a) << 1) | //side of dst
537 (0 << 0)); //parallel
538 } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
539 C67_g((C67_map_regn(a) << 23) | //dst
540 (15 << 18) | //base reg A15
541 (0 << 13) | //offset reg A0
542 (5 << 9) | //mode 5 = pos offset, base reg + off reg
543 (1 << 8) | //r (LDDW bit 1)
544 (0 << 7) | //y D1/D2 A side
545 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
546 (1 << 2) | //opcode
547 (C67_map_regs(a) << 1) | //side of dst
548 (0 << 0)); //parallel
549 } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
550 C67_g((C67_map_regn(a) << 23) | //dst
551 (15 << 18) | //base reg A15
552 (0 << 13) | //offset reg A0
553 (5 << 9) | //mode 5 = pos offset, base reg + off reg
554 (0 << 8) | //r (LDDW bit 0)
555 (0 << 7) | //y D1/D2 A side
556 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
557 (1 << 2) | //opcode
558 (C67_map_regs(a) << 1) | //side of dst
559 (0 << 0)); //parallel
560 } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
561 C67_g((C67_map_regn(a) << 23) | //dst
562 (15 << 18) | //base reg A15
563 (0 << 13) | //offset reg A0
564 (5 << 9) | //mode 5 = pos offset, base reg + off reg
565 (0 << 8) | //r (LDDW bit 0)
566 (0 << 7) | //y D1/D2 A side
567 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
568 (1 << 2) | //opcode
569 (C67_map_regs(a) << 1) | //side of dst
570 (0 << 0)); //parallel
571 } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
572 C67_g((C67_map_regn(a) << 23) | //dst
573 (15 << 18) | //base reg A15
574 (0 << 13) | //offset reg A0
575 (5 << 9) | //mode 5 = pos offset, base reg + off reg
576 (0 << 8) | //r (LDDW bit 0)
577 (0 << 7) | //y D1/D2 A side
578 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
579 (1 << 2) | //opcode
580 (C67_map_regs(a) << 1) | //side of dst
581 (0 << 0)); //parallel
582 } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
583 C67_g((C67_map_regn(a) << 23) | //dst
584 (15 << 18) | //base reg A15
585 (0 << 13) | //offset reg A0
586 (5 << 9) | //mode 5 = pos offset, base reg + off reg
587 (0 << 8) | //r (LDDW bit 0)
588 (0 << 7) | //y D1/D2 A side
589 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
590 (1 << 2) | //opcode
591 (C67_map_regs(a) << 1) | //side of dst
592 (0 << 0)); //parallel
593 } else if (strstr(s, "LDW.D *") == s) {
594 C67_g((C67_map_regn(b) << 23) | //dst
595 (C67_map_regn(a) << 18) | //base reg A15
596 (0 << 13) | //cst5
597 (1 << 9) | //mode 1 = pos cst offset
598 (0 << 8) | //r (LDDW bit 0)
599 (C67_map_regs(a) << 7) | //y D1/D2 src side
600 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
601 (1 << 2) | //opcode
602 (C67_map_regs(b) << 1) | //side of dst
603 (0 << 0)); //parallel
604 } else if (strstr(s, "LDDW.D *") == s) {
605 C67_g((C67_map_regn(b) << 23) | //dst
606 (C67_map_regn(a) << 18) | //base reg A15
607 (0 << 13) | //cst5
608 (1 << 9) | //mode 1 = pos cst offset
609 (1 << 8) | //r (LDDW bit 1)
610 (C67_map_regs(a) << 7) | //y D1/D2 src side
611 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
612 (1 << 2) | //opcode
613 (C67_map_regs(b) << 1) | //side of dst
614 (0 << 0)); //parallel
615 } else if (strstr(s, "LDH.D *") == s) {
616 C67_g((C67_map_regn(b) << 23) | //dst
617 (C67_map_regn(a) << 18) | //base reg A15
618 (0 << 13) | //cst5
619 (1 << 9) | //mode 1 = pos cst offset
620 (0 << 8) | //r (LDDW bit 0)
621 (C67_map_regs(a) << 7) | //y D1/D2 src side
622 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
623 (1 << 2) | //opcode
624 (C67_map_regs(b) << 1) | //side of dst
625 (0 << 0)); //parallel
626 } else if (strstr(s, "LDB.D *") == s) {
627 C67_g((C67_map_regn(b) << 23) | //dst
628 (C67_map_regn(a) << 18) | //base reg A15
629 (0 << 13) | //cst5
630 (1 << 9) | //mode 1 = pos cst offset
631 (0 << 8) | //r (LDDW bit 0)
632 (C67_map_regs(a) << 7) | //y D1/D2 src side
633 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
634 (1 << 2) | //opcode
635 (C67_map_regs(b) << 1) | //side of dst
636 (0 << 0)); //parallel
637 } else if (strstr(s, "LDHU.D *") == s) {
638 C67_g((C67_map_regn(b) << 23) | //dst
639 (C67_map_regn(a) << 18) | //base reg A15
640 (0 << 13) | //cst5
641 (1 << 9) | //mode 1 = pos cst offset
642 (0 << 8) | //r (LDDW bit 0)
643 (C67_map_regs(a) << 7) | //y D1/D2 src side
644 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
645 (1 << 2) | //opcode
646 (C67_map_regs(b) << 1) | //side of dst
647 (0 << 0)); //parallel
648 } else if (strstr(s, "LDBU.D *") == s) {
649 C67_g((C67_map_regn(b) << 23) | //dst
650 (C67_map_regn(a) << 18) | //base reg A15
651 (0 << 13) | //cst5
652 (1 << 9) | //mode 1 = pos cst offset
653 (0 << 8) | //r (LDDW bit 0)
654 (C67_map_regs(a) << 7) | //y D1/D2 src side
655 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
656 (1 << 2) | //opcode
657 (C67_map_regs(b) << 1) | //side of dst
658 (0 << 0)); //parallel
659 } else if (strstr(s, "LDW.D +*") == s) {
660 C67_g((C67_map_regn(b) << 23) | //dst
661 (C67_map_regn(a) << 18) | //base reg A15
662 (1 << 13) | //cst5
663 (1 << 9) | //mode 1 = pos cst offset
664 (0 << 8) | //r (LDDW bit 0)
665 (C67_map_regs(a) << 7) | //y D1/D2 src side
666 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
667 (1 << 2) | //opcode
668 (C67_map_regs(b) << 1) | //side of dst
669 (0 << 0)); //parallel
670 } else if (strstr(s, "CMPLTSP") == s) {
671 xpath = C67_map_regs(a) ^ C67_map_regs(b);
672 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
674 C67_g((C67_map_regn(c) << 23) | //dst
675 (C67_map_regn(b) << 18) | //src2
676 (C67_map_regn(a) << 13) | //src1
677 (xpath << 12) | //x use cross path for src2
678 (0x3a << 6) | //opcode
679 (0x8 << 2) | //opcode fixed
680 (C67_map_regs(c) << 1) | //side for reg c
681 (0 << 0)); //parallel
682 } else if (strstr(s, "CMPGTSP") == s) {
683 xpath = C67_map_regs(a) ^ C67_map_regs(b);
684 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
686 C67_g((C67_map_regn(c) << 23) | //dst
687 (C67_map_regn(b) << 18) | //src2
688 (C67_map_regn(a) << 13) | //src1
689 (xpath << 12) | //x use cross path for src2
690 (0x39 << 6) | //opcode
691 (0x8 << 2) | //opcode fixed
692 (C67_map_regs(c) << 1) | //side for reg c
693 (0 << 0)); //parallel
694 } else if (strstr(s, "CMPEQSP") == s) {
695 xpath = C67_map_regs(a) ^ C67_map_regs(b);
696 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
698 C67_g((C67_map_regn(c) << 23) | //dst
699 (C67_map_regn(b) << 18) | //src2
700 (C67_map_regn(a) << 13) | //src1
701 (xpath << 12) | //x use cross path for src2
702 (0x38 << 6) | //opcode
703 (0x8 << 2) | //opcode fixed
704 (C67_map_regs(c) << 1) | //side for reg c
705 (0 << 0)); //parallel
708 else if (strstr(s, "CMPLTDP") == s) {
709 xpath = C67_map_regs(a) ^ C67_map_regs(b);
710 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
712 C67_g((C67_map_regn(c) << 23) | //dst
713 (C67_map_regn(b) << 18) | //src2
714 (C67_map_regn(a) << 13) | //src1
715 (xpath << 12) | //x use cross path for src2
716 (0x2a << 6) | //opcode
717 (0x8 << 2) | //opcode fixed
718 (C67_map_regs(c) << 1) | //side for reg c
719 (0 << 0)); //parallel
720 } else if (strstr(s, "CMPGTDP") == s) {
721 xpath = C67_map_regs(a) ^ C67_map_regs(b);
722 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
724 C67_g((C67_map_regn(c) << 23) | //dst
725 (C67_map_regn(b) << 18) | //src2
726 (C67_map_regn(a) << 13) | //src1
727 (xpath << 12) | //x use cross path for src2
728 (0x29 << 6) | //opcode
729 (0x8 << 2) | //opcode fixed
730 (C67_map_regs(c) << 1) | //side for reg c
731 (0 << 0)); //parallel
732 } else if (strstr(s, "CMPEQDP") == s) {
733 xpath = C67_map_regs(a) ^ C67_map_regs(b);
734 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
736 C67_g((C67_map_regn(c) << 23) | //dst
737 (C67_map_regn(b) << 18) | //src2
738 (C67_map_regn(a) << 13) | //src1
739 (xpath << 12) | //x use cross path for src2
740 (0x28 << 6) | //opcode
741 (0x8 << 2) | //opcode fixed
742 (C67_map_regs(c) << 1) | //side for reg c
743 (0 << 0)); //parallel
744 } else if (strstr(s, "CMPLT") == s) {
745 xpath = C67_map_regs(a) ^ C67_map_regs(b);
746 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
748 C67_g((C67_map_regn(c) << 23) | //dst
749 (C67_map_regn(b) << 18) | //src2
750 (C67_map_regn(a) << 13) | //src1
751 (xpath << 12) | //x use cross path for src2
752 (0x57 << 5) | //opcode
753 (0x6 << 2) | //opcode fixed
754 (C67_map_regs(c) << 1) | //side for reg c
755 (0 << 0)); //parallel
756 } else if (strstr(s, "CMPGT") == s) {
757 xpath = C67_map_regs(a) ^ C67_map_regs(b);
758 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
760 C67_g((C67_map_regn(c) << 23) | //dst
761 (C67_map_regn(b) << 18) | //src2
762 (C67_map_regn(a) << 13) | //src1
763 (xpath << 12) | //x use cross path for src2
764 (0x47 << 5) | //opcode
765 (0x6 << 2) | //opcode fixed
766 (C67_map_regs(c) << 1) | //side for reg c
767 (0 << 0)); //parallel
768 } else if (strstr(s, "CMPEQ") == s) {
769 xpath = C67_map_regs(a) ^ C67_map_regs(b);
770 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
772 C67_g((C67_map_regn(c) << 23) | //dst
773 (C67_map_regn(b) << 18) | //src2
774 (C67_map_regn(a) << 13) | //src1
775 (xpath << 12) | //x use cross path for src2
776 (0x53 << 5) | //opcode
777 (0x6 << 2) | //opcode fixed
778 (C67_map_regs(c) << 1) | //side for reg c
779 (0 << 0)); //parallel
780 } else if (strstr(s, "CMPLTU") == s) {
781 xpath = C67_map_regs(a) ^ C67_map_regs(b);
782 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
784 C67_g((C67_map_regn(c) << 23) | //dst
785 (C67_map_regn(b) << 18) | //src2
786 (C67_map_regn(a) << 13) | //src1
787 (xpath << 12) | //x use cross path for src2
788 (0x5f << 5) | //opcode
789 (0x6 << 2) | //opcode fixed
790 (C67_map_regs(c) << 1) | //side for reg c
791 (0 << 0)); //parallel
792 } else if (strstr(s, "CMPGTU") == s) {
793 xpath = C67_map_regs(a) ^ C67_map_regs(b);
794 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
796 C67_g((C67_map_regn(c) << 23) | //dst
797 (C67_map_regn(b) << 18) | //src2
798 (C67_map_regn(a) << 13) | //src1
799 (xpath << 12) | //x use cross path for src2
800 (0x4f << 5) | //opcode
801 (0x6 << 2) | //opcode fixed
802 (C67_map_regs(c) << 1) | //side for reg c
803 (0 << 0)); //parallel
804 } else if (strstr(s, "B DISP") == s) {
805 C67_g((0 << 29) | //creg
806 (0 << 28) | //z
807 (a << 7) | //cnst
808 (0x4 << 2) | //opcode fixed
809 (0 << 1) | //S0/S1
810 (0 << 0)); //parallel
811 } else if (strstr(s, "B.") == s) {
812 xpath = C67_map_regs(c) ^ 1;
814 C67_g((C67_map_regc(b) << 29) | //creg
815 (a << 28) | //inv
816 (0 << 23) | //dst
817 (C67_map_regn(c) << 18) | //src2
818 (0 << 13) | //
819 (xpath << 12) | //x cross path if !B side
820 (0xd << 6) | //opcode
821 (0x8 << 2) | //opcode fixed
822 (1 << 1) | //must be S2
823 (0 << 0)); //parallel
824 } else if (strstr(s, "MV.L") == s) {
825 xpath = C67_map_regs(b) ^ C67_map_regs(c);
827 C67_g((0 << 29) | //creg
828 (0 << 28) | //inv
829 (C67_map_regn(c) << 23) | //dst
830 (C67_map_regn(b) << 18) | //src2
831 (0 << 13) | //src1 (cst5)
832 (xpath << 12) | //x cross path if opposite sides
833 (0x2 << 5) | //opcode
834 (0x6 << 2) | //opcode fixed
835 (C67_map_regs(c) << 1) | //side of dest
836 (0 << 0)); //parallel
837 } else if (strstr(s, "SPTRUNC.L") == s) {
838 xpath = C67_map_regs(b) ^ C67_map_regs(c);
840 C67_g((0 << 29) | //creg
841 (0 << 28) | //inv
842 (C67_map_regn(c) << 23) | //dst
843 (C67_map_regn(b) << 18) | //src2
844 (0 << 13) | //src1 NA
845 (xpath << 12) | //x cross path if opposite sides
846 (0xb << 5) | //opcode
847 (0x6 << 2) | //opcode fixed
848 (C67_map_regs(c) << 1) | //side of dest
849 (0 << 0)); //parallel
850 } else if (strstr(s, "DPTRUNC.L") == s) {
851 xpath = C67_map_regs(b) ^ C67_map_regs(c);
853 C67_g((0 << 29) | //creg
854 (0 << 28) | //inv
855 (C67_map_regn(c) << 23) | //dst
856 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
857 (0 << 13) | //src1 NA
858 (xpath << 12) | //x cross path if opposite sides
859 (0x1 << 5) | //opcode
860 (0x6 << 2) | //opcode fixed
861 (C67_map_regs(c) << 1) | //side of dest
862 (0 << 0)); //parallel
863 } else if (strstr(s, "INTSP.L") == s) {
864 xpath = C67_map_regs(b) ^ C67_map_regs(c);
866 C67_g((0 << 29) | //creg
867 (0 << 28) | //inv
868 (C67_map_regn(c) << 23) | //dst
869 (C67_map_regn(b) << 18) | //src2
870 (0 << 13) | //src1 NA
871 (xpath << 12) | //x cross path if opposite sides
872 (0x4a << 5) | //opcode
873 (0x6 << 2) | //opcode fixed
874 (C67_map_regs(c) << 1) | //side of dest
875 (0 << 0)); //parallel
876 } else if (strstr(s, "INTSPU.L") == s) {
877 xpath = C67_map_regs(b) ^ C67_map_regs(c);
879 C67_g((0 << 29) | //creg
880 (0 << 28) | //inv
881 (C67_map_regn(c) << 23) | //dst
882 (C67_map_regn(b) << 18) | //src2
883 (0 << 13) | //src1 NA
884 (xpath << 12) | //x cross path if opposite sides
885 (0x49 << 5) | //opcode
886 (0x6 << 2) | //opcode fixed
887 (C67_map_regs(c) << 1) | //side of dest
888 (0 << 0)); //parallel
889 } else if (strstr(s, "INTDP.L") == s) {
890 xpath = C67_map_regs(b) ^ C67_map_regs(c);
892 C67_g((0 << 29) | //creg
893 (0 << 28) | //inv
894 (C67_map_regn(c) << 23) | //dst
895 (C67_map_regn(b) << 18) | //src2
896 (0 << 13) | //src1 NA
897 (xpath << 12) | //x cross path if opposite sides
898 (0x39 << 5) | //opcode
899 (0x6 << 2) | //opcode fixed
900 (C67_map_regs(c) << 1) | //side of dest
901 (0 << 0)); //parallel
902 } else if (strstr(s, "INTDPU.L") == s) {
903 xpath = C67_map_regs(b) ^ C67_map_regs(c);
905 C67_g((0 << 29) | //creg
906 (0 << 28) | //inv
907 (C67_map_regn(c) << 23) | //dst
908 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
909 (0 << 13) | //src1 NA
910 (xpath << 12) | //x cross path if opposite sides
911 (0x3b << 5) | //opcode
912 (0x6 << 2) | //opcode fixed
913 (C67_map_regs(c) << 1) | //side of dest
914 (0 << 0)); //parallel
915 } else if (strstr(s, "SPDP.L") == s) {
916 xpath = C67_map_regs(b) ^ C67_map_regs(c);
918 C67_g((0 << 29) | //creg
919 (0 << 28) | //inv
920 (C67_map_regn(c) << 23) | //dst
921 (C67_map_regn(b) << 18) | //src2
922 (0 << 13) | //src1 NA
923 (xpath << 12) | //x cross path if opposite sides
924 (0x2 << 6) | //opcode
925 (0x8 << 2) | //opcode fixed
926 (C67_map_regs(c) << 1) | //side of dest
927 (0 << 0)); //parallel
928 } else if (strstr(s, "DPSP.L") == s) {
929 ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
931 C67_g((0 << 29) | //creg
932 (0 << 28) | //inv
933 (C67_map_regn(c) << 23) | //dst
934 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
935 (0 << 13) | //src1 NA
936 (0 << 12) | //x cross path if opposite sides
937 (0x9 << 5) | //opcode
938 (0x6 << 2) | //opcode fixed
939 (C67_map_regs(c) << 1) | //side of dest
940 (0 << 0)); //parallel
941 } else if (strstr(s, "ADD.L") == s) {
942 xpath = C67_map_regs(b) ^ C67_map_regs(c);
944 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
946 C67_g((0 << 29) | //creg
947 (0 << 28) | //inv
948 (C67_map_regn(c) << 23) | //dst
949 (C67_map_regn(b) << 18) | //src2 (possible x path)
950 (C67_map_regn(a) << 13) | //src1
951 (xpath << 12) | //x cross path if opposite sides
952 (0x3 << 5) | //opcode
953 (0x6 << 2) | //opcode fixed
954 (C67_map_regs(c) << 1) | //side of dest
955 (0 << 0)); //parallel
956 } else if (strstr(s, "SUB.L") == s) {
957 xpath = C67_map_regs(b) ^ C67_map_regs(c);
959 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
961 C67_g((0 << 29) | //creg
962 (0 << 28) | //inv
963 (C67_map_regn(c) << 23) | //dst
964 (C67_map_regn(b) << 18) | //src2 (possible x path)
965 (C67_map_regn(a) << 13) | //src1
966 (xpath << 12) | //x cross path if opposite sides
967 (0x7 << 5) | //opcode
968 (0x6 << 2) | //opcode fixed
969 (C67_map_regs(c) << 1) | //side of dest
970 (0 << 0)); //parallel
971 } else if (strstr(s, "OR.L") == s) {
972 xpath = C67_map_regs(b) ^ C67_map_regs(c);
974 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
976 C67_g((0 << 29) | //creg
977 (0 << 28) | //inv
978 (C67_map_regn(c) << 23) | //dst
979 (C67_map_regn(b) << 18) | //src2 (possible x path)
980 (C67_map_regn(a) << 13) | //src1
981 (xpath << 12) | //x cross path if opposite sides
982 (0x7f << 5) | //opcode
983 (0x6 << 2) | //opcode fixed
984 (C67_map_regs(c) << 1) | //side of dest
985 (0 << 0)); //parallel
986 } else if (strstr(s, "AND.L") == s) {
987 xpath = C67_map_regs(b) ^ C67_map_regs(c);
989 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
991 C67_g((0 << 29) | //creg
992 (0 << 28) | //inv
993 (C67_map_regn(c) << 23) | //dst
994 (C67_map_regn(b) << 18) | //src2 (possible x path)
995 (C67_map_regn(a) << 13) | //src1
996 (xpath << 12) | //x cross path if opposite sides
997 (0x7b << 5) | //opcode
998 (0x6 << 2) | //opcode fixed
999 (C67_map_regs(c) << 1) | //side of dest
1000 (0 << 0)); //parallel
1001 } else if (strstr(s, "XOR.L") == s) {
1002 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1004 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1006 C67_g((0 << 29) | //creg
1007 (0 << 28) | //inv
1008 (C67_map_regn(c) << 23) | //dst
1009 (C67_map_regn(b) << 18) | //src2 (possible x path)
1010 (C67_map_regn(a) << 13) | //src1
1011 (xpath << 12) | //x cross path if opposite sides
1012 (0x6f << 5) | //opcode
1013 (0x6 << 2) | //opcode fixed
1014 (C67_map_regs(c) << 1) | //side of dest
1015 (0 << 0)); //parallel
1016 } else if (strstr(s, "ADDSP.L") == s) {
1017 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1019 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1021 C67_g((0 << 29) | //creg
1022 (0 << 28) | //inv
1023 (C67_map_regn(c) << 23) | //dst
1024 (C67_map_regn(b) << 18) | //src2 (possible x path)
1025 (C67_map_regn(a) << 13) | //src1
1026 (xpath << 12) | //x cross path if opposite sides
1027 (0x10 << 5) | //opcode
1028 (0x6 << 2) | //opcode fixed
1029 (C67_map_regs(c) << 1) | //side of dest
1030 (0 << 0)); //parallel
1031 } else if (strstr(s, "ADDDP.L") == s) {
1032 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1034 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1036 C67_g((0 << 29) | //creg
1037 (0 << 28) | //inv
1038 (C67_map_regn(c) << 23) | //dst
1039 (C67_map_regn(b) << 18) | //src2 (possible x path)
1040 (C67_map_regn(a) << 13) | //src1
1041 (xpath << 12) | //x cross path if opposite sides
1042 (0x18 << 5) | //opcode
1043 (0x6 << 2) | //opcode fixed
1044 (C67_map_regs(c) << 1) | //side of dest
1045 (0 << 0)); //parallel
1046 } else if (strstr(s, "SUBSP.L") == s) {
1047 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1049 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1051 C67_g((0 << 29) | //creg
1052 (0 << 28) | //inv
1053 (C67_map_regn(c) << 23) | //dst
1054 (C67_map_regn(b) << 18) | //src2 (possible x path)
1055 (C67_map_regn(a) << 13) | //src1
1056 (xpath << 12) | //x cross path if opposite sides
1057 (0x11 << 5) | //opcode
1058 (0x6 << 2) | //opcode fixed
1059 (C67_map_regs(c) << 1) | //side of dest
1060 (0 << 0)); //parallel
1061 } else if (strstr(s, "SUBDP.L") == s) {
1062 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1064 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1066 C67_g((0 << 29) | //creg
1067 (0 << 28) | //inv
1068 (C67_map_regn(c) << 23) | //dst
1069 (C67_map_regn(b) << 18) | //src2 (possible x path)
1070 (C67_map_regn(a) << 13) | //src1
1071 (xpath << 12) | //x cross path if opposite sides
1072 (0x19 << 5) | //opcode
1073 (0x6 << 2) | //opcode fixed
1074 (C67_map_regs(c) << 1) | //side of dest
1075 (0 << 0)); //parallel
1076 } else if (strstr(s, "MPYSP.M") == s) {
1077 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1079 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1081 C67_g((0 << 29) | //creg
1082 (0 << 28) | //inv
1083 (C67_map_regn(c) << 23) | //dst
1084 (C67_map_regn(b) << 18) | //src2 (possible x path)
1085 (C67_map_regn(a) << 13) | //src1
1086 (xpath << 12) | //x cross path if opposite sides
1087 (0x1c << 7) | //opcode
1088 (0x0 << 2) | //opcode fixed
1089 (C67_map_regs(c) << 1) | //side of dest
1090 (0 << 0)); //parallel
1091 } else if (strstr(s, "MPYDP.M") == s) {
1092 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1094 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1096 C67_g((0 << 29) | //creg
1097 (0 << 28) | //inv
1098 (C67_map_regn(c) << 23) | //dst
1099 (C67_map_regn(b) << 18) | //src2 (possible x path)
1100 (C67_map_regn(a) << 13) | //src1
1101 (xpath << 12) | //x cross path if opposite sides
1102 (0x0e << 7) | //opcode
1103 (0x0 << 2) | //opcode fixed
1104 (C67_map_regs(c) << 1) | //side of dest
1105 (0 << 0)); //parallel
1106 } else if (strstr(s, "MPYI.M") == s) {
1107 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1109 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1111 C67_g((0 << 29) | //creg
1112 (0 << 28) | //inv
1113 (C67_map_regn(c) << 23) | //dst
1114 (C67_map_regn(b) << 18) | //src2
1115 (C67_map_regn(a) << 13) | //src1 (cst5)
1116 (xpath << 12) | //x cross path if opposite sides
1117 (0x4 << 7) | //opcode
1118 (0x0 << 2) | //opcode fixed
1119 (C67_map_regs(c) << 1) | //side of dest
1120 (0 << 0)); //parallel
1121 } else if (strstr(s, "SHR.S") == s) {
1122 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1124 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1126 C67_g((0 << 29) | //creg
1127 (0 << 28) | //inv
1128 (C67_map_regn(c) << 23) | //dst
1129 (C67_map_regn(b) << 18) | //src2
1130 (C67_map_regn(a) << 13) | //src1
1131 (xpath << 12) | //x cross path if opposite sides
1132 (0x37 << 6) | //opcode
1133 (0x8 << 2) | //opcode fixed
1134 (C67_map_regs(c) << 1) | //side of dest
1135 (0 << 0)); //parallel
1136 } else if (strstr(s, "SHRU.S") == s) {
1137 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1139 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1141 C67_g((0 << 29) | //creg
1142 (0 << 28) | //inv
1143 (C67_map_regn(c) << 23) | //dst
1144 (C67_map_regn(b) << 18) | //src2
1145 (C67_map_regn(a) << 13) | //src1
1146 (xpath << 12) | //x cross path if opposite sides
1147 (0x27 << 6) | //opcode
1148 (0x8 << 2) | //opcode fixed
1149 (C67_map_regs(c) << 1) | //side of dest
1150 (0 << 0)); //parallel
1151 } else if (strstr(s, "SHL.S") == s) {
1152 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1154 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1156 C67_g((0 << 29) | //creg
1157 (0 << 28) | //inv
1158 (C67_map_regn(c) << 23) | //dst
1159 (C67_map_regn(b) << 18) | //src2
1160 (C67_map_regn(a) << 13) | //src1
1161 (xpath << 12) | //x cross path if opposite sides
1162 (0x33 << 6) | //opcode
1163 (0x8 << 2) | //opcode fixed
1164 (C67_map_regs(c) << 1) | //side of dest
1165 (0 << 0)); //parallel
1166 } else if (strstr(s, "||ADDK") == s) {
1167 xpath = 0; // no xpath required just use the side of the src/dst
1169 C67_g((0 << 29) | //creg
1170 (0 << 28) | //inv
1171 (C67_map_regn(b) << 23) | //dst
1172 (a << 07) | //scst16
1173 (0x14 << 2) | //opcode fixed
1174 (C67_map_regs(b) << 1) | //side of dst
1175 (1 << 0)); //parallel
1176 } else if (strstr(s, "ADDK") == s) {
1177 xpath = 0; // no xpath required just use the side of the src/dst
1179 C67_g((0 << 29) | //creg
1180 (0 << 28) | //inv
1181 (C67_map_regn(b) << 23) | //dst
1182 (a << 07) | //scst16
1183 (0x14 << 2) | //opcode fixed
1184 (C67_map_regs(b) << 1) | //side of dst
1185 (0 << 0)); //parallel
1186 } else if (strstr(s, "NOP") == s) {
1187 C67_g(((a - 1) << 13) | //no of cycles
1188 (0 << 0)); //parallel
1189 } else
1190 ALWAYS_ASSERT(FALSE);
1192 #ifdef ASSEMBLY_LISTING_C67
1193 fprintf(f, " %s %d %d %d\n", s, a, b, c);
1194 #endif
1198 //r=reg to load, fr=from reg, symbol for relocation, constant
1200 void C67_MVKL(int r, int fc)
1202 C67_asm("MVKL.", fc, r, 0);
1205 void C67_MVKH(int r, int fc)
1207 C67_asm("MVKH.", fc, r, 0);
1210 void C67_STB_SP_A0(int r)
1212 C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB r,*+SP[A0]
1215 void C67_STH_SP_A0(int r)
1217 C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH r,*+SP[A0]
1220 void C67_STW_SP_A0(int r)
1222 C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW r,*+SP[A0]
1225 void C67_STB_PTR(int r, int r2)
1227 C67_asm("STB.D *", r, r2, 0); // STB r, *r2
1230 void C67_STH_PTR(int r, int r2)
1232 C67_asm("STH.D *", r, r2, 0); // STH r, *r2
1235 void C67_STW_PTR(int r, int r2)
1237 C67_asm("STW.D *", r, r2, 0); // STW r, *r2
1240 void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1242 C67_asm("STW.D +*", r, r2, n); // STW r, *+r2
1245 void C67_PUSH(int r)
1247 C67_asm("STW.D SP POST DEC", r, 0, 0); // STW r,*SP--
1250 void C67_LDW_SP_A0(int r)
1252 C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW *+SP[A0],r
1255 void C67_LDDW_SP_A0(int r)
1257 C67_asm("LDDW.D *+SP[A0]", r, 0, 0); // LDDW *+SP[A0],r
1260 void C67_LDH_SP_A0(int r)
1262 C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH *+SP[A0],r
1265 void C67_LDB_SP_A0(int r)
1267 C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB *+SP[A0],r
1270 void C67_LDHU_SP_A0(int r)
1272 C67_asm("LDHU.D *+SP[A0]", r, 0, 0); // LDHU *+SP[A0],r
1275 void C67_LDBU_SP_A0(int r)
1277 C67_asm("LDBU.D *+SP[A0]", r, 0, 0); // LDBU *+SP[A0],r
1280 void C67_LDW_PTR(int r, int r2)
1282 C67_asm("LDW.D *", r, r2, 0); // LDW *r,r2
1285 void C67_LDDW_PTR(int r, int r2)
1287 C67_asm("LDDW.D *", r, r2, 0); // LDDW *r,r2
1290 void C67_LDH_PTR(int r, int r2)
1292 C67_asm("LDH.D *", r, r2, 0); // LDH *r,r2
1295 void C67_LDB_PTR(int r, int r2)
1297 C67_asm("LDB.D *", r, r2, 0); // LDB *r,r2
1300 void C67_LDHU_PTR(int r, int r2)
1302 C67_asm("LDHU.D *", r, r2, 0); // LDHU *r,r2
1305 void C67_LDBU_PTR(int r, int r2)
1307 C67_asm("LDBU.D *", r, r2, 0); // LDBU *r,r2
1310 void C67_LDW_PTR_PRE_INC(int r, int r2)
1312 C67_asm("LDW.D +*", r, r2, 0); // LDW *+r,r2
1315 void C67_POP(int r)
1317 C67_asm("LDW.D SP PRE INC", r, 0, 0); // LDW *++SP,r
1320 void C67_POP_DW(int r)
1322 C67_asm("LDDW.D SP PRE INC", r, 0, 0); // LDDW *++SP,r
1325 void C67_CMPLT(int s1, int s2, int dst)
1327 C67_asm("CMPLT.L1", s1, s2, dst);
1330 void C67_CMPGT(int s1, int s2, int dst)
1332 C67_asm("CMPGT.L1", s1, s2, dst);
1335 void C67_CMPEQ(int s1, int s2, int dst)
1337 C67_asm("CMPEQ.L1", s1, s2, dst);
1340 void C67_CMPLTU(int s1, int s2, int dst)
1342 C67_asm("CMPLTU.L1", s1, s2, dst);
1345 void C67_CMPGTU(int s1, int s2, int dst)
1347 C67_asm("CMPGTU.L1", s1, s2, dst);
1351 void C67_CMPLTSP(int s1, int s2, int dst)
1353 C67_asm("CMPLTSP.S1", s1, s2, dst);
1356 void C67_CMPGTSP(int s1, int s2, int dst)
1358 C67_asm("CMPGTSP.S1", s1, s2, dst);
1361 void C67_CMPEQSP(int s1, int s2, int dst)
1363 C67_asm("CMPEQSP.S1", s1, s2, dst);
1366 void C67_CMPLTDP(int s1, int s2, int dst)
1368 C67_asm("CMPLTDP.S1", s1, s2, dst);
1371 void C67_CMPGTDP(int s1, int s2, int dst)
1373 C67_asm("CMPGTDP.S1", s1, s2, dst);
1376 void C67_CMPEQDP(int s1, int s2, int dst)
1378 C67_asm("CMPEQDP.S1", s1, s2, dst);
1382 void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2
1384 C67_asm("B.S2", inv, r1, r2);
1388 // call with how many 32 bit words to skip
1389 // (0 would branch to the branch instruction)
1391 void C67_B_DISP(int disp) // B +2 Branch with constant displacement
1393 // Branch point is relative to the 8 word fetch packet
1395 // we will assume the text section always starts on an 8 word (32 byte boundary)
1397 // so add in how many words into the fetch packet the branch is
1400 C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1403 void C67_NOP(int n)
1405 C67_asm("NOP", n, 0, 0);
1408 void C67_ADDK(int n, int r)
1410 ALWAYS_ASSERT(abs(n) < 32767);
1412 C67_asm("ADDK", n, r, 0);
1415 void C67_ADDK_PARALLEL(int n, int r)
1417 ALWAYS_ASSERT(abs(n) < 32767);
1419 C67_asm("||ADDK", n, r, 0);
1422 void C67_Adjust_ADDK(int *inst, int n)
1424 ALWAYS_ASSERT(abs(n) < 32767);
1426 *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1429 void C67_MV(int r, int v)
1431 C67_asm("MV.L", 0, r, v);
1435 void C67_DPTRUNC(int r, int v)
1437 C67_asm("DPTRUNC.L", 0, r, v);
1440 void C67_SPTRUNC(int r, int v)
1442 C67_asm("SPTRUNC.L", 0, r, v);
1445 void C67_INTSP(int r, int v)
1447 C67_asm("INTSP.L", 0, r, v);
1450 void C67_INTDP(int r, int v)
1452 C67_asm("INTDP.L", 0, r, v);
1455 void C67_INTSPU(int r, int v)
1457 C67_asm("INTSPU.L", 0, r, v);
1460 void C67_INTDPU(int r, int v)
1462 C67_asm("INTDPU.L", 0, r, v);
1465 void C67_SPDP(int r, int v)
1467 C67_asm("SPDP.L", 0, r, v);
1470 void C67_DPSP(int r, int v) // note regs must be on the same side
1472 C67_asm("DPSP.L", 0, r, v);
1475 void C67_ADD(int r, int v)
1477 C67_asm("ADD.L", v, r, v);
1480 void C67_SUB(int r, int v)
1482 C67_asm("SUB.L", v, r, v);
1485 void C67_AND(int r, int v)
1487 C67_asm("AND.L", v, r, v);
1490 void C67_OR(int r, int v)
1492 C67_asm("OR.L", v, r, v);
1495 void C67_XOR(int r, int v)
1497 C67_asm("XOR.L", v, r, v);
1500 void C67_ADDSP(int r, int v)
1502 C67_asm("ADDSP.L", v, r, v);
1505 void C67_SUBSP(int r, int v)
1507 C67_asm("SUBSP.L", v, r, v);
1510 void C67_MPYSP(int r, int v)
1512 C67_asm("MPYSP.M", v, r, v);
1515 void C67_ADDDP(int r, int v)
1517 C67_asm("ADDDP.L", v, r, v);
1520 void C67_SUBDP(int r, int v)
1522 C67_asm("SUBDP.L", v, r, v);
1525 void C67_MPYDP(int r, int v)
1527 C67_asm("MPYDP.M", v, r, v);
1530 void C67_MPYI(int r, int v)
1532 C67_asm("MPYI.M", v, r, v);
1535 void C67_SHL(int r, int v)
1537 C67_asm("SHL.S", r, v, v);
1540 void C67_SHRU(int r, int v)
1542 C67_asm("SHRU.S", r, v, v);
1545 void C67_SHR(int r, int v)
1547 C67_asm("SHR.S", r, v, v);
1552 /* load 'r' from value 'sv' */
1553 void load(int r, SValue * sv)
1555 int v, t, ft, fc, fr, size = 0, element;
1556 BOOL Unsigned = false;
1557 SValue v1;
1559 fr = sv->r;
1560 ft = sv->type.t;
1561 fc = sv->c.ul;
1563 v = fr & VT_VALMASK;
1564 if (fr & VT_LVAL) {
1565 if (v == VT_LLOCAL) {
1566 v1.type.t = VT_INT;
1567 v1.r = VT_LOCAL | VT_LVAL;
1568 v1.c.ul = fc;
1569 load(r, &v1);
1570 fr = r;
1571 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
1572 error("long double not supported");
1573 } else if ((ft & VT_TYPE) == VT_BYTE) {
1574 size = 1;
1575 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1576 size = 1;
1577 Unsigned = TRUE;
1578 } else if ((ft & VT_TYPE) == VT_SHORT) {
1579 size = 2;
1580 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1581 size = 2;
1582 Unsigned = TRUE;
1583 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1584 size = 8;
1585 } else {
1586 size = 4;
1589 // check if fc is a positive reference on the stack,
1590 // if it is tcc is referencing what it thinks is a parameter
1591 // on the stack, so check if it is really in a register.
1594 if (v == VT_LOCAL && fc > 0) {
1595 int stack_pos = 8;
1597 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1598 if (fc == stack_pos)
1599 break;
1601 stack_pos += TranslateStackToReg[t];
1604 // param has been pushed on stack, get it like a local var
1606 fc = ParamLocOnStack[t] - 8;
1609 if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect
1611 if (size == 1) {
1612 if (Unsigned)
1613 C67_LDBU_PTR(v, r); // LDBU *v,r
1614 else
1615 C67_LDB_PTR(v, r); // LDB *v,r
1616 } else if (size == 2) {
1617 if (Unsigned)
1618 C67_LDHU_PTR(v, r); // LDHU *v,r
1619 else
1620 C67_LDH_PTR(v, r); // LDH *v,r
1621 } else if (size == 4) {
1622 C67_LDW_PTR(v, r); // LDW *v,r
1623 } else if (size == 8) {
1624 C67_LDDW_PTR(v, r); // LDDW *v,r
1627 C67_NOP(4); // NOP 4
1628 return;
1629 } else if (fr & VT_SYM) {
1630 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1631 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1634 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1635 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1638 if (size == 1) {
1639 if (Unsigned)
1640 C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r
1641 else
1642 C67_LDB_PTR(C67_A0, r); // LDB *A0,r
1643 } else if (size == 2) {
1644 if (Unsigned)
1645 C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r
1646 else
1647 C67_LDH_PTR(C67_A0, r); // LDH *A0,r
1648 } else if (size == 4) {
1649 C67_LDW_PTR(C67_A0, r); // LDW *A0,r
1650 } else if (size == 8) {
1651 C67_LDDW_PTR(C67_A0, r); // LDDW *A0,r
1654 C67_NOP(4); // NOP 4
1655 return;
1656 } else {
1657 element = size;
1659 // divide offset in bytes to create element index
1660 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1661 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1663 if (size == 1) {
1664 if (Unsigned)
1665 C67_LDBU_SP_A0(r); // LDBU r, SP[A0]
1666 else
1667 C67_LDB_SP_A0(r); // LDB r, SP[A0]
1668 } else if (size == 2) {
1669 if (Unsigned)
1670 C67_LDHU_SP_A0(r); // LDHU r, SP[A0]
1671 else
1672 C67_LDH_SP_A0(r); // LDH r, SP[A0]
1673 } else if (size == 4) {
1674 C67_LDW_SP_A0(r); // LDW r, SP[A0]
1675 } else if (size == 8) {
1676 C67_LDDW_SP_A0(r); // LDDW r, SP[A0]
1680 C67_NOP(4); // NOP 4
1681 return;
1683 } else {
1684 if (v == VT_CONST) {
1685 if (fr & VT_SYM) {
1686 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1687 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1689 C67_MVKL(r, fc); //r=reg to load, constant
1690 C67_MVKH(r, fc); //r=reg to load, constant
1691 } else if (v == VT_LOCAL) {
1692 C67_MVKL(r, fc + 8); //r=reg to load, constant C67 stack points to next free
1693 C67_MVKH(r, fc + 8); //r=reg to load, constant
1694 C67_ADD(C67_FP, r); // MV v,r v -> r
1695 } else if (v == VT_CMP) {
1696 C67_MV(C67_compare_reg, r); // MV v,r v -> r
1697 } else if (v == VT_JMP || v == VT_JMPI) {
1698 t = v & 1;
1699 C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
1700 C67_MVKL(r, t); // r=reg to load, 0 or 1 (do this while branching)
1701 C67_NOP(4); // NOP 4
1702 gsym(fc); // modifies other branches to branch here
1703 C67_MVKL(r, t ^ 1); // r=reg to load, 0 or 1
1704 } else if (v != r) {
1705 C67_MV(v, r); // MV v,r v -> r
1707 if ((ft & VT_BTYPE) == VT_DOUBLE)
1708 C67_MV(v + 1, r + 1); // MV v,r v -> r
1714 /* store register 'r' in lvalue 'v' */
1715 void store(int r, SValue * v)
1717 int fr, bt, ft, fc, size, t, element;
1719 ft = v->type.t;
1720 fc = v->c.ul;
1721 fr = v->r & VT_VALMASK;
1722 bt = ft & VT_BTYPE;
1723 /* XXX: incorrect if float reg to reg */
1725 if (bt == VT_LDOUBLE) {
1726 error("long double not supported");
1727 } else {
1728 if (bt == VT_SHORT)
1729 size = 2;
1730 else if (bt == VT_BYTE)
1731 size = 1;
1732 else if (bt == VT_DOUBLE)
1733 size = 8;
1734 else
1735 size = 4;
1737 if ((v->r & VT_VALMASK) == VT_CONST) {
1738 /* constant memory reference */
1740 if (v->r & VT_SYM) {
1741 greloc(cur_text_section, v->sym, ind, R_C60LO16); // rem the inst need to be patched
1742 greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
1744 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1745 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1747 if (size == 1)
1748 C67_STB_PTR(r, C67_A0); // STB r, *A0
1749 else if (size == 2)
1750 C67_STH_PTR(r, C67_A0); // STH r, *A0
1751 else if (size == 4 || size == 8)
1752 C67_STW_PTR(r, C67_A0); // STW r, *A0
1754 if (size == 8)
1755 C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1); // STW r, *+A0[1]
1756 } else if ((v->r & VT_VALMASK) == VT_LOCAL) {
1757 // check case of storing to passed argument that
1758 // tcc thinks is on the stack but for C67 is
1759 // passed as a reg. However it may have been
1760 // saved to the stack, if that reg was required
1761 // for a call to a child function
1763 if (fc > 0) // argument ??
1765 // walk through sizes and figure which param
1767 int stack_pos = 8;
1769 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1770 if (fc == stack_pos)
1771 break;
1773 stack_pos += TranslateStackToReg[t];
1776 // param has been pushed on stack, get it like a local var
1777 fc = ParamLocOnStack[t] - 8;
1780 if (size == 8)
1781 element = 4;
1782 else
1783 element = size;
1785 // divide offset in bytes to create word index
1786 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1787 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1791 if (size == 1)
1792 C67_STB_SP_A0(r); // STB r, SP[A0]
1793 else if (size == 2)
1794 C67_STH_SP_A0(r); // STH r, SP[A0]
1795 else if (size == 4 || size == 8)
1796 C67_STW_SP_A0(r); // STW r, SP[A0]
1798 if (size == 8) {
1799 C67_ADDK(1, C67_A0); // ADDK 1,A0
1800 C67_STW_SP_A0(r + 1); // STW r, SP[A0]
1802 } else {
1803 if (size == 1)
1804 C67_STB_PTR(r, fr); // STB r, *fr
1805 else if (size == 2)
1806 C67_STH_PTR(r, fr); // STH r, *fr
1807 else if (size == 4 || size == 8)
1808 C67_STW_PTR(r, fr); // STW r, *fr
1810 if (size == 8) {
1811 C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1]
1817 /* 'is_jmp' is '1' if it is a jump */
1818 static void gcall_or_jmp(int is_jmp)
1820 int r;
1821 Sym *sym;
1823 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1824 /* constant case */
1825 if (vtop->r & VT_SYM) {
1826 /* relocation case */
1828 // get add into A0, then start the jump B3
1830 greloc(cur_text_section, vtop->sym, ind, R_C60LO16); // rem the inst need to be patched
1831 greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
1833 C67_MVKL(C67_A0, 0); //r=reg to load, constant
1834 C67_MVKH(C67_A0, 0); //r=reg to load, constant
1835 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // B.S2x A0
1837 if (is_jmp) {
1838 C67_NOP(5); // simple jump, just put NOP
1839 } else {
1840 // Call, must load return address into B3 during delay slots
1842 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1843 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1844 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1845 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1846 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1847 C67_NOP(3); // put remaining NOPs
1849 } else {
1850 /* put an empty PC32 relocation */
1851 ALWAYS_ASSERT(FALSE);
1853 } else {
1854 /* otherwise, indirect call */
1855 r = gv(RC_INT);
1856 C67_IREG_B_REG(0, C67_CREG_ZERO, r); // B.S2x r
1858 if (is_jmp) {
1859 C67_NOP(5); // simple jump, just put NOP
1860 } else {
1861 // Call, must load return address into B3 during delay slots
1863 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1864 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1865 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1866 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1867 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1868 C67_NOP(3); // put remaining NOPs
1873 /* generate function call with address in (vtop->t, vtop->c) and free function
1874 context. Stack entry is popped */
1875 void gfunc_call(int nb_args)
1877 int i, r, size = 0;
1878 int args_sizes[NoCallArgsPassedOnStack];
1880 if (nb_args > NoCallArgsPassedOnStack) {
1881 error("more than 10 function params not currently supported");
1882 // handle more than 10, put some on the stack
1885 for (i = 0; i < nb_args; i++) {
1886 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1887 ALWAYS_ASSERT(FALSE);
1888 } else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1889 ALWAYS_ASSERT(FALSE);
1890 } else {
1891 /* simple type (currently always same size) */
1892 /* XXX: implicit cast ? */
1895 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1896 error("long long not supported");
1897 } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
1898 error("long double not supported");
1899 } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1900 size = 8;
1901 } else {
1902 size = 4;
1905 // put the parameter into the corresponding reg (pair)
1907 r = gv(RC_C67_A4 << (2 * i));
1909 // must put on stack because with 1 pass compiler , no way to tell
1910 // if an up coming nested call might overwrite these regs
1912 C67_PUSH(r);
1914 if (size == 8) {
1915 C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3); // STW r, *+SP[3] (go back and put the other)
1917 args_sizes[i] = size;
1919 vtop--;
1921 // POP all the params on the stack into registers for the
1922 // immediate call (in reverse order)
1924 for (i = nb_args - 1; i >= 0; i--) {
1926 if (args_sizes[i] == 8)
1927 C67_POP_DW(TREG_C67_A4 + i * 2);
1928 else
1929 C67_POP(TREG_C67_A4 + i * 2);
1931 gcall_or_jmp(0);
1932 vtop--;
1936 // to be compatible with Code Composer for the C67
1937 // the first 10 parameters must be passed in registers
1938 // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1939 // ending with B12:B13.
1941 // When a call is made, if the caller has its parameters
1942 // in regs A4-B13 these must be saved before/as the call
1943 // parameters are loaded and restored upon return (or if/when needed).
1945 /* generate function prolog of type 't' */
1946 void gfunc_prolog(CType * func_type)
1948 int addr, align, size, func_call, i;
1949 Sym *sym;
1950 CType *type;
1952 sym = func_type->ref;
1953 func_call = sym->r;
1954 addr = 8;
1955 /* if the function returns a structure, then add an
1956 implicit pointer parameter */
1957 func_vt = sym->type;
1958 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1959 func_vc = addr;
1960 addr += 4;
1963 NoOfCurFuncArgs = 0;
1965 /* define parameters */
1966 while ((sym = sym->next) != NULL) {
1967 type = &sym->type;
1968 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
1969 size = type_size(type, &align);
1970 size = (size + 3) & ~3;
1972 // keep track of size of arguments so
1973 // we can translate where tcc thinks they
1974 // are on the stack into the appropriate reg
1976 TranslateStackToReg[NoOfCurFuncArgs] = size;
1977 NoOfCurFuncArgs++;
1979 #ifdef FUNC_STRUCT_PARAM_AS_PTR
1980 /* structs are passed as pointer */
1981 if ((type->t & VT_BTYPE) == VT_STRUCT) {
1982 size = 4;
1984 #endif
1985 addr += size;
1987 func_ret_sub = 0;
1988 /* pascal type call ? */
1989 if (func_call == FUNC_STDCALL)
1990 func_ret_sub = addr - 8;
1992 C67_MV(C67_FP, C67_A0); // move FP -> A0
1993 C67_MV(C67_SP, C67_FP); // move SP -> FP
1995 // place all the args passed in regs onto the stack
1997 loc = 0;
1998 for (i = 0; i < NoOfCurFuncArgs; i++) {
2000 ParamLocOnStack[i] = loc; // remember where the param is
2001 loc += -8;
2003 C67_PUSH(TREG_C67_A4 + i * 2);
2005 if (TranslateStackToReg[i] == 8) {
2006 C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3); // STW r, *+SP[1] (go back and put the other)
2010 TotalBytesPushedOnStack = -loc;
2012 func_sub_sp_offset = ind; // remember where we put the stack instruction
2013 C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily)
2015 C67_PUSH(C67_A0);
2016 C67_PUSH(C67_B3);
2019 /* generate function epilog */
2020 void gfunc_epilog(void)
2023 int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2024 C67_POP(C67_B3);
2025 C67_NOP(4); // NOP wait for load
2026 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3
2027 C67_POP(C67_FP);
2028 C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP
2029 C67_Adjust_ADDK((int *) (cur_text_section->data +
2030 func_sub_sp_offset),
2031 -local + TotalBytesPushedOnStack);
2032 C67_NOP(3); // NOP
2036 /* generate a jump to a label */
2037 int gjmp(int t)
2039 int ind1 = ind;
2041 C67_MVKL(C67_A0, t); //r=reg to load, constant
2042 C67_MVKH(C67_A0, t); //r=reg to load, constant
2043 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // [!R] B.S2x A0
2044 C67_NOP(5);
2045 return ind1;
2048 /* generate a jump to a fixed address */
2049 void gjmp_addr(int a)
2051 Sym *sym;
2052 // I guess this routine is used for relative short
2053 // local jumps, for now just handle it as the general
2054 // case
2056 // define a label that will be relocated
2058 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
2059 greloc(cur_text_section, sym, ind, R_C60LO16);
2060 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
2062 gjmp(0); // place a zero there later the symbol will be added to it
2065 /* generate a test. set 'inv' to invert test. Stack entry is popped */
2066 int gtst(int inv, int t)
2068 int ind1, n;
2069 int v, *p;
2071 v = vtop->r & VT_VALMASK;
2072 if (v == VT_CMP) {
2073 /* fast case : can jump directly since flags are set */
2074 // C67 uses B2 sort of as flags register
2075 ind1 = ind;
2076 C67_MVKL(C67_A0, t); //r=reg to load, constant
2077 C67_MVKH(C67_A0, t); //r=reg to load, constant
2079 if (C67_compare_reg != TREG_EAX && // check if not already in a conditional test reg
2080 C67_compare_reg != TREG_EDX &&
2081 C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
2082 C67_MV(C67_compare_reg, C67_B2);
2083 C67_compare_reg = C67_B2;
2086 C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x A0
2087 C67_NOP(5);
2088 t = ind1; //return where we need to patch
2090 } else if (v == VT_JMP || v == VT_JMPI) {
2091 /* && or || optimization */
2092 if ((v & 1) == inv) {
2093 /* insert vtop->c jump list in t */
2094 p = &vtop->c.i;
2096 // I guess the idea is to traverse to the
2097 // null at the end of the list and store t
2098 // there
2100 n = *p;
2101 while (n != 0) {
2102 p = (int *) (cur_text_section->data + n);
2104 // extract 32 bit address from MVKH/MVKL
2105 n = ((*p >> 7) & 0xffff);
2106 n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2108 *p |= (t & 0xffff) << 7;
2109 *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2110 t = vtop->c.i;
2112 } else {
2113 t = gjmp(t);
2114 gsym(vtop->c.i);
2116 } else {
2117 if (is_float(vtop->type.t)) {
2118 vpushi(0);
2119 gen_op(TOK_NE);
2121 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
2122 /* constant jmp optimization */
2123 if ((vtop->c.i != 0) != inv)
2124 t = gjmp(t);
2125 } else {
2126 // I think we need to get the value on the stack
2127 // into a register, test it, and generate a branch
2128 // return the address of the branch, so it can be
2129 // later patched
2131 v = gv(RC_INT); // get value into a reg
2132 ind1 = ind;
2133 C67_MVKL(C67_A0, t); //r=reg to load, constant
2134 C67_MVKH(C67_A0, t); //r=reg to load, constant
2136 if (v != TREG_EAX && // check if not already in a conditional test reg
2137 v != TREG_EDX && v != TREG_ST0 && v != C67_B2) {
2138 C67_MV(v, C67_B2);
2139 v = C67_B2;
2142 C67_IREG_B_REG(inv, v, C67_A0); // [!R] B.S2x A0
2143 C67_NOP(5);
2144 t = ind1; //return where we need to patch
2145 ind1 = ind;
2148 vtop--;
2149 return t;
2152 /* generate an integer binary operation */
2153 void gen_opi(int op)
2155 int r, fr, opc, t;
2157 switch (op) {
2158 case '+':
2159 case TOK_ADDC1: /* add with carry generation */
2160 opc = 0;
2161 gen_op8:
2164 // C67 can't do const compares, must load into a reg
2165 // so just go to gv2 directly - tktk
2169 if (op >= TOK_ULT && op <= TOK_GT)
2170 gv2(RC_INT_BSIDE, RC_INT); // make sure r (src1) is on the B Side of CPU
2171 else
2172 gv2(RC_INT, RC_INT);
2174 r = vtop[-1].r;
2175 fr = vtop[0].r;
2177 C67_compare_reg = C67_B2;
2180 if (op == TOK_LT) {
2181 C67_CMPLT(r, fr, C67_B2);
2182 C67_invert_test = false;
2183 } else if (op == TOK_GE) {
2184 C67_CMPLT(r, fr, C67_B2);
2185 C67_invert_test = true;
2186 } else if (op == TOK_GT) {
2187 C67_CMPGT(r, fr, C67_B2);
2188 C67_invert_test = false;
2189 } else if (op == TOK_LE) {
2190 C67_CMPGT(r, fr, C67_B2);
2191 C67_invert_test = true;
2192 } else if (op == TOK_EQ) {
2193 C67_CMPEQ(r, fr, C67_B2);
2194 C67_invert_test = false;
2195 } else if (op == TOK_NE) {
2196 C67_CMPEQ(r, fr, C67_B2);
2197 C67_invert_test = true;
2198 } else if (op == TOK_ULT) {
2199 C67_CMPLTU(r, fr, C67_B2);
2200 C67_invert_test = false;
2201 } else if (op == TOK_UGE) {
2202 C67_CMPLTU(r, fr, C67_B2);
2203 C67_invert_test = true;
2204 } else if (op == TOK_UGT) {
2205 C67_CMPGTU(r, fr, C67_B2);
2206 C67_invert_test = false;
2207 } else if (op == TOK_ULE) {
2208 C67_CMPGTU(r, fr, C67_B2);
2209 C67_invert_test = true;
2210 } else if (op == '+')
2211 C67_ADD(fr, r); // ADD r,fr,r
2212 else if (op == '-')
2213 C67_SUB(fr, r); // SUB r,fr,r
2214 else if (op == '&')
2215 C67_AND(fr, r); // AND r,fr,r
2216 else if (op == '|')
2217 C67_OR(fr, r); // OR r,fr,r
2218 else if (op == '^')
2219 C67_XOR(fr, r); // XOR r,fr,r
2220 else
2221 ALWAYS_ASSERT(FALSE);
2223 vtop--;
2224 if (op >= TOK_ULT && op <= TOK_GT) {
2225 vtop->r = VT_CMP;
2226 vtop->c.i = op;
2228 break;
2229 case '-':
2230 case TOK_SUBC1: /* sub with carry generation */
2231 opc = 5;
2232 goto gen_op8;
2233 case TOK_ADDC2: /* add with carry use */
2234 opc = 2;
2235 goto gen_op8;
2236 case TOK_SUBC2: /* sub with carry use */
2237 opc = 3;
2238 goto gen_op8;
2239 case '&':
2240 opc = 4;
2241 goto gen_op8;
2242 case '^':
2243 opc = 6;
2244 goto gen_op8;
2245 case '|':
2246 opc = 1;
2247 goto gen_op8;
2248 case '*':
2249 case TOK_UMULL:
2250 gv2(RC_INT, RC_INT);
2251 r = vtop[-1].r;
2252 fr = vtop[0].r;
2253 vtop--;
2254 C67_MPYI(fr, r); // 32 bit bultiply fr,r,fr
2255 C67_NOP(8); // NOP 8 for worst case
2256 break;
2257 case TOK_SHL:
2258 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2259 r = vtop[-1].r;
2260 fr = vtop[0].r;
2261 vtop--;
2262 C67_SHL(fr, r); // arithmetic/logical shift
2263 break;
2265 case TOK_SHR:
2266 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2267 r = vtop[-1].r;
2268 fr = vtop[0].r;
2269 vtop--;
2270 C67_SHRU(fr, r); // logical shift
2271 break;
2273 case TOK_SAR:
2274 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2275 r = vtop[-1].r;
2276 fr = vtop[0].r;
2277 vtop--;
2278 C67_SHR(fr, r); // arithmetic shift
2279 break;
2281 case '/':
2282 t = TOK__divi;
2283 call_func:
2284 vswap();
2285 /* call generic idiv function */
2286 vpush_global_sym(&func_old_type, t);
2287 vrott(3);
2288 gfunc_call(2);
2289 vpushi(0);
2290 vtop->r = REG_IRET;
2291 vtop->r2 = VT_CONST;
2292 break;
2293 case TOK_UDIV:
2294 case TOK_PDIV:
2295 t = TOK__divu;
2296 goto call_func;
2297 case '%':
2298 t = TOK__remi;
2299 goto call_func;
2300 case TOK_UMOD:
2301 t = TOK__remu;
2302 goto call_func;
2304 default:
2305 opc = 7;
2306 goto gen_op8;
2310 /* generate a floating point operation 'v = t1 op t2' instruction. The
2311 two operands are guaranted to have the same floating point type */
2312 /* XXX: need to use ST1 too */
2313 void gen_opf(int op)
2315 int ft, fc, fr, r;
2317 if (op >= TOK_ULT && op <= TOK_GT)
2318 gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
2319 else
2320 gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
2322 ft = vtop->type.t;
2323 fc = vtop->c.ul;
2324 r = vtop->r;
2325 fr = vtop[-1].r;
2328 if ((ft & VT_BTYPE) == VT_LDOUBLE)
2329 error("long doubles not supported");
2331 if (op >= TOK_ULT && op <= TOK_GT) {
2333 r = vtop[-1].r;
2334 fr = vtop[0].r;
2336 C67_compare_reg = C67_B2;
2338 if (op == TOK_LT) {
2339 if ((ft & VT_BTYPE) == VT_DOUBLE)
2340 C67_CMPLTDP(r, fr, C67_B2);
2341 else
2342 C67_CMPLTSP(r, fr, C67_B2);
2344 C67_invert_test = false;
2345 } else if (op == TOK_GE) {
2346 if ((ft & VT_BTYPE) == VT_DOUBLE)
2347 C67_CMPLTDP(r, fr, C67_B2);
2348 else
2349 C67_CMPLTSP(r, fr, C67_B2);
2351 C67_invert_test = true;
2352 } else if (op == TOK_GT) {
2353 if ((ft & VT_BTYPE) == VT_DOUBLE)
2354 C67_CMPGTDP(r, fr, C67_B2);
2355 else
2356 C67_CMPGTSP(r, fr, C67_B2);
2358 C67_invert_test = false;
2359 } else if (op == TOK_LE) {
2360 if ((ft & VT_BTYPE) == VT_DOUBLE)
2361 C67_CMPGTDP(r, fr, C67_B2);
2362 else
2363 C67_CMPGTSP(r, fr, C67_B2);
2365 C67_invert_test = true;
2366 } else if (op == TOK_EQ) {
2367 if ((ft & VT_BTYPE) == VT_DOUBLE)
2368 C67_CMPEQDP(r, fr, C67_B2);
2369 else
2370 C67_CMPEQSP(r, fr, C67_B2);
2372 C67_invert_test = false;
2373 } else if (op == TOK_NE) {
2374 if ((ft & VT_BTYPE) == VT_DOUBLE)
2375 C67_CMPEQDP(r, fr, C67_B2);
2376 else
2377 C67_CMPEQSP(r, fr, C67_B2);
2379 C67_invert_test = true;
2380 } else {
2381 ALWAYS_ASSERT(FALSE);
2383 vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2
2384 } else {
2385 if (op == '+') {
2386 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2387 C67_ADDDP(r, fr); // ADD fr,r,fr
2388 C67_NOP(6);
2389 } else {
2390 C67_ADDSP(r, fr); // ADD fr,r,fr
2391 C67_NOP(3);
2393 vtop--;
2394 } else if (op == '-') {
2395 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2396 C67_SUBDP(r, fr); // SUB fr,r,fr
2397 C67_NOP(6);
2398 } else {
2399 C67_SUBSP(r, fr); // SUB fr,r,fr
2400 C67_NOP(3);
2402 vtop--;
2403 } else if (op == '*') {
2404 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2405 C67_MPYDP(r, fr); // MPY fr,r,fr
2406 C67_NOP(9);
2407 } else {
2408 C67_MPYSP(r, fr); // MPY fr,r,fr
2409 C67_NOP(3);
2411 vtop--;
2412 } else if (op == '/') {
2413 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2414 // must call intrinsic DP floating point divide
2415 vswap();
2416 /* call generic idiv function */
2417 vpush_global_sym(&func_old_type, TOK__divd);
2418 vrott(3);
2419 gfunc_call(2);
2420 vpushi(0);
2421 vtop->r = REG_FRET;
2422 vtop->r2 = REG_LRET;
2424 } else {
2425 // must call intrinsic SP floating point divide
2426 vswap();
2427 /* call generic idiv function */
2428 vpush_global_sym(&func_old_type, TOK__divf);
2429 vrott(3);
2430 gfunc_call(2);
2431 vpushi(0);
2432 vtop->r = REG_FRET;
2433 vtop->r2 = VT_CONST;
2435 } else
2436 ALWAYS_ASSERT(FALSE);
2443 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2444 and 'long long' cases. */
2445 void gen_cvt_itof(int t)
2447 int r;
2449 gv(RC_INT);
2450 r = vtop->r;
2452 if ((t & VT_BTYPE) == VT_DOUBLE) {
2453 if (t & VT_UNSIGNED)
2454 C67_INTDPU(r, r);
2455 else
2456 C67_INTDP(r, r);
2458 C67_NOP(4);
2459 vtop->type.t = VT_DOUBLE;
2460 } else {
2461 if (t & VT_UNSIGNED)
2462 C67_INTSPU(r, r);
2463 else
2464 C67_INTSP(r, r);
2465 C67_NOP(3);
2466 vtop->type.t = VT_FLOAT;
2471 /* convert fp to int 't' type */
2472 /* XXX: handle long long case */
2473 void gen_cvt_ftoi(int t)
2475 int r;
2477 gv(RC_FLOAT);
2478 r = vtop->r;
2480 if (t != VT_INT)
2481 error("long long not supported");
2482 else {
2483 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2484 C67_DPTRUNC(r, r);
2485 C67_NOP(3);
2486 } else {
2487 C67_SPTRUNC(r, r);
2488 C67_NOP(3);
2491 vtop->type.t = VT_INT;
2496 /* convert from one floating point type to another */
2497 void gen_cvt_ftof(int t)
2499 int r, r2;
2501 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2502 (t & VT_BTYPE) == VT_FLOAT) {
2503 // convert double to float
2505 gv(RC_FLOAT); // get it in a register pair
2507 r = vtop->r;
2509 C67_DPSP(r, r); // convert it to SP same register
2510 C67_NOP(3);
2512 vtop->type.t = VT_FLOAT;
2513 vtop->r2 = VT_CONST; // set this as unused
2514 } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
2515 (t & VT_BTYPE) == VT_DOUBLE) {
2516 // convert float to double
2518 gv(RC_FLOAT); // get it in a register
2520 r = vtop->r;
2522 if (r == TREG_EAX) { // make sure the paired reg is avail
2523 r2 = get_reg(RC_ECX);
2524 } else if (r == TREG_EDX) {
2525 r2 = get_reg(RC_ST0);
2526 } else {
2527 ALWAYS_ASSERT(FALSE);
2528 r2 = 0; /* avoid warning */
2531 C67_SPDP(r, r); // convert it to DP same register
2532 C67_NOP(1);
2534 vtop->type.t = VT_DOUBLE;
2535 vtop->r2 = r2; // set this as unused
2536 } else {
2537 ALWAYS_ASSERT(FALSE);
2541 /* computed goto support */
2542 void ggoto(void)
2544 gcall_or_jmp(1);
2545 vtop--;
2548 /* end of X86 code generator */
2549 /*************************************************************/