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