final update for 0.9.27
[tinycc.git] / c67-gen.c
blobbcb4b0e3e5422784e312b0a318b28566fbaf3d4d
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 void gsym(int t)
231 gsym_addr(t, ind);
234 // these are regs that tcc doesn't really know about,
235 // but assign them unique values so the mapping routines
236 // can distinguish them
238 #define C67_A0 105
239 #define C67_SP 106
240 #define C67_B3 107
241 #define C67_FP 108
242 #define C67_B2 109
243 #define C67_CREG_ZERO -1 /* Special code for no condition reg test */
246 int ConvertRegToRegClass(int r)
248 // only works for A4-B13
250 return RC_C67_A4 << (r - TREG_C67_A4);
254 // map TCC reg to C67 reg number
256 int C67_map_regn(int r)
258 if (r == 0) // normal tcc regs
259 return 0x2; // A2
260 else if (r == 1) // normal tcc regs
261 return 3; // A3
262 else if (r == 2) // normal tcc regs
263 return 0; // B0
264 else if (r == 3) // normal tcc regs
265 return 1; // B1
266 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
267 return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
268 else if (r == C67_A0)
269 return 0; // set to A0 (offset reg)
270 else if (r == C67_B2)
271 return 2; // set to B2 (offset reg)
272 else if (r == C67_B3)
273 return 3; // set to B3 (return address reg)
274 else if (r == C67_SP)
275 return 15; // set to SP (B15) (offset reg)
276 else if (r == C67_FP)
277 return 15; // set to FP (A15) (offset reg)
278 else if (r == C67_CREG_ZERO)
279 return 0; // Special code for no condition reg test
280 else
281 ALWAYS_ASSERT(FALSE);
283 return 0;
286 // mapping from tcc reg number to
287 // C67 register to condition code field
289 // valid condition code regs are:
291 // tcc reg 2 ->B0 -> 1
292 // tcc reg 3 ->B1 -> 2
293 // tcc reg 0 -> A2 -> 5
294 // tcc reg 1 -> A3 -> X
295 // tcc reg B2 -> 3
297 int C67_map_regc(int r)
299 if (r == 0) // normal tcc regs
300 return 0x5;
301 else if (r == 2) // normal tcc regs
302 return 0x1;
303 else if (r == 3) // normal tcc regs
304 return 0x2;
305 else if (r == C67_B2) // normal tcc regs
306 return 0x3;
307 else if (r == C67_CREG_ZERO)
308 return 0; // Special code for no condition reg test
309 else
310 ALWAYS_ASSERT(FALSE);
312 return 0;
316 // map TCC reg to C67 reg side A or B
318 int C67_map_regs(int r)
320 if (r == 0) // normal tcc regs
321 return 0x0;
322 else if (r == 1) // normal tcc regs
323 return 0x0;
324 else if (r == 2) // normal tcc regs
325 return 0x1;
326 else if (r == 3) // normal tcc regs
327 return 0x1;
328 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
329 return (r & 2) >> 1;
330 else if (r == C67_A0)
331 return 0; // set to A side
332 else if (r == C67_B2)
333 return 1; // set to B side
334 else if (r == C67_B3)
335 return 1; // set to B side
336 else if (r == C67_SP)
337 return 0x1; // set to SP (B15) B side
338 else if (r == C67_FP)
339 return 0x0; // set to FP (A15) A side
340 else
341 ALWAYS_ASSERT(FALSE);
343 return 0;
346 int C67_map_S12(char *s)
348 if (strstr(s, ".S1") != NULL)
349 return 0;
350 else if (strcmp(s, ".S2"))
351 return 1;
352 else
353 ALWAYS_ASSERT(FALSE);
355 return 0;
358 int C67_map_D12(char *s)
360 if (strstr(s, ".D1") != NULL)
361 return 0;
362 else if (strcmp(s, ".D2"))
363 return 1;
364 else
365 ALWAYS_ASSERT(FALSE);
367 return 0;
372 void C67_asm(char *s, int a, int b, int c)
374 BOOL xpath;
376 #ifdef ASSEMBLY_LISTING_C67
377 if (!f) {
378 f = fopen("TCC67_out.txt", "wt");
380 fprintf(f, "%04X ", ind);
381 #endif
383 if (strstr(s, "MVKL") == s) {
384 C67_g((C67_map_regn(b) << 23) |
385 ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
386 } else if (strstr(s, "MVKH") == s) {
387 C67_g((C67_map_regn(b) << 23) |
388 (((a >> 16) & 0xffff) << 7) |
389 (0x1a << 2) | (C67_map_regs(b) << 1));
390 } else if (strstr(s, "STW.D SP POST DEC") == s) {
391 C67_g((C67_map_regn(a) << 23) | //src
392 (15 << 18) | //SP B15
393 (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
394 (0xa << 9) | //mode a = post dec ucst
395 (0 << 8) | //r (LDDW bit 0)
396 (1 << 7) | //y D1/D2 use B side
397 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
398 (1 << 2) | //opcode
399 (C67_map_regs(a) << 1) | //side of src
400 (0 << 0)); //parallel
401 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
402 C67_g((C67_map_regn(a) << 23) | //src
403 (15 << 18) | //base reg A15
404 (0 << 13) | //offset reg A0
405 (5 << 9) | //mode 5 = pos offset, base reg + off reg
406 (0 << 8) | //r (LDDW bit 0)
407 (0 << 7) | //y D1/D2 A side
408 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
409 (1 << 2) | //opcode
410 (C67_map_regs(a) << 1) | //side of src
411 (0 << 0)); //parallel
412 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
413 C67_g((C67_map_regn(a) << 23) | //src
414 (15 << 18) | //base reg A15
415 (0 << 13) | //offset reg A0
416 (5 << 9) | //mode 5 = pos offset, base reg + off reg
417 (0 << 8) | //r (LDDW bit 0)
418 (0 << 7) | //y D1/D2 A side
419 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
420 (1 << 2) | //opcode
421 (C67_map_regs(a) << 1) | //side of src
422 (0 << 0)); //parallel
423 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
424 C67_g((C67_map_regn(a) << 23) | //src
425 (15 << 18) | //base reg A15
426 (0 << 13) | //offset reg A0
427 (5 << 9) | //mode 5 = pos offset, base reg + off reg
428 (0 << 8) | //r (LDDW bit 0)
429 (0 << 7) | //y D1/D2 A side
430 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
431 (1 << 2) | //opcode
432 (C67_map_regs(a) << 1) | //side of src
433 (0 << 0)); //parallel
434 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
435 C67_g((C67_map_regn(a) << 23) | //src
436 (15 << 18) | //base reg A15
437 (0 << 13) | //offset reg A0
438 (5 << 9) | //mode 5 = pos offset, base reg + off reg
439 (0 << 8) | //r (LDDW bit 0)
440 (0 << 7) | //y D1/D2 A side
441 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
442 (1 << 2) | //opcode
443 (C67_map_regs(a) << 1) | //side of src
444 (0 << 0)); //parallel
445 } else if (strstr(s, "STW.D *+SP[A0]") == s) {
446 C67_g((C67_map_regn(a) << 23) | //src
447 (15 << 18) | //base reg A15
448 (0 << 13) | //offset reg A0
449 (5 << 9) | //mode 5 = pos offset, base reg + off reg
450 (0 << 8) | //r (LDDW bit 0)
451 (0 << 7) | //y D1/D2 A side
452 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
453 (1 << 2) | //opcode
454 (C67_map_regs(a) << 1) | //side of src
455 (0 << 0)); //parallel
456 } else if (strstr(s, "STW.D *") == s) {
457 C67_g((C67_map_regn(a) << 23) | //src
458 (C67_map_regn(b) << 18) | //base reg A0
459 (0 << 13) | //cst5
460 (1 << 9) | //mode 1 = pos cst offset
461 (0 << 8) | //r (LDDW bit 0)
462 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
463 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
464 (1 << 2) | //opcode
465 (C67_map_regs(a) << 1) | //side of src
466 (0 << 0)); //parallel
467 } else if (strstr(s, "STH.D *") == s) {
468 C67_g((C67_map_regn(a) << 23) | //src
469 (C67_map_regn(b) << 18) | //base reg A0
470 (0 << 13) | //cst5
471 (1 << 9) | //mode 1 = pos cst offset
472 (0 << 8) | //r (LDDW bit 0)
473 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
474 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
475 (1 << 2) | //opcode
476 (C67_map_regs(a) << 1) | //side of src
477 (0 << 0)); //parallel
478 } else if (strstr(s, "STB.D *") == s) {
479 C67_g((C67_map_regn(a) << 23) | //src
480 (C67_map_regn(b) << 18) | //base reg A0
481 (0 << 13) | //cst5
482 (1 << 9) | //mode 1 = pos cst offset
483 (0 << 8) | //r (LDDW bit 0)
484 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
485 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
486 (1 << 2) | //opcode
487 (C67_map_regs(a) << 1) | //side of src
488 (0 << 0)); //parallel
489 } else if (strstr(s, "STW.D +*") == s) {
490 ALWAYS_ASSERT(c < 32);
491 C67_g((C67_map_regn(a) << 23) | //src
492 (C67_map_regn(b) << 18) | //base reg A0
493 (c << 13) | //cst5
494 (1 << 9) | //mode 1 = pos cst offset
495 (0 << 8) | //r (LDDW bit 0)
496 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
497 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
498 (1 << 2) | //opcode
499 (C67_map_regs(a) << 1) | //side of src
500 (0 << 0)); //parallel
501 } else if (strstr(s, "LDW.D SP PRE INC") == s) {
502 C67_g((C67_map_regn(a) << 23) | //dst
503 (15 << 18) | //base reg B15
504 (2 << 13) | //ucst5 (must keep 8 byte boundary)
505 (9 << 9) | //mode 9 = pre inc ucst5
506 (0 << 8) | //r (LDDW bit 0)
507 (1 << 7) | //y D1/D2 B side
508 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
509 (1 << 2) | //opcode
510 (C67_map_regs(a) << 1) | //side of dst
511 (0 << 0)); //parallel
512 } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
513 C67_g((C67_map_regn(a) << 23) | //dst
514 (15 << 18) | //base reg B15
515 (1 << 13) | //ucst5 (must keep 8 byte boundary)
516 (9 << 9) | //mode 9 = pre inc ucst5
517 (1 << 8) | //r (LDDW bit 1)
518 (1 << 7) | //y D1/D2 B side
519 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
520 (1 << 2) | //opcode
521 (C67_map_regs(a) << 1) | //side of dst
522 (0 << 0)); //parallel
523 } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
524 C67_g((C67_map_regn(a) << 23) | //dst
525 (15 << 18) | //base reg A15
526 (0 << 13) | //offset reg A0
527 (5 << 9) | //mode 5 = pos offset, base reg + off reg
528 (0 << 8) | //r (LDDW bit 0)
529 (0 << 7) | //y D1/D2 A side
530 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
531 (1 << 2) | //opcode
532 (C67_map_regs(a) << 1) | //side of dst
533 (0 << 0)); //parallel
534 } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
535 C67_g((C67_map_regn(a) << 23) | //dst
536 (15 << 18) | //base reg A15
537 (0 << 13) | //offset reg A0
538 (5 << 9) | //mode 5 = pos offset, base reg + off reg
539 (1 << 8) | //r (LDDW bit 1)
540 (0 << 7) | //y D1/D2 A side
541 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
542 (1 << 2) | //opcode
543 (C67_map_regs(a) << 1) | //side of dst
544 (0 << 0)); //parallel
545 } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
546 C67_g((C67_map_regn(a) << 23) | //dst
547 (15 << 18) | //base reg A15
548 (0 << 13) | //offset reg A0
549 (5 << 9) | //mode 5 = pos offset, base reg + off reg
550 (0 << 8) | //r (LDDW bit 0)
551 (0 << 7) | //y D1/D2 A side
552 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
553 (1 << 2) | //opcode
554 (C67_map_regs(a) << 1) | //side of dst
555 (0 << 0)); //parallel
556 } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
557 C67_g((C67_map_regn(a) << 23) | //dst
558 (15 << 18) | //base reg A15
559 (0 << 13) | //offset reg A0
560 (5 << 9) | //mode 5 = pos offset, base reg + off reg
561 (0 << 8) | //r (LDDW bit 0)
562 (0 << 7) | //y D1/D2 A side
563 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
564 (1 << 2) | //opcode
565 (C67_map_regs(a) << 1) | //side of dst
566 (0 << 0)); //parallel
567 } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
568 C67_g((C67_map_regn(a) << 23) | //dst
569 (15 << 18) | //base reg A15
570 (0 << 13) | //offset reg A0
571 (5 << 9) | //mode 5 = pos offset, base reg + off reg
572 (0 << 8) | //r (LDDW bit 0)
573 (0 << 7) | //y D1/D2 A side
574 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
575 (1 << 2) | //opcode
576 (C67_map_regs(a) << 1) | //side of dst
577 (0 << 0)); //parallel
578 } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
579 C67_g((C67_map_regn(a) << 23) | //dst
580 (15 << 18) | //base reg A15
581 (0 << 13) | //offset reg A0
582 (5 << 9) | //mode 5 = pos offset, base reg + off reg
583 (0 << 8) | //r (LDDW bit 0)
584 (0 << 7) | //y D1/D2 A side
585 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
586 (1 << 2) | //opcode
587 (C67_map_regs(a) << 1) | //side of dst
588 (0 << 0)); //parallel
589 } else if (strstr(s, "LDW.D *") == s) {
590 C67_g((C67_map_regn(b) << 23) | //dst
591 (C67_map_regn(a) << 18) | //base reg A15
592 (0 << 13) | //cst5
593 (1 << 9) | //mode 1 = pos cst offset
594 (0 << 8) | //r (LDDW bit 0)
595 (C67_map_regs(a) << 7) | //y D1/D2 src side
596 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
597 (1 << 2) | //opcode
598 (C67_map_regs(b) << 1) | //side of dst
599 (0 << 0)); //parallel
600 } else if (strstr(s, "LDDW.D *") == s) {
601 C67_g((C67_map_regn(b) << 23) | //dst
602 (C67_map_regn(a) << 18) | //base reg A15
603 (0 << 13) | //cst5
604 (1 << 9) | //mode 1 = pos cst offset
605 (1 << 8) | //r (LDDW bit 1)
606 (C67_map_regs(a) << 7) | //y D1/D2 src side
607 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
608 (1 << 2) | //opcode
609 (C67_map_regs(b) << 1) | //side of dst
610 (0 << 0)); //parallel
611 } else if (strstr(s, "LDH.D *") == s) {
612 C67_g((C67_map_regn(b) << 23) | //dst
613 (C67_map_regn(a) << 18) | //base reg A15
614 (0 << 13) | //cst5
615 (1 << 9) | //mode 1 = pos cst offset
616 (0 << 8) | //r (LDDW bit 0)
617 (C67_map_regs(a) << 7) | //y D1/D2 src side
618 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
619 (1 << 2) | //opcode
620 (C67_map_regs(b) << 1) | //side of dst
621 (0 << 0)); //parallel
622 } else if (strstr(s, "LDB.D *") == s) {
623 C67_g((C67_map_regn(b) << 23) | //dst
624 (C67_map_regn(a) << 18) | //base reg A15
625 (0 << 13) | //cst5
626 (1 << 9) | //mode 1 = pos cst offset
627 (0 << 8) | //r (LDDW bit 0)
628 (C67_map_regs(a) << 7) | //y D1/D2 src side
629 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
630 (1 << 2) | //opcode
631 (C67_map_regs(b) << 1) | //side of dst
632 (0 << 0)); //parallel
633 } else if (strstr(s, "LDHU.D *") == s) {
634 C67_g((C67_map_regn(b) << 23) | //dst
635 (C67_map_regn(a) << 18) | //base reg A15
636 (0 << 13) | //cst5
637 (1 << 9) | //mode 1 = pos cst offset
638 (0 << 8) | //r (LDDW bit 0)
639 (C67_map_regs(a) << 7) | //y D1/D2 src side
640 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
641 (1 << 2) | //opcode
642 (C67_map_regs(b) << 1) | //side of dst
643 (0 << 0)); //parallel
644 } else if (strstr(s, "LDBU.D *") == s) {
645 C67_g((C67_map_regn(b) << 23) | //dst
646 (C67_map_regn(a) << 18) | //base reg A15
647 (0 << 13) | //cst5
648 (1 << 9) | //mode 1 = pos cst offset
649 (0 << 8) | //r (LDDW bit 0)
650 (C67_map_regs(a) << 7) | //y D1/D2 src side
651 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
652 (1 << 2) | //opcode
653 (C67_map_regs(b) << 1) | //side of dst
654 (0 << 0)); //parallel
655 } else if (strstr(s, "LDW.D +*") == s) {
656 C67_g((C67_map_regn(b) << 23) | //dst
657 (C67_map_regn(a) << 18) | //base reg A15
658 (1 << 13) | //cst5
659 (1 << 9) | //mode 1 = pos cst offset
660 (0 << 8) | //r (LDDW bit 0)
661 (C67_map_regs(a) << 7) | //y D1/D2 src side
662 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
663 (1 << 2) | //opcode
664 (C67_map_regs(b) << 1) | //side of dst
665 (0 << 0)); //parallel
666 } else if (strstr(s, "CMPLTSP") == s) {
667 xpath = C67_map_regs(a) ^ C67_map_regs(b);
668 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
670 C67_g((C67_map_regn(c) << 23) | //dst
671 (C67_map_regn(b) << 18) | //src2
672 (C67_map_regn(a) << 13) | //src1
673 (xpath << 12) | //x use cross path for src2
674 (0x3a << 6) | //opcode
675 (0x8 << 2) | //opcode fixed
676 (C67_map_regs(c) << 1) | //side for reg c
677 (0 << 0)); //parallel
678 } else if (strstr(s, "CMPGTSP") == s) {
679 xpath = C67_map_regs(a) ^ C67_map_regs(b);
680 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
682 C67_g((C67_map_regn(c) << 23) | //dst
683 (C67_map_regn(b) << 18) | //src2
684 (C67_map_regn(a) << 13) | //src1
685 (xpath << 12) | //x use cross path for src2
686 (0x39 << 6) | //opcode
687 (0x8 << 2) | //opcode fixed
688 (C67_map_regs(c) << 1) | //side for reg c
689 (0 << 0)); //parallel
690 } else if (strstr(s, "CMPEQSP") == s) {
691 xpath = C67_map_regs(a) ^ C67_map_regs(b);
692 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
694 C67_g((C67_map_regn(c) << 23) | //dst
695 (C67_map_regn(b) << 18) | //src2
696 (C67_map_regn(a) << 13) | //src1
697 (xpath << 12) | //x use cross path for src2
698 (0x38 << 6) | //opcode
699 (0x8 << 2) | //opcode fixed
700 (C67_map_regs(c) << 1) | //side for reg c
701 (0 << 0)); //parallel
704 else if (strstr(s, "CMPLTDP") == s) {
705 xpath = C67_map_regs(a) ^ C67_map_regs(b);
706 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
708 C67_g((C67_map_regn(c) << 23) | //dst
709 (C67_map_regn(b) << 18) | //src2
710 (C67_map_regn(a) << 13) | //src1
711 (xpath << 12) | //x use cross path for src2
712 (0x2a << 6) | //opcode
713 (0x8 << 2) | //opcode fixed
714 (C67_map_regs(c) << 1) | //side for reg c
715 (0 << 0)); //parallel
716 } else if (strstr(s, "CMPGTDP") == s) {
717 xpath = C67_map_regs(a) ^ C67_map_regs(b);
718 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
720 C67_g((C67_map_regn(c) << 23) | //dst
721 (C67_map_regn(b) << 18) | //src2
722 (C67_map_regn(a) << 13) | //src1
723 (xpath << 12) | //x use cross path for src2
724 (0x29 << 6) | //opcode
725 (0x8 << 2) | //opcode fixed
726 (C67_map_regs(c) << 1) | //side for reg c
727 (0 << 0)); //parallel
728 } else if (strstr(s, "CMPEQDP") == s) {
729 xpath = C67_map_regs(a) ^ C67_map_regs(b);
730 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
732 C67_g((C67_map_regn(c) << 23) | //dst
733 (C67_map_regn(b) << 18) | //src2
734 (C67_map_regn(a) << 13) | //src1
735 (xpath << 12) | //x use cross path for src2
736 (0x28 << 6) | //opcode
737 (0x8 << 2) | //opcode fixed
738 (C67_map_regs(c) << 1) | //side for reg c
739 (0 << 0)); //parallel
740 } else if (strstr(s, "CMPLT") == s) {
741 xpath = C67_map_regs(a) ^ C67_map_regs(b);
742 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
744 C67_g((C67_map_regn(c) << 23) | //dst
745 (C67_map_regn(b) << 18) | //src2
746 (C67_map_regn(a) << 13) | //src1
747 (xpath << 12) | //x use cross path for src2
748 (0x57 << 5) | //opcode
749 (0x6 << 2) | //opcode fixed
750 (C67_map_regs(c) << 1) | //side for reg c
751 (0 << 0)); //parallel
752 } else if (strstr(s, "CMPGT") == s) {
753 xpath = C67_map_regs(a) ^ C67_map_regs(b);
754 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
756 C67_g((C67_map_regn(c) << 23) | //dst
757 (C67_map_regn(b) << 18) | //src2
758 (C67_map_regn(a) << 13) | //src1
759 (xpath << 12) | //x use cross path for src2
760 (0x47 << 5) | //opcode
761 (0x6 << 2) | //opcode fixed
762 (C67_map_regs(c) << 1) | //side for reg c
763 (0 << 0)); //parallel
764 } else if (strstr(s, "CMPEQ") == s) {
765 xpath = C67_map_regs(a) ^ C67_map_regs(b);
766 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
768 C67_g((C67_map_regn(c) << 23) | //dst
769 (C67_map_regn(b) << 18) | //src2
770 (C67_map_regn(a) << 13) | //src1
771 (xpath << 12) | //x use cross path for src2
772 (0x53 << 5) | //opcode
773 (0x6 << 2) | //opcode fixed
774 (C67_map_regs(c) << 1) | //side for reg c
775 (0 << 0)); //parallel
776 } else if (strstr(s, "CMPLTU") == s) {
777 xpath = C67_map_regs(a) ^ C67_map_regs(b);
778 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
780 C67_g((C67_map_regn(c) << 23) | //dst
781 (C67_map_regn(b) << 18) | //src2
782 (C67_map_regn(a) << 13) | //src1
783 (xpath << 12) | //x use cross path for src2
784 (0x5f << 5) | //opcode
785 (0x6 << 2) | //opcode fixed
786 (C67_map_regs(c) << 1) | //side for reg c
787 (0 << 0)); //parallel
788 } else if (strstr(s, "CMPGTU") == s) {
789 xpath = C67_map_regs(a) ^ C67_map_regs(b);
790 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
792 C67_g((C67_map_regn(c) << 23) | //dst
793 (C67_map_regn(b) << 18) | //src2
794 (C67_map_regn(a) << 13) | //src1
795 (xpath << 12) | //x use cross path for src2
796 (0x4f << 5) | //opcode
797 (0x6 << 2) | //opcode fixed
798 (C67_map_regs(c) << 1) | //side for reg c
799 (0 << 0)); //parallel
800 } else if (strstr(s, "B DISP") == s) {
801 C67_g((0 << 29) | //creg
802 (0 << 28) | //z
803 (a << 7) | //cnst
804 (0x4 << 2) | //opcode fixed
805 (0 << 1) | //S0/S1
806 (0 << 0)); //parallel
807 } else if (strstr(s, "B.") == s) {
808 xpath = C67_map_regs(c) ^ 1;
810 C67_g((C67_map_regc(b) << 29) | //creg
811 (a << 28) | //inv
812 (0 << 23) | //dst
813 (C67_map_regn(c) << 18) | //src2
814 (0 << 13) | //
815 (xpath << 12) | //x cross path if !B side
816 (0xd << 6) | //opcode
817 (0x8 << 2) | //opcode fixed
818 (1 << 1) | //must be S2
819 (0 << 0)); //parallel
820 } else if (strstr(s, "MV.L") == s) {
821 xpath = C67_map_regs(b) ^ C67_map_regs(c);
823 C67_g((0 << 29) | //creg
824 (0 << 28) | //inv
825 (C67_map_regn(c) << 23) | //dst
826 (C67_map_regn(b) << 18) | //src2
827 (0 << 13) | //src1 (cst5)
828 (xpath << 12) | //x cross path if opposite sides
829 (0x2 << 5) | //opcode
830 (0x6 << 2) | //opcode fixed
831 (C67_map_regs(c) << 1) | //side of dest
832 (0 << 0)); //parallel
833 } else if (strstr(s, "SPTRUNC.L") == s) {
834 xpath = C67_map_regs(b) ^ C67_map_regs(c);
836 C67_g((0 << 29) | //creg
837 (0 << 28) | //inv
838 (C67_map_regn(c) << 23) | //dst
839 (C67_map_regn(b) << 18) | //src2
840 (0 << 13) | //src1 NA
841 (xpath << 12) | //x cross path if opposite sides
842 (0xb << 5) | //opcode
843 (0x6 << 2) | //opcode fixed
844 (C67_map_regs(c) << 1) | //side of dest
845 (0 << 0)); //parallel
846 } else if (strstr(s, "DPTRUNC.L") == s) {
847 xpath = C67_map_regs(b) ^ C67_map_regs(c);
849 C67_g((0 << 29) | //creg
850 (0 << 28) | //inv
851 (C67_map_regn(c) << 23) | //dst
852 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
853 (0 << 13) | //src1 NA
854 (xpath << 12) | //x cross path if opposite sides
855 (0x1 << 5) | //opcode
856 (0x6 << 2) | //opcode fixed
857 (C67_map_regs(c) << 1) | //side of dest
858 (0 << 0)); //parallel
859 } else if (strstr(s, "INTSP.L") == s) {
860 xpath = C67_map_regs(b) ^ C67_map_regs(c);
862 C67_g((0 << 29) | //creg
863 (0 << 28) | //inv
864 (C67_map_regn(c) << 23) | //dst
865 (C67_map_regn(b) << 18) | //src2
866 (0 << 13) | //src1 NA
867 (xpath << 12) | //x cross path if opposite sides
868 (0x4a << 5) | //opcode
869 (0x6 << 2) | //opcode fixed
870 (C67_map_regs(c) << 1) | //side of dest
871 (0 << 0)); //parallel
872 } else if (strstr(s, "INTSPU.L") == s) {
873 xpath = C67_map_regs(b) ^ C67_map_regs(c);
875 C67_g((0 << 29) | //creg
876 (0 << 28) | //inv
877 (C67_map_regn(c) << 23) | //dst
878 (C67_map_regn(b) << 18) | //src2
879 (0 << 13) | //src1 NA
880 (xpath << 12) | //x cross path if opposite sides
881 (0x49 << 5) | //opcode
882 (0x6 << 2) | //opcode fixed
883 (C67_map_regs(c) << 1) | //side of dest
884 (0 << 0)); //parallel
885 } else if (strstr(s, "INTDP.L") == s) {
886 xpath = C67_map_regs(b) ^ C67_map_regs(c);
888 C67_g((0 << 29) | //creg
889 (0 << 28) | //inv
890 (C67_map_regn(c) << 23) | //dst
891 (C67_map_regn(b) << 18) | //src2
892 (0 << 13) | //src1 NA
893 (xpath << 12) | //x cross path if opposite sides
894 (0x39 << 5) | //opcode
895 (0x6 << 2) | //opcode fixed
896 (C67_map_regs(c) << 1) | //side of dest
897 (0 << 0)); //parallel
898 } else if (strstr(s, "INTDPU.L") == s) {
899 xpath = C67_map_regs(b) ^ C67_map_regs(c);
901 C67_g((0 << 29) | //creg
902 (0 << 28) | //inv
903 (C67_map_regn(c) << 23) | //dst
904 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
905 (0 << 13) | //src1 NA
906 (xpath << 12) | //x cross path if opposite sides
907 (0x3b << 5) | //opcode
908 (0x6 << 2) | //opcode fixed
909 (C67_map_regs(c) << 1) | //side of dest
910 (0 << 0)); //parallel
911 } else if (strstr(s, "SPDP.L") == s) {
912 xpath = C67_map_regs(b) ^ C67_map_regs(c);
914 C67_g((0 << 29) | //creg
915 (0 << 28) | //inv
916 (C67_map_regn(c) << 23) | //dst
917 (C67_map_regn(b) << 18) | //src2
918 (0 << 13) | //src1 NA
919 (xpath << 12) | //x cross path if opposite sides
920 (0x2 << 6) | //opcode
921 (0x8 << 2) | //opcode fixed
922 (C67_map_regs(c) << 1) | //side of dest
923 (0 << 0)); //parallel
924 } else if (strstr(s, "DPSP.L") == s) {
925 ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
927 C67_g((0 << 29) | //creg
928 (0 << 28) | //inv
929 (C67_map_regn(c) << 23) | //dst
930 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
931 (0 << 13) | //src1 NA
932 (0 << 12) | //x cross path if opposite sides
933 (0x9 << 5) | //opcode
934 (0x6 << 2) | //opcode fixed
935 (C67_map_regs(c) << 1) | //side of dest
936 (0 << 0)); //parallel
937 } else if (strstr(s, "ADD.L") == s) {
938 xpath = C67_map_regs(b) ^ C67_map_regs(c);
940 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
942 C67_g((0 << 29) | //creg
943 (0 << 28) | //inv
944 (C67_map_regn(c) << 23) | //dst
945 (C67_map_regn(b) << 18) | //src2 (possible x path)
946 (C67_map_regn(a) << 13) | //src1
947 (xpath << 12) | //x cross path if opposite sides
948 (0x3 << 5) | //opcode
949 (0x6 << 2) | //opcode fixed
950 (C67_map_regs(c) << 1) | //side of dest
951 (0 << 0)); //parallel
952 } else if (strstr(s, "SUB.L") == s) {
953 xpath = C67_map_regs(b) ^ C67_map_regs(c);
955 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
957 C67_g((0 << 29) | //creg
958 (0 << 28) | //inv
959 (C67_map_regn(c) << 23) | //dst
960 (C67_map_regn(b) << 18) | //src2 (possible x path)
961 (C67_map_regn(a) << 13) | //src1
962 (xpath << 12) | //x cross path if opposite sides
963 (0x7 << 5) | //opcode
964 (0x6 << 2) | //opcode fixed
965 (C67_map_regs(c) << 1) | //side of dest
966 (0 << 0)); //parallel
967 } else if (strstr(s, "OR.L") == s) {
968 xpath = C67_map_regs(b) ^ C67_map_regs(c);
970 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
972 C67_g((0 << 29) | //creg
973 (0 << 28) | //inv
974 (C67_map_regn(c) << 23) | //dst
975 (C67_map_regn(b) << 18) | //src2 (possible x path)
976 (C67_map_regn(a) << 13) | //src1
977 (xpath << 12) | //x cross path if opposite sides
978 (0x7f << 5) | //opcode
979 (0x6 << 2) | //opcode fixed
980 (C67_map_regs(c) << 1) | //side of dest
981 (0 << 0)); //parallel
982 } else if (strstr(s, "AND.L") == s) {
983 xpath = C67_map_regs(b) ^ C67_map_regs(c);
985 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
987 C67_g((0 << 29) | //creg
988 (0 << 28) | //inv
989 (C67_map_regn(c) << 23) | //dst
990 (C67_map_regn(b) << 18) | //src2 (possible x path)
991 (C67_map_regn(a) << 13) | //src1
992 (xpath << 12) | //x cross path if opposite sides
993 (0x7b << 5) | //opcode
994 (0x6 << 2) | //opcode fixed
995 (C67_map_regs(c) << 1) | //side of dest
996 (0 << 0)); //parallel
997 } else if (strstr(s, "XOR.L") == s) {
998 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1000 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1002 C67_g((0 << 29) | //creg
1003 (0 << 28) | //inv
1004 (C67_map_regn(c) << 23) | //dst
1005 (C67_map_regn(b) << 18) | //src2 (possible x path)
1006 (C67_map_regn(a) << 13) | //src1
1007 (xpath << 12) | //x cross path if opposite sides
1008 (0x6f << 5) | //opcode
1009 (0x6 << 2) | //opcode fixed
1010 (C67_map_regs(c) << 1) | //side of dest
1011 (0 << 0)); //parallel
1012 } else if (strstr(s, "ADDSP.L") == s) {
1013 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1015 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1017 C67_g((0 << 29) | //creg
1018 (0 << 28) | //inv
1019 (C67_map_regn(c) << 23) | //dst
1020 (C67_map_regn(b) << 18) | //src2 (possible x path)
1021 (C67_map_regn(a) << 13) | //src1
1022 (xpath << 12) | //x cross path if opposite sides
1023 (0x10 << 5) | //opcode
1024 (0x6 << 2) | //opcode fixed
1025 (C67_map_regs(c) << 1) | //side of dest
1026 (0 << 0)); //parallel
1027 } else if (strstr(s, "ADDDP.L") == s) {
1028 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1030 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1032 C67_g((0 << 29) | //creg
1033 (0 << 28) | //inv
1034 (C67_map_regn(c) << 23) | //dst
1035 (C67_map_regn(b) << 18) | //src2 (possible x path)
1036 (C67_map_regn(a) << 13) | //src1
1037 (xpath << 12) | //x cross path if opposite sides
1038 (0x18 << 5) | //opcode
1039 (0x6 << 2) | //opcode fixed
1040 (C67_map_regs(c) << 1) | //side of dest
1041 (0 << 0)); //parallel
1042 } else if (strstr(s, "SUBSP.L") == s) {
1043 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1045 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1047 C67_g((0 << 29) | //creg
1048 (0 << 28) | //inv
1049 (C67_map_regn(c) << 23) | //dst
1050 (C67_map_regn(b) << 18) | //src2 (possible x path)
1051 (C67_map_regn(a) << 13) | //src1
1052 (xpath << 12) | //x cross path if opposite sides
1053 (0x11 << 5) | //opcode
1054 (0x6 << 2) | //opcode fixed
1055 (C67_map_regs(c) << 1) | //side of dest
1056 (0 << 0)); //parallel
1057 } else if (strstr(s, "SUBDP.L") == s) {
1058 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1060 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1062 C67_g((0 << 29) | //creg
1063 (0 << 28) | //inv
1064 (C67_map_regn(c) << 23) | //dst
1065 (C67_map_regn(b) << 18) | //src2 (possible x path)
1066 (C67_map_regn(a) << 13) | //src1
1067 (xpath << 12) | //x cross path if opposite sides
1068 (0x19 << 5) | //opcode
1069 (0x6 << 2) | //opcode fixed
1070 (C67_map_regs(c) << 1) | //side of dest
1071 (0 << 0)); //parallel
1072 } else if (strstr(s, "MPYSP.M") == s) {
1073 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1075 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1077 C67_g((0 << 29) | //creg
1078 (0 << 28) | //inv
1079 (C67_map_regn(c) << 23) | //dst
1080 (C67_map_regn(b) << 18) | //src2 (possible x path)
1081 (C67_map_regn(a) << 13) | //src1
1082 (xpath << 12) | //x cross path if opposite sides
1083 (0x1c << 7) | //opcode
1084 (0x0 << 2) | //opcode fixed
1085 (C67_map_regs(c) << 1) | //side of dest
1086 (0 << 0)); //parallel
1087 } else if (strstr(s, "MPYDP.M") == s) {
1088 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1090 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1092 C67_g((0 << 29) | //creg
1093 (0 << 28) | //inv
1094 (C67_map_regn(c) << 23) | //dst
1095 (C67_map_regn(b) << 18) | //src2 (possible x path)
1096 (C67_map_regn(a) << 13) | //src1
1097 (xpath << 12) | //x cross path if opposite sides
1098 (0x0e << 7) | //opcode
1099 (0x0 << 2) | //opcode fixed
1100 (C67_map_regs(c) << 1) | //side of dest
1101 (0 << 0)); //parallel
1102 } else if (strstr(s, "MPYI.M") == s) {
1103 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1105 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1107 C67_g((0 << 29) | //creg
1108 (0 << 28) | //inv
1109 (C67_map_regn(c) << 23) | //dst
1110 (C67_map_regn(b) << 18) | //src2
1111 (C67_map_regn(a) << 13) | //src1 (cst5)
1112 (xpath << 12) | //x cross path if opposite sides
1113 (0x4 << 7) | //opcode
1114 (0x0 << 2) | //opcode fixed
1115 (C67_map_regs(c) << 1) | //side of dest
1116 (0 << 0)); //parallel
1117 } else if (strstr(s, "SHR.S") == s) {
1118 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1120 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1122 C67_g((0 << 29) | //creg
1123 (0 << 28) | //inv
1124 (C67_map_regn(c) << 23) | //dst
1125 (C67_map_regn(b) << 18) | //src2
1126 (C67_map_regn(a) << 13) | //src1
1127 (xpath << 12) | //x cross path if opposite sides
1128 (0x37 << 6) | //opcode
1129 (0x8 << 2) | //opcode fixed
1130 (C67_map_regs(c) << 1) | //side of dest
1131 (0 << 0)); //parallel
1132 } else if (strstr(s, "SHRU.S") == s) {
1133 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1135 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1137 C67_g((0 << 29) | //creg
1138 (0 << 28) | //inv
1139 (C67_map_regn(c) << 23) | //dst
1140 (C67_map_regn(b) << 18) | //src2
1141 (C67_map_regn(a) << 13) | //src1
1142 (xpath << 12) | //x cross path if opposite sides
1143 (0x27 << 6) | //opcode
1144 (0x8 << 2) | //opcode fixed
1145 (C67_map_regs(c) << 1) | //side of dest
1146 (0 << 0)); //parallel
1147 } else if (strstr(s, "SHL.S") == s) {
1148 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1150 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1152 C67_g((0 << 29) | //creg
1153 (0 << 28) | //inv
1154 (C67_map_regn(c) << 23) | //dst
1155 (C67_map_regn(b) << 18) | //src2
1156 (C67_map_regn(a) << 13) | //src1
1157 (xpath << 12) | //x cross path if opposite sides
1158 (0x33 << 6) | //opcode
1159 (0x8 << 2) | //opcode fixed
1160 (C67_map_regs(c) << 1) | //side of dest
1161 (0 << 0)); //parallel
1162 } else if (strstr(s, "||ADDK") == s) {
1163 xpath = 0; // no xpath required just use the side of the src/dst
1165 C67_g((0 << 29) | //creg
1166 (0 << 28) | //inv
1167 (C67_map_regn(b) << 23) | //dst
1168 (a << 07) | //scst16
1169 (0x14 << 2) | //opcode fixed
1170 (C67_map_regs(b) << 1) | //side of dst
1171 (1 << 0)); //parallel
1172 } else if (strstr(s, "ADDK") == s) {
1173 xpath = 0; // no xpath required just use the side of the src/dst
1175 C67_g((0 << 29) | //creg
1176 (0 << 28) | //inv
1177 (C67_map_regn(b) << 23) | //dst
1178 (a << 07) | //scst16
1179 (0x14 << 2) | //opcode fixed
1180 (C67_map_regs(b) << 1) | //side of dst
1181 (0 << 0)); //parallel
1182 } else if (strstr(s, "NOP") == s) {
1183 C67_g(((a - 1) << 13) | //no of cycles
1184 (0 << 0)); //parallel
1185 } else
1186 ALWAYS_ASSERT(FALSE);
1188 #ifdef ASSEMBLY_LISTING_C67
1189 fprintf(f, " %s %d %d %d\n", s, a, b, c);
1190 #endif
1194 //r=reg to load, fr=from reg, symbol for relocation, constant
1196 void C67_MVKL(int r, int fc)
1198 C67_asm("MVKL.", fc, r, 0);
1201 void C67_MVKH(int r, int fc)
1203 C67_asm("MVKH.", fc, r, 0);
1206 void C67_STB_SP_A0(int r)
1208 C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB r,*+SP[A0]
1211 void C67_STH_SP_A0(int r)
1213 C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH r,*+SP[A0]
1216 void C67_STW_SP_A0(int r)
1218 C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW r,*+SP[A0]
1221 void C67_STB_PTR(int r, int r2)
1223 C67_asm("STB.D *", r, r2, 0); // STB r, *r2
1226 void C67_STH_PTR(int r, int r2)
1228 C67_asm("STH.D *", r, r2, 0); // STH r, *r2
1231 void C67_STW_PTR(int r, int r2)
1233 C67_asm("STW.D *", r, r2, 0); // STW r, *r2
1236 void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1238 C67_asm("STW.D +*", r, r2, n); // STW r, *+r2
1241 void C67_PUSH(int r)
1243 C67_asm("STW.D SP POST DEC", r, 0, 0); // STW r,*SP--
1246 void C67_LDW_SP_A0(int r)
1248 C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW *+SP[A0],r
1251 void C67_LDDW_SP_A0(int r)
1253 C67_asm("LDDW.D *+SP[A0]", r, 0, 0); // LDDW *+SP[A0],r
1256 void C67_LDH_SP_A0(int r)
1258 C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH *+SP[A0],r
1261 void C67_LDB_SP_A0(int r)
1263 C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB *+SP[A0],r
1266 void C67_LDHU_SP_A0(int r)
1268 C67_asm("LDHU.D *+SP[A0]", r, 0, 0); // LDHU *+SP[A0],r
1271 void C67_LDBU_SP_A0(int r)
1273 C67_asm("LDBU.D *+SP[A0]", r, 0, 0); // LDBU *+SP[A0],r
1276 void C67_LDW_PTR(int r, int r2)
1278 C67_asm("LDW.D *", r, r2, 0); // LDW *r,r2
1281 void C67_LDDW_PTR(int r, int r2)
1283 C67_asm("LDDW.D *", r, r2, 0); // LDDW *r,r2
1286 void C67_LDH_PTR(int r, int r2)
1288 C67_asm("LDH.D *", r, r2, 0); // LDH *r,r2
1291 void C67_LDB_PTR(int r, int r2)
1293 C67_asm("LDB.D *", r, r2, 0); // LDB *r,r2
1296 void C67_LDHU_PTR(int r, int r2)
1298 C67_asm("LDHU.D *", r, r2, 0); // LDHU *r,r2
1301 void C67_LDBU_PTR(int r, int r2)
1303 C67_asm("LDBU.D *", r, r2, 0); // LDBU *r,r2
1306 void C67_LDW_PTR_PRE_INC(int r, int r2)
1308 C67_asm("LDW.D +*", r, r2, 0); // LDW *+r,r2
1311 void C67_POP(int r)
1313 C67_asm("LDW.D SP PRE INC", r, 0, 0); // LDW *++SP,r
1316 void C67_POP_DW(int r)
1318 C67_asm("LDDW.D SP PRE INC", r, 0, 0); // LDDW *++SP,r
1321 void C67_CMPLT(int s1, int s2, int dst)
1323 C67_asm("CMPLT.L1", s1, s2, dst);
1326 void C67_CMPGT(int s1, int s2, int dst)
1328 C67_asm("CMPGT.L1", s1, s2, dst);
1331 void C67_CMPEQ(int s1, int s2, int dst)
1333 C67_asm("CMPEQ.L1", s1, s2, dst);
1336 void C67_CMPLTU(int s1, int s2, int dst)
1338 C67_asm("CMPLTU.L1", s1, s2, dst);
1341 void C67_CMPGTU(int s1, int s2, int dst)
1343 C67_asm("CMPGTU.L1", s1, s2, dst);
1347 void C67_CMPLTSP(int s1, int s2, int dst)
1349 C67_asm("CMPLTSP.S1", s1, s2, dst);
1352 void C67_CMPGTSP(int s1, int s2, int dst)
1354 C67_asm("CMPGTSP.S1", s1, s2, dst);
1357 void C67_CMPEQSP(int s1, int s2, int dst)
1359 C67_asm("CMPEQSP.S1", s1, s2, dst);
1362 void C67_CMPLTDP(int s1, int s2, int dst)
1364 C67_asm("CMPLTDP.S1", s1, s2, dst);
1367 void C67_CMPGTDP(int s1, int s2, int dst)
1369 C67_asm("CMPGTDP.S1", s1, s2, dst);
1372 void C67_CMPEQDP(int s1, int s2, int dst)
1374 C67_asm("CMPEQDP.S1", s1, s2, dst);
1378 void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2
1380 C67_asm("B.S2", inv, r1, r2);
1384 // call with how many 32 bit words to skip
1385 // (0 would branch to the branch instruction)
1387 void C67_B_DISP(int disp) // B +2 Branch with constant displacement
1389 // Branch point is relative to the 8 word fetch packet
1391 // we will assume the text section always starts on an 8 word (32 byte boundary)
1393 // so add in how many words into the fetch packet the branch is
1396 C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1399 void C67_NOP(int n)
1401 C67_asm("NOP", n, 0, 0);
1404 void C67_ADDK(int n, int r)
1406 ALWAYS_ASSERT(abs(n) < 32767);
1408 C67_asm("ADDK", n, r, 0);
1411 void C67_ADDK_PARALLEL(int n, int r)
1413 ALWAYS_ASSERT(abs(n) < 32767);
1415 C67_asm("||ADDK", n, r, 0);
1418 void C67_Adjust_ADDK(int *inst, int n)
1420 ALWAYS_ASSERT(abs(n) < 32767);
1422 *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1425 void C67_MV(int r, int v)
1427 C67_asm("MV.L", 0, r, v);
1431 void C67_DPTRUNC(int r, int v)
1433 C67_asm("DPTRUNC.L", 0, r, v);
1436 void C67_SPTRUNC(int r, int v)
1438 C67_asm("SPTRUNC.L", 0, r, v);
1441 void C67_INTSP(int r, int v)
1443 C67_asm("INTSP.L", 0, r, v);
1446 void C67_INTDP(int r, int v)
1448 C67_asm("INTDP.L", 0, r, v);
1451 void C67_INTSPU(int r, int v)
1453 C67_asm("INTSPU.L", 0, r, v);
1456 void C67_INTDPU(int r, int v)
1458 C67_asm("INTDPU.L", 0, r, v);
1461 void C67_SPDP(int r, int v)
1463 C67_asm("SPDP.L", 0, r, v);
1466 void C67_DPSP(int r, int v) // note regs must be on the same side
1468 C67_asm("DPSP.L", 0, r, v);
1471 void C67_ADD(int r, int v)
1473 C67_asm("ADD.L", v, r, v);
1476 void C67_SUB(int r, int v)
1478 C67_asm("SUB.L", v, r, v);
1481 void C67_AND(int r, int v)
1483 C67_asm("AND.L", v, r, v);
1486 void C67_OR(int r, int v)
1488 C67_asm("OR.L", v, r, v);
1491 void C67_XOR(int r, int v)
1493 C67_asm("XOR.L", v, r, v);
1496 void C67_ADDSP(int r, int v)
1498 C67_asm("ADDSP.L", v, r, v);
1501 void C67_SUBSP(int r, int v)
1503 C67_asm("SUBSP.L", v, r, v);
1506 void C67_MPYSP(int r, int v)
1508 C67_asm("MPYSP.M", v, r, v);
1511 void C67_ADDDP(int r, int v)
1513 C67_asm("ADDDP.L", v, r, v);
1516 void C67_SUBDP(int r, int v)
1518 C67_asm("SUBDP.L", v, r, v);
1521 void C67_MPYDP(int r, int v)
1523 C67_asm("MPYDP.M", v, r, v);
1526 void C67_MPYI(int r, int v)
1528 C67_asm("MPYI.M", v, r, v);
1531 void C67_SHL(int r, int v)
1533 C67_asm("SHL.S", r, v, v);
1536 void C67_SHRU(int r, int v)
1538 C67_asm("SHRU.S", r, v, v);
1541 void C67_SHR(int r, int v)
1543 C67_asm("SHR.S", r, v, v);
1548 /* load 'r' from value 'sv' */
1549 void load(int r, SValue * sv)
1551 int v, t, ft, fc, fr, size = 0, element;
1552 BOOL Unsigned = FALSE;
1553 SValue v1;
1555 fr = sv->r;
1556 ft = sv->type.t;
1557 fc = sv->c.i;
1559 v = fr & VT_VALMASK;
1560 if (fr & VT_LVAL) {
1561 if (v == VT_LLOCAL) {
1562 v1.type.t = VT_INT;
1563 v1.r = VT_LOCAL | VT_LVAL;
1564 v1.c.i = fc;
1565 load(r, &v1);
1566 fr = r;
1567 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
1568 tcc_error("long double not supported");
1569 } else if ((ft & VT_TYPE) == VT_BYTE) {
1570 size = 1;
1571 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1572 size = 1;
1573 Unsigned = TRUE;
1574 } else if ((ft & VT_TYPE) == VT_SHORT) {
1575 size = 2;
1576 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1577 size = 2;
1578 Unsigned = TRUE;
1579 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1580 size = 8;
1581 } else {
1582 size = 4;
1585 // check if fc is a positive reference on the stack,
1586 // if it is tcc is referencing what it thinks is a parameter
1587 // on the stack, so check if it is really in a register.
1590 if (v == VT_LOCAL && fc > 0) {
1591 int stack_pos = 8;
1593 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1594 if (fc == stack_pos)
1595 break;
1597 stack_pos += TranslateStackToReg[t];
1600 // param has been pushed on stack, get it like a local var
1602 fc = ParamLocOnStack[t] - 8;
1605 if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect
1607 if (size == 1) {
1608 if (Unsigned)
1609 C67_LDBU_PTR(v, r); // LDBU *v,r
1610 else
1611 C67_LDB_PTR(v, r); // LDB *v,r
1612 } else if (size == 2) {
1613 if (Unsigned)
1614 C67_LDHU_PTR(v, r); // LDHU *v,r
1615 else
1616 C67_LDH_PTR(v, r); // LDH *v,r
1617 } else if (size == 4) {
1618 C67_LDW_PTR(v, r); // LDW *v,r
1619 } else if (size == 8) {
1620 C67_LDDW_PTR(v, r); // LDDW *v,r
1623 C67_NOP(4); // NOP 4
1624 return;
1625 } else if (fr & VT_SYM) {
1626 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1627 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1630 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1631 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1634 if (size == 1) {
1635 if (Unsigned)
1636 C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r
1637 else
1638 C67_LDB_PTR(C67_A0, r); // LDB *A0,r
1639 } else if (size == 2) {
1640 if (Unsigned)
1641 C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r
1642 else
1643 C67_LDH_PTR(C67_A0, r); // LDH *A0,r
1644 } else if (size == 4) {
1645 C67_LDW_PTR(C67_A0, r); // LDW *A0,r
1646 } else if (size == 8) {
1647 C67_LDDW_PTR(C67_A0, r); // LDDW *A0,r
1650 C67_NOP(4); // NOP 4
1651 return;
1652 } else {
1653 element = size;
1655 // divide offset in bytes to create element index
1656 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1657 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1659 if (size == 1) {
1660 if (Unsigned)
1661 C67_LDBU_SP_A0(r); // LDBU r, SP[A0]
1662 else
1663 C67_LDB_SP_A0(r); // LDB r, SP[A0]
1664 } else if (size == 2) {
1665 if (Unsigned)
1666 C67_LDHU_SP_A0(r); // LDHU r, SP[A0]
1667 else
1668 C67_LDH_SP_A0(r); // LDH r, SP[A0]
1669 } else if (size == 4) {
1670 C67_LDW_SP_A0(r); // LDW r, SP[A0]
1671 } else if (size == 8) {
1672 C67_LDDW_SP_A0(r); // LDDW r, SP[A0]
1676 C67_NOP(4); // NOP 4
1677 return;
1679 } else {
1680 if (v == VT_CONST) {
1681 if (fr & VT_SYM) {
1682 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1683 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1685 C67_MVKL(r, fc); //r=reg to load, constant
1686 C67_MVKH(r, fc); //r=reg to load, constant
1687 } else if (v == VT_LOCAL) {
1688 C67_MVKL(r, fc + 8); //r=reg to load, constant C67 stack points to next free
1689 C67_MVKH(r, fc + 8); //r=reg to load, constant
1690 C67_ADD(C67_FP, r); // MV v,r v -> r
1691 } else if (v == VT_CMP) {
1692 C67_MV(C67_compare_reg, r); // MV v,r v -> r
1693 } else if (v == VT_JMP || v == VT_JMPI) {
1694 t = v & 1;
1695 C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
1696 C67_MVKL(r, t); // r=reg to load, 0 or 1 (do this while branching)
1697 C67_NOP(4); // NOP 4
1698 gsym(fc); // modifies other branches to branch here
1699 C67_MVKL(r, t ^ 1); // r=reg to load, 0 or 1
1700 } else if (v != r) {
1701 C67_MV(v, r); // MV v,r v -> r
1703 if ((ft & VT_BTYPE) == VT_DOUBLE)
1704 C67_MV(v + 1, r + 1); // MV v,r v -> r
1710 /* store register 'r' in lvalue 'v' */
1711 void store(int r, SValue * v)
1713 int fr, bt, ft, fc, size, t, element;
1715 ft = v->type.t;
1716 fc = v->c.i;
1717 fr = v->r & VT_VALMASK;
1718 bt = ft & VT_BTYPE;
1719 /* XXX: incorrect if float reg to reg */
1721 if (bt == VT_LDOUBLE) {
1722 tcc_error("long double not supported");
1723 } else {
1724 if (bt == VT_SHORT)
1725 size = 2;
1726 else if (bt == VT_BYTE)
1727 size = 1;
1728 else if (bt == VT_DOUBLE)
1729 size = 8;
1730 else
1731 size = 4;
1733 if ((v->r & VT_VALMASK) == VT_CONST) {
1734 /* constant memory reference */
1736 if (v->r & VT_SYM) {
1737 greloc(cur_text_section, v->sym, ind, R_C60LO16); // rem the inst need to be patched
1738 greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
1740 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1741 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1743 if (size == 1)
1744 C67_STB_PTR(r, C67_A0); // STB r, *A0
1745 else if (size == 2)
1746 C67_STH_PTR(r, C67_A0); // STH r, *A0
1747 else if (size == 4 || size == 8)
1748 C67_STW_PTR(r, C67_A0); // STW r, *A0
1750 if (size == 8)
1751 C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1); // STW r, *+A0[1]
1752 } else if ((v->r & VT_VALMASK) == VT_LOCAL) {
1753 // check case of storing to passed argument that
1754 // tcc thinks is on the stack but for C67 is
1755 // passed as a reg. However it may have been
1756 // saved to the stack, if that reg was required
1757 // for a call to a child function
1759 if (fc > 0) // argument ??
1761 // walk through sizes and figure which param
1763 int stack_pos = 8;
1765 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1766 if (fc == stack_pos)
1767 break;
1769 stack_pos += TranslateStackToReg[t];
1772 // param has been pushed on stack, get it like a local var
1773 fc = ParamLocOnStack[t] - 8;
1776 if (size == 8)
1777 element = 4;
1778 else
1779 element = size;
1781 // divide offset in bytes to create word index
1782 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1783 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1787 if (size == 1)
1788 C67_STB_SP_A0(r); // STB r, SP[A0]
1789 else if (size == 2)
1790 C67_STH_SP_A0(r); // STH r, SP[A0]
1791 else if (size == 4 || size == 8)
1792 C67_STW_SP_A0(r); // STW r, SP[A0]
1794 if (size == 8) {
1795 C67_ADDK(1, C67_A0); // ADDK 1,A0
1796 C67_STW_SP_A0(r + 1); // STW r, SP[A0]
1798 } else {
1799 if (size == 1)
1800 C67_STB_PTR(r, fr); // STB r, *fr
1801 else if (size == 2)
1802 C67_STH_PTR(r, fr); // STH r, *fr
1803 else if (size == 4 || size == 8)
1804 C67_STW_PTR(r, fr); // STW r, *fr
1806 if (size == 8) {
1807 C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1]
1813 /* 'is_jmp' is '1' if it is a jump */
1814 static void gcall_or_jmp(int is_jmp)
1816 int r;
1817 Sym *sym;
1819 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1820 /* constant case */
1821 if (vtop->r & VT_SYM) {
1822 /* relocation case */
1824 // get add into A0, then start the jump B3
1826 greloc(cur_text_section, vtop->sym, ind, R_C60LO16); // rem the inst need to be patched
1827 greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
1829 C67_MVKL(C67_A0, 0); //r=reg to load, constant
1830 C67_MVKH(C67_A0, 0); //r=reg to load, constant
1831 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // B.S2x A0
1833 if (is_jmp) {
1834 C67_NOP(5); // simple jump, just put NOP
1835 } else {
1836 // Call, must load return address into B3 during delay slots
1838 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1839 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1840 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1841 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1842 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1843 C67_NOP(3); // put remaining NOPs
1845 } else {
1846 /* put an empty PC32 relocation */
1847 ALWAYS_ASSERT(FALSE);
1849 } else {
1850 /* otherwise, indirect call */
1851 r = gv(RC_INT);
1852 C67_IREG_B_REG(0, C67_CREG_ZERO, r); // B.S2x r
1854 if (is_jmp) {
1855 C67_NOP(5); // simple jump, just put NOP
1856 } else {
1857 // Call, must load return address into B3 during delay slots
1859 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1860 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1861 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1862 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1863 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1864 C67_NOP(3); // put remaining NOPs
1869 /* Return the number of registers needed to return the struct, or 0 if
1870 returning via struct pointer. */
1871 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
1872 *ret_align = 1; // Never have to re-align return values for x86-64
1873 return 0;
1876 /* generate function call with address in (vtop->t, vtop->c) and free function
1877 context. Stack entry is popped */
1878 void gfunc_call(int nb_args)
1880 int i, r, size = 0;
1881 int args_sizes[NoCallArgsPassedOnStack];
1883 if (nb_args > NoCallArgsPassedOnStack) {
1884 tcc_error("more than 10 function params not currently supported");
1885 // handle more than 10, put some on the stack
1888 for (i = 0; i < nb_args; i++) {
1889 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1890 ALWAYS_ASSERT(FALSE);
1891 } else {
1892 /* simple type (currently always same size) */
1893 /* XXX: implicit cast ? */
1896 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1897 tcc_error("long long not supported");
1898 } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
1899 tcc_error("long double not supported");
1900 } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1901 size = 8;
1902 } else {
1903 size = 4;
1906 // put the parameter into the corresponding reg (pair)
1908 r = gv(RC_C67_A4 << (2 * i));
1910 // must put on stack because with 1 pass compiler , no way to tell
1911 // if an up coming nested call might overwrite these regs
1913 C67_PUSH(r);
1915 if (size == 8) {
1916 C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3); // STW r, *+SP[3] (go back and put the other)
1918 args_sizes[i] = size;
1920 vtop--;
1922 // POP all the params on the stack into registers for the
1923 // immediate call (in reverse order)
1925 for (i = nb_args - 1; i >= 0; i--) {
1927 if (args_sizes[i] == 8)
1928 C67_POP_DW(TREG_C67_A4 + i * 2);
1929 else
1930 C67_POP(TREG_C67_A4 + i * 2);
1932 gcall_or_jmp(0);
1933 vtop--;
1937 // to be compatible with Code Composer for the C67
1938 // the first 10 parameters must be passed in registers
1939 // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1940 // ending with B12:B13.
1942 // When a call is made, if the caller has its parameters
1943 // in regs A4-B13 these must be saved before/as the call
1944 // parameters are loaded and restored upon return (or if/when needed).
1946 /* generate function prolog of type 't' */
1947 void gfunc_prolog(CType * func_type)
1949 int addr, align, size, func_call, i;
1950 Sym *sym;
1951 CType *type;
1953 sym = func_type->ref;
1954 func_call = sym->f.func_call;
1955 addr = 8;
1956 /* if the function returns a structure, then add an
1957 implicit pointer parameter */
1958 func_vt = sym->type;
1959 func_var = (sym->f.func_type == FUNC_ELLIPSIS);
1960 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1961 func_vc = addr;
1962 addr += 4;
1965 NoOfCurFuncArgs = 0;
1967 /* define parameters */
1968 while ((sym = sym->next) != NULL) {
1969 type = &sym->type;
1970 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
1971 size = type_size(type, &align);
1972 size = (size + 3) & ~3;
1974 // keep track of size of arguments so
1975 // we can translate where tcc thinks they
1976 // are on the stack into the appropriate reg
1978 TranslateStackToReg[NoOfCurFuncArgs] = size;
1979 NoOfCurFuncArgs++;
1981 #ifdef FUNC_STRUCT_PARAM_AS_PTR
1982 /* structs are passed as pointer */
1983 if ((type->t & VT_BTYPE) == VT_STRUCT) {
1984 size = 4;
1986 #endif
1987 addr += size;
1989 func_ret_sub = 0;
1990 /* pascal type call ? */
1991 if (func_call == FUNC_STDCALL)
1992 func_ret_sub = addr - 8;
1994 C67_MV(C67_FP, C67_A0); // move FP -> A0
1995 C67_MV(C67_SP, C67_FP); // move SP -> FP
1997 // place all the args passed in regs onto the stack
1999 loc = 0;
2000 for (i = 0; i < NoOfCurFuncArgs; i++) {
2002 ParamLocOnStack[i] = loc; // remember where the param is
2003 loc += -8;
2005 C67_PUSH(TREG_C67_A4 + i * 2);
2007 if (TranslateStackToReg[i] == 8) {
2008 C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3); // STW r, *+SP[1] (go back and put the other)
2012 TotalBytesPushedOnStack = -loc;
2014 func_sub_sp_offset = ind; // remember where we put the stack instruction
2015 C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily)
2017 C67_PUSH(C67_A0);
2018 C67_PUSH(C67_B3);
2021 /* generate function epilog */
2022 void gfunc_epilog(void)
2025 int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2026 C67_POP(C67_B3);
2027 C67_NOP(4); // NOP wait for load
2028 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3
2029 C67_POP(C67_FP);
2030 C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP
2031 C67_Adjust_ADDK((int *) (cur_text_section->data +
2032 func_sub_sp_offset),
2033 -local + TotalBytesPushedOnStack);
2034 C67_NOP(3); // NOP
2038 /* generate a jump to a label */
2039 int gjmp(int t)
2041 int ind1 = ind;
2042 if (nocode_wanted)
2043 return t;
2045 C67_MVKL(C67_A0, t); //r=reg to load, constant
2046 C67_MVKH(C67_A0, t); //r=reg to load, constant
2047 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // [!R] B.S2x A0
2048 C67_NOP(5);
2049 return ind1;
2052 /* generate a jump to a fixed address */
2053 void gjmp_addr(int a)
2055 Sym *sym;
2056 // I guess this routine is used for relative short
2057 // local jumps, for now just handle it as the general
2058 // case
2060 // define a label that will be relocated
2062 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
2063 greloc(cur_text_section, sym, ind, R_C60LO16);
2064 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
2066 gjmp(0); // place a zero there later the symbol will be added to it
2069 /* generate a test. set 'inv' to invert test. Stack entry is popped */
2070 int gtst(int inv, int t)
2072 int ind1, n;
2073 int v, *p;
2075 v = vtop->r & VT_VALMASK;
2076 if (nocode_wanted) {
2078 } else if (v == VT_CMP) {
2079 /* fast case : can jump directly since flags are set */
2080 // C67 uses B2 sort of as flags register
2081 ind1 = ind;
2082 C67_MVKL(C67_A0, t); //r=reg to load, constant
2083 C67_MVKH(C67_A0, t); //r=reg to load, constant
2085 if (C67_compare_reg != TREG_EAX && // check if not already in a conditional test reg
2086 C67_compare_reg != TREG_EDX &&
2087 C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
2088 C67_MV(C67_compare_reg, C67_B2);
2089 C67_compare_reg = C67_B2;
2092 C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x A0
2093 C67_NOP(5);
2094 t = ind1; //return where we need to patch
2096 } else if (v == VT_JMP || v == VT_JMPI) {
2097 /* && or || optimization */
2098 if ((v & 1) == inv) {
2099 /* insert vtop->c jump list in t */
2101 // I guess the idea is to traverse to the
2102 // null at the end of the list and store t
2103 // there
2105 n = vtop->c.i;
2106 while (n != 0) {
2107 p = (int *) (cur_text_section->data + n);
2109 // extract 32 bit address from MVKH/MVKL
2110 n = ((*p >> 7) & 0xffff);
2111 n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2113 *p |= (t & 0xffff) << 7;
2114 *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2115 t = vtop->c.i;
2117 } else {
2118 t = gjmp(t);
2119 gsym(vtop->c.i);
2122 vtop--;
2123 return t;
2126 /* generate an integer binary operation */
2127 void gen_opi(int op)
2129 int r, fr, opc, t;
2131 switch (op) {
2132 case '+':
2133 case TOK_ADDC1: /* add with carry generation */
2134 opc = 0;
2135 gen_op8:
2138 // C67 can't do const compares, must load into a reg
2139 // so just go to gv2 directly - tktk
2143 if (op >= TOK_ULT && op <= TOK_GT)
2144 gv2(RC_INT_BSIDE, RC_INT); // make sure r (src1) is on the B Side of CPU
2145 else
2146 gv2(RC_INT, RC_INT);
2148 r = vtop[-1].r;
2149 fr = vtop[0].r;
2151 C67_compare_reg = C67_B2;
2154 if (op == TOK_LT) {
2155 C67_CMPLT(r, fr, C67_B2);
2156 C67_invert_test = FALSE;
2157 } else if (op == TOK_GE) {
2158 C67_CMPLT(r, fr, C67_B2);
2159 C67_invert_test = TRUE;
2160 } else if (op == TOK_GT) {
2161 C67_CMPGT(r, fr, C67_B2);
2162 C67_invert_test = FALSE;
2163 } else if (op == TOK_LE) {
2164 C67_CMPGT(r, fr, C67_B2);
2165 C67_invert_test = TRUE;
2166 } else if (op == TOK_EQ) {
2167 C67_CMPEQ(r, fr, C67_B2);
2168 C67_invert_test = FALSE;
2169 } else if (op == TOK_NE) {
2170 C67_CMPEQ(r, fr, C67_B2);
2171 C67_invert_test = TRUE;
2172 } else if (op == TOK_ULT) {
2173 C67_CMPLTU(r, fr, C67_B2);
2174 C67_invert_test = FALSE;
2175 } else if (op == TOK_UGE) {
2176 C67_CMPLTU(r, fr, C67_B2);
2177 C67_invert_test = TRUE;
2178 } else if (op == TOK_UGT) {
2179 C67_CMPGTU(r, fr, C67_B2);
2180 C67_invert_test = FALSE;
2181 } else if (op == TOK_ULE) {
2182 C67_CMPGTU(r, fr, C67_B2);
2183 C67_invert_test = TRUE;
2184 } else if (op == '+')
2185 C67_ADD(fr, r); // ADD r,fr,r
2186 else if (op == '-')
2187 C67_SUB(fr, r); // SUB r,fr,r
2188 else if (op == '&')
2189 C67_AND(fr, r); // AND r,fr,r
2190 else if (op == '|')
2191 C67_OR(fr, r); // OR r,fr,r
2192 else if (op == '^')
2193 C67_XOR(fr, r); // XOR r,fr,r
2194 else
2195 ALWAYS_ASSERT(FALSE);
2197 vtop--;
2198 if (op >= TOK_ULT && op <= TOK_GT) {
2199 vtop->r = VT_CMP;
2200 vtop->c.i = op;
2202 break;
2203 case '-':
2204 case TOK_SUBC1: /* sub with carry generation */
2205 opc = 5;
2206 goto gen_op8;
2207 case TOK_ADDC2: /* add with carry use */
2208 opc = 2;
2209 goto gen_op8;
2210 case TOK_SUBC2: /* sub with carry use */
2211 opc = 3;
2212 goto gen_op8;
2213 case '&':
2214 opc = 4;
2215 goto gen_op8;
2216 case '^':
2217 opc = 6;
2218 goto gen_op8;
2219 case '|':
2220 opc = 1;
2221 goto gen_op8;
2222 case '*':
2223 case TOK_UMULL:
2224 gv2(RC_INT, RC_INT);
2225 r = vtop[-1].r;
2226 fr = vtop[0].r;
2227 vtop--;
2228 C67_MPYI(fr, r); // 32 bit multiply fr,r,fr
2229 C67_NOP(8); // NOP 8 for worst case
2230 break;
2231 case TOK_SHL:
2232 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2233 r = vtop[-1].r;
2234 fr = vtop[0].r;
2235 vtop--;
2236 C67_SHL(fr, r); // arithmetic/logical shift
2237 break;
2239 case TOK_SHR:
2240 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2241 r = vtop[-1].r;
2242 fr = vtop[0].r;
2243 vtop--;
2244 C67_SHRU(fr, r); // logical shift
2245 break;
2247 case TOK_SAR:
2248 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2249 r = vtop[-1].r;
2250 fr = vtop[0].r;
2251 vtop--;
2252 C67_SHR(fr, r); // arithmetic shift
2253 break;
2255 case '/':
2256 t = TOK__divi;
2257 call_func:
2258 vswap();
2259 /* call generic idiv function */
2260 vpush_global_sym(&func_old_type, t);
2261 vrott(3);
2262 gfunc_call(2);
2263 vpushi(0);
2264 vtop->r = REG_IRET;
2265 vtop->r2 = VT_CONST;
2266 break;
2267 case TOK_UDIV:
2268 case TOK_PDIV:
2269 t = TOK__divu;
2270 goto call_func;
2271 case '%':
2272 t = TOK__remi;
2273 goto call_func;
2274 case TOK_UMOD:
2275 t = TOK__remu;
2276 goto call_func;
2278 default:
2279 opc = 7;
2280 goto gen_op8;
2284 /* generate a floating point operation 'v = t1 op t2' instruction. The
2285 two operands are guaranteed to have the same floating point type */
2286 /* XXX: need to use ST1 too */
2287 void gen_opf(int op)
2289 int ft, fc, fr, r;
2291 if (op >= TOK_ULT && op <= TOK_GT)
2292 gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
2293 else
2294 gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
2296 ft = vtop->type.t;
2297 fc = vtop->c.i;
2298 r = vtop->r;
2299 fr = vtop[-1].r;
2302 if ((ft & VT_BTYPE) == VT_LDOUBLE)
2303 tcc_error("long doubles not supported");
2305 if (op >= TOK_ULT && op <= TOK_GT) {
2307 r = vtop[-1].r;
2308 fr = vtop[0].r;
2310 C67_compare_reg = C67_B2;
2312 if (op == TOK_LT) {
2313 if ((ft & VT_BTYPE) == VT_DOUBLE)
2314 C67_CMPLTDP(r, fr, C67_B2);
2315 else
2316 C67_CMPLTSP(r, fr, C67_B2);
2318 C67_invert_test = FALSE;
2319 } else if (op == TOK_GE) {
2320 if ((ft & VT_BTYPE) == VT_DOUBLE)
2321 C67_CMPLTDP(r, fr, C67_B2);
2322 else
2323 C67_CMPLTSP(r, fr, C67_B2);
2325 C67_invert_test = TRUE;
2326 } else if (op == TOK_GT) {
2327 if ((ft & VT_BTYPE) == VT_DOUBLE)
2328 C67_CMPGTDP(r, fr, C67_B2);
2329 else
2330 C67_CMPGTSP(r, fr, C67_B2);
2332 C67_invert_test = FALSE;
2333 } else if (op == TOK_LE) {
2334 if ((ft & VT_BTYPE) == VT_DOUBLE)
2335 C67_CMPGTDP(r, fr, C67_B2);
2336 else
2337 C67_CMPGTSP(r, fr, C67_B2);
2339 C67_invert_test = TRUE;
2340 } else if (op == TOK_EQ) {
2341 if ((ft & VT_BTYPE) == VT_DOUBLE)
2342 C67_CMPEQDP(r, fr, C67_B2);
2343 else
2344 C67_CMPEQSP(r, fr, C67_B2);
2346 C67_invert_test = FALSE;
2347 } else if (op == TOK_NE) {
2348 if ((ft & VT_BTYPE) == VT_DOUBLE)
2349 C67_CMPEQDP(r, fr, C67_B2);
2350 else
2351 C67_CMPEQSP(r, fr, C67_B2);
2353 C67_invert_test = TRUE;
2354 } else {
2355 ALWAYS_ASSERT(FALSE);
2357 vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2
2358 } else {
2359 if (op == '+') {
2360 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2361 C67_ADDDP(r, fr); // ADD fr,r,fr
2362 C67_NOP(6);
2363 } else {
2364 C67_ADDSP(r, fr); // ADD fr,r,fr
2365 C67_NOP(3);
2367 vtop--;
2368 } else if (op == '-') {
2369 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2370 C67_SUBDP(r, fr); // SUB fr,r,fr
2371 C67_NOP(6);
2372 } else {
2373 C67_SUBSP(r, fr); // SUB fr,r,fr
2374 C67_NOP(3);
2376 vtop--;
2377 } else if (op == '*') {
2378 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2379 C67_MPYDP(r, fr); // MPY fr,r,fr
2380 C67_NOP(9);
2381 } else {
2382 C67_MPYSP(r, fr); // MPY fr,r,fr
2383 C67_NOP(3);
2385 vtop--;
2386 } else if (op == '/') {
2387 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2388 // must call intrinsic DP floating point divide
2389 vswap();
2390 /* call generic idiv function */
2391 vpush_global_sym(&func_old_type, TOK__divd);
2392 vrott(3);
2393 gfunc_call(2);
2394 vpushi(0);
2395 vtop->r = REG_FRET;
2396 vtop->r2 = REG_LRET;
2398 } else {
2399 // must call intrinsic SP floating point divide
2400 vswap();
2401 /* call generic idiv function */
2402 vpush_global_sym(&func_old_type, TOK__divf);
2403 vrott(3);
2404 gfunc_call(2);
2405 vpushi(0);
2406 vtop->r = REG_FRET;
2407 vtop->r2 = VT_CONST;
2409 } else
2410 ALWAYS_ASSERT(FALSE);
2417 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2418 and 'long long' cases. */
2419 void gen_cvt_itof(int t)
2421 int r;
2423 gv(RC_INT);
2424 r = vtop->r;
2426 if ((t & VT_BTYPE) == VT_DOUBLE) {
2427 if (t & VT_UNSIGNED)
2428 C67_INTDPU(r, r);
2429 else
2430 C67_INTDP(r, r);
2432 C67_NOP(4);
2433 vtop->type.t = VT_DOUBLE;
2434 } else {
2435 if (t & VT_UNSIGNED)
2436 C67_INTSPU(r, r);
2437 else
2438 C67_INTSP(r, r);
2439 C67_NOP(3);
2440 vtop->type.t = VT_FLOAT;
2445 /* convert fp to int 't' type */
2446 /* XXX: handle long long case */
2447 void gen_cvt_ftoi(int t)
2449 int r;
2451 gv(RC_FLOAT);
2452 r = vtop->r;
2454 if (t != VT_INT)
2455 tcc_error("long long not supported");
2456 else {
2457 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2458 C67_DPTRUNC(r, r);
2459 C67_NOP(3);
2460 } else {
2461 C67_SPTRUNC(r, r);
2462 C67_NOP(3);
2465 vtop->type.t = VT_INT;
2470 /* convert from one floating point type to another */
2471 void gen_cvt_ftof(int t)
2473 int r, r2;
2475 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2476 (t & VT_BTYPE) == VT_FLOAT) {
2477 // convert double to float
2479 gv(RC_FLOAT); // get it in a register pair
2481 r = vtop->r;
2483 C67_DPSP(r, r); // convert it to SP same register
2484 C67_NOP(3);
2486 vtop->type.t = VT_FLOAT;
2487 vtop->r2 = VT_CONST; // set this as unused
2488 } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
2489 (t & VT_BTYPE) == VT_DOUBLE) {
2490 // convert float to double
2492 gv(RC_FLOAT); // get it in a register
2494 r = vtop->r;
2496 if (r == TREG_EAX) { // make sure the paired reg is avail
2497 r2 = get_reg(RC_ECX);
2498 } else if (r == TREG_EDX) {
2499 r2 = get_reg(RC_ST0);
2500 } else {
2501 ALWAYS_ASSERT(FALSE);
2502 r2 = 0; /* avoid warning */
2505 C67_SPDP(r, r); // convert it to DP same register
2506 C67_NOP(1);
2508 vtop->type.t = VT_DOUBLE;
2509 vtop->r2 = r2; // set this as unused
2510 } else {
2511 ALWAYS_ASSERT(FALSE);
2515 /* computed goto support */
2516 void ggoto(void)
2518 gcall_or_jmp(1);
2519 vtop--;
2522 /* Save the stack pointer onto the stack and return the location of its address */
2523 ST_FUNC void gen_vla_sp_save(int addr) {
2524 tcc_error("variable length arrays unsupported for this target");
2527 /* Restore the SP from a location on the stack */
2528 ST_FUNC void gen_vla_sp_restore(int addr) {
2529 tcc_error("variable length arrays unsupported for this target");
2532 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2533 ST_FUNC void gen_vla_alloc(CType *type, int align) {
2534 tcc_error("variable length arrays unsupported for this target");
2537 /* end of C67 code generator */
2538 /*************************************************************/
2539 #endif
2540 /*************************************************************/