2 * TMS320C67xx code generator for TCC
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 */
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 */
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 */
64 TREG_EAX
= 0, // really A2
65 TREG_ECX
, // really A3
66 TREG_EDX
, // really B0
67 TREG_ST0
, // really B1
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 */
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) */
111 /******************************************************/
112 #else /* ! TARGET_DEFS_ONLY */
113 /******************************************************/
114 #define USING_GLOBALS
117 ST_DATA
const int reg_classes
[NB_REGS
] = {
118 /* eax */ RC_INT
| RC_FLOAT
| RC_EAX
,
119 // only allow even regs for floats (allow for doubles)
120 /* ecx */ RC_INT
| RC_ECX
,
121 /* edx */ RC_INT
| RC_INT_BSIDE
| RC_FLOAT
| RC_EDX
,
122 // only allow even regs for floats (allow for doubles)
123 /* st0 */ RC_INT
| RC_INT_BSIDE
| RC_ST0
,
136 /* A10 */ RC_C67_A10
,
137 /* A11 */ RC_C67_A11
,
138 /* B10 */ RC_C67_B10
,
139 /* B11 */ RC_C67_B11
,
140 /* A12 */ RC_C67_A10
,
141 /* A13 */ RC_C67_A11
,
142 /* B12 */ RC_C67_B10
,
146 // although tcc thinks it is passing parameters on the stack,
147 // the C67 really passes up to the first 10 params in special
148 // regs or regs pairs (for 64 bit params). So keep track of
149 // the stack offsets so we can translate to the appropriate
152 #define NoCallArgsPassedOnStack 10
154 int TranslateStackToReg
[NoCallArgsPassedOnStack
];
155 int ParamLocOnStack
[NoCallArgsPassedOnStack
];
156 int TotalBytesPushedOnStack
;
166 #define ALWAYS_ASSERT(x) \
169 tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
172 /******************************************************/
173 static unsigned long func_sub_sp_offset
;
174 static int func_ret_sub
;
176 static BOOL C67_invert_test
;
177 static int C67_compare_reg
;
179 #ifdef ASSEMBLY_LISTING_C67
188 #ifdef ASSEMBLY_LISTING_C67
189 fprintf(f
, " %08X", c
);
192 if (ind1
> (int) cur_text_section
->data_allocated
)
193 section_realloc(cur_text_section
, ind1
);
194 cur_text_section
->data
[ind
] = c
& 0xff;
195 cur_text_section
->data
[ind
+ 1] = (c
>> 8) & 0xff;
196 cur_text_section
->data
[ind
+ 2] = (c
>> 16) & 0xff;
197 cur_text_section
->data
[ind
+ 3] = (c
>> 24) & 0xff;
202 /* output a symbol and patch all calls to it */
203 void gsym_addr(int t
, int a
)
207 ptr
= (int *) (cur_text_section
->data
+ t
);
211 // extract 32 bit address from MVKH/MVKL
212 n
= ((*ptr
>> 7) & 0xffff);
213 n
|= ((*(ptr
+ 1) >> 7) & 0xffff) << 16;
215 // define a label that will be relocated
217 sym
= get_sym_ref(&char_pointer_type
, cur_text_section
, a
, 0);
218 greloc(cur_text_section
, sym
, t
, R_C60LO16
);
219 greloc(cur_text_section
, sym
, t
+ 4, R_C60HI16
);
221 // clear out where the pointer was
223 *ptr
&= ~(0xffff << 7);
224 *(ptr
+ 1) &= ~(0xffff << 7);
230 // these are regs that tcc doesn't really know about,
231 // but assign them unique values so the mapping routines
232 // can distinguish them
239 #define C67_CREG_ZERO -1 /* Special code for no condition reg test */
242 int ConvertRegToRegClass(int r
)
244 // only works for A4-B13
246 return RC_C67_A4
<< (r
- TREG_C67_A4
);
250 // map TCC reg to C67 reg number
252 int C67_map_regn(int r
)
254 if (r
== 0) // normal tcc regs
256 else if (r
== 1) // normal tcc regs
258 else if (r
== 2) // normal tcc regs
260 else if (r
== 3) // normal tcc regs
262 else if (r
>= TREG_C67_A4
&& r
<= TREG_C67_B13
) // these form a pattern of alt pairs
263 return (((r
& 0xfffffffc) >> 1) | (r
& 1)) + 2;
264 else if (r
== C67_A0
)
265 return 0; // set to A0 (offset reg)
266 else if (r
== C67_B2
)
267 return 2; // set to B2 (offset reg)
268 else if (r
== C67_B3
)
269 return 3; // set to B3 (return address reg)
270 else if (r
== C67_SP
)
271 return 15; // set to SP (B15) (offset reg)
272 else if (r
== C67_FP
)
273 return 15; // set to FP (A15) (offset reg)
274 else if (r
== C67_CREG_ZERO
)
275 return 0; // Special code for no condition reg test
277 ALWAYS_ASSERT(FALSE
);
282 // mapping from tcc reg number to
283 // C67 register to condition code field
285 // valid condition code regs are:
287 // tcc reg 2 ->B0 -> 1
288 // tcc reg 3 ->B1 -> 2
289 // tcc reg 0 -> A2 -> 5
290 // tcc reg 1 -> A3 -> X
293 int C67_map_regc(int r
)
295 if (r
== 0) // normal tcc regs
297 else if (r
== 2) // normal tcc regs
299 else if (r
== 3) // normal tcc regs
301 else if (r
== C67_B2
) // normal tcc regs
303 else if (r
== C67_CREG_ZERO
)
304 return 0; // Special code for no condition reg test
306 ALWAYS_ASSERT(FALSE
);
312 // map TCC reg to C67 reg side A or B
314 int C67_map_regs(int r
)
316 if (r
== 0) // normal tcc regs
318 else if (r
== 1) // normal tcc regs
320 else if (r
== 2) // normal tcc regs
322 else if (r
== 3) // normal tcc regs
324 else if (r
>= TREG_C67_A4
&& r
<= TREG_C67_B13
) // these form a pattern of alt pairs
326 else if (r
== C67_A0
)
327 return 0; // set to A side
328 else if (r
== C67_B2
)
329 return 1; // set to B side
330 else if (r
== C67_B3
)
331 return 1; // set to B side
332 else if (r
== C67_SP
)
333 return 0x1; // set to SP (B15) B side
334 else if (r
== C67_FP
)
335 return 0x0; // set to FP (A15) A side
337 ALWAYS_ASSERT(FALSE
);
342 int C67_map_S12(char *s
)
344 if (strstr(s
, ".S1") != NULL
)
346 else if (strcmp(s
, ".S2"))
349 ALWAYS_ASSERT(FALSE
);
354 int C67_map_D12(char *s
)
356 if (strstr(s
, ".D1") != NULL
)
358 else if (strcmp(s
, ".D2"))
361 ALWAYS_ASSERT(FALSE
);
368 void C67_asm(char *s
, int a
, int b
, int c
)
372 #ifdef ASSEMBLY_LISTING_C67
374 f
= fopen("TCC67_out.txt", "wt");
376 fprintf(f
, "%04X ", ind
);
379 if (strstr(s
, "MVKL") == s
) {
380 C67_g((C67_map_regn(b
) << 23) |
381 ((a
& 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b
) << 1));
382 } else if (strstr(s
, "MVKH") == s
) {
383 C67_g((C67_map_regn(b
) << 23) |
384 (((a
>> 16) & 0xffff) << 7) |
385 (0x1a << 2) | (C67_map_regs(b
) << 1));
386 } else if (strstr(s
, "STW.D SP POST DEC") == s
) {
387 C67_g((C67_map_regn(a
) << 23) | //src
388 (15 << 18) | //SP B15
389 (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
390 (0xa << 9) | //mode a = post dec ucst
391 (0 << 8) | //r (LDDW bit 0)
392 (1 << 7) | //y D1/D2 use B side
393 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
395 (C67_map_regs(a
) << 1) | //side of src
396 (0 << 0)); //parallel
397 } else if (strstr(s
, "STB.D *+SP[A0]") == s
) {
398 C67_g((C67_map_regn(a
) << 23) | //src
399 (15 << 18) | //base reg A15
400 (0 << 13) | //offset reg A0
401 (5 << 9) | //mode 5 = pos offset, base reg + off reg
402 (0 << 8) | //r (LDDW bit 0)
403 (0 << 7) | //y D1/D2 A side
404 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
406 (C67_map_regs(a
) << 1) | //side of src
407 (0 << 0)); //parallel
408 } else if (strstr(s
, "STH.D *+SP[A0]") == s
) {
409 C67_g((C67_map_regn(a
) << 23) | //src
410 (15 << 18) | //base reg A15
411 (0 << 13) | //offset reg A0
412 (5 << 9) | //mode 5 = pos offset, base reg + off reg
413 (0 << 8) | //r (LDDW bit 0)
414 (0 << 7) | //y D1/D2 A side
415 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
417 (C67_map_regs(a
) << 1) | //side of src
418 (0 << 0)); //parallel
419 } else if (strstr(s
, "STB.D *+SP[A0]") == s
) {
420 C67_g((C67_map_regn(a
) << 23) | //src
421 (15 << 18) | //base reg A15
422 (0 << 13) | //offset reg A0
423 (5 << 9) | //mode 5 = pos offset, base reg + off reg
424 (0 << 8) | //r (LDDW bit 0)
425 (0 << 7) | //y D1/D2 A side
426 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
428 (C67_map_regs(a
) << 1) | //side of src
429 (0 << 0)); //parallel
430 } else if (strstr(s
, "STH.D *+SP[A0]") == s
) {
431 C67_g((C67_map_regn(a
) << 23) | //src
432 (15 << 18) | //base reg A15
433 (0 << 13) | //offset reg A0
434 (5 << 9) | //mode 5 = pos offset, base reg + off reg
435 (0 << 8) | //r (LDDW bit 0)
436 (0 << 7) | //y D1/D2 A side
437 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
439 (C67_map_regs(a
) << 1) | //side of src
440 (0 << 0)); //parallel
441 } else if (strstr(s
, "STW.D *+SP[A0]") == s
) {
442 C67_g((C67_map_regn(a
) << 23) | //src
443 (15 << 18) | //base reg A15
444 (0 << 13) | //offset reg A0
445 (5 << 9) | //mode 5 = pos offset, base reg + off reg
446 (0 << 8) | //r (LDDW bit 0)
447 (0 << 7) | //y D1/D2 A side
448 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
450 (C67_map_regs(a
) << 1) | //side of src
451 (0 << 0)); //parallel
452 } else if (strstr(s
, "STW.D *") == s
) {
453 C67_g((C67_map_regn(a
) << 23) | //src
454 (C67_map_regn(b
) << 18) | //base reg A0
456 (1 << 9) | //mode 1 = pos cst offset
457 (0 << 8) | //r (LDDW bit 0)
458 (C67_map_regs(b
) << 7) | //y D1/D2 base reg side
459 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
461 (C67_map_regs(a
) << 1) | //side of src
462 (0 << 0)); //parallel
463 } else if (strstr(s
, "STH.D *") == s
) {
464 C67_g((C67_map_regn(a
) << 23) | //src
465 (C67_map_regn(b
) << 18) | //base reg A0
467 (1 << 9) | //mode 1 = pos cst offset
468 (0 << 8) | //r (LDDW bit 0)
469 (C67_map_regs(b
) << 7) | //y D1/D2 base reg side
470 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
472 (C67_map_regs(a
) << 1) | //side of src
473 (0 << 0)); //parallel
474 } else if (strstr(s
, "STB.D *") == s
) {
475 C67_g((C67_map_regn(a
) << 23) | //src
476 (C67_map_regn(b
) << 18) | //base reg A0
478 (1 << 9) | //mode 1 = pos cst offset
479 (0 << 8) | //r (LDDW bit 0)
480 (C67_map_regs(b
) << 7) | //y D1/D2 base reg side
481 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
483 (C67_map_regs(a
) << 1) | //side of src
484 (0 << 0)); //parallel
485 } else if (strstr(s
, "STW.D +*") == s
) {
486 ALWAYS_ASSERT(c
< 32);
487 C67_g((C67_map_regn(a
) << 23) | //src
488 (C67_map_regn(b
) << 18) | //base reg A0
490 (1 << 9) | //mode 1 = pos cst offset
491 (0 << 8) | //r (LDDW bit 0)
492 (C67_map_regs(b
) << 7) | //y D1/D2 base reg side
493 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
495 (C67_map_regs(a
) << 1) | //side of src
496 (0 << 0)); //parallel
497 } else if (strstr(s
, "LDW.D SP PRE INC") == s
) {
498 C67_g((C67_map_regn(a
) << 23) | //dst
499 (15 << 18) | //base reg B15
500 (2 << 13) | //ucst5 (must keep 8 byte boundary)
501 (9 << 9) | //mode 9 = pre inc ucst5
502 (0 << 8) | //r (LDDW bit 0)
503 (1 << 7) | //y D1/D2 B side
504 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
506 (C67_map_regs(a
) << 1) | //side of dst
507 (0 << 0)); //parallel
508 } else if (strstr(s
, "LDDW.D SP PRE INC") == s
) {
509 C67_g((C67_map_regn(a
) << 23) | //dst
510 (15 << 18) | //base reg B15
511 (1 << 13) | //ucst5 (must keep 8 byte boundary)
512 (9 << 9) | //mode 9 = pre inc ucst5
513 (1 << 8) | //r (LDDW bit 1)
514 (1 << 7) | //y D1/D2 B side
515 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
517 (C67_map_regs(a
) << 1) | //side of dst
518 (0 << 0)); //parallel
519 } else if (strstr(s
, "LDW.D *+SP[A0]") == s
) {
520 C67_g((C67_map_regn(a
) << 23) | //dst
521 (15 << 18) | //base reg A15
522 (0 << 13) | //offset reg A0
523 (5 << 9) | //mode 5 = pos offset, base reg + off reg
524 (0 << 8) | //r (LDDW bit 0)
525 (0 << 7) | //y D1/D2 A side
526 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
528 (C67_map_regs(a
) << 1) | //side of dst
529 (0 << 0)); //parallel
530 } else if (strstr(s
, "LDDW.D *+SP[A0]") == s
) {
531 C67_g((C67_map_regn(a
) << 23) | //dst
532 (15 << 18) | //base reg A15
533 (0 << 13) | //offset reg A0
534 (5 << 9) | //mode 5 = pos offset, base reg + off reg
535 (1 << 8) | //r (LDDW bit 1)
536 (0 << 7) | //y D1/D2 A side
537 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
539 (C67_map_regs(a
) << 1) | //side of dst
540 (0 << 0)); //parallel
541 } else if (strstr(s
, "LDH.D *+SP[A0]") == s
) {
542 C67_g((C67_map_regn(a
) << 23) | //dst
543 (15 << 18) | //base reg A15
544 (0 << 13) | //offset reg A0
545 (5 << 9) | //mode 5 = pos offset, base reg + off reg
546 (0 << 8) | //r (LDDW bit 0)
547 (0 << 7) | //y D1/D2 A side
548 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
550 (C67_map_regs(a
) << 1) | //side of dst
551 (0 << 0)); //parallel
552 } else if (strstr(s
, "LDB.D *+SP[A0]") == s
) {
553 C67_g((C67_map_regn(a
) << 23) | //dst
554 (15 << 18) | //base reg A15
555 (0 << 13) | //offset reg A0
556 (5 << 9) | //mode 5 = pos offset, base reg + off reg
557 (0 << 8) | //r (LDDW bit 0)
558 (0 << 7) | //y D1/D2 A side
559 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
561 (C67_map_regs(a
) << 1) | //side of dst
562 (0 << 0)); //parallel
563 } else if (strstr(s
, "LDHU.D *+SP[A0]") == s
) {
564 C67_g((C67_map_regn(a
) << 23) | //dst
565 (15 << 18) | //base reg A15
566 (0 << 13) | //offset reg A0
567 (5 << 9) | //mode 5 = pos offset, base reg + off reg
568 (0 << 8) | //r (LDDW bit 0)
569 (0 << 7) | //y D1/D2 A side
570 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
572 (C67_map_regs(a
) << 1) | //side of dst
573 (0 << 0)); //parallel
574 } else if (strstr(s
, "LDBU.D *+SP[A0]") == s
) {
575 C67_g((C67_map_regn(a
) << 23) | //dst
576 (15 << 18) | //base reg A15
577 (0 << 13) | //offset reg A0
578 (5 << 9) | //mode 5 = pos offset, base reg + off reg
579 (0 << 8) | //r (LDDW bit 0)
580 (0 << 7) | //y D1/D2 A side
581 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
583 (C67_map_regs(a
) << 1) | //side of dst
584 (0 << 0)); //parallel
585 } else if (strstr(s
, "LDW.D *") == s
) {
586 C67_g((C67_map_regn(b
) << 23) | //dst
587 (C67_map_regn(a
) << 18) | //base reg A15
589 (1 << 9) | //mode 1 = pos cst offset
590 (0 << 8) | //r (LDDW bit 0)
591 (C67_map_regs(a
) << 7) | //y D1/D2 src side
592 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
594 (C67_map_regs(b
) << 1) | //side of dst
595 (0 << 0)); //parallel
596 } else if (strstr(s
, "LDDW.D *") == s
) {
597 C67_g((C67_map_regn(b
) << 23) | //dst
598 (C67_map_regn(a
) << 18) | //base reg A15
600 (1 << 9) | //mode 1 = pos cst offset
601 (1 << 8) | //r (LDDW bit 1)
602 (C67_map_regs(a
) << 7) | //y D1/D2 src side
603 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
605 (C67_map_regs(b
) << 1) | //side of dst
606 (0 << 0)); //parallel
607 } else if (strstr(s
, "LDH.D *") == s
) {
608 C67_g((C67_map_regn(b
) << 23) | //dst
609 (C67_map_regn(a
) << 18) | //base reg A15
611 (1 << 9) | //mode 1 = pos cst offset
612 (0 << 8) | //r (LDDW bit 0)
613 (C67_map_regs(a
) << 7) | //y D1/D2 src side
614 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
616 (C67_map_regs(b
) << 1) | //side of dst
617 (0 << 0)); //parallel
618 } else if (strstr(s
, "LDB.D *") == s
) {
619 C67_g((C67_map_regn(b
) << 23) | //dst
620 (C67_map_regn(a
) << 18) | //base reg A15
622 (1 << 9) | //mode 1 = pos cst offset
623 (0 << 8) | //r (LDDW bit 0)
624 (C67_map_regs(a
) << 7) | //y D1/D2 src side
625 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
627 (C67_map_regs(b
) << 1) | //side of dst
628 (0 << 0)); //parallel
629 } else if (strstr(s
, "LDHU.D *") == s
) {
630 C67_g((C67_map_regn(b
) << 23) | //dst
631 (C67_map_regn(a
) << 18) | //base reg A15
633 (1 << 9) | //mode 1 = pos cst offset
634 (0 << 8) | //r (LDDW bit 0)
635 (C67_map_regs(a
) << 7) | //y D1/D2 src side
636 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
638 (C67_map_regs(b
) << 1) | //side of dst
639 (0 << 0)); //parallel
640 } else if (strstr(s
, "LDBU.D *") == s
) {
641 C67_g((C67_map_regn(b
) << 23) | //dst
642 (C67_map_regn(a
) << 18) | //base reg A15
644 (1 << 9) | //mode 1 = pos cst offset
645 (0 << 8) | //r (LDDW bit 0)
646 (C67_map_regs(a
) << 7) | //y D1/D2 src side
647 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
649 (C67_map_regs(b
) << 1) | //side of dst
650 (0 << 0)); //parallel
651 } else if (strstr(s
, "LDW.D +*") == s
) {
652 C67_g((C67_map_regn(b
) << 23) | //dst
653 (C67_map_regn(a
) << 18) | //base reg A15
655 (1 << 9) | //mode 1 = pos cst offset
656 (0 << 8) | //r (LDDW bit 0)
657 (C67_map_regs(a
) << 7) | //y D1/D2 src side
658 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
660 (C67_map_regs(b
) << 1) | //side of dst
661 (0 << 0)); //parallel
662 } else if (strstr(s
, "CMPLTSP") == s
) {
663 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
664 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
666 C67_g((C67_map_regn(c
) << 23) | //dst
667 (C67_map_regn(b
) << 18) | //src2
668 (C67_map_regn(a
) << 13) | //src1
669 (xpath
<< 12) | //x use cross path for src2
670 (0x3a << 6) | //opcode
671 (0x8 << 2) | //opcode fixed
672 (C67_map_regs(c
) << 1) | //side for reg c
673 (0 << 0)); //parallel
674 } else if (strstr(s
, "CMPGTSP") == s
) {
675 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
676 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
678 C67_g((C67_map_regn(c
) << 23) | //dst
679 (C67_map_regn(b
) << 18) | //src2
680 (C67_map_regn(a
) << 13) | //src1
681 (xpath
<< 12) | //x use cross path for src2
682 (0x39 << 6) | //opcode
683 (0x8 << 2) | //opcode fixed
684 (C67_map_regs(c
) << 1) | //side for reg c
685 (0 << 0)); //parallel
686 } else if (strstr(s
, "CMPEQSP") == s
) {
687 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
688 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
690 C67_g((C67_map_regn(c
) << 23) | //dst
691 (C67_map_regn(b
) << 18) | //src2
692 (C67_map_regn(a
) << 13) | //src1
693 (xpath
<< 12) | //x use cross path for src2
694 (0x38 << 6) | //opcode
695 (0x8 << 2) | //opcode fixed
696 (C67_map_regs(c
) << 1) | //side for reg c
697 (0 << 0)); //parallel
700 else if (strstr(s
, "CMPLTDP") == s
) {
701 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
702 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
704 C67_g((C67_map_regn(c
) << 23) | //dst
705 (C67_map_regn(b
) << 18) | //src2
706 (C67_map_regn(a
) << 13) | //src1
707 (xpath
<< 12) | //x use cross path for src2
708 (0x2a << 6) | //opcode
709 (0x8 << 2) | //opcode fixed
710 (C67_map_regs(c
) << 1) | //side for reg c
711 (0 << 0)); //parallel
712 } else if (strstr(s
, "CMPGTDP") == s
) {
713 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
714 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
716 C67_g((C67_map_regn(c
) << 23) | //dst
717 (C67_map_regn(b
) << 18) | //src2
718 (C67_map_regn(a
) << 13) | //src1
719 (xpath
<< 12) | //x use cross path for src2
720 (0x29 << 6) | //opcode
721 (0x8 << 2) | //opcode fixed
722 (C67_map_regs(c
) << 1) | //side for reg c
723 (0 << 0)); //parallel
724 } else if (strstr(s
, "CMPEQDP") == s
) {
725 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
726 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
728 C67_g((C67_map_regn(c
) << 23) | //dst
729 (C67_map_regn(b
) << 18) | //src2
730 (C67_map_regn(a
) << 13) | //src1
731 (xpath
<< 12) | //x use cross path for src2
732 (0x28 << 6) | //opcode
733 (0x8 << 2) | //opcode fixed
734 (C67_map_regs(c
) << 1) | //side for reg c
735 (0 << 0)); //parallel
736 } else if (strstr(s
, "CMPLT") == s
) {
737 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
738 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
740 C67_g((C67_map_regn(c
) << 23) | //dst
741 (C67_map_regn(b
) << 18) | //src2
742 (C67_map_regn(a
) << 13) | //src1
743 (xpath
<< 12) | //x use cross path for src2
744 (0x57 << 5) | //opcode
745 (0x6 << 2) | //opcode fixed
746 (C67_map_regs(c
) << 1) | //side for reg c
747 (0 << 0)); //parallel
748 } else if (strstr(s
, "CMPGT") == s
) {
749 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
750 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
752 C67_g((C67_map_regn(c
) << 23) | //dst
753 (C67_map_regn(b
) << 18) | //src2
754 (C67_map_regn(a
) << 13) | //src1
755 (xpath
<< 12) | //x use cross path for src2
756 (0x47 << 5) | //opcode
757 (0x6 << 2) | //opcode fixed
758 (C67_map_regs(c
) << 1) | //side for reg c
759 (0 << 0)); //parallel
760 } else if (strstr(s
, "CMPEQ") == s
) {
761 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
762 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
764 C67_g((C67_map_regn(c
) << 23) | //dst
765 (C67_map_regn(b
) << 18) | //src2
766 (C67_map_regn(a
) << 13) | //src1
767 (xpath
<< 12) | //x use cross path for src2
768 (0x53 << 5) | //opcode
769 (0x6 << 2) | //opcode fixed
770 (C67_map_regs(c
) << 1) | //side for reg c
771 (0 << 0)); //parallel
772 } else if (strstr(s
, "CMPLTU") == s
) {
773 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
774 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
776 C67_g((C67_map_regn(c
) << 23) | //dst
777 (C67_map_regn(b
) << 18) | //src2
778 (C67_map_regn(a
) << 13) | //src1
779 (xpath
<< 12) | //x use cross path for src2
780 (0x5f << 5) | //opcode
781 (0x6 << 2) | //opcode fixed
782 (C67_map_regs(c
) << 1) | //side for reg c
783 (0 << 0)); //parallel
784 } else if (strstr(s
, "CMPGTU") == s
) {
785 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
786 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
788 C67_g((C67_map_regn(c
) << 23) | //dst
789 (C67_map_regn(b
) << 18) | //src2
790 (C67_map_regn(a
) << 13) | //src1
791 (xpath
<< 12) | //x use cross path for src2
792 (0x4f << 5) | //opcode
793 (0x6 << 2) | //opcode fixed
794 (C67_map_regs(c
) << 1) | //side for reg c
795 (0 << 0)); //parallel
796 } else if (strstr(s
, "B DISP") == s
) {
797 C67_g((0 << 29) | //creg
800 (0x4 << 2) | //opcode fixed
802 (0 << 0)); //parallel
803 } else if (strstr(s
, "B.") == s
) {
804 xpath
= C67_map_regs(c
) ^ 1;
806 C67_g((C67_map_regc(b
) << 29) | //creg
809 (C67_map_regn(c
) << 18) | //src2
811 (xpath
<< 12) | //x cross path if !B side
812 (0xd << 6) | //opcode
813 (0x8 << 2) | //opcode fixed
814 (1 << 1) | //must be S2
815 (0 << 0)); //parallel
816 } else if (strstr(s
, "MV.L") == s
) {
817 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
819 C67_g((0 << 29) | //creg
821 (C67_map_regn(c
) << 23) | //dst
822 (C67_map_regn(b
) << 18) | //src2
823 (0 << 13) | //src1 (cst5)
824 (xpath
<< 12) | //x cross path if opposite sides
825 (0x2 << 5) | //opcode
826 (0x6 << 2) | //opcode fixed
827 (C67_map_regs(c
) << 1) | //side of dest
828 (0 << 0)); //parallel
829 } else if (strstr(s
, "SPTRUNC.L") == s
) {
830 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
832 C67_g((0 << 29) | //creg
834 (C67_map_regn(c
) << 23) | //dst
835 (C67_map_regn(b
) << 18) | //src2
836 (0 << 13) | //src1 NA
837 (xpath
<< 12) | //x cross path if opposite sides
838 (0xb << 5) | //opcode
839 (0x6 << 2) | //opcode fixed
840 (C67_map_regs(c
) << 1) | //side of dest
841 (0 << 0)); //parallel
842 } else if (strstr(s
, "DPTRUNC.L") == s
) {
843 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
845 C67_g((0 << 29) | //creg
847 (C67_map_regn(c
) << 23) | //dst
848 ((C67_map_regn(b
) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
849 (0 << 13) | //src1 NA
850 (xpath
<< 12) | //x cross path if opposite sides
851 (0x1 << 5) | //opcode
852 (0x6 << 2) | //opcode fixed
853 (C67_map_regs(c
) << 1) | //side of dest
854 (0 << 0)); //parallel
855 } else if (strstr(s
, "INTSP.L") == s
) {
856 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
858 C67_g((0 << 29) | //creg
860 (C67_map_regn(c
) << 23) | //dst
861 (C67_map_regn(b
) << 18) | //src2
862 (0 << 13) | //src1 NA
863 (xpath
<< 12) | //x cross path if opposite sides
864 (0x4a << 5) | //opcode
865 (0x6 << 2) | //opcode fixed
866 (C67_map_regs(c
) << 1) | //side of dest
867 (0 << 0)); //parallel
868 } else if (strstr(s
, "INTSPU.L") == s
) {
869 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
871 C67_g((0 << 29) | //creg
873 (C67_map_regn(c
) << 23) | //dst
874 (C67_map_regn(b
) << 18) | //src2
875 (0 << 13) | //src1 NA
876 (xpath
<< 12) | //x cross path if opposite sides
877 (0x49 << 5) | //opcode
878 (0x6 << 2) | //opcode fixed
879 (C67_map_regs(c
) << 1) | //side of dest
880 (0 << 0)); //parallel
881 } else if (strstr(s
, "INTDP.L") == s
) {
882 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
884 C67_g((0 << 29) | //creg
886 (C67_map_regn(c
) << 23) | //dst
887 (C67_map_regn(b
) << 18) | //src2
888 (0 << 13) | //src1 NA
889 (xpath
<< 12) | //x cross path if opposite sides
890 (0x39 << 5) | //opcode
891 (0x6 << 2) | //opcode fixed
892 (C67_map_regs(c
) << 1) | //side of dest
893 (0 << 0)); //parallel
894 } else if (strstr(s
, "INTDPU.L") == s
) {
895 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
897 C67_g((0 << 29) | //creg
899 (C67_map_regn(c
) << 23) | //dst
900 ((C67_map_regn(b
) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
901 (0 << 13) | //src1 NA
902 (xpath
<< 12) | //x cross path if opposite sides
903 (0x3b << 5) | //opcode
904 (0x6 << 2) | //opcode fixed
905 (C67_map_regs(c
) << 1) | //side of dest
906 (0 << 0)); //parallel
907 } else if (strstr(s
, "SPDP.L") == s
) {
908 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
910 C67_g((0 << 29) | //creg
912 (C67_map_regn(c
) << 23) | //dst
913 (C67_map_regn(b
) << 18) | //src2
914 (0 << 13) | //src1 NA
915 (xpath
<< 12) | //x cross path if opposite sides
916 (0x2 << 6) | //opcode
917 (0x8 << 2) | //opcode fixed
918 (C67_map_regs(c
) << 1) | //side of dest
919 (0 << 0)); //parallel
920 } else if (strstr(s
, "DPSP.L") == s
) {
921 ALWAYS_ASSERT(C67_map_regs(b
) == C67_map_regs(c
));
923 C67_g((0 << 29) | //creg
925 (C67_map_regn(c
) << 23) | //dst
926 ((C67_map_regn(b
) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
927 (0 << 13) | //src1 NA
928 (0 << 12) | //x cross path if opposite sides
929 (0x9 << 5) | //opcode
930 (0x6 << 2) | //opcode fixed
931 (C67_map_regs(c
) << 1) | //side of dest
932 (0 << 0)); //parallel
933 } else if (strstr(s
, "ADD.L") == s
) {
934 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
936 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
938 C67_g((0 << 29) | //creg
940 (C67_map_regn(c
) << 23) | //dst
941 (C67_map_regn(b
) << 18) | //src2 (possible x path)
942 (C67_map_regn(a
) << 13) | //src1
943 (xpath
<< 12) | //x cross path if opposite sides
944 (0x3 << 5) | //opcode
945 (0x6 << 2) | //opcode fixed
946 (C67_map_regs(c
) << 1) | //side of dest
947 (0 << 0)); //parallel
948 } else if (strstr(s
, "SUB.L") == s
) {
949 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
951 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
953 C67_g((0 << 29) | //creg
955 (C67_map_regn(c
) << 23) | //dst
956 (C67_map_regn(b
) << 18) | //src2 (possible x path)
957 (C67_map_regn(a
) << 13) | //src1
958 (xpath
<< 12) | //x cross path if opposite sides
959 (0x7 << 5) | //opcode
960 (0x6 << 2) | //opcode fixed
961 (C67_map_regs(c
) << 1) | //side of dest
962 (0 << 0)); //parallel
963 } else if (strstr(s
, "OR.L") == s
) {
964 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
966 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
968 C67_g((0 << 29) | //creg
970 (C67_map_regn(c
) << 23) | //dst
971 (C67_map_regn(b
) << 18) | //src2 (possible x path)
972 (C67_map_regn(a
) << 13) | //src1
973 (xpath
<< 12) | //x cross path if opposite sides
974 (0x7f << 5) | //opcode
975 (0x6 << 2) | //opcode fixed
976 (C67_map_regs(c
) << 1) | //side of dest
977 (0 << 0)); //parallel
978 } else if (strstr(s
, "AND.L") == s
) {
979 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
981 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
983 C67_g((0 << 29) | //creg
985 (C67_map_regn(c
) << 23) | //dst
986 (C67_map_regn(b
) << 18) | //src2 (possible x path)
987 (C67_map_regn(a
) << 13) | //src1
988 (xpath
<< 12) | //x cross path if opposite sides
989 (0x7b << 5) | //opcode
990 (0x6 << 2) | //opcode fixed
991 (C67_map_regs(c
) << 1) | //side of dest
992 (0 << 0)); //parallel
993 } else if (strstr(s
, "XOR.L") == s
) {
994 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
996 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
998 C67_g((0 << 29) | //creg
1000 (C67_map_regn(c
) << 23) | //dst
1001 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1002 (C67_map_regn(a
) << 13) | //src1
1003 (xpath
<< 12) | //x cross path if opposite sides
1004 (0x6f << 5) | //opcode
1005 (0x6 << 2) | //opcode fixed
1006 (C67_map_regs(c
) << 1) | //side of dest
1007 (0 << 0)); //parallel
1008 } else if (strstr(s
, "ADDSP.L") == s
) {
1009 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1011 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1013 C67_g((0 << 29) | //creg
1015 (C67_map_regn(c
) << 23) | //dst
1016 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1017 (C67_map_regn(a
) << 13) | //src1
1018 (xpath
<< 12) | //x cross path if opposite sides
1019 (0x10 << 5) | //opcode
1020 (0x6 << 2) | //opcode fixed
1021 (C67_map_regs(c
) << 1) | //side of dest
1022 (0 << 0)); //parallel
1023 } else if (strstr(s
, "ADDDP.L") == s
) {
1024 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1026 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1028 C67_g((0 << 29) | //creg
1030 (C67_map_regn(c
) << 23) | //dst
1031 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1032 (C67_map_regn(a
) << 13) | //src1
1033 (xpath
<< 12) | //x cross path if opposite sides
1034 (0x18 << 5) | //opcode
1035 (0x6 << 2) | //opcode fixed
1036 (C67_map_regs(c
) << 1) | //side of dest
1037 (0 << 0)); //parallel
1038 } else if (strstr(s
, "SUBSP.L") == s
) {
1039 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1041 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1043 C67_g((0 << 29) | //creg
1045 (C67_map_regn(c
) << 23) | //dst
1046 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1047 (C67_map_regn(a
) << 13) | //src1
1048 (xpath
<< 12) | //x cross path if opposite sides
1049 (0x11 << 5) | //opcode
1050 (0x6 << 2) | //opcode fixed
1051 (C67_map_regs(c
) << 1) | //side of dest
1052 (0 << 0)); //parallel
1053 } else if (strstr(s
, "SUBDP.L") == s
) {
1054 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1056 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1058 C67_g((0 << 29) | //creg
1060 (C67_map_regn(c
) << 23) | //dst
1061 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1062 (C67_map_regn(a
) << 13) | //src1
1063 (xpath
<< 12) | //x cross path if opposite sides
1064 (0x19 << 5) | //opcode
1065 (0x6 << 2) | //opcode fixed
1066 (C67_map_regs(c
) << 1) | //side of dest
1067 (0 << 0)); //parallel
1068 } else if (strstr(s
, "MPYSP.M") == s
) {
1069 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1071 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1073 C67_g((0 << 29) | //creg
1075 (C67_map_regn(c
) << 23) | //dst
1076 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1077 (C67_map_regn(a
) << 13) | //src1
1078 (xpath
<< 12) | //x cross path if opposite sides
1079 (0x1c << 7) | //opcode
1080 (0x0 << 2) | //opcode fixed
1081 (C67_map_regs(c
) << 1) | //side of dest
1082 (0 << 0)); //parallel
1083 } else if (strstr(s
, "MPYDP.M") == s
) {
1084 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1086 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1088 C67_g((0 << 29) | //creg
1090 (C67_map_regn(c
) << 23) | //dst
1091 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1092 (C67_map_regn(a
) << 13) | //src1
1093 (xpath
<< 12) | //x cross path if opposite sides
1094 (0x0e << 7) | //opcode
1095 (0x0 << 2) | //opcode fixed
1096 (C67_map_regs(c
) << 1) | //side of dest
1097 (0 << 0)); //parallel
1098 } else if (strstr(s
, "MPYI.M") == s
) {
1099 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1101 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1103 C67_g((0 << 29) | //creg
1105 (C67_map_regn(c
) << 23) | //dst
1106 (C67_map_regn(b
) << 18) | //src2
1107 (C67_map_regn(a
) << 13) | //src1 (cst5)
1108 (xpath
<< 12) | //x cross path if opposite sides
1109 (0x4 << 7) | //opcode
1110 (0x0 << 2) | //opcode fixed
1111 (C67_map_regs(c
) << 1) | //side of dest
1112 (0 << 0)); //parallel
1113 } else if (strstr(s
, "SHR.S") == s
) {
1114 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1116 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
1118 C67_g((0 << 29) | //creg
1120 (C67_map_regn(c
) << 23) | //dst
1121 (C67_map_regn(b
) << 18) | //src2
1122 (C67_map_regn(a
) << 13) | //src1
1123 (xpath
<< 12) | //x cross path if opposite sides
1124 (0x37 << 6) | //opcode
1125 (0x8 << 2) | //opcode fixed
1126 (C67_map_regs(c
) << 1) | //side of dest
1127 (0 << 0)); //parallel
1128 } else if (strstr(s
, "SHRU.S") == s
) {
1129 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1131 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
1133 C67_g((0 << 29) | //creg
1135 (C67_map_regn(c
) << 23) | //dst
1136 (C67_map_regn(b
) << 18) | //src2
1137 (C67_map_regn(a
) << 13) | //src1
1138 (xpath
<< 12) | //x cross path if opposite sides
1139 (0x27 << 6) | //opcode
1140 (0x8 << 2) | //opcode fixed
1141 (C67_map_regs(c
) << 1) | //side of dest
1142 (0 << 0)); //parallel
1143 } else if (strstr(s
, "SHL.S") == s
) {
1144 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1146 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
1148 C67_g((0 << 29) | //creg
1150 (C67_map_regn(c
) << 23) | //dst
1151 (C67_map_regn(b
) << 18) | //src2
1152 (C67_map_regn(a
) << 13) | //src1
1153 (xpath
<< 12) | //x cross path if opposite sides
1154 (0x33 << 6) | //opcode
1155 (0x8 << 2) | //opcode fixed
1156 (C67_map_regs(c
) << 1) | //side of dest
1157 (0 << 0)); //parallel
1158 } else if (strstr(s
, "||ADDK") == s
) {
1159 xpath
= 0; // no xpath required just use the side of the src/dst
1161 C67_g((0 << 29) | //creg
1163 (C67_map_regn(b
) << 23) | //dst
1164 (a
<< 07) | //scst16
1165 (0x14 << 2) | //opcode fixed
1166 (C67_map_regs(b
) << 1) | //side of dst
1167 (1 << 0)); //parallel
1168 } else if (strstr(s
, "ADDK") == s
) {
1169 xpath
= 0; // no xpath required just use the side of the src/dst
1171 C67_g((0 << 29) | //creg
1173 (C67_map_regn(b
) << 23) | //dst
1174 (a
<< 07) | //scst16
1175 (0x14 << 2) | //opcode fixed
1176 (C67_map_regs(b
) << 1) | //side of dst
1177 (0 << 0)); //parallel
1178 } else if (strstr(s
, "NOP") == s
) {
1179 C67_g(((a
- 1) << 13) | //no of cycles
1180 (0 << 0)); //parallel
1182 ALWAYS_ASSERT(FALSE
);
1184 #ifdef ASSEMBLY_LISTING_C67
1185 fprintf(f
, " %s %d %d %d\n", s
, a
, b
, c
);
1190 //r=reg to load, fr=from reg, symbol for relocation, constant
1192 void C67_MVKL(int r
, int fc
)
1194 C67_asm("MVKL.", fc
, r
, 0);
1197 void C67_MVKH(int r
, int fc
)
1199 C67_asm("MVKH.", fc
, r
, 0);
1202 void C67_STB_SP_A0(int r
)
1204 C67_asm("STB.D *+SP[A0]", r
, 0, 0); // STB r,*+SP[A0]
1207 void C67_STH_SP_A0(int r
)
1209 C67_asm("STH.D *+SP[A0]", r
, 0, 0); // STH r,*+SP[A0]
1212 void C67_STW_SP_A0(int r
)
1214 C67_asm("STW.D *+SP[A0]", r
, 0, 0); // STW r,*+SP[A0]
1217 void C67_STB_PTR(int r
, int r2
)
1219 C67_asm("STB.D *", r
, r2
, 0); // STB r, *r2
1222 void C67_STH_PTR(int r
, int r2
)
1224 C67_asm("STH.D *", r
, r2
, 0); // STH r, *r2
1227 void C67_STW_PTR(int r
, int r2
)
1229 C67_asm("STW.D *", r
, r2
, 0); // STW r, *r2
1232 void C67_STW_PTR_PRE_INC(int r
, int r2
, int n
)
1234 C67_asm("STW.D +*", r
, r2
, n
); // STW r, *+r2
1237 void C67_PUSH(int r
)
1239 C67_asm("STW.D SP POST DEC", r
, 0, 0); // STW r,*SP--
1242 void C67_LDW_SP_A0(int r
)
1244 C67_asm("LDW.D *+SP[A0]", r
, 0, 0); // LDW *+SP[A0],r
1247 void C67_LDDW_SP_A0(int r
)
1249 C67_asm("LDDW.D *+SP[A0]", r
, 0, 0); // LDDW *+SP[A0],r
1252 void C67_LDH_SP_A0(int r
)
1254 C67_asm("LDH.D *+SP[A0]", r
, 0, 0); // LDH *+SP[A0],r
1257 void C67_LDB_SP_A0(int r
)
1259 C67_asm("LDB.D *+SP[A0]", r
, 0, 0); // LDB *+SP[A0],r
1262 void C67_LDHU_SP_A0(int r
)
1264 C67_asm("LDHU.D *+SP[A0]", r
, 0, 0); // LDHU *+SP[A0],r
1267 void C67_LDBU_SP_A0(int r
)
1269 C67_asm("LDBU.D *+SP[A0]", r
, 0, 0); // LDBU *+SP[A0],r
1272 void C67_LDW_PTR(int r
, int r2
)
1274 C67_asm("LDW.D *", r
, r2
, 0); // LDW *r,r2
1277 void C67_LDDW_PTR(int r
, int r2
)
1279 C67_asm("LDDW.D *", r
, r2
, 0); // LDDW *r,r2
1282 void C67_LDH_PTR(int r
, int r2
)
1284 C67_asm("LDH.D *", r
, r2
, 0); // LDH *r,r2
1287 void C67_LDB_PTR(int r
, int r2
)
1289 C67_asm("LDB.D *", r
, r2
, 0); // LDB *r,r2
1292 void C67_LDHU_PTR(int r
, int r2
)
1294 C67_asm("LDHU.D *", r
, r2
, 0); // LDHU *r,r2
1297 void C67_LDBU_PTR(int r
, int r2
)
1299 C67_asm("LDBU.D *", r
, r2
, 0); // LDBU *r,r2
1302 void C67_LDW_PTR_PRE_INC(int r
, int r2
)
1304 C67_asm("LDW.D +*", r
, r2
, 0); // LDW *+r,r2
1309 C67_asm("LDW.D SP PRE INC", r
, 0, 0); // LDW *++SP,r
1312 void C67_POP_DW(int r
)
1314 C67_asm("LDDW.D SP PRE INC", r
, 0, 0); // LDDW *++SP,r
1317 void C67_CMPLT(int s1
, int s2
, int dst
)
1319 C67_asm("CMPLT.L1", s1
, s2
, dst
);
1322 void C67_CMPGT(int s1
, int s2
, int dst
)
1324 C67_asm("CMPGT.L1", s1
, s2
, dst
);
1327 void C67_CMPEQ(int s1
, int s2
, int dst
)
1329 C67_asm("CMPEQ.L1", s1
, s2
, dst
);
1332 void C67_CMPLTU(int s1
, int s2
, int dst
)
1334 C67_asm("CMPLTU.L1", s1
, s2
, dst
);
1337 void C67_CMPGTU(int s1
, int s2
, int dst
)
1339 C67_asm("CMPGTU.L1", s1
, s2
, dst
);
1343 void C67_CMPLTSP(int s1
, int s2
, int dst
)
1345 C67_asm("CMPLTSP.S1", s1
, s2
, dst
);
1348 void C67_CMPGTSP(int s1
, int s2
, int dst
)
1350 C67_asm("CMPGTSP.S1", s1
, s2
, dst
);
1353 void C67_CMPEQSP(int s1
, int s2
, int dst
)
1355 C67_asm("CMPEQSP.S1", s1
, s2
, dst
);
1358 void C67_CMPLTDP(int s1
, int s2
, int dst
)
1360 C67_asm("CMPLTDP.S1", s1
, s2
, dst
);
1363 void C67_CMPGTDP(int s1
, int s2
, int dst
)
1365 C67_asm("CMPGTDP.S1", s1
, s2
, dst
);
1368 void C67_CMPEQDP(int s1
, int s2
, int dst
)
1370 C67_asm("CMPEQDP.S1", s1
, s2
, dst
);
1374 void C67_IREG_B_REG(int inv
, int r1
, int r2
) // [!R] B r2
1376 C67_asm("B.S2", inv
, r1
, r2
);
1380 // call with how many 32 bit words to skip
1381 // (0 would branch to the branch instruction)
1383 void C67_B_DISP(int disp
) // B +2 Branch with constant displacement
1385 // Branch point is relative to the 8 word fetch packet
1387 // we will assume the text section always starts on an 8 word (32 byte boundary)
1389 // so add in how many words into the fetch packet the branch is
1392 C67_asm("B DISP", disp
+ ((ind
& 31) >> 2), 0, 0);
1397 C67_asm("NOP", n
, 0, 0);
1400 void C67_ADDK(int n
, int r
)
1402 ALWAYS_ASSERT(abs(n
) < 32767);
1404 C67_asm("ADDK", n
, r
, 0);
1407 void C67_ADDK_PARALLEL(int n
, int r
)
1409 ALWAYS_ASSERT(abs(n
) < 32767);
1411 C67_asm("||ADDK", n
, r
, 0);
1414 void C67_Adjust_ADDK(int *inst
, int n
)
1416 ALWAYS_ASSERT(abs(n
) < 32767);
1418 *inst
= (*inst
& (~(0xffff << 7))) | ((n
& 0xffff) << 7);
1421 void C67_MV(int r
, int v
)
1423 C67_asm("MV.L", 0, r
, v
);
1427 void C67_DPTRUNC(int r
, int v
)
1429 C67_asm("DPTRUNC.L", 0, r
, v
);
1432 void C67_SPTRUNC(int r
, int v
)
1434 C67_asm("SPTRUNC.L", 0, r
, v
);
1437 void C67_INTSP(int r
, int v
)
1439 C67_asm("INTSP.L", 0, r
, v
);
1442 void C67_INTDP(int r
, int v
)
1444 C67_asm("INTDP.L", 0, r
, v
);
1447 void C67_INTSPU(int r
, int v
)
1449 C67_asm("INTSPU.L", 0, r
, v
);
1452 void C67_INTDPU(int r
, int v
)
1454 C67_asm("INTDPU.L", 0, r
, v
);
1457 void C67_SPDP(int r
, int v
)
1459 C67_asm("SPDP.L", 0, r
, v
);
1462 void C67_DPSP(int r
, int v
) // note regs must be on the same side
1464 C67_asm("DPSP.L", 0, r
, v
);
1467 void C67_ADD(int r
, int v
)
1469 C67_asm("ADD.L", v
, r
, v
);
1472 void C67_SUB(int r
, int v
)
1474 C67_asm("SUB.L", v
, r
, v
);
1477 void C67_AND(int r
, int v
)
1479 C67_asm("AND.L", v
, r
, v
);
1482 void C67_OR(int r
, int v
)
1484 C67_asm("OR.L", v
, r
, v
);
1487 void C67_XOR(int r
, int v
)
1489 C67_asm("XOR.L", v
, r
, v
);
1492 void C67_ADDSP(int r
, int v
)
1494 C67_asm("ADDSP.L", v
, r
, v
);
1497 void C67_SUBSP(int r
, int v
)
1499 C67_asm("SUBSP.L", v
, r
, v
);
1502 void C67_MPYSP(int r
, int v
)
1504 C67_asm("MPYSP.M", v
, r
, v
);
1507 void C67_ADDDP(int r
, int v
)
1509 C67_asm("ADDDP.L", v
, r
, v
);
1512 void C67_SUBDP(int r
, int v
)
1514 C67_asm("SUBDP.L", v
, r
, v
);
1517 void C67_MPYDP(int r
, int v
)
1519 C67_asm("MPYDP.M", v
, r
, v
);
1522 void C67_MPYI(int r
, int v
)
1524 C67_asm("MPYI.M", v
, r
, v
);
1527 void C67_SHL(int r
, int v
)
1529 C67_asm("SHL.S", r
, v
, v
);
1532 void C67_SHRU(int r
, int v
)
1534 C67_asm("SHRU.S", r
, v
, v
);
1537 void C67_SHR(int r
, int v
)
1539 C67_asm("SHR.S", r
, v
, v
);
1544 /* load 'r' from value 'sv' */
1545 void load(int r
, SValue
* sv
)
1547 int v
, t
, ft
, fc
, fr
, size
= 0, element
;
1548 BOOL Unsigned
= FALSE
;
1555 v
= fr
& VT_VALMASK
;
1557 if (v
== VT_LLOCAL
) {
1559 v1
.r
= VT_LOCAL
| VT_LVAL
;
1563 } else if ((ft
& VT_BTYPE
) == VT_LDOUBLE
) {
1564 tcc_error("long double not supported");
1565 } else if ((ft
& VT_TYPE
) == VT_BYTE
) {
1567 } else if ((ft
& VT_TYPE
) == (VT_BYTE
| VT_UNSIGNED
)) {
1570 } else if ((ft
& VT_TYPE
) == VT_SHORT
) {
1572 } else if ((ft
& VT_TYPE
) == (VT_SHORT
| VT_UNSIGNED
)) {
1575 } else if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
1581 // check if fc is a positive reference on the stack,
1582 // if it is tcc is referencing what it thinks is a parameter
1583 // on the stack, so check if it is really in a register.
1586 if (v
== VT_LOCAL
&& fc
> 0) {
1589 for (t
= 0; t
< NoCallArgsPassedOnStack
; t
++) {
1590 if (fc
== stack_pos
)
1593 stack_pos
+= TranslateStackToReg
[t
];
1596 // param has been pushed on stack, get it like a local var
1598 fc
= ParamLocOnStack
[t
] - 8;
1601 if ((fr
& VT_VALMASK
) < VT_CONST
) // check for pure indirect
1605 C67_LDBU_PTR(v
, r
); // LDBU *v,r
1607 C67_LDB_PTR(v
, r
); // LDB *v,r
1608 } else if (size
== 2) {
1610 C67_LDHU_PTR(v
, r
); // LDHU *v,r
1612 C67_LDH_PTR(v
, r
); // LDH *v,r
1613 } else if (size
== 4) {
1614 C67_LDW_PTR(v
, r
); // LDW *v,r
1615 } else if (size
== 8) {
1616 C67_LDDW_PTR(v
, r
); // LDDW *v,r
1619 C67_NOP(4); // NOP 4
1621 } else if (fr
& VT_SYM
) {
1622 greloc(cur_text_section
, sv
->sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1623 greloc(cur_text_section
, sv
->sym
, ind
+ 4, R_C60HI16
);
1626 C67_MVKL(C67_A0
, fc
); //r=reg to load, constant
1627 C67_MVKH(C67_A0
, fc
); //r=reg to load, constant
1632 C67_LDBU_PTR(C67_A0
, r
); // LDBU *A0,r
1634 C67_LDB_PTR(C67_A0
, r
); // LDB *A0,r
1635 } else if (size
== 2) {
1637 C67_LDHU_PTR(C67_A0
, r
); // LDHU *A0,r
1639 C67_LDH_PTR(C67_A0
, r
); // LDH *A0,r
1640 } else if (size
== 4) {
1641 C67_LDW_PTR(C67_A0
, r
); // LDW *A0,r
1642 } else if (size
== 8) {
1643 C67_LDDW_PTR(C67_A0
, r
); // LDDW *A0,r
1646 C67_NOP(4); // NOP 4
1651 // divide offset in bytes to create element index
1652 C67_MVKL(C67_A0
, (fc
/ element
) + 8 / element
); //r=reg to load, constant
1653 C67_MVKH(C67_A0
, (fc
/ element
) + 8 / element
); //r=reg to load, constant
1657 C67_LDBU_SP_A0(r
); // LDBU r, SP[A0]
1659 C67_LDB_SP_A0(r
); // LDB r, SP[A0]
1660 } else if (size
== 2) {
1662 C67_LDHU_SP_A0(r
); // LDHU r, SP[A0]
1664 C67_LDH_SP_A0(r
); // LDH r, SP[A0]
1665 } else if (size
== 4) {
1666 C67_LDW_SP_A0(r
); // LDW r, SP[A0]
1667 } else if (size
== 8) {
1668 C67_LDDW_SP_A0(r
); // LDDW r, SP[A0]
1672 C67_NOP(4); // NOP 4
1676 if (v
== VT_CONST
) {
1678 greloc(cur_text_section
, sv
->sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1679 greloc(cur_text_section
, sv
->sym
, ind
+ 4, R_C60HI16
);
1681 C67_MVKL(r
, fc
); //r=reg to load, constant
1682 C67_MVKH(r
, fc
); //r=reg to load, constant
1683 } else if (v
== VT_LOCAL
) {
1684 C67_MVKL(r
, fc
+ 8); //r=reg to load, constant C67 stack points to next free
1685 C67_MVKH(r
, fc
+ 8); //r=reg to load, constant
1686 C67_ADD(C67_FP
, r
); // MV v,r v -> r
1687 } else if (v
== VT_CMP
) {
1688 C67_MV(C67_compare_reg
, r
); // MV v,r v -> r
1689 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1691 C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
1692 C67_MVKL(r
, t
); // r=reg to load, 0 or 1 (do this while branching)
1693 C67_NOP(4); // NOP 4
1694 gsym(fc
); // modifies other branches to branch here
1695 C67_MVKL(r
, t
^ 1); // r=reg to load, 0 or 1
1696 } else if (v
!= r
) {
1697 C67_MV(v
, r
); // MV v,r v -> r
1699 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
1700 C67_MV(v
+ 1, r
+ 1); // MV v,r v -> r
1706 /* store register 'r' in lvalue 'v' */
1707 void store(int r
, SValue
* v
)
1709 int fr
, bt
, ft
, fc
, size
, t
, element
;
1713 fr
= v
->r
& VT_VALMASK
;
1715 /* XXX: incorrect if float reg to reg */
1717 if (bt
== VT_LDOUBLE
) {
1718 tcc_error("long double not supported");
1722 else if (bt
== VT_BYTE
)
1724 else if (bt
== VT_DOUBLE
)
1729 if ((v
->r
& VT_VALMASK
) == VT_CONST
) {
1730 /* constant memory reference */
1732 if (v
->r
& VT_SYM
) {
1733 greloc(cur_text_section
, v
->sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1734 greloc(cur_text_section
, v
->sym
, ind
+ 4, R_C60HI16
);
1736 C67_MVKL(C67_A0
, fc
); //r=reg to load, constant
1737 C67_MVKH(C67_A0
, fc
); //r=reg to load, constant
1740 C67_STB_PTR(r
, C67_A0
); // STB r, *A0
1742 C67_STH_PTR(r
, C67_A0
); // STH r, *A0
1743 else if (size
== 4 || size
== 8)
1744 C67_STW_PTR(r
, C67_A0
); // STW r, *A0
1747 C67_STW_PTR_PRE_INC(r
+ 1, C67_A0
, 1); // STW r, *+A0[1]
1748 } else if ((v
->r
& VT_VALMASK
) == VT_LOCAL
) {
1749 // check case of storing to passed argument that
1750 // tcc thinks is on the stack but for C67 is
1751 // passed as a reg. However it may have been
1752 // saved to the stack, if that reg was required
1753 // for a call to a child function
1755 if (fc
> 0) // argument ??
1757 // walk through sizes and figure which param
1761 for (t
= 0; t
< NoCallArgsPassedOnStack
; t
++) {
1762 if (fc
== stack_pos
)
1765 stack_pos
+= TranslateStackToReg
[t
];
1768 // param has been pushed on stack, get it like a local var
1769 fc
= ParamLocOnStack
[t
] - 8;
1777 // divide offset in bytes to create word index
1778 C67_MVKL(C67_A0
, (fc
/ element
) + 8 / element
); //r=reg to load, constant
1779 C67_MVKH(C67_A0
, (fc
/ element
) + 8 / element
); //r=reg to load, constant
1784 C67_STB_SP_A0(r
); // STB r, SP[A0]
1786 C67_STH_SP_A0(r
); // STH r, SP[A0]
1787 else if (size
== 4 || size
== 8)
1788 C67_STW_SP_A0(r
); // STW r, SP[A0]
1791 C67_ADDK(1, C67_A0
); // ADDK 1,A0
1792 C67_STW_SP_A0(r
+ 1); // STW r, SP[A0]
1796 C67_STB_PTR(r
, fr
); // STB r, *fr
1798 C67_STH_PTR(r
, fr
); // STH r, *fr
1799 else if (size
== 4 || size
== 8)
1800 C67_STW_PTR(r
, fr
); // STW r, *fr
1803 C67_STW_PTR_PRE_INC(r
+ 1, fr
, 1); // STW r, *+fr[1]
1809 /* 'is_jmp' is '1' if it is a jump */
1810 static void gcall_or_jmp(int is_jmp
)
1815 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1817 if (vtop
->r
& VT_SYM
) {
1818 /* relocation case */
1820 // get add into A0, then start the jump B3
1822 greloc(cur_text_section
, vtop
->sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1823 greloc(cur_text_section
, vtop
->sym
, ind
+ 4, R_C60HI16
);
1825 C67_MVKL(C67_A0
, 0); //r=reg to load, constant
1826 C67_MVKH(C67_A0
, 0); //r=reg to load, constant
1827 C67_IREG_B_REG(0, C67_CREG_ZERO
, C67_A0
); // B.S2x A0
1830 C67_NOP(5); // simple jump, just put NOP
1832 // Call, must load return address into B3 during delay slots
1834 sym
= get_sym_ref(&char_pointer_type
, cur_text_section
, ind
+ 12, 0); // symbol for return address
1835 greloc(cur_text_section
, sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1836 greloc(cur_text_section
, sym
, ind
+ 4, R_C60HI16
);
1837 C67_MVKL(C67_B3
, 0); //r=reg to load, constant
1838 C67_MVKH(C67_B3
, 0); //r=reg to load, constant
1839 C67_NOP(3); // put remaining NOPs
1842 /* put an empty PC32 relocation */
1843 ALWAYS_ASSERT(FALSE
);
1846 /* otherwise, indirect call */
1848 C67_IREG_B_REG(0, C67_CREG_ZERO
, r
); // B.S2x r
1851 C67_NOP(5); // simple jump, just put NOP
1853 // Call, must load return address into B3 during delay slots
1855 sym
= get_sym_ref(&char_pointer_type
, cur_text_section
, ind
+ 12, 0); // symbol for return address
1856 greloc(cur_text_section
, sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1857 greloc(cur_text_section
, sym
, ind
+ 4, R_C60HI16
);
1858 C67_MVKL(C67_B3
, 0); //r=reg to load, constant
1859 C67_MVKH(C67_B3
, 0); //r=reg to load, constant
1860 C67_NOP(3); // put remaining NOPs
1865 /* Return the number of registers needed to return the struct, or 0 if
1866 returning via struct pointer. */
1867 ST_FUNC
int gfunc_sret(CType
*vt
, int variadic
, CType
*ret
, int *ret_align
, int *regsize
) {
1868 *ret_align
= 1; // Never have to re-align return values for x86-64
1872 /* generate function call with address in (vtop->t, vtop->c) and free function
1873 context. Stack entry is popped */
1874 void gfunc_call(int nb_args
)
1877 int args_sizes
[NoCallArgsPassedOnStack
];
1879 if (nb_args
> NoCallArgsPassedOnStack
) {
1880 tcc_error("more than 10 function params not currently supported");
1881 // handle more than 10, put some on the stack
1884 for (i
= 0; i
< nb_args
; i
++) {
1885 if ((vtop
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
1886 ALWAYS_ASSERT(FALSE
);
1888 /* simple type (currently always same size) */
1889 /* XXX: implicit cast ? */
1892 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
1893 tcc_error("long long not supported");
1894 } else if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
1895 tcc_error("long double not supported");
1896 } else if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
) {
1902 // put the parameter into the corresponding reg (pair)
1904 r
= gv(RC_C67_A4
<< (2 * i
));
1906 // must put on stack because with 1 pass compiler , no way to tell
1907 // if an up coming nested call might overwrite these regs
1912 C67_STW_PTR_PRE_INC(r
+ 1, C67_SP
, 3); // STW r, *+SP[3] (go back and put the other)
1914 args_sizes
[i
] = size
;
1918 // POP all the params on the stack into registers for the
1919 // immediate call (in reverse order)
1921 for (i
= nb_args
- 1; i
>= 0; i
--) {
1923 if (args_sizes
[i
] == 8)
1924 C67_POP_DW(TREG_C67_A4
+ i
* 2);
1926 C67_POP(TREG_C67_A4
+ i
* 2);
1933 // to be compatible with Code Composer for the C67
1934 // the first 10 parameters must be passed in registers
1935 // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1936 // ending with B12:B13.
1938 // When a call is made, if the caller has its parameters
1939 // in regs A4-B13 these must be saved before/as the call
1940 // parameters are loaded and restored upon return (or if/when needed).
1942 /* generate function prolog of type 't' */
1943 void gfunc_prolog(Sym
*func_sym
)
1945 CType
*func_type
= &func_sym
->type
;
1946 int addr
, align
, size
, func_call
, i
;
1950 sym
= func_type
->ref
;
1951 func_call
= sym
->f
.func_call
;
1953 /* if the function returns a structure, then add an
1954 implicit pointer parameter */
1955 func_vt
= sym
->type
;
1956 func_var
= (sym
->f
.func_type
== FUNC_ELLIPSIS
);
1957 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
1962 NoOfCurFuncArgs
= 0;
1964 /* define parameters */
1965 while ((sym
= sym
->next
) != NULL
) {
1967 sym_push(sym
->v
& ~SYM_FIELD
, type
, VT_LOCAL
| VT_LVAL
, addr
);
1968 size
= type_size(type
, &align
);
1969 size
= (size
+ 3) & ~3;
1971 // keep track of size of arguments so
1972 // we can translate where tcc thinks they
1973 // are on the stack into the appropriate reg
1975 TranslateStackToReg
[NoOfCurFuncArgs
] = size
;
1978 #ifdef FUNC_STRUCT_PARAM_AS_PTR
1979 /* structs are passed as pointer */
1980 if ((type
->t
& VT_BTYPE
) == VT_STRUCT
) {
1987 /* pascal type call ? */
1988 if (func_call
== FUNC_STDCALL
)
1989 func_ret_sub
= addr
- 8;
1991 C67_MV(C67_FP
, C67_A0
); // move FP -> A0
1992 C67_MV(C67_SP
, C67_FP
); // move SP -> FP
1994 // place all the args passed in regs onto the stack
1997 for (i
= 0; i
< NoOfCurFuncArgs
; i
++) {
1999 ParamLocOnStack
[i
] = loc
; // remember where the param is
2002 C67_PUSH(TREG_C67_A4
+ i
* 2);
2004 if (TranslateStackToReg
[i
] == 8) {
2005 C67_STW_PTR_PRE_INC(TREG_C67_A4
+ i
* 2 + 1, C67_SP
, 3); // STW r, *+SP[1] (go back and put the other)
2009 TotalBytesPushedOnStack
= -loc
;
2011 func_sub_sp_offset
= ind
; // remember where we put the stack instruction
2012 C67_ADDK(0, C67_SP
); // ADDK.L2 loc,SP (just put zero temporarily)
2018 /* generate function epilog */
2019 void gfunc_epilog(void)
2022 int local
= (-loc
+ 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2024 C67_NOP(4); // NOP wait for load
2025 C67_IREG_B_REG(0, C67_CREG_ZERO
, C67_B3
); // B.S2 B3
2027 C67_ADDK(local
, C67_SP
); // ADDK.L2 loc,SP
2028 C67_Adjust_ADDK((int *) (cur_text_section
->data
+
2029 func_sub_sp_offset
),
2030 -local
+ TotalBytesPushedOnStack
);
2035 ST_FUNC
void gen_fill_nops(int bytes
)
2038 tcc_error("alignment of code section not multiple of 4");
2045 /* generate a jump to a label */
2052 C67_MVKL(C67_A0
, t
); //r=reg to load, constant
2053 C67_MVKH(C67_A0
, t
); //r=reg to load, constant
2054 C67_IREG_B_REG(0, C67_CREG_ZERO
, C67_A0
); // [!R] B.S2x A0
2059 /* generate a jump to a fixed address */
2060 void gjmp_addr(int a
)
2063 // I guess this routine is used for relative short
2064 // local jumps, for now just handle it as the general
2067 // define a label that will be relocated
2069 sym
= get_sym_ref(&char_pointer_type
, cur_text_section
, a
, 0);
2070 greloc(cur_text_section
, sym
, ind
, R_C60LO16
);
2071 greloc(cur_text_section
, sym
, ind
+ 4, R_C60HI16
);
2073 gjmp(0); // place a zero there later the symbol will be added to it
2076 /* generate a test. set 'inv' to invert test. Stack entry is popped */
2077 ST_FUNC
int gjmp_cond(int op
, int t
)
2084 /* fast case : can jump directly since flags are set */
2085 // C67 uses B2 sort of as flags register
2087 C67_MVKL(C67_A0
, t
); //r=reg to load, constant
2088 C67_MVKH(C67_A0
, t
); //r=reg to load, constant
2090 if (C67_compare_reg
!= TREG_EAX
&& // check if not already in a conditional test reg
2091 C67_compare_reg
!= TREG_EDX
&&
2092 C67_compare_reg
!= TREG_ST0
&& C67_compare_reg
!= C67_B2
) {
2093 C67_MV(C67_compare_reg
, C67_B2
);
2094 C67_compare_reg
= C67_B2
;
2097 C67_IREG_B_REG(C67_invert_test
^ inv
, C67_compare_reg
, C67_A0
); // [!R] B.S2x A0
2099 t
= ind1
; //return where we need to patch
2104 ST_FUNC
int gjmp_append(int n0
, int t
)
2108 /* insert vtop->c jump list in t */
2110 // I guess the idea is to traverse to the
2111 // null at the end of the list and store t
2114 p
= (int *) (cur_text_section
->data
+ n
);
2116 // extract 32 bit address from MVKH/MVKL
2117 n
= ((*p
>> 7) & 0xffff);
2118 n
|= ((*(p
+ 1) >> 7) & 0xffff) << 16;
2120 *p
|= (t
& 0xffff) << 7;
2121 *(p
+ 1) |= ((t
>> 16) & 0xffff) << 7;
2127 /* generate an integer binary operation */
2128 void gen_opi(int op
)
2134 case TOK_ADDC1
: /* add with carry generation */
2139 // C67 can't do const compares, must load into a reg
2140 // so just go to gv2 directly - tktk
2144 if (op
>= TOK_ULT
&& op
<= TOK_GT
)
2145 gv2(RC_INT_BSIDE
, RC_INT
); // make sure r (src1) is on the B Side of CPU
2147 gv2(RC_INT
, RC_INT
);
2152 C67_compare_reg
= C67_B2
;
2156 C67_CMPLT(r
, fr
, C67_B2
);
2157 C67_invert_test
= FALSE
;
2158 } else if (op
== TOK_GE
) {
2159 C67_CMPLT(r
, fr
, C67_B2
);
2160 C67_invert_test
= TRUE
;
2161 } else if (op
== TOK_GT
) {
2162 C67_CMPGT(r
, fr
, C67_B2
);
2163 C67_invert_test
= FALSE
;
2164 } else if (op
== TOK_LE
) {
2165 C67_CMPGT(r
, fr
, C67_B2
);
2166 C67_invert_test
= TRUE
;
2167 } else if (op
== TOK_EQ
) {
2168 C67_CMPEQ(r
, fr
, C67_B2
);
2169 C67_invert_test
= FALSE
;
2170 } else if (op
== TOK_NE
) {
2171 C67_CMPEQ(r
, fr
, C67_B2
);
2172 C67_invert_test
= TRUE
;
2173 } else if (op
== TOK_ULT
) {
2174 C67_CMPLTU(r
, fr
, C67_B2
);
2175 C67_invert_test
= FALSE
;
2176 } else if (op
== TOK_UGE
) {
2177 C67_CMPLTU(r
, fr
, C67_B2
);
2178 C67_invert_test
= TRUE
;
2179 } else if (op
== TOK_UGT
) {
2180 C67_CMPGTU(r
, fr
, C67_B2
);
2181 C67_invert_test
= FALSE
;
2182 } else if (op
== TOK_ULE
) {
2183 C67_CMPGTU(r
, fr
, C67_B2
);
2184 C67_invert_test
= TRUE
;
2185 } else if (op
== '+')
2186 C67_ADD(fr
, r
); // ADD r,fr,r
2188 C67_SUB(fr
, r
); // SUB r,fr,r
2190 C67_AND(fr
, r
); // AND r,fr,r
2192 C67_OR(fr
, r
); // OR r,fr,r
2194 C67_XOR(fr
, r
); // XOR r,fr,r
2196 ALWAYS_ASSERT(FALSE
);
2199 if (op
>= TOK_ULT
&& op
<= TOK_GT
)
2203 case TOK_SUBC1
: /* sub with carry generation */
2206 case TOK_ADDC2
: /* add with carry use */
2209 case TOK_SUBC2
: /* sub with carry use */
2223 gv2(RC_INT
, RC_INT
);
2227 C67_MPYI(fr
, r
); // 32 bit multiply fr,r,fr
2228 C67_NOP(8); // NOP 8 for worst case
2231 gv2(RC_INT_BSIDE
, RC_INT_BSIDE
); // shift amount must be on same side as dst
2235 C67_SHL(fr
, r
); // arithmetic/logical shift
2239 gv2(RC_INT_BSIDE
, RC_INT_BSIDE
); // shift amount must be on same side as dst
2243 C67_SHRU(fr
, r
); // logical shift
2247 gv2(RC_INT_BSIDE
, RC_INT_BSIDE
); // shift amount must be on same side as dst
2251 C67_SHR(fr
, r
); // arithmetic shift
2258 /* call generic idiv function */
2259 vpush_global_sym(&func_old_type
, t
);
2264 vtop
->r2
= VT_CONST
;
2283 /* generate a floating point operation 'v = t1 op t2' instruction. The
2284 two operands are guaranteed to have the same floating point type */
2285 /* XXX: need to use ST1 too */
2286 void gen_opf(int op
)
2290 if (op
>= TOK_ULT
&& op
<= TOK_GT
)
2291 gv2(RC_EDX
, RC_EAX
); // make sure src2 is on b side
2293 gv2(RC_FLOAT
, RC_FLOAT
); // make sure src2 is on b side
2301 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
)
2302 tcc_error("long doubles not supported");
2304 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2309 C67_compare_reg
= C67_B2
;
2312 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2313 C67_CMPLTDP(r
, fr
, C67_B2
);
2315 C67_CMPLTSP(r
, fr
, C67_B2
);
2317 C67_invert_test
= FALSE
;
2318 } else if (op
== TOK_GE
) {
2319 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2320 C67_CMPLTDP(r
, fr
, C67_B2
);
2322 C67_CMPLTSP(r
, fr
, C67_B2
);
2324 C67_invert_test
= TRUE
;
2325 } else if (op
== TOK_GT
) {
2326 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2327 C67_CMPGTDP(r
, fr
, C67_B2
);
2329 C67_CMPGTSP(r
, fr
, C67_B2
);
2331 C67_invert_test
= FALSE
;
2332 } else if (op
== TOK_LE
) {
2333 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2334 C67_CMPGTDP(r
, fr
, C67_B2
);
2336 C67_CMPGTSP(r
, fr
, C67_B2
);
2338 C67_invert_test
= TRUE
;
2339 } else if (op
== TOK_EQ
) {
2340 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2341 C67_CMPEQDP(r
, fr
, C67_B2
);
2343 C67_CMPEQSP(r
, fr
, C67_B2
);
2345 C67_invert_test
= FALSE
;
2346 } else if (op
== TOK_NE
) {
2347 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2348 C67_CMPEQDP(r
, fr
, C67_B2
);
2350 C67_CMPEQSP(r
, fr
, C67_B2
);
2352 C67_invert_test
= TRUE
;
2354 ALWAYS_ASSERT(FALSE
);
2359 if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
2360 C67_ADDDP(r
, fr
); // ADD fr,r,fr
2363 C67_ADDSP(r
, fr
); // ADD fr,r,fr
2367 } else if (op
== '-') {
2368 if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
2369 C67_SUBDP(r
, fr
); // SUB fr,r,fr
2372 C67_SUBSP(r
, fr
); // SUB fr,r,fr
2376 } else if (op
== '*') {
2377 if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
2378 C67_MPYDP(r
, fr
); // MPY fr,r,fr
2381 C67_MPYSP(r
, fr
); // MPY fr,r,fr
2385 } else if (op
== '/') {
2386 if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
2387 // must call intrinsic DP floating point divide
2389 /* call generic idiv function */
2390 vpush_global_sym(&func_old_type
, TOK__divd
);
2395 vtop
->r2
= REG_IRE2
;
2398 // must call intrinsic SP floating point divide
2400 /* call generic idiv function */
2401 vpush_global_sym(&func_old_type
, TOK__divf
);
2406 vtop
->r2
= VT_CONST
;
2409 ALWAYS_ASSERT(FALSE
);
2416 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2417 and 'long long' cases. */
2418 void gen_cvt_itof(int t
)
2425 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
2426 if (t
& VT_UNSIGNED
)
2432 vtop
->type
.t
= VT_DOUBLE
;
2434 if (t
& VT_UNSIGNED
)
2439 vtop
->type
.t
= VT_FLOAT
;
2444 /* convert fp to int 't' type */
2445 /* XXX: handle long long case */
2446 void gen_cvt_ftoi(int t
)
2454 tcc_error("long long not supported");
2456 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
) {
2464 vtop
->type
.t
= VT_INT
;
2469 /* convert from one floating point type to another */
2470 void gen_cvt_ftof(int t
)
2474 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
&&
2475 (t
& VT_BTYPE
) == VT_FLOAT
) {
2476 // convert double to float
2478 gv(RC_FLOAT
); // get it in a register pair
2482 C67_DPSP(r
, r
); // convert it to SP same register
2485 vtop
->type
.t
= VT_FLOAT
;
2486 vtop
->r2
= VT_CONST
; // set this as unused
2487 } else if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
&&
2488 (t
& VT_BTYPE
) == VT_DOUBLE
) {
2489 // convert float to double
2491 gv(RC_FLOAT
); // get it in a register
2495 if (r
== TREG_EAX
) { // make sure the paired reg is avail
2496 r2
= get_reg(RC_ECX
);
2497 } else if (r
== TREG_EDX
) {
2498 r2
= get_reg(RC_ST0
);
2500 ALWAYS_ASSERT(FALSE
);
2501 r2
= 0; /* avoid warning */
2504 C67_SPDP(r
, r
); // convert it to DP same register
2507 vtop
->type
.t
= VT_DOUBLE
;
2508 vtop
->r2
= r2
; // set this as unused
2510 ALWAYS_ASSERT(FALSE
);
2514 /* computed goto support */
2521 /* Save the stack pointer onto the stack and return the location of its address */
2522 ST_FUNC
void gen_vla_sp_save(int addr
) {
2523 tcc_error("variable length arrays unsupported for this target");
2526 /* Restore the SP from a location on the stack */
2527 ST_FUNC
void gen_vla_sp_restore(int addr
) {
2528 tcc_error("variable length arrays unsupported for this target");
2531 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2532 ST_FUNC
void gen_vla_alloc(CType
*type
, int align
) {
2533 tcc_error("variable length arrays unsupported for this target");
2536 /* end of C67 code generator */
2537 /*************************************************************/
2539 /*************************************************************/