riscv: fp parameters
[tinycc.git] / c67-gen.c
blob880a5720813158ca01ca4932b317b26f51a3f816
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 /* defined if function parameters must be evaluated in reverse order */
96 /* #define INVERT_FUNC_PARAMS */
98 /* defined if structures are passed as pointers. Otherwise structures
99 are directly pushed on stack. */
100 /* #define FUNC_STRUCT_PARAM_AS_PTR */
102 /* pointer size, in bytes */
103 #define PTR_SIZE 4
105 /* long double size and alignment, in bytes */
106 #define LDOUBLE_SIZE 12
107 #define LDOUBLE_ALIGN 4
108 /* maximum alignment (for aligned attribute support) */
109 #define MAX_ALIGN 8
111 /******************************************************/
112 #else /* ! TARGET_DEFS_ONLY */
113 /******************************************************/
114 #include "tcc.h"
116 ST_DATA const int reg_classes[NB_REGS] = {
117 /* eax */ RC_INT | RC_FLOAT | RC_EAX,
118 // only allow even regs for floats (allow for doubles)
119 /* ecx */ RC_INT | RC_ECX,
120 /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
121 // only allow even regs for floats (allow for doubles)
122 /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
123 /* A4 */ RC_C67_A4,
124 /* A5 */ RC_C67_A5,
125 /* B4 */ RC_C67_B4,
126 /* B5 */ RC_C67_B5,
127 /* A6 */ RC_C67_A6,
128 /* A7 */ RC_C67_A7,
129 /* B6 */ RC_C67_B6,
130 /* B7 */ RC_C67_B7,
131 /* A8 */ RC_C67_A8,
132 /* A9 */ RC_C67_A9,
133 /* B8 */ RC_C67_B8,
134 /* B9 */ RC_C67_B9,
135 /* A10 */ RC_C67_A10,
136 /* A11 */ RC_C67_A11,
137 /* B10 */ RC_C67_B10,
138 /* B11 */ RC_C67_B11,
139 /* A12 */ RC_C67_A10,
140 /* A13 */ RC_C67_A11,
141 /* B12 */ RC_C67_B10,
142 /* B13 */ RC_C67_B11
145 // although tcc thinks it is passing parameters on the stack,
146 // the C67 really passes up to the first 10 params in special
147 // regs or regs pairs (for 64 bit params). So keep track of
148 // the stack offsets so we can translate to the appropriate
149 // reg (pair)
151 #define NoCallArgsPassedOnStack 10
152 int NoOfCurFuncArgs;
153 int TranslateStackToReg[NoCallArgsPassedOnStack];
154 int ParamLocOnStack[NoCallArgsPassedOnStack];
155 int TotalBytesPushedOnStack;
157 #ifndef FALSE
158 # define FALSE 0
159 # define TRUE 1
160 #endif
162 #undef BOOL
163 #define BOOL int
165 #define ALWAYS_ASSERT(x) \
166 do {\
167 if (!(x))\
168 tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
169 } while (0)
171 /******************************************************/
172 static unsigned long func_sub_sp_offset;
173 static int func_ret_sub;
175 static BOOL C67_invert_test;
176 static int C67_compare_reg;
178 #ifdef ASSEMBLY_LISTING_C67
179 FILE *f = NULL;
180 #endif
182 void C67_g(int c)
184 int ind1;
185 if (nocode_wanted)
186 return;
187 #ifdef ASSEMBLY_LISTING_C67
188 fprintf(f, " %08X", c);
189 #endif
190 ind1 = ind + 4;
191 if (ind1 > (int) cur_text_section->data_allocated)
192 section_realloc(cur_text_section, ind1);
193 cur_text_section->data[ind] = c & 0xff;
194 cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
195 cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
196 cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
197 ind = ind1;
201 /* output a symbol and patch all calls to it */
202 void gsym_addr(int t, int a)
204 int n, *ptr;
205 while (t) {
206 ptr = (int *) (cur_text_section->data + t);
208 Sym *sym;
210 // extract 32 bit address from MVKH/MVKL
211 n = ((*ptr >> 7) & 0xffff);
212 n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
214 // define a label that will be relocated
216 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
217 greloc(cur_text_section, sym, t, R_C60LO16);
218 greloc(cur_text_section, sym, t + 4, R_C60HI16);
220 // clear out where the pointer was
222 *ptr &= ~(0xffff << 7);
223 *(ptr + 1) &= ~(0xffff << 7);
225 t = n;
229 // these are regs that tcc doesn't really know about,
230 // but assign them unique values so the mapping routines
231 // can distinguish them
233 #define C67_A0 105
234 #define C67_SP 106
235 #define C67_B3 107
236 #define C67_FP 108
237 #define C67_B2 109
238 #define C67_CREG_ZERO -1 /* Special code for no condition reg test */
241 int ConvertRegToRegClass(int r)
243 // only works for A4-B13
245 return RC_C67_A4 << (r - TREG_C67_A4);
249 // map TCC reg to C67 reg number
251 int C67_map_regn(int r)
253 if (r == 0) // normal tcc regs
254 return 0x2; // A2
255 else if (r == 1) // normal tcc regs
256 return 3; // A3
257 else if (r == 2) // normal tcc regs
258 return 0; // B0
259 else if (r == 3) // normal tcc regs
260 return 1; // B1
261 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
262 return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
263 else if (r == C67_A0)
264 return 0; // set to A0 (offset reg)
265 else if (r == C67_B2)
266 return 2; // set to B2 (offset reg)
267 else if (r == C67_B3)
268 return 3; // set to B3 (return address reg)
269 else if (r == C67_SP)
270 return 15; // set to SP (B15) (offset reg)
271 else if (r == C67_FP)
272 return 15; // set to FP (A15) (offset reg)
273 else if (r == C67_CREG_ZERO)
274 return 0; // Special code for no condition reg test
275 else
276 ALWAYS_ASSERT(FALSE);
278 return 0;
281 // mapping from tcc reg number to
282 // C67 register to condition code field
284 // valid condition code regs are:
286 // tcc reg 2 ->B0 -> 1
287 // tcc reg 3 ->B1 -> 2
288 // tcc reg 0 -> A2 -> 5
289 // tcc reg 1 -> A3 -> X
290 // tcc reg B2 -> 3
292 int C67_map_regc(int r)
294 if (r == 0) // normal tcc regs
295 return 0x5;
296 else if (r == 2) // normal tcc regs
297 return 0x1;
298 else if (r == 3) // normal tcc regs
299 return 0x2;
300 else if (r == C67_B2) // normal tcc regs
301 return 0x3;
302 else if (r == C67_CREG_ZERO)
303 return 0; // Special code for no condition reg test
304 else
305 ALWAYS_ASSERT(FALSE);
307 return 0;
311 // map TCC reg to C67 reg side A or B
313 int C67_map_regs(int r)
315 if (r == 0) // normal tcc regs
316 return 0x0;
317 else if (r == 1) // normal tcc regs
318 return 0x0;
319 else if (r == 2) // normal tcc regs
320 return 0x1;
321 else if (r == 3) // normal tcc regs
322 return 0x1;
323 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
324 return (r & 2) >> 1;
325 else if (r == C67_A0)
326 return 0; // set to A side
327 else if (r == C67_B2)
328 return 1; // set to B side
329 else if (r == C67_B3)
330 return 1; // set to B side
331 else if (r == C67_SP)
332 return 0x1; // set to SP (B15) B side
333 else if (r == C67_FP)
334 return 0x0; // set to FP (A15) A side
335 else
336 ALWAYS_ASSERT(FALSE);
338 return 0;
341 int C67_map_S12(char *s)
343 if (strstr(s, ".S1") != NULL)
344 return 0;
345 else if (strcmp(s, ".S2"))
346 return 1;
347 else
348 ALWAYS_ASSERT(FALSE);
350 return 0;
353 int C67_map_D12(char *s)
355 if (strstr(s, ".D1") != NULL)
356 return 0;
357 else if (strcmp(s, ".D2"))
358 return 1;
359 else
360 ALWAYS_ASSERT(FALSE);
362 return 0;
367 void C67_asm(char *s, int a, int b, int c)
369 BOOL xpath;
371 #ifdef ASSEMBLY_LISTING_C67
372 if (!f) {
373 f = fopen("TCC67_out.txt", "wt");
375 fprintf(f, "%04X ", ind);
376 #endif
378 if (strstr(s, "MVKL") == s) {
379 C67_g((C67_map_regn(b) << 23) |
380 ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
381 } else if (strstr(s, "MVKH") == s) {
382 C67_g((C67_map_regn(b) << 23) |
383 (((a >> 16) & 0xffff) << 7) |
384 (0x1a << 2) | (C67_map_regs(b) << 1));
385 } else if (strstr(s, "STW.D SP POST DEC") == s) {
386 C67_g((C67_map_regn(a) << 23) | //src
387 (15 << 18) | //SP B15
388 (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
389 (0xa << 9) | //mode a = post dec ucst
390 (0 << 8) | //r (LDDW bit 0)
391 (1 << 7) | //y D1/D2 use B side
392 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
393 (1 << 2) | //opcode
394 (C67_map_regs(a) << 1) | //side of src
395 (0 << 0)); //parallel
396 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
397 C67_g((C67_map_regn(a) << 23) | //src
398 (15 << 18) | //base reg A15
399 (0 << 13) | //offset reg A0
400 (5 << 9) | //mode 5 = pos offset, base reg + off reg
401 (0 << 8) | //r (LDDW bit 0)
402 (0 << 7) | //y D1/D2 A side
403 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
404 (1 << 2) | //opcode
405 (C67_map_regs(a) << 1) | //side of src
406 (0 << 0)); //parallel
407 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
408 C67_g((C67_map_regn(a) << 23) | //src
409 (15 << 18) | //base reg A15
410 (0 << 13) | //offset reg A0
411 (5 << 9) | //mode 5 = pos offset, base reg + off reg
412 (0 << 8) | //r (LDDW bit 0)
413 (0 << 7) | //y D1/D2 A side
414 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
415 (1 << 2) | //opcode
416 (C67_map_regs(a) << 1) | //side of src
417 (0 << 0)); //parallel
418 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
419 C67_g((C67_map_regn(a) << 23) | //src
420 (15 << 18) | //base reg A15
421 (0 << 13) | //offset reg A0
422 (5 << 9) | //mode 5 = pos offset, base reg + off reg
423 (0 << 8) | //r (LDDW bit 0)
424 (0 << 7) | //y D1/D2 A side
425 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
426 (1 << 2) | //opcode
427 (C67_map_regs(a) << 1) | //side of src
428 (0 << 0)); //parallel
429 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
430 C67_g((C67_map_regn(a) << 23) | //src
431 (15 << 18) | //base reg A15
432 (0 << 13) | //offset reg A0
433 (5 << 9) | //mode 5 = pos offset, base reg + off reg
434 (0 << 8) | //r (LDDW bit 0)
435 (0 << 7) | //y D1/D2 A side
436 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
437 (1 << 2) | //opcode
438 (C67_map_regs(a) << 1) | //side of src
439 (0 << 0)); //parallel
440 } else if (strstr(s, "STW.D *+SP[A0]") == s) {
441 C67_g((C67_map_regn(a) << 23) | //src
442 (15 << 18) | //base reg A15
443 (0 << 13) | //offset reg A0
444 (5 << 9) | //mode 5 = pos offset, base reg + off reg
445 (0 << 8) | //r (LDDW bit 0)
446 (0 << 7) | //y D1/D2 A side
447 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
448 (1 << 2) | //opcode
449 (C67_map_regs(a) << 1) | //side of src
450 (0 << 0)); //parallel
451 } else if (strstr(s, "STW.D *") == s) {
452 C67_g((C67_map_regn(a) << 23) | //src
453 (C67_map_regn(b) << 18) | //base reg A0
454 (0 << 13) | //cst5
455 (1 << 9) | //mode 1 = pos cst offset
456 (0 << 8) | //r (LDDW bit 0)
457 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
458 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
459 (1 << 2) | //opcode
460 (C67_map_regs(a) << 1) | //side of src
461 (0 << 0)); //parallel
462 } else if (strstr(s, "STH.D *") == s) {
463 C67_g((C67_map_regn(a) << 23) | //src
464 (C67_map_regn(b) << 18) | //base reg A0
465 (0 << 13) | //cst5
466 (1 << 9) | //mode 1 = pos cst offset
467 (0 << 8) | //r (LDDW bit 0)
468 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
469 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
470 (1 << 2) | //opcode
471 (C67_map_regs(a) << 1) | //side of src
472 (0 << 0)); //parallel
473 } else if (strstr(s, "STB.D *") == s) {
474 C67_g((C67_map_regn(a) << 23) | //src
475 (C67_map_regn(b) << 18) | //base reg A0
476 (0 << 13) | //cst5
477 (1 << 9) | //mode 1 = pos cst offset
478 (0 << 8) | //r (LDDW bit 0)
479 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
480 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
481 (1 << 2) | //opcode
482 (C67_map_regs(a) << 1) | //side of src
483 (0 << 0)); //parallel
484 } else if (strstr(s, "STW.D +*") == s) {
485 ALWAYS_ASSERT(c < 32);
486 C67_g((C67_map_regn(a) << 23) | //src
487 (C67_map_regn(b) << 18) | //base reg A0
488 (c << 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 (7 << 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, "LDW.D SP PRE INC") == s) {
497 C67_g((C67_map_regn(a) << 23) | //dst
498 (15 << 18) | //base reg B15
499 (2 << 13) | //ucst5 (must keep 8 byte boundary)
500 (9 << 9) | //mode 9 = pre inc ucst5
501 (0 << 8) | //r (LDDW bit 0)
502 (1 << 7) | //y D1/D2 B side
503 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
504 (1 << 2) | //opcode
505 (C67_map_regs(a) << 1) | //side of dst
506 (0 << 0)); //parallel
507 } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
508 C67_g((C67_map_regn(a) << 23) | //dst
509 (15 << 18) | //base reg B15
510 (1 << 13) | //ucst5 (must keep 8 byte boundary)
511 (9 << 9) | //mode 9 = pre inc ucst5
512 (1 << 8) | //r (LDDW bit 1)
513 (1 << 7) | //y D1/D2 B side
514 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
515 (1 << 2) | //opcode
516 (C67_map_regs(a) << 1) | //side of dst
517 (0 << 0)); //parallel
518 } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
519 C67_g((C67_map_regn(a) << 23) | //dst
520 (15 << 18) | //base reg A15
521 (0 << 13) | //offset reg A0
522 (5 << 9) | //mode 5 = pos offset, base reg + off reg
523 (0 << 8) | //r (LDDW bit 0)
524 (0 << 7) | //y D1/D2 A side
525 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
526 (1 << 2) | //opcode
527 (C67_map_regs(a) << 1) | //side of dst
528 (0 << 0)); //parallel
529 } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
530 C67_g((C67_map_regn(a) << 23) | //dst
531 (15 << 18) | //base reg A15
532 (0 << 13) | //offset reg A0
533 (5 << 9) | //mode 5 = pos offset, base reg + off reg
534 (1 << 8) | //r (LDDW bit 1)
535 (0 << 7) | //y D1/D2 A side
536 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
537 (1 << 2) | //opcode
538 (C67_map_regs(a) << 1) | //side of dst
539 (0 << 0)); //parallel
540 } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
541 C67_g((C67_map_regn(a) << 23) | //dst
542 (15 << 18) | //base reg A15
543 (0 << 13) | //offset reg A0
544 (5 << 9) | //mode 5 = pos offset, base reg + off reg
545 (0 << 8) | //r (LDDW bit 0)
546 (0 << 7) | //y D1/D2 A side
547 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
548 (1 << 2) | //opcode
549 (C67_map_regs(a) << 1) | //side of dst
550 (0 << 0)); //parallel
551 } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
552 C67_g((C67_map_regn(a) << 23) | //dst
553 (15 << 18) | //base reg A15
554 (0 << 13) | //offset reg A0
555 (5 << 9) | //mode 5 = pos offset, base reg + off reg
556 (0 << 8) | //r (LDDW bit 0)
557 (0 << 7) | //y D1/D2 A side
558 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
559 (1 << 2) | //opcode
560 (C67_map_regs(a) << 1) | //side of dst
561 (0 << 0)); //parallel
562 } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
563 C67_g((C67_map_regn(a) << 23) | //dst
564 (15 << 18) | //base reg A15
565 (0 << 13) | //offset reg A0
566 (5 << 9) | //mode 5 = pos offset, base reg + off reg
567 (0 << 8) | //r (LDDW bit 0)
568 (0 << 7) | //y D1/D2 A side
569 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
570 (1 << 2) | //opcode
571 (C67_map_regs(a) << 1) | //side of dst
572 (0 << 0)); //parallel
573 } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
574 C67_g((C67_map_regn(a) << 23) | //dst
575 (15 << 18) | //base reg A15
576 (0 << 13) | //offset reg A0
577 (5 << 9) | //mode 5 = pos offset, base reg + off reg
578 (0 << 8) | //r (LDDW bit 0)
579 (0 << 7) | //y D1/D2 A side
580 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
581 (1 << 2) | //opcode
582 (C67_map_regs(a) << 1) | //side of dst
583 (0 << 0)); //parallel
584 } else if (strstr(s, "LDW.D *") == s) {
585 C67_g((C67_map_regn(b) << 23) | //dst
586 (C67_map_regn(a) << 18) | //base reg A15
587 (0 << 13) | //cst5
588 (1 << 9) | //mode 1 = pos cst offset
589 (0 << 8) | //r (LDDW bit 0)
590 (C67_map_regs(a) << 7) | //y D1/D2 src side
591 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
592 (1 << 2) | //opcode
593 (C67_map_regs(b) << 1) | //side of dst
594 (0 << 0)); //parallel
595 } else if (strstr(s, "LDDW.D *") == s) {
596 C67_g((C67_map_regn(b) << 23) | //dst
597 (C67_map_regn(a) << 18) | //base reg A15
598 (0 << 13) | //cst5
599 (1 << 9) | //mode 1 = pos cst offset
600 (1 << 8) | //r (LDDW bit 1)
601 (C67_map_regs(a) << 7) | //y D1/D2 src side
602 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
603 (1 << 2) | //opcode
604 (C67_map_regs(b) << 1) | //side of dst
605 (0 << 0)); //parallel
606 } else if (strstr(s, "LDH.D *") == s) {
607 C67_g((C67_map_regn(b) << 23) | //dst
608 (C67_map_regn(a) << 18) | //base reg A15
609 (0 << 13) | //cst5
610 (1 << 9) | //mode 1 = pos cst offset
611 (0 << 8) | //r (LDDW bit 0)
612 (C67_map_regs(a) << 7) | //y D1/D2 src side
613 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
614 (1 << 2) | //opcode
615 (C67_map_regs(b) << 1) | //side of dst
616 (0 << 0)); //parallel
617 } else if (strstr(s, "LDB.D *") == s) {
618 C67_g((C67_map_regn(b) << 23) | //dst
619 (C67_map_regn(a) << 18) | //base reg A15
620 (0 << 13) | //cst5
621 (1 << 9) | //mode 1 = pos cst offset
622 (0 << 8) | //r (LDDW bit 0)
623 (C67_map_regs(a) << 7) | //y D1/D2 src side
624 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
625 (1 << 2) | //opcode
626 (C67_map_regs(b) << 1) | //side of dst
627 (0 << 0)); //parallel
628 } else if (strstr(s, "LDHU.D *") == s) {
629 C67_g((C67_map_regn(b) << 23) | //dst
630 (C67_map_regn(a) << 18) | //base reg A15
631 (0 << 13) | //cst5
632 (1 << 9) | //mode 1 = pos cst offset
633 (0 << 8) | //r (LDDW bit 0)
634 (C67_map_regs(a) << 7) | //y D1/D2 src side
635 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
636 (1 << 2) | //opcode
637 (C67_map_regs(b) << 1) | //side of dst
638 (0 << 0)); //parallel
639 } else if (strstr(s, "LDBU.D *") == s) {
640 C67_g((C67_map_regn(b) << 23) | //dst
641 (C67_map_regn(a) << 18) | //base reg A15
642 (0 << 13) | //cst5
643 (1 << 9) | //mode 1 = pos cst offset
644 (0 << 8) | //r (LDDW bit 0)
645 (C67_map_regs(a) << 7) | //y D1/D2 src side
646 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
647 (1 << 2) | //opcode
648 (C67_map_regs(b) << 1) | //side of dst
649 (0 << 0)); //parallel
650 } else if (strstr(s, "LDW.D +*") == s) {
651 C67_g((C67_map_regn(b) << 23) | //dst
652 (C67_map_regn(a) << 18) | //base reg A15
653 (1 << 13) | //cst5
654 (1 << 9) | //mode 1 = pos cst offset
655 (0 << 8) | //r (LDDW bit 0)
656 (C67_map_regs(a) << 7) | //y D1/D2 src side
657 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
658 (1 << 2) | //opcode
659 (C67_map_regs(b) << 1) | //side of dst
660 (0 << 0)); //parallel
661 } else if (strstr(s, "CMPLTSP") == s) {
662 xpath = C67_map_regs(a) ^ C67_map_regs(b);
663 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
665 C67_g((C67_map_regn(c) << 23) | //dst
666 (C67_map_regn(b) << 18) | //src2
667 (C67_map_regn(a) << 13) | //src1
668 (xpath << 12) | //x use cross path for src2
669 (0x3a << 6) | //opcode
670 (0x8 << 2) | //opcode fixed
671 (C67_map_regs(c) << 1) | //side for reg c
672 (0 << 0)); //parallel
673 } else if (strstr(s, "CMPGTSP") == 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 (0x39 << 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, "CMPEQSP") == 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 (0x38 << 6) | //opcode
694 (0x8 << 2) | //opcode fixed
695 (C67_map_regs(c) << 1) | //side for reg c
696 (0 << 0)); //parallel
699 else if (strstr(s, "CMPLTDP") == s) {
700 xpath = C67_map_regs(a) ^ C67_map_regs(b);
701 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
703 C67_g((C67_map_regn(c) << 23) | //dst
704 (C67_map_regn(b) << 18) | //src2
705 (C67_map_regn(a) << 13) | //src1
706 (xpath << 12) | //x use cross path for src2
707 (0x2a << 6) | //opcode
708 (0x8 << 2) | //opcode fixed
709 (C67_map_regs(c) << 1) | //side for reg c
710 (0 << 0)); //parallel
711 } else if (strstr(s, "CMPGTDP") == 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 (0x29 << 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, "CMPEQDP") == 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 (0x28 << 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, "CMPLT") == 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 (0x57 << 5) | //opcode
744 (0x6 << 2) | //opcode fixed
745 (C67_map_regs(c) << 1) | //side for reg c
746 (0 << 0)); //parallel
747 } else if (strstr(s, "CMPGT") == 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 (0x47 << 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, "CMPEQ") == 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 (0x53 << 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, "CMPLTU") == 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 (0x5f << 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, "CMPGTU") == 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 (0x4f << 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, "B DISP") == s) {
796 C67_g((0 << 29) | //creg
797 (0 << 28) | //z
798 (a << 7) | //cnst
799 (0x4 << 2) | //opcode fixed
800 (0 << 1) | //S0/S1
801 (0 << 0)); //parallel
802 } else if (strstr(s, "B.") == s) {
803 xpath = C67_map_regs(c) ^ 1;
805 C67_g((C67_map_regc(b) << 29) | //creg
806 (a << 28) | //inv
807 (0 << 23) | //dst
808 (C67_map_regn(c) << 18) | //src2
809 (0 << 13) | //
810 (xpath << 12) | //x cross path if !B side
811 (0xd << 6) | //opcode
812 (0x8 << 2) | //opcode fixed
813 (1 << 1) | //must be S2
814 (0 << 0)); //parallel
815 } else if (strstr(s, "MV.L") == s) {
816 xpath = C67_map_regs(b) ^ C67_map_regs(c);
818 C67_g((0 << 29) | //creg
819 (0 << 28) | //inv
820 (C67_map_regn(c) << 23) | //dst
821 (C67_map_regn(b) << 18) | //src2
822 (0 << 13) | //src1 (cst5)
823 (xpath << 12) | //x cross path if opposite sides
824 (0x2 << 5) | //opcode
825 (0x6 << 2) | //opcode fixed
826 (C67_map_regs(c) << 1) | //side of dest
827 (0 << 0)); //parallel
828 } else if (strstr(s, "SPTRUNC.L") == s) {
829 xpath = C67_map_regs(b) ^ C67_map_regs(c);
831 C67_g((0 << 29) | //creg
832 (0 << 28) | //inv
833 (C67_map_regn(c) << 23) | //dst
834 (C67_map_regn(b) << 18) | //src2
835 (0 << 13) | //src1 NA
836 (xpath << 12) | //x cross path if opposite sides
837 (0xb << 5) | //opcode
838 (0x6 << 2) | //opcode fixed
839 (C67_map_regs(c) << 1) | //side of dest
840 (0 << 0)); //parallel
841 } else if (strstr(s, "DPTRUNC.L") == s) {
842 xpath = C67_map_regs(b) ^ C67_map_regs(c);
844 C67_g((0 << 29) | //creg
845 (0 << 28) | //inv
846 (C67_map_regn(c) << 23) | //dst
847 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
848 (0 << 13) | //src1 NA
849 (xpath << 12) | //x cross path if opposite sides
850 (0x1 << 5) | //opcode
851 (0x6 << 2) | //opcode fixed
852 (C67_map_regs(c) << 1) | //side of dest
853 (0 << 0)); //parallel
854 } else if (strstr(s, "INTSP.L") == s) {
855 xpath = C67_map_regs(b) ^ C67_map_regs(c);
857 C67_g((0 << 29) | //creg
858 (0 << 28) | //inv
859 (C67_map_regn(c) << 23) | //dst
860 (C67_map_regn(b) << 18) | //src2
861 (0 << 13) | //src1 NA
862 (xpath << 12) | //x cross path if opposite sides
863 (0x4a << 5) | //opcode
864 (0x6 << 2) | //opcode fixed
865 (C67_map_regs(c) << 1) | //side of dest
866 (0 << 0)); //parallel
867 } else if (strstr(s, "INTSPU.L") == s) {
868 xpath = C67_map_regs(b) ^ C67_map_regs(c);
870 C67_g((0 << 29) | //creg
871 (0 << 28) | //inv
872 (C67_map_regn(c) << 23) | //dst
873 (C67_map_regn(b) << 18) | //src2
874 (0 << 13) | //src1 NA
875 (xpath << 12) | //x cross path if opposite sides
876 (0x49 << 5) | //opcode
877 (0x6 << 2) | //opcode fixed
878 (C67_map_regs(c) << 1) | //side of dest
879 (0 << 0)); //parallel
880 } else if (strstr(s, "INTDP.L") == s) {
881 xpath = C67_map_regs(b) ^ C67_map_regs(c);
883 C67_g((0 << 29) | //creg
884 (0 << 28) | //inv
885 (C67_map_regn(c) << 23) | //dst
886 (C67_map_regn(b) << 18) | //src2
887 (0 << 13) | //src1 NA
888 (xpath << 12) | //x cross path if opposite sides
889 (0x39 << 5) | //opcode
890 (0x6 << 2) | //opcode fixed
891 (C67_map_regs(c) << 1) | //side of dest
892 (0 << 0)); //parallel
893 } else if (strstr(s, "INTDPU.L") == s) {
894 xpath = C67_map_regs(b) ^ C67_map_regs(c);
896 C67_g((0 << 29) | //creg
897 (0 << 28) | //inv
898 (C67_map_regn(c) << 23) | //dst
899 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
900 (0 << 13) | //src1 NA
901 (xpath << 12) | //x cross path if opposite sides
902 (0x3b << 5) | //opcode
903 (0x6 << 2) | //opcode fixed
904 (C67_map_regs(c) << 1) | //side of dest
905 (0 << 0)); //parallel
906 } else if (strstr(s, "SPDP.L") == s) {
907 xpath = C67_map_regs(b) ^ C67_map_regs(c);
909 C67_g((0 << 29) | //creg
910 (0 << 28) | //inv
911 (C67_map_regn(c) << 23) | //dst
912 (C67_map_regn(b) << 18) | //src2
913 (0 << 13) | //src1 NA
914 (xpath << 12) | //x cross path if opposite sides
915 (0x2 << 6) | //opcode
916 (0x8 << 2) | //opcode fixed
917 (C67_map_regs(c) << 1) | //side of dest
918 (0 << 0)); //parallel
919 } else if (strstr(s, "DPSP.L") == s) {
920 ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
922 C67_g((0 << 29) | //creg
923 (0 << 28) | //inv
924 (C67_map_regn(c) << 23) | //dst
925 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
926 (0 << 13) | //src1 NA
927 (0 << 12) | //x cross path if opposite sides
928 (0x9 << 5) | //opcode
929 (0x6 << 2) | //opcode fixed
930 (C67_map_regs(c) << 1) | //side of dest
931 (0 << 0)); //parallel
932 } else if (strstr(s, "ADD.L") == s) {
933 xpath = C67_map_regs(b) ^ C67_map_regs(c);
935 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
937 C67_g((0 << 29) | //creg
938 (0 << 28) | //inv
939 (C67_map_regn(c) << 23) | //dst
940 (C67_map_regn(b) << 18) | //src2 (possible x path)
941 (C67_map_regn(a) << 13) | //src1
942 (xpath << 12) | //x cross path if opposite sides
943 (0x3 << 5) | //opcode
944 (0x6 << 2) | //opcode fixed
945 (C67_map_regs(c) << 1) | //side of dest
946 (0 << 0)); //parallel
947 } else if (strstr(s, "SUB.L") == s) {
948 xpath = C67_map_regs(b) ^ C67_map_regs(c);
950 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
952 C67_g((0 << 29) | //creg
953 (0 << 28) | //inv
954 (C67_map_regn(c) << 23) | //dst
955 (C67_map_regn(b) << 18) | //src2 (possible x path)
956 (C67_map_regn(a) << 13) | //src1
957 (xpath << 12) | //x cross path if opposite sides
958 (0x7 << 5) | //opcode
959 (0x6 << 2) | //opcode fixed
960 (C67_map_regs(c) << 1) | //side of dest
961 (0 << 0)); //parallel
962 } else if (strstr(s, "OR.L") == s) {
963 xpath = C67_map_regs(b) ^ C67_map_regs(c);
965 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
967 C67_g((0 << 29) | //creg
968 (0 << 28) | //inv
969 (C67_map_regn(c) << 23) | //dst
970 (C67_map_regn(b) << 18) | //src2 (possible x path)
971 (C67_map_regn(a) << 13) | //src1
972 (xpath << 12) | //x cross path if opposite sides
973 (0x7f << 5) | //opcode
974 (0x6 << 2) | //opcode fixed
975 (C67_map_regs(c) << 1) | //side of dest
976 (0 << 0)); //parallel
977 } else if (strstr(s, "AND.L") == s) {
978 xpath = C67_map_regs(b) ^ C67_map_regs(c);
980 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
982 C67_g((0 << 29) | //creg
983 (0 << 28) | //inv
984 (C67_map_regn(c) << 23) | //dst
985 (C67_map_regn(b) << 18) | //src2 (possible x path)
986 (C67_map_regn(a) << 13) | //src1
987 (xpath << 12) | //x cross path if opposite sides
988 (0x7b << 5) | //opcode
989 (0x6 << 2) | //opcode fixed
990 (C67_map_regs(c) << 1) | //side of dest
991 (0 << 0)); //parallel
992 } else if (strstr(s, "XOR.L") == s) {
993 xpath = C67_map_regs(b) ^ C67_map_regs(c);
995 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
997 C67_g((0 << 29) | //creg
998 (0 << 28) | //inv
999 (C67_map_regn(c) << 23) | //dst
1000 (C67_map_regn(b) << 18) | //src2 (possible x path)
1001 (C67_map_regn(a) << 13) | //src1
1002 (xpath << 12) | //x cross path if opposite sides
1003 (0x6f << 5) | //opcode
1004 (0x6 << 2) | //opcode fixed
1005 (C67_map_regs(c) << 1) | //side of dest
1006 (0 << 0)); //parallel
1007 } else if (strstr(s, "ADDSP.L") == s) {
1008 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1010 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1012 C67_g((0 << 29) | //creg
1013 (0 << 28) | //inv
1014 (C67_map_regn(c) << 23) | //dst
1015 (C67_map_regn(b) << 18) | //src2 (possible x path)
1016 (C67_map_regn(a) << 13) | //src1
1017 (xpath << 12) | //x cross path if opposite sides
1018 (0x10 << 5) | //opcode
1019 (0x6 << 2) | //opcode fixed
1020 (C67_map_regs(c) << 1) | //side of dest
1021 (0 << 0)); //parallel
1022 } else if (strstr(s, "ADDDP.L") == s) {
1023 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1025 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1027 C67_g((0 << 29) | //creg
1028 (0 << 28) | //inv
1029 (C67_map_regn(c) << 23) | //dst
1030 (C67_map_regn(b) << 18) | //src2 (possible x path)
1031 (C67_map_regn(a) << 13) | //src1
1032 (xpath << 12) | //x cross path if opposite sides
1033 (0x18 << 5) | //opcode
1034 (0x6 << 2) | //opcode fixed
1035 (C67_map_regs(c) << 1) | //side of dest
1036 (0 << 0)); //parallel
1037 } else if (strstr(s, "SUBSP.L") == s) {
1038 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1040 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1042 C67_g((0 << 29) | //creg
1043 (0 << 28) | //inv
1044 (C67_map_regn(c) << 23) | //dst
1045 (C67_map_regn(b) << 18) | //src2 (possible x path)
1046 (C67_map_regn(a) << 13) | //src1
1047 (xpath << 12) | //x cross path if opposite sides
1048 (0x11 << 5) | //opcode
1049 (0x6 << 2) | //opcode fixed
1050 (C67_map_regs(c) << 1) | //side of dest
1051 (0 << 0)); //parallel
1052 } else if (strstr(s, "SUBDP.L") == s) {
1053 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1055 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1057 C67_g((0 << 29) | //creg
1058 (0 << 28) | //inv
1059 (C67_map_regn(c) << 23) | //dst
1060 (C67_map_regn(b) << 18) | //src2 (possible x path)
1061 (C67_map_regn(a) << 13) | //src1
1062 (xpath << 12) | //x cross path if opposite sides
1063 (0x19 << 5) | //opcode
1064 (0x6 << 2) | //opcode fixed
1065 (C67_map_regs(c) << 1) | //side of dest
1066 (0 << 0)); //parallel
1067 } else if (strstr(s, "MPYSP.M") == s) {
1068 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1070 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1072 C67_g((0 << 29) | //creg
1073 (0 << 28) | //inv
1074 (C67_map_regn(c) << 23) | //dst
1075 (C67_map_regn(b) << 18) | //src2 (possible x path)
1076 (C67_map_regn(a) << 13) | //src1
1077 (xpath << 12) | //x cross path if opposite sides
1078 (0x1c << 7) | //opcode
1079 (0x0 << 2) | //opcode fixed
1080 (C67_map_regs(c) << 1) | //side of dest
1081 (0 << 0)); //parallel
1082 } else if (strstr(s, "MPYDP.M") == s) {
1083 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1085 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1087 C67_g((0 << 29) | //creg
1088 (0 << 28) | //inv
1089 (C67_map_regn(c) << 23) | //dst
1090 (C67_map_regn(b) << 18) | //src2 (possible x path)
1091 (C67_map_regn(a) << 13) | //src1
1092 (xpath << 12) | //x cross path if opposite sides
1093 (0x0e << 7) | //opcode
1094 (0x0 << 2) | //opcode fixed
1095 (C67_map_regs(c) << 1) | //side of dest
1096 (0 << 0)); //parallel
1097 } else if (strstr(s, "MPYI.M") == s) {
1098 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1100 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1102 C67_g((0 << 29) | //creg
1103 (0 << 28) | //inv
1104 (C67_map_regn(c) << 23) | //dst
1105 (C67_map_regn(b) << 18) | //src2
1106 (C67_map_regn(a) << 13) | //src1 (cst5)
1107 (xpath << 12) | //x cross path if opposite sides
1108 (0x4 << 7) | //opcode
1109 (0x0 << 2) | //opcode fixed
1110 (C67_map_regs(c) << 1) | //side of dest
1111 (0 << 0)); //parallel
1112 } else if (strstr(s, "SHR.S") == s) {
1113 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1115 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1117 C67_g((0 << 29) | //creg
1118 (0 << 28) | //inv
1119 (C67_map_regn(c) << 23) | //dst
1120 (C67_map_regn(b) << 18) | //src2
1121 (C67_map_regn(a) << 13) | //src1
1122 (xpath << 12) | //x cross path if opposite sides
1123 (0x37 << 6) | //opcode
1124 (0x8 << 2) | //opcode fixed
1125 (C67_map_regs(c) << 1) | //side of dest
1126 (0 << 0)); //parallel
1127 } else if (strstr(s, "SHRU.S") == s) {
1128 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1130 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1132 C67_g((0 << 29) | //creg
1133 (0 << 28) | //inv
1134 (C67_map_regn(c) << 23) | //dst
1135 (C67_map_regn(b) << 18) | //src2
1136 (C67_map_regn(a) << 13) | //src1
1137 (xpath << 12) | //x cross path if opposite sides
1138 (0x27 << 6) | //opcode
1139 (0x8 << 2) | //opcode fixed
1140 (C67_map_regs(c) << 1) | //side of dest
1141 (0 << 0)); //parallel
1142 } else if (strstr(s, "SHL.S") == s) {
1143 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1145 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1147 C67_g((0 << 29) | //creg
1148 (0 << 28) | //inv
1149 (C67_map_regn(c) << 23) | //dst
1150 (C67_map_regn(b) << 18) | //src2
1151 (C67_map_regn(a) << 13) | //src1
1152 (xpath << 12) | //x cross path if opposite sides
1153 (0x33 << 6) | //opcode
1154 (0x8 << 2) | //opcode fixed
1155 (C67_map_regs(c) << 1) | //side of dest
1156 (0 << 0)); //parallel
1157 } else if (strstr(s, "||ADDK") == s) {
1158 xpath = 0; // no xpath required just use the side of the src/dst
1160 C67_g((0 << 29) | //creg
1161 (0 << 28) | //inv
1162 (C67_map_regn(b) << 23) | //dst
1163 (a << 07) | //scst16
1164 (0x14 << 2) | //opcode fixed
1165 (C67_map_regs(b) << 1) | //side of dst
1166 (1 << 0)); //parallel
1167 } else if (strstr(s, "ADDK") == s) {
1168 xpath = 0; // no xpath required just use the side of the src/dst
1170 C67_g((0 << 29) | //creg
1171 (0 << 28) | //inv
1172 (C67_map_regn(b) << 23) | //dst
1173 (a << 07) | //scst16
1174 (0x14 << 2) | //opcode fixed
1175 (C67_map_regs(b) << 1) | //side of dst
1176 (0 << 0)); //parallel
1177 } else if (strstr(s, "NOP") == s) {
1178 C67_g(((a - 1) << 13) | //no of cycles
1179 (0 << 0)); //parallel
1180 } else
1181 ALWAYS_ASSERT(FALSE);
1183 #ifdef ASSEMBLY_LISTING_C67
1184 fprintf(f, " %s %d %d %d\n", s, a, b, c);
1185 #endif
1189 //r=reg to load, fr=from reg, symbol for relocation, constant
1191 void C67_MVKL(int r, int fc)
1193 C67_asm("MVKL.", fc, r, 0);
1196 void C67_MVKH(int r, int fc)
1198 C67_asm("MVKH.", fc, r, 0);
1201 void C67_STB_SP_A0(int r)
1203 C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB r,*+SP[A0]
1206 void C67_STH_SP_A0(int r)
1208 C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH r,*+SP[A0]
1211 void C67_STW_SP_A0(int r)
1213 C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW r,*+SP[A0]
1216 void C67_STB_PTR(int r, int r2)
1218 C67_asm("STB.D *", r, r2, 0); // STB r, *r2
1221 void C67_STH_PTR(int r, int r2)
1223 C67_asm("STH.D *", r, r2, 0); // STH r, *r2
1226 void C67_STW_PTR(int r, int r2)
1228 C67_asm("STW.D *", r, r2, 0); // STW r, *r2
1231 void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1233 C67_asm("STW.D +*", r, r2, n); // STW r, *+r2
1236 void C67_PUSH(int r)
1238 C67_asm("STW.D SP POST DEC", r, 0, 0); // STW r,*SP--
1241 void C67_LDW_SP_A0(int r)
1243 C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW *+SP[A0],r
1246 void C67_LDDW_SP_A0(int r)
1248 C67_asm("LDDW.D *+SP[A0]", r, 0, 0); // LDDW *+SP[A0],r
1251 void C67_LDH_SP_A0(int r)
1253 C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH *+SP[A0],r
1256 void C67_LDB_SP_A0(int r)
1258 C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB *+SP[A0],r
1261 void C67_LDHU_SP_A0(int r)
1263 C67_asm("LDHU.D *+SP[A0]", r, 0, 0); // LDHU *+SP[A0],r
1266 void C67_LDBU_SP_A0(int r)
1268 C67_asm("LDBU.D *+SP[A0]", r, 0, 0); // LDBU *+SP[A0],r
1271 void C67_LDW_PTR(int r, int r2)
1273 C67_asm("LDW.D *", r, r2, 0); // LDW *r,r2
1276 void C67_LDDW_PTR(int r, int r2)
1278 C67_asm("LDDW.D *", r, r2, 0); // LDDW *r,r2
1281 void C67_LDH_PTR(int r, int r2)
1283 C67_asm("LDH.D *", r, r2, 0); // LDH *r,r2
1286 void C67_LDB_PTR(int r, int r2)
1288 C67_asm("LDB.D *", r, r2, 0); // LDB *r,r2
1291 void C67_LDHU_PTR(int r, int r2)
1293 C67_asm("LDHU.D *", r, r2, 0); // LDHU *r,r2
1296 void C67_LDBU_PTR(int r, int r2)
1298 C67_asm("LDBU.D *", r, r2, 0); // LDBU *r,r2
1301 void C67_LDW_PTR_PRE_INC(int r, int r2)
1303 C67_asm("LDW.D +*", r, r2, 0); // LDW *+r,r2
1306 void C67_POP(int r)
1308 C67_asm("LDW.D SP PRE INC", r, 0, 0); // LDW *++SP,r
1311 void C67_POP_DW(int r)
1313 C67_asm("LDDW.D SP PRE INC", r, 0, 0); // LDDW *++SP,r
1316 void C67_CMPLT(int s1, int s2, int dst)
1318 C67_asm("CMPLT.L1", s1, s2, dst);
1321 void C67_CMPGT(int s1, int s2, int dst)
1323 C67_asm("CMPGT.L1", s1, s2, dst);
1326 void C67_CMPEQ(int s1, int s2, int dst)
1328 C67_asm("CMPEQ.L1", s1, s2, dst);
1331 void C67_CMPLTU(int s1, int s2, int dst)
1333 C67_asm("CMPLTU.L1", s1, s2, dst);
1336 void C67_CMPGTU(int s1, int s2, int dst)
1338 C67_asm("CMPGTU.L1", s1, s2, dst);
1342 void C67_CMPLTSP(int s1, int s2, int dst)
1344 C67_asm("CMPLTSP.S1", s1, s2, dst);
1347 void C67_CMPGTSP(int s1, int s2, int dst)
1349 C67_asm("CMPGTSP.S1", s1, s2, dst);
1352 void C67_CMPEQSP(int s1, int s2, int dst)
1354 C67_asm("CMPEQSP.S1", s1, s2, dst);
1357 void C67_CMPLTDP(int s1, int s2, int dst)
1359 C67_asm("CMPLTDP.S1", s1, s2, dst);
1362 void C67_CMPGTDP(int s1, int s2, int dst)
1364 C67_asm("CMPGTDP.S1", s1, s2, dst);
1367 void C67_CMPEQDP(int s1, int s2, int dst)
1369 C67_asm("CMPEQDP.S1", s1, s2, dst);
1373 void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2
1375 C67_asm("B.S2", inv, r1, r2);
1379 // call with how many 32 bit words to skip
1380 // (0 would branch to the branch instruction)
1382 void C67_B_DISP(int disp) // B +2 Branch with constant displacement
1384 // Branch point is relative to the 8 word fetch packet
1386 // we will assume the text section always starts on an 8 word (32 byte boundary)
1388 // so add in how many words into the fetch packet the branch is
1391 C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1394 void C67_NOP(int n)
1396 C67_asm("NOP", n, 0, 0);
1399 void C67_ADDK(int n, int r)
1401 ALWAYS_ASSERT(abs(n) < 32767);
1403 C67_asm("ADDK", n, r, 0);
1406 void C67_ADDK_PARALLEL(int n, int r)
1408 ALWAYS_ASSERT(abs(n) < 32767);
1410 C67_asm("||ADDK", n, r, 0);
1413 void C67_Adjust_ADDK(int *inst, int n)
1415 ALWAYS_ASSERT(abs(n) < 32767);
1417 *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1420 void C67_MV(int r, int v)
1422 C67_asm("MV.L", 0, r, v);
1426 void C67_DPTRUNC(int r, int v)
1428 C67_asm("DPTRUNC.L", 0, r, v);
1431 void C67_SPTRUNC(int r, int v)
1433 C67_asm("SPTRUNC.L", 0, r, v);
1436 void C67_INTSP(int r, int v)
1438 C67_asm("INTSP.L", 0, r, v);
1441 void C67_INTDP(int r, int v)
1443 C67_asm("INTDP.L", 0, r, v);
1446 void C67_INTSPU(int r, int v)
1448 C67_asm("INTSPU.L", 0, r, v);
1451 void C67_INTDPU(int r, int v)
1453 C67_asm("INTDPU.L", 0, r, v);
1456 void C67_SPDP(int r, int v)
1458 C67_asm("SPDP.L", 0, r, v);
1461 void C67_DPSP(int r, int v) // note regs must be on the same side
1463 C67_asm("DPSP.L", 0, r, v);
1466 void C67_ADD(int r, int v)
1468 C67_asm("ADD.L", v, r, v);
1471 void C67_SUB(int r, int v)
1473 C67_asm("SUB.L", v, r, v);
1476 void C67_AND(int r, int v)
1478 C67_asm("AND.L", v, r, v);
1481 void C67_OR(int r, int v)
1483 C67_asm("OR.L", v, r, v);
1486 void C67_XOR(int r, int v)
1488 C67_asm("XOR.L", v, r, v);
1491 void C67_ADDSP(int r, int v)
1493 C67_asm("ADDSP.L", v, r, v);
1496 void C67_SUBSP(int r, int v)
1498 C67_asm("SUBSP.L", v, r, v);
1501 void C67_MPYSP(int r, int v)
1503 C67_asm("MPYSP.M", v, r, v);
1506 void C67_ADDDP(int r, int v)
1508 C67_asm("ADDDP.L", v, r, v);
1511 void C67_SUBDP(int r, int v)
1513 C67_asm("SUBDP.L", v, r, v);
1516 void C67_MPYDP(int r, int v)
1518 C67_asm("MPYDP.M", v, r, v);
1521 void C67_MPYI(int r, int v)
1523 C67_asm("MPYI.M", v, r, v);
1526 void C67_SHL(int r, int v)
1528 C67_asm("SHL.S", r, v, v);
1531 void C67_SHRU(int r, int v)
1533 C67_asm("SHRU.S", r, v, v);
1536 void C67_SHR(int r, int v)
1538 C67_asm("SHR.S", r, v, v);
1543 /* load 'r' from value 'sv' */
1544 void load(int r, SValue * sv)
1546 int v, t, ft, fc, fr, size = 0, element;
1547 BOOL Unsigned = FALSE;
1548 SValue v1;
1550 fr = sv->r;
1551 ft = sv->type.t;
1552 fc = sv->c.i;
1554 v = fr & VT_VALMASK;
1555 if (fr & VT_LVAL) {
1556 if (v == VT_LLOCAL) {
1557 v1.type.t = VT_INT;
1558 v1.r = VT_LOCAL | VT_LVAL;
1559 v1.c.i = fc;
1560 load(r, &v1);
1561 fr = r;
1562 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
1563 tcc_error("long double not supported");
1564 } else if ((ft & VT_TYPE) == VT_BYTE) {
1565 size = 1;
1566 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1567 size = 1;
1568 Unsigned = TRUE;
1569 } else if ((ft & VT_TYPE) == VT_SHORT) {
1570 size = 2;
1571 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1572 size = 2;
1573 Unsigned = TRUE;
1574 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1575 size = 8;
1576 } else {
1577 size = 4;
1580 // check if fc is a positive reference on the stack,
1581 // if it is tcc is referencing what it thinks is a parameter
1582 // on the stack, so check if it is really in a register.
1585 if (v == VT_LOCAL && fc > 0) {
1586 int stack_pos = 8;
1588 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1589 if (fc == stack_pos)
1590 break;
1592 stack_pos += TranslateStackToReg[t];
1595 // param has been pushed on stack, get it like a local var
1597 fc = ParamLocOnStack[t] - 8;
1600 if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect
1602 if (size == 1) {
1603 if (Unsigned)
1604 C67_LDBU_PTR(v, r); // LDBU *v,r
1605 else
1606 C67_LDB_PTR(v, r); // LDB *v,r
1607 } else if (size == 2) {
1608 if (Unsigned)
1609 C67_LDHU_PTR(v, r); // LDHU *v,r
1610 else
1611 C67_LDH_PTR(v, r); // LDH *v,r
1612 } else if (size == 4) {
1613 C67_LDW_PTR(v, r); // LDW *v,r
1614 } else if (size == 8) {
1615 C67_LDDW_PTR(v, r); // LDDW *v,r
1618 C67_NOP(4); // NOP 4
1619 return;
1620 } else if (fr & VT_SYM) {
1621 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1622 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1625 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1626 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1629 if (size == 1) {
1630 if (Unsigned)
1631 C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r
1632 else
1633 C67_LDB_PTR(C67_A0, r); // LDB *A0,r
1634 } else if (size == 2) {
1635 if (Unsigned)
1636 C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r
1637 else
1638 C67_LDH_PTR(C67_A0, r); // LDH *A0,r
1639 } else if (size == 4) {
1640 C67_LDW_PTR(C67_A0, r); // LDW *A0,r
1641 } else if (size == 8) {
1642 C67_LDDW_PTR(C67_A0, r); // LDDW *A0,r
1645 C67_NOP(4); // NOP 4
1646 return;
1647 } else {
1648 element = size;
1650 // divide offset in bytes to create element index
1651 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1652 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1654 if (size == 1) {
1655 if (Unsigned)
1656 C67_LDBU_SP_A0(r); // LDBU r, SP[A0]
1657 else
1658 C67_LDB_SP_A0(r); // LDB r, SP[A0]
1659 } else if (size == 2) {
1660 if (Unsigned)
1661 C67_LDHU_SP_A0(r); // LDHU r, SP[A0]
1662 else
1663 C67_LDH_SP_A0(r); // LDH r, SP[A0]
1664 } else if (size == 4) {
1665 C67_LDW_SP_A0(r); // LDW r, SP[A0]
1666 } else if (size == 8) {
1667 C67_LDDW_SP_A0(r); // LDDW r, SP[A0]
1671 C67_NOP(4); // NOP 4
1672 return;
1674 } else {
1675 if (v == VT_CONST) {
1676 if (fr & VT_SYM) {
1677 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1678 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1680 C67_MVKL(r, fc); //r=reg to load, constant
1681 C67_MVKH(r, fc); //r=reg to load, constant
1682 } else if (v == VT_LOCAL) {
1683 C67_MVKL(r, fc + 8); //r=reg to load, constant C67 stack points to next free
1684 C67_MVKH(r, fc + 8); //r=reg to load, constant
1685 C67_ADD(C67_FP, r); // MV v,r v -> r
1686 } else if (v == VT_CMP) {
1687 C67_MV(C67_compare_reg, r); // MV v,r v -> r
1688 } else if (v == VT_JMP || v == VT_JMPI) {
1689 t = v & 1;
1690 C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
1691 C67_MVKL(r, t); // r=reg to load, 0 or 1 (do this while branching)
1692 C67_NOP(4); // NOP 4
1693 gsym(fc); // modifies other branches to branch here
1694 C67_MVKL(r, t ^ 1); // r=reg to load, 0 or 1
1695 } else if (v != r) {
1696 C67_MV(v, r); // MV v,r v -> r
1698 if ((ft & VT_BTYPE) == VT_DOUBLE)
1699 C67_MV(v + 1, r + 1); // MV v,r v -> r
1705 /* store register 'r' in lvalue 'v' */
1706 void store(int r, SValue * v)
1708 int fr, bt, ft, fc, size, t, element;
1710 ft = v->type.t;
1711 fc = v->c.i;
1712 fr = v->r & VT_VALMASK;
1713 bt = ft & VT_BTYPE;
1714 /* XXX: incorrect if float reg to reg */
1716 if (bt == VT_LDOUBLE) {
1717 tcc_error("long double not supported");
1718 } else {
1719 if (bt == VT_SHORT)
1720 size = 2;
1721 else if (bt == VT_BYTE)
1722 size = 1;
1723 else if (bt == VT_DOUBLE)
1724 size = 8;
1725 else
1726 size = 4;
1728 if ((v->r & VT_VALMASK) == VT_CONST) {
1729 /* constant memory reference */
1731 if (v->r & VT_SYM) {
1732 greloc(cur_text_section, v->sym, ind, R_C60LO16); // rem the inst need to be patched
1733 greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
1735 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1736 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1738 if (size == 1)
1739 C67_STB_PTR(r, C67_A0); // STB r, *A0
1740 else if (size == 2)
1741 C67_STH_PTR(r, C67_A0); // STH r, *A0
1742 else if (size == 4 || size == 8)
1743 C67_STW_PTR(r, C67_A0); // STW r, *A0
1745 if (size == 8)
1746 C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1); // STW r, *+A0[1]
1747 } else if ((v->r & VT_VALMASK) == VT_LOCAL) {
1748 // check case of storing to passed argument that
1749 // tcc thinks is on the stack but for C67 is
1750 // passed as a reg. However it may have been
1751 // saved to the stack, if that reg was required
1752 // for a call to a child function
1754 if (fc > 0) // argument ??
1756 // walk through sizes and figure which param
1758 int stack_pos = 8;
1760 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1761 if (fc == stack_pos)
1762 break;
1764 stack_pos += TranslateStackToReg[t];
1767 // param has been pushed on stack, get it like a local var
1768 fc = ParamLocOnStack[t] - 8;
1771 if (size == 8)
1772 element = 4;
1773 else
1774 element = size;
1776 // divide offset in bytes to create word index
1777 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1778 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1782 if (size == 1)
1783 C67_STB_SP_A0(r); // STB r, SP[A0]
1784 else if (size == 2)
1785 C67_STH_SP_A0(r); // STH r, SP[A0]
1786 else if (size == 4 || size == 8)
1787 C67_STW_SP_A0(r); // STW r, SP[A0]
1789 if (size == 8) {
1790 C67_ADDK(1, C67_A0); // ADDK 1,A0
1791 C67_STW_SP_A0(r + 1); // STW r, SP[A0]
1793 } else {
1794 if (size == 1)
1795 C67_STB_PTR(r, fr); // STB r, *fr
1796 else if (size == 2)
1797 C67_STH_PTR(r, fr); // STH r, *fr
1798 else if (size == 4 || size == 8)
1799 C67_STW_PTR(r, fr); // STW r, *fr
1801 if (size == 8) {
1802 C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1]
1808 /* 'is_jmp' is '1' if it is a jump */
1809 static void gcall_or_jmp(int is_jmp)
1811 int r;
1812 Sym *sym;
1814 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1815 /* constant case */
1816 if (vtop->r & VT_SYM) {
1817 /* relocation case */
1819 // get add into A0, then start the jump B3
1821 greloc(cur_text_section, vtop->sym, ind, R_C60LO16); // rem the inst need to be patched
1822 greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
1824 C67_MVKL(C67_A0, 0); //r=reg to load, constant
1825 C67_MVKH(C67_A0, 0); //r=reg to load, constant
1826 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // B.S2x A0
1828 if (is_jmp) {
1829 C67_NOP(5); // simple jump, just put NOP
1830 } else {
1831 // Call, must load return address into B3 during delay slots
1833 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1834 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1835 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1836 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1837 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1838 C67_NOP(3); // put remaining NOPs
1840 } else {
1841 /* put an empty PC32 relocation */
1842 ALWAYS_ASSERT(FALSE);
1844 } else {
1845 /* otherwise, indirect call */
1846 r = gv(RC_INT);
1847 C67_IREG_B_REG(0, C67_CREG_ZERO, r); // B.S2x r
1849 if (is_jmp) {
1850 C67_NOP(5); // simple jump, just put NOP
1851 } else {
1852 // Call, must load return address into B3 during delay slots
1854 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1855 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1856 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1857 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1858 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1859 C67_NOP(3); // put remaining NOPs
1864 /* Return the number of registers needed to return the struct, or 0 if
1865 returning via struct pointer. */
1866 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
1867 *ret_align = 1; // Never have to re-align return values for x86-64
1868 return 0;
1871 /* generate function call with address in (vtop->t, vtop->c) and free function
1872 context. Stack entry is popped */
1873 void gfunc_call(int nb_args)
1875 int i, r, size = 0;
1876 int args_sizes[NoCallArgsPassedOnStack];
1878 if (nb_args > NoCallArgsPassedOnStack) {
1879 tcc_error("more than 10 function params not currently supported");
1880 // handle more than 10, put some on the stack
1883 for (i = 0; i < nb_args; i++) {
1884 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1885 ALWAYS_ASSERT(FALSE);
1886 } else {
1887 /* simple type (currently always same size) */
1888 /* XXX: implicit cast ? */
1891 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1892 tcc_error("long long not supported");
1893 } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
1894 tcc_error("long double not supported");
1895 } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1896 size = 8;
1897 } else {
1898 size = 4;
1901 // put the parameter into the corresponding reg (pair)
1903 r = gv(RC_C67_A4 << (2 * i));
1905 // must put on stack because with 1 pass compiler , no way to tell
1906 // if an up coming nested call might overwrite these regs
1908 C67_PUSH(r);
1910 if (size == 8) {
1911 C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3); // STW r, *+SP[3] (go back and put the other)
1913 args_sizes[i] = size;
1915 vtop--;
1917 // POP all the params on the stack into registers for the
1918 // immediate call (in reverse order)
1920 for (i = nb_args - 1; i >= 0; i--) {
1922 if (args_sizes[i] == 8)
1923 C67_POP_DW(TREG_C67_A4 + i * 2);
1924 else
1925 C67_POP(TREG_C67_A4 + i * 2);
1927 gcall_or_jmp(0);
1928 vtop--;
1932 // to be compatible with Code Composer for the C67
1933 // the first 10 parameters must be passed in registers
1934 // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1935 // ending with B12:B13.
1937 // When a call is made, if the caller has its parameters
1938 // in regs A4-B13 these must be saved before/as the call
1939 // parameters are loaded and restored upon return (or if/when needed).
1941 /* generate function prolog of type 't' */
1942 void gfunc_prolog(CType * func_type)
1944 int addr, align, size, func_call, i;
1945 Sym *sym;
1946 CType *type;
1948 sym = func_type->ref;
1949 func_call = sym->f.func_call;
1950 addr = 8;
1951 /* if the function returns a structure, then add an
1952 implicit pointer parameter */
1953 func_vt = sym->type;
1954 func_var = (sym->f.func_type == FUNC_ELLIPSIS);
1955 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1956 func_vc = addr;
1957 addr += 4;
1960 NoOfCurFuncArgs = 0;
1962 /* define parameters */
1963 while ((sym = sym->next) != NULL) {
1964 type = &sym->type;
1965 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
1966 size = type_size(type, &align);
1967 size = (size + 3) & ~3;
1969 // keep track of size of arguments so
1970 // we can translate where tcc thinks they
1971 // are on the stack into the appropriate reg
1973 TranslateStackToReg[NoOfCurFuncArgs] = size;
1974 NoOfCurFuncArgs++;
1976 #ifdef FUNC_STRUCT_PARAM_AS_PTR
1977 /* structs are passed as pointer */
1978 if ((type->t & VT_BTYPE) == VT_STRUCT) {
1979 size = 4;
1981 #endif
1982 addr += size;
1984 func_ret_sub = 0;
1985 /* pascal type call ? */
1986 if (func_call == FUNC_STDCALL)
1987 func_ret_sub = addr - 8;
1989 C67_MV(C67_FP, C67_A0); // move FP -> A0
1990 C67_MV(C67_SP, C67_FP); // move SP -> FP
1992 // place all the args passed in regs onto the stack
1994 loc = 0;
1995 for (i = 0; i < NoOfCurFuncArgs; i++) {
1997 ParamLocOnStack[i] = loc; // remember where the param is
1998 loc += -8;
2000 C67_PUSH(TREG_C67_A4 + i * 2);
2002 if (TranslateStackToReg[i] == 8) {
2003 C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3); // STW r, *+SP[1] (go back and put the other)
2007 TotalBytesPushedOnStack = -loc;
2009 func_sub_sp_offset = ind; // remember where we put the stack instruction
2010 C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily)
2012 C67_PUSH(C67_A0);
2013 C67_PUSH(C67_B3);
2016 /* generate function epilog */
2017 void gfunc_epilog(void)
2020 int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2021 C67_POP(C67_B3);
2022 C67_NOP(4); // NOP wait for load
2023 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3
2024 C67_POP(C67_FP);
2025 C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP
2026 C67_Adjust_ADDK((int *) (cur_text_section->data +
2027 func_sub_sp_offset),
2028 -local + TotalBytesPushedOnStack);
2029 C67_NOP(3); // NOP
2033 ST_FUNC void gen_fill_nops(int bytes)
2035 if ((bytes & 3))
2036 tcc_error("alignment of code section not multiple of 4");
2037 while (bytes > 0) {
2038 C67_NOP(4);
2039 bytes -= 4;
2043 /* generate a jump to a label */
2044 int gjmp(int t)
2046 int ind1 = ind;
2047 if (nocode_wanted)
2048 return t;
2050 C67_MVKL(C67_A0, t); //r=reg to load, constant
2051 C67_MVKH(C67_A0, t); //r=reg to load, constant
2052 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // [!R] B.S2x A0
2053 C67_NOP(5);
2054 return ind1;
2057 /* generate a jump to a fixed address */
2058 void gjmp_addr(int a)
2060 Sym *sym;
2061 // I guess this routine is used for relative short
2062 // local jumps, for now just handle it as the general
2063 // case
2065 // define a label that will be relocated
2067 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
2068 greloc(cur_text_section, sym, ind, R_C60LO16);
2069 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
2071 gjmp(0); // place a zero there later the symbol will be added to it
2074 /* generate a test. set 'inv' to invert test. Stack entry is popped */
2075 ST_FUNC int gjmp_cond(int op, int t)
2077 int ind1;
2078 int inv = op & 1;
2079 if (nocode_wanted)
2080 return t;
2082 /* fast case : can jump directly since flags are set */
2083 // C67 uses B2 sort of as flags register
2084 ind1 = ind;
2085 C67_MVKL(C67_A0, t); //r=reg to load, constant
2086 C67_MVKH(C67_A0, t); //r=reg to load, constant
2088 if (C67_compare_reg != TREG_EAX && // check if not already in a conditional test reg
2089 C67_compare_reg != TREG_EDX &&
2090 C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
2091 C67_MV(C67_compare_reg, C67_B2);
2092 C67_compare_reg = C67_B2;
2095 C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x A0
2096 C67_NOP(5);
2097 t = ind1; //return where we need to patch
2099 return t;
2102 ST_FUNC int gjmp_append(int n0, int t)
2104 if (n0) {
2105 int n = n0, *p;
2106 /* insert vtop->c jump list in t */
2108 // I guess the idea is to traverse to the
2109 // null at the end of the list and store t
2110 // there
2111 while (n != 0) {
2112 p = (int *) (cur_text_section->data + n);
2114 // extract 32 bit address from MVKH/MVKL
2115 n = ((*p >> 7) & 0xffff);
2116 n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2118 *p |= (t & 0xffff) << 7;
2119 *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2120 t = n0;
2122 return t;
2125 /* generate an integer binary operation */
2126 void gen_opi(int op)
2128 int r, fr, opc, t;
2130 switch (op) {
2131 case '+':
2132 case TOK_ADDC1: /* add with carry generation */
2133 opc = 0;
2134 gen_op8:
2137 // C67 can't do const compares, must load into a reg
2138 // so just go to gv2 directly - tktk
2142 if (op >= TOK_ULT && op <= TOK_GT)
2143 gv2(RC_INT_BSIDE, RC_INT); // make sure r (src1) is on the B Side of CPU
2144 else
2145 gv2(RC_INT, RC_INT);
2147 r = vtop[-1].r;
2148 fr = vtop[0].r;
2150 C67_compare_reg = C67_B2;
2153 if (op == TOK_LT) {
2154 C67_CMPLT(r, fr, C67_B2);
2155 C67_invert_test = FALSE;
2156 } else if (op == TOK_GE) {
2157 C67_CMPLT(r, fr, C67_B2);
2158 C67_invert_test = TRUE;
2159 } else if (op == TOK_GT) {
2160 C67_CMPGT(r, fr, C67_B2);
2161 C67_invert_test = FALSE;
2162 } else if (op == TOK_LE) {
2163 C67_CMPGT(r, fr, C67_B2);
2164 C67_invert_test = TRUE;
2165 } else if (op == TOK_EQ) {
2166 C67_CMPEQ(r, fr, C67_B2);
2167 C67_invert_test = FALSE;
2168 } else if (op == TOK_NE) {
2169 C67_CMPEQ(r, fr, C67_B2);
2170 C67_invert_test = TRUE;
2171 } else if (op == TOK_ULT) {
2172 C67_CMPLTU(r, fr, C67_B2);
2173 C67_invert_test = FALSE;
2174 } else if (op == TOK_UGE) {
2175 C67_CMPLTU(r, fr, C67_B2);
2176 C67_invert_test = TRUE;
2177 } else if (op == TOK_UGT) {
2178 C67_CMPGTU(r, fr, C67_B2);
2179 C67_invert_test = FALSE;
2180 } else if (op == TOK_ULE) {
2181 C67_CMPGTU(r, fr, C67_B2);
2182 C67_invert_test = TRUE;
2183 } else if (op == '+')
2184 C67_ADD(fr, r); // ADD r,fr,r
2185 else if (op == '-')
2186 C67_SUB(fr, r); // SUB r,fr,r
2187 else if (op == '&')
2188 C67_AND(fr, r); // AND r,fr,r
2189 else if (op == '|')
2190 C67_OR(fr, r); // OR r,fr,r
2191 else if (op == '^')
2192 C67_XOR(fr, r); // XOR r,fr,r
2193 else
2194 ALWAYS_ASSERT(FALSE);
2196 vtop--;
2197 if (op >= TOK_ULT && op <= TOK_GT)
2198 vset_VT_CMP(0x80);
2199 break;
2200 case '-':
2201 case TOK_SUBC1: /* sub with carry generation */
2202 opc = 5;
2203 goto gen_op8;
2204 case TOK_ADDC2: /* add with carry use */
2205 opc = 2;
2206 goto gen_op8;
2207 case TOK_SUBC2: /* sub with carry use */
2208 opc = 3;
2209 goto gen_op8;
2210 case '&':
2211 opc = 4;
2212 goto gen_op8;
2213 case '^':
2214 opc = 6;
2215 goto gen_op8;
2216 case '|':
2217 opc = 1;
2218 goto gen_op8;
2219 case '*':
2220 case TOK_UMULL:
2221 gv2(RC_INT, RC_INT);
2222 r = vtop[-1].r;
2223 fr = vtop[0].r;
2224 vtop--;
2225 C67_MPYI(fr, r); // 32 bit multiply fr,r,fr
2226 C67_NOP(8); // NOP 8 for worst case
2227 break;
2228 case TOK_SHL:
2229 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2230 r = vtop[-1].r;
2231 fr = vtop[0].r;
2232 vtop--;
2233 C67_SHL(fr, r); // arithmetic/logical shift
2234 break;
2236 case TOK_SHR:
2237 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2238 r = vtop[-1].r;
2239 fr = vtop[0].r;
2240 vtop--;
2241 C67_SHRU(fr, r); // logical shift
2242 break;
2244 case TOK_SAR:
2245 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2246 r = vtop[-1].r;
2247 fr = vtop[0].r;
2248 vtop--;
2249 C67_SHR(fr, r); // arithmetic shift
2250 break;
2252 case '/':
2253 t = TOK__divi;
2254 call_func:
2255 vswap();
2256 /* call generic idiv function */
2257 vpush_global_sym(&func_old_type, t);
2258 vrott(3);
2259 gfunc_call(2);
2260 vpushi(0);
2261 vtop->r = REG_IRET;
2262 vtop->r2 = VT_CONST;
2263 break;
2264 case TOK_UDIV:
2265 case TOK_PDIV:
2266 t = TOK__divu;
2267 goto call_func;
2268 case '%':
2269 t = TOK__remi;
2270 goto call_func;
2271 case TOK_UMOD:
2272 t = TOK__remu;
2273 goto call_func;
2275 default:
2276 opc = 7;
2277 goto gen_op8;
2281 /* generate a floating point operation 'v = t1 op t2' instruction. The
2282 two operands are guaranteed to have the same floating point type */
2283 /* XXX: need to use ST1 too */
2284 void gen_opf(int op)
2286 int ft, fc, fr, r;
2288 if (op >= TOK_ULT && op <= TOK_GT)
2289 gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
2290 else
2291 gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
2293 ft = vtop->type.t;
2294 fc = vtop->c.i;
2295 r = vtop->r;
2296 fr = vtop[-1].r;
2299 if ((ft & VT_BTYPE) == VT_LDOUBLE)
2300 tcc_error("long doubles not supported");
2302 if (op >= TOK_ULT && op <= TOK_GT) {
2304 r = vtop[-1].r;
2305 fr = vtop[0].r;
2307 C67_compare_reg = C67_B2;
2309 if (op == TOK_LT) {
2310 if ((ft & VT_BTYPE) == VT_DOUBLE)
2311 C67_CMPLTDP(r, fr, C67_B2);
2312 else
2313 C67_CMPLTSP(r, fr, C67_B2);
2315 C67_invert_test = FALSE;
2316 } else if (op == TOK_GE) {
2317 if ((ft & VT_BTYPE) == VT_DOUBLE)
2318 C67_CMPLTDP(r, fr, C67_B2);
2319 else
2320 C67_CMPLTSP(r, fr, C67_B2);
2322 C67_invert_test = TRUE;
2323 } else if (op == TOK_GT) {
2324 if ((ft & VT_BTYPE) == VT_DOUBLE)
2325 C67_CMPGTDP(r, fr, C67_B2);
2326 else
2327 C67_CMPGTSP(r, fr, C67_B2);
2329 C67_invert_test = FALSE;
2330 } else if (op == TOK_LE) {
2331 if ((ft & VT_BTYPE) == VT_DOUBLE)
2332 C67_CMPGTDP(r, fr, C67_B2);
2333 else
2334 C67_CMPGTSP(r, fr, C67_B2);
2336 C67_invert_test = TRUE;
2337 } else if (op == TOK_EQ) {
2338 if ((ft & VT_BTYPE) == VT_DOUBLE)
2339 C67_CMPEQDP(r, fr, C67_B2);
2340 else
2341 C67_CMPEQSP(r, fr, C67_B2);
2343 C67_invert_test = FALSE;
2344 } else if (op == TOK_NE) {
2345 if ((ft & VT_BTYPE) == VT_DOUBLE)
2346 C67_CMPEQDP(r, fr, C67_B2);
2347 else
2348 C67_CMPEQSP(r, fr, C67_B2);
2350 C67_invert_test = TRUE;
2351 } else {
2352 ALWAYS_ASSERT(FALSE);
2354 vset_VT_CMP(0x80);
2355 } else {
2356 if (op == '+') {
2357 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2358 C67_ADDDP(r, fr); // ADD fr,r,fr
2359 C67_NOP(6);
2360 } else {
2361 C67_ADDSP(r, fr); // ADD fr,r,fr
2362 C67_NOP(3);
2364 vtop--;
2365 } else if (op == '-') {
2366 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2367 C67_SUBDP(r, fr); // SUB fr,r,fr
2368 C67_NOP(6);
2369 } else {
2370 C67_SUBSP(r, fr); // SUB fr,r,fr
2371 C67_NOP(3);
2373 vtop--;
2374 } else if (op == '*') {
2375 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2376 C67_MPYDP(r, fr); // MPY fr,r,fr
2377 C67_NOP(9);
2378 } else {
2379 C67_MPYSP(r, fr); // MPY fr,r,fr
2380 C67_NOP(3);
2382 vtop--;
2383 } else if (op == '/') {
2384 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2385 // must call intrinsic DP floating point divide
2386 vswap();
2387 /* call generic idiv function */
2388 vpush_global_sym(&func_old_type, TOK__divd);
2389 vrott(3);
2390 gfunc_call(2);
2391 vpushi(0);
2392 vtop->r = REG_FRET;
2393 vtop->r2 = REG_LRET;
2395 } else {
2396 // must call intrinsic SP floating point divide
2397 vswap();
2398 /* call generic idiv function */
2399 vpush_global_sym(&func_old_type, TOK__divf);
2400 vrott(3);
2401 gfunc_call(2);
2402 vpushi(0);
2403 vtop->r = REG_FRET;
2404 vtop->r2 = VT_CONST;
2406 } else
2407 ALWAYS_ASSERT(FALSE);
2414 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2415 and 'long long' cases. */
2416 void gen_cvt_itof(int t)
2418 int r;
2420 gv(RC_INT);
2421 r = vtop->r;
2423 if ((t & VT_BTYPE) == VT_DOUBLE) {
2424 if (t & VT_UNSIGNED)
2425 C67_INTDPU(r, r);
2426 else
2427 C67_INTDP(r, r);
2429 C67_NOP(4);
2430 vtop->type.t = VT_DOUBLE;
2431 } else {
2432 if (t & VT_UNSIGNED)
2433 C67_INTSPU(r, r);
2434 else
2435 C67_INTSP(r, r);
2436 C67_NOP(3);
2437 vtop->type.t = VT_FLOAT;
2442 /* convert fp to int 't' type */
2443 /* XXX: handle long long case */
2444 void gen_cvt_ftoi(int t)
2446 int r;
2448 gv(RC_FLOAT);
2449 r = vtop->r;
2451 if (t != VT_INT)
2452 tcc_error("long long not supported");
2453 else {
2454 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2455 C67_DPTRUNC(r, r);
2456 C67_NOP(3);
2457 } else {
2458 C67_SPTRUNC(r, r);
2459 C67_NOP(3);
2462 vtop->type.t = VT_INT;
2467 /* convert from one floating point type to another */
2468 void gen_cvt_ftof(int t)
2470 int r, r2;
2472 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2473 (t & VT_BTYPE) == VT_FLOAT) {
2474 // convert double to float
2476 gv(RC_FLOAT); // get it in a register pair
2478 r = vtop->r;
2480 C67_DPSP(r, r); // convert it to SP same register
2481 C67_NOP(3);
2483 vtop->type.t = VT_FLOAT;
2484 vtop->r2 = VT_CONST; // set this as unused
2485 } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
2486 (t & VT_BTYPE) == VT_DOUBLE) {
2487 // convert float to double
2489 gv(RC_FLOAT); // get it in a register
2491 r = vtop->r;
2493 if (r == TREG_EAX) { // make sure the paired reg is avail
2494 r2 = get_reg(RC_ECX);
2495 } else if (r == TREG_EDX) {
2496 r2 = get_reg(RC_ST0);
2497 } else {
2498 ALWAYS_ASSERT(FALSE);
2499 r2 = 0; /* avoid warning */
2502 C67_SPDP(r, r); // convert it to DP same register
2503 C67_NOP(1);
2505 vtop->type.t = VT_DOUBLE;
2506 vtop->r2 = r2; // set this as unused
2507 } else {
2508 ALWAYS_ASSERT(FALSE);
2512 /* computed goto support */
2513 void ggoto(void)
2515 gcall_or_jmp(1);
2516 vtop--;
2519 /* Save the stack pointer onto the stack and return the location of its address */
2520 ST_FUNC void gen_vla_sp_save(int addr) {
2521 tcc_error("variable length arrays unsupported for this target");
2524 /* Restore the SP from a location on the stack */
2525 ST_FUNC void gen_vla_sp_restore(int addr) {
2526 tcc_error("variable length arrays unsupported for this target");
2529 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2530 ST_FUNC void gen_vla_alloc(CType *type, int align) {
2531 tcc_error("variable length arrays unsupported for this target");
2534 /* end of C67 code generator */
2535 /*************************************************************/
2536 #endif
2537 /*************************************************************/