fix-mixed-struct (patch by Pip Cet)
[tinycc.git] / c67-gen.c
Commit [+]AuthorDateLineData
bf45336a bellard2004-10-05 17:55:18 +00001/*
2 * TMS320C67xx code generator for TCC
3 *
4 * Copyright (c) 2001, 2002 Fabrice Bellard
5 *
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.
10 *
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.
15 *
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
19 */
20
88a3ccab grischka2009-12-20 01:53:49 +010021#ifdef TARGET_DEFS_ONLY
22
0bdbd49e Urs Janssen2013-02-17 00:48:51 +010023/* #define ASSEMBLY_LISTING_C67 */
bf45336a bellard2004-10-05 17:55:18 +000024
25/* number of available registers */
26#define NB_REGS 24
27
4e04f67c seyko2015-05-14 07:32:24 +030028typedef int RegArgs;
29
bf45336a bellard2004-10-05 17:55:18 +000030/* a register can belong to several classes. The classes must be
31 sorted from more general to more precise (see gv2() code which does
32 assumptions on it). */
33#define RC_INT 0x0001 /* generic integer register */
34#define RC_FLOAT 0x0002 /* generic float register */
35#define RC_EAX 0x0004
36#define RC_ST0 0x0008
37#define RC_ECX 0x0010
38#define RC_EDX 0x0020
39#define RC_INT_BSIDE 0x00000040 /* generic integer register on b side */
40#define RC_C67_A4 0x00000100
41#define RC_C67_A5 0x00000200
42#define RC_C67_B4 0x00000400
43#define RC_C67_B5 0x00000800
44#define RC_C67_A6 0x00001000
45#define RC_C67_A7 0x00002000
46#define RC_C67_B6 0x00004000
47#define RC_C67_B7 0x00008000
48#define RC_C67_A8 0x00010000
49#define RC_C67_A9 0x00020000
50#define RC_C67_B8 0x00040000
51#define RC_C67_B9 0x00080000
52#define RC_C67_A10 0x00100000
53#define RC_C67_A11 0x00200000
54#define RC_C67_B10 0x00400000
55#define RC_C67_B11 0x00800000
56#define RC_C67_A12 0x01000000
57#define RC_C67_A13 0x02000000
58#define RC_C67_B12 0x04000000
59#define RC_C67_B13 0x08000000
60#define RC_IRET RC_C67_A4 /* function return: integer register */
61#define RC_LRET RC_C67_A5 /* function return: second integer register */
62#define RC_FRET RC_C67_A4 /* function return: float register */
63
64/* pretty names for the registers */
65enum {
66 TREG_EAX = 0, // really A2
67 TREG_ECX, // really A3
68 TREG_EDX, // really B0
69 TREG_ST0, // really B1
70 TREG_C67_A4,
71 TREG_C67_A5,
72 TREG_C67_B4,
73 TREG_C67_B5,
74 TREG_C67_A6,
75 TREG_C67_A7,
76 TREG_C67_B6,
77 TREG_C67_B7,
78 TREG_C67_A8,
79 TREG_C67_A9,
80 TREG_C67_B8,
81 TREG_C67_B9,
82 TREG_C67_A10,
83 TREG_C67_A11,
84 TREG_C67_B10,
85 TREG_C67_B11,
86 TREG_C67_A12,
87 TREG_C67_A13,
88 TREG_C67_B12,
89 TREG_C67_B13,
90};
91
bf45336a bellard2004-10-05 17:55:18 +000092/* return registers for function */
93#define REG_IRET TREG_C67_A4 /* single word int return register */
94#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */
95#define REG_FRET TREG_C67_A4 /* float return register */
96
bf45336a bellard2004-10-05 17:55:18 +000097/* defined if function parameters must be evaluated in reverse order */
0bdbd49e Urs Janssen2013-02-17 00:48:51 +010098/* #define INVERT_FUNC_PARAMS */
bf45336a bellard2004-10-05 17:55:18 +000099
100/* defined if structures are passed as pointers. Otherwise structures
101 are directly pushed on stack. */
0bdbd49e Urs Janssen2013-02-17 00:48:51 +0100102/* #define FUNC_STRUCT_PARAM_AS_PTR */
bf45336a bellard2004-10-05 17:55:18 +0000103
104/* pointer size, in bytes */
105#define PTR_SIZE 4
106
107/* long double size and alignment, in bytes */
108#define LDOUBLE_SIZE 12
109#define LDOUBLE_ALIGN 4
110/* maximum alignment (for aligned attribute support) */
111#define MAX_ALIGN 8
112
113/******************************************************/
114/* ELF defines */
115
116#define EM_TCC_TARGET EM_C60
117
118/* relocation type for 32 bit data relocation */
119#define R_DATA_32 R_C60_32
5dadff3d Shinichiro Hamaji2009-07-19 06:42:23 +0900120#define R_DATA_PTR R_C60_32
bf45336a bellard2004-10-05 17:55:18 +0000121#define R_JMP_SLOT R_C60_JMP_SLOT
122#define R_COPY R_C60_COPY
123
124#define ELF_START_ADDR 0x00000400
125#define ELF_PAGE_SIZE 0x1000
126
127/******************************************************/
88a3ccab grischka2009-12-20 01:53:49 +0100128#else /* ! TARGET_DEFS_ONLY */
129/******************************************************/
130#include "tcc.h"
131
132ST_DATA const int reg_classes[NB_REGS] = {
133 /* eax */ RC_INT | RC_FLOAT | RC_EAX,
134 // only allow even regs for floats (allow for doubles)
135 /* ecx */ RC_INT | RC_ECX,
136 /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
137 // only allow even regs for floats (allow for doubles)
138 /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
139 /* A4 */ RC_C67_A4,
140 /* A5 */ RC_C67_A5,
141 /* B4 */ RC_C67_B4,
142 /* B5 */ RC_C67_B5,
143 /* A6 */ RC_C67_A6,
144 /* A7 */ RC_C67_A7,
145 /* B6 */ RC_C67_B6,
146 /* B7 */ RC_C67_B7,
147 /* A8 */ RC_C67_A8,
148 /* A9 */ RC_C67_A9,
149 /* B8 */ RC_C67_B8,
150 /* B9 */ RC_C67_B9,
151 /* A10 */ RC_C67_A10,
152 /* A11 */ RC_C67_A11,
153 /* B10 */ RC_C67_B10,
154 /* B11 */ RC_C67_B11,
155 /* A12 */ RC_C67_A10,
156 /* A13 */ RC_C67_A11,
157 /* B12 */ RC_C67_B10,
158 /* B13 */ RC_C67_B11
159};
160
161// although tcc thinks it is passing parameters on the stack,
162// the C67 really passes up to the first 10 params in special
163// regs or regs pairs (for 64 bit params). So keep track of
164// the stack offsets so we can translate to the appropriate
165// reg (pair)
166
167#define NoCallArgsPassedOnStack 10
168int NoOfCurFuncArgs;
169int TranslateStackToReg[NoCallArgsPassedOnStack];
170int ParamLocOnStack[NoCallArgsPassedOnStack];
171int TotalBytesPushedOnStack;
bf45336a bellard2004-10-05 17:55:18 +0000172
263dc93c grischka2013-02-04 15:10:08 +0100173#ifndef FALSE
174# define FALSE 0
175# define TRUE 1
176#endif
177
178#undef BOOL
179#define BOOL int
180
d6d7686b grischka2013-02-08 19:07:11 +0100181#define ALWAYS_ASSERT(x) \
182do {\
183 if (!(x))\
184 tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
185} while (0)
186
88a3ccab grischka2009-12-20 01:53:49 +0100187/******************************************************/
bf45336a bellard2004-10-05 17:55:18 +0000188static unsigned long func_sub_sp_offset;
189static int func_ret_sub;
190
bf45336a bellard2004-10-05 17:55:18 +0000191static BOOL C67_invert_test;
192static int C67_compare_reg;
193
194#ifdef ASSEMBLY_LISTING_C67
195FILE *f = NULL;
196#endif
197
bf45336a bellard2004-10-05 17:55:18 +0000198void C67_g(int c)
199{
200 int ind1;
201
202#ifdef ASSEMBLY_LISTING_C67
203 fprintf(f, " %08X", c);
204#endif
205 ind1 = ind + 4;
206 if (ind1 > (int) cur_text_section->data_allocated)
207 section_realloc(cur_text_section, ind1);
208 cur_text_section->data[ind] = c & 0xff;
209 cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
210 cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
211 cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
212 ind = ind1;
213}
214
215
216/* output a symbol and patch all calls to it */
217void gsym_addr(int t, int a)
218{
219 int n, *ptr;
220 while (t) {
221 ptr = (int *) (cur_text_section->data + t);
222 {
223 Sym *sym;
224
225 // extract 32 bit address from MVKH/MVKL
226 n = ((*ptr >> 7) & 0xffff);
227 n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
228
229 // define a label that will be relocated
230
231 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
232 greloc(cur_text_section, sym, t, R_C60LO16);
233 greloc(cur_text_section, sym, t + 4, R_C60HI16);
234
235 // clear out where the pointer was
236
237 *ptr &= ~(0xffff << 7);
238 *(ptr + 1) &= ~(0xffff << 7);
239 }
240 t = n;
241 }
242}
243
244void gsym(int t)
245{
246 gsym_addr(t, ind);
247}
248
249// these are regs that tcc doesn't really know about,
3e9a7e9d
VL
Vincent Lefevre2014-04-07 13:31:00 +0200250// but assign them unique values so the mapping routines
251// can distinguish them
bf45336a bellard2004-10-05 17:55:18 +0000252
253#define C67_A0 105
254#define C67_SP 106
255#define C67_B3 107
256#define C67_FP 108
257#define C67_B2 109
0bdbd49e Urs Janssen2013-02-17 00:48:51 +0100258#define C67_CREG_ZERO -1 /* Special code for no condition reg test */
bf45336a bellard2004-10-05 17:55:18 +0000259
260
261int ConvertRegToRegClass(int r)
262{
263 // only works for A4-B13
264
265 return RC_C67_A4 << (r - TREG_C67_A4);
266}
267
268
269// map TCC reg to C67 reg number
270
271int C67_map_regn(int r)
272{
273 if (r == 0) // normal tcc regs
274 return 0x2; // A2
275 else if (r == 1) // normal tcc regs
276 return 3; // A3
277 else if (r == 2) // normal tcc regs
278 return 0; // B0
279 else if (r == 3) // normal tcc regs
280 return 1; // B1
281 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
282 return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
283 else if (r == C67_A0)
284 return 0; // set to A0 (offset reg)
285 else if (r == C67_B2)
286 return 2; // set to B2 (offset reg)
287 else if (r == C67_B3)
288 return 3; // set to B3 (return address reg)
289 else if (r == C67_SP)
290 return 15; // set to SP (B15) (offset reg)
291 else if (r == C67_FP)
292 return 15; // set to FP (A15) (offset reg)
293 else if (r == C67_CREG_ZERO)
294 return 0; // Special code for no condition reg test
295 else
296 ALWAYS_ASSERT(FALSE);
297
298 return 0;
299}
300
301// mapping from tcc reg number to
302// C67 register to condition code field
303//
304// valid condition code regs are:
305//
306// tcc reg 2 ->B0 -> 1
307// tcc reg 3 ->B1 -> 2
308// tcc reg 0 -> A2 -> 5
309// tcc reg 1 -> A3 -> X
310// tcc reg B2 -> 3
311
312int C67_map_regc(int r)
313{
314 if (r == 0) // normal tcc regs
315 return 0x5;
316 else if (r == 2) // normal tcc regs
317 return 0x1;
318 else if (r == 3) // normal tcc regs
319 return 0x2;
320 else if (r == C67_B2) // normal tcc regs
321 return 0x3;
322 else if (r == C67_CREG_ZERO)
323 return 0; // Special code for no condition reg test
324 else
325 ALWAYS_ASSERT(FALSE);
326
327 return 0;
328}
329
330
331// map TCC reg to C67 reg side A or B
332
333int C67_map_regs(int r)
334{
335 if (r == 0) // normal tcc regs
336 return 0x0;
337 else if (r == 1) // normal tcc regs
338 return 0x0;
339 else if (r == 2) // normal tcc regs
340 return 0x1;
341 else if (r == 3) // normal tcc regs
342 return 0x1;
343 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
344 return (r & 2) >> 1;
345 else if (r == C67_A0)
346 return 0; // set to A side
347 else if (r == C67_B2)
348 return 1; // set to B side
349 else if (r == C67_B3)
350 return 1; // set to B side
351 else if (r == C67_SP)
352 return 0x1; // set to SP (B15) B side
353 else if (r == C67_FP)
354 return 0x0; // set to FP (A15) A side
355 else
356 ALWAYS_ASSERT(FALSE);
357
358 return 0;
359}
360
361int C67_map_S12(char *s)
362{
363 if (strstr(s, ".S1") != NULL)
364 return 0;
365 else if (strcmp(s, ".S2"))
366 return 1;
367 else
368 ALWAYS_ASSERT(FALSE);
369
370 return 0;
371}
372
373int C67_map_D12(char *s)
374{
375 if (strstr(s, ".D1") != NULL)
376 return 0;
377 else if (strcmp(s, ".D2"))
378 return 1;
379 else
380 ALWAYS_ASSERT(FALSE);
381
382 return 0;
383}
384
385
386
387void C67_asm(char *s, int a, int b, int c)
388{
389 BOOL xpath;
390
391#ifdef ASSEMBLY_LISTING_C67
392 if (!f) {
393 f = fopen("TCC67_out.txt", "wt");
394 }
395 fprintf(f, "%04X ", ind);
396#endif
397
398 if (strstr(s, "MVKL") == s) {
399 C67_g((C67_map_regn(b) << 23) |
400 ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
401 } else if (strstr(s, "MVKH") == s) {
402 C67_g((C67_map_regn(b) << 23) |
403 (((a >> 16) & 0xffff) << 7) |
404 (0x1a << 2) | (C67_map_regs(b) << 1));
405 } else if (strstr(s, "STW.D SP POST DEC") == s) {
406 C67_g((C67_map_regn(a) << 23) | //src
407 (15 << 18) | //SP B15
408 (2 << 13) | //ucst5 (must keep 8 byte boundary !!)
409 (0xa << 9) | //mode a = post dec ucst
410 (0 << 8) | //r (LDDW bit 0)
411 (1 << 7) | //y D1/D2 use B side
412 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
413 (1 << 2) | //opcode
414 (C67_map_regs(a) << 1) | //side of src
415 (0 << 0)); //parallel
416 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
417 C67_g((C67_map_regn(a) << 23) | //src
418 (15 << 18) | //base reg A15
419 (0 << 13) | //offset reg A0
420 (5 << 9) | //mode 5 = pos offset, base reg + off reg
421 (0 << 8) | //r (LDDW bit 0)
422 (0 << 7) | //y D1/D2 A side
423 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
424 (1 << 2) | //opcode
425 (C67_map_regs(a) << 1) | //side of src
426 (0 << 0)); //parallel
427 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
428 C67_g((C67_map_regn(a) << 23) | //src
429 (15 << 18) | //base reg A15
430 (0 << 13) | //offset reg A0
431 (5 << 9) | //mode 5 = pos offset, base reg + off reg
432 (0 << 8) | //r (LDDW bit 0)
433 (0 << 7) | //y D1/D2 A side
434 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
435 (1 << 2) | //opcode
436 (C67_map_regs(a) << 1) | //side of src
437 (0 << 0)); //parallel
438 } else if (strstr(s, "STB.D *+SP[A0]") == s) {
439 C67_g((C67_map_regn(a) << 23) | //src
440 (15 << 18) | //base reg A15
441 (0 << 13) | //offset reg A0
442 (5 << 9) | //mode 5 = pos offset, base reg + off reg
443 (0 << 8) | //r (LDDW bit 0)
444 (0 << 7) | //y D1/D2 A side
445 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
446 (1 << 2) | //opcode
447 (C67_map_regs(a) << 1) | //side of src
448 (0 << 0)); //parallel
449 } else if (strstr(s, "STH.D *+SP[A0]") == s) {
450 C67_g((C67_map_regn(a) << 23) | //src
451 (15 << 18) | //base reg A15
452 (0 << 13) | //offset reg A0
453 (5 << 9) | //mode 5 = pos offset, base reg + off reg
454 (0 << 8) | //r (LDDW bit 0)
455 (0 << 7) | //y D1/D2 A side
456 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
457 (1 << 2) | //opcode
458 (C67_map_regs(a) << 1) | //side of src
459 (0 << 0)); //parallel
460 } else if (strstr(s, "STW.D *+SP[A0]") == s) {
461 C67_g((C67_map_regn(a) << 23) | //src
462 (15 << 18) | //base reg A15
463 (0 << 13) | //offset reg A0
464 (5 << 9) | //mode 5 = pos offset, base reg + off reg
465 (0 << 8) | //r (LDDW bit 0)
466 (0 << 7) | //y D1/D2 A side
467 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
468 (1 << 2) | //opcode
469 (C67_map_regs(a) << 1) | //side of src
470 (0 << 0)); //parallel
471 } else if (strstr(s, "STW.D *") == s) {
472 C67_g((C67_map_regn(a) << 23) | //src
473 (C67_map_regn(b) << 18) | //base reg A0
474 (0 << 13) | //cst5
475 (1 << 9) | //mode 1 = pos cst offset
476 (0 << 8) | //r (LDDW bit 0)
477 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
478 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
479 (1 << 2) | //opcode
480 (C67_map_regs(a) << 1) | //side of src
481 (0 << 0)); //parallel
482 } else if (strstr(s, "STH.D *") == s) {
483 C67_g((C67_map_regn(a) << 23) | //src
484 (C67_map_regn(b) << 18) | //base reg A0
485 (0 << 13) | //cst5
486 (1 << 9) | //mode 1 = pos cst offset
487 (0 << 8) | //r (LDDW bit 0)
488 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
489 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
490 (1 << 2) | //opcode
491 (C67_map_regs(a) << 1) | //side of src
492 (0 << 0)); //parallel
493 } else if (strstr(s, "STB.D *") == s) {
494 C67_g((C67_map_regn(a) << 23) | //src
495 (C67_map_regn(b) << 18) | //base reg A0
496 (0 << 13) | //cst5
497 (1 << 9) | //mode 1 = pos cst offset
498 (0 << 8) | //r (LDDW bit 0)
499 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
500 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
501 (1 << 2) | //opcode
502 (C67_map_regs(a) << 1) | //side of src
503 (0 << 0)); //parallel
504 } else if (strstr(s, "STW.D +*") == s) {
505 ALWAYS_ASSERT(c < 32);
506 C67_g((C67_map_regn(a) << 23) | //src
507 (C67_map_regn(b) << 18) | //base reg A0
508 (c << 13) | //cst5
509 (1 << 9) | //mode 1 = pos cst offset
510 (0 << 8) | //r (LDDW bit 0)
511 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
512 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
513 (1 << 2) | //opcode
514 (C67_map_regs(a) << 1) | //side of src
515 (0 << 0)); //parallel
516 } else if (strstr(s, "LDW.D SP PRE INC") == s) {
517 C67_g((C67_map_regn(a) << 23) | //dst
518 (15 << 18) | //base reg B15
519 (2 << 13) | //ucst5 (must keep 8 byte boundary)
520 (9 << 9) | //mode 9 = pre inc ucst5
521 (0 << 8) | //r (LDDW bit 0)
522 (1 << 7) | //y D1/D2 B side
523 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
524 (1 << 2) | //opcode
525 (C67_map_regs(a) << 1) | //side of dst
526 (0 << 0)); //parallel
527 } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
528 C67_g((C67_map_regn(a) << 23) | //dst
529 (15 << 18) | //base reg B15
530 (1 << 13) | //ucst5 (must keep 8 byte boundary)
531 (9 << 9) | //mode 9 = pre inc ucst5
532 (1 << 8) | //r (LDDW bit 1)
533 (1 << 7) | //y D1/D2 B side
534 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
535 (1 << 2) | //opcode
536 (C67_map_regs(a) << 1) | //side of dst
537 (0 << 0)); //parallel
538 } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
539 C67_g((C67_map_regn(a) << 23) | //dst
540 (15 << 18) | //base reg A15
541 (0 << 13) | //offset reg A0
542 (5 << 9) | //mode 5 = pos offset, base reg + off reg
543 (0 << 8) | //r (LDDW bit 0)
544 (0 << 7) | //y D1/D2 A side
545 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
546 (1 << 2) | //opcode
547 (C67_map_regs(a) << 1) | //side of dst
548 (0 << 0)); //parallel
549 } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
550 C67_g((C67_map_regn(a) << 23) | //dst
551 (15 << 18) | //base reg A15
552 (0 << 13) | //offset reg A0
553 (5 << 9) | //mode 5 = pos offset, base reg + off reg
554 (1 << 8) | //r (LDDW bit 1)
555 (0 << 7) | //y D1/D2 A side
556 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
557 (1 << 2) | //opcode
558 (C67_map_regs(a) << 1) | //side of dst
559 (0 << 0)); //parallel
560 } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
561 C67_g((C67_map_regn(a) << 23) | //dst
562 (15 << 18) | //base reg A15
563 (0 << 13) | //offset reg A0
564 (5 << 9) | //mode 5 = pos offset, base reg + off reg
565 (0 << 8) | //r (LDDW bit 0)
566 (0 << 7) | //y D1/D2 A side
567 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
568 (1 << 2) | //opcode
569 (C67_map_regs(a) << 1) | //side of dst
570 (0 << 0)); //parallel
571 } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
572 C67_g((C67_map_regn(a) << 23) | //dst
573 (15 << 18) | //base reg A15
574 (0 << 13) | //offset reg A0
575 (5 << 9) | //mode 5 = pos offset, base reg + off reg
576 (0 << 8) | //r (LDDW bit 0)
577 (0 << 7) | //y D1/D2 A side
578 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
579 (1 << 2) | //opcode
580 (C67_map_regs(a) << 1) | //side of dst
581 (0 << 0)); //parallel
582 } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
583 C67_g((C67_map_regn(a) << 23) | //dst
584 (15 << 18) | //base reg A15
585 (0 << 13) | //offset reg A0
586 (5 << 9) | //mode 5 = pos offset, base reg + off reg
587 (0 << 8) | //r (LDDW bit 0)
588 (0 << 7) | //y D1/D2 A side
589 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
590 (1 << 2) | //opcode
591 (C67_map_regs(a) << 1) | //side of dst
592 (0 << 0)); //parallel
593 } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
594 C67_g((C67_map_regn(a) << 23) | //dst
595 (15 << 18) | //base reg A15
596 (0 << 13) | //offset reg A0
597 (5 << 9) | //mode 5 = pos offset, base reg + off reg
598 (0 << 8) | //r (LDDW bit 0)
599 (0 << 7) | //y D1/D2 A side
600 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
601 (1 << 2) | //opcode
602 (C67_map_regs(a) << 1) | //side of dst
603 (0 << 0)); //parallel
604 } else if (strstr(s, "LDW.D *") == s) {
605 C67_g((C67_map_regn(b) << 23) | //dst
606 (C67_map_regn(a) << 18) | //base reg A15
607 (0 << 13) | //cst5
608 (1 << 9) | //mode 1 = pos cst offset
609 (0 << 8) | //r (LDDW bit 0)
610 (C67_map_regs(a) << 7) | //y D1/D2 src side
611 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
612 (1 << 2) | //opcode
613 (C67_map_regs(b) << 1) | //side of dst
614 (0 << 0)); //parallel
615 } else if (strstr(s, "LDDW.D *") == s) {
616 C67_g((C67_map_regn(b) << 23) | //dst
617 (C67_map_regn(a) << 18) | //base reg A15
618 (0 << 13) | //cst5
619 (1 << 9) | //mode 1 = pos cst offset
620 (1 << 8) | //r (LDDW bit 1)
621 (C67_map_regs(a) << 7) | //y D1/D2 src side
622 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
623 (1 << 2) | //opcode
624 (C67_map_regs(b) << 1) | //side of dst
625 (0 << 0)); //parallel
626 } else if (strstr(s, "LDH.D *") == s) {
627 C67_g((C67_map_regn(b) << 23) | //dst
628 (C67_map_regn(a) << 18) | //base reg A15
629 (0 << 13) | //cst5
630 (1 << 9) | //mode 1 = pos cst offset
631 (0 << 8) | //r (LDDW bit 0)
632 (C67_map_regs(a) << 7) | //y D1/D2 src side
633 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
634 (1 << 2) | //opcode
635 (C67_map_regs(b) << 1) | //side of dst
636 (0 << 0)); //parallel
637 } else if (strstr(s, "LDB.D *") == s) {
638 C67_g((C67_map_regn(b) << 23) | //dst
639 (C67_map_regn(a) << 18) | //base reg A15
640 (0 << 13) | //cst5
641 (1 << 9) | //mode 1 = pos cst offset
642 (0 << 8) | //r (LDDW bit 0)
643 (C67_map_regs(a) << 7) | //y D1/D2 src side
644 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
645 (1 << 2) | //opcode
646 (C67_map_regs(b) << 1) | //side of dst
647 (0 << 0)); //parallel
648 } else if (strstr(s, "LDHU.D *") == s) {
649 C67_g((C67_map_regn(b) << 23) | //dst
650 (C67_map_regn(a) << 18) | //base reg A15
651 (0 << 13) | //cst5
652 (1 << 9) | //mode 1 = pos cst offset
653 (0 << 8) | //r (LDDW bit 0)
654 (C67_map_regs(a) << 7) | //y D1/D2 src side
655 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
656 (1 << 2) | //opcode
657 (C67_map_regs(b) << 1) | //side of dst
658 (0 << 0)); //parallel
659 } else if (strstr(s, "LDBU.D *") == s) {
660 C67_g((C67_map_regn(b) << 23) | //dst
661 (C67_map_regn(a) << 18) | //base reg A15
662 (0 << 13) | //cst5
663 (1 << 9) | //mode 1 = pos cst offset
664 (0 << 8) | //r (LDDW bit 0)
665 (C67_map_regs(a) << 7) | //y D1/D2 src side
666 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
667 (1 << 2) | //opcode
668 (C67_map_regs(b) << 1) | //side of dst
669 (0 << 0)); //parallel
670 } else if (strstr(s, "LDW.D +*") == s) {
671 C67_g((C67_map_regn(b) << 23) | //dst
672 (C67_map_regn(a) << 18) | //base reg A15
673 (1 << 13) | //cst5
674 (1 << 9) | //mode 1 = pos cst offset
675 (0 << 8) | //r (LDDW bit 0)
676 (C67_map_regs(a) << 7) | //y D1/D2 src side
677 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
678 (1 << 2) | //opcode
679 (C67_map_regs(b) << 1) | //side of dst
680 (0 << 0)); //parallel
681 } else if (strstr(s, "CMPLTSP") == s) {
682 xpath = C67_map_regs(a) ^ C67_map_regs(b);
683 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
684
685 C67_g((C67_map_regn(c) << 23) | //dst
686 (C67_map_regn(b) << 18) | //src2
687 (C67_map_regn(a) << 13) | //src1
688 (xpath << 12) | //x use cross path for src2
689 (0x3a << 6) | //opcode
690 (0x8 << 2) | //opcode fixed
691 (C67_map_regs(c) << 1) | //side for reg c
692 (0 << 0)); //parallel
693 } else if (strstr(s, "CMPGTSP") == s) {
694 xpath = C67_map_regs(a) ^ C67_map_regs(b);
695 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
696
697 C67_g((C67_map_regn(c) << 23) | //dst
698 (C67_map_regn(b) << 18) | //src2
699 (C67_map_regn(a) << 13) | //src1
700 (xpath << 12) | //x use cross path for src2
701 (0x39 << 6) | //opcode
702 (0x8 << 2) | //opcode fixed
703 (C67_map_regs(c) << 1) | //side for reg c
704 (0 << 0)); //parallel
705 } else if (strstr(s, "CMPEQSP") == s) {
706 xpath = C67_map_regs(a) ^ C67_map_regs(b);
707 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
708
709 C67_g((C67_map_regn(c) << 23) | //dst
710 (C67_map_regn(b) << 18) | //src2
711 (C67_map_regn(a) << 13) | //src1
712 (xpath << 12) | //x use cross path for src2
713 (0x38 << 6) | //opcode
714 (0x8 << 2) | //opcode fixed
715 (C67_map_regs(c) << 1) | //side for reg c
716 (0 << 0)); //parallel
717 }
718
719 else if (strstr(s, "CMPLTDP") == s) {
720 xpath = C67_map_regs(a) ^ C67_map_regs(b);
721 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
722
723 C67_g((C67_map_regn(c) << 23) | //dst
724 (C67_map_regn(b) << 18) | //src2
725 (C67_map_regn(a) << 13) | //src1
726 (xpath << 12) | //x use cross path for src2
727 (0x2a << 6) | //opcode
728 (0x8 << 2) | //opcode fixed
729 (C67_map_regs(c) << 1) | //side for reg c
730 (0 << 0)); //parallel
731 } else if (strstr(s, "CMPGTDP") == s) {
732 xpath = C67_map_regs(a) ^ C67_map_regs(b);
733 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
734
735 C67_g((C67_map_regn(c) << 23) | //dst
736 (C67_map_regn(b) << 18) | //src2
737 (C67_map_regn(a) << 13) | //src1
738 (xpath << 12) | //x use cross path for src2
739 (0x29 << 6) | //opcode
740 (0x8 << 2) | //opcode fixed
741 (C67_map_regs(c) << 1) | //side for reg c
742 (0 << 0)); //parallel
743 } else if (strstr(s, "CMPEQDP") == s) {
744 xpath = C67_map_regs(a) ^ C67_map_regs(b);
745 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
746
747 C67_g((C67_map_regn(c) << 23) | //dst
748 (C67_map_regn(b) << 18) | //src2
749 (C67_map_regn(a) << 13) | //src1
750 (xpath << 12) | //x use cross path for src2
751 (0x28 << 6) | //opcode
752 (0x8 << 2) | //opcode fixed
753 (C67_map_regs(c) << 1) | //side for reg c
754 (0 << 0)); //parallel
755 } else if (strstr(s, "CMPLT") == s) {
756 xpath = C67_map_regs(a) ^ C67_map_regs(b);
757 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
758
759 C67_g((C67_map_regn(c) << 23) | //dst
760 (C67_map_regn(b) << 18) | //src2
761 (C67_map_regn(a) << 13) | //src1
762 (xpath << 12) | //x use cross path for src2
763 (0x57 << 5) | //opcode
764 (0x6 << 2) | //opcode fixed
765 (C67_map_regs(c) << 1) | //side for reg c
766 (0 << 0)); //parallel
767 } else if (strstr(s, "CMPGT") == s) {
768 xpath = C67_map_regs(a) ^ C67_map_regs(b);
769 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
770
771 C67_g((C67_map_regn(c) << 23) | //dst
772 (C67_map_regn(b) << 18) | //src2
773 (C67_map_regn(a) << 13) | //src1
774 (xpath << 12) | //x use cross path for src2
775 (0x47 << 5) | //opcode
776 (0x6 << 2) | //opcode fixed
777 (C67_map_regs(c) << 1) | //side for reg c
778 (0 << 0)); //parallel
779 } else if (strstr(s, "CMPEQ") == s) {
780 xpath = C67_map_regs(a) ^ C67_map_regs(b);
781 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
782
783 C67_g((C67_map_regn(c) << 23) | //dst
784 (C67_map_regn(b) << 18) | //src2
785 (C67_map_regn(a) << 13) | //src1
786 (xpath << 12) | //x use cross path for src2
787 (0x53 << 5) | //opcode
788 (0x6 << 2) | //opcode fixed
789 (C67_map_regs(c) << 1) | //side for reg c
790 (0 << 0)); //parallel
791 } else if (strstr(s, "CMPLTU") == s) {
792 xpath = C67_map_regs(a) ^ C67_map_regs(b);
793 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
794
795 C67_g((C67_map_regn(c) << 23) | //dst
796 (C67_map_regn(b) << 18) | //src2
797 (C67_map_regn(a) << 13) | //src1
798 (xpath << 12) | //x use cross path for src2
799 (0x5f << 5) | //opcode
800 (0x6 << 2) | //opcode fixed
801 (C67_map_regs(c) << 1) | //side for reg c
802 (0 << 0)); //parallel
803 } else if (strstr(s, "CMPGTU") == s) {
804 xpath = C67_map_regs(a) ^ C67_map_regs(b);
805 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
806
807 C67_g((C67_map_regn(c) << 23) | //dst
808 (C67_map_regn(b) << 18) | //src2
809 (C67_map_regn(a) << 13) | //src1
810 (xpath << 12) | //x use cross path for src2
811 (0x4f << 5) | //opcode
812 (0x6 << 2) | //opcode fixed
813 (C67_map_regs(c) << 1) | //side for reg c
814 (0 << 0)); //parallel
815 } else if (strstr(s, "B DISP") == s) {
816 C67_g((0 << 29) | //creg
817 (0 << 28) | //z
818 (a << 7) | //cnst
819 (0x4 << 2) | //opcode fixed
820 (0 << 1) | //S0/S1
821 (0 << 0)); //parallel
822 } else if (strstr(s, "B.") == s) {
823 xpath = C67_map_regs(c) ^ 1;
824
825 C67_g((C67_map_regc(b) << 29) | //creg
826 (a << 28) | //inv
827 (0 << 23) | //dst
828 (C67_map_regn(c) << 18) | //src2
829 (0 << 13) | //
830 (xpath << 12) | //x cross path if !B side
831 (0xd << 6) | //opcode
832 (0x8 << 2) | //opcode fixed
833 (1 << 1) | //must be S2
834 (0 << 0)); //parallel
835 } else if (strstr(s, "MV.L") == s) {
836 xpath = C67_map_regs(b) ^ C67_map_regs(c);
837
838 C67_g((0 << 29) | //creg
839 (0 << 28) | //inv
840 (C67_map_regn(c) << 23) | //dst
841 (C67_map_regn(b) << 18) | //src2
842 (0 << 13) | //src1 (cst5)
843 (xpath << 12) | //x cross path if opposite sides
844 (0x2 << 5) | //opcode
845 (0x6 << 2) | //opcode fixed
846 (C67_map_regs(c) << 1) | //side of dest
847 (0 << 0)); //parallel
848 } else if (strstr(s, "SPTRUNC.L") == s) {
849 xpath = C67_map_regs(b) ^ C67_map_regs(c);
850
851 C67_g((0 << 29) | //creg
852 (0 << 28) | //inv
853 (C67_map_regn(c) << 23) | //dst
854 (C67_map_regn(b) << 18) | //src2
855 (0 << 13) | //src1 NA
856 (xpath << 12) | //x cross path if opposite sides
857 (0xb << 5) | //opcode
858 (0x6 << 2) | //opcode fixed
859 (C67_map_regs(c) << 1) | //side of dest
860 (0 << 0)); //parallel
861 } else if (strstr(s, "DPTRUNC.L") == s) {
862 xpath = C67_map_regs(b) ^ C67_map_regs(c);
863
864 C67_g((0 << 29) | //creg
865 (0 << 28) | //inv
866 (C67_map_regn(c) << 23) | //dst
867 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
868 (0 << 13) | //src1 NA
869 (xpath << 12) | //x cross path if opposite sides
870 (0x1 << 5) | //opcode
871 (0x6 << 2) | //opcode fixed
872 (C67_map_regs(c) << 1) | //side of dest
873 (0 << 0)); //parallel
874 } else if (strstr(s, "INTSP.L") == s) {
875 xpath = C67_map_regs(b) ^ C67_map_regs(c);
876
877 C67_g((0 << 29) | //creg
878 (0 << 28) | //inv
879 (C67_map_regn(c) << 23) | //dst
880 (C67_map_regn(b) << 18) | //src2
881 (0 << 13) | //src1 NA
882 (xpath << 12) | //x cross path if opposite sides
883 (0x4a << 5) | //opcode
884 (0x6 << 2) | //opcode fixed
885 (C67_map_regs(c) << 1) | //side of dest
886 (0 << 0)); //parallel
887 } else if (strstr(s, "INTSPU.L") == s) {
888 xpath = C67_map_regs(b) ^ C67_map_regs(c);
889
890 C67_g((0 << 29) | //creg
891 (0 << 28) | //inv
892 (C67_map_regn(c) << 23) | //dst
893 (C67_map_regn(b) << 18) | //src2
894 (0 << 13) | //src1 NA
895 (xpath << 12) | //x cross path if opposite sides
896 (0x49 << 5) | //opcode
897 (0x6 << 2) | //opcode fixed
898 (C67_map_regs(c) << 1) | //side of dest
899 (0 << 0)); //parallel
900 } else if (strstr(s, "INTDP.L") == s) {
901 xpath = C67_map_regs(b) ^ C67_map_regs(c);
902
903 C67_g((0 << 29) | //creg
904 (0 << 28) | //inv
905 (C67_map_regn(c) << 23) | //dst
906 (C67_map_regn(b) << 18) | //src2
907 (0 << 13) | //src1 NA
908 (xpath << 12) | //x cross path if opposite sides
909 (0x39 << 5) | //opcode
910 (0x6 << 2) | //opcode fixed
911 (C67_map_regs(c) << 1) | //side of dest
912 (0 << 0)); //parallel
913 } else if (strstr(s, "INTDPU.L") == s) {
914 xpath = C67_map_regs(b) ^ C67_map_regs(c);
915
916 C67_g((0 << 29) | //creg
917 (0 << 28) | //inv
918 (C67_map_regn(c) << 23) | //dst
919 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
920 (0 << 13) | //src1 NA
921 (xpath << 12) | //x cross path if opposite sides
922 (0x3b << 5) | //opcode
923 (0x6 << 2) | //opcode fixed
924 (C67_map_regs(c) << 1) | //side of dest
925 (0 << 0)); //parallel
926 } else if (strstr(s, "SPDP.L") == s) {
927 xpath = C67_map_regs(b) ^ C67_map_regs(c);
928
929 C67_g((0 << 29) | //creg
930 (0 << 28) | //inv
931 (C67_map_regn(c) << 23) | //dst
932 (C67_map_regn(b) << 18) | //src2
933 (0 << 13) | //src1 NA
934 (xpath << 12) | //x cross path if opposite sides
935 (0x2 << 6) | //opcode
936 (0x8 << 2) | //opcode fixed
937 (C67_map_regs(c) << 1) | //side of dest
938 (0 << 0)); //parallel
939 } else if (strstr(s, "DPSP.L") == s) {
940 ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
941
942 C67_g((0 << 29) | //creg
943 (0 << 28) | //inv
944 (C67_map_regn(c) << 23) | //dst
945 ((C67_map_regn(b) + 1) << 18) | //src2 WEIRD CPU must specify odd reg for some reason
946 (0 << 13) | //src1 NA
947 (0 << 12) | //x cross path if opposite sides
948 (0x9 << 5) | //opcode
949 (0x6 << 2) | //opcode fixed
950 (C67_map_regs(c) << 1) | //side of dest
951 (0 << 0)); //parallel
952 } else if (strstr(s, "ADD.L") == s) {
953 xpath = C67_map_regs(b) ^ C67_map_regs(c);
954
955 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
956
957 C67_g((0 << 29) | //creg
958 (0 << 28) | //inv
959 (C67_map_regn(c) << 23) | //dst
960 (C67_map_regn(b) << 18) | //src2 (possible x path)
961 (C67_map_regn(a) << 13) | //src1
962 (xpath << 12) | //x cross path if opposite sides
963 (0x3 << 5) | //opcode
964 (0x6 << 2) | //opcode fixed
965 (C67_map_regs(c) << 1) | //side of dest
966 (0 << 0)); //parallel
967 } else if (strstr(s, "SUB.L") == s) {
968 xpath = C67_map_regs(b) ^ C67_map_regs(c);
969
970 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
971
972 C67_g((0 << 29) | //creg
973 (0 << 28) | //inv
974 (C67_map_regn(c) << 23) | //dst
975 (C67_map_regn(b) << 18) | //src2 (possible x path)
976 (C67_map_regn(a) << 13) | //src1
977 (xpath << 12) | //x cross path if opposite sides
978 (0x7 << 5) | //opcode
979 (0x6 << 2) | //opcode fixed
980 (C67_map_regs(c) << 1) | //side of dest
981 (0 << 0)); //parallel
982 } else if (strstr(s, "OR.L") == s) {
983 xpath = C67_map_regs(b) ^ C67_map_regs(c);
984
985 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
986
987 C67_g((0 << 29) | //creg
988 (0 << 28) | //inv
989 (C67_map_regn(c) << 23) | //dst
990 (C67_map_regn(b) << 18) | //src2 (possible x path)
991 (C67_map_regn(a) << 13) | //src1
992 (xpath << 12) | //x cross path if opposite sides
993 (0x7f << 5) | //opcode
994 (0x6 << 2) | //opcode fixed
995 (C67_map_regs(c) << 1) | //side of dest
996 (0 << 0)); //parallel
997 } else if (strstr(s, "AND.L") == s) {
998 xpath = C67_map_regs(b) ^ C67_map_regs(c);
999
1000 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1001
1002 C67_g((0 << 29) | //creg
1003 (0 << 28) | //inv
1004 (C67_map_regn(c) << 23) | //dst
1005 (C67_map_regn(b) << 18) | //src2 (possible x path)
1006 (C67_map_regn(a) << 13) | //src1
1007 (xpath << 12) | //x cross path if opposite sides
1008 (0x7b << 5) | //opcode
1009 (0x6 << 2) | //opcode fixed
1010 (C67_map_regs(c) << 1) | //side of dest
1011 (0 << 0)); //parallel
1012 } else if (strstr(s, "XOR.L") == s) {
1013 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1014
1015 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1016
1017 C67_g((0 << 29) | //creg
1018 (0 << 28) | //inv
1019 (C67_map_regn(c) << 23) | //dst
1020 (C67_map_regn(b) << 18) | //src2 (possible x path)
1021 (C67_map_regn(a) << 13) | //src1
1022 (xpath << 12) | //x cross path if opposite sides
1023 (0x6f << 5) | //opcode
1024 (0x6 << 2) | //opcode fixed
1025 (C67_map_regs(c) << 1) | //side of dest
1026 (0 << 0)); //parallel
1027 } else if (strstr(s, "ADDSP.L") == s) {
1028 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1029
1030 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1031
1032 C67_g((0 << 29) | //creg
1033 (0 << 28) | //inv
1034 (C67_map_regn(c) << 23) | //dst
1035 (C67_map_regn(b) << 18) | //src2 (possible x path)
1036 (C67_map_regn(a) << 13) | //src1
1037 (xpath << 12) | //x cross path if opposite sides
1038 (0x10 << 5) | //opcode
1039 (0x6 << 2) | //opcode fixed
1040 (C67_map_regs(c) << 1) | //side of dest
1041 (0 << 0)); //parallel
1042 } else if (strstr(s, "ADDDP.L") == s) {
1043 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1044
1045 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1046
1047 C67_g((0 << 29) | //creg
1048 (0 << 28) | //inv
1049 (C67_map_regn(c) << 23) | //dst
1050 (C67_map_regn(b) << 18) | //src2 (possible x path)
1051 (C67_map_regn(a) << 13) | //src1
1052 (xpath << 12) | //x cross path if opposite sides
1053 (0x18 << 5) | //opcode
1054 (0x6 << 2) | //opcode fixed
1055 (C67_map_regs(c) << 1) | //side of dest
1056 (0 << 0)); //parallel
1057 } else if (strstr(s, "SUBSP.L") == s) {
1058 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1059
1060 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1061
1062 C67_g((0 << 29) | //creg
1063 (0 << 28) | //inv
1064 (C67_map_regn(c) << 23) | //dst
1065 (C67_map_regn(b) << 18) | //src2 (possible x path)
1066 (C67_map_regn(a) << 13) | //src1
1067 (xpath << 12) | //x cross path if opposite sides
1068 (0x11 << 5) | //opcode
1069 (0x6 << 2) | //opcode fixed
1070 (C67_map_regs(c) << 1) | //side of dest
1071 (0 << 0)); //parallel
1072 } else if (strstr(s, "SUBDP.L") == s) {
1073 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1074
1075 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1076
1077 C67_g((0 << 29) | //creg
1078 (0 << 28) | //inv
1079 (C67_map_regn(c) << 23) | //dst
1080 (C67_map_regn(b) << 18) | //src2 (possible x path)
1081 (C67_map_regn(a) << 13) | //src1
1082 (xpath << 12) | //x cross path if opposite sides
1083 (0x19 << 5) | //opcode
1084 (0x6 << 2) | //opcode fixed
1085 (C67_map_regs(c) << 1) | //side of dest
1086 (0 << 0)); //parallel
1087 } else if (strstr(s, "MPYSP.M") == s) {
1088 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1089
1090 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1091
1092 C67_g((0 << 29) | //creg
1093 (0 << 28) | //inv
1094 (C67_map_regn(c) << 23) | //dst
1095 (C67_map_regn(b) << 18) | //src2 (possible x path)
1096 (C67_map_regn(a) << 13) | //src1
1097 (xpath << 12) | //x cross path if opposite sides
1098 (0x1c << 7) | //opcode
1099 (0x0 << 2) | //opcode fixed
1100 (C67_map_regs(c) << 1) | //side of dest
1101 (0 << 0)); //parallel
1102 } else if (strstr(s, "MPYDP.M") == s) {
1103 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1104
1105 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1106
1107 C67_g((0 << 29) | //creg
1108 (0 << 28) | //inv
1109 (C67_map_regn(c) << 23) | //dst
1110 (C67_map_regn(b) << 18) | //src2 (possible x path)
1111 (C67_map_regn(a) << 13) | //src1
1112 (xpath << 12) | //x cross path if opposite sides
1113 (0x0e << 7) | //opcode
1114 (0x0 << 2) | //opcode fixed
1115 (C67_map_regs(c) << 1) | //side of dest
1116 (0 << 0)); //parallel
1117 } else if (strstr(s, "MPYI.M") == s) {
1118 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1119
1120 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1121
1122 C67_g((0 << 29) | //creg
1123 (0 << 28) | //inv
1124 (C67_map_regn(c) << 23) | //dst
1125 (C67_map_regn(b) << 18) | //src2
1126 (C67_map_regn(a) << 13) | //src1 (cst5)
1127 (xpath << 12) | //x cross path if opposite sides
1128 (0x4 << 7) | //opcode
1129 (0x0 << 2) | //opcode fixed
1130 (C67_map_regs(c) << 1) | //side of dest
1131 (0 << 0)); //parallel
1132 } else if (strstr(s, "SHR.S") == s) {
1133 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1134
1135 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1136
1137 C67_g((0 << 29) | //creg
1138 (0 << 28) | //inv
1139 (C67_map_regn(c) << 23) | //dst
1140 (C67_map_regn(b) << 18) | //src2
1141 (C67_map_regn(a) << 13) | //src1
1142 (xpath << 12) | //x cross path if opposite sides
1143 (0x37 << 6) | //opcode
1144 (0x8 << 2) | //opcode fixed
1145 (C67_map_regs(c) << 1) | //side of dest
1146 (0 << 0)); //parallel
1147 } else if (strstr(s, "SHRU.S") == s) {
1148 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1149
1150 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1151
1152 C67_g((0 << 29) | //creg
1153 (0 << 28) | //inv
1154 (C67_map_regn(c) << 23) | //dst
1155 (C67_map_regn(b) << 18) | //src2
1156 (C67_map_regn(a) << 13) | //src1
1157 (xpath << 12) | //x cross path if opposite sides
1158 (0x27 << 6) | //opcode
1159 (0x8 << 2) | //opcode fixed
1160 (C67_map_regs(c) << 1) | //side of dest
1161 (0 << 0)); //parallel
1162 } else if (strstr(s, "SHL.S") == s) {
1163 xpath = C67_map_regs(b) ^ C67_map_regs(c);
1164
1165 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1166
1167 C67_g((0 << 29) | //creg
1168 (0 << 28) | //inv
1169 (C67_map_regn(c) << 23) | //dst
1170 (C67_map_regn(b) << 18) | //src2
1171 (C67_map_regn(a) << 13) | //src1
1172 (xpath << 12) | //x cross path if opposite sides
1173 (0x33 << 6) | //opcode
1174 (0x8 << 2) | //opcode fixed
1175 (C67_map_regs(c) << 1) | //side of dest
1176 (0 << 0)); //parallel
1177 } else if (strstr(s, "||ADDK") == s) {
1178 xpath = 0; // no xpath required just use the side of the src/dst
1179
1180 C67_g((0 << 29) | //creg
1181 (0 << 28) | //inv
1182 (C67_map_regn(b) << 23) | //dst
1183 (a << 07) | //scst16
1184 (0x14 << 2) | //opcode fixed
1185 (C67_map_regs(b) << 1) | //side of dst
1186 (1 << 0)); //parallel
1187 } else if (strstr(s, "ADDK") == s) {
1188 xpath = 0; // no xpath required just use the side of the src/dst
1189
1190 C67_g((0 << 29) | //creg
1191 (0 << 28) | //inv
1192 (C67_map_regn(b) << 23) | //dst
1193 (a << 07) | //scst16
1194 (0x14 << 2) | //opcode fixed
1195 (C67_map_regs(b) << 1) | //side of dst
1196 (0 << 0)); //parallel
1197 } else if (strstr(s, "NOP") == s) {
1198 C67_g(((a - 1) << 13) | //no of cycles
1199 (0 << 0)); //parallel
1200 } else
1201 ALWAYS_ASSERT(FALSE);
1202
1203#ifdef ASSEMBLY_LISTING_C67
1204 fprintf(f, " %s %d %d %d\n", s, a, b, c);
1205#endif
1206
1207}
1208
1209//r=reg to load, fr=from reg, symbol for relocation, constant
1210
1211void C67_MVKL(int r, int fc)
1212{
1213 C67_asm("MVKL.", fc, r, 0);
1214}
1215
1216void C67_MVKH(int r, int fc)
1217{
1218 C67_asm("MVKH.", fc, r, 0);
1219}
1220
1221void C67_STB_SP_A0(int r)
1222{
1223 C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB r,*+SP[A0]
1224}
1225
1226void C67_STH_SP_A0(int r)
1227{
1228 C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH r,*+SP[A0]
1229}
1230
1231void C67_STW_SP_A0(int r)
1232{
1233 C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW r,*+SP[A0]
1234}
1235
1236void C67_STB_PTR(int r, int r2)
1237{
1238 C67_asm("STB.D *", r, r2, 0); // STB r, *r2
1239}
1240
1241void C67_STH_PTR(int r, int r2)
1242{
1243 C67_asm("STH.D *", r, r2, 0); // STH r, *r2
1244}
1245
1246void C67_STW_PTR(int r, int r2)
1247{
1248 C67_asm("STW.D *", r, r2, 0); // STW r, *r2
1249}
1250
1251void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1252{
1253 C67_asm("STW.D +*", r, r2, n); // STW r, *+r2
1254}
1255
1256void C67_PUSH(int r)
1257{
1258 C67_asm("STW.D SP POST DEC", r, 0, 0); // STW r,*SP--
1259}
1260
1261void C67_LDW_SP_A0(int r)
1262{
1263 C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW *+SP[A0],r
1264}
1265
1266void C67_LDDW_SP_A0(int r)
1267{
1268 C67_asm("LDDW.D *+SP[A0]", r, 0, 0); // LDDW *+SP[A0],r
1269}
1270
1271void C67_LDH_SP_A0(int r)
1272{
1273 C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH *+SP[A0],r
1274}
1275
1276void C67_LDB_SP_A0(int r)
1277{
1278 C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB *+SP[A0],r
1279}
1280
1281void C67_LDHU_SP_A0(int r)
1282{
1283 C67_asm("LDHU.D *+SP[A0]", r, 0, 0); // LDHU *+SP[A0],r
1284}
1285
1286void C67_LDBU_SP_A0(int r)
1287{
1288 C67_asm("LDBU.D *+SP[A0]", r, 0, 0); // LDBU *+SP[A0],r
1289}
1290
1291void C67_LDW_PTR(int r, int r2)
1292{
1293 C67_asm("LDW.D *", r, r2, 0); // LDW *r,r2
1294}
1295
1296void C67_LDDW_PTR(int r, int r2)
1297{
1298 C67_asm("LDDW.D *", r, r2, 0); // LDDW *r,r2
1299}
1300
1301void C67_LDH_PTR(int r, int r2)
1302{
1303 C67_asm("LDH.D *", r, r2, 0); // LDH *r,r2
1304}
1305
1306void C67_LDB_PTR(int r, int r2)
1307{
1308 C67_asm("LDB.D *", r, r2, 0); // LDB *r,r2
1309}
1310
1311void C67_LDHU_PTR(int r, int r2)
1312{
1313 C67_asm("LDHU.D *", r, r2, 0); // LDHU *r,r2
1314}
1315
1316void C67_LDBU_PTR(int r, int r2)
1317{
1318 C67_asm("LDBU.D *", r, r2, 0); // LDBU *r,r2
1319}
1320
1321void C67_LDW_PTR_PRE_INC(int r, int r2)
1322{
1323 C67_asm("LDW.D +*", r, r2, 0); // LDW *+r,r2
1324}
1325
1326void C67_POP(int r)
1327{
1328 C67_asm("LDW.D SP PRE INC", r, 0, 0); // LDW *++SP,r
1329}
1330
1331void C67_POP_DW(int r)
1332{
1333 C67_asm("LDDW.D SP PRE INC", r, 0, 0); // LDDW *++SP,r
1334}
1335
1336void C67_CMPLT(int s1, int s2, int dst)
1337{
1338 C67_asm("CMPLT.L1", s1, s2, dst);
1339}
1340
1341void C67_CMPGT(int s1, int s2, int dst)
1342{
1343 C67_asm("CMPGT.L1", s1, s2, dst);
1344}
1345
1346void C67_CMPEQ(int s1, int s2, int dst)
1347{
1348 C67_asm("CMPEQ.L1", s1, s2, dst);
1349}
1350
1351void C67_CMPLTU(int s1, int s2, int dst)
1352{
1353 C67_asm("CMPLTU.L1", s1, s2, dst);
1354}
1355
1356void C67_CMPGTU(int s1, int s2, int dst)
1357{
1358 C67_asm("CMPGTU.L1", s1, s2, dst);
1359}
1360
1361
1362void C67_CMPLTSP(int s1, int s2, int dst)
1363{
1364 C67_asm("CMPLTSP.S1", s1, s2, dst);
1365}
1366
1367void C67_CMPGTSP(int s1, int s2, int dst)
1368{
1369 C67_asm("CMPGTSP.S1", s1, s2, dst);
1370}
1371
1372void C67_CMPEQSP(int s1, int s2, int dst)
1373{
1374 C67_asm("CMPEQSP.S1", s1, s2, dst);
1375}
1376
1377void C67_CMPLTDP(int s1, int s2, int dst)
1378{
1379 C67_asm("CMPLTDP.S1", s1, s2, dst);
1380}
1381
1382void C67_CMPGTDP(int s1, int s2, int dst)
1383{
1384 C67_asm("CMPGTDP.S1", s1, s2, dst);
1385}
1386
1387void C67_CMPEQDP(int s1, int s2, int dst)
1388{
1389 C67_asm("CMPEQDP.S1", s1, s2, dst);
1390}
1391
1392
1393void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2
1394{
1395 C67_asm("B.S2", inv, r1, r2);
1396}
1397
1398
1399// call with how many 32 bit words to skip
1400// (0 would branch to the branch instruction)
1401
1402void C67_B_DISP(int disp) // B +2 Branch with constant displacement
1403{
1404 // Branch point is relative to the 8 word fetch packet
1405 //
1406 // we will assume the text section always starts on an 8 word (32 byte boundary)
1407 //
1408 // so add in how many words into the fetch packet the branch is
1409
1410
1411 C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1412}
1413
1414void C67_NOP(int n)
1415{
1416 C67_asm("NOP", n, 0, 0);
1417}
1418
1419void C67_ADDK(int n, int r)
1420{
1421 ALWAYS_ASSERT(abs(n) < 32767);
1422
1423 C67_asm("ADDK", n, r, 0);
1424}
1425
1426void C67_ADDK_PARALLEL(int n, int r)
1427{
1428 ALWAYS_ASSERT(abs(n) < 32767);
1429
1430 C67_asm("||ADDK", n, r, 0);
1431}
1432
1433void C67_Adjust_ADDK(int *inst, int n)
1434{
1435 ALWAYS_ASSERT(abs(n) < 32767);
1436
1437 *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1438}
1439
1440void C67_MV(int r, int v)
1441{
1442 C67_asm("MV.L", 0, r, v);
1443}
1444
1445
1446void C67_DPTRUNC(int r, int v)
1447{
1448 C67_asm("DPTRUNC.L", 0, r, v);
1449}
1450
1451void C67_SPTRUNC(int r, int v)
1452{
1453 C67_asm("SPTRUNC.L", 0, r, v);
1454}
1455
1456void C67_INTSP(int r, int v)
1457{
1458 C67_asm("INTSP.L", 0, r, v);
1459}
1460
1461void C67_INTDP(int r, int v)
1462{
1463 C67_asm("INTDP.L", 0, r, v);
1464}
1465
1466void C67_INTSPU(int r, int v)
1467{
1468 C67_asm("INTSPU.L", 0, r, v);
1469}
1470
1471void C67_INTDPU(int r, int v)
1472{
1473 C67_asm("INTDPU.L", 0, r, v);
1474}
1475
1476void C67_SPDP(int r, int v)
1477{
1478 C67_asm("SPDP.L", 0, r, v);
1479}
1480
1481void C67_DPSP(int r, int v) // note regs must be on the same side
1482{
1483 C67_asm("DPSP.L", 0, r, v);
1484}
1485
1486void C67_ADD(int r, int v)
1487{
1488 C67_asm("ADD.L", v, r, v);
1489}
1490
1491void C67_SUB(int r, int v)
1492{
1493 C67_asm("SUB.L", v, r, v);
1494}
1495
1496void C67_AND(int r, int v)
1497{
1498 C67_asm("AND.L", v, r, v);
1499}
1500
1501void C67_OR(int r, int v)
1502{
1503 C67_asm("OR.L", v, r, v);
1504}
1505
1506void C67_XOR(int r, int v)
1507{
1508 C67_asm("XOR.L", v, r, v);
1509}
1510
1511void C67_ADDSP(int r, int v)
1512{
1513 C67_asm("ADDSP.L", v, r, v);
1514}
1515
1516void C67_SUBSP(int r, int v)
1517{
1518 C67_asm("SUBSP.L", v, r, v);
1519}
1520
1521void C67_MPYSP(int r, int v)
1522{
1523 C67_asm("MPYSP.M", v, r, v);
1524}
1525
1526void C67_ADDDP(int r, int v)
1527{
1528 C67_asm("ADDDP.L", v, r, v);
1529}
1530
1531void C67_SUBDP(int r, int v)
1532{
1533 C67_asm("SUBDP.L", v, r, v);
1534}
1535
1536void C67_MPYDP(int r, int v)
1537{
1538 C67_asm("MPYDP.M", v, r, v);
1539}
1540
1541void C67_MPYI(int r, int v)
1542{
1543 C67_asm("MPYI.M", v, r, v);
1544}
1545
1546void C67_SHL(int r, int v)
1547{
1548 C67_asm("SHL.S", r, v, v);
1549}
1550
1551void C67_SHRU(int r, int v)
1552{
1553 C67_asm("SHRU.S", r, v, v);
1554}
1555
1556void C67_SHR(int r, int v)
1557{
1558 C67_asm("SHR.S", r, v, v);
1559}
1560
1561
1562
1563/* load 'r' from value 'sv' */
1564void load(int r, SValue * sv)
1565{
6bbfb8f6 bellard2004-11-07 15:43:15 +00001566 int v, t, ft, fc, fr, size = 0, element;
263dc93c grischka2013-02-04 15:10:08 +01001567 BOOL Unsigned = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00001568 SValue v1;
1569
1570 fr = sv->r;
1571 ft = sv->type.t;
1572 fc = sv->c.ul;
1573
1574 v = fr & VT_VALMASK;
1575 if (fr & VT_LVAL) {
1576 if (v == VT_LLOCAL) {
1577 v1.type.t = VT_INT;
1578 v1.r = VT_LOCAL | VT_LVAL;
1579 v1.c.ul = fc;
1580 load(r, &v1);
1581 fr = r;
1582 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
bf374a5f grischka2011-08-11 17:07:56 +02001583 tcc_error("long double not supported");
bf45336a bellard2004-10-05 17:55:18 +00001584 } else if ((ft & VT_TYPE) == VT_BYTE) {
1585 size = 1;
1586 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1587 size = 1;
1588 Unsigned = TRUE;
1589 } else if ((ft & VT_TYPE) == VT_SHORT) {
1590 size = 2;
1591 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1592 size = 2;
1593 Unsigned = TRUE;
1594 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1595 size = 8;
1596 } else {
1597 size = 4;
1598 }
1599
1600 // check if fc is a positive reference on the stack,
1601 // if it is tcc is referencing what it thinks is a parameter
1602 // on the stack, so check if it is really in a register.
1603
1604
1605 if (v == VT_LOCAL && fc > 0) {
1606 int stack_pos = 8;
1607
1608 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1609 if (fc == stack_pos)
1610 break;
1611
1612 stack_pos += TranslateStackToReg[t];
1613 }
1614
1615 // param has been pushed on stack, get it like a local var
1616
1617 fc = ParamLocOnStack[t] - 8;
1618 }
1619
1620 if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect
1621 {
1622 if (size == 1) {
1623 if (Unsigned)
1624 C67_LDBU_PTR(v, r); // LDBU *v,r
1625 else
1626 C67_LDB_PTR(v, r); // LDB *v,r
1627 } else if (size == 2) {
1628 if (Unsigned)
1629 C67_LDHU_PTR(v, r); // LDHU *v,r
1630 else
1631 C67_LDH_PTR(v, r); // LDH *v,r
1632 } else if (size == 4) {
1633 C67_LDW_PTR(v, r); // LDW *v,r
1634 } else if (size == 8) {
1635 C67_LDDW_PTR(v, r); // LDDW *v,r
1636 }
1637
1638 C67_NOP(4); // NOP 4
1639 return;
1640 } else if (fr & VT_SYM) {
1641 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1642 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1643
1644
1645 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1646 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1647
1648
1649 if (size == 1) {
1650 if (Unsigned)
1651 C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r
1652 else
1653 C67_LDB_PTR(C67_A0, r); // LDB *A0,r
1654 } else if (size == 2) {
1655 if (Unsigned)
1656 C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r
1657 else
1658 C67_LDH_PTR(C67_A0, r); // LDH *A0,r
1659 } else if (size == 4) {
1660 C67_LDW_PTR(C67_A0, r); // LDW *A0,r
1661 } else if (size == 8) {
1662 C67_LDDW_PTR(C67_A0, r); // LDDW *A0,r
1663 }
1664
1665 C67_NOP(4); // NOP 4
1666 return;
1667 } else {
1668 element = size;
1669
1670 // divide offset in bytes to create element index
1671 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1672 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1673
1674 if (size == 1) {
1675 if (Unsigned)
1676 C67_LDBU_SP_A0(r); // LDBU r, SP[A0]
1677 else
1678 C67_LDB_SP_A0(r); // LDB r, SP[A0]
1679 } else if (size == 2) {
1680 if (Unsigned)
1681 C67_LDHU_SP_A0(r); // LDHU r, SP[A0]
1682 else
1683 C67_LDH_SP_A0(r); // LDH r, SP[A0]
1684 } else if (size == 4) {
1685 C67_LDW_SP_A0(r); // LDW r, SP[A0]
1686 } else if (size == 8) {
1687 C67_LDDW_SP_A0(r); // LDDW r, SP[A0]
1688 }
1689
1690
1691 C67_NOP(4); // NOP 4
1692 return;
1693 }
1694 } else {
1695 if (v == VT_CONST) {
1696 if (fr & VT_SYM) {
1697 greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched
1698 greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1699 }
1700 C67_MVKL(r, fc); //r=reg to load, constant
1701 C67_MVKH(r, fc); //r=reg to load, constant
1702 } else if (v == VT_LOCAL) {
1703 C67_MVKL(r, fc + 8); //r=reg to load, constant C67 stack points to next free
1704 C67_MVKH(r, fc + 8); //r=reg to load, constant
1705 C67_ADD(C67_FP, r); // MV v,r v -> r
1706 } else if (v == VT_CMP) {
1707 C67_MV(C67_compare_reg, r); // MV v,r v -> r
1708 } else if (v == VT_JMP || v == VT_JMPI) {
1709 t = v & 1;
1710 C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load
1711 C67_MVKL(r, t); // r=reg to load, 0 or 1 (do this while branching)
1712 C67_NOP(4); // NOP 4
1713 gsym(fc); // modifies other branches to branch here
1714 C67_MVKL(r, t ^ 1); // r=reg to load, 0 or 1
1715 } else if (v != r) {
1716 C67_MV(v, r); // MV v,r v -> r
1717
1718 if ((ft & VT_BTYPE) == VT_DOUBLE)
1719 C67_MV(v + 1, r + 1); // MV v,r v -> r
1720 }
1721 }
1722}
1723
1724
1725/* store register 'r' in lvalue 'v' */
1726void store(int r, SValue * v)
1727{
1728 int fr, bt, ft, fc, size, t, element;
1729
1730 ft = v->type.t;
1731 fc = v->c.ul;
1732 fr = v->r & VT_VALMASK;
1733 bt = ft & VT_BTYPE;
1734 /* XXX: incorrect if float reg to reg */
1735
1736 if (bt == VT_LDOUBLE) {
bf374a5f grischka2011-08-11 17:07:56 +02001737 tcc_error("long double not supported");
bf45336a bellard2004-10-05 17:55:18 +00001738 } else {
1739 if (bt == VT_SHORT)
1740 size = 2;
1741 else if (bt == VT_BYTE)
1742 size = 1;
1743 else if (bt == VT_DOUBLE)
1744 size = 8;
1745 else
1746 size = 4;
1747
1748 if ((v->r & VT_VALMASK) == VT_CONST) {
1749 /* constant memory reference */
1750
1751 if (v->r & VT_SYM) {
1752 greloc(cur_text_section, v->sym, ind, R_C60LO16); // rem the inst need to be patched
1753 greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
1754 }
1755 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1756 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1757
1758 if (size == 1)
1759 C67_STB_PTR(r, C67_A0); // STB r, *A0
1760 else if (size == 2)
1761 C67_STH_PTR(r, C67_A0); // STH r, *A0
1762 else if (size == 4 || size == 8)
1763 C67_STW_PTR(r, C67_A0); // STW r, *A0
1764
1765 if (size == 8)
1766 C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1); // STW r, *+A0[1]
1767 } else if ((v->r & VT_VALMASK) == VT_LOCAL) {
1768 // check case of storing to passed argument that
1769 // tcc thinks is on the stack but for C67 is
1770 // passed as a reg. However it may have been
1771 // saved to the stack, if that reg was required
1772 // for a call to a child function
1773
1774 if (fc > 0) // argument ??
1775 {
1776 // walk through sizes and figure which param
1777
1778 int stack_pos = 8;
1779
1780 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1781 if (fc == stack_pos)
1782 break;
1783
1784 stack_pos += TranslateStackToReg[t];
1785 }
1786
1787 // param has been pushed on stack, get it like a local var
1788 fc = ParamLocOnStack[t] - 8;
1789 }
1790
1791 if (size == 8)
1792 element = 4;
1793 else
1794 element = size;
1795
1796 // divide offset in bytes to create word index
1797 C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1798 C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant
1799
1800
1801
1802 if (size == 1)
1803 C67_STB_SP_A0(r); // STB r, SP[A0]
1804 else if (size == 2)
1805 C67_STH_SP_A0(r); // STH r, SP[A0]
1806 else if (size == 4 || size == 8)
1807 C67_STW_SP_A0(r); // STW r, SP[A0]
1808
1809 if (size == 8) {
1810 C67_ADDK(1, C67_A0); // ADDK 1,A0
1811 C67_STW_SP_A0(r + 1); // STW r, SP[A0]
1812 }
1813 } else {
1814 if (size == 1)
1815 C67_STB_PTR(r, fr); // STB r, *fr
1816 else if (size == 2)
1817 C67_STH_PTR(r, fr); // STH r, *fr
1818 else if (size == 4 || size == 8)
1819 C67_STW_PTR(r, fr); // STW r, *fr
1820
1821 if (size == 8) {
1822 C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1]
1823 }
1824 }
1825 }
1826}
1827
1828/* 'is_jmp' is '1' if it is a jump */
1829static void gcall_or_jmp(int is_jmp)
1830{
1831 int r;
1832 Sym *sym;
1833
1834 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1835 /* constant case */
1836 if (vtop->r & VT_SYM) {
1837 /* relocation case */
1838
1839 // get add into A0, then start the jump B3
1840
1841 greloc(cur_text_section, vtop->sym, ind, R_C60LO16); // rem the inst need to be patched
1842 greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
1843
1844 C67_MVKL(C67_A0, 0); //r=reg to load, constant
1845 C67_MVKH(C67_A0, 0); //r=reg to load, constant
1846 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // B.S2x A0
1847
1848 if (is_jmp) {
1849 C67_NOP(5); // simple jump, just put NOP
1850 } else {
1851 // Call, must load return address into B3 during delay slots
1852
1853 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1854 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1855 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1856 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1857 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1858 C67_NOP(3); // put remaining NOPs
1859 }
1860 } else {
1861 /* put an empty PC32 relocation */
1862 ALWAYS_ASSERT(FALSE);
1863 }
1864 } else {
1865 /* otherwise, indirect call */
1866 r = gv(RC_INT);
1867 C67_IREG_B_REG(0, C67_CREG_ZERO, r); // B.S2x r
1868
1869 if (is_jmp) {
1870 C67_NOP(5); // simple jump, just put NOP
1871 } else {
1872 // Call, must load return address into B3 during delay slots
1873
1874 sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0); // symbol for return address
1875 greloc(cur_text_section, sym, ind, R_C60LO16); // rem the inst need to be patched
1876 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1877 C67_MVKL(C67_B3, 0); //r=reg to load, constant
1878 C67_MVKH(C67_B3, 0); //r=reg to load, constant
1879 C67_NOP(3); // put remaining NOPs
1880 }
1881 }
1882}
1883
4e04f67c seyko2015-05-14 07:32:24 +03001884ST_FUNC int regargs_nregs(RegArgs *args)
1885{
1886 return *args;
1887}
1888
dcec8673
TP
Thomas Preud'homme2013-11-22 09:27:15 +08001889/* Return the number of registers needed to return the struct, or 0 if
1890 returning via struct pointer. */
4e04f67c seyko2015-05-14 07:32:24 +03001891ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize, RegArgs *args) {
55ea6d3f James Lyon2013-04-19 00:40:48 +01001892 *ret_align = 1; // Never have to re-align return values for x86-64
4e04f67c seyko2015-05-14 07:32:24 +03001893 *args = 0;
1894
dcec8673 Thomas Preud'homme2013-11-22 09:27:15 +08001895 return 0;
55ea6d3f
JL
James Lyon2013-04-19 00:40:48 +01001896}
1897
bf45336a bellard2004-10-05 17:55:18 +00001898/* generate function call with address in (vtop->t, vtop->c) and free function
1899 context. Stack entry is popped */
1900void gfunc_call(int nb_args)
1901{
6bbfb8f6 bellard2004-11-07 15:43:15 +00001902 int i, r, size = 0;
bf45336a bellard2004-10-05 17:55:18 +00001903 int args_sizes[NoCallArgsPassedOnStack];
1904
1905 if (nb_args > NoCallArgsPassedOnStack) {
bf374a5f grischka2011-08-11 17:07:56 +02001906 tcc_error("more than 10 function params not currently supported");
bf45336a bellard2004-10-05 17:55:18 +00001907 // handle more than 10, put some on the stack
1908 }
1909
1910 for (i = 0; i < nb_args; i++) {
1911 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1912 ALWAYS_ASSERT(FALSE);
bf45336a bellard2004-10-05 17:55:18 +00001913 } else {
1914 /* simple type (currently always same size) */
1915 /* XXX: implicit cast ? */
1916
1917
1918 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
bf374a5f grischka2011-08-11 17:07:56 +02001919 tcc_error("long long not supported");
bf45336a bellard2004-10-05 17:55:18 +00001920 } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
bf374a5f grischka2011-08-11 17:07:56 +02001921 tcc_error("long double not supported");
bf45336a bellard2004-10-05 17:55:18 +00001922 } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1923 size = 8;
1924 } else {
1925 size = 4;
1926 }
1927
1928 // put the parameter into the corresponding reg (pair)
1929
1930 r = gv(RC_C67_A4 << (2 * i));
1931
1932 // must put on stack because with 1 pass compiler , no way to tell
1933 // if an up coming nested call might overwrite these regs
1934
1935 C67_PUSH(r);
1936
1937 if (size == 8) {
1938 C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3); // STW r, *+SP[3] (go back and put the other)
1939 }
1940 args_sizes[i] = size;
1941 }
1942 vtop--;
1943 }
1944 // POP all the params on the stack into registers for the
1945 // immediate call (in reverse order)
1946
1947 for (i = nb_args - 1; i >= 0; i--) {
1948
1949 if (args_sizes[i] == 8)
1950 C67_POP_DW(TREG_C67_A4 + i * 2);
1951 else
1952 C67_POP(TREG_C67_A4 + i * 2);
1953 }
1954 gcall_or_jmp(0);
1955 vtop--;
1956}
1957
1958
1959// to be compatible with Code Composer for the C67
1960// the first 10 parameters must be passed in registers
1961// (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1962// ending with B12:B13.
1963//
1964// When a call is made, if the caller has its parameters
1965// in regs A4-B13 these must be saved before/as the call
1966// parameters are loaded and restored upon return (or if/when needed).
1967
1968/* generate function prolog of type 't' */
1969void gfunc_prolog(CType * func_type)
1970{
1971 int addr, align, size, func_call, i;
1972 Sym *sym;
1973 CType *type;
1974
1975 sym = func_type->ref;
1976 func_call = sym->r;
1977 addr = 8;
1978 /* if the function returns a structure, then add an
1979 implicit pointer parameter */
1980 func_vt = sym->type;
8efaa711 Thomas Preud'homme2014-01-06 22:27:39 +08001981 func_var = (sym->c == FUNC_ELLIPSIS);
bf45336a bellard2004-10-05 17:55:18 +00001982 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1983 func_vc = addr;
1984 addr += 4;
1985 }
1986
1987 NoOfCurFuncArgs = 0;
1988
1989 /* define parameters */
1990 while ((sym = sym->next) != NULL) {
1991 type = &sym->type;
2c657f66 Daniel Glöckner2008-08-20 01:44:12 +02001992 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
bf45336a bellard2004-10-05 17:55:18 +00001993 size = type_size(type, &align);
1994 size = (size + 3) & ~3;
1995
1996 // keep track of size of arguments so
1997 // we can translate where tcc thinks they
1998 // are on the stack into the appropriate reg
1999
2000 TranslateStackToReg[NoOfCurFuncArgs] = size;
2001 NoOfCurFuncArgs++;
2002
2003#ifdef FUNC_STRUCT_PARAM_AS_PTR
2004 /* structs are passed as pointer */
2005 if ((type->t & VT_BTYPE) == VT_STRUCT) {
2006 size = 4;
2007 }
2008#endif
2009 addr += size;
2010 }
2011 func_ret_sub = 0;
2012 /* pascal type call ? */
2013 if (func_call == FUNC_STDCALL)
2014 func_ret_sub = addr - 8;
2015
2016 C67_MV(C67_FP, C67_A0); // move FP -> A0
2017 C67_MV(C67_SP, C67_FP); // move SP -> FP
2018
2019 // place all the args passed in regs onto the stack
2020
2021 loc = 0;
2022 for (i = 0; i < NoOfCurFuncArgs; i++) {
2023
2024 ParamLocOnStack[i] = loc; // remember where the param is
2025 loc += -8;
2026
2027 C67_PUSH(TREG_C67_A4 + i * 2);
2028
2029 if (TranslateStackToReg[i] == 8) {
2030 C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3); // STW r, *+SP[1] (go back and put the other)
2031 }
2032 }
2033
2034 TotalBytesPushedOnStack = -loc;
2035
2036 func_sub_sp_offset = ind; // remember where we put the stack instruction
2037 C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily)
2038
2039 C67_PUSH(C67_A0);
2040 C67_PUSH(C67_B3);
2041}
2042
2043/* generate function epilog */
2044void gfunc_epilog(void)
2045{
2046 {
2047 int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2048 C67_POP(C67_B3);
2049 C67_NOP(4); // NOP wait for load
2050 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3
2051 C67_POP(C67_FP);
2052 C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP
2053 C67_Adjust_ADDK((int *) (cur_text_section->data +
2054 func_sub_sp_offset),
2055 -local + TotalBytesPushedOnStack);
2056 C67_NOP(3); // NOP
2057 }
2058}
2059
2060/* generate a jump to a label */
2061int gjmp(int t)
2062{
2063 int ind1 = ind;
2064
2065 C67_MVKL(C67_A0, t); //r=reg to load, constant
2066 C67_MVKH(C67_A0, t); //r=reg to load, constant
2067 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // [!R] B.S2x A0
2068 C67_NOP(5);
2069 return ind1;
2070}
2071
2072/* generate a jump to a fixed address */
2073void gjmp_addr(int a)
2074{
2075 Sym *sym;
2076 // I guess this routine is used for relative short
2077 // local jumps, for now just handle it as the general
2078 // case
2079
2080 // define a label that will be relocated
2081
2082 sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
2083 greloc(cur_text_section, sym, ind, R_C60LO16);
2084 greloc(cur_text_section, sym, ind + 4, R_C60HI16);
2085
2086 gjmp(0); // place a zero there later the symbol will be added to it
2087}
2088
2089/* generate a test. set 'inv' to invert test. Stack entry is popped */
2090int gtst(int inv, int t)
2091{
2092 int ind1, n;
2093 int v, *p;
2094
2095 v = vtop->r & VT_VALMASK;
2096 if (v == VT_CMP) {
2097 /* fast case : can jump directly since flags are set */
2098 // C67 uses B2 sort of as flags register
2099 ind1 = ind;
2100 C67_MVKL(C67_A0, t); //r=reg to load, constant
2101 C67_MVKH(C67_A0, t); //r=reg to load, constant
2102
2103 if (C67_compare_reg != TREG_EAX && // check if not already in a conditional test reg
2104 C67_compare_reg != TREG_EDX &&
2105 C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
2106 C67_MV(C67_compare_reg, C67_B2);
2107 C67_compare_reg = C67_B2;
2108 }
2109
2110 C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x A0
2111 C67_NOP(5);
2112 t = ind1; //return where we need to patch
2113
2437ccdc seyko2015-03-03 15:51:09 +03002114 } else if (v == VT_JMP || v == VT_JMPI) {
bf45336a bellard2004-10-05 17:55:18 +00002115 /* && or || optimization */
2116 if ((v & 1) == inv) {
2117 /* insert vtop->c jump list in t */
2118 p = &vtop->c.i;
2119
2120 // I guess the idea is to traverse to the
2121 // null at the end of the list and store t
2122 // there
2123
2124 n = *p;
2125 while (n != 0) {
2126 p = (int *) (cur_text_section->data + n);
2127
2128 // extract 32 bit address from MVKH/MVKL
2129 n = ((*p >> 7) & 0xffff);
2130 n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2131 }
2132 *p |= (t & 0xffff) << 7;
2133 *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2134 t = vtop->c.i;
2135
2136 } else {
2137 t = gjmp(t);
2138 gsym(vtop->c.i);
2139 }
bf45336a bellard2004-10-05 17:55:18 +00002140 }
2141 vtop--;
2142 return t;
2143}
2144
2145/* generate an integer binary operation */
2146void gen_opi(int op)
2147{
2148 int r, fr, opc, t;
2149
2150 switch (op) {
2151 case '+':
2152 case TOK_ADDC1: /* add with carry generation */
2153 opc = 0;
2154 gen_op8:
2155
2156
2157// C67 can't do const compares, must load into a reg
2158// so just go to gv2 directly - tktk
2159
2160
2161
2162 if (op >= TOK_ULT && op <= TOK_GT)
2163 gv2(RC_INT_BSIDE, RC_INT); // make sure r (src1) is on the B Side of CPU
2164 else
2165 gv2(RC_INT, RC_INT);
2166
2167 r = vtop[-1].r;
2168 fr = vtop[0].r;
2169
2170 C67_compare_reg = C67_B2;
2171
2172
2173 if (op == TOK_LT) {
2174 C67_CMPLT(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002175 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002176 } else if (op == TOK_GE) {
2177 C67_CMPLT(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002178 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002179 } else if (op == TOK_GT) {
2180 C67_CMPGT(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002181 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002182 } else if (op == TOK_LE) {
2183 C67_CMPGT(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002184 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002185 } else if (op == TOK_EQ) {
2186 C67_CMPEQ(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002187 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002188 } else if (op == TOK_NE) {
2189 C67_CMPEQ(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002190 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002191 } else if (op == TOK_ULT) {
2192 C67_CMPLTU(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002193 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002194 } else if (op == TOK_UGE) {
2195 C67_CMPLTU(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002196 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002197 } else if (op == TOK_UGT) {
2198 C67_CMPGTU(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002199 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002200 } else if (op == TOK_ULE) {
2201 C67_CMPGTU(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002202 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002203 } else if (op == '+')
2204 C67_ADD(fr, r); // ADD r,fr,r
2205 else if (op == '-')
2206 C67_SUB(fr, r); // SUB r,fr,r
2207 else if (op == '&')
2208 C67_AND(fr, r); // AND r,fr,r
2209 else if (op == '|')
2210 C67_OR(fr, r); // OR r,fr,r
2211 else if (op == '^')
2212 C67_XOR(fr, r); // XOR r,fr,r
2213 else
2214 ALWAYS_ASSERT(FALSE);
2215
2216 vtop--;
2217 if (op >= TOK_ULT && op <= TOK_GT) {
2218 vtop->r = VT_CMP;
2219 vtop->c.i = op;
2220 }
2221 break;
2222 case '-':
2223 case TOK_SUBC1: /* sub with carry generation */
2224 opc = 5;
2225 goto gen_op8;
2226 case TOK_ADDC2: /* add with carry use */
2227 opc = 2;
2228 goto gen_op8;
2229 case TOK_SUBC2: /* sub with carry use */
2230 opc = 3;
2231 goto gen_op8;
2232 case '&':
2233 opc = 4;
2234 goto gen_op8;
2235 case '^':
2236 opc = 6;
2237 goto gen_op8;
2238 case '|':
2239 opc = 1;
2240 goto gen_op8;
2241 case '*':
2242 case TOK_UMULL:
2243 gv2(RC_INT, RC_INT);
2244 r = vtop[-1].r;
2245 fr = vtop[0].r;
2246 vtop--;
2247 C67_MPYI(fr, r); // 32 bit bultiply fr,r,fr
2248 C67_NOP(8); // NOP 8 for worst case
2249 break;
2250 case TOK_SHL:
2251 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2252 r = vtop[-1].r;
2253 fr = vtop[0].r;
2254 vtop--;
2255 C67_SHL(fr, r); // arithmetic/logical shift
2256 break;
2257
2258 case TOK_SHR:
2259 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2260 r = vtop[-1].r;
2261 fr = vtop[0].r;
2262 vtop--;
2263 C67_SHRU(fr, r); // logical shift
2264 break;
2265
2266 case TOK_SAR:
2267 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2268 r = vtop[-1].r;
2269 fr = vtop[0].r;
2270 vtop--;
2271 C67_SHR(fr, r); // arithmetic shift
2272 break;
2273
2274 case '/':
ec7d3632 bellard2004-10-05 22:33:55 +00002275 t = TOK__divi;
bf45336a bellard2004-10-05 17:55:18 +00002276 call_func:
2277 vswap();
2278 /* call generic idiv function */
2279 vpush_global_sym(&func_old_type, t);
2280 vrott(3);
2281 gfunc_call(2);
2282 vpushi(0);
2283 vtop->r = REG_IRET;
2284 vtop->r2 = VT_CONST;
2285 break;
2286 case TOK_UDIV:
2287 case TOK_PDIV:
ec7d3632 bellard2004-10-05 22:33:55 +00002288 t = TOK__divu;
bf45336a bellard2004-10-05 17:55:18 +00002289 goto call_func;
2290 case '%':
ec7d3632 bellard2004-10-05 22:33:55 +00002291 t = TOK__remi;
bf45336a bellard2004-10-05 17:55:18 +00002292 goto call_func;
2293 case TOK_UMOD:
ec7d3632 bellard2004-10-05 22:33:55 +00002294 t = TOK__remu;
bf45336a bellard2004-10-05 17:55:18 +00002295 goto call_func;
2296
2297 default:
2298 opc = 7;
2299 goto gen_op8;
2300 }
2301}
2302
2303/* generate a floating point operation 'v = t1 op t2' instruction. The
2304 two operands are guaranted to have the same floating point type */
2305/* XXX: need to use ST1 too */
2306void gen_opf(int op)
2307{
2308 int ft, fc, fr, r;
2309
2310 if (op >= TOK_ULT && op <= TOK_GT)
2311 gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
2312 else
2313 gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
2314
2315 ft = vtop->type.t;
2316 fc = vtop->c.ul;
2317 r = vtop->r;
2318 fr = vtop[-1].r;
2319
2320
2321 if ((ft & VT_BTYPE) == VT_LDOUBLE)
bf374a5f grischka2011-08-11 17:07:56 +02002322 tcc_error("long doubles not supported");
bf45336a bellard2004-10-05 17:55:18 +00002323
2324 if (op >= TOK_ULT && op <= TOK_GT) {
2325
2326 r = vtop[-1].r;
2327 fr = vtop[0].r;
2328
2329 C67_compare_reg = C67_B2;
2330
2331 if (op == TOK_LT) {
2332 if ((ft & VT_BTYPE) == VT_DOUBLE)
2333 C67_CMPLTDP(r, fr, C67_B2);
2334 else
2335 C67_CMPLTSP(r, fr, C67_B2);
2336
263dc93c grischka2013-02-04 15:10:08 +01002337 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002338 } else if (op == TOK_GE) {
2339 if ((ft & VT_BTYPE) == VT_DOUBLE)
2340 C67_CMPLTDP(r, fr, C67_B2);
2341 else
2342 C67_CMPLTSP(r, fr, C67_B2);
2343
263dc93c grischka2013-02-04 15:10:08 +01002344 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002345 } else if (op == TOK_GT) {
2346 if ((ft & VT_BTYPE) == VT_DOUBLE)
2347 C67_CMPGTDP(r, fr, C67_B2);
2348 else
2349 C67_CMPGTSP(r, fr, C67_B2);
2350
263dc93c grischka2013-02-04 15:10:08 +01002351 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002352 } else if (op == TOK_LE) {
2353 if ((ft & VT_BTYPE) == VT_DOUBLE)
2354 C67_CMPGTDP(r, fr, C67_B2);
2355 else
2356 C67_CMPGTSP(r, fr, C67_B2);
2357
263dc93c grischka2013-02-04 15:10:08 +01002358 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002359 } else if (op == TOK_EQ) {
2360 if ((ft & VT_BTYPE) == VT_DOUBLE)
2361 C67_CMPEQDP(r, fr, C67_B2);
2362 else
2363 C67_CMPEQSP(r, fr, C67_B2);
2364
263dc93c grischka2013-02-04 15:10:08 +01002365 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002366 } else if (op == TOK_NE) {
2367 if ((ft & VT_BTYPE) == VT_DOUBLE)
2368 C67_CMPEQDP(r, fr, C67_B2);
2369 else
2370 C67_CMPEQSP(r, fr, C67_B2);
2371
263dc93c grischka2013-02-04 15:10:08 +01002372 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002373 } else {
2374 ALWAYS_ASSERT(FALSE);
2375 }
2376 vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2
2377 } else {
2378 if (op == '+') {
2379 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2380 C67_ADDDP(r, fr); // ADD fr,r,fr
2381 C67_NOP(6);
2382 } else {
2383 C67_ADDSP(r, fr); // ADD fr,r,fr
2384 C67_NOP(3);
2385 }
2386 vtop--;
2387 } else if (op == '-') {
2388 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2389 C67_SUBDP(r, fr); // SUB fr,r,fr
2390 C67_NOP(6);
2391 } else {
2392 C67_SUBSP(r, fr); // SUB fr,r,fr
2393 C67_NOP(3);
2394 }
2395 vtop--;
2396 } else if (op == '*') {
2397 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2398 C67_MPYDP(r, fr); // MPY fr,r,fr
2399 C67_NOP(9);
2400 } else {
2401 C67_MPYSP(r, fr); // MPY fr,r,fr
2402 C67_NOP(3);
2403 }
2404 vtop--;
2405 } else if (op == '/') {
2406 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2407 // must call intrinsic DP floating point divide
2408 vswap();
2409 /* call generic idiv function */
ec7d3632 bellard2004-10-05 22:33:55 +00002410 vpush_global_sym(&func_old_type, TOK__divd);
bf45336a bellard2004-10-05 17:55:18 +00002411 vrott(3);
2412 gfunc_call(2);
2413 vpushi(0);
2414 vtop->r = REG_FRET;
2415 vtop->r2 = REG_LRET;
2416
2417 } else {
2418 // must call intrinsic SP floating point divide
2419 vswap();
2420 /* call generic idiv function */
ec7d3632 bellard2004-10-05 22:33:55 +00002421 vpush_global_sym(&func_old_type, TOK__divf);
bf45336a bellard2004-10-05 17:55:18 +00002422 vrott(3);
2423 gfunc_call(2);
2424 vpushi(0);
2425 vtop->r = REG_FRET;
2426 vtop->r2 = VT_CONST;
2427 }
2428 } else
2429 ALWAYS_ASSERT(FALSE);
2430
2431
2432 }
2433}
2434
2435
2436/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2437 and 'long long' cases. */
2438void gen_cvt_itof(int t)
2439{
2440 int r;
2441
2442 gv(RC_INT);
2443 r = vtop->r;
2444
2445 if ((t & VT_BTYPE) == VT_DOUBLE) {
2446 if (t & VT_UNSIGNED)
2447 C67_INTDPU(r, r);
2448 else
2449 C67_INTDP(r, r);
2450
2451 C67_NOP(4);
2452 vtop->type.t = VT_DOUBLE;
2453 } else {
2454 if (t & VT_UNSIGNED)
2455 C67_INTSPU(r, r);
2456 else
2457 C67_INTSP(r, r);
2458 C67_NOP(3);
2459 vtop->type.t = VT_FLOAT;
2460 }
2461
2462}
2463
2464/* convert fp to int 't' type */
2465/* XXX: handle long long case */
2466void gen_cvt_ftoi(int t)
2467{
2468 int r;
2469
2470 gv(RC_FLOAT);
2471 r = vtop->r;
2472
2473 if (t != VT_INT)
bf374a5f grischka2011-08-11 17:07:56 +02002474 tcc_error("long long not supported");
bf45336a bellard2004-10-05 17:55:18 +00002475 else {
2476 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2477 C67_DPTRUNC(r, r);
2478 C67_NOP(3);
2479 } else {
2480 C67_SPTRUNC(r, r);
2481 C67_NOP(3);
2482 }
2483
2484 vtop->type.t = VT_INT;
2485
2486 }
2487}
2488
2489/* convert from one floating point type to another */
2490void gen_cvt_ftof(int t)
2491{
2492 int r, r2;
2493
2494 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2495 (t & VT_BTYPE) == VT_FLOAT) {
2496 // convert double to float
2497
2498 gv(RC_FLOAT); // get it in a register pair
2499
2500 r = vtop->r;
2501
2502 C67_DPSP(r, r); // convert it to SP same register
2503 C67_NOP(3);
2504
2505 vtop->type.t = VT_FLOAT;
2506 vtop->r2 = VT_CONST; // set this as unused
2507 } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
2508 (t & VT_BTYPE) == VT_DOUBLE) {
2509 // convert float to double
2510
2511 gv(RC_FLOAT); // get it in a register
2512
2513 r = vtop->r;
2514
6bbfb8f6 bellard2004-11-07 15:43:15 +00002515 if (r == TREG_EAX) { // make sure the paired reg is avail
bf45336a bellard2004-10-05 17:55:18 +00002516 r2 = get_reg(RC_ECX);
6bbfb8f6 bellard2004-11-07 15:43:15 +00002517 } else if (r == TREG_EDX) {
bf45336a bellard2004-10-05 17:55:18 +00002518 r2 = get_reg(RC_ST0);
6bbfb8f6 bellard2004-11-07 15:43:15 +00002519 } else {
bf45336a bellard2004-10-05 17:55:18 +00002520 ALWAYS_ASSERT(FALSE);
6bbfb8f6 bellard2004-11-07 15:43:15 +00002521 r2 = 0; /* avoid warning */
2522 }
bf45336a bellard2004-10-05 17:55:18 +00002523
2524 C67_SPDP(r, r); // convert it to DP same register
2525 C67_NOP(1);
2526
2527 vtop->type.t = VT_DOUBLE;
2528 vtop->r2 = r2; // set this as unused
2529 } else {
2530 ALWAYS_ASSERT(FALSE);
2531 }
2532}
2533
2534/* computed goto support */
2535void ggoto(void)
2536{
2537 gcall_or_jmp(1);
2538 vtop--;
2539}
2540
41b3c7a5
JL
James Lyon2013-04-27 20:39:34 +01002541/* Save the stack pointer onto the stack and return the location of its address */
2542ST_FUNC void gen_vla_sp_save(int addr) {
2543 tcc_error("variable length arrays unsupported for this target");
2544}
2545
2546/* Restore the SP from a location on the stack */
2547ST_FUNC void gen_vla_sp_restore(int addr) {
2548 tcc_error("variable length arrays unsupported for this target");
2549}
2550
2551/* Subtract from the stack pointer, and push the resulting value onto the stack */
2552ST_FUNC void gen_vla_alloc(CType *type, int align) {
2553 tcc_error("variable length arrays unsupported for this target");
2554}
2555
88a3ccab grischka2009-12-20 01:53:49 +01002556/* end of C67 code generator */
2557/*************************************************************/
2558#endif
bf45336a bellard2004-10-05 17:55:18 +00002559/*************************************************************/