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_LRET RC_C67_A5 /* function return: second integer register */
60 #define RC_FRET RC_C67_A4 /* function return: float register */
62 /* pretty names for the registers */
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_LRET TREG_C67_A5 /* second word return register (for long long) */
93 #define REG_FRET TREG_C67_A4 /* float return register */
95 /* defined if function parameters must be evaluated in reverse order */
96 /* #define INVERT_FUNC_PARAMS */
98 /* defined if structures are passed as pointers. Otherwise structures
99 are directly pushed on stack. */
100 /* #define FUNC_STRUCT_PARAM_AS_PTR */
102 /* pointer size, in bytes */
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 /******************************************************/
114 #define EM_TCC_TARGET EM_C60
116 /* relocation type for 32 bit data relocation */
117 #define R_DATA_32 R_C60_32
118 #define R_DATA_PTR R_C60_32
119 #define R_JMP_SLOT R_C60_JMP_SLOT
120 #define R_COPY R_C60_COPY
122 #define ELF_START_ADDR 0x00000400
123 #define ELF_PAGE_SIZE 0x1000
125 /******************************************************/
126 #else /* ! TARGET_DEFS_ONLY */
127 /******************************************************/
130 ST_DATA
const int reg_classes
[NB_REGS
] = {
131 /* eax */ RC_INT
| RC_FLOAT
| RC_EAX
,
132 // only allow even regs for floats (allow for doubles)
133 /* ecx */ RC_INT
| RC_ECX
,
134 /* edx */ RC_INT
| RC_INT_BSIDE
| RC_FLOAT
| RC_EDX
,
135 // only allow even regs for floats (allow for doubles)
136 /* st0 */ RC_INT
| RC_INT_BSIDE
| RC_ST0
,
149 /* A10 */ RC_C67_A10
,
150 /* A11 */ RC_C67_A11
,
151 /* B10 */ RC_C67_B10
,
152 /* B11 */ RC_C67_B11
,
153 /* A12 */ RC_C67_A10
,
154 /* A13 */ RC_C67_A11
,
155 /* B12 */ RC_C67_B10
,
159 // although tcc thinks it is passing parameters on the stack,
160 // the C67 really passes up to the first 10 params in special
161 // regs or regs pairs (for 64 bit params). So keep track of
162 // the stack offsets so we can translate to the appropriate
165 #define NoCallArgsPassedOnStack 10
167 int TranslateStackToReg
[NoCallArgsPassedOnStack
];
168 int ParamLocOnStack
[NoCallArgsPassedOnStack
];
169 int TotalBytesPushedOnStack
;
179 #define ALWAYS_ASSERT(x) \
182 tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
185 /******************************************************/
186 static unsigned long func_sub_sp_offset
;
187 static int func_ret_sub
;
189 static BOOL C67_invert_test
;
190 static int C67_compare_reg
;
192 #ifdef ASSEMBLY_LISTING_C67
200 #ifdef ASSEMBLY_LISTING_C67
201 fprintf(f
, " %08X", c
);
204 if (ind1
> (int) cur_text_section
->data_allocated
)
205 section_realloc(cur_text_section
, ind1
);
206 cur_text_section
->data
[ind
] = c
& 0xff;
207 cur_text_section
->data
[ind
+ 1] = (c
>> 8) & 0xff;
208 cur_text_section
->data
[ind
+ 2] = (c
>> 16) & 0xff;
209 cur_text_section
->data
[ind
+ 3] = (c
>> 24) & 0xff;
214 /* output a symbol and patch all calls to it */
215 void gsym_addr(int t
, int a
)
219 ptr
= (int *) (cur_text_section
->data
+ t
);
223 // extract 32 bit address from MVKH/MVKL
224 n
= ((*ptr
>> 7) & 0xffff);
225 n
|= ((*(ptr
+ 1) >> 7) & 0xffff) << 16;
227 // define a label that will be relocated
229 sym
= get_sym_ref(&char_pointer_type
, cur_text_section
, a
, 0);
230 greloc(cur_text_section
, sym
, t
, R_C60LO16
);
231 greloc(cur_text_section
, sym
, t
+ 4, R_C60HI16
);
233 // clear out where the pointer was
235 *ptr
&= ~(0xffff << 7);
236 *(ptr
+ 1) &= ~(0xffff << 7);
247 // these are regs that tcc doesn't really know about,
248 // but assign them unique values so the mapping routines
249 // can distinguish them
256 #define C67_CREG_ZERO -1 /* Special code for no condition reg test */
259 int ConvertRegToRegClass(int r
)
261 // only works for A4-B13
263 return RC_C67_A4
<< (r
- TREG_C67_A4
);
267 // map TCC reg to C67 reg number
269 int C67_map_regn(int r
)
271 if (r
== 0) // normal tcc regs
273 else if (r
== 1) // normal tcc regs
275 else if (r
== 2) // normal tcc regs
277 else if (r
== 3) // normal tcc regs
279 else if (r
>= TREG_C67_A4
&& r
<= TREG_C67_B13
) // these form a pattern of alt pairs
280 return (((r
& 0xfffffffc) >> 1) | (r
& 1)) + 2;
281 else if (r
== C67_A0
)
282 return 0; // set to A0 (offset reg)
283 else if (r
== C67_B2
)
284 return 2; // set to B2 (offset reg)
285 else if (r
== C67_B3
)
286 return 3; // set to B3 (return address reg)
287 else if (r
== C67_SP
)
288 return 15; // set to SP (B15) (offset reg)
289 else if (r
== C67_FP
)
290 return 15; // set to FP (A15) (offset reg)
291 else if (r
== C67_CREG_ZERO
)
292 return 0; // Special code for no condition reg test
294 ALWAYS_ASSERT(FALSE
);
299 // mapping from tcc reg number to
300 // C67 register to condition code field
302 // valid condition code regs are:
304 // tcc reg 2 ->B0 -> 1
305 // tcc reg 3 ->B1 -> 2
306 // tcc reg 0 -> A2 -> 5
307 // tcc reg 1 -> A3 -> X
310 int C67_map_regc(int r
)
312 if (r
== 0) // normal tcc regs
314 else if (r
== 2) // normal tcc regs
316 else if (r
== 3) // normal tcc regs
318 else if (r
== C67_B2
) // normal tcc regs
320 else if (r
== C67_CREG_ZERO
)
321 return 0; // Special code for no condition reg test
323 ALWAYS_ASSERT(FALSE
);
329 // map TCC reg to C67 reg side A or B
331 int C67_map_regs(int r
)
333 if (r
== 0) // normal tcc regs
335 else if (r
== 1) // normal tcc regs
337 else if (r
== 2) // normal tcc regs
339 else if (r
== 3) // normal tcc regs
341 else if (r
>= TREG_C67_A4
&& r
<= TREG_C67_B13
) // these form a pattern of alt pairs
343 else if (r
== C67_A0
)
344 return 0; // set to A side
345 else if (r
== C67_B2
)
346 return 1; // set to B side
347 else if (r
== C67_B3
)
348 return 1; // set to B side
349 else if (r
== C67_SP
)
350 return 0x1; // set to SP (B15) B side
351 else if (r
== C67_FP
)
352 return 0x0; // set to FP (A15) A side
354 ALWAYS_ASSERT(FALSE
);
359 int C67_map_S12(char *s
)
361 if (strstr(s
, ".S1") != NULL
)
363 else if (strcmp(s
, ".S2"))
366 ALWAYS_ASSERT(FALSE
);
371 int C67_map_D12(char *s
)
373 if (strstr(s
, ".D1") != NULL
)
375 else if (strcmp(s
, ".D2"))
378 ALWAYS_ASSERT(FALSE
);
385 void C67_asm(char *s
, int a
, int b
, int c
)
389 #ifdef ASSEMBLY_LISTING_C67
391 f
= fopen("TCC67_out.txt", "wt");
393 fprintf(f
, "%04X ", ind
);
396 if (strstr(s
, "MVKL") == s
) {
397 C67_g((C67_map_regn(b
) << 23) |
398 ((a
& 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b
) << 1));
399 } else if (strstr(s
, "MVKH") == s
) {
400 C67_g((C67_map_regn(b
) << 23) |
401 (((a
>> 16) & 0xffff) << 7) |
402 (0x1a << 2) | (C67_map_regs(b
) << 1));
403 } else if (strstr(s
, "STW.D SP POST DEC") == s
) {
404 C67_g((C67_map_regn(a
) << 23) | //src
405 (15 << 18) | //SP B15
406 (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
407 (0xa << 9) | //mode a = post dec ucst
408 (0 << 8) | //r (LDDW bit 0)
409 (1 << 7) | //y D1/D2 use B side
410 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
412 (C67_map_regs(a
) << 1) | //side of src
413 (0 << 0)); //parallel
414 } else if (strstr(s
, "STB.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 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
423 (C67_map_regs(a
) << 1) | //side of src
424 (0 << 0)); //parallel
425 } else if (strstr(s
, "STH.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 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
434 (C67_map_regs(a
) << 1) | //side of src
435 (0 << 0)); //parallel
436 } else if (strstr(s
, "STB.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 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
445 (C67_map_regs(a
) << 1) | //side of src
446 (0 << 0)); //parallel
447 } else if (strstr(s
, "STH.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 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
456 (C67_map_regs(a
) << 1) | //side of src
457 (0 << 0)); //parallel
458 } else if (strstr(s
, "STW.D *+SP[A0]") == s
) {
459 C67_g((C67_map_regn(a
) << 23) | //src
460 (15 << 18) | //base reg A15
461 (0 << 13) | //offset reg A0
462 (5 << 9) | //mode 5 = pos offset, base reg + off reg
463 (0 << 8) | //r (LDDW bit 0)
464 (0 << 7) | //y D1/D2 A side
465 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
467 (C67_map_regs(a
) << 1) | //side of src
468 (0 << 0)); //parallel
469 } else if (strstr(s
, "STW.D *") == s
) {
470 C67_g((C67_map_regn(a
) << 23) | //src
471 (C67_map_regn(b
) << 18) | //base reg A0
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 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
478 (C67_map_regs(a
) << 1) | //side of src
479 (0 << 0)); //parallel
480 } else if (strstr(s
, "STH.D *") == s
) {
481 C67_g((C67_map_regn(a
) << 23) | //src
482 (C67_map_regn(b
) << 18) | //base reg A0
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 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
489 (C67_map_regs(a
) << 1) | //side of src
490 (0 << 0)); //parallel
491 } else if (strstr(s
, "STB.D *") == s
) {
492 C67_g((C67_map_regn(a
) << 23) | //src
493 (C67_map_regn(b
) << 18) | //base reg A0
495 (1 << 9) | //mode 1 = pos cst offset
496 (0 << 8) | //r (LDDW bit 0)
497 (C67_map_regs(b
) << 7) | //y D1/D2 base reg side
498 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
500 (C67_map_regs(a
) << 1) | //side of src
501 (0 << 0)); //parallel
502 } else if (strstr(s
, "STW.D +*") == s
) {
503 ALWAYS_ASSERT(c
< 32);
504 C67_g((C67_map_regn(a
) << 23) | //src
505 (C67_map_regn(b
) << 18) | //base reg A0
507 (1 << 9) | //mode 1 = pos cst offset
508 (0 << 8) | //r (LDDW bit 0)
509 (C67_map_regs(b
) << 7) | //y D1/D2 base reg side
510 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
512 (C67_map_regs(a
) << 1) | //side of src
513 (0 << 0)); //parallel
514 } else if (strstr(s
, "LDW.D SP PRE INC") == s
) {
515 C67_g((C67_map_regn(a
) << 23) | //dst
516 (15 << 18) | //base reg B15
517 (2 << 13) | //ucst5 (must keep 8 byte boundary)
518 (9 << 9) | //mode 9 = pre inc ucst5
519 (0 << 8) | //r (LDDW bit 0)
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
523 (C67_map_regs(a
) << 1) | //side of dst
524 (0 << 0)); //parallel
525 } else if (strstr(s
, "LDDW.D SP PRE INC") == s
) {
526 C67_g((C67_map_regn(a
) << 23) | //dst
527 (15 << 18) | //base reg B15
528 (1 << 13) | //ucst5 (must keep 8 byte boundary)
529 (9 << 9) | //mode 9 = pre inc ucst5
530 (1 << 8) | //r (LDDW bit 1)
531 (1 << 7) | //y D1/D2 B side
532 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
534 (C67_map_regs(a
) << 1) | //side of dst
535 (0 << 0)); //parallel
536 } else if (strstr(s
, "LDW.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 (0 << 8) | //r (LDDW bit 0)
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
545 (C67_map_regs(a
) << 1) | //side of dst
546 (0 << 0)); //parallel
547 } else if (strstr(s
, "LDDW.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 (1 << 8) | //r (LDDW bit 1)
553 (0 << 7) | //y D1/D2 A side
554 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
556 (C67_map_regs(a
) << 1) | //side of dst
557 (0 << 0)); //parallel
558 } else if (strstr(s
, "LDH.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 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
567 (C67_map_regs(a
) << 1) | //side of dst
568 (0 << 0)); //parallel
569 } else if (strstr(s
, "LDB.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 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
578 (C67_map_regs(a
) << 1) | //side of dst
579 (0 << 0)); //parallel
580 } else if (strstr(s
, "LDHU.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 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
589 (C67_map_regs(a
) << 1) | //side of dst
590 (0 << 0)); //parallel
591 } else if (strstr(s
, "LDBU.D *+SP[A0]") == s
) {
592 C67_g((C67_map_regn(a
) << 23) | //dst
593 (15 << 18) | //base reg A15
594 (0 << 13) | //offset reg A0
595 (5 << 9) | //mode 5 = pos offset, base reg + off reg
596 (0 << 8) | //r (LDDW bit 0)
597 (0 << 7) | //y D1/D2 A side
598 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
600 (C67_map_regs(a
) << 1) | //side of dst
601 (0 << 0)); //parallel
602 } else if (strstr(s
, "LDW.D *") == s
) {
603 C67_g((C67_map_regn(b
) << 23) | //dst
604 (C67_map_regn(a
) << 18) | //base reg A15
606 (1 << 9) | //mode 1 = pos cst offset
607 (0 << 8) | //r (LDDW bit 0)
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
611 (C67_map_regs(b
) << 1) | //side of dst
612 (0 << 0)); //parallel
613 } else if (strstr(s
, "LDDW.D *") == s
) {
614 C67_g((C67_map_regn(b
) << 23) | //dst
615 (C67_map_regn(a
) << 18) | //base reg A15
617 (1 << 9) | //mode 1 = pos cst offset
618 (1 << 8) | //r (LDDW bit 1)
619 (C67_map_regs(a
) << 7) | //y D1/D2 src side
620 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
622 (C67_map_regs(b
) << 1) | //side of dst
623 (0 << 0)); //parallel
624 } else if (strstr(s
, "LDH.D *") == s
) {
625 C67_g((C67_map_regn(b
) << 23) | //dst
626 (C67_map_regn(a
) << 18) | //base reg A15
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 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
633 (C67_map_regs(b
) << 1) | //side of dst
634 (0 << 0)); //parallel
635 } else if (strstr(s
, "LDB.D *") == s
) {
636 C67_g((C67_map_regn(b
) << 23) | //dst
637 (C67_map_regn(a
) << 18) | //base reg A15
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 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
644 (C67_map_regs(b
) << 1) | //side of dst
645 (0 << 0)); //parallel
646 } else if (strstr(s
, "LDHU.D *") == s
) {
647 C67_g((C67_map_regn(b
) << 23) | //dst
648 (C67_map_regn(a
) << 18) | //base reg A15
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 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
655 (C67_map_regs(b
) << 1) | //side of dst
656 (0 << 0)); //parallel
657 } else if (strstr(s
, "LDBU.D *") == s
) {
658 C67_g((C67_map_regn(b
) << 23) | //dst
659 (C67_map_regn(a
) << 18) | //base reg A15
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 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
666 (C67_map_regs(b
) << 1) | //side of dst
667 (0 << 0)); //parallel
668 } else if (strstr(s
, "LDW.D +*") == s
) {
669 C67_g((C67_map_regn(b
) << 23) | //dst
670 (C67_map_regn(a
) << 18) | //base reg A15
672 (1 << 9) | //mode 1 = pos cst offset
673 (0 << 8) | //r (LDDW bit 0)
674 (C67_map_regs(a
) << 7) | //y D1/D2 src side
675 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
677 (C67_map_regs(b
) << 1) | //side of dst
678 (0 << 0)); //parallel
679 } else if (strstr(s
, "CMPLTSP") == s
) {
680 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
681 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
683 C67_g((C67_map_regn(c
) << 23) | //dst
684 (C67_map_regn(b
) << 18) | //src2
685 (C67_map_regn(a
) << 13) | //src1
686 (xpath
<< 12) | //x use cross path for src2
687 (0x3a << 6) | //opcode
688 (0x8 << 2) | //opcode fixed
689 (C67_map_regs(c
) << 1) | //side for reg c
690 (0 << 0)); //parallel
691 } else if (strstr(s
, "CMPGTSP") == s
) {
692 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
693 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
695 C67_g((C67_map_regn(c
) << 23) | //dst
696 (C67_map_regn(b
) << 18) | //src2
697 (C67_map_regn(a
) << 13) | //src1
698 (xpath
<< 12) | //x use cross path for src2
699 (0x39 << 6) | //opcode
700 (0x8 << 2) | //opcode fixed
701 (C67_map_regs(c
) << 1) | //side for reg c
702 (0 << 0)); //parallel
703 } else if (strstr(s
, "CMPEQSP") == s
) {
704 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
705 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
707 C67_g((C67_map_regn(c
) << 23) | //dst
708 (C67_map_regn(b
) << 18) | //src2
709 (C67_map_regn(a
) << 13) | //src1
710 (xpath
<< 12) | //x use cross path for src2
711 (0x38 << 6) | //opcode
712 (0x8 << 2) | //opcode fixed
713 (C67_map_regs(c
) << 1) | //side for reg c
714 (0 << 0)); //parallel
717 else if (strstr(s
, "CMPLTDP") == s
) {
718 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
719 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
721 C67_g((C67_map_regn(c
) << 23) | //dst
722 (C67_map_regn(b
) << 18) | //src2
723 (C67_map_regn(a
) << 13) | //src1
724 (xpath
<< 12) | //x use cross path for src2
725 (0x2a << 6) | //opcode
726 (0x8 << 2) | //opcode fixed
727 (C67_map_regs(c
) << 1) | //side for reg c
728 (0 << 0)); //parallel
729 } else if (strstr(s
, "CMPGTDP") == s
) {
730 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
731 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
733 C67_g((C67_map_regn(c
) << 23) | //dst
734 (C67_map_regn(b
) << 18) | //src2
735 (C67_map_regn(a
) << 13) | //src1
736 (xpath
<< 12) | //x use cross path for src2
737 (0x29 << 6) | //opcode
738 (0x8 << 2) | //opcode fixed
739 (C67_map_regs(c
) << 1) | //side for reg c
740 (0 << 0)); //parallel
741 } else if (strstr(s
, "CMPEQDP") == s
) {
742 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
743 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
745 C67_g((C67_map_regn(c
) << 23) | //dst
746 (C67_map_regn(b
) << 18) | //src2
747 (C67_map_regn(a
) << 13) | //src1
748 (xpath
<< 12) | //x use cross path for src2
749 (0x28 << 6) | //opcode
750 (0x8 << 2) | //opcode fixed
751 (C67_map_regs(c
) << 1) | //side for reg c
752 (0 << 0)); //parallel
753 } else if (strstr(s
, "CMPLT") == s
) {
754 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
755 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
757 C67_g((C67_map_regn(c
) << 23) | //dst
758 (C67_map_regn(b
) << 18) | //src2
759 (C67_map_regn(a
) << 13) | //src1
760 (xpath
<< 12) | //x use cross path for src2
761 (0x57 << 5) | //opcode
762 (0x6 << 2) | //opcode fixed
763 (C67_map_regs(c
) << 1) | //side for reg c
764 (0 << 0)); //parallel
765 } else if (strstr(s
, "CMPGT") == s
) {
766 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
767 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
769 C67_g((C67_map_regn(c
) << 23) | //dst
770 (C67_map_regn(b
) << 18) | //src2
771 (C67_map_regn(a
) << 13) | //src1
772 (xpath
<< 12) | //x use cross path for src2
773 (0x47 << 5) | //opcode
774 (0x6 << 2) | //opcode fixed
775 (C67_map_regs(c
) << 1) | //side for reg c
776 (0 << 0)); //parallel
777 } else if (strstr(s
, "CMPEQ") == s
) {
778 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
779 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
781 C67_g((C67_map_regn(c
) << 23) | //dst
782 (C67_map_regn(b
) << 18) | //src2
783 (C67_map_regn(a
) << 13) | //src1
784 (xpath
<< 12) | //x use cross path for src2
785 (0x53 << 5) | //opcode
786 (0x6 << 2) | //opcode fixed
787 (C67_map_regs(c
) << 1) | //side for reg c
788 (0 << 0)); //parallel
789 } else if (strstr(s
, "CMPLTU") == s
) {
790 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
791 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
793 C67_g((C67_map_regn(c
) << 23) | //dst
794 (C67_map_regn(b
) << 18) | //src2
795 (C67_map_regn(a
) << 13) | //src1
796 (xpath
<< 12) | //x use cross path for src2
797 (0x5f << 5) | //opcode
798 (0x6 << 2) | //opcode fixed
799 (C67_map_regs(c
) << 1) | //side for reg c
800 (0 << 0)); //parallel
801 } else if (strstr(s
, "CMPGTU") == s
) {
802 xpath
= C67_map_regs(a
) ^ C67_map_regs(b
);
803 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
805 C67_g((C67_map_regn(c
) << 23) | //dst
806 (C67_map_regn(b
) << 18) | //src2
807 (C67_map_regn(a
) << 13) | //src1
808 (xpath
<< 12) | //x use cross path for src2
809 (0x4f << 5) | //opcode
810 (0x6 << 2) | //opcode fixed
811 (C67_map_regs(c
) << 1) | //side for reg c
812 (0 << 0)); //parallel
813 } else if (strstr(s
, "B DISP") == s
) {
814 C67_g((0 << 29) | //creg
817 (0x4 << 2) | //opcode fixed
819 (0 << 0)); //parallel
820 } else if (strstr(s
, "B.") == s
) {
821 xpath
= C67_map_regs(c
) ^ 1;
823 C67_g((C67_map_regc(b
) << 29) | //creg
826 (C67_map_regn(c
) << 18) | //src2
828 (xpath
<< 12) | //x cross path if !B side
829 (0xd << 6) | //opcode
830 (0x8 << 2) | //opcode fixed
831 (1 << 1) | //must be S2
832 (0 << 0)); //parallel
833 } else if (strstr(s
, "MV.L") == s
) {
834 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
836 C67_g((0 << 29) | //creg
838 (C67_map_regn(c
) << 23) | //dst
839 (C67_map_regn(b
) << 18) | //src2
840 (0 << 13) | //src1 (cst5)
841 (xpath
<< 12) | //x cross path if opposite sides
842 (0x2 << 5) | //opcode
843 (0x6 << 2) | //opcode fixed
844 (C67_map_regs(c
) << 1) | //side of dest
845 (0 << 0)); //parallel
846 } else if (strstr(s
, "SPTRUNC.L") == s
) {
847 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
849 C67_g((0 << 29) | //creg
851 (C67_map_regn(c
) << 23) | //dst
852 (C67_map_regn(b
) << 18) | //src2
853 (0 << 13) | //src1 NA
854 (xpath
<< 12) | //x cross path if opposite sides
855 (0xb << 5) | //opcode
856 (0x6 << 2) | //opcode fixed
857 (C67_map_regs(c
) << 1) | //side of dest
858 (0 << 0)); //parallel
859 } else if (strstr(s
, "DPTRUNC.L") == s
) {
860 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
862 C67_g((0 << 29) | //creg
864 (C67_map_regn(c
) << 23) | //dst
865 ((C67_map_regn(b
) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
866 (0 << 13) | //src1 NA
867 (xpath
<< 12) | //x cross path if opposite sides
868 (0x1 << 5) | //opcode
869 (0x6 << 2) | //opcode fixed
870 (C67_map_regs(c
) << 1) | //side of dest
871 (0 << 0)); //parallel
872 } else if (strstr(s
, "INTSP.L") == s
) {
873 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
875 C67_g((0 << 29) | //creg
877 (C67_map_regn(c
) << 23) | //dst
878 (C67_map_regn(b
) << 18) | //src2
879 (0 << 13) | //src1 NA
880 (xpath
<< 12) | //x cross path if opposite sides
881 (0x4a << 5) | //opcode
882 (0x6 << 2) | //opcode fixed
883 (C67_map_regs(c
) << 1) | //side of dest
884 (0 << 0)); //parallel
885 } else if (strstr(s
, "INTSPU.L") == s
) {
886 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
888 C67_g((0 << 29) | //creg
890 (C67_map_regn(c
) << 23) | //dst
891 (C67_map_regn(b
) << 18) | //src2
892 (0 << 13) | //src1 NA
893 (xpath
<< 12) | //x cross path if opposite sides
894 (0x49 << 5) | //opcode
895 (0x6 << 2) | //opcode fixed
896 (C67_map_regs(c
) << 1) | //side of dest
897 (0 << 0)); //parallel
898 } else if (strstr(s
, "INTDP.L") == s
) {
899 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
901 C67_g((0 << 29) | //creg
903 (C67_map_regn(c
) << 23) | //dst
904 (C67_map_regn(b
) << 18) | //src2
905 (0 << 13) | //src1 NA
906 (xpath
<< 12) | //x cross path if opposite sides
907 (0x39 << 5) | //opcode
908 (0x6 << 2) | //opcode fixed
909 (C67_map_regs(c
) << 1) | //side of dest
910 (0 << 0)); //parallel
911 } else if (strstr(s
, "INTDPU.L") == s
) {
912 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
914 C67_g((0 << 29) | //creg
916 (C67_map_regn(c
) << 23) | //dst
917 ((C67_map_regn(b
) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
918 (0 << 13) | //src1 NA
919 (xpath
<< 12) | //x cross path if opposite sides
920 (0x3b << 5) | //opcode
921 (0x6 << 2) | //opcode fixed
922 (C67_map_regs(c
) << 1) | //side of dest
923 (0 << 0)); //parallel
924 } else if (strstr(s
, "SPDP.L") == s
) {
925 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
927 C67_g((0 << 29) | //creg
929 (C67_map_regn(c
) << 23) | //dst
930 (C67_map_regn(b
) << 18) | //src2
931 (0 << 13) | //src1 NA
932 (xpath
<< 12) | //x cross path if opposite sides
933 (0x2 << 6) | //opcode
934 (0x8 << 2) | //opcode fixed
935 (C67_map_regs(c
) << 1) | //side of dest
936 (0 << 0)); //parallel
937 } else if (strstr(s
, "DPSP.L") == s
) {
938 ALWAYS_ASSERT(C67_map_regs(b
) == C67_map_regs(c
));
940 C67_g((0 << 29) | //creg
942 (C67_map_regn(c
) << 23) | //dst
943 ((C67_map_regn(b
) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
944 (0 << 13) | //src1 NA
945 (0 << 12) | //x cross path if opposite sides
946 (0x9 << 5) | //opcode
947 (0x6 << 2) | //opcode fixed
948 (C67_map_regs(c
) << 1) | //side of dest
949 (0 << 0)); //parallel
950 } else if (strstr(s
, "ADD.L") == s
) {
951 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
953 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
955 C67_g((0 << 29) | //creg
957 (C67_map_regn(c
) << 23) | //dst
958 (C67_map_regn(b
) << 18) | //src2 (possible x path)
959 (C67_map_regn(a
) << 13) | //src1
960 (xpath
<< 12) | //x cross path if opposite sides
961 (0x3 << 5) | //opcode
962 (0x6 << 2) | //opcode fixed
963 (C67_map_regs(c
) << 1) | //side of dest
964 (0 << 0)); //parallel
965 } else if (strstr(s
, "SUB.L") == s
) {
966 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
968 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
970 C67_g((0 << 29) | //creg
972 (C67_map_regn(c
) << 23) | //dst
973 (C67_map_regn(b
) << 18) | //src2 (possible x path)
974 (C67_map_regn(a
) << 13) | //src1
975 (xpath
<< 12) | //x cross path if opposite sides
976 (0x7 << 5) | //opcode
977 (0x6 << 2) | //opcode fixed
978 (C67_map_regs(c
) << 1) | //side of dest
979 (0 << 0)); //parallel
980 } else if (strstr(s
, "OR.L") == s
) {
981 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
983 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
985 C67_g((0 << 29) | //creg
987 (C67_map_regn(c
) << 23) | //dst
988 (C67_map_regn(b
) << 18) | //src2 (possible x path)
989 (C67_map_regn(a
) << 13) | //src1
990 (xpath
<< 12) | //x cross path if opposite sides
991 (0x7f << 5) | //opcode
992 (0x6 << 2) | //opcode fixed
993 (C67_map_regs(c
) << 1) | //side of dest
994 (0 << 0)); //parallel
995 } else if (strstr(s
, "AND.L") == s
) {
996 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
998 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1000 C67_g((0 << 29) | //creg
1002 (C67_map_regn(c
) << 23) | //dst
1003 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1004 (C67_map_regn(a
) << 13) | //src1
1005 (xpath
<< 12) | //x cross path if opposite sides
1006 (0x7b << 5) | //opcode
1007 (0x6 << 2) | //opcode fixed
1008 (C67_map_regs(c
) << 1) | //side of dest
1009 (0 << 0)); //parallel
1010 } else if (strstr(s
, "XOR.L") == s
) {
1011 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1013 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1015 C67_g((0 << 29) | //creg
1017 (C67_map_regn(c
) << 23) | //dst
1018 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1019 (C67_map_regn(a
) << 13) | //src1
1020 (xpath
<< 12) | //x cross path if opposite sides
1021 (0x6f << 5) | //opcode
1022 (0x6 << 2) | //opcode fixed
1023 (C67_map_regs(c
) << 1) | //side of dest
1024 (0 << 0)); //parallel
1025 } else if (strstr(s
, "ADDSP.L") == s
) {
1026 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1028 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1030 C67_g((0 << 29) | //creg
1032 (C67_map_regn(c
) << 23) | //dst
1033 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1034 (C67_map_regn(a
) << 13) | //src1
1035 (xpath
<< 12) | //x cross path if opposite sides
1036 (0x10 << 5) | //opcode
1037 (0x6 << 2) | //opcode fixed
1038 (C67_map_regs(c
) << 1) | //side of dest
1039 (0 << 0)); //parallel
1040 } else if (strstr(s
, "ADDDP.L") == s
) {
1041 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1043 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1045 C67_g((0 << 29) | //creg
1047 (C67_map_regn(c
) << 23) | //dst
1048 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1049 (C67_map_regn(a
) << 13) | //src1
1050 (xpath
<< 12) | //x cross path if opposite sides
1051 (0x18 << 5) | //opcode
1052 (0x6 << 2) | //opcode fixed
1053 (C67_map_regs(c
) << 1) | //side of dest
1054 (0 << 0)); //parallel
1055 } else if (strstr(s
, "SUBSP.L") == s
) {
1056 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1058 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1060 C67_g((0 << 29) | //creg
1062 (C67_map_regn(c
) << 23) | //dst
1063 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1064 (C67_map_regn(a
) << 13) | //src1
1065 (xpath
<< 12) | //x cross path if opposite sides
1066 (0x11 << 5) | //opcode
1067 (0x6 << 2) | //opcode fixed
1068 (C67_map_regs(c
) << 1) | //side of dest
1069 (0 << 0)); //parallel
1070 } else if (strstr(s
, "SUBDP.L") == s
) {
1071 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1073 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1075 C67_g((0 << 29) | //creg
1077 (C67_map_regn(c
) << 23) | //dst
1078 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1079 (C67_map_regn(a
) << 13) | //src1
1080 (xpath
<< 12) | //x cross path if opposite sides
1081 (0x19 << 5) | //opcode
1082 (0x6 << 2) | //opcode fixed
1083 (C67_map_regs(c
) << 1) | //side of dest
1084 (0 << 0)); //parallel
1085 } else if (strstr(s
, "MPYSP.M") == s
) {
1086 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1088 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1090 C67_g((0 << 29) | //creg
1092 (C67_map_regn(c
) << 23) | //dst
1093 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1094 (C67_map_regn(a
) << 13) | //src1
1095 (xpath
<< 12) | //x cross path if opposite sides
1096 (0x1c << 7) | //opcode
1097 (0x0 << 2) | //opcode fixed
1098 (C67_map_regs(c
) << 1) | //side of dest
1099 (0 << 0)); //parallel
1100 } else if (strstr(s
, "MPYDP.M") == s
) {
1101 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1103 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1105 C67_g((0 << 29) | //creg
1107 (C67_map_regn(c
) << 23) | //dst
1108 (C67_map_regn(b
) << 18) | //src2 (possible x path)
1109 (C67_map_regn(a
) << 13) | //src1
1110 (xpath
<< 12) | //x cross path if opposite sides
1111 (0x0e << 7) | //opcode
1112 (0x0 << 2) | //opcode fixed
1113 (C67_map_regs(c
) << 1) | //side of dest
1114 (0 << 0)); //parallel
1115 } else if (strstr(s
, "MPYI.M") == s
) {
1116 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1118 ALWAYS_ASSERT(C67_map_regs(a
) == C67_map_regs(c
));
1120 C67_g((0 << 29) | //creg
1122 (C67_map_regn(c
) << 23) | //dst
1123 (C67_map_regn(b
) << 18) | //src2
1124 (C67_map_regn(a
) << 13) | //src1 (cst5)
1125 (xpath
<< 12) | //x cross path if opposite sides
1126 (0x4 << 7) | //opcode
1127 (0x0 << 2) | //opcode fixed
1128 (C67_map_regs(c
) << 1) | //side of dest
1129 (0 << 0)); //parallel
1130 } else if (strstr(s
, "SHR.S") == s
) {
1131 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1133 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
1135 C67_g((0 << 29) | //creg
1137 (C67_map_regn(c
) << 23) | //dst
1138 (C67_map_regn(b
) << 18) | //src2
1139 (C67_map_regn(a
) << 13) | //src1
1140 (xpath
<< 12) | //x cross path if opposite sides
1141 (0x37 << 6) | //opcode
1142 (0x8 << 2) | //opcode fixed
1143 (C67_map_regs(c
) << 1) | //side of dest
1144 (0 << 0)); //parallel
1145 } else if (strstr(s
, "SHRU.S") == s
) {
1146 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1148 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
1150 C67_g((0 << 29) | //creg
1152 (C67_map_regn(c
) << 23) | //dst
1153 (C67_map_regn(b
) << 18) | //src2
1154 (C67_map_regn(a
) << 13) | //src1
1155 (xpath
<< 12) | //x cross path if opposite sides
1156 (0x27 << 6) | //opcode
1157 (0x8 << 2) | //opcode fixed
1158 (C67_map_regs(c
) << 1) | //side of dest
1159 (0 << 0)); //parallel
1160 } else if (strstr(s
, "SHL.S") == s
) {
1161 xpath
= C67_map_regs(b
) ^ C67_map_regs(c
);
1163 ALWAYS_ASSERT(C67_map_regs(c
) == C67_map_regs(a
));
1165 C67_g((0 << 29) | //creg
1167 (C67_map_regn(c
) << 23) | //dst
1168 (C67_map_regn(b
) << 18) | //src2
1169 (C67_map_regn(a
) << 13) | //src1
1170 (xpath
<< 12) | //x cross path if opposite sides
1171 (0x33 << 6) | //opcode
1172 (0x8 << 2) | //opcode fixed
1173 (C67_map_regs(c
) << 1) | //side of dest
1174 (0 << 0)); //parallel
1175 } else if (strstr(s
, "||ADDK") == s
) {
1176 xpath
= 0; // no xpath required just use the side of the src/dst
1178 C67_g((0 << 29) | //creg
1180 (C67_map_regn(b
) << 23) | //dst
1181 (a
<< 07) | //scst16
1182 (0x14 << 2) | //opcode fixed
1183 (C67_map_regs(b
) << 1) | //side of dst
1184 (1 << 0)); //parallel
1185 } else if (strstr(s
, "ADDK") == s
) {
1186 xpath
= 0; // no xpath required just use the side of the src/dst
1188 C67_g((0 << 29) | //creg
1190 (C67_map_regn(b
) << 23) | //dst
1191 (a
<< 07) | //scst16
1192 (0x14 << 2) | //opcode fixed
1193 (C67_map_regs(b
) << 1) | //side of dst
1194 (0 << 0)); //parallel
1195 } else if (strstr(s
, "NOP") == s
) {
1196 C67_g(((a
- 1) << 13) | //no of cycles
1197 (0 << 0)); //parallel
1199 ALWAYS_ASSERT(FALSE
);
1201 #ifdef ASSEMBLY_LISTING_C67
1202 fprintf(f
, " %s %d %d %d\n", s
, a
, b
, c
);
1207 //r=reg to load, fr=from reg, symbol for relocation, constant
1209 void C67_MVKL(int r
, int fc
)
1211 C67_asm("MVKL.", fc
, r
, 0);
1214 void C67_MVKH(int r
, int fc
)
1216 C67_asm("MVKH.", fc
, r
, 0);
1219 void C67_STB_SP_A0(int r
)
1221 C67_asm("STB.D *+SP[A0]", r
, 0, 0); // STB r,*+SP[A0]
1224 void C67_STH_SP_A0(int r
)
1226 C67_asm("STH.D *+SP[A0]", r
, 0, 0); // STH r,*+SP[A0]
1229 void C67_STW_SP_A0(int r
)
1231 C67_asm("STW.D *+SP[A0]", r
, 0, 0); // STW r,*+SP[A0]
1234 void C67_STB_PTR(int r
, int r2
)
1236 C67_asm("STB.D *", r
, r2
, 0); // STB r, *r2
1239 void C67_STH_PTR(int r
, int r2
)
1241 C67_asm("STH.D *", r
, r2
, 0); // STH r, *r2
1244 void C67_STW_PTR(int r
, int r2
)
1246 C67_asm("STW.D *", r
, r2
, 0); // STW r, *r2
1249 void C67_STW_PTR_PRE_INC(int r
, int r2
, int n
)
1251 C67_asm("STW.D +*", r
, r2
, n
); // STW r, *+r2
1254 void C67_PUSH(int r
)
1256 C67_asm("STW.D SP POST DEC", r
, 0, 0); // STW r,*SP--
1259 void C67_LDW_SP_A0(int r
)
1261 C67_asm("LDW.D *+SP[A0]", r
, 0, 0); // LDW *+SP[A0],r
1264 void C67_LDDW_SP_A0(int r
)
1266 C67_asm("LDDW.D *+SP[A0]", r
, 0, 0); // LDDW *+SP[A0],r
1269 void C67_LDH_SP_A0(int r
)
1271 C67_asm("LDH.D *+SP[A0]", r
, 0, 0); // LDH *+SP[A0],r
1274 void C67_LDB_SP_A0(int r
)
1276 C67_asm("LDB.D *+SP[A0]", r
, 0, 0); // LDB *+SP[A0],r
1279 void C67_LDHU_SP_A0(int r
)
1281 C67_asm("LDHU.D *+SP[A0]", r
, 0, 0); // LDHU *+SP[A0],r
1284 void C67_LDBU_SP_A0(int r
)
1286 C67_asm("LDBU.D *+SP[A0]", r
, 0, 0); // LDBU *+SP[A0],r
1289 void C67_LDW_PTR(int r
, int r2
)
1291 C67_asm("LDW.D *", r
, r2
, 0); // LDW *r,r2
1294 void C67_LDDW_PTR(int r
, int r2
)
1296 C67_asm("LDDW.D *", r
, r2
, 0); // LDDW *r,r2
1299 void C67_LDH_PTR(int r
, int r2
)
1301 C67_asm("LDH.D *", r
, r2
, 0); // LDH *r,r2
1304 void C67_LDB_PTR(int r
, int r2
)
1306 C67_asm("LDB.D *", r
, r2
, 0); // LDB *r,r2
1309 void C67_LDHU_PTR(int r
, int r2
)
1311 C67_asm("LDHU.D *", r
, r2
, 0); // LDHU *r,r2
1314 void C67_LDBU_PTR(int r
, int r2
)
1316 C67_asm("LDBU.D *", r
, r2
, 0); // LDBU *r,r2
1319 void C67_LDW_PTR_PRE_INC(int r
, int r2
)
1321 C67_asm("LDW.D +*", r
, r2
, 0); // LDW *+r,r2
1326 C67_asm("LDW.D SP PRE INC", r
, 0, 0); // LDW *++SP,r
1329 void C67_POP_DW(int r
)
1331 C67_asm("LDDW.D SP PRE INC", r
, 0, 0); // LDDW *++SP,r
1334 void C67_CMPLT(int s1
, int s2
, int dst
)
1336 C67_asm("CMPLT.L1", s1
, s2
, dst
);
1339 void C67_CMPGT(int s1
, int s2
, int dst
)
1341 C67_asm("CMPGT.L1", s1
, s2
, dst
);
1344 void C67_CMPEQ(int s1
, int s2
, int dst
)
1346 C67_asm("CMPEQ.L1", s1
, s2
, dst
);
1349 void C67_CMPLTU(int s1
, int s2
, int dst
)
1351 C67_asm("CMPLTU.L1", s1
, s2
, dst
);
1354 void C67_CMPGTU(int s1
, int s2
, int dst
)
1356 C67_asm("CMPGTU.L1", s1
, s2
, dst
);
1360 void C67_CMPLTSP(int s1
, int s2
, int dst
)
1362 C67_asm("CMPLTSP.S1", s1
, s2
, dst
);
1365 void C67_CMPGTSP(int s1
, int s2
, int dst
)
1367 C67_asm("CMPGTSP.S1", s1
, s2
, dst
);
1370 void C67_CMPEQSP(int s1
, int s2
, int dst
)
1372 C67_asm("CMPEQSP.S1", s1
, s2
, dst
);
1375 void C67_CMPLTDP(int s1
, int s2
, int dst
)
1377 C67_asm("CMPLTDP.S1", s1
, s2
, dst
);
1380 void C67_CMPGTDP(int s1
, int s2
, int dst
)
1382 C67_asm("CMPGTDP.S1", s1
, s2
, dst
);
1385 void C67_CMPEQDP(int s1
, int s2
, int dst
)
1387 C67_asm("CMPEQDP.S1", s1
, s2
, dst
);
1391 void C67_IREG_B_REG(int inv
, int r1
, int r2
) // [!R] B r2
1393 C67_asm("B.S2", inv
, r1
, r2
);
1397 // call with how many 32 bit words to skip
1398 // (0 would branch to the branch instruction)
1400 void C67_B_DISP(int disp
) // B +2 Branch with constant displacement
1402 // Branch point is relative to the 8 word fetch packet
1404 // we will assume the text section always starts on an 8 word (32 byte boundary)
1406 // so add in how many words into the fetch packet the branch is
1409 C67_asm("B DISP", disp
+ ((ind
& 31) >> 2), 0, 0);
1414 C67_asm("NOP", n
, 0, 0);
1417 void C67_ADDK(int n
, int r
)
1419 ALWAYS_ASSERT(abs(n
) < 32767);
1421 C67_asm("ADDK", n
, r
, 0);
1424 void C67_ADDK_PARALLEL(int n
, int r
)
1426 ALWAYS_ASSERT(abs(n
) < 32767);
1428 C67_asm("||ADDK", n
, r
, 0);
1431 void C67_Adjust_ADDK(int *inst
, int n
)
1433 ALWAYS_ASSERT(abs(n
) < 32767);
1435 *inst
= (*inst
& (~(0xffff << 7))) | ((n
& 0xffff) << 7);
1438 void C67_MV(int r
, int v
)
1440 C67_asm("MV.L", 0, r
, v
);
1444 void C67_DPTRUNC(int r
, int v
)
1446 C67_asm("DPTRUNC.L", 0, r
, v
);
1449 void C67_SPTRUNC(int r
, int v
)
1451 C67_asm("SPTRUNC.L", 0, r
, v
);
1454 void C67_INTSP(int r
, int v
)
1456 C67_asm("INTSP.L", 0, r
, v
);
1459 void C67_INTDP(int r
, int v
)
1461 C67_asm("INTDP.L", 0, r
, v
);
1464 void C67_INTSPU(int r
, int v
)
1466 C67_asm("INTSPU.L", 0, r
, v
);
1469 void C67_INTDPU(int r
, int v
)
1471 C67_asm("INTDPU.L", 0, r
, v
);
1474 void C67_SPDP(int r
, int v
)
1476 C67_asm("SPDP.L", 0, r
, v
);
1479 void C67_DPSP(int r
, int v
) // note regs must be on the same side
1481 C67_asm("DPSP.L", 0, r
, v
);
1484 void C67_ADD(int r
, int v
)
1486 C67_asm("ADD.L", v
, r
, v
);
1489 void C67_SUB(int r
, int v
)
1491 C67_asm("SUB.L", v
, r
, v
);
1494 void C67_AND(int r
, int v
)
1496 C67_asm("AND.L", v
, r
, v
);
1499 void C67_OR(int r
, int v
)
1501 C67_asm("OR.L", v
, r
, v
);
1504 void C67_XOR(int r
, int v
)
1506 C67_asm("XOR.L", v
, r
, v
);
1509 void C67_ADDSP(int r
, int v
)
1511 C67_asm("ADDSP.L", v
, r
, v
);
1514 void C67_SUBSP(int r
, int v
)
1516 C67_asm("SUBSP.L", v
, r
, v
);
1519 void C67_MPYSP(int r
, int v
)
1521 C67_asm("MPYSP.M", v
, r
, v
);
1524 void C67_ADDDP(int r
, int v
)
1526 C67_asm("ADDDP.L", v
, r
, v
);
1529 void C67_SUBDP(int r
, int v
)
1531 C67_asm("SUBDP.L", v
, r
, v
);
1534 void C67_MPYDP(int r
, int v
)
1536 C67_asm("MPYDP.M", v
, r
, v
);
1539 void C67_MPYI(int r
, int v
)
1541 C67_asm("MPYI.M", v
, r
, v
);
1544 void C67_SHL(int r
, int v
)
1546 C67_asm("SHL.S", r
, v
, v
);
1549 void C67_SHRU(int r
, int v
)
1551 C67_asm("SHRU.S", r
, v
, v
);
1554 void C67_SHR(int r
, int v
)
1556 C67_asm("SHR.S", r
, v
, v
);
1561 /* load 'r' from value 'sv' */
1562 void load(int r
, SValue
* sv
)
1564 int v
, t
, ft
, fc
, fr
, size
= 0, element
;
1565 BOOL Unsigned
= FALSE
;
1572 v
= fr
& VT_VALMASK
;
1574 if (v
== VT_LLOCAL
) {
1576 v1
.r
= VT_LOCAL
| VT_LVAL
;
1580 } else if ((ft
& VT_BTYPE
) == VT_LDOUBLE
) {
1581 tcc_error("long double not supported");
1582 } else if ((ft
& VT_TYPE
) == VT_BYTE
) {
1584 } else if ((ft
& VT_TYPE
) == (VT_BYTE
| VT_UNSIGNED
)) {
1587 } else if ((ft
& VT_TYPE
) == VT_SHORT
) {
1589 } else if ((ft
& VT_TYPE
) == (VT_SHORT
| VT_UNSIGNED
)) {
1592 } else if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
1598 // check if fc is a positive reference on the stack,
1599 // if it is tcc is referencing what it thinks is a parameter
1600 // on the stack, so check if it is really in a register.
1603 if (v
== VT_LOCAL
&& fc
> 0) {
1606 for (t
= 0; t
< NoCallArgsPassedOnStack
; t
++) {
1607 if (fc
== stack_pos
)
1610 stack_pos
+= TranslateStackToReg
[t
];
1613 // param has been pushed on stack, get it like a local var
1615 fc
= ParamLocOnStack
[t
] - 8;
1618 if ((fr
& VT_VALMASK
) < VT_CONST
) // check for pure indirect
1622 C67_LDBU_PTR(v
, r
); // LDBU *v,r
1624 C67_LDB_PTR(v
, r
); // LDB *v,r
1625 } else if (size
== 2) {
1627 C67_LDHU_PTR(v
, r
); // LDHU *v,r
1629 C67_LDH_PTR(v
, r
); // LDH *v,r
1630 } else if (size
== 4) {
1631 C67_LDW_PTR(v
, r
); // LDW *v,r
1632 } else if (size
== 8) {
1633 C67_LDDW_PTR(v
, r
); // LDDW *v,r
1636 C67_NOP(4); // NOP 4
1638 } else if (fr
& VT_SYM
) {
1639 greloc(cur_text_section
, sv
->sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1640 greloc(cur_text_section
, sv
->sym
, ind
+ 4, R_C60HI16
);
1643 C67_MVKL(C67_A0
, fc
); //r=reg to load, constant
1644 C67_MVKH(C67_A0
, fc
); //r=reg to load, constant
1649 C67_LDBU_PTR(C67_A0
, r
); // LDBU *A0,r
1651 C67_LDB_PTR(C67_A0
, r
); // LDB *A0,r
1652 } else if (size
== 2) {
1654 C67_LDHU_PTR(C67_A0
, r
); // LDHU *A0,r
1656 C67_LDH_PTR(C67_A0
, r
); // LDH *A0,r
1657 } else if (size
== 4) {
1658 C67_LDW_PTR(C67_A0
, r
); // LDW *A0,r
1659 } else if (size
== 8) {
1660 C67_LDDW_PTR(C67_A0
, r
); // LDDW *A0,r
1663 C67_NOP(4); // NOP 4
1668 // divide offset in bytes to create element index
1669 C67_MVKL(C67_A0
, (fc
/ element
) + 8 / element
); //r=reg to load, constant
1670 C67_MVKH(C67_A0
, (fc
/ element
) + 8 / element
); //r=reg to load, constant
1674 C67_LDBU_SP_A0(r
); // LDBU r, SP[A0]
1676 C67_LDB_SP_A0(r
); // LDB r, SP[A0]
1677 } else if (size
== 2) {
1679 C67_LDHU_SP_A0(r
); // LDHU r, SP[A0]
1681 C67_LDH_SP_A0(r
); // LDH r, SP[A0]
1682 } else if (size
== 4) {
1683 C67_LDW_SP_A0(r
); // LDW r, SP[A0]
1684 } else if (size
== 8) {
1685 C67_LDDW_SP_A0(r
); // LDDW r, SP[A0]
1689 C67_NOP(4); // NOP 4
1693 if (v
== VT_CONST
) {
1695 greloc(cur_text_section
, sv
->sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1696 greloc(cur_text_section
, sv
->sym
, ind
+ 4, R_C60HI16
);
1698 C67_MVKL(r
, fc
); //r=reg to load, constant
1699 C67_MVKH(r
, fc
); //r=reg to load, constant
1700 } else if (v
== VT_LOCAL
) {
1701 C67_MVKL(r
, fc
+ 8); //r=reg to load, constant C67 stack points to next free
1702 C67_MVKH(r
, fc
+ 8); //r=reg to load, constant
1703 C67_ADD(C67_FP
, r
); // MV v,r v -> r
1704 } else if (v
== VT_CMP
) {
1705 C67_MV(C67_compare_reg
, r
); // MV v,r v -> r
1706 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1708 C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
1709 C67_MVKL(r
, t
); // r=reg to load, 0 or 1 (do this while branching)
1710 C67_NOP(4); // NOP 4
1711 gsym(fc
); // modifies other branches to branch here
1712 C67_MVKL(r
, t
^ 1); // r=reg to load, 0 or 1
1713 } else if (v
!= r
) {
1714 C67_MV(v
, r
); // MV v,r v -> r
1716 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
1717 C67_MV(v
+ 1, r
+ 1); // MV v,r v -> r
1723 /* store register 'r' in lvalue 'v' */
1724 void store(int r
, SValue
* v
)
1726 int fr
, bt
, ft
, fc
, size
, t
, element
;
1730 fr
= v
->r
& VT_VALMASK
;
1732 /* XXX: incorrect if float reg to reg */
1734 if (bt
== VT_LDOUBLE
) {
1735 tcc_error("long double not supported");
1739 else if (bt
== VT_BYTE
)
1741 else if (bt
== VT_DOUBLE
)
1746 if ((v
->r
& VT_VALMASK
) == VT_CONST
) {
1747 /* constant memory reference */
1749 if (v
->r
& VT_SYM
) {
1750 greloc(cur_text_section
, v
->sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1751 greloc(cur_text_section
, v
->sym
, ind
+ 4, R_C60HI16
);
1753 C67_MVKL(C67_A0
, fc
); //r=reg to load, constant
1754 C67_MVKH(C67_A0
, fc
); //r=reg to load, constant
1757 C67_STB_PTR(r
, C67_A0
); // STB r, *A0
1759 C67_STH_PTR(r
, C67_A0
); // STH r, *A0
1760 else if (size
== 4 || size
== 8)
1761 C67_STW_PTR(r
, C67_A0
); // STW r, *A0
1764 C67_STW_PTR_PRE_INC(r
+ 1, C67_A0
, 1); // STW r, *+A0[1]
1765 } else if ((v
->r
& VT_VALMASK
) == VT_LOCAL
) {
1766 // check case of storing to passed argument that
1767 // tcc thinks is on the stack but for C67 is
1768 // passed as a reg. However it may have been
1769 // saved to the stack, if that reg was required
1770 // for a call to a child function
1772 if (fc
> 0) // argument ??
1774 // walk through sizes and figure which param
1778 for (t
= 0; t
< NoCallArgsPassedOnStack
; t
++) {
1779 if (fc
== stack_pos
)
1782 stack_pos
+= TranslateStackToReg
[t
];
1785 // param has been pushed on stack, get it like a local var
1786 fc
= ParamLocOnStack
[t
] - 8;
1794 // divide offset in bytes to create word index
1795 C67_MVKL(C67_A0
, (fc
/ element
) + 8 / element
); //r=reg to load, constant
1796 C67_MVKH(C67_A0
, (fc
/ element
) + 8 / element
); //r=reg to load, constant
1801 C67_STB_SP_A0(r
); // STB r, SP[A0]
1803 C67_STH_SP_A0(r
); // STH r, SP[A0]
1804 else if (size
== 4 || size
== 8)
1805 C67_STW_SP_A0(r
); // STW r, SP[A0]
1808 C67_ADDK(1, C67_A0
); // ADDK 1,A0
1809 C67_STW_SP_A0(r
+ 1); // STW r, SP[A0]
1813 C67_STB_PTR(r
, fr
); // STB r, *fr
1815 C67_STH_PTR(r
, fr
); // STH r, *fr
1816 else if (size
== 4 || size
== 8)
1817 C67_STW_PTR(r
, fr
); // STW r, *fr
1820 C67_STW_PTR_PRE_INC(r
+ 1, fr
, 1); // STW r, *+fr[1]
1826 /* 'is_jmp' is '1' if it is a jump */
1827 static void gcall_or_jmp(int is_jmp
)
1832 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1834 if (vtop
->r
& VT_SYM
) {
1835 /* relocation case */
1837 // get add into A0, then start the jump B3
1839 greloc(cur_text_section
, vtop
->sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1840 greloc(cur_text_section
, vtop
->sym
, ind
+ 4, R_C60HI16
);
1842 C67_MVKL(C67_A0
, 0); //r=reg to load, constant
1843 C67_MVKH(C67_A0
, 0); //r=reg to load, constant
1844 C67_IREG_B_REG(0, C67_CREG_ZERO
, C67_A0
); // B.S2x A0
1847 C67_NOP(5); // simple jump, just put NOP
1849 // Call, must load return address into B3 during delay slots
1851 sym
= get_sym_ref(&char_pointer_type
, cur_text_section
, ind
+ 12, 0); // symbol for return address
1852 greloc(cur_text_section
, sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1853 greloc(cur_text_section
, sym
, ind
+ 4, R_C60HI16
);
1854 C67_MVKL(C67_B3
, 0); //r=reg to load, constant
1855 C67_MVKH(C67_B3
, 0); //r=reg to load, constant
1856 C67_NOP(3); // put remaining NOPs
1859 /* put an empty PC32 relocation */
1860 ALWAYS_ASSERT(FALSE
);
1863 /* otherwise, indirect call */
1865 C67_IREG_B_REG(0, C67_CREG_ZERO
, r
); // B.S2x r
1868 C67_NOP(5); // simple jump, just put NOP
1870 // Call, must load return address into B3 during delay slots
1872 sym
= get_sym_ref(&char_pointer_type
, cur_text_section
, ind
+ 12, 0); // symbol for return address
1873 greloc(cur_text_section
, sym
, ind
, R_C60LO16
); // rem the inst need to be patched
1874 greloc(cur_text_section
, sym
, ind
+ 4, R_C60HI16
);
1875 C67_MVKL(C67_B3
, 0); //r=reg to load, constant
1876 C67_MVKH(C67_B3
, 0); //r=reg to load, constant
1877 C67_NOP(3); // put remaining NOPs
1882 /* Return the number of registers needed to return the struct, or 0 if
1883 returning via struct pointer. */
1884 ST_FUNC
int gfunc_sret(CType
*vt
, int variadic
, CType
*ret
, int *ret_align
) {
1885 *ret_align
= 1; // Never have to re-align return values for x86-64
1889 /* generate function call with address in (vtop->t, vtop->c) and free function
1890 context. Stack entry is popped */
1891 void gfunc_call(int nb_args
)
1894 int args_sizes
[NoCallArgsPassedOnStack
];
1896 if (nb_args
> NoCallArgsPassedOnStack
) {
1897 tcc_error("more than 10 function params not currently supported");
1898 // handle more than 10, put some on the stack
1901 for (i
= 0; i
< nb_args
; i
++) {
1902 if ((vtop
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
1903 ALWAYS_ASSERT(FALSE
);
1905 /* simple type (currently always same size) */
1906 /* XXX: implicit cast ? */
1909 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
1910 tcc_error("long long not supported");
1911 } else if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
1912 tcc_error("long double not supported");
1913 } else if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
) {
1919 // put the parameter into the corresponding reg (pair)
1921 r
= gv(RC_C67_A4
<< (2 * i
));
1923 // must put on stack because with 1 pass compiler , no way to tell
1924 // if an up coming nested call might overwrite these regs
1929 C67_STW_PTR_PRE_INC(r
+ 1, C67_SP
, 3); // STW r, *+SP[3] (go back and put the other)
1931 args_sizes
[i
] = size
;
1935 // POP all the params on the stack into registers for the
1936 // immediate call (in reverse order)
1938 for (i
= nb_args
- 1; i
>= 0; i
--) {
1940 if (args_sizes
[i
] == 8)
1941 C67_POP_DW(TREG_C67_A4
+ i
* 2);
1943 C67_POP(TREG_C67_A4
+ i
* 2);
1950 // to be compatible with Code Composer for the C67
1951 // the first 10 parameters must be passed in registers
1952 // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1953 // ending with B12:B13.
1955 // When a call is made, if the caller has its parameters
1956 // in regs A4-B13 these must be saved before/as the call
1957 // parameters are loaded and restored upon return (or if/when needed).
1959 /* generate function prolog of type 't' */
1960 void gfunc_prolog(CType
* func_type
)
1962 int addr
, align
, size
, func_call
, i
;
1966 sym
= func_type
->ref
;
1969 /* if the function returns a structure, then add an
1970 implicit pointer parameter */
1971 func_vt
= sym
->type
;
1972 func_var
= (sym
->c
== FUNC_ELLIPSIS
);
1973 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
1978 NoOfCurFuncArgs
= 0;
1980 /* define parameters */
1981 while ((sym
= sym
->next
) != NULL
) {
1983 sym_push(sym
->v
& ~SYM_FIELD
, type
, VT_LOCAL
| lvalue_type(type
->t
), addr
);
1984 size
= type_size(type
, &align
);
1985 size
= (size
+ 3) & ~3;
1987 // keep track of size of arguments so
1988 // we can translate where tcc thinks they
1989 // are on the stack into the appropriate reg
1991 TranslateStackToReg
[NoOfCurFuncArgs
] = size
;
1994 #ifdef FUNC_STRUCT_PARAM_AS_PTR
1995 /* structs are passed as pointer */
1996 if ((type
->t
& VT_BTYPE
) == VT_STRUCT
) {
2003 /* pascal type call ? */
2004 if (func_call
== FUNC_STDCALL
)
2005 func_ret_sub
= addr
- 8;
2007 C67_MV(C67_FP
, C67_A0
); // move FP -> A0
2008 C67_MV(C67_SP
, C67_FP
); // move SP -> FP
2010 // place all the args passed in regs onto the stack
2013 for (i
= 0; i
< NoOfCurFuncArgs
; i
++) {
2015 ParamLocOnStack
[i
] = loc
; // remember where the param is
2018 C67_PUSH(TREG_C67_A4
+ i
* 2);
2020 if (TranslateStackToReg
[i
] == 8) {
2021 C67_STW_PTR_PRE_INC(TREG_C67_A4
+ i
* 2 + 1, C67_SP
, 3); // STW r, *+SP[1] (go back and put the other)
2025 TotalBytesPushedOnStack
= -loc
;
2027 func_sub_sp_offset
= ind
; // remember where we put the stack instruction
2028 C67_ADDK(0, C67_SP
); // ADDK.L2 loc,SP (just put zero temporarily)
2034 /* generate function epilog */
2035 void gfunc_epilog(void)
2038 int local
= (-loc
+ 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2040 C67_NOP(4); // NOP wait for load
2041 C67_IREG_B_REG(0, C67_CREG_ZERO
, C67_B3
); // B.S2 B3
2043 C67_ADDK(local
, C67_SP
); // ADDK.L2 loc,SP
2044 C67_Adjust_ADDK((int *) (cur_text_section
->data
+
2045 func_sub_sp_offset
),
2046 -local
+ TotalBytesPushedOnStack
);
2051 /* generate a jump to a label */
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
2063 /* generate a jump to a fixed address */
2064 void gjmp_addr(int a
)
2067 // I guess this routine is used for relative short
2068 // local jumps, for now just handle it as the general
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 int gtst(int inv
, int t
)
2086 v
= vtop
->r
& VT_VALMASK
;
2088 /* fast case : can jump directly since flags are set */
2089 // C67 uses B2 sort of as flags register
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
2103 t
= ind1
; //return where we need to patch
2105 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
2106 /* && or || optimization */
2107 if ((v
& 1) == inv
) {
2108 /* insert vtop->c jump list in t */
2111 // I guess the idea is to traverse to the
2112 // null at the end of the list and store t
2117 p
= (int *) (cur_text_section
->data
+ n
);
2119 // extract 32 bit address from MVKH/MVKL
2120 n
= ((*p
>> 7) & 0xffff);
2121 n
|= ((*(p
+ 1) >> 7) & 0xffff) << 16;
2123 *p
|= (t
& 0xffff) << 7;
2124 *(p
+ 1) |= ((t
>> 16) & 0xffff) << 7;
2136 /* generate an integer binary operation */
2137 void gen_opi(int op
)
2143 case TOK_ADDC1
: /* add with carry generation */
2148 // C67 can't do const compares, must load into a reg
2149 // so just go to gv2 directly - tktk
2153 if (op
>= TOK_ULT
&& op
<= TOK_GT
)
2154 gv2(RC_INT_BSIDE
, RC_INT
); // make sure r (src1) is on the B Side of CPU
2156 gv2(RC_INT
, RC_INT
);
2161 C67_compare_reg
= C67_B2
;
2165 C67_CMPLT(r
, fr
, C67_B2
);
2166 C67_invert_test
= FALSE
;
2167 } else if (op
== TOK_GE
) {
2168 C67_CMPLT(r
, fr
, C67_B2
);
2169 C67_invert_test
= TRUE
;
2170 } else if (op
== TOK_GT
) {
2171 C67_CMPGT(r
, fr
, C67_B2
);
2172 C67_invert_test
= FALSE
;
2173 } else if (op
== TOK_LE
) {
2174 C67_CMPGT(r
, fr
, C67_B2
);
2175 C67_invert_test
= TRUE
;
2176 } else if (op
== TOK_EQ
) {
2177 C67_CMPEQ(r
, fr
, C67_B2
);
2178 C67_invert_test
= FALSE
;
2179 } else if (op
== TOK_NE
) {
2180 C67_CMPEQ(r
, fr
, C67_B2
);
2181 C67_invert_test
= TRUE
;
2182 } else if (op
== TOK_ULT
) {
2183 C67_CMPLTU(r
, fr
, C67_B2
);
2184 C67_invert_test
= FALSE
;
2185 } else if (op
== TOK_UGE
) {
2186 C67_CMPLTU(r
, fr
, C67_B2
);
2187 C67_invert_test
= TRUE
;
2188 } else if (op
== TOK_UGT
) {
2189 C67_CMPGTU(r
, fr
, C67_B2
);
2190 C67_invert_test
= FALSE
;
2191 } else if (op
== TOK_ULE
) {
2192 C67_CMPGTU(r
, fr
, C67_B2
);
2193 C67_invert_test
= TRUE
;
2194 } else if (op
== '+')
2195 C67_ADD(fr
, r
); // ADD r,fr,r
2197 C67_SUB(fr
, r
); // SUB r,fr,r
2199 C67_AND(fr
, r
); // AND r,fr,r
2201 C67_OR(fr
, r
); // OR r,fr,r
2203 C67_XOR(fr
, r
); // XOR r,fr,r
2205 ALWAYS_ASSERT(FALSE
);
2208 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2214 case TOK_SUBC1
: /* sub with carry generation */
2217 case TOK_ADDC2
: /* add with carry use */
2220 case TOK_SUBC2
: /* sub with carry use */
2234 gv2(RC_INT
, RC_INT
);
2238 C67_MPYI(fr
, r
); // 32 bit bultiply fr,r,fr
2239 C67_NOP(8); // NOP 8 for worst case
2242 gv2(RC_INT_BSIDE
, RC_INT_BSIDE
); // shift amount must be on same side as dst
2246 C67_SHL(fr
, r
); // arithmetic/logical shift
2250 gv2(RC_INT_BSIDE
, RC_INT_BSIDE
); // shift amount must be on same side as dst
2254 C67_SHRU(fr
, r
); // logical shift
2258 gv2(RC_INT_BSIDE
, RC_INT_BSIDE
); // shift amount must be on same side as dst
2262 C67_SHR(fr
, r
); // arithmetic shift
2269 /* call generic idiv function */
2270 vpush_global_sym(&func_old_type
, t
);
2275 vtop
->r2
= VT_CONST
;
2294 /* generate a floating point operation 'v = t1 op t2' instruction. The
2295 two operands are guaranted to have the same floating point type */
2296 /* XXX: need to use ST1 too */
2297 void gen_opf(int op
)
2301 if (op
>= TOK_ULT
&& op
<= TOK_GT
)
2302 gv2(RC_EDX
, RC_EAX
); // make sure src2 is on b side
2304 gv2(RC_FLOAT
, RC_FLOAT
); // make sure src2 is on b side
2312 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
)
2313 tcc_error("long doubles not supported");
2315 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
2320 C67_compare_reg
= C67_B2
;
2323 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2324 C67_CMPLTDP(r
, fr
, C67_B2
);
2326 C67_CMPLTSP(r
, fr
, C67_B2
);
2328 C67_invert_test
= FALSE
;
2329 } else if (op
== TOK_GE
) {
2330 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2331 C67_CMPLTDP(r
, fr
, C67_B2
);
2333 C67_CMPLTSP(r
, fr
, C67_B2
);
2335 C67_invert_test
= TRUE
;
2336 } else if (op
== TOK_GT
) {
2337 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2338 C67_CMPGTDP(r
, fr
, C67_B2
);
2340 C67_CMPGTSP(r
, fr
, C67_B2
);
2342 C67_invert_test
= FALSE
;
2343 } else if (op
== TOK_LE
) {
2344 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2345 C67_CMPGTDP(r
, fr
, C67_B2
);
2347 C67_CMPGTSP(r
, fr
, C67_B2
);
2349 C67_invert_test
= TRUE
;
2350 } else if (op
== TOK_EQ
) {
2351 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2352 C67_CMPEQDP(r
, fr
, C67_B2
);
2354 C67_CMPEQSP(r
, fr
, C67_B2
);
2356 C67_invert_test
= FALSE
;
2357 } else if (op
== TOK_NE
) {
2358 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
2359 C67_CMPEQDP(r
, fr
, C67_B2
);
2361 C67_CMPEQSP(r
, fr
, C67_B2
);
2363 C67_invert_test
= TRUE
;
2365 ALWAYS_ASSERT(FALSE
);
2367 vtop
->r
= VT_CMP
; // tell TCC that result is in "flags" actually B2
2370 if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
2371 C67_ADDDP(r
, fr
); // ADD fr,r,fr
2374 C67_ADDSP(r
, fr
); // ADD fr,r,fr
2378 } else if (op
== '-') {
2379 if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
2380 C67_SUBDP(r
, fr
); // SUB fr,r,fr
2383 C67_SUBSP(r
, fr
); // SUB fr,r,fr
2387 } else if (op
== '*') {
2388 if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
2389 C67_MPYDP(r
, fr
); // MPY fr,r,fr
2392 C67_MPYSP(r
, fr
); // MPY fr,r,fr
2396 } else if (op
== '/') {
2397 if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
2398 // must call intrinsic DP floating point divide
2400 /* call generic idiv function */
2401 vpush_global_sym(&func_old_type
, TOK__divd
);
2406 vtop
->r2
= REG_LRET
;
2409 // must call intrinsic SP floating point divide
2411 /* call generic idiv function */
2412 vpush_global_sym(&func_old_type
, TOK__divf
);
2417 vtop
->r2
= VT_CONST
;
2420 ALWAYS_ASSERT(FALSE
);
2427 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2428 and 'long long' cases. */
2429 void gen_cvt_itof(int t
)
2436 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
2437 if (t
& VT_UNSIGNED
)
2443 vtop
->type
.t
= VT_DOUBLE
;
2445 if (t
& VT_UNSIGNED
)
2450 vtop
->type
.t
= VT_FLOAT
;
2455 /* convert fp to int 't' type */
2456 /* XXX: handle long long case */
2457 void gen_cvt_ftoi(int t
)
2465 tcc_error("long long not supported");
2467 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
) {
2475 vtop
->type
.t
= VT_INT
;
2480 /* convert from one floating point type to another */
2481 void gen_cvt_ftof(int t
)
2485 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
&&
2486 (t
& VT_BTYPE
) == VT_FLOAT
) {
2487 // convert double to float
2489 gv(RC_FLOAT
); // get it in a register pair
2493 C67_DPSP(r
, r
); // convert it to SP same register
2496 vtop
->type
.t
= VT_FLOAT
;
2497 vtop
->r2
= VT_CONST
; // set this as unused
2498 } else if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
&&
2499 (t
& VT_BTYPE
) == VT_DOUBLE
) {
2500 // convert float to double
2502 gv(RC_FLOAT
); // get it in a register
2506 if (r
== TREG_EAX
) { // make sure the paired reg is avail
2507 r2
= get_reg(RC_ECX
);
2508 } else if (r
== TREG_EDX
) {
2509 r2
= get_reg(RC_ST0
);
2511 ALWAYS_ASSERT(FALSE
);
2512 r2
= 0; /* avoid warning */
2515 C67_SPDP(r
, r
); // convert it to DP same register
2518 vtop
->type
.t
= VT_DOUBLE
;
2519 vtop
->r2
= r2
; // set this as unused
2521 ALWAYS_ASSERT(FALSE
);
2525 /* computed goto support */
2532 /* Save the stack pointer onto the stack and return the location of its address */
2533 ST_FUNC
void gen_vla_sp_save(int addr
) {
2534 tcc_error("variable length arrays unsupported for this target");
2537 /* Restore the SP from a location on the stack */
2538 ST_FUNC
void gen_vla_sp_restore(int addr
) {
2539 tcc_error("variable length arrays unsupported for this target");
2542 /* Subtract from the stack pointer, and push the resulting value onto the stack */
2543 ST_FUNC
void gen_vla_alloc(CType
*type
, int align
) {
2544 tcc_error("variable length arrays unsupported for this target");
2547 /* end of C67 code generator */
2548 /*************************************************************/
2550 /*************************************************************/