Use functions to get relocation info
[tinycc.git] / c67-gen.c
blob28db68b26a66c78261352031000d67f07d52bc31
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;
186 #ifdef ASSEMBLY_LISTING_C67
187 fprintf(f, " %08X", c);
188 #endif
189 ind1 = ind + 4;
190 if (ind1 > (int) cur_text_section->data_allocated)
191 section_realloc(cur_text_section, ind1);
192 cur_text_section->data[ind] = c & 0xff;
193 cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
194 cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
195 cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
196 ind = ind1;
200 /* output a symbol and patch all calls to it */
201 void gsym_addr(int t, int a)
203 int n, *ptr;
204 while (t) {
205 ptr = (int *) (cur_text_section->data + t);
207 Sym *sym;
209 // extract 32 bit address from MVKH/MVKL
210 n = ((*ptr >> 7) & 0xffff);
211 n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
213 // define a label that will be relocated
215 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
216 greloc(cur_text_section, sym, t, R_C60LO16);
217 greloc(cur_text_section, sym, t + 4, R_C60HI16);
219 // clear out where the pointer was
221 *ptr &= ~(0xffff << 7);
222 *(ptr + 1) &= ~(0xffff << 7);
224 t = n;
228 void gsym(int t)
230 gsym_addr(t, ind);
233 // these are regs that tcc doesn't really know about,
234 // but assign them unique values so the mapping routines
235 // can distinguish them
237 #define C67_A0 105
238 #define C67_SP 106
239 #define C67_B3 107
240 #define C67_FP 108
241 #define C67_B2 109
242 #define C67_CREG_ZERO -1 /* Special code for no condition reg test */
245 int ConvertRegToRegClass(int r)
247 // only works for A4-B13
249 return RC_C67_A4 << (r - TREG_C67_A4);
253 // map TCC reg to C67 reg number
255 int C67_map_regn(int r)
257 if (r == 0) // normal tcc regs
258 return 0x2; // A2
259 else if (r == 1) // normal tcc regs
260 return 3; // A3
261 else if (r == 2) // normal tcc regs
262 return 0; // B0
263 else if (r == 3) // normal tcc regs
264 return 1; // B1
265 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
266 return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
267 else if (r == C67_A0)
268 return 0; // set to A0 (offset reg)
269 else if (r == C67_B2)
270 return 2; // set to B2 (offset reg)
271 else if (r == C67_B3)
272 return 3; // set to B3 (return address reg)
273 else if (r == C67_SP)
274 return 15; // set to SP (B15) (offset reg)
275 else if (r == C67_FP)
276 return 15; // set to FP (A15) (offset reg)
277 else if (r == C67_CREG_ZERO)
278 return 0; // Special code for no condition reg test
279 else
280 ALWAYS_ASSERT(FALSE);
282 return 0;
285 // mapping from tcc reg number to
286 // C67 register to condition code field
288 // valid condition code regs are:
290 // tcc reg 2 ->B0 -> 1
291 // tcc reg 3 ->B1 -> 2
292 // tcc reg 0 -> A2 -> 5
293 // tcc reg 1 -> A3 -> X
294 // tcc reg B2 -> 3
296 int C67_map_regc(int r)
298 if (r == 0) // normal tcc regs
299 return 0x5;
300 else if (r == 2) // normal tcc regs
301 return 0x1;
302 else if (r == 3) // normal tcc regs
303 return 0x2;
304 else if (r == C67_B2) // normal tcc regs
305 return 0x3;
306 else if (r == C67_CREG_ZERO)
307 return 0; // Special code for no condition reg test
308 else
309 ALWAYS_ASSERT(FALSE);
311 return 0;
315 // map TCC reg to C67 reg side A or B
317 int C67_map_regs(int r)
319 if (r == 0) // normal tcc regs
320 return 0x0;
321 else if (r == 1) // normal tcc regs
322 return 0x0;
323 else if (r == 2) // normal tcc regs
324 return 0x1;
325 else if (r == 3) // normal tcc regs
326 return 0x1;
327 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
328 return (r & 2) >> 1;
329 else if (r == C67_A0)
330 return 0; // set to A side
331 else if (r == C67_B2)
332 return 1; // set to B side
333 else if (r == C67_B3)
334 return 1; // set to B side
335 else if (r == C67_SP)
336 return 0x1; // set to SP (B15) B side
337 else if (r == C67_FP)
338 return 0x0; // set to FP (A15) A side
339 else
340 ALWAYS_ASSERT(FALSE);
342 return 0;
345 int C67_map_S12(char *s)
347 if (strstr(s, ".S1") != NULL)
348 return 0;
349 else if (strcmp(s, ".S2"))
350 return 1;
351 else
352 ALWAYS_ASSERT(FALSE);
354 return 0;
357 int C67_map_D12(char *s)
359 if (strstr(s, ".D1") != NULL)
360 return 0;
361 else if (strcmp(s, ".D2"))
362 return 1;
363 else
364 ALWAYS_ASSERT(FALSE);
366 return 0;
371 void C67_asm(char *s, int a, int b, int c)
373 BOOL xpath;
375 #ifdef ASSEMBLY_LISTING_C67
376 if (!f) {
377 f = fopen("TCC67_out.txt", "wt");
379 fprintf(f, "%04X ", ind);
380 #endif
382 if (strstr(s, "MVKL") == s) {
383 C67_g((C67_map_regn(b) << 23) |
384 ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
385 } else if (strstr(s, "MVKH") == s) {
386 C67_g((C67_map_regn(b) << 23) |
387 (((a >> 16) & 0xffff) << 7) |
388 (0x1a << 2) | (C67_map_regs(b) << 1));
389 } else if (strstr(s, "STW.D SP POST DEC") == s) {
390 C67_g((C67_map_regn(a) << 23) | //src
391 (15 << 18) | //SP B15
392 (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
393 (0xa << 9) | //mode a = post dec ucst
394 (0 << 8) | //r (LDDW bit 0)
395 (1 << 7) | //y D1/D2 use B side
396 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
397 (1 << 2) | //opcode
398 (C67_map_regs(a) << 1) | //side of src
399 (0 << 0)); //parallel
400 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
401 C67_g((C67_map_regn(a) << 23) | //src
402 (15 << 18) | //base reg A15
403 (0 << 13) | //offset reg A0
404 (5 << 9) | //mode 5 = pos offset, base reg + off reg
405 (0 << 8) | //r (LDDW bit 0)
406 (0 << 7) | //y D1/D2 A side
407 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
408 (1 << 2) | //opcode
409 (C67_map_regs(a) << 1) | //side of src
410 (0 << 0)); //parallel
411 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
412 C67_g((C67_map_regn(a) << 23) | //src
413 (15 << 18) | //base reg A15
414 (0 << 13) | //offset reg A0
415 (5 << 9) | //mode 5 = pos offset, base reg + off reg
416 (0 << 8) | //r (LDDW bit 0)
417 (0 << 7) | //y D1/D2 A side
418 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
419 (1 << 2) | //opcode
420 (C67_map_regs(a) << 1) | //side of src
421 (0 << 0)); //parallel
422 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
423 C67_g((C67_map_regn(a) << 23) | //src
424 (15 << 18) | //base reg A15
425 (0 << 13) | //offset reg A0
426 (5 << 9) | //mode 5 = pos offset, base reg + off reg
427 (0 << 8) | //r (LDDW bit 0)
428 (0 << 7) | //y D1/D2 A side
429 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
430 (1 << 2) | //opcode
431 (C67_map_regs(a) << 1) | //side of src
432 (0 << 0)); //parallel
433 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
434 C67_g((C67_map_regn(a) << 23) | //src
435 (15 << 18) | //base reg A15
436 (0 << 13) | //offset reg A0
437 (5 << 9) | //mode 5 = pos offset, base reg + off reg
438 (0 << 8) | //r (LDDW bit 0)
439 (0 << 7) | //y D1/D2 A side
440 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
441 (1 << 2) | //opcode
442 (C67_map_regs(a) << 1) | //side of src
443 (0 << 0)); //parallel
444 } else if (strstr(s, "STW.D *+SP[A0]") == s) {
445 C67_g((C67_map_regn(a) << 23) | //src
446 (15 << 18) | //base reg A15
447 (0 << 13) | //offset reg A0
448 (5 << 9) | //mode 5 = pos offset, base reg + off reg
449 (0 << 8) | //r (LDDW bit 0)
450 (0 << 7) | //y D1/D2 A side
451 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
452 (1 << 2) | //opcode
453 (C67_map_regs(a) << 1) | //side of src
454 (0 << 0)); //parallel
455 } else if (strstr(s, "STW.D *") == s) {
456 C67_g((C67_map_regn(a) << 23) | //src
457 (C67_map_regn(b) << 18) | //base reg A0
458 (0 << 13) | //cst5
459 (1 << 9) | //mode 1 = pos cst offset
460 (0 << 8) | //r (LDDW bit 0)
461 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
462 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
463 (1 << 2) | //opcode
464 (C67_map_regs(a) << 1) | //side of src
465 (0 << 0)); //parallel
466 } else if (strstr(s, "STH.D *") == s) {
467 C67_g((C67_map_regn(a) << 23) | //src
468 (C67_map_regn(b) << 18) | //base reg A0
469 (0 << 13) | //cst5
470 (1 << 9) | //mode 1 = pos cst offset
471 (0 << 8) | //r (LDDW bit 0)
472 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
473 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
474 (1 << 2) | //opcode
475 (C67_map_regs(a) << 1) | //side of src
476 (0 << 0)); //parallel
477 } else if (strstr(s, "STB.D *") == s) {
478 C67_g((C67_map_regn(a) << 23) | //src
479 (C67_map_regn(b) << 18) | //base reg A0
480 (0 << 13) | //cst5
481 (1 << 9) | //mode 1 = pos cst offset
482 (0 << 8) | //r (LDDW bit 0)
483 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
484 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
485 (1 << 2) | //opcode
486 (C67_map_regs(a) << 1) | //side of src
487 (0 << 0)); //parallel
488 } else if (strstr(s, "STW.D +*") == s) {
489 ALWAYS_ASSERT(c < 32);
490 C67_g((C67_map_regn(a) << 23) | //src
491 (C67_map_regn(b) << 18) | //base reg A0
492 (c << 13) | //cst5
493 (1 << 9) | //mode 1 = pos cst offset
494 (0 << 8) | //r (LDDW bit 0)
495 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
496 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
497 (1 << 2) | //opcode
498 (C67_map_regs(a) << 1) | //side of src
499 (0 << 0)); //parallel
500 } else if (strstr(s, "LDW.D SP PRE INC") == s) {
501 C67_g((C67_map_regn(a) << 23) | //dst
502 (15 << 18) | //base reg B15
503 (2 << 13) | //ucst5 (must keep 8 byte boundary)
504 (9 << 9) | //mode 9 = pre inc ucst5
505 (0 << 8) | //r (LDDW bit 0)
506 (1 << 7) | //y D1/D2 B side
507 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
508 (1 << 2) | //opcode
509 (C67_map_regs(a) << 1) | //side of dst
510 (0 << 0)); //parallel
511 } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
512 C67_g((C67_map_regn(a) << 23) | //dst
513 (15 << 18) | //base reg B15
514 (1 << 13) | //ucst5 (must keep 8 byte boundary)
515 (9 << 9) | //mode 9 = pre inc ucst5
516 (1 << 8) | //r (LDDW bit 1)
517 (1 << 7) | //y D1/D2 B side
518 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
519 (1 << 2) | //opcode
520 (C67_map_regs(a) << 1) | //side of dst
521 (0 << 0)); //parallel
522 } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
523 C67_g((C67_map_regn(a) << 23) | //dst
524 (15 << 18) | //base reg A15
525 (0 << 13) | //offset reg A0
526 (5 << 9) | //mode 5 = pos offset, base reg + off reg
527 (0 << 8) | //r (LDDW bit 0)
528 (0 << 7) | //y D1/D2 A side
529 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
530 (1 << 2) | //opcode
531 (C67_map_regs(a) << 1) | //side of dst
532 (0 << 0)); //parallel
533 } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
534 C67_g((C67_map_regn(a) << 23) | //dst
535 (15 << 18) | //base reg A15
536 (0 << 13) | //offset reg A0
537 (5 << 9) | //mode 5 = pos offset, base reg + off reg
538 (1 << 8) | //r (LDDW bit 1)
539 (0 << 7) | //y D1/D2 A side
540 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
541 (1 << 2) | //opcode
542 (C67_map_regs(a) << 1) | //side of dst
543 (0 << 0)); //parallel
544 } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
545 C67_g((C67_map_regn(a) << 23) | //dst
546 (15 << 18) | //base reg A15
547 (0 << 13) | //offset reg A0
548 (5 << 9) | //mode 5 = pos offset, base reg + off reg
549 (0 << 8) | //r (LDDW bit 0)
550 (0 << 7) | //y D1/D2 A side
551 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
552 (1 << 2) | //opcode
553 (C67_map_regs(a) << 1) | //side of dst
554 (0 << 0)); //parallel
555 } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
556 C67_g((C67_map_regn(a) << 23) | //dst
557 (15 << 18) | //base reg A15
558 (0 << 13) | //offset reg A0
559 (5 << 9) | //mode 5 = pos offset, base reg + off reg
560 (0 << 8) | //r (LDDW bit 0)
561 (0 << 7) | //y D1/D2 A side
562 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
563 (1 << 2) | //opcode
564 (C67_map_regs(a) << 1) | //side of dst
565 (0 << 0)); //parallel
566 } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
567 C67_g((C67_map_regn(a) << 23) | //dst
568 (15 << 18) | //base reg A15
569 (0 << 13) | //offset reg A0
570 (5 << 9) | //mode 5 = pos offset, base reg + off reg
571 (0 << 8) | //r (LDDW bit 0)
572 (0 << 7) | //y D1/D2 A side
573 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
574 (1 << 2) | //opcode
575 (C67_map_regs(a) << 1) | //side of dst
576 (0 << 0)); //parallel
577 } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
578 C67_g((C67_map_regn(a) << 23) | //dst
579 (15 << 18) | //base reg A15
580 (0 << 13) | //offset reg A0
581 (5 << 9) | //mode 5 = pos offset, base reg + off reg
582 (0 << 8) | //r (LDDW bit 0)
583 (0 << 7) | //y D1/D2 A side
584 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
585 (1 << 2) | //opcode
586 (C67_map_regs(a) << 1) | //side of dst
587 (0 << 0)); //parallel
588 } else if (strstr(s, "LDW.D *") == s) {
589 C67_g((C67_map_regn(b) << 23) | //dst
590 (C67_map_regn(a) << 18) | //base reg A15
591 (0 << 13) | //cst5
592 (1 << 9) | //mode 1 = pos cst offset
593 (0 << 8) | //r (LDDW bit 0)
594 (C67_map_regs(a) << 7) | //y D1/D2 src side
595 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
596 (1 << 2) | //opcode
597 (C67_map_regs(b) << 1) | //side of dst
598 (0 << 0)); //parallel
599 } else if (strstr(s, "LDDW.D *") == s) {
600 C67_g((C67_map_regn(b) << 23) | //dst
601 (C67_map_regn(a) << 18) | //base reg A15
602 (0 << 13) | //cst5
603 (1 << 9) | //mode 1 = pos cst offset
604 (1 << 8) | //r (LDDW bit 1)
605 (C67_map_regs(a) << 7) | //y D1/D2 src side
606 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
607 (1 << 2) | //opcode
608 (C67_map_regs(b) << 1) | //side of dst
609 (0 << 0)); //parallel
610 } else if (strstr(s, "LDH.D *") == s) {
611 C67_g((C67_map_regn(b) << 23) | //dst
612 (C67_map_regn(a) << 18) | //base reg A15
613 (0 << 13) | //cst5
614 (1 << 9) | //mode 1 = pos cst offset
615 (0 << 8) | //r (LDDW bit 0)
616 (C67_map_regs(a) << 7) | //y D1/D2 src side
617 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
618 (1 << 2) | //opcode
619 (C67_map_regs(b) << 1) | //side of dst
620 (0 << 0)); //parallel
621 } else if (strstr(s, "LDB.D *") == s) {
622 C67_g((C67_map_regn(b) << 23) | //dst
623 (C67_map_regn(a) << 18) | //base reg A15
624 (0 << 13) | //cst5
625 (1 << 9) | //mode 1 = pos cst offset
626 (0 << 8) | //r (LDDW bit 0)
627 (C67_map_regs(a) << 7) | //y D1/D2 src side
628 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
629 (1 << 2) | //opcode
630 (C67_map_regs(b) << 1) | //side of dst
631 (0 << 0)); //parallel
632 } else if (strstr(s, "LDHU.D *") == s) {
633 C67_g((C67_map_regn(b) << 23) | //dst
634 (C67_map_regn(a) << 18) | //base reg A15
635 (0 << 13) | //cst5
636 (1 << 9) | //mode 1 = pos cst offset
637 (0 << 8) | //r (LDDW bit 0)
638 (C67_map_regs(a) << 7) | //y D1/D2 src side
639 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
640 (1 << 2) | //opcode
641 (C67_map_regs(b) << 1) | //side of dst
642 (0 << 0)); //parallel
643 } else if (strstr(s, "LDBU.D *") == s) {
644 C67_g((C67_map_regn(b) << 23) | //dst
645 (C67_map_regn(a) << 18) | //base reg A15
646 (0 << 13) | //cst5
647 (1 << 9) | //mode 1 = pos cst offset
648 (0 << 8) | //r (LDDW bit 0)
649 (C67_map_regs(a) << 7) | //y D1/D2 src side
650 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
651 (1 << 2) | //opcode
652 (C67_map_regs(b) << 1) | //side of dst
653 (0 << 0)); //parallel
654 } else if (strstr(s, "LDW.D +*") == s) {
655 C67_g((C67_map_regn(b) << 23) | //dst
656 (C67_map_regn(a) << 18) | //base reg A15
657 (1 << 13) | //cst5
658 (1 << 9) | //mode 1 = pos cst offset
659 (0 << 8) | //r (LDDW bit 0)
660 (C67_map_regs(a) << 7) | //y D1/D2 src side
661 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
662 (1 << 2) | //opcode
663 (C67_map_regs(b) << 1) | //side of dst
664 (0 << 0)); //parallel
665 } else if (strstr(s, "CMPLTSP") == s) {
666 xpath = C67_map_regs(a) ^ C67_map_regs(b);
667 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
669 C67_g((C67_map_regn(c) << 23) | //dst
670 (C67_map_regn(b) << 18) | //src2
671 (C67_map_regn(a) << 13) | //src1
672 (xpath << 12) | //x use cross path for src2
673 (0x3a << 6) | //opcode
674 (0x8 << 2) | //opcode fixed
675 (C67_map_regs(c) << 1) | //side for reg c
676 (0 << 0)); //parallel
677 } else if (strstr(s, "CMPGTSP") == s) {
678 xpath = C67_map_regs(a) ^ C67_map_regs(b);
679 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
681 C67_g((C67_map_regn(c) << 23) | //dst
682 (C67_map_regn(b) << 18) | //src2
683 (C67_map_regn(a) << 13) | //src1
684 (xpath << 12) | //x use cross path for src2
685 (0x39 << 6) | //opcode
686 (0x8 << 2) | //opcode fixed
687 (C67_map_regs(c) << 1) | //side for reg c
688 (0 << 0)); //parallel
689 } else if (strstr(s, "CMPEQSP") == s) {
690 xpath = C67_map_regs(a) ^ C67_map_regs(b);
691 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
693 C67_g((C67_map_regn(c) << 23) | //dst
694 (C67_map_regn(b) << 18) | //src2
695 (C67_map_regn(a) << 13) | //src1
696 (xpath << 12) | //x use cross path for src2
697 (0x38 << 6) | //opcode
698 (0x8 << 2) | //opcode fixed
699 (C67_map_regs(c) << 1) | //side for reg c
700 (0 << 0)); //parallel
703 else if (strstr(s, "CMPLTDP") == s) {
704 xpath = C67_map_regs(a) ^ C67_map_regs(b);
705 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
707 C67_g((C67_map_regn(c) << 23) | //dst
708 (C67_map_regn(b) << 18) | //src2
709 (C67_map_regn(a) << 13) | //src1
710 (xpath << 12) | //x use cross path for src2
711 (0x2a << 6) | //opcode
712 (0x8 << 2) | //opcode fixed
713 (C67_map_regs(c) << 1) | //side for reg c
714 (0 << 0)); //parallel
715 } else if (strstr(s, "CMPGTDP") == s) {
716 xpath = C67_map_regs(a) ^ C67_map_regs(b);
717 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
719 C67_g((C67_map_regn(c) << 23) | //dst
720 (C67_map_regn(b) << 18) | //src2
721 (C67_map_regn(a) << 13) | //src1
722 (xpath << 12) | //x use cross path for src2
723 (0x29 << 6) | //opcode
724 (0x8 << 2) | //opcode fixed
725 (C67_map_regs(c) << 1) | //side for reg c
726 (0 << 0)); //parallel
727 } else if (strstr(s, "CMPEQDP") == s) {
728 xpath = C67_map_regs(a) ^ C67_map_regs(b);
729 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
731 C67_g((C67_map_regn(c) << 23) | //dst
732 (C67_map_regn(b) << 18) | //src2
733 (C67_map_regn(a) << 13) | //src1
734 (xpath << 12) | //x use cross path for src2
735 (0x28 << 6) | //opcode
736 (0x8 << 2) | //opcode fixed
737 (C67_map_regs(c) << 1) | //side for reg c
738 (0 << 0)); //parallel
739 } else if (strstr(s, "CMPLT") == s) {
740 xpath = C67_map_regs(a) ^ C67_map_regs(b);
741 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
743 C67_g((C67_map_regn(c) << 23) | //dst
744 (C67_map_regn(b) << 18) | //src2
745 (C67_map_regn(a) << 13) | //src1
746 (xpath << 12) | //x use cross path for src2
747 (0x57 << 5) | //opcode
748 (0x6 << 2) | //opcode fixed
749 (C67_map_regs(c) << 1) | //side for reg c
750 (0 << 0)); //parallel
751 } else if (strstr(s, "CMPGT") == s) {
752 xpath = C67_map_regs(a) ^ C67_map_regs(b);
753 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
755 C67_g((C67_map_regn(c) << 23) | //dst
756 (C67_map_regn(b) << 18) | //src2
757 (C67_map_regn(a) << 13) | //src1
758 (xpath << 12) | //x use cross path for src2
759 (0x47 << 5) | //opcode
760 (0x6 << 2) | //opcode fixed
761 (C67_map_regs(c) << 1) | //side for reg c
762 (0 << 0)); //parallel
763 } else if (strstr(s, "CMPEQ") == s) {
764 xpath = C67_map_regs(a) ^ C67_map_regs(b);
765 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
767 C67_g((C67_map_regn(c) << 23) | //dst
768 (C67_map_regn(b) << 18) | //src2
769 (C67_map_regn(a) << 13) | //src1
770 (xpath << 12) | //x use cross path for src2
771 (0x53 << 5) | //opcode
772 (0x6 << 2) | //opcode fixed
773 (C67_map_regs(c) << 1) | //side for reg c
774 (0 << 0)); //parallel
775 } else if (strstr(s, "CMPLTU") == s) {
776 xpath = C67_map_regs(a) ^ C67_map_regs(b);
777 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
779 C67_g((C67_map_regn(c) << 23) | //dst
780 (C67_map_regn(b) << 18) | //src2
781 (C67_map_regn(a) << 13) | //src1
782 (xpath << 12) | //x use cross path for src2
783 (0x5f << 5) | //opcode
784 (0x6 << 2) | //opcode fixed
785 (C67_map_regs(c) << 1) | //side for reg c
786 (0 << 0)); //parallel
787 } else if (strstr(s, "CMPGTU") == s) {
788 xpath = C67_map_regs(a) ^ C67_map_regs(b);
789 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
791 C67_g((C67_map_regn(c) << 23) | //dst
792 (C67_map_regn(b) << 18) | //src2
793 (C67_map_regn(a) << 13) | //src1
794 (xpath << 12) | //x use cross path for src2
795 (0x4f << 5) | //opcode
796 (0x6 << 2) | //opcode fixed
797 (C67_map_regs(c) << 1) | //side for reg c
798 (0 << 0)); //parallel
799 } else if (strstr(s, "B DISP") == s) {
800 C67_g((0 << 29) | //creg
801 (0 << 28) | //z
802 (a << 7) | //cnst
803 (0x4 << 2) | //opcode fixed
804 (0 << 1) | //S0/S1
805 (0 << 0)); //parallel
806 } else if (strstr(s, "B.") == s) {
807 xpath = C67_map_regs(c) ^ 1;
809 C67_g((C67_map_regc(b) << 29) | //creg
810 (a << 28) | //inv
811 (0 << 23) | //dst
812 (C67_map_regn(c) << 18) | //src2
813 (0 << 13) | //
814 (xpath << 12) | //x cross path if !B side
815 (0xd << 6) | //opcode
816 (0x8 << 2) | //opcode fixed
817 (1 << 1) | //must be S2
818 (0 << 0)); //parallel
819 } else if (strstr(s, "MV.L") == s) {
820 xpath = C67_map_regs(b) ^ C67_map_regs(c);
822 C67_g((0 << 29) | //creg
823 (0 << 28) | //inv
824 (C67_map_regn(c) << 23) | //dst
825 (C67_map_regn(b) << 18) | //src2
826 (0 << 13) | //src1 (cst5)
827 (xpath << 12) | //x cross path if opposite sides
828 (0x2 << 5) | //opcode
829 (0x6 << 2) | //opcode fixed
830 (C67_map_regs(c) << 1) | //side of dest
831 (0 << 0)); //parallel
832 } else if (strstr(s, "SPTRUNC.L") == s) {
833 xpath = C67_map_regs(b) ^ C67_map_regs(c);
835 C67_g((0 << 29) | //creg
836 (0 << 28) | //inv
837 (C67_map_regn(c) << 23) | //dst
838 (C67_map_regn(b) << 18) | //src2
839 (0 << 13) | //src1 NA
840 (xpath << 12) | //x cross path if opposite sides
841 (0xb << 5) | //opcode
842 (0x6 << 2) | //opcode fixed
843 (C67_map_regs(c) << 1) | //side of dest
844 (0 << 0)); //parallel
845 } else if (strstr(s, "DPTRUNC.L") == s) {
846 xpath = C67_map_regs(b) ^ C67_map_regs(c);
848 C67_g((0 << 29) | //creg
849 (0 << 28) | //inv
850 (C67_map_regn(c) << 23) | //dst
851 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
852 (0 << 13) | //src1 NA
853 (xpath << 12) | //x cross path if opposite sides
854 (0x1 << 5) | //opcode
855 (0x6 << 2) | //opcode fixed
856 (C67_map_regs(c) << 1) | //side of dest
857 (0 << 0)); //parallel
858 } else if (strstr(s, "INTSP.L") == s) {
859 xpath = C67_map_regs(b) ^ C67_map_regs(c);
861 C67_g((0 << 29) | //creg
862 (0 << 28) | //inv
863 (C67_map_regn(c) << 23) | //dst
864 (C67_map_regn(b) << 18) | //src2
865 (0 << 13) | //src1 NA
866 (xpath << 12) | //x cross path if opposite sides
867 (0x4a << 5) | //opcode
868 (0x6 << 2) | //opcode fixed
869 (C67_map_regs(c) << 1) | //side of dest
870 (0 << 0)); //parallel
871 } else if (strstr(s, "INTSPU.L") == s) {
872 xpath = C67_map_regs(b) ^ C67_map_regs(c);
874 C67_g((0 << 29) | //creg
875 (0 << 28) | //inv
876 (C67_map_regn(c) << 23) | //dst
877 (C67_map_regn(b) << 18) | //src2
878 (0 << 13) | //src1 NA
879 (xpath << 12) | //x cross path if opposite sides
880 (0x49 << 5) | //opcode
881 (0x6 << 2) | //opcode fixed
882 (C67_map_regs(c) << 1) | //side of dest
883 (0 << 0)); //parallel
884 } else if (strstr(s, "INTDP.L") == s) {
885 xpath = C67_map_regs(b) ^ C67_map_regs(c);
887 C67_g((0 << 29) | //creg
888 (0 << 28) | //inv
889 (C67_map_regn(c) << 23) | //dst
890 (C67_map_regn(b) << 18) | //src2
891 (0 << 13) | //src1 NA
892 (xpath << 12) | //x cross path if opposite sides
893 (0x39 << 5) | //opcode
894 (0x6 << 2) | //opcode fixed
895 (C67_map_regs(c) << 1) | //side of dest
896 (0 << 0)); //parallel
897 } else if (strstr(s, "INTDPU.L") == s) {
898 xpath = C67_map_regs(b) ^ C67_map_regs(c);
900 C67_g((0 << 29) | //creg
901 (0 << 28) | //inv
902 (C67_map_regn(c) << 23) | //dst
903 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
904 (0 << 13) | //src1 NA
905 (xpath << 12) | //x cross path if opposite sides
906 (0x3b << 5) | //opcode
907 (0x6 << 2) | //opcode fixed
908 (C67_map_regs(c) << 1) | //side of dest
909 (0 << 0)); //parallel
910 } else if (strstr(s, "SPDP.L") == s) {
911 xpath = C67_map_regs(b) ^ C67_map_regs(c);
913 C67_g((0 << 29) | //creg
914 (0 << 28) | //inv
915 (C67_map_regn(c) << 23) | //dst
916 (C67_map_regn(b) << 18) | //src2
917 (0 << 13) | //src1 NA
918 (xpath << 12) | //x cross path if opposite sides
919 (0x2 << 6) | //opcode
920 (0x8 << 2) | //opcode fixed
921 (C67_map_regs(c) << 1) | //side of dest
922 (0 << 0)); //parallel
923 } else if (strstr(s, "DPSP.L") == s) {
924 ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
926 C67_g((0 << 29) | //creg
927 (0 << 28) | //inv
928 (C67_map_regn(c) << 23) | //dst
929 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
930 (0 << 13) | //src1 NA
931 (0 << 12) | //x cross path if opposite sides
932 (0x9 << 5) | //opcode
933 (0x6 << 2) | //opcode fixed
934 (C67_map_regs(c) << 1) | //side of dest
935 (0 << 0)); //parallel
936 } else if (strstr(s, "ADD.L") == s) {
937 xpath = C67_map_regs(b) ^ C67_map_regs(c);
939 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
941 C67_g((0 << 29) | //creg
942 (0 << 28) | //inv
943 (C67_map_regn(c) << 23) | //dst
944 (C67_map_regn(b) << 18) | //src2 (possible x path)
945 (C67_map_regn(a) << 13) | //src1
946 (xpath << 12) | //x cross path if opposite sides
947 (0x3 << 5) | //opcode
948 (0x6 << 2) | //opcode fixed
949 (C67_map_regs(c) << 1) | //side of dest
950 (0 << 0)); //parallel
951 } else if (strstr(s, "SUB.L") == s) {
952 xpath = C67_map_regs(b) ^ C67_map_regs(c);
954 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
956 C67_g((0 << 29) | //creg
957 (0 << 28) | //inv
958 (C67_map_regn(c) << 23) | //dst
959 (C67_map_regn(b) << 18) | //src2 (possible x path)
960 (C67_map_regn(a) << 13) | //src1
961 (xpath << 12) | //x cross path if opposite sides
962 (0x7 << 5) | //opcode
963 (0x6 << 2) | //opcode fixed
964 (C67_map_regs(c) << 1) | //side of dest
965 (0 << 0)); //parallel
966 } else if (strstr(s, "OR.L") == s) {
967 xpath = C67_map_regs(b) ^ C67_map_regs(c);
969 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
971 C67_g((0 << 29) | //creg
972 (0 << 28) | //inv
973 (C67_map_regn(c) << 23) | //dst
974 (C67_map_regn(b) << 18) | //src2 (possible x path)
975 (C67_map_regn(a) << 13) | //src1
976 (xpath << 12) | //x cross path if opposite sides
977 (0x7f << 5) | //opcode
978 (0x6 << 2) | //opcode fixed
979 (C67_map_regs(c) << 1) | //side of dest
980 (0 << 0)); //parallel
981 } else if (strstr(s, "AND.L") == s) {
982 xpath = C67_map_regs(b) ^ C67_map_regs(c);
984 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
986 C67_g((0 << 29) | //creg
987 (0 << 28) | //inv
988 (C67_map_regn(c) << 23) | //dst
989 (C67_map_regn(b) << 18) | //src2 (possible x path)
990 (C67_map_regn(a) << 13) | //src1
991 (xpath << 12) | //x cross path if opposite sides
992 (0x7b << 5) | //opcode
993 (0x6 << 2) | //opcode fixed
994 (C67_map_regs(c) << 1) | //side of dest
995 (0 << 0)); //parallel
996 } else if (strstr(s, "XOR.L") == s) {
997 xpath = C67_map_regs(b) ^ C67_map_regs(c);
999 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1001 C67_g((0 << 29) | //creg
1002 (0 << 28) | //inv
1003 (C67_map_regn(c) << 23) | //dst
1004 (C67_map_regn(b) << 18) | //src2 (possible x path)
1005 (C67_map_regn(a) << 13) | //src1
1006 (xpath << 12) | //x cross path if opposite sides
1007 (0x6f << 5) | //opcode
1008 (0x6 << 2) | //opcode fixed
1009 (C67_map_regs(c) << 1) | //side of dest
1010 (0 << 0)); //parallel
1011 } else if (strstr(s, "ADDSP.L") == s) {
1012 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1014 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1016 C67_g((0 << 29) | //creg
1017 (0 << 28) | //inv
1018 (C67_map_regn(c) << 23) | //dst
1019 (C67_map_regn(b) << 18) | //src2 (possible x path)
1020 (C67_map_regn(a) << 13) | //src1
1021 (xpath << 12) | //x cross path if opposite sides
1022 (0x10 << 5) | //opcode
1023 (0x6 << 2) | //opcode fixed
1024 (C67_map_regs(c) << 1) | //side of dest
1025 (0 << 0)); //parallel
1026 } else if (strstr(s, "ADDDP.L") == s) {
1027 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1029 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1031 C67_g((0 << 29) | //creg
1032 (0 << 28) | //inv
1033 (C67_map_regn(c) << 23) | //dst
1034 (C67_map_regn(b) << 18) | //src2 (possible x path)
1035 (C67_map_regn(a) << 13) | //src1
1036 (xpath << 12) | //x cross path if opposite sides
1037 (0x18 << 5) | //opcode
1038 (0x6 << 2) | //opcode fixed
1039 (C67_map_regs(c) << 1) | //side of dest
1040 (0 << 0)); //parallel
1041 } else if (strstr(s, "SUBSP.L") == s) {
1042 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1044 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1046 C67_g((0 << 29) | //creg
1047 (0 << 28) | //inv
1048 (C67_map_regn(c) << 23) | //dst
1049 (C67_map_regn(b) << 18) | //src2 (possible x path)
1050 (C67_map_regn(a) << 13) | //src1
1051 (xpath << 12) | //x cross path if opposite sides
1052 (0x11 << 5) | //opcode
1053 (0x6 << 2) | //opcode fixed
1054 (C67_map_regs(c) << 1) | //side of dest
1055 (0 << 0)); //parallel
1056 } else if (strstr(s, "SUBDP.L") == s) {
1057 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1059 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1061 C67_g((0 << 29) | //creg
1062 (0 << 28) | //inv
1063 (C67_map_regn(c) << 23) | //dst
1064 (C67_map_regn(b) << 18) | //src2 (possible x path)
1065 (C67_map_regn(a) << 13) | //src1
1066 (xpath << 12) | //x cross path if opposite sides
1067 (0x19 << 5) | //opcode
1068 (0x6 << 2) | //opcode fixed
1069 (C67_map_regs(c) << 1) | //side of dest
1070 (0 << 0)); //parallel
1071 } else if (strstr(s, "MPYSP.M") == s) {
1072 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1074 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1076 C67_g((0 << 29) | //creg
1077 (0 << 28) | //inv
1078 (C67_map_regn(c) << 23) | //dst
1079 (C67_map_regn(b) << 18) | //src2 (possible x path)
1080 (C67_map_regn(a) << 13) | //src1
1081 (xpath << 12) | //x cross path if opposite sides
1082 (0x1c << 7) | //opcode
1083 (0x0 << 2) | //opcode fixed
1084 (C67_map_regs(c) << 1) | //side of dest
1085 (0 << 0)); //parallel
1086 } else if (strstr(s, "MPYDP.M") == s) {
1087 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1089 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1091 C67_g((0 << 29) | //creg
1092 (0 << 28) | //inv
1093 (C67_map_regn(c) << 23) | //dst
1094 (C67_map_regn(b) << 18) | //src2 (possible x path)
1095 (C67_map_regn(a) << 13) | //src1
1096 (xpath << 12) | //x cross path if opposite sides
1097 (0x0e << 7) | //opcode
1098 (0x0 << 2) | //opcode fixed
1099 (C67_map_regs(c) << 1) | //side of dest
1100 (0 << 0)); //parallel
1101 } else if (strstr(s, "MPYI.M") == s) {
1102 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1104 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1106 C67_g((0 << 29) | //creg
1107 (0 << 28) | //inv
1108 (C67_map_regn(c) << 23) | //dst
1109 (C67_map_regn(b) << 18) | //src2
1110 (C67_map_regn(a) << 13) | //src1 (cst5)
1111 (xpath << 12) | //x cross path if opposite sides
1112 (0x4 << 7) | //opcode
1113 (0x0 << 2) | //opcode fixed
1114 (C67_map_regs(c) << 1) | //side of dest
1115 (0 << 0)); //parallel
1116 } else if (strstr(s, "SHR.S") == s) {
1117 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1119 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1121 C67_g((0 << 29) | //creg
1122 (0 << 28) | //inv
1123 (C67_map_regn(c) << 23) | //dst
1124 (C67_map_regn(b) << 18) | //src2
1125 (C67_map_regn(a) << 13) | //src1
1126 (xpath << 12) | //x cross path if opposite sides
1127 (0x37 << 6) | //opcode
1128 (0x8 << 2) | //opcode fixed
1129 (C67_map_regs(c) << 1) | //side of dest
1130 (0 << 0)); //parallel
1131 } else if (strstr(s, "SHRU.S") == s) {
1132 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1134 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1136 C67_g((0 << 29) | //creg
1137 (0 << 28) | //inv
1138 (C67_map_regn(c) << 23) | //dst
1139 (C67_map_regn(b) << 18) | //src2
1140 (C67_map_regn(a) << 13) | //src1
1141 (xpath << 12) | //x cross path if opposite sides
1142 (0x27 << 6) | //opcode
1143 (0x8 << 2) | //opcode fixed
1144 (C67_map_regs(c) << 1) | //side of dest
1145 (0 << 0)); //parallel
1146 } else if (strstr(s, "SHL.S") == s) {
1147 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1149 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1151 C67_g((0 << 29) | //creg
1152 (0 << 28) | //inv
1153 (C67_map_regn(c) << 23) | //dst
1154 (C67_map_regn(b) << 18) | //src2
1155 (C67_map_regn(a) << 13) | //src1
1156 (xpath << 12) | //x cross path if opposite sides
1157 (0x33 << 6) | //opcode
1158 (0x8 << 2) | //opcode fixed
1159 (C67_map_regs(c) << 1) | //side of dest
1160 (0 << 0)); //parallel
1161 } else if (strstr(s, "||ADDK") == s) {
1162 xpath = 0; // no xpath required just use the side of the src/dst
1164 C67_g((0 << 29) | //creg
1165 (0 << 28) | //inv
1166 (C67_map_regn(b) << 23) | //dst
1167 (a << 07) | //scst16
1168 (0x14 << 2) | //opcode fixed
1169 (C67_map_regs(b) << 1) | //side of dst
1170 (1 << 0)); //parallel
1171 } else if (strstr(s, "ADDK") == s) {
1172 xpath = 0; // no xpath required just use the side of the src/dst
1174 C67_g((0 << 29) | //creg
1175 (0 << 28) | //inv
1176 (C67_map_regn(b) << 23) | //dst
1177 (a << 07) | //scst16
1178 (0x14 << 2) | //opcode fixed
1179 (C67_map_regs(b) << 1) | //side of dst
1180 (0 << 0)); //parallel
1181 } else if (strstr(s, "NOP") == s) {
1182 C67_g(((a - 1) << 13) | //no of cycles
1183 (0 << 0)); //parallel
1184 } else
1185 ALWAYS_ASSERT(FALSE);
1187 #ifdef ASSEMBLY_LISTING_C67
1188 fprintf(f, " %s %d %d %d\n", s, a, b, c);
1189 #endif
1193 //r=reg to load, fr=from reg, symbol for relocation, constant
1195 void C67_MVKL(int r, int fc)
1197 C67_asm("MVKL.", fc, r, 0);
1200 void C67_MVKH(int r, int fc)
1202 C67_asm("MVKH.", fc, r, 0);
1205 void C67_STB_SP_A0(int r)
1207 C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB r,*+SP[A0]
1210 void C67_STH_SP_A0(int r)
1212 C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH r,*+SP[A0]
1215 void C67_STW_SP_A0(int r)
1217 C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW r,*+SP[A0]
1220 void C67_STB_PTR(int r, int r2)
1222 C67_asm("STB.D *", r, r2, 0); // STB r, *r2
1225 void C67_STH_PTR(int r, int r2)
1227 C67_asm("STH.D *", r, r2, 0); // STH r, *r2
1230 void C67_STW_PTR(int r, int r2)
1232 C67_asm("STW.D *", r, r2, 0); // STW r, *r2
1235 void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1237 C67_asm("STW.D +*", r, r2, n); // STW r, *+r2
1240 void C67_PUSH(int r)
1242 C67_asm("STW.D SP POST DEC", r, 0, 0); // STW r,*SP--
1245 void C67_LDW_SP_A0(int r)
1247 C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW *+SP[A0],r
1250 void C67_LDDW_SP_A0(int r)
1252 C67_asm("LDDW.D *+SP[A0]", r, 0, 0); // LDDW *+SP[A0],r
1255 void C67_LDH_SP_A0(int r)
1257 C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH *+SP[A0],r
1260 void C67_LDB_SP_A0(int r)
1262 C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB *+SP[A0],r
1265 void C67_LDHU_SP_A0(int r)
1267 C67_asm("LDHU.D *+SP[A0]", r, 0, 0); // LDHU *+SP[A0],r
1270 void C67_LDBU_SP_A0(int r)
1272 C67_asm("LDBU.D *+SP[A0]", r, 0, 0); // LDBU *+SP[A0],r
1275 void C67_LDW_PTR(int r, int r2)
1277 C67_asm("LDW.D *", r, r2, 0); // LDW *r,r2
1280 void C67_LDDW_PTR(int r, int r2)
1282 C67_asm("LDDW.D *", r, r2, 0); // LDDW *r,r2
1285 void C67_LDH_PTR(int r, int r2)
1287 C67_asm("LDH.D *", r, r2, 0); // LDH *r,r2
1290 void C67_LDB_PTR(int r, int r2)
1292 C67_asm("LDB.D *", r, r2, 0); // LDB *r,r2
1295 void C67_LDHU_PTR(int r, int r2)
1297 C67_asm("LDHU.D *", r, r2, 0); // LDHU *r,r2
1300 void C67_LDBU_PTR(int r, int r2)
1302 C67_asm("LDBU.D *", r, r2, 0); // LDBU *r,r2
1305 void C67_LDW_PTR_PRE_INC(int r, int r2)
1307 C67_asm("LDW.D +*", r, r2, 0); // LDW *+r,r2
1310 void C67_POP(int r)
1312 C67_asm("LDW.D SP PRE INC", r, 0, 0); // LDW *++SP,r
1315 void C67_POP_DW(int r)
1317 C67_asm("LDDW.D SP PRE INC", r, 0, 0); // LDDW *++SP,r
1320 void C67_CMPLT(int s1, int s2, int dst)
1322 C67_asm("CMPLT.L1", s1, s2, dst);
1325 void C67_CMPGT(int s1, int s2, int dst)
1327 C67_asm("CMPGT.L1", s1, s2, dst);
1330 void C67_CMPEQ(int s1, int s2, int dst)
1332 C67_asm("CMPEQ.L1", s1, s2, dst);
1335 void C67_CMPLTU(int s1, int s2, int dst)
1337 C67_asm("CMPLTU.L1", s1, s2, dst);
1340 void C67_CMPGTU(int s1, int s2, int dst)
1342 C67_asm("CMPGTU.L1", s1, s2, dst);
1346 void C67_CMPLTSP(int s1, int s2, int dst)
1348 C67_asm("CMPLTSP.S1", s1, s2, dst);
1351 void C67_CMPGTSP(int s1, int s2, int dst)
1353 C67_asm("CMPGTSP.S1", s1, s2, dst);
1356 void C67_CMPEQSP(int s1, int s2, int dst)
1358 C67_asm("CMPEQSP.S1", s1, s2, dst);
1361 void C67_CMPLTDP(int s1, int s2, int dst)
1363 C67_asm("CMPLTDP.S1", s1, s2, dst);
1366 void C67_CMPGTDP(int s1, int s2, int dst)
1368 C67_asm("CMPGTDP.S1", s1, s2, dst);
1371 void C67_CMPEQDP(int s1, int s2, int dst)
1373 C67_asm("CMPEQDP.S1", s1, s2, dst);
1377 void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2
1379 C67_asm("B.S2", inv, r1, r2);
1383 // call with how many 32 bit words to skip
1384 // (0 would branch to the branch instruction)
1386 void C67_B_DISP(int disp) // B +2 Branch with constant displacement
1388 // Branch point is relative to the 8 word fetch packet
1390 // we will assume the text section always starts on an 8 word (32 byte boundary)
1392 // so add in how many words into the fetch packet the branch is
1395 C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1398 void C67_NOP(int n)
1400 C67_asm("NOP", n, 0, 0);
1403 void C67_ADDK(int n, int r)
1405 ALWAYS_ASSERT(abs(n) < 32767);
1407 C67_asm("ADDK", n, r, 0);
1410 void C67_ADDK_PARALLEL(int n, int r)
1412 ALWAYS_ASSERT(abs(n) < 32767);
1414 C67_asm("||ADDK", n, r, 0);
1417 void C67_Adjust_ADDK(int *inst, int n)
1419 ALWAYS_ASSERT(abs(n) < 32767);
1421 *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1424 void C67_MV(int r, int v)
1426 C67_asm("MV.L", 0, r, v);
1430 void C67_DPTRUNC(int r, int v)
1432 C67_asm("DPTRUNC.L", 0, r, v);
1435 void C67_SPTRUNC(int r, int v)
1437 C67_asm("SPTRUNC.L", 0, r, v);
1440 void C67_INTSP(int r, int v)
1442 C67_asm("INTSP.L", 0, r, v);
1445 void C67_INTDP(int r, int v)
1447 C67_asm("INTDP.L", 0, r, v);
1450 void C67_INTSPU(int r, int v)
1452 C67_asm("INTSPU.L", 0, r, v);
1455 void C67_INTDPU(int r, int v)
1457 C67_asm("INTDPU.L", 0, r, v);
1460 void C67_SPDP(int r, int v)
1462 C67_asm("SPDP.L", 0, r, v);
1465 void C67_DPSP(int r, int v) // note regs must be on the same side
1467 C67_asm("DPSP.L", 0, r, v);
1470 void C67_ADD(int r, int v)
1472 C67_asm("ADD.L", v, r, v);
1475 void C67_SUB(int r, int v)
1477 C67_asm("SUB.L", v, r, v);
1480 void C67_AND(int r, int v)
1482 C67_asm("AND.L", v, r, v);
1485 void C67_OR(int r, int v)
1487 C67_asm("OR.L", v, r, v);
1490 void C67_XOR(int r, int v)
1492 C67_asm("XOR.L", v, r, v);
1495 void C67_ADDSP(int r, int v)
1497 C67_asm("ADDSP.L", v, r, v);
1500 void C67_SUBSP(int r, int v)
1502 C67_asm("SUBSP.L", v, r, v);
1505 void C67_MPYSP(int r, int v)
1507 C67_asm("MPYSP.M", v, r, v);
1510 void C67_ADDDP(int r, int v)
1512 C67_asm("ADDDP.L", v, r, v);
1515 void C67_SUBDP(int r, int v)
1517 C67_asm("SUBDP.L", v, r, v);
1520 void C67_MPYDP(int r, int v)
1522 C67_asm("MPYDP.M", v, r, v);
1525 void C67_MPYI(int r, int v)
1527 C67_asm("MPYI.M", v, r, v);
1530 void C67_SHL(int r, int v)
1532 C67_asm("SHL.S", r, v, v);
1535 void C67_SHRU(int r, int v)
1537 C67_asm("SHRU.S", r, v, v);
1540 void C67_SHR(int r, int v)
1542 C67_asm("SHR.S", r, v, v);
1547 /* load 'r' from value 'sv' */
1548 void load(int r, SValue * sv)
1550 int v, t, ft, fc, fr, size = 0, element;
1551 BOOL Unsigned = FALSE;
1552 SValue v1;
1554 fr = sv->r;
1555 ft = sv->type.t;
1556 fc = sv->c.i;
1558 v = fr & VT_VALMASK;
1559 if (fr & VT_LVAL) {
1560 if (v == VT_LLOCAL) {
1561 v1.type.t = VT_INT;
1562 v1.r = VT_LOCAL | VT_LVAL;
1563 v1.c.i = fc;
1564 load(r, &v1);
1565 fr = r;
1566 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
1567 tcc_error("long double not supported");
1568 } else if ((ft & VT_TYPE) == VT_BYTE) {
1569 size = 1;
1570 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1571 size = 1;
1572 Unsigned = TRUE;
1573 } else if ((ft & VT_TYPE) == VT_SHORT) {
1574 size = 2;
1575 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1576 size = 2;
1577 Unsigned = TRUE;
1578 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1579 size = 8;
1580 } else {
1581 size = 4;
1584 // check if fc is a positive reference on the stack,
1585 // if it is tcc is referencing what it thinks is a parameter
1586 // on the stack, so check if it is really in a register.
1589 if (v == VT_LOCAL && fc > 0) {
1590 int stack_pos = 8;
1592 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1593 if (fc == stack_pos)
1594 break;
1596 stack_pos += TranslateStackToReg[t];
1599 // param has been pushed on stack, get it like a local var
1601 fc = ParamLocOnStack[t] - 8;
1604 if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect
1606 if (size == 1) {
1607 if (Unsigned)
1608 C67_LDBU_PTR(v, r); // LDBU *v,r
1609 else
1610 C67_LDB_PTR(v, r); // LDB *v,r
1611 } else if (size == 2) {
1612 if (Unsigned)
1613 C67_LDHU_PTR(v, r); // LDHU *v,r
1614 else
1615 C67_LDH_PTR(v, r); // LDH *v,r
1616 } else if (size == 4) {
1617 C67_LDW_PTR(v, r); // LDW *v,r
1618 } else if (size == 8) {
1619 C67_LDDW_PTR(v, r); // LDDW *v,r
1622 C67_NOP(4); // NOP 4
1623 return;
1624 } else if (fr & VT_SYM) {
1625 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1626 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1629 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1630 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1633 if (size == 1) {
1634 if (Unsigned)
1635 C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r
1636 else
1637 C67_LDB_PTR(C67_A0, r); // LDB *A0,r
1638 } else if (size == 2) {
1639 if (Unsigned)
1640 C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r
1641 else
1642 C67_LDH_PTR(C67_A0, r); // LDH *A0,r
1643 } else if (size == 4) {
1644 C67_LDW_PTR(C67_A0, r); // LDW *A0,r
1645 } else if (size == 8) {
1646 C67_LDDW_PTR(C67_A0, r); // LDDW *A0,r
1649 C67_NOP(4); // NOP 4
1650 return;
1651 } else {
1652 element = size;
1654 // divide offset in bytes to create element index
1655 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1656 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1658 if (size == 1) {
1659 if (Unsigned)
1660 C67_LDBU_SP_A0(r); // LDBU r, SP[A0]
1661 else
1662 C67_LDB_SP_A0(r); // LDB r, SP[A0]
1663 } else if (size == 2) {
1664 if (Unsigned)
1665 C67_LDHU_SP_A0(r); // LDHU r, SP[A0]
1666 else
1667 C67_LDH_SP_A0(r); // LDH r, SP[A0]
1668 } else if (size == 4) {
1669 C67_LDW_SP_A0(r); // LDW r, SP[A0]
1670 } else if (size == 8) {
1671 C67_LDDW_SP_A0(r); // LDDW r, SP[A0]
1675 C67_NOP(4); // NOP 4
1676 return;
1678 } else {
1679 if (v == VT_CONST) {
1680 if (fr & VT_SYM) {
1681 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1682 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1684 C67_MVKL(r, fc); //r=reg to load, constant
1685 C67_MVKH(r, fc); //r=reg to load, constant
1686 } else if (v == VT_LOCAL) {
1687 C67_MVKL(r, fc + 8); //r=reg to load, constant C67 stack points to next free
1688 C67_MVKH(r, fc + 8); //r=reg to load, constant
1689 C67_ADD(C67_FP, r); // MV v,r v -> r
1690 } else if (v == VT_CMP) {
1691 C67_MV(C67_compare_reg, r); // MV v,r v -> r
1692 } else if (v == VT_JMP || v == VT_JMPI) {
1693 t = v & 1;
1694 C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
1695 C67_MVKL(r, t); // r=reg to load, 0 or 1 (do this while branching)
1696 C67_NOP(4); // NOP 4
1697 gsym(fc); // modifies other branches to branch here
1698 C67_MVKL(r, t ^ 1); // r=reg to load, 0 or 1
1699 } else if (v != r) {
1700 C67_MV(v, r); // MV v,r v -> r
1702 if ((ft & VT_BTYPE) == VT_DOUBLE)
1703 C67_MV(v + 1, r + 1); // MV v,r v -> r
1709 /* store register 'r' in lvalue 'v' */
1710 void store(int r, SValue * v)
1712 int fr, bt, ft, fc, size, t, element;
1714 ft = v->type.t;
1715 fc = v->c.i;
1716 fr = v->r & VT_VALMASK;
1717 bt = ft & VT_BTYPE;
1718 /* XXX: incorrect if float reg to reg */
1720 if (bt == VT_LDOUBLE) {
1721 tcc_error("long double not supported");
1722 } else {
1723 if (bt == VT_SHORT)
1724 size = 2;
1725 else if (bt == VT_BYTE)
1726 size = 1;
1727 else if (bt == VT_DOUBLE)
1728 size = 8;
1729 else
1730 size = 4;
1732 if ((v->r & VT_VALMASK) == VT_CONST) {
1733 /* constant memory reference */
1735 if (v->r & VT_SYM) {
1736 greloc(cur_text_section, v->sym, ind, R_C60LO16); // rem the inst need to be patched
1737 greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
1739 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1740 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1742 if (size == 1)
1743 C67_STB_PTR(r, C67_A0); // STB r, *A0
1744 else if (size == 2)
1745 C67_STH_PTR(r, C67_A0); // STH r, *A0
1746 else if (size == 4 || size == 8)
1747 C67_STW_PTR(r, C67_A0); // STW r, *A0
1749 if (size == 8)
1750 C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1); // STW r, *+A0[1]
1751 } else if ((v->r & VT_VALMASK) == VT_LOCAL) {
1752 // check case of storing to passed argument that
1753 // tcc thinks is on the stack but for C67 is
1754 // passed as a reg. However it may have been
1755 // saved to the stack, if that reg was required
1756 // for a call to a child function
1758 if (fc > 0) // argument ??
1760 // walk through sizes and figure which param
1762 int stack_pos = 8;
1764 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1765 if (fc == stack_pos)
1766 break;
1768 stack_pos += TranslateStackToReg[t];
1771 // param has been pushed on stack, get it like a local var
1772 fc = ParamLocOnStack[t] - 8;
1775 if (size == 8)
1776 element = 4;
1777 else
1778 element = size;
1780 // divide offset in bytes to create word index
1781 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1782 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1786 if (size == 1)
1787 C67_STB_SP_A0(r); // STB r, SP[A0]
1788 else if (size == 2)
1789 C67_STH_SP_A0(r); // STH r, SP[A0]
1790 else if (size == 4 || size == 8)
1791 C67_STW_SP_A0(r); // STW r, SP[A0]
1793 if (size == 8) {
1794 C67_ADDK(1, C67_A0); // ADDK 1,A0
1795 C67_STW_SP_A0(r + 1); // STW r, SP[A0]
1797 } else {
1798 if (size == 1)
1799 C67_STB_PTR(r, fr); // STB r, *fr
1800 else if (size == 2)
1801 C67_STH_PTR(r, fr); // STH r, *fr
1802 else if (size == 4 || size == 8)
1803 C67_STW_PTR(r, fr); // STW r, *fr
1805 if (size == 8) {
1806 C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1]
1812 /* 'is_jmp' is '1' if it is a jump */
1813 static void gcall_or_jmp(int is_jmp)
1815 int r;
1816 Sym *sym;
1818 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1819 /* constant case */
1820 if (vtop->r & VT_SYM) {
1821 /* relocation case */
1823 // get add into A0, then start the jump B3
1825 greloc(cur_text_section, vtop->sym, ind, R_C60LO16); // rem the inst need to be patched
1826 greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
1828 C67_MVKL(C67_A0, 0); //r=reg to load, constant
1829 C67_MVKH(C67_A0, 0); //r=reg to load, constant
1830 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // B.S2x A0
1832 if (is_jmp) {
1833 C67_NOP(5); // simple jump, just put NOP
1834 } else {
1835 // Call, must load return address into B3 during delay slots
1837 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1838 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1839 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1840 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1841 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1842 C67_NOP(3); // put remaining NOPs
1844 } else {
1845 /* put an empty PC32 relocation */
1846 ALWAYS_ASSERT(FALSE);
1848 } else {
1849 /* otherwise, indirect call */
1850 r = gv(RC_INT);
1851 C67_IREG_B_REG(0, C67_CREG_ZERO, r); // B.S2x r
1853 if (is_jmp) {
1854 C67_NOP(5); // simple jump, just put NOP
1855 } else {
1856 // Call, must load return address into B3 during delay slots
1858 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1859 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1860 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1861 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1862 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1863 C67_NOP(3); // put remaining NOPs
1868 /* Return the number of registers needed to return the struct, or 0 if
1869 returning via struct pointer. */
1870 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
1871 *ret_align = 1; // Never have to re-align return values for x86-64
1872 return 0;
1875 /* generate function call with address in (vtop->t, vtop->c) and free function
1876 context. Stack entry is popped */
1877 void gfunc_call(int nb_args)
1879 int i, r, size = 0;
1880 int args_sizes[NoCallArgsPassedOnStack];
1882 if (nb_args > NoCallArgsPassedOnStack) {
1883 tcc_error("more than 10 function params not currently supported");
1884 // handle more than 10, put some on the stack
1887 for (i = 0; i < nb_args; i++) {
1888 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1889 ALWAYS_ASSERT(FALSE);
1890 } else {
1891 /* simple type (currently always same size) */
1892 /* XXX: implicit cast ? */
1895 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1896 tcc_error("long long not supported");
1897 } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
1898 tcc_error("long double not supported");
1899 } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1900 size = 8;
1901 } else {
1902 size = 4;
1905 // put the parameter into the corresponding reg (pair)
1907 r = gv(RC_C67_A4 << (2 * i));
1909 // must put on stack because with 1 pass compiler , no way to tell
1910 // if an up coming nested call might overwrite these regs
1912 C67_PUSH(r);
1914 if (size == 8) {
1915 C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3); // STW r, *+SP[3] (go back and put the other)
1917 args_sizes[i] = size;
1919 vtop--;
1921 // POP all the params on the stack into registers for the
1922 // immediate call (in reverse order)
1924 for (i = nb_args - 1; i >= 0; i--) {
1926 if (args_sizes[i] == 8)
1927 C67_POP_DW(TREG_C67_A4 + i * 2);
1928 else
1929 C67_POP(TREG_C67_A4 + i * 2);
1931 gcall_or_jmp(0);
1932 vtop--;
1936 // to be compatible with Code Composer for the C67
1937 // the first 10 parameters must be passed in registers
1938 // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1939 // ending with B12:B13.
1941 // When a call is made, if the caller has its parameters
1942 // in regs A4-B13 these must be saved before/as the call
1943 // parameters are loaded and restored upon return (or if/when needed).
1945 /* generate function prolog of type 't' */
1946 void gfunc_prolog(CType * func_type)
1948 int addr, align, size, func_call, i;
1949 Sym *sym;
1950 CType *type;
1952 sym = func_type->ref;
1953 func_call = sym->r;
1954 addr = 8;
1955 /* if the function returns a structure, then add an
1956 implicit pointer parameter */
1957 func_vt = sym->type;
1958 func_var = (sym->c == FUNC_ELLIPSIS);
1959 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1960 func_vc = addr;
1961 addr += 4;
1964 NoOfCurFuncArgs = 0;
1966 /* define parameters */
1967 while ((sym = sym->next) != NULL) {
1968 type = &sym->type;
1969 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
1970 size = type_size(type, &align);
1971 size = (size + 3) & ~3;
1973 // keep track of size of arguments so
1974 // we can translate where tcc thinks they
1975 // are on the stack into the appropriate reg
1977 TranslateStackToReg[NoOfCurFuncArgs] = size;
1978 NoOfCurFuncArgs++;
1980 #ifdef FUNC_STRUCT_PARAM_AS_PTR
1981 /* structs are passed as pointer */
1982 if ((type->t & VT_BTYPE) == VT_STRUCT) {
1983 size = 4;
1985 #endif
1986 addr += size;
1988 func_ret_sub = 0;
1989 /* pascal type call ? */
1990 if (func_call == FUNC_STDCALL)
1991 func_ret_sub = addr - 8;
1993 C67_MV(C67_FP, C67_A0); // move FP -> A0
1994 C67_MV(C67_SP, C67_FP); // move SP -> FP
1996 // place all the args passed in regs onto the stack
1998 loc = 0;
1999 for (i = 0; i < NoOfCurFuncArgs; i++) {
2001 ParamLocOnStack[i] = loc; // remember where the param is
2002 loc += -8;
2004 C67_PUSH(TREG_C67_A4 + i * 2);
2006 if (TranslateStackToReg[i] == 8) {
2007 C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3); // STW r, *+SP[1] (go back and put the other)
2011 TotalBytesPushedOnStack = -loc;
2013 func_sub_sp_offset = ind; // remember where we put the stack instruction
2014 C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily)
2016 C67_PUSH(C67_A0);
2017 C67_PUSH(C67_B3);
2020 /* generate function epilog */
2021 void gfunc_epilog(void)
2024 int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2025 C67_POP(C67_B3);
2026 C67_NOP(4); // NOP wait for load
2027 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3
2028 C67_POP(C67_FP);
2029 C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP
2030 C67_Adjust_ADDK((int *) (cur_text_section->data +
2031 func_sub_sp_offset),
2032 -local + TotalBytesPushedOnStack);
2033 C67_NOP(3); // NOP
2037 /* generate a jump to a label */
2038 int gjmp(int t)
2040 int ind1 = ind;
2042 C67_MVKL(C67_A0, t); //r=reg to load, constant
2043 C67_MVKH(C67_A0, t); //r=reg to load, constant
2044 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // [!R] B.S2x A0
2045 C67_NOP(5);
2046 return ind1;
2049 /* generate a jump to a fixed address */
2050 void gjmp_addr(int a)
2052 Sym *sym;
2053 // I guess this routine is used for relative short
2054 // local jumps, for now just handle it as the general
2055 // case
2057 // define a label that will be relocated
2059 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
2060 greloc(cur_text_section, sym, ind, R_C60LO16);
2061 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
2063 gjmp(0); // place a zero there later the symbol will be added to it
2066 /* generate a test. set 'inv' to invert test. Stack entry is popped */
2067 int gtst(int inv, int t)
2069 int ind1, n;
2070 int v, *p;
2072 v = vtop->r & VT_VALMASK;
2073 if (v == VT_CMP) {
2074 /* fast case : can jump directly since flags are set */
2075 // C67 uses B2 sort of as flags register
2076 ind1 = ind;
2077 C67_MVKL(C67_A0, t); //r=reg to load, constant
2078 C67_MVKH(C67_A0, t); //r=reg to load, constant
2080 if (C67_compare_reg != TREG_EAX && // check if not already in a conditional test reg
2081 C67_compare_reg != TREG_EDX &&
2082 C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
2083 C67_MV(C67_compare_reg, C67_B2);
2084 C67_compare_reg = C67_B2;
2087 C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x A0
2088 C67_NOP(5);
2089 t = ind1; //return where we need to patch
2091 } else if (v == VT_JMP || v == VT_JMPI) {
2092 /* && or || optimization */
2093 if ((v & 1) == inv) {
2094 /* insert vtop->c jump list in t */
2096 // I guess the idea is to traverse to the
2097 // null at the end of the list and store t
2098 // there
2100 n = vtop->c.i;
2101 while (n != 0) {
2102 p = (int *) (cur_text_section->data + n);
2104 // extract 32 bit address from MVKH/MVKL
2105 n = ((*p >> 7) & 0xffff);
2106 n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2108 *p |= (t & 0xffff) << 7;
2109 *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2110 t = vtop->c.i;
2112 } else {
2113 t = gjmp(t);
2114 gsym(vtop->c.i);
2117 vtop--;
2118 return t;
2121 /* generate an integer binary operation */
2122 void gen_opi(int op)
2124 int r, fr, opc, t;
2126 switch (op) {
2127 case '+':
2128 case TOK_ADDC1: /* add with carry generation */
2129 opc = 0;
2130 gen_op8:
2133 // C67 can't do const compares, must load into a reg
2134 // so just go to gv2 directly - tktk
2138 if (op >= TOK_ULT && op <= TOK_GT)
2139 gv2(RC_INT_BSIDE, RC_INT); // make sure r (src1) is on the B Side of CPU
2140 else
2141 gv2(RC_INT, RC_INT);
2143 r = vtop[-1].r;
2144 fr = vtop[0].r;
2146 C67_compare_reg = C67_B2;
2149 if (op == TOK_LT) {
2150 C67_CMPLT(r, fr, C67_B2);
2151 C67_invert_test = FALSE;
2152 } else if (op == TOK_GE) {
2153 C67_CMPLT(r, fr, C67_B2);
2154 C67_invert_test = TRUE;
2155 } else if (op == TOK_GT) {
2156 C67_CMPGT(r, fr, C67_B2);
2157 C67_invert_test = FALSE;
2158 } else if (op == TOK_LE) {
2159 C67_CMPGT(r, fr, C67_B2);
2160 C67_invert_test = TRUE;
2161 } else if (op == TOK_EQ) {
2162 C67_CMPEQ(r, fr, C67_B2);
2163 C67_invert_test = FALSE;
2164 } else if (op == TOK_NE) {
2165 C67_CMPEQ(r, fr, C67_B2);
2166 C67_invert_test = TRUE;
2167 } else if (op == TOK_ULT) {
2168 C67_CMPLTU(r, fr, C67_B2);
2169 C67_invert_test = FALSE;
2170 } else if (op == TOK_UGE) {
2171 C67_CMPLTU(r, fr, C67_B2);
2172 C67_invert_test = TRUE;
2173 } else if (op == TOK_UGT) {
2174 C67_CMPGTU(r, fr, C67_B2);
2175 C67_invert_test = FALSE;
2176 } else if (op == TOK_ULE) {
2177 C67_CMPGTU(r, fr, C67_B2);
2178 C67_invert_test = TRUE;
2179 } else if (op == '+')
2180 C67_ADD(fr, r); // ADD r,fr,r
2181 else if (op == '-')
2182 C67_SUB(fr, r); // SUB r,fr,r
2183 else if (op == '&')
2184 C67_AND(fr, r); // AND r,fr,r
2185 else if (op == '|')
2186 C67_OR(fr, r); // OR r,fr,r
2187 else if (op == '^')
2188 C67_XOR(fr, r); // XOR r,fr,r
2189 else
2190 ALWAYS_ASSERT(FALSE);
2192 vtop--;
2193 if (op >= TOK_ULT && op <= TOK_GT) {
2194 vtop->r = VT_CMP;
2195 vtop->c.i = op;
2197 break;
2198 case '-':
2199 case TOK_SUBC1: /* sub with carry generation */
2200 opc = 5;
2201 goto gen_op8;
2202 case TOK_ADDC2: /* add with carry use */
2203 opc = 2;
2204 goto gen_op8;
2205 case TOK_SUBC2: /* sub with carry use */
2206 opc = 3;
2207 goto gen_op8;
2208 case '&':
2209 opc = 4;
2210 goto gen_op8;
2211 case '^':
2212 opc = 6;
2213 goto gen_op8;
2214 case '|':
2215 opc = 1;
2216 goto gen_op8;
2217 case '*':
2218 case TOK_UMULL:
2219 gv2(RC_INT, RC_INT);
2220 r = vtop[-1].r;
2221 fr = vtop[0].r;
2222 vtop--;
2223 C67_MPYI(fr, r); // 32 bit bultiply fr,r,fr
2224 C67_NOP(8); // NOP 8 for worst case
2225 break;
2226 case TOK_SHL:
2227 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2228 r = vtop[-1].r;
2229 fr = vtop[0].r;
2230 vtop--;
2231 C67_SHL(fr, r); // arithmetic/logical shift
2232 break;
2234 case TOK_SHR:
2235 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2236 r = vtop[-1].r;
2237 fr = vtop[0].r;
2238 vtop--;
2239 C67_SHRU(fr, r); // logical shift
2240 break;
2242 case TOK_SAR:
2243 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2244 r = vtop[-1].r;
2245 fr = vtop[0].r;
2246 vtop--;
2247 C67_SHR(fr, r); // arithmetic shift
2248 break;
2250 case '/':
2251 t = TOK__divi;
2252 call_func:
2253 vswap();
2254 /* call generic idiv function */
2255 vpush_global_sym(&func_old_type, t);
2256 vrott(3);
2257 gfunc_call(2);
2258 vpushi(0);
2259 vtop->r = REG_IRET;
2260 vtop->r2 = VT_CONST;
2261 break;
2262 case TOK_UDIV:
2263 case TOK_PDIV:
2264 t = TOK__divu;
2265 goto call_func;
2266 case '%':
2267 t = TOK__remi;
2268 goto call_func;
2269 case TOK_UMOD:
2270 t = TOK__remu;
2271 goto call_func;
2273 default:
2274 opc = 7;
2275 goto gen_op8;
2279 /* generate a floating point operation 'v = t1 op t2' instruction. The
2280 two operands are guaranted to have the same floating point type */
2281 /* XXX: need to use ST1 too */
2282 void gen_opf(int op)
2284 int ft, fc, fr, r;
2286 if (op >= TOK_ULT && op <= TOK_GT)
2287 gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
2288 else
2289 gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
2291 ft = vtop->type.t;
2292 fc = vtop->c.i;
2293 r = vtop->r;
2294 fr = vtop[-1].r;
2297 if ((ft & VT_BTYPE) == VT_LDOUBLE)
2298 tcc_error("long doubles not supported");
2300 if (op >= TOK_ULT && op <= TOK_GT) {
2302 r = vtop[-1].r;
2303 fr = vtop[0].r;
2305 C67_compare_reg = C67_B2;
2307 if (op == TOK_LT) {
2308 if ((ft & VT_BTYPE) == VT_DOUBLE)
2309 C67_CMPLTDP(r, fr, C67_B2);
2310 else
2311 C67_CMPLTSP(r, fr, C67_B2);
2313 C67_invert_test = FALSE;
2314 } else if (op == TOK_GE) {
2315 if ((ft & VT_BTYPE) == VT_DOUBLE)
2316 C67_CMPLTDP(r, fr, C67_B2);
2317 else
2318 C67_CMPLTSP(r, fr, C67_B2);
2320 C67_invert_test = TRUE;
2321 } else if (op == TOK_GT) {
2322 if ((ft & VT_BTYPE) == VT_DOUBLE)
2323 C67_CMPGTDP(r, fr, C67_B2);
2324 else
2325 C67_CMPGTSP(r, fr, C67_B2);
2327 C67_invert_test = FALSE;
2328 } else if (op == TOK_LE) {
2329 if ((ft & VT_BTYPE) == VT_DOUBLE)
2330 C67_CMPGTDP(r, fr, C67_B2);
2331 else
2332 C67_CMPGTSP(r, fr, C67_B2);
2334 C67_invert_test = TRUE;
2335 } else if (op == TOK_EQ) {
2336 if ((ft & VT_BTYPE) == VT_DOUBLE)
2337 C67_CMPEQDP(r, fr, C67_B2);
2338 else
2339 C67_CMPEQSP(r, fr, C67_B2);
2341 C67_invert_test = FALSE;
2342 } else if (op == TOK_NE) {
2343 if ((ft & VT_BTYPE) == VT_DOUBLE)
2344 C67_CMPEQDP(r, fr, C67_B2);
2345 else
2346 C67_CMPEQSP(r, fr, C67_B2);
2348 C67_invert_test = TRUE;
2349 } else {
2350 ALWAYS_ASSERT(FALSE);
2352 vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2
2353 } else {
2354 if (op == '+') {
2355 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2356 C67_ADDDP(r, fr); // ADD fr,r,fr
2357 C67_NOP(6);
2358 } else {
2359 C67_ADDSP(r, fr); // ADD fr,r,fr
2360 C67_NOP(3);
2362 vtop--;
2363 } else if (op == '-') {
2364 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2365 C67_SUBDP(r, fr); // SUB fr,r,fr
2366 C67_NOP(6);
2367 } else {
2368 C67_SUBSP(r, fr); // SUB fr,r,fr
2369 C67_NOP(3);
2371 vtop--;
2372 } else if (op == '*') {
2373 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2374 C67_MPYDP(r, fr); // MPY fr,r,fr
2375 C67_NOP(9);
2376 } else {
2377 C67_MPYSP(r, fr); // MPY fr,r,fr
2378 C67_NOP(3);
2380 vtop--;
2381 } else if (op == '/') {
2382 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2383 // must call intrinsic DP floating point divide
2384 vswap();
2385 /* call generic idiv function */
2386 vpush_global_sym(&func_old_type, TOK__divd);
2387 vrott(3);
2388 gfunc_call(2);
2389 vpushi(0);
2390 vtop->r = REG_FRET;
2391 vtop->r2 = REG_LRET;
2393 } else {
2394 // must call intrinsic SP floating point divide
2395 vswap();
2396 /* call generic idiv function */
2397 vpush_global_sym(&func_old_type, TOK__divf);
2398 vrott(3);
2399 gfunc_call(2);
2400 vpushi(0);
2401 vtop->r = REG_FRET;
2402 vtop->r2 = VT_CONST;
2404 } else
2405 ALWAYS_ASSERT(FALSE);
2412 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2413 and 'long long' cases. */
2414 void gen_cvt_itof(int t)
2416 int r;
2418 gv(RC_INT);
2419 r = vtop->r;
2421 if ((t & VT_BTYPE) == VT_DOUBLE) {
2422 if (t & VT_UNSIGNED)
2423 C67_INTDPU(r, r);
2424 else
2425 C67_INTDP(r, r);
2427 C67_NOP(4);
2428 vtop->type.t = VT_DOUBLE;
2429 } else {
2430 if (t & VT_UNSIGNED)
2431 C67_INTSPU(r, r);
2432 else
2433 C67_INTSP(r, r);
2434 C67_NOP(3);
2435 vtop->type.t = VT_FLOAT;
2440 /* convert fp to int 't' type */
2441 /* XXX: handle long long case */
2442 void gen_cvt_ftoi(int t)
2444 int r;
2446 gv(RC_FLOAT);
2447 r = vtop->r;
2449 if (t != VT_INT)
2450 tcc_error("long long not supported");
2451 else {
2452 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2453 C67_DPTRUNC(r, r);
2454 C67_NOP(3);
2455 } else {
2456 C67_SPTRUNC(r, r);
2457 C67_NOP(3);
2460 vtop->type.t = VT_INT;
2465 /* convert from one floating point type to another */
2466 void gen_cvt_ftof(int t)
2468 int r, r2;
2470 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2471 (t & VT_BTYPE) == VT_FLOAT) {
2472 // convert double to float
2474 gv(RC_FLOAT); // get it in a register pair
2476 r = vtop->r;
2478 C67_DPSP(r, r); // convert it to SP same register
2479 C67_NOP(3);
2481 vtop->type.t = VT_FLOAT;
2482 vtop->r2 = VT_CONST; // set this as unused
2483 } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
2484 (t & VT_BTYPE) == VT_DOUBLE) {
2485 // convert float to double
2487 gv(RC_FLOAT); // get it in a register
2489 r = vtop->r;
2491 if (r == TREG_EAX) { // make sure the paired reg is avail
2492 r2 = get_reg(RC_ECX);
2493 } else if (r == TREG_EDX) {
2494 r2 = get_reg(RC_ST0);
2495 } else {
2496 ALWAYS_ASSERT(FALSE);
2497 r2 = 0; /* avoid warning */
2500 C67_SPDP(r, r); // convert it to DP same register
2501 C67_NOP(1);
2503 vtop->type.t = VT_DOUBLE;
2504 vtop->r2 = r2; // set this as unused
2505 } else {
2506 ALWAYS_ASSERT(FALSE);
2510 /* computed goto support */
2511 void ggoto(void)
2513 gcall_or_jmp(1);
2514 vtop--;
2517 /* Save the stack pointer onto the stack and return the location of its address */
2518 ST_FUNC void gen_vla_sp_save(int addr) {
2519 tcc_error("variable length arrays unsupported for this target");
2522 /* Restore the SP from a location on the stack */
2523 ST_FUNC void gen_vla_sp_restore(int addr) {
2524 tcc_error("variable length arrays unsupported for this target");
2527 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2528 ST_FUNC void gen_vla_alloc(CType *type, int align) {
2529 tcc_error("variable length arrays unsupported for this target");
2532 /* end of C67 code generator */
2533 /*************************************************************/
2534 #endif
2535 /*************************************************************/