riscv: asm: Add branch to label
[tinycc.git] / c67-gen.c
blob9490a27fab77233fd8c57dae1b9f3a2b2e5c41c4
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_IRE2 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_IRE2 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 #undef CONFIG_TCC_BCHECK
113 /******************************************************/
114 #else /* ! TARGET_DEFS_ONLY */
115 /******************************************************/
116 #define USING_GLOBALS
117 #include "tcc.h"
119 ST_DATA const char * const target_machine_defs =
120 "__C67__\0"
123 ST_DATA const int reg_classes[NB_REGS] = {
124 /* eax */ RC_INT | RC_FLOAT | RC_EAX,
125 // only allow even regs for floats (allow for doubles)
126 /* ecx */ RC_INT | RC_ECX,
127 /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
128 // only allow even regs for floats (allow for doubles)
129 /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
130 /* A4 */ RC_C67_A4,
131 /* A5 */ RC_C67_A5,
132 /* B4 */ RC_C67_B4,
133 /* B5 */ RC_C67_B5,
134 /* A6 */ RC_C67_A6,
135 /* A7 */ RC_C67_A7,
136 /* B6 */ RC_C67_B6,
137 /* B7 */ RC_C67_B7,
138 /* A8 */ RC_C67_A8,
139 /* A9 */ RC_C67_A9,
140 /* B8 */ RC_C67_B8,
141 /* B9 */ RC_C67_B9,
142 /* A10 */ RC_C67_A10,
143 /* A11 */ RC_C67_A11,
144 /* B10 */ RC_C67_B10,
145 /* B11 */ RC_C67_B11,
146 /* A12 */ RC_C67_A10,
147 /* A13 */ RC_C67_A11,
148 /* B12 */ RC_C67_B10,
149 /* B13 */ RC_C67_B11
152 // although tcc thinks it is passing parameters on the stack,
153 // the C67 really passes up to the first 10 params in special
154 // regs or regs pairs (for 64 bit params). So keep track of
155 // the stack offsets so we can translate to the appropriate
156 // reg (pair)
158 #define NoCallArgsPassedOnStack 10
159 int NoOfCurFuncArgs;
160 int TranslateStackToReg[NoCallArgsPassedOnStack];
161 int ParamLocOnStack[NoCallArgsPassedOnStack];
162 int TotalBytesPushedOnStack;
164 #ifndef FALSE
165 # define FALSE 0
166 # define TRUE 1
167 #endif
169 #undef BOOL
170 #define BOOL int
172 #define ALWAYS_ASSERT(x) \
173 do {\
174 if (!(x))\
175 tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
176 } while (0)
178 /******************************************************/
179 static unsigned long func_sub_sp_offset;
180 static int func_ret_sub;
182 static BOOL C67_invert_test;
183 static int C67_compare_reg;
185 #ifdef ASSEMBLY_LISTING_C67
186 FILE *f = NULL;
187 #endif
189 void C67_g(int c)
191 int ind1;
192 if (nocode_wanted)
193 return;
194 #ifdef ASSEMBLY_LISTING_C67
195 fprintf(f, " %08X", c);
196 #endif
197 ind1 = ind + 4;
198 if (ind1 > (int) cur_text_section->data_allocated)
199 section_realloc(cur_text_section, ind1);
200 cur_text_section->data[ind] = c & 0xff;
201 cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
202 cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
203 cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
204 ind = ind1;
208 /* output a symbol and patch all calls to it */
209 void gsym_addr(int t, int a)
211 int n, *ptr;
212 while (t) {
213 ptr = (int *) (cur_text_section->data + t);
215 Sym *sym;
217 // extract 32 bit address from MVKH/MVKL
218 n = ((*ptr >> 7) & 0xffff);
219 n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
221 // define a label that will be relocated
223 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
224 greloc(cur_text_section, sym, t, R_C60LO16);
225 greloc(cur_text_section, sym, t + 4, R_C60HI16);
227 // clear out where the pointer was
229 *ptr &= ~(0xffff << 7);
230 *(ptr + 1) &= ~(0xffff << 7);
232 t = n;
236 // these are regs that tcc doesn't really know about,
237 // but assign them unique values so the mapping routines
238 // can distinguish them
240 #define C67_A0 105
241 #define C67_SP 106
242 #define C67_B3 107
243 #define C67_FP 108
244 #define C67_B2 109
245 #define C67_CREG_ZERO -1 /* Special code for no condition reg test */
248 int ConvertRegToRegClass(int r)
250 // only works for A4-B13
252 return RC_C67_A4 << (r - TREG_C67_A4);
256 // map TCC reg to C67 reg number
258 int C67_map_regn(int r)
260 if (r == 0) // normal tcc regs
261 return 0x2; // A2
262 else if (r == 1) // normal tcc regs
263 return 3; // A3
264 else if (r == 2) // normal tcc regs
265 return 0; // B0
266 else if (r == 3) // normal tcc regs
267 return 1; // B1
268 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
269 return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
270 else if (r == C67_A0)
271 return 0; // set to A0 (offset reg)
272 else if (r == C67_B2)
273 return 2; // set to B2 (offset reg)
274 else if (r == C67_B3)
275 return 3; // set to B3 (return address reg)
276 else if (r == C67_SP)
277 return 15; // set to SP (B15) (offset reg)
278 else if (r == C67_FP)
279 return 15; // set to FP (A15) (offset reg)
280 else if (r == C67_CREG_ZERO)
281 return 0; // Special code for no condition reg test
282 else
283 ALWAYS_ASSERT(FALSE);
285 return 0;
288 // mapping from tcc reg number to
289 // C67 register to condition code field
291 // valid condition code regs are:
293 // tcc reg 2 ->B0 -> 1
294 // tcc reg 3 ->B1 -> 2
295 // tcc reg 0 -> A2 -> 5
296 // tcc reg 1 -> A3 -> X
297 // tcc reg B2 -> 3
299 int C67_map_regc(int r)
301 if (r == 0) // normal tcc regs
302 return 0x5;
303 else if (r == 2) // normal tcc regs
304 return 0x1;
305 else if (r == 3) // normal tcc regs
306 return 0x2;
307 else if (r == C67_B2) // normal tcc regs
308 return 0x3;
309 else if (r == C67_CREG_ZERO)
310 return 0; // Special code for no condition reg test
311 else
312 ALWAYS_ASSERT(FALSE);
314 return 0;
318 // map TCC reg to C67 reg side A or B
320 int C67_map_regs(int r)
322 if (r == 0) // normal tcc regs
323 return 0x0;
324 else if (r == 1) // normal tcc regs
325 return 0x0;
326 else if (r == 2) // normal tcc regs
327 return 0x1;
328 else if (r == 3) // normal tcc regs
329 return 0x1;
330 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
331 return (r & 2) >> 1;
332 else if (r == C67_A0)
333 return 0; // set to A side
334 else if (r == C67_B2)
335 return 1; // set to B side
336 else if (r == C67_B3)
337 return 1; // set to B side
338 else if (r == C67_SP)
339 return 0x1; // set to SP (B15) B side
340 else if (r == C67_FP)
341 return 0x0; // set to FP (A15) A side
342 else
343 ALWAYS_ASSERT(FALSE);
345 return 0;
348 int C67_map_S12(char *s)
350 if (strstr(s, ".S1") != NULL)
351 return 0;
352 else if (strcmp(s, ".S2"))
353 return 1;
354 else
355 ALWAYS_ASSERT(FALSE);
357 return 0;
360 int C67_map_D12(char *s)
362 if (strstr(s, ".D1") != NULL)
363 return 0;
364 else if (strcmp(s, ".D2"))
365 return 1;
366 else
367 ALWAYS_ASSERT(FALSE);
369 return 0;
374 void C67_asm(const char *s, int a, int b, int c)
376 BOOL xpath;
378 #ifdef ASSEMBLY_LISTING_C67
379 if (!f) {
380 f = fopen("TCC67_out.txt", "wt");
382 fprintf(f, "%04X ", ind);
383 #endif
385 if (strstr(s, "MVKL") == s) {
386 C67_g((C67_map_regn(b) << 23) |
387 ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
388 } else if (strstr(s, "MVKH") == s) {
389 C67_g((C67_map_regn(b) << 23) |
390 (((a >> 16) & 0xffff) << 7) |
391 (0x1a << 2) | (C67_map_regs(b) << 1));
392 } else if (strstr(s, "STW.D SP POST DEC") == s) {
393 C67_g((C67_map_regn(a) << 23) | //src
394 (15 << 18) | //SP B15
395 (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
396 (0xa << 9) | //mode a = post dec ucst
397 (0 << 8) | //r (LDDW bit 0)
398 (1 << 7) | //y D1/D2 use B side
399 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
400 (1 << 2) | //opcode
401 (C67_map_regs(a) << 1) | //side of src
402 (0 << 0)); //parallel
403 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
404 C67_g((C67_map_regn(a) << 23) | //src
405 (15 << 18) | //base reg A15
406 (0 << 13) | //offset reg A0
407 (5 << 9) | //mode 5 = pos offset, base reg + off reg
408 (0 << 8) | //r (LDDW bit 0)
409 (0 << 7) | //y D1/D2 A side
410 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
411 (1 << 2) | //opcode
412 (C67_map_regs(a) << 1) | //side of src
413 (0 << 0)); //parallel
414 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
415 C67_g((C67_map_regn(a) << 23) | //src
416 (15 << 18) | //base reg A15
417 (0 << 13) | //offset reg A0
418 (5 << 9) | //mode 5 = pos offset, base reg + off reg
419 (0 << 8) | //r (LDDW bit 0)
420 (0 << 7) | //y D1/D2 A side
421 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
422 (1 << 2) | //opcode
423 (C67_map_regs(a) << 1) | //side of src
424 (0 << 0)); //parallel
425 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
426 C67_g((C67_map_regn(a) << 23) | //src
427 (15 << 18) | //base reg A15
428 (0 << 13) | //offset reg A0
429 (5 << 9) | //mode 5 = pos offset, base reg + off reg
430 (0 << 8) | //r (LDDW bit 0)
431 (0 << 7) | //y D1/D2 A side
432 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
433 (1 << 2) | //opcode
434 (C67_map_regs(a) << 1) | //side of src
435 (0 << 0)); //parallel
436 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
437 C67_g((C67_map_regn(a) << 23) | //src
438 (15 << 18) | //base reg A15
439 (0 << 13) | //offset reg A0
440 (5 << 9) | //mode 5 = pos offset, base reg + off reg
441 (0 << 8) | //r (LDDW bit 0)
442 (0 << 7) | //y D1/D2 A side
443 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
444 (1 << 2) | //opcode
445 (C67_map_regs(a) << 1) | //side of src
446 (0 << 0)); //parallel
447 } else if (strstr(s, "STW.D *+SP[A0]") == s) {
448 C67_g((C67_map_regn(a) << 23) | //src
449 (15 << 18) | //base reg A15
450 (0 << 13) | //offset reg A0
451 (5 << 9) | //mode 5 = pos offset, base reg + off reg
452 (0 << 8) | //r (LDDW bit 0)
453 (0 << 7) | //y D1/D2 A side
454 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
455 (1 << 2) | //opcode
456 (C67_map_regs(a) << 1) | //side of src
457 (0 << 0)); //parallel
458 } else if (strstr(s, "STW.D *") == s) {
459 C67_g((C67_map_regn(a) << 23) | //src
460 (C67_map_regn(b) << 18) | //base reg A0
461 (0 << 13) | //cst5
462 (1 << 9) | //mode 1 = pos cst offset
463 (0 << 8) | //r (LDDW bit 0)
464 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
465 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
466 (1 << 2) | //opcode
467 (C67_map_regs(a) << 1) | //side of src
468 (0 << 0)); //parallel
469 } else if (strstr(s, "STH.D *") == s) {
470 C67_g((C67_map_regn(a) << 23) | //src
471 (C67_map_regn(b) << 18) | //base reg A0
472 (0 << 13) | //cst5
473 (1 << 9) | //mode 1 = pos cst offset
474 (0 << 8) | //r (LDDW bit 0)
475 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
476 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
477 (1 << 2) | //opcode
478 (C67_map_regs(a) << 1) | //side of src
479 (0 << 0)); //parallel
480 } else if (strstr(s, "STB.D *") == s) {
481 C67_g((C67_map_regn(a) << 23) | //src
482 (C67_map_regn(b) << 18) | //base reg A0
483 (0 << 13) | //cst5
484 (1 << 9) | //mode 1 = pos cst offset
485 (0 << 8) | //r (LDDW bit 0)
486 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
487 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
488 (1 << 2) | //opcode
489 (C67_map_regs(a) << 1) | //side of src
490 (0 << 0)); //parallel
491 } else if (strstr(s, "STW.D +*") == s) {
492 ALWAYS_ASSERT(c < 32);
493 C67_g((C67_map_regn(a) << 23) | //src
494 (C67_map_regn(b) << 18) | //base reg A0
495 (c << 13) | //cst5
496 (1 << 9) | //mode 1 = pos cst offset
497 (0 << 8) | //r (LDDW bit 0)
498 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
499 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
500 (1 << 2) | //opcode
501 (C67_map_regs(a) << 1) | //side of src
502 (0 << 0)); //parallel
503 } else if (strstr(s, "LDW.D SP PRE INC") == s) {
504 C67_g((C67_map_regn(a) << 23) | //dst
505 (15 << 18) | //base reg B15
506 (2 << 13) | //ucst5 (must keep 8 byte boundary)
507 (9 << 9) | //mode 9 = pre inc ucst5
508 (0 << 8) | //r (LDDW bit 0)
509 (1 << 7) | //y D1/D2 B side
510 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
511 (1 << 2) | //opcode
512 (C67_map_regs(a) << 1) | //side of dst
513 (0 << 0)); //parallel
514 } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
515 C67_g((C67_map_regn(a) << 23) | //dst
516 (15 << 18) | //base reg B15
517 (1 << 13) | //ucst5 (must keep 8 byte boundary)
518 (9 << 9) | //mode 9 = pre inc ucst5
519 (1 << 8) | //r (LDDW bit 1)
520 (1 << 7) | //y D1/D2 B side
521 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
522 (1 << 2) | //opcode
523 (C67_map_regs(a) << 1) | //side of dst
524 (0 << 0)); //parallel
525 } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
526 C67_g((C67_map_regn(a) << 23) | //dst
527 (15 << 18) | //base reg A15
528 (0 << 13) | //offset reg A0
529 (5 << 9) | //mode 5 = pos offset, base reg + off reg
530 (0 << 8) | //r (LDDW bit 0)
531 (0 << 7) | //y D1/D2 A side
532 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
533 (1 << 2) | //opcode
534 (C67_map_regs(a) << 1) | //side of dst
535 (0 << 0)); //parallel
536 } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
537 C67_g((C67_map_regn(a) << 23) | //dst
538 (15 << 18) | //base reg A15
539 (0 << 13) | //offset reg A0
540 (5 << 9) | //mode 5 = pos offset, base reg + off reg
541 (1 << 8) | //r (LDDW bit 1)
542 (0 << 7) | //y D1/D2 A side
543 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
544 (1 << 2) | //opcode
545 (C67_map_regs(a) << 1) | //side of dst
546 (0 << 0)); //parallel
547 } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
548 C67_g((C67_map_regn(a) << 23) | //dst
549 (15 << 18) | //base reg A15
550 (0 << 13) | //offset reg A0
551 (5 << 9) | //mode 5 = pos offset, base reg + off reg
552 (0 << 8) | //r (LDDW bit 0)
553 (0 << 7) | //y D1/D2 A side
554 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
555 (1 << 2) | //opcode
556 (C67_map_regs(a) << 1) | //side of dst
557 (0 << 0)); //parallel
558 } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
559 C67_g((C67_map_regn(a) << 23) | //dst
560 (15 << 18) | //base reg A15
561 (0 << 13) | //offset reg A0
562 (5 << 9) | //mode 5 = pos offset, base reg + off reg
563 (0 << 8) | //r (LDDW bit 0)
564 (0 << 7) | //y D1/D2 A side
565 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
566 (1 << 2) | //opcode
567 (C67_map_regs(a) << 1) | //side of dst
568 (0 << 0)); //parallel
569 } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
570 C67_g((C67_map_regn(a) << 23) | //dst
571 (15 << 18) | //base reg A15
572 (0 << 13) | //offset reg A0
573 (5 << 9) | //mode 5 = pos offset, base reg + off reg
574 (0 << 8) | //r (LDDW bit 0)
575 (0 << 7) | //y D1/D2 A side
576 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
577 (1 << 2) | //opcode
578 (C67_map_regs(a) << 1) | //side of dst
579 (0 << 0)); //parallel
580 } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
581 C67_g((C67_map_regn(a) << 23) | //dst
582 (15 << 18) | //base reg A15
583 (0 << 13) | //offset reg A0
584 (5 << 9) | //mode 5 = pos offset, base reg + off reg
585 (0 << 8) | //r (LDDW bit 0)
586 (0 << 7) | //y D1/D2 A side
587 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
588 (1 << 2) | //opcode
589 (C67_map_regs(a) << 1) | //side of dst
590 (0 << 0)); //parallel
591 } else if (strstr(s, "LDW.D *") == s) {
592 C67_g((C67_map_regn(b) << 23) | //dst
593 (C67_map_regn(a) << 18) | //base reg A15
594 (0 << 13) | //cst5
595 (1 << 9) | //mode 1 = pos cst offset
596 (0 << 8) | //r (LDDW bit 0)
597 (C67_map_regs(a) << 7) | //y D1/D2 src side
598 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
599 (1 << 2) | //opcode
600 (C67_map_regs(b) << 1) | //side of dst
601 (0 << 0)); //parallel
602 } else if (strstr(s, "LDDW.D *") == s) {
603 C67_g((C67_map_regn(b) << 23) | //dst
604 (C67_map_regn(a) << 18) | //base reg A15
605 (0 << 13) | //cst5
606 (1 << 9) | //mode 1 = pos cst offset
607 (1 << 8) | //r (LDDW bit 1)
608 (C67_map_regs(a) << 7) | //y D1/D2 src side
609 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
610 (1 << 2) | //opcode
611 (C67_map_regs(b) << 1) | //side of dst
612 (0 << 0)); //parallel
613 } else if (strstr(s, "LDH.D *") == s) {
614 C67_g((C67_map_regn(b) << 23) | //dst
615 (C67_map_regn(a) << 18) | //base reg A15
616 (0 << 13) | //cst5
617 (1 << 9) | //mode 1 = pos cst offset
618 (0 << 8) | //r (LDDW bit 0)
619 (C67_map_regs(a) << 7) | //y D1/D2 src side
620 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
621 (1 << 2) | //opcode
622 (C67_map_regs(b) << 1) | //side of dst
623 (0 << 0)); //parallel
624 } else if (strstr(s, "LDB.D *") == s) {
625 C67_g((C67_map_regn(b) << 23) | //dst
626 (C67_map_regn(a) << 18) | //base reg A15
627 (0 << 13) | //cst5
628 (1 << 9) | //mode 1 = pos cst offset
629 (0 << 8) | //r (LDDW bit 0)
630 (C67_map_regs(a) << 7) | //y D1/D2 src side
631 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
632 (1 << 2) | //opcode
633 (C67_map_regs(b) << 1) | //side of dst
634 (0 << 0)); //parallel
635 } else if (strstr(s, "LDHU.D *") == s) {
636 C67_g((C67_map_regn(b) << 23) | //dst
637 (C67_map_regn(a) << 18) | //base reg A15
638 (0 << 13) | //cst5
639 (1 << 9) | //mode 1 = pos cst offset
640 (0 << 8) | //r (LDDW bit 0)
641 (C67_map_regs(a) << 7) | //y D1/D2 src side
642 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
643 (1 << 2) | //opcode
644 (C67_map_regs(b) << 1) | //side of dst
645 (0 << 0)); //parallel
646 } else if (strstr(s, "LDBU.D *") == s) {
647 C67_g((C67_map_regn(b) << 23) | //dst
648 (C67_map_regn(a) << 18) | //base reg A15
649 (0 << 13) | //cst5
650 (1 << 9) | //mode 1 = pos cst offset
651 (0 << 8) | //r (LDDW bit 0)
652 (C67_map_regs(a) << 7) | //y D1/D2 src side
653 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
654 (1 << 2) | //opcode
655 (C67_map_regs(b) << 1) | //side of dst
656 (0 << 0)); //parallel
657 } else if (strstr(s, "LDW.D +*") == s) {
658 C67_g((C67_map_regn(b) << 23) | //dst
659 (C67_map_regn(a) << 18) | //base reg A15
660 (1 << 13) | //cst5
661 (1 << 9) | //mode 1 = pos cst offset
662 (0 << 8) | //r (LDDW bit 0)
663 (C67_map_regs(a) << 7) | //y D1/D2 src side
664 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
665 (1 << 2) | //opcode
666 (C67_map_regs(b) << 1) | //side of dst
667 (0 << 0)); //parallel
668 } else if (strstr(s, "CMPLTSP") == s) {
669 xpath = C67_map_regs(a) ^ C67_map_regs(b);
670 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
672 C67_g((C67_map_regn(c) << 23) | //dst
673 (C67_map_regn(b) << 18) | //src2
674 (C67_map_regn(a) << 13) | //src1
675 (xpath << 12) | //x use cross path for src2
676 (0x3a << 6) | //opcode
677 (0x8 << 2) | //opcode fixed
678 (C67_map_regs(c) << 1) | //side for reg c
679 (0 << 0)); //parallel
680 } else if (strstr(s, "CMPGTSP") == s) {
681 xpath = C67_map_regs(a) ^ C67_map_regs(b);
682 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
684 C67_g((C67_map_regn(c) << 23) | //dst
685 (C67_map_regn(b) << 18) | //src2
686 (C67_map_regn(a) << 13) | //src1
687 (xpath << 12) | //x use cross path for src2
688 (0x39 << 6) | //opcode
689 (0x8 << 2) | //opcode fixed
690 (C67_map_regs(c) << 1) | //side for reg c
691 (0 << 0)); //parallel
692 } else if (strstr(s, "CMPEQSP") == s) {
693 xpath = C67_map_regs(a) ^ C67_map_regs(b);
694 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
696 C67_g((C67_map_regn(c) << 23) | //dst
697 (C67_map_regn(b) << 18) | //src2
698 (C67_map_regn(a) << 13) | //src1
699 (xpath << 12) | //x use cross path for src2
700 (0x38 << 6) | //opcode
701 (0x8 << 2) | //opcode fixed
702 (C67_map_regs(c) << 1) | //side for reg c
703 (0 << 0)); //parallel
706 else if (strstr(s, "CMPLTDP") == s) {
707 xpath = C67_map_regs(a) ^ C67_map_regs(b);
708 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
710 C67_g((C67_map_regn(c) << 23) | //dst
711 (C67_map_regn(b) << 18) | //src2
712 (C67_map_regn(a) << 13) | //src1
713 (xpath << 12) | //x use cross path for src2
714 (0x2a << 6) | //opcode
715 (0x8 << 2) | //opcode fixed
716 (C67_map_regs(c) << 1) | //side for reg c
717 (0 << 0)); //parallel
718 } else if (strstr(s, "CMPGTDP") == s) {
719 xpath = C67_map_regs(a) ^ C67_map_regs(b);
720 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
722 C67_g((C67_map_regn(c) << 23) | //dst
723 (C67_map_regn(b) << 18) | //src2
724 (C67_map_regn(a) << 13) | //src1
725 (xpath << 12) | //x use cross path for src2
726 (0x29 << 6) | //opcode
727 (0x8 << 2) | //opcode fixed
728 (C67_map_regs(c) << 1) | //side for reg c
729 (0 << 0)); //parallel
730 } else if (strstr(s, "CMPEQDP") == s) {
731 xpath = C67_map_regs(a) ^ C67_map_regs(b);
732 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
734 C67_g((C67_map_regn(c) << 23) | //dst
735 (C67_map_regn(b) << 18) | //src2
736 (C67_map_regn(a) << 13) | //src1
737 (xpath << 12) | //x use cross path for src2
738 (0x28 << 6) | //opcode
739 (0x8 << 2) | //opcode fixed
740 (C67_map_regs(c) << 1) | //side for reg c
741 (0 << 0)); //parallel
742 } else if (strstr(s, "CMPLT") == s) {
743 xpath = C67_map_regs(a) ^ C67_map_regs(b);
744 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
746 C67_g((C67_map_regn(c) << 23) | //dst
747 (C67_map_regn(b) << 18) | //src2
748 (C67_map_regn(a) << 13) | //src1
749 (xpath << 12) | //x use cross path for src2
750 (0x57 << 5) | //opcode
751 (0x6 << 2) | //opcode fixed
752 (C67_map_regs(c) << 1) | //side for reg c
753 (0 << 0)); //parallel
754 } else if (strstr(s, "CMPGT") == s) {
755 xpath = C67_map_regs(a) ^ C67_map_regs(b);
756 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
758 C67_g((C67_map_regn(c) << 23) | //dst
759 (C67_map_regn(b) << 18) | //src2
760 (C67_map_regn(a) << 13) | //src1
761 (xpath << 12) | //x use cross path for src2
762 (0x47 << 5) | //opcode
763 (0x6 << 2) | //opcode fixed
764 (C67_map_regs(c) << 1) | //side for reg c
765 (0 << 0)); //parallel
766 } else if (strstr(s, "CMPEQ") == s) {
767 xpath = C67_map_regs(a) ^ C67_map_regs(b);
768 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
770 C67_g((C67_map_regn(c) << 23) | //dst
771 (C67_map_regn(b) << 18) | //src2
772 (C67_map_regn(a) << 13) | //src1
773 (xpath << 12) | //x use cross path for src2
774 (0x53 << 5) | //opcode
775 (0x6 << 2) | //opcode fixed
776 (C67_map_regs(c) << 1) | //side for reg c
777 (0 << 0)); //parallel
778 } else if (strstr(s, "CMPLTU") == s) {
779 xpath = C67_map_regs(a) ^ C67_map_regs(b);
780 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
782 C67_g((C67_map_regn(c) << 23) | //dst
783 (C67_map_regn(b) << 18) | //src2
784 (C67_map_regn(a) << 13) | //src1
785 (xpath << 12) | //x use cross path for src2
786 (0x5f << 5) | //opcode
787 (0x6 << 2) | //opcode fixed
788 (C67_map_regs(c) << 1) | //side for reg c
789 (0 << 0)); //parallel
790 } else if (strstr(s, "CMPGTU") == s) {
791 xpath = C67_map_regs(a) ^ C67_map_regs(b);
792 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
794 C67_g((C67_map_regn(c) << 23) | //dst
795 (C67_map_regn(b) << 18) | //src2
796 (C67_map_regn(a) << 13) | //src1
797 (xpath << 12) | //x use cross path for src2
798 (0x4f << 5) | //opcode
799 (0x6 << 2) | //opcode fixed
800 (C67_map_regs(c) << 1) | //side for reg c
801 (0 << 0)); //parallel
802 } else if (strstr(s, "B DISP") == s) {
803 C67_g((0 << 29) | //creg
804 (0 << 28) | //z
805 (a << 7) | //cnst
806 (0x4 << 2) | //opcode fixed
807 (0 << 1) | //S0/S1
808 (0 << 0)); //parallel
809 } else if (strstr(s, "B.") == s) {
810 xpath = C67_map_regs(c) ^ 1;
812 C67_g((C67_map_regc(b) << 29) | //creg
813 (a << 28) | //inv
814 (0 << 23) | //dst
815 (C67_map_regn(c) << 18) | //src2
816 (0 << 13) | //
817 (xpath << 12) | //x cross path if !B side
818 (0xd << 6) | //opcode
819 (0x8 << 2) | //opcode fixed
820 (1 << 1) | //must be S2
821 (0 << 0)); //parallel
822 } else if (strstr(s, "MV.L") == s) {
823 xpath = C67_map_regs(b) ^ C67_map_regs(c);
825 C67_g((0 << 29) | //creg
826 (0 << 28) | //inv
827 (C67_map_regn(c) << 23) | //dst
828 (C67_map_regn(b) << 18) | //src2
829 (0 << 13) | //src1 (cst5)
830 (xpath << 12) | //x cross path if opposite sides
831 (0x2 << 5) | //opcode
832 (0x6 << 2) | //opcode fixed
833 (C67_map_regs(c) << 1) | //side of dest
834 (0 << 0)); //parallel
835 } else if (strstr(s, "SPTRUNC.L") == s) {
836 xpath = C67_map_regs(b) ^ C67_map_regs(c);
838 C67_g((0 << 29) | //creg
839 (0 << 28) | //inv
840 (C67_map_regn(c) << 23) | //dst
841 (C67_map_regn(b) << 18) | //src2
842 (0 << 13) | //src1 NA
843 (xpath << 12) | //x cross path if opposite sides
844 (0xb << 5) | //opcode
845 (0x6 << 2) | //opcode fixed
846 (C67_map_regs(c) << 1) | //side of dest
847 (0 << 0)); //parallel
848 } else if (strstr(s, "DPTRUNC.L") == s) {
849 xpath = C67_map_regs(b) ^ C67_map_regs(c);
851 C67_g((0 << 29) | //creg
852 (0 << 28) | //inv
853 (C67_map_regn(c) << 23) | //dst
854 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
855 (0 << 13) | //src1 NA
856 (xpath << 12) | //x cross path if opposite sides
857 (0x1 << 5) | //opcode
858 (0x6 << 2) | //opcode fixed
859 (C67_map_regs(c) << 1) | //side of dest
860 (0 << 0)); //parallel
861 } else if (strstr(s, "INTSP.L") == s) {
862 xpath = C67_map_regs(b) ^ C67_map_regs(c);
864 C67_g((0 << 29) | //creg
865 (0 << 28) | //inv
866 (C67_map_regn(c) << 23) | //dst
867 (C67_map_regn(b) << 18) | //src2
868 (0 << 13) | //src1 NA
869 (xpath << 12) | //x cross path if opposite sides
870 (0x4a << 5) | //opcode
871 (0x6 << 2) | //opcode fixed
872 (C67_map_regs(c) << 1) | //side of dest
873 (0 << 0)); //parallel
874 } else if (strstr(s, "INTSPU.L") == s) {
875 xpath = C67_map_regs(b) ^ C67_map_regs(c);
877 C67_g((0 << 29) | //creg
878 (0 << 28) | //inv
879 (C67_map_regn(c) << 23) | //dst
880 (C67_map_regn(b) << 18) | //src2
881 (0 << 13) | //src1 NA
882 (xpath << 12) | //x cross path if opposite sides
883 (0x49 << 5) | //opcode
884 (0x6 << 2) | //opcode fixed
885 (C67_map_regs(c) << 1) | //side of dest
886 (0 << 0)); //parallel
887 } else if (strstr(s, "INTDP.L") == s) {
888 xpath = C67_map_regs(b) ^ C67_map_regs(c);
890 C67_g((0 << 29) | //creg
891 (0 << 28) | //inv
892 (C67_map_regn(c) << 23) | //dst
893 (C67_map_regn(b) << 18) | //src2
894 (0 << 13) | //src1 NA
895 (xpath << 12) | //x cross path if opposite sides
896 (0x39 << 5) | //opcode
897 (0x6 << 2) | //opcode fixed
898 (C67_map_regs(c) << 1) | //side of dest
899 (0 << 0)); //parallel
900 } else if (strstr(s, "INTDPU.L") == s) {
901 xpath = C67_map_regs(b) ^ C67_map_regs(c);
903 C67_g((0 << 29) | //creg
904 (0 << 28) | //inv
905 (C67_map_regn(c) << 23) | //dst
906 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
907 (0 << 13) | //src1 NA
908 (xpath << 12) | //x cross path if opposite sides
909 (0x3b << 5) | //opcode
910 (0x6 << 2) | //opcode fixed
911 (C67_map_regs(c) << 1) | //side of dest
912 (0 << 0)); //parallel
913 } else if (strstr(s, "SPDP.L") == s) {
914 xpath = C67_map_regs(b) ^ C67_map_regs(c);
916 C67_g((0 << 29) | //creg
917 (0 << 28) | //inv
918 (C67_map_regn(c) << 23) | //dst
919 (C67_map_regn(b) << 18) | //src2
920 (0 << 13) | //src1 NA
921 (xpath << 12) | //x cross path if opposite sides
922 (0x2 << 6) | //opcode
923 (0x8 << 2) | //opcode fixed
924 (C67_map_regs(c) << 1) | //side of dest
925 (0 << 0)); //parallel
926 } else if (strstr(s, "DPSP.L") == s) {
927 ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
929 C67_g((0 << 29) | //creg
930 (0 << 28) | //inv
931 (C67_map_regn(c) << 23) | //dst
932 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
933 (0 << 13) | //src1 NA
934 (0 << 12) | //x cross path if opposite sides
935 (0x9 << 5) | //opcode
936 (0x6 << 2) | //opcode fixed
937 (C67_map_regs(c) << 1) | //side of dest
938 (0 << 0)); //parallel
939 } else if (strstr(s, "ADD.L") == s) {
940 xpath = C67_map_regs(b) ^ C67_map_regs(c);
942 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
944 C67_g((0 << 29) | //creg
945 (0 << 28) | //inv
946 (C67_map_regn(c) << 23) | //dst
947 (C67_map_regn(b) << 18) | //src2 (possible x path)
948 (C67_map_regn(a) << 13) | //src1
949 (xpath << 12) | //x cross path if opposite sides
950 (0x3 << 5) | //opcode
951 (0x6 << 2) | //opcode fixed
952 (C67_map_regs(c) << 1) | //side of dest
953 (0 << 0)); //parallel
954 } else if (strstr(s, "SUB.L") == s) {
955 xpath = C67_map_regs(b) ^ C67_map_regs(c);
957 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
959 C67_g((0 << 29) | //creg
960 (0 << 28) | //inv
961 (C67_map_regn(c) << 23) | //dst
962 (C67_map_regn(b) << 18) | //src2 (possible x path)
963 (C67_map_regn(a) << 13) | //src1
964 (xpath << 12) | //x cross path if opposite sides
965 (0x7 << 5) | //opcode
966 (0x6 << 2) | //opcode fixed
967 (C67_map_regs(c) << 1) | //side of dest
968 (0 << 0)); //parallel
969 } else if (strstr(s, "OR.L") == s) {
970 xpath = C67_map_regs(b) ^ C67_map_regs(c);
972 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
974 C67_g((0 << 29) | //creg
975 (0 << 28) | //inv
976 (C67_map_regn(c) << 23) | //dst
977 (C67_map_regn(b) << 18) | //src2 (possible x path)
978 (C67_map_regn(a) << 13) | //src1
979 (xpath << 12) | //x cross path if opposite sides
980 (0x7f << 5) | //opcode
981 (0x6 << 2) | //opcode fixed
982 (C67_map_regs(c) << 1) | //side of dest
983 (0 << 0)); //parallel
984 } else if (strstr(s, "AND.L") == s) {
985 xpath = C67_map_regs(b) ^ C67_map_regs(c);
987 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
989 C67_g((0 << 29) | //creg
990 (0 << 28) | //inv
991 (C67_map_regn(c) << 23) | //dst
992 (C67_map_regn(b) << 18) | //src2 (possible x path)
993 (C67_map_regn(a) << 13) | //src1
994 (xpath << 12) | //x cross path if opposite sides
995 (0x7b << 5) | //opcode
996 (0x6 << 2) | //opcode fixed
997 (C67_map_regs(c) << 1) | //side of dest
998 (0 << 0)); //parallel
999 } else if (strstr(s, "XOR.L") == s) {
1000 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1002 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1004 C67_g((0 << 29) | //creg
1005 (0 << 28) | //inv
1006 (C67_map_regn(c) << 23) | //dst
1007 (C67_map_regn(b) << 18) | //src2 (possible x path)
1008 (C67_map_regn(a) << 13) | //src1
1009 (xpath << 12) | //x cross path if opposite sides
1010 (0x6f << 5) | //opcode
1011 (0x6 << 2) | //opcode fixed
1012 (C67_map_regs(c) << 1) | //side of dest
1013 (0 << 0)); //parallel
1014 } else if (strstr(s, "ADDSP.L") == s) {
1015 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1017 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1019 C67_g((0 << 29) | //creg
1020 (0 << 28) | //inv
1021 (C67_map_regn(c) << 23) | //dst
1022 (C67_map_regn(b) << 18) | //src2 (possible x path)
1023 (C67_map_regn(a) << 13) | //src1
1024 (xpath << 12) | //x cross path if opposite sides
1025 (0x10 << 5) | //opcode
1026 (0x6 << 2) | //opcode fixed
1027 (C67_map_regs(c) << 1) | //side of dest
1028 (0 << 0)); //parallel
1029 } else if (strstr(s, "ADDDP.L") == s) {
1030 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1032 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1034 C67_g((0 << 29) | //creg
1035 (0 << 28) | //inv
1036 (C67_map_regn(c) << 23) | //dst
1037 (C67_map_regn(b) << 18) | //src2 (possible x path)
1038 (C67_map_regn(a) << 13) | //src1
1039 (xpath << 12) | //x cross path if opposite sides
1040 (0x18 << 5) | //opcode
1041 (0x6 << 2) | //opcode fixed
1042 (C67_map_regs(c) << 1) | //side of dest
1043 (0 << 0)); //parallel
1044 } else if (strstr(s, "SUBSP.L") == s) {
1045 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1047 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1049 C67_g((0 << 29) | //creg
1050 (0 << 28) | //inv
1051 (C67_map_regn(c) << 23) | //dst
1052 (C67_map_regn(b) << 18) | //src2 (possible x path)
1053 (C67_map_regn(a) << 13) | //src1
1054 (xpath << 12) | //x cross path if opposite sides
1055 (0x11 << 5) | //opcode
1056 (0x6 << 2) | //opcode fixed
1057 (C67_map_regs(c) << 1) | //side of dest
1058 (0 << 0)); //parallel
1059 } else if (strstr(s, "SUBDP.L") == s) {
1060 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1062 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1064 C67_g((0 << 29) | //creg
1065 (0 << 28) | //inv
1066 (C67_map_regn(c) << 23) | //dst
1067 (C67_map_regn(b) << 18) | //src2 (possible x path)
1068 (C67_map_regn(a) << 13) | //src1
1069 (xpath << 12) | //x cross path if opposite sides
1070 (0x19 << 5) | //opcode
1071 (0x6 << 2) | //opcode fixed
1072 (C67_map_regs(c) << 1) | //side of dest
1073 (0 << 0)); //parallel
1074 } else if (strstr(s, "MPYSP.M") == s) {
1075 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1077 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1079 C67_g((0 << 29) | //creg
1080 (0 << 28) | //inv
1081 (C67_map_regn(c) << 23) | //dst
1082 (C67_map_regn(b) << 18) | //src2 (possible x path)
1083 (C67_map_regn(a) << 13) | //src1
1084 (xpath << 12) | //x cross path if opposite sides
1085 (0x1c << 7) | //opcode
1086 (0x0 << 2) | //opcode fixed
1087 (C67_map_regs(c) << 1) | //side of dest
1088 (0 << 0)); //parallel
1089 } else if (strstr(s, "MPYDP.M") == s) {
1090 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1092 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1094 C67_g((0 << 29) | //creg
1095 (0 << 28) | //inv
1096 (C67_map_regn(c) << 23) | //dst
1097 (C67_map_regn(b) << 18) | //src2 (possible x path)
1098 (C67_map_regn(a) << 13) | //src1
1099 (xpath << 12) | //x cross path if opposite sides
1100 (0x0e << 7) | //opcode
1101 (0x0 << 2) | //opcode fixed
1102 (C67_map_regs(c) << 1) | //side of dest
1103 (0 << 0)); //parallel
1104 } else if (strstr(s, "MPYI.M") == s) {
1105 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1107 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1109 C67_g((0 << 29) | //creg
1110 (0 << 28) | //inv
1111 (C67_map_regn(c) << 23) | //dst
1112 (C67_map_regn(b) << 18) | //src2
1113 (C67_map_regn(a) << 13) | //src1 (cst5)
1114 (xpath << 12) | //x cross path if opposite sides
1115 (0x4 << 7) | //opcode
1116 (0x0 << 2) | //opcode fixed
1117 (C67_map_regs(c) << 1) | //side of dest
1118 (0 << 0)); //parallel
1119 } else if (strstr(s, "SHR.S") == s) {
1120 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1122 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1124 C67_g((0 << 29) | //creg
1125 (0 << 28) | //inv
1126 (C67_map_regn(c) << 23) | //dst
1127 (C67_map_regn(b) << 18) | //src2
1128 (C67_map_regn(a) << 13) | //src1
1129 (xpath << 12) | //x cross path if opposite sides
1130 (0x37 << 6) | //opcode
1131 (0x8 << 2) | //opcode fixed
1132 (C67_map_regs(c) << 1) | //side of dest
1133 (0 << 0)); //parallel
1134 } else if (strstr(s, "SHRU.S") == s) {
1135 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1137 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1139 C67_g((0 << 29) | //creg
1140 (0 << 28) | //inv
1141 (C67_map_regn(c) << 23) | //dst
1142 (C67_map_regn(b) << 18) | //src2
1143 (C67_map_regn(a) << 13) | //src1
1144 (xpath << 12) | //x cross path if opposite sides
1145 (0x27 << 6) | //opcode
1146 (0x8 << 2) | //opcode fixed
1147 (C67_map_regs(c) << 1) | //side of dest
1148 (0 << 0)); //parallel
1149 } else if (strstr(s, "SHL.S") == s) {
1150 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1152 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1154 C67_g((0 << 29) | //creg
1155 (0 << 28) | //inv
1156 (C67_map_regn(c) << 23) | //dst
1157 (C67_map_regn(b) << 18) | //src2
1158 (C67_map_regn(a) << 13) | //src1
1159 (xpath << 12) | //x cross path if opposite sides
1160 (0x33 << 6) | //opcode
1161 (0x8 << 2) | //opcode fixed
1162 (C67_map_regs(c) << 1) | //side of dest
1163 (0 << 0)); //parallel
1164 } else if (strstr(s, "||ADDK") == s) {
1165 xpath = 0; // no xpath required just use the side of the src/dst
1167 C67_g((0 << 29) | //creg
1168 (0 << 28) | //inv
1169 (C67_map_regn(b) << 23) | //dst
1170 (a << 07) | //scst16
1171 (0x14 << 2) | //opcode fixed
1172 (C67_map_regs(b) << 1) | //side of dst
1173 (1 << 0)); //parallel
1174 } else if (strstr(s, "ADDK") == s) {
1175 xpath = 0; // no xpath required just use the side of the src/dst
1177 C67_g((0 << 29) | //creg
1178 (0 << 28) | //inv
1179 (C67_map_regn(b) << 23) | //dst
1180 (a << 07) | //scst16
1181 (0x14 << 2) | //opcode fixed
1182 (C67_map_regs(b) << 1) | //side of dst
1183 (0 << 0)); //parallel
1184 } else if (strstr(s, "NOP") == s) {
1185 C67_g(((a - 1) << 13) | //no of cycles
1186 (0 << 0)); //parallel
1187 } else
1188 ALWAYS_ASSERT(FALSE);
1190 #ifdef ASSEMBLY_LISTING_C67
1191 fprintf(f, " %s %d %d %d\n", s, a, b, c);
1192 #endif
1196 //r=reg to load, fr=from reg, symbol for relocation, constant
1198 void C67_MVKL(int r, int fc)
1200 C67_asm("MVKL.", fc, r, 0);
1203 void C67_MVKH(int r, int fc)
1205 C67_asm("MVKH.", fc, r, 0);
1208 void C67_STB_SP_A0(int r)
1210 C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB r,*+SP[A0]
1213 void C67_STH_SP_A0(int r)
1215 C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH r,*+SP[A0]
1218 void C67_STW_SP_A0(int r)
1220 C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW r,*+SP[A0]
1223 void C67_STB_PTR(int r, int r2)
1225 C67_asm("STB.D *", r, r2, 0); // STB r, *r2
1228 void C67_STH_PTR(int r, int r2)
1230 C67_asm("STH.D *", r, r2, 0); // STH r, *r2
1233 void C67_STW_PTR(int r, int r2)
1235 C67_asm("STW.D *", r, r2, 0); // STW r, *r2
1238 void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1240 C67_asm("STW.D +*", r, r2, n); // STW r, *+r2
1243 void C67_PUSH(int r)
1245 C67_asm("STW.D SP POST DEC", r, 0, 0); // STW r,*SP--
1248 void C67_LDW_SP_A0(int r)
1250 C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW *+SP[A0],r
1253 void C67_LDDW_SP_A0(int r)
1255 C67_asm("LDDW.D *+SP[A0]", r, 0, 0); // LDDW *+SP[A0],r
1258 void C67_LDH_SP_A0(int r)
1260 C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH *+SP[A0],r
1263 void C67_LDB_SP_A0(int r)
1265 C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB *+SP[A0],r
1268 void C67_LDHU_SP_A0(int r)
1270 C67_asm("LDHU.D *+SP[A0]", r, 0, 0); // LDHU *+SP[A0],r
1273 void C67_LDBU_SP_A0(int r)
1275 C67_asm("LDBU.D *+SP[A0]", r, 0, 0); // LDBU *+SP[A0],r
1278 void C67_LDW_PTR(int r, int r2)
1280 C67_asm("LDW.D *", r, r2, 0); // LDW *r,r2
1283 void C67_LDDW_PTR(int r, int r2)
1285 C67_asm("LDDW.D *", r, r2, 0); // LDDW *r,r2
1288 void C67_LDH_PTR(int r, int r2)
1290 C67_asm("LDH.D *", r, r2, 0); // LDH *r,r2
1293 void C67_LDB_PTR(int r, int r2)
1295 C67_asm("LDB.D *", r, r2, 0); // LDB *r,r2
1298 void C67_LDHU_PTR(int r, int r2)
1300 C67_asm("LDHU.D *", r, r2, 0); // LDHU *r,r2
1303 void C67_LDBU_PTR(int r, int r2)
1305 C67_asm("LDBU.D *", r, r2, 0); // LDBU *r,r2
1308 void C67_LDW_PTR_PRE_INC(int r, int r2)
1310 C67_asm("LDW.D +*", r, r2, 0); // LDW *+r,r2
1313 void C67_POP(int r)
1315 C67_asm("LDW.D SP PRE INC", r, 0, 0); // LDW *++SP,r
1318 void C67_POP_DW(int r)
1320 C67_asm("LDDW.D SP PRE INC", r, 0, 0); // LDDW *++SP,r
1323 void C67_CMPLT(int s1, int s2, int dst)
1325 C67_asm("CMPLT.L1", s1, s2, dst);
1328 void C67_CMPGT(int s1, int s2, int dst)
1330 C67_asm("CMPGT.L1", s1, s2, dst);
1333 void C67_CMPEQ(int s1, int s2, int dst)
1335 C67_asm("CMPEQ.L1", s1, s2, dst);
1338 void C67_CMPLTU(int s1, int s2, int dst)
1340 C67_asm("CMPLTU.L1", s1, s2, dst);
1343 void C67_CMPGTU(int s1, int s2, int dst)
1345 C67_asm("CMPGTU.L1", s1, s2, dst);
1349 void C67_CMPLTSP(int s1, int s2, int dst)
1351 C67_asm("CMPLTSP.S1", s1, s2, dst);
1354 void C67_CMPGTSP(int s1, int s2, int dst)
1356 C67_asm("CMPGTSP.S1", s1, s2, dst);
1359 void C67_CMPEQSP(int s1, int s2, int dst)
1361 C67_asm("CMPEQSP.S1", s1, s2, dst);
1364 void C67_CMPLTDP(int s1, int s2, int dst)
1366 C67_asm("CMPLTDP.S1", s1, s2, dst);
1369 void C67_CMPGTDP(int s1, int s2, int dst)
1371 C67_asm("CMPGTDP.S1", s1, s2, dst);
1374 void C67_CMPEQDP(int s1, int s2, int dst)
1376 C67_asm("CMPEQDP.S1", s1, s2, dst);
1380 void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2
1382 C67_asm("B.S2", inv, r1, r2);
1386 // call with how many 32 bit words to skip
1387 // (0 would branch to the branch instruction)
1389 void C67_B_DISP(int disp) // B +2 Branch with constant displacement
1391 // Branch point is relative to the 8 word fetch packet
1393 // we will assume the text section always starts on an 8 word (32 byte boundary)
1395 // so add in how many words into the fetch packet the branch is
1398 C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1401 void C67_NOP(int n)
1403 C67_asm("NOP", n, 0, 0);
1406 void C67_ADDK(int n, int r)
1408 ALWAYS_ASSERT(abs(n) < 32767);
1410 C67_asm("ADDK", n, r, 0);
1413 void C67_ADDK_PARALLEL(int n, int r)
1415 ALWAYS_ASSERT(abs(n) < 32767);
1417 C67_asm("||ADDK", n, r, 0);
1420 void C67_Adjust_ADDK(int *inst, int n)
1422 ALWAYS_ASSERT(abs(n) < 32767);
1424 *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1427 void C67_MV(int r, int v)
1429 C67_asm("MV.L", 0, r, v);
1433 void C67_DPTRUNC(int r, int v)
1435 C67_asm("DPTRUNC.L", 0, r, v);
1438 void C67_SPTRUNC(int r, int v)
1440 C67_asm("SPTRUNC.L", 0, r, v);
1443 void C67_INTSP(int r, int v)
1445 C67_asm("INTSP.L", 0, r, v);
1448 void C67_INTDP(int r, int v)
1450 C67_asm("INTDP.L", 0, r, v);
1453 void C67_INTSPU(int r, int v)
1455 C67_asm("INTSPU.L", 0, r, v);
1458 void C67_INTDPU(int r, int v)
1460 C67_asm("INTDPU.L", 0, r, v);
1463 void C67_SPDP(int r, int v)
1465 C67_asm("SPDP.L", 0, r, v);
1468 void C67_DPSP(int r, int v) // note regs must be on the same side
1470 C67_asm("DPSP.L", 0, r, v);
1473 void C67_ADD(int r, int v)
1475 C67_asm("ADD.L", v, r, v);
1478 void C67_SUB(int r, int v)
1480 C67_asm("SUB.L", v, r, v);
1483 void C67_AND(int r, int v)
1485 C67_asm("AND.L", v, r, v);
1488 void C67_OR(int r, int v)
1490 C67_asm("OR.L", v, r, v);
1493 void C67_XOR(int r, int v)
1495 C67_asm("XOR.L", v, r, v);
1498 void C67_ADDSP(int r, int v)
1500 C67_asm("ADDSP.L", v, r, v);
1503 void C67_SUBSP(int r, int v)
1505 C67_asm("SUBSP.L", v, r, v);
1508 void C67_MPYSP(int r, int v)
1510 C67_asm("MPYSP.M", v, r, v);
1513 void C67_ADDDP(int r, int v)
1515 C67_asm("ADDDP.L", v, r, v);
1518 void C67_SUBDP(int r, int v)
1520 C67_asm("SUBDP.L", v, r, v);
1523 void C67_MPYDP(int r, int v)
1525 C67_asm("MPYDP.M", v, r, v);
1528 void C67_MPYI(int r, int v)
1530 C67_asm("MPYI.M", v, r, v);
1533 void C67_SHL(int r, int v)
1535 C67_asm("SHL.S", r, v, v);
1538 void C67_SHRU(int r, int v)
1540 C67_asm("SHRU.S", r, v, v);
1543 void C67_SHR(int r, int v)
1545 C67_asm("SHR.S", r, v, v);
1550 /* load 'r' from value 'sv' */
1551 void load(int r, SValue * sv)
1553 int v, t, ft, fc, fr, size = 0, element;
1554 BOOL Unsigned = FALSE;
1555 SValue v1;
1557 fr = sv->r;
1558 ft = sv->type.t;
1559 fc = sv->c.i;
1561 v = fr & VT_VALMASK;
1562 if (fr & VT_LVAL) {
1563 if (v == VT_LLOCAL) {
1564 v1.type.t = VT_INT;
1565 v1.r = VT_LOCAL | VT_LVAL;
1566 v1.c.i = fc;
1567 load(r, &v1);
1568 fr = r;
1569 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
1570 tcc_error("long double not supported");
1571 } else if ((ft & VT_TYPE) == VT_BYTE) {
1572 size = 1;
1573 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1574 size = 1;
1575 Unsigned = TRUE;
1576 } else if ((ft & VT_TYPE) == VT_SHORT) {
1577 size = 2;
1578 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1579 size = 2;
1580 Unsigned = TRUE;
1581 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1582 size = 8;
1583 } else {
1584 size = 4;
1587 // check if fc is a positive reference on the stack,
1588 // if it is tcc is referencing what it thinks is a parameter
1589 // on the stack, so check if it is really in a register.
1592 if (v == VT_LOCAL && fc > 0) {
1593 int stack_pos = 8;
1595 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1596 if (fc == stack_pos)
1597 break;
1599 stack_pos += TranslateStackToReg[t];
1602 // param has been pushed on stack, get it like a local var
1604 fc = ParamLocOnStack[t] - 8;
1607 if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect
1609 if (size == 1) {
1610 if (Unsigned)
1611 C67_LDBU_PTR(v, r); // LDBU *v,r
1612 else
1613 C67_LDB_PTR(v, r); // LDB *v,r
1614 } else if (size == 2) {
1615 if (Unsigned)
1616 C67_LDHU_PTR(v, r); // LDHU *v,r
1617 else
1618 C67_LDH_PTR(v, r); // LDH *v,r
1619 } else if (size == 4) {
1620 C67_LDW_PTR(v, r); // LDW *v,r
1621 } else if (size == 8) {
1622 C67_LDDW_PTR(v, r); // LDDW *v,r
1625 C67_NOP(4); // NOP 4
1626 return;
1627 } else if (fr & VT_SYM) {
1628 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1629 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1632 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1633 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1636 if (size == 1) {
1637 if (Unsigned)
1638 C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r
1639 else
1640 C67_LDB_PTR(C67_A0, r); // LDB *A0,r
1641 } else if (size == 2) {
1642 if (Unsigned)
1643 C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r
1644 else
1645 C67_LDH_PTR(C67_A0, r); // LDH *A0,r
1646 } else if (size == 4) {
1647 C67_LDW_PTR(C67_A0, r); // LDW *A0,r
1648 } else if (size == 8) {
1649 C67_LDDW_PTR(C67_A0, r); // LDDW *A0,r
1652 C67_NOP(4); // NOP 4
1653 return;
1654 } else {
1655 element = size;
1657 // divide offset in bytes to create element index
1658 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1659 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1661 if (size == 1) {
1662 if (Unsigned)
1663 C67_LDBU_SP_A0(r); // LDBU r, SP[A0]
1664 else
1665 C67_LDB_SP_A0(r); // LDB r, SP[A0]
1666 } else if (size == 2) {
1667 if (Unsigned)
1668 C67_LDHU_SP_A0(r); // LDHU r, SP[A0]
1669 else
1670 C67_LDH_SP_A0(r); // LDH r, SP[A0]
1671 } else if (size == 4) {
1672 C67_LDW_SP_A0(r); // LDW r, SP[A0]
1673 } else if (size == 8) {
1674 C67_LDDW_SP_A0(r); // LDDW r, SP[A0]
1678 C67_NOP(4); // NOP 4
1679 return;
1681 } else {
1682 if (v == VT_CONST) {
1683 if (fr & VT_SYM) {
1684 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1685 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1687 C67_MVKL(r, fc); //r=reg to load, constant
1688 C67_MVKH(r, fc); //r=reg to load, constant
1689 } else if (v == VT_LOCAL) {
1690 C67_MVKL(r, fc + 8); //r=reg to load, constant C67 stack points to next free
1691 C67_MVKH(r, fc + 8); //r=reg to load, constant
1692 C67_ADD(C67_FP, r); // MV v,r v -> r
1693 } else if (v == VT_CMP) {
1694 C67_MV(C67_compare_reg, r); // MV v,r v -> r
1695 } else if (v == VT_JMP || v == VT_JMPI) {
1696 t = v & 1;
1697 C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
1698 C67_MVKL(r, t); // r=reg to load, 0 or 1 (do this while branching)
1699 C67_NOP(4); // NOP 4
1700 gsym(fc); // modifies other branches to branch here
1701 C67_MVKL(r, t ^ 1); // r=reg to load, 0 or 1
1702 } else if (v != r) {
1703 C67_MV(v, r); // MV v,r v -> r
1705 if ((ft & VT_BTYPE) == VT_DOUBLE)
1706 C67_MV(v + 1, r + 1); // MV v,r v -> r
1712 /* store register 'r' in lvalue 'v' */
1713 void store(int r, SValue * v)
1715 int fr, bt, ft, fc, size, t, element;
1717 ft = v->type.t;
1718 fc = v->c.i;
1719 fr = v->r & VT_VALMASK;
1720 bt = ft & VT_BTYPE;
1721 /* XXX: incorrect if float reg to reg */
1723 if (bt == VT_LDOUBLE) {
1724 tcc_error("long double not supported");
1725 } else {
1726 if (bt == VT_SHORT)
1727 size = 2;
1728 else if (bt == VT_BYTE)
1729 size = 1;
1730 else if (bt == VT_DOUBLE)
1731 size = 8;
1732 else
1733 size = 4;
1735 if ((v->r & VT_VALMASK) == VT_CONST) {
1736 /* constant memory reference */
1738 if (v->r & VT_SYM) {
1739 greloc(cur_text_section, v->sym, ind, R_C60LO16); // rem the inst need to be patched
1740 greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
1742 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1743 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1745 if (size == 1)
1746 C67_STB_PTR(r, C67_A0); // STB r, *A0
1747 else if (size == 2)
1748 C67_STH_PTR(r, C67_A0); // STH r, *A0
1749 else if (size == 4 || size == 8)
1750 C67_STW_PTR(r, C67_A0); // STW r, *A0
1752 if (size == 8)
1753 C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1); // STW r, *+A0[1]
1754 } else if ((v->r & VT_VALMASK) == VT_LOCAL) {
1755 // check case of storing to passed argument that
1756 // tcc thinks is on the stack but for C67 is
1757 // passed as a reg. However it may have been
1758 // saved to the stack, if that reg was required
1759 // for a call to a child function
1761 if (fc > 0) // argument ??
1763 // walk through sizes and figure which param
1765 int stack_pos = 8;
1767 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1768 if (fc == stack_pos)
1769 break;
1771 stack_pos += TranslateStackToReg[t];
1774 // param has been pushed on stack, get it like a local var
1775 fc = ParamLocOnStack[t] - 8;
1778 if (size == 8)
1779 element = 4;
1780 else
1781 element = size;
1783 // divide offset in bytes to create word index
1784 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1785 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1789 if (size == 1)
1790 C67_STB_SP_A0(r); // STB r, SP[A0]
1791 else if (size == 2)
1792 C67_STH_SP_A0(r); // STH r, SP[A0]
1793 else if (size == 4 || size == 8)
1794 C67_STW_SP_A0(r); // STW r, SP[A0]
1796 if (size == 8) {
1797 C67_ADDK(1, C67_A0); // ADDK 1,A0
1798 C67_STW_SP_A0(r + 1); // STW r, SP[A0]
1800 } else {
1801 if (size == 1)
1802 C67_STB_PTR(r, fr); // STB r, *fr
1803 else if (size == 2)
1804 C67_STH_PTR(r, fr); // STH r, *fr
1805 else if (size == 4 || size == 8)
1806 C67_STW_PTR(r, fr); // STW r, *fr
1808 if (size == 8) {
1809 C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1]
1815 /* 'is_jmp' is '1' if it is a jump */
1816 static void gcall_or_jmp(int is_jmp)
1818 int r;
1819 Sym *sym;
1821 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1822 /* constant case */
1823 if (vtop->r & VT_SYM) {
1824 /* relocation case */
1826 // get add into A0, then start the jump B3
1828 greloc(cur_text_section, vtop->sym, ind, R_C60LO16); // rem the inst need to be patched
1829 greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
1831 C67_MVKL(C67_A0, 0); //r=reg to load, constant
1832 C67_MVKH(C67_A0, 0); //r=reg to load, constant
1833 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // B.S2x A0
1835 if (is_jmp) {
1836 C67_NOP(5); // simple jump, just put NOP
1837 } else {
1838 // Call, must load return address into B3 during delay slots
1840 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1841 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1842 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1843 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1844 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1845 C67_NOP(3); // put remaining NOPs
1847 } else {
1848 /* put an empty PC32 relocation */
1849 ALWAYS_ASSERT(FALSE);
1851 } else {
1852 /* otherwise, indirect call */
1853 r = gv(RC_INT);
1854 C67_IREG_B_REG(0, C67_CREG_ZERO, r); // B.S2x r
1856 if (is_jmp) {
1857 C67_NOP(5); // simple jump, just put NOP
1858 } else {
1859 // Call, must load return address into B3 during delay slots
1861 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1862 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1863 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1864 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1865 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1866 C67_NOP(3); // put remaining NOPs
1871 /* Return the number of registers needed to return the struct, or 0 if
1872 returning via struct pointer. */
1873 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
1874 *ret_align = 1; // Never have to re-align return values for x86-64
1875 return 0;
1878 /* generate function call with address in (vtop->t, vtop->c) and free function
1879 context. Stack entry is popped */
1880 void gfunc_call(int nb_args)
1882 int i, r, size = 0;
1883 int args_sizes[NoCallArgsPassedOnStack];
1885 if (nb_args > NoCallArgsPassedOnStack) {
1886 tcc_error("more than 10 function params not currently supported");
1887 // handle more than 10, put some on the stack
1890 for (i = 0; i < nb_args; i++) {
1891 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1892 ALWAYS_ASSERT(FALSE);
1893 } else {
1894 /* simple type (currently always same size) */
1895 /* XXX: implicit cast ? */
1898 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1899 tcc_error("long long not supported");
1900 } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
1901 tcc_error("long double not supported");
1902 } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1903 size = 8;
1904 } else {
1905 size = 4;
1908 // put the parameter into the corresponding reg (pair)
1910 r = gv(RC_C67_A4 << (2 * i));
1912 // must put on stack because with 1 pass compiler , no way to tell
1913 // if an up coming nested call might overwrite these regs
1915 C67_PUSH(r);
1917 if (size == 8) {
1918 C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3); // STW r, *+SP[3] (go back and put the other)
1920 args_sizes[i] = size;
1922 vtop--;
1924 // POP all the params on the stack into registers for the
1925 // immediate call (in reverse order)
1927 for (i = nb_args - 1; i >= 0; i--) {
1929 if (args_sizes[i] == 8)
1930 C67_POP_DW(TREG_C67_A4 + i * 2);
1931 else
1932 C67_POP(TREG_C67_A4 + i * 2);
1934 gcall_or_jmp(0);
1935 vtop--;
1939 // to be compatible with Code Composer for the C67
1940 // the first 10 parameters must be passed in registers
1941 // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1942 // ending with B12:B13.
1944 // When a call is made, if the caller has its parameters
1945 // in regs A4-B13 these must be saved before/as the call
1946 // parameters are loaded and restored upon return (or if/when needed).
1948 /* generate function prolog of type 't' */
1949 void gfunc_prolog(Sym *func_sym)
1951 CType *func_type = &func_sym->type;
1952 int addr, align, size, func_call, i;
1953 Sym *sym;
1954 CType *type;
1956 sym = func_type->ref;
1957 func_call = sym->f.func_call;
1958 addr = 8;
1959 /* if the function returns a structure, then add an
1960 implicit pointer parameter */
1961 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1962 func_vc = addr;
1963 addr += 4;
1966 NoOfCurFuncArgs = 0;
1968 /* define parameters */
1969 while ((sym = sym->next) != NULL) {
1970 type = &sym->type;
1971 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
1972 size = type_size(type, &align);
1973 size = (size + 3) & ~3;
1975 // keep track of size of arguments so
1976 // we can translate where tcc thinks they
1977 // are on the stack into the appropriate reg
1979 TranslateStackToReg[NoOfCurFuncArgs] = size;
1980 NoOfCurFuncArgs++;
1982 #ifdef FUNC_STRUCT_PARAM_AS_PTR
1983 /* structs are passed as pointer */
1984 if ((type->t & VT_BTYPE) == VT_STRUCT) {
1985 size = 4;
1987 #endif
1988 addr += size;
1990 func_ret_sub = 0;
1991 /* pascal type call ? */
1992 if (func_call == FUNC_STDCALL)
1993 func_ret_sub = addr - 8;
1995 C67_MV(C67_FP, C67_A0); // move FP -> A0
1996 C67_MV(C67_SP, C67_FP); // move SP -> FP
1998 // place all the args passed in regs onto the stack
2000 loc = 0;
2001 for (i = 0; i < NoOfCurFuncArgs; i++) {
2003 ParamLocOnStack[i] = loc; // remember where the param is
2004 loc += -8;
2006 C67_PUSH(TREG_C67_A4 + i * 2);
2008 if (TranslateStackToReg[i] == 8) {
2009 C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3); // STW r, *+SP[1] (go back and put the other)
2013 TotalBytesPushedOnStack = -loc;
2015 func_sub_sp_offset = ind; // remember where we put the stack instruction
2016 C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily)
2018 C67_PUSH(C67_A0);
2019 C67_PUSH(C67_B3);
2022 /* generate function epilog */
2023 void gfunc_epilog(void)
2026 int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2027 C67_POP(C67_B3);
2028 C67_NOP(4); // NOP wait for load
2029 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3
2030 C67_POP(C67_FP);
2031 C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP
2032 C67_Adjust_ADDK((int *) (cur_text_section->data +
2033 func_sub_sp_offset),
2034 -local + TotalBytesPushedOnStack);
2035 C67_NOP(3); // NOP
2039 ST_FUNC void gen_fill_nops(int bytes)
2041 if ((bytes & 3))
2042 tcc_error("alignment of code section not multiple of 4");
2043 while (bytes > 0) {
2044 C67_NOP(4);
2045 bytes -= 4;
2049 /* generate a jump to a label */
2050 int gjmp(int t)
2052 int ind1 = ind;
2053 if (nocode_wanted)
2054 return t;
2056 C67_MVKL(C67_A0, t); //r=reg to load, constant
2057 C67_MVKH(C67_A0, t); //r=reg to load, constant
2058 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // [!R] B.S2x A0
2059 C67_NOP(5);
2060 return ind1;
2063 /* generate a jump to a fixed address */
2064 void gjmp_addr(int a)
2066 Sym *sym;
2067 // I guess this routine is used for relative short
2068 // local jumps, for now just handle it as the general
2069 // case
2071 // define a label that will be relocated
2073 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
2074 greloc(cur_text_section, sym, ind, R_C60LO16);
2075 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
2077 gjmp(0); // place a zero there later the symbol will be added to it
2080 /* generate a test. set 'inv' to invert test. Stack entry is popped */
2081 ST_FUNC int gjmp_cond(int op, int t)
2083 int ind1;
2084 int inv = op & 1;
2085 if (nocode_wanted)
2086 return t;
2088 /* fast case : can jump directly since flags are set */
2089 // C67 uses B2 sort of as flags register
2090 ind1 = ind;
2091 C67_MVKL(C67_A0, t); //r=reg to load, constant
2092 C67_MVKH(C67_A0, t); //r=reg to load, constant
2094 if (C67_compare_reg != TREG_EAX && // check if not already in a conditional test reg
2095 C67_compare_reg != TREG_EDX &&
2096 C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
2097 C67_MV(C67_compare_reg, C67_B2);
2098 C67_compare_reg = C67_B2;
2101 C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x A0
2102 C67_NOP(5);
2103 t = ind1; //return where we need to patch
2105 return t;
2108 ST_FUNC int gjmp_append(int n0, int t)
2110 if (n0) {
2111 int n = n0, *p;
2112 /* insert vtop->c jump list in t */
2114 // I guess the idea is to traverse to the
2115 // null at the end of the list and store t
2116 // there
2117 while (n != 0) {
2118 p = (int *) (cur_text_section->data + n);
2120 // extract 32 bit address from MVKH/MVKL
2121 n = ((*p >> 7) & 0xffff);
2122 n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2124 *p |= (t & 0xffff) << 7;
2125 *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2126 t = n0;
2128 return t;
2131 /* generate an integer binary operation */
2132 void gen_opi(int op)
2134 int r, fr, opc, t;
2136 switch (op) {
2137 case '+':
2138 case TOK_ADDC1: /* add with carry generation */
2139 opc = 0;
2140 gen_op8:
2143 // C67 can't do const compares, must load into a reg
2144 // so just go to gv2 directly - tktk
2148 if (op >= TOK_ULT && op <= TOK_GT)
2149 gv2(RC_INT_BSIDE, RC_INT); // make sure r (src1) is on the B Side of CPU
2150 else
2151 gv2(RC_INT, RC_INT);
2153 r = vtop[-1].r;
2154 fr = vtop[0].r;
2156 C67_compare_reg = C67_B2;
2159 if (op == TOK_LT) {
2160 C67_CMPLT(r, fr, C67_B2);
2161 C67_invert_test = FALSE;
2162 } else if (op == TOK_GE) {
2163 C67_CMPLT(r, fr, C67_B2);
2164 C67_invert_test = TRUE;
2165 } else if (op == TOK_GT) {
2166 C67_CMPGT(r, fr, C67_B2);
2167 C67_invert_test = FALSE;
2168 } else if (op == TOK_LE) {
2169 C67_CMPGT(r, fr, C67_B2);
2170 C67_invert_test = TRUE;
2171 } else if (op == TOK_EQ) {
2172 C67_CMPEQ(r, fr, C67_B2);
2173 C67_invert_test = FALSE;
2174 } else if (op == TOK_NE) {
2175 C67_CMPEQ(r, fr, C67_B2);
2176 C67_invert_test = TRUE;
2177 } else if (op == TOK_ULT) {
2178 C67_CMPLTU(r, fr, C67_B2);
2179 C67_invert_test = FALSE;
2180 } else if (op == TOK_UGE) {
2181 C67_CMPLTU(r, fr, C67_B2);
2182 C67_invert_test = TRUE;
2183 } else if (op == TOK_UGT) {
2184 C67_CMPGTU(r, fr, C67_B2);
2185 C67_invert_test = FALSE;
2186 } else if (op == TOK_ULE) {
2187 C67_CMPGTU(r, fr, C67_B2);
2188 C67_invert_test = TRUE;
2189 } else if (op == '+')
2190 C67_ADD(fr, r); // ADD r,fr,r
2191 else if (op == '-')
2192 C67_SUB(fr, r); // SUB r,fr,r
2193 else if (op == '&')
2194 C67_AND(fr, r); // AND r,fr,r
2195 else if (op == '|')
2196 C67_OR(fr, r); // OR r,fr,r
2197 else if (op == '^')
2198 C67_XOR(fr, r); // XOR r,fr,r
2199 else
2200 ALWAYS_ASSERT(FALSE);
2202 vtop--;
2203 if (op >= TOK_ULT && op <= TOK_GT)
2204 vset_VT_CMP(0x80);
2205 break;
2206 case '-':
2207 case TOK_SUBC1: /* sub with carry generation */
2208 opc = 5;
2209 goto gen_op8;
2210 case TOK_ADDC2: /* add with carry use */
2211 opc = 2;
2212 goto gen_op8;
2213 case TOK_SUBC2: /* sub with carry use */
2214 opc = 3;
2215 goto gen_op8;
2216 case '&':
2217 opc = 4;
2218 goto gen_op8;
2219 case '^':
2220 opc = 6;
2221 goto gen_op8;
2222 case '|':
2223 opc = 1;
2224 goto gen_op8;
2225 case '*':
2226 case TOK_UMULL:
2227 gv2(RC_INT, RC_INT);
2228 r = vtop[-1].r;
2229 fr = vtop[0].r;
2230 vtop--;
2231 C67_MPYI(fr, r); // 32 bit multiply fr,r,fr
2232 C67_NOP(8); // NOP 8 for worst case
2233 break;
2234 case TOK_SHL:
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_SHL(fr, r); // arithmetic/logical shift
2240 break;
2242 case TOK_SHR:
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_SHRU(fr, r); // logical shift
2248 break;
2250 case TOK_SAR:
2251 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2252 r = vtop[-1].r;
2253 fr = vtop[0].r;
2254 vtop--;
2255 C67_SHR(fr, r); // arithmetic shift
2256 break;
2258 case '/':
2259 t = TOK__divi;
2260 call_func:
2261 vswap();
2262 /* call generic idiv function */
2263 vpush_helper_func(t);
2264 vrott(3);
2265 gfunc_call(2);
2266 vpushi(0);
2267 vtop->r = REG_IRET;
2268 vtop->r2 = VT_CONST;
2269 break;
2270 case TOK_UDIV:
2271 case TOK_PDIV:
2272 t = TOK__divu;
2273 goto call_func;
2274 case '%':
2275 t = TOK__remi;
2276 goto call_func;
2277 case TOK_UMOD:
2278 t = TOK__remu;
2279 goto call_func;
2281 default:
2282 opc = 7;
2283 goto gen_op8;
2287 /* generate a floating point operation 'v = t1 op t2' instruction. The
2288 two operands are guaranteed to have the same floating point type */
2289 /* XXX: need to use ST1 too */
2290 void gen_opf(int op)
2292 int ft, fc, fr, r;
2294 if (op >= TOK_ULT && op <= TOK_GT)
2295 gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
2296 else
2297 gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
2299 ft = vtop->type.t;
2300 fc = vtop->c.i;
2301 r = vtop->r;
2302 fr = vtop[-1].r;
2305 if ((ft & VT_BTYPE) == VT_LDOUBLE)
2306 tcc_error("long doubles not supported");
2308 if (op >= TOK_ULT && op <= TOK_GT) {
2310 r = vtop[-1].r;
2311 fr = vtop[0].r;
2313 C67_compare_reg = C67_B2;
2315 if (op == TOK_LT) {
2316 if ((ft & VT_BTYPE) == VT_DOUBLE)
2317 C67_CMPLTDP(r, fr, C67_B2);
2318 else
2319 C67_CMPLTSP(r, fr, C67_B2);
2321 C67_invert_test = FALSE;
2322 } else if (op == TOK_GE) {
2323 if ((ft & VT_BTYPE) == VT_DOUBLE)
2324 C67_CMPLTDP(r, fr, C67_B2);
2325 else
2326 C67_CMPLTSP(r, fr, C67_B2);
2328 C67_invert_test = TRUE;
2329 } else if (op == TOK_GT) {
2330 if ((ft & VT_BTYPE) == VT_DOUBLE)
2331 C67_CMPGTDP(r, fr, C67_B2);
2332 else
2333 C67_CMPGTSP(r, fr, C67_B2);
2335 C67_invert_test = FALSE;
2336 } else if (op == TOK_LE) {
2337 if ((ft & VT_BTYPE) == VT_DOUBLE)
2338 C67_CMPGTDP(r, fr, C67_B2);
2339 else
2340 C67_CMPGTSP(r, fr, C67_B2);
2342 C67_invert_test = TRUE;
2343 } else if (op == TOK_EQ) {
2344 if ((ft & VT_BTYPE) == VT_DOUBLE)
2345 C67_CMPEQDP(r, fr, C67_B2);
2346 else
2347 C67_CMPEQSP(r, fr, C67_B2);
2349 C67_invert_test = FALSE;
2350 } else if (op == TOK_NE) {
2351 if ((ft & VT_BTYPE) == VT_DOUBLE)
2352 C67_CMPEQDP(r, fr, C67_B2);
2353 else
2354 C67_CMPEQSP(r, fr, C67_B2);
2356 C67_invert_test = TRUE;
2357 } else {
2358 ALWAYS_ASSERT(FALSE);
2360 vset_VT_CMP(0x80);
2361 } else {
2362 if (op == '+') {
2363 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2364 C67_ADDDP(r, fr); // ADD fr,r,fr
2365 C67_NOP(6);
2366 } else {
2367 C67_ADDSP(r, fr); // ADD fr,r,fr
2368 C67_NOP(3);
2370 vtop--;
2371 } else if (op == '-') {
2372 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2373 C67_SUBDP(r, fr); // SUB fr,r,fr
2374 C67_NOP(6);
2375 } else {
2376 C67_SUBSP(r, fr); // SUB fr,r,fr
2377 C67_NOP(3);
2379 vtop--;
2380 } else if (op == '*') {
2381 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2382 C67_MPYDP(r, fr); // MPY fr,r,fr
2383 C67_NOP(9);
2384 } else {
2385 C67_MPYSP(r, fr); // MPY fr,r,fr
2386 C67_NOP(3);
2388 vtop--;
2389 } else if (op == '/') {
2390 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2391 // must call intrinsic DP floating point divide
2392 vswap();
2393 /* call generic idiv function */
2394 vpush_helper_func(TOK__divd);
2395 vrott(3);
2396 gfunc_call(2);
2397 vpushi(0);
2398 vtop->r = REG_FRET;
2399 vtop->r2 = REG_IRE2;
2401 } else {
2402 // must call intrinsic SP floating point divide
2403 vswap();
2404 /* call generic idiv function */
2405 vpush_helper_func(TOK__divf);
2406 vrott(3);
2407 gfunc_call(2);
2408 vpushi(0);
2409 vtop->r = REG_FRET;
2410 vtop->r2 = VT_CONST;
2412 } else
2413 ALWAYS_ASSERT(FALSE);
2420 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2421 and 'long long' cases. */
2422 void gen_cvt_itof(int t)
2424 int r;
2426 gv(RC_INT);
2427 r = vtop->r;
2429 if ((t & VT_BTYPE) == VT_DOUBLE) {
2430 if (t & VT_UNSIGNED)
2431 C67_INTDPU(r, r);
2432 else
2433 C67_INTDP(r, r);
2435 C67_NOP(4);
2436 vtop->type.t = VT_DOUBLE;
2437 } else {
2438 if (t & VT_UNSIGNED)
2439 C67_INTSPU(r, r);
2440 else
2441 C67_INTSP(r, r);
2442 C67_NOP(3);
2443 vtop->type.t = VT_FLOAT;
2448 /* convert fp to int 't' type */
2449 /* XXX: handle long long case */
2450 void gen_cvt_ftoi(int t)
2452 int r;
2454 gv(RC_FLOAT);
2455 r = vtop->r;
2457 if (t != VT_INT)
2458 tcc_error("long long not supported");
2459 else {
2460 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2461 C67_DPTRUNC(r, r);
2462 C67_NOP(3);
2463 } else {
2464 C67_SPTRUNC(r, r);
2465 C67_NOP(3);
2468 vtop->type.t = VT_INT;
2473 /* convert from one floating point type to another */
2474 void gen_cvt_ftof(int t)
2476 int r, r2;
2478 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2479 (t & VT_BTYPE) == VT_FLOAT) {
2480 // convert double to float
2482 gv(RC_FLOAT); // get it in a register pair
2484 r = vtop->r;
2486 C67_DPSP(r, r); // convert it to SP same register
2487 C67_NOP(3);
2489 vtop->type.t = VT_FLOAT;
2490 vtop->r2 = VT_CONST; // set this as unused
2491 } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
2492 (t & VT_BTYPE) == VT_DOUBLE) {
2493 // convert float to double
2495 gv(RC_FLOAT); // get it in a register
2497 r = vtop->r;
2499 if (r == TREG_EAX) { // make sure the paired reg is avail
2500 r2 = get_reg(RC_ECX);
2501 } else if (r == TREG_EDX) {
2502 r2 = get_reg(RC_ST0);
2503 } else {
2504 ALWAYS_ASSERT(FALSE);
2505 r2 = 0; /* avoid warning */
2508 C67_SPDP(r, r); // convert it to DP same register
2509 C67_NOP(1);
2511 vtop->type.t = VT_DOUBLE;
2512 vtop->r2 = r2; // set this as unused
2513 } else {
2514 ALWAYS_ASSERT(FALSE);
2518 /* computed goto support */
2519 void ggoto(void)
2521 gcall_or_jmp(1);
2522 vtop--;
2525 /* Save the stack pointer onto the stack and return the location of its address */
2526 ST_FUNC void gen_vla_sp_save(int addr) {
2527 tcc_error("variable length arrays unsupported for this target");
2530 /* Restore the SP from a location on the stack */
2531 ST_FUNC void gen_vla_sp_restore(int addr) {
2532 tcc_error("variable length arrays unsupported for this target");
2535 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2536 ST_FUNC void gen_vla_alloc(CType *type, int align) {
2537 tcc_error("variable length arrays unsupported for this target");
2540 /* end of C67 code generator */
2541 /*************************************************************/
2542 #endif
2543 /*************************************************************/