Adding two more people to the RELICENSING file.
[tinycc.git] / c67-gen.c
Commit [+]AuthorDateLineData
bf45336a bellard2004-10-05 17:55:18 +00001/*
2 * TMS320C67xx code generator for TCC
89ad24e7 gus knight2015-07-29 16:53:57 -04003 *
bf45336a bellard2004-10-05 17:55:18 +00004 * 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
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). */
7f5b95ea gus knight2015-07-29 09:54:03 -040031#define RC_INT 0x0001 /* generic integer register */
32#define RC_FLOAT 0x0002 /* generic float register */
bf45336a bellard2004-10-05 17:55:18 +000033#define RC_EAX 0x0004
34#define RC_ST0 0x0008
35#define RC_ECX 0x0010
36#define RC_EDX 0x0020
7f5b95ea gus knight2015-07-29 09:54:03 -040037#define RC_INT_BSIDE 0x00000040 /* generic integer register on b side */
bf45336a bellard2004-10-05 17:55:18 +000038#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 */
61
62/* pretty names for the registers */
63enum {
64 TREG_EAX = 0, // really A2
65 TREG_ECX, // really A3
66 TREG_EDX, // really B0
67 TREG_ST0, // really B1
68 TREG_C67_A4,
69 TREG_C67_A5,
70 TREG_C67_B4,
71 TREG_C67_B5,
72 TREG_C67_A6,
73 TREG_C67_A7,
74 TREG_C67_B6,
75 TREG_C67_B7,
76 TREG_C67_A8,
77 TREG_C67_A9,
78 TREG_C67_B8,
79 TREG_C67_B9,
80 TREG_C67_A10,
81 TREG_C67_A11,
82 TREG_C67_B10,
83 TREG_C67_B11,
84 TREG_C67_A12,
85 TREG_C67_A13,
86 TREG_C67_B12,
87 TREG_C67_B13,
88};
89
bf45336a bellard2004-10-05 17:55:18 +000090/* 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 */
94
bf45336a bellard2004-10-05 17:55:18 +000095/* defined if function parameters must be evaluated in reverse order */
0bdbd49e Urs Janssen2013-02-17 00:48:51 +010096/* #define INVERT_FUNC_PARAMS */
bf45336a bellard2004-10-05 17:55:18 +000097
98/* defined if structures are passed as pointers. Otherwise structures
99 are directly pushed on stack. */
0bdbd49e Urs Janssen2013-02-17 00:48:51 +0100100/* #define FUNC_STRUCT_PARAM_AS_PTR */
bf45336a bellard2004-10-05 17:55:18 +0000101
102/* pointer size, in bytes */
103#define PTR_SIZE 4
104
105/* long double size and alignment, in bytes */
106#define LDOUBLE_SIZE 12
107#define LDOUBLE_ALIGN 4
108/* maximum alignment (for aligned attribute support) */
109#define MAX_ALIGN 8
110
111/******************************************************/
112/* ELF defines */
113
114#define EM_TCC_TARGET EM_C60
115
116/* relocation type for 32 bit data relocation */
117#define R_DATA_32 R_C60_32
5dadff3d Shinichiro Hamaji2009-07-19 06:42:23 +0900118#define R_DATA_PTR R_C60_32
bf45336a bellard2004-10-05 17:55:18 +0000119#define R_JMP_SLOT R_C60_JMP_SLOT
120#define R_COPY R_C60_COPY
121
122#define ELF_START_ADDR 0x00000400
123#define ELF_PAGE_SIZE 0x1000
124
125/******************************************************/
88a3ccab grischka2009-12-20 01:53:49 +0100126#else /* ! TARGET_DEFS_ONLY */
127/******************************************************/
89ad24e7 gus knight2015-07-29 16:53:57 -0400128#include "tcc.h"
88a3ccab grischka2009-12-20 01:53:49 +0100129
130ST_DATA const int reg_classes[NB_REGS] = {
89ad24e7 gus knight2015-07-29 16:53:57 -0400131 /* eax */ RC_INT | RC_FLOAT | RC_EAX,
88a3ccab grischka2009-12-20 01:53:49 +0100132 // 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,
137 /* A4 */ RC_C67_A4,
138 /* A5 */ RC_C67_A5,
139 /* B4 */ RC_C67_B4,
140 /* B5 */ RC_C67_B5,
141 /* A6 */ RC_C67_A6,
142 /* A7 */ RC_C67_A7,
143 /* B6 */ RC_C67_B6,
144 /* B7 */ RC_C67_B7,
145 /* A8 */ RC_C67_A8,
146 /* A9 */ RC_C67_A9,
147 /* B8 */ RC_C67_B8,
148 /* B9 */ RC_C67_B9,
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,
156 /* B13 */ RC_C67_B11
157};
158
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
89ad24e7 gus knight2015-07-29 16:53:57 -0400162// the stack offsets so we can translate to the appropriate
88a3ccab grischka2009-12-20 01:53:49 +0100163// reg (pair)
164
165#define NoCallArgsPassedOnStack 10
166int NoOfCurFuncArgs;
167int TranslateStackToReg[NoCallArgsPassedOnStack];
168int ParamLocOnStack[NoCallArgsPassedOnStack];
169int TotalBytesPushedOnStack;
bf45336a bellard2004-10-05 17:55:18 +0000170
263dc93c grischka2013-02-04 15:10:08 +0100171#ifndef FALSE
172# define FALSE 0
173# define TRUE 1
174#endif
175
176#undef BOOL
177#define BOOL int
178
d6d7686b grischka2013-02-08 19:07:11 +0100179#define ALWAYS_ASSERT(x) \
180do {\
181 if (!(x))\
182 tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
183} while (0)
184
88a3ccab grischka2009-12-20 01:53:49 +0100185/******************************************************/
bf45336a bellard2004-10-05 17:55:18 +0000186static unsigned long func_sub_sp_offset;
187static int func_ret_sub;
188
bf45336a bellard2004-10-05 17:55:18 +0000189static BOOL C67_invert_test;
190static int C67_compare_reg;
191
192#ifdef ASSEMBLY_LISTING_C67
193FILE *f = NULL;
194#endif
195
bf45336a bellard2004-10-05 17:55:18 +0000196void C67_g(int c)
197{
198 int ind1;
199
200#ifdef ASSEMBLY_LISTING_C67
201 fprintf(f, " %08X", c);
202#endif
203 ind1 = ind + 4;
204 if (ind1 > (int) cur_text_section->data_allocated)
89ad24e7 gus knight2015-07-29 16:53:57 -0400205 section_realloc(cur_text_section, ind1);
bf45336a bellard2004-10-05 17:55:18 +0000206 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;
210 ind = ind1;
211}
212
213
214/* output a symbol and patch all calls to it */
215void gsym_addr(int t, int a)
216{
217 int n, *ptr;
218 while (t) {
89ad24e7 gus knight2015-07-29 16:53:57 -0400219 ptr = (int *) (cur_text_section->data + t);
220 {
221 Sym *sym;
bf45336a bellard2004-10-05 17:55:18 +0000222
89ad24e7 gus knight2015-07-29 16:53:57 -0400223 // extract 32 bit address from MVKH/MVKL
224 n = ((*ptr >> 7) & 0xffff);
225 n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
bf45336a bellard2004-10-05 17:55:18 +0000226
89ad24e7 gus knight2015-07-29 16:53:57 -0400227 // define a label that will be relocated
bf45336a bellard2004-10-05 17:55:18 +0000228
89ad24e7 gus knight2015-07-29 16:53:57 -0400229 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);
bf45336a bellard2004-10-05 17:55:18 +0000232
89ad24e7 gus knight2015-07-29 16:53:57 -0400233 // clear out where the pointer was
bf45336a bellard2004-10-05 17:55:18 +0000234
89ad24e7 gus knight2015-07-29 16:53:57 -0400235 *ptr &= ~(0xffff << 7);
236 *(ptr + 1) &= ~(0xffff << 7);
237 }
238 t = n;
bf45336a bellard2004-10-05 17:55:18 +0000239 }
240}
241
242void gsym(int t)
243{
244 gsym_addr(t, ind);
245}
246
89ad24e7 gus knight2015-07-29 16:53:57 -0400247// these are regs that tcc doesn't really know about,
3e9a7e9d
VL
Vincent Lefevre2014-04-07 13:31:00 +0200248// but assign them unique values so the mapping routines
249// can distinguish them
bf45336a bellard2004-10-05 17:55:18 +0000250
251#define C67_A0 105
252#define C67_SP 106
253#define C67_B3 107
254#define C67_FP 108
255#define C67_B2 109
0bdbd49e Urs Janssen2013-02-17 00:48:51 +0100256#define C67_CREG_ZERO -1 /* Special code for no condition reg test */
bf45336a bellard2004-10-05 17:55:18 +0000257
258
259int ConvertRegToRegClass(int r)
260{
261 // only works for A4-B13
262
263 return RC_C67_A4 << (r - TREG_C67_A4);
264}
265
266
267// map TCC reg to C67 reg number
268
269int C67_map_regn(int r)
270{
271 if (r == 0) // normal tcc regs
272 return 0x2; // A2
273 else if (r == 1) // normal tcc regs
274 return 3; // A3
275 else if (r == 2) // normal tcc regs
276 return 0; // B0
277 else if (r == 3) // normal tcc regs
278 return 1; // B1
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
293 else
294 ALWAYS_ASSERT(FALSE);
295
296 return 0;
297}
298
89ad24e7 gus knight2015-07-29 16:53:57 -0400299// mapping from tcc reg number to
bf45336a bellard2004-10-05 17:55:18 +0000300// C67 register to condition code field
301//
302// valid condition code regs are:
303//
304// tcc reg 2 ->B0 -> 1
305// tcc reg 3 ->B1 -> 2
306// tcc reg 0 -> A2 -> 5
307// tcc reg 1 -> A3 -> X
308// tcc reg B2 -> 3
309
310int C67_map_regc(int r)
311{
312 if (r == 0) // normal tcc regs
313 return 0x5;
314 else if (r == 2) // normal tcc regs
315 return 0x1;
316 else if (r == 3) // normal tcc regs
317 return 0x2;
318 else if (r == C67_B2) // normal tcc regs
319 return 0x3;
320 else if (r == C67_CREG_ZERO)
321 return 0; // Special code for no condition reg test
322 else
323 ALWAYS_ASSERT(FALSE);
324
325 return 0;
326}
327
328
329// map TCC reg to C67 reg side A or B
330
331int C67_map_regs(int r)
332{
333 if (r == 0) // normal tcc regs
334 return 0x0;
335 else if (r == 1) // normal tcc regs
336 return 0x0;
337 else if (r == 2) // normal tcc regs
338 return 0x1;
339 else if (r == 3) // normal tcc regs
340 return 0x1;
341 else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs
342 return (r & 2) >> 1;
343 else if (r == C67_A0)
89ad24e7 gus knight2015-07-29 16:53:57 -0400344 return 0; // set to A side
bf45336a bellard2004-10-05 17:55:18 +0000345 else if (r == C67_B2)
89ad24e7 gus knight2015-07-29 16:53:57 -0400346 return 1; // set to B side
bf45336a bellard2004-10-05 17:55:18 +0000347 else if (r == C67_B3)
348 return 1; // set to B side
349 else if (r == C67_SP)
89ad24e7 gus knight2015-07-29 16:53:57 -0400350 return 0x1; // set to SP (B15) B side
bf45336a bellard2004-10-05 17:55:18 +0000351 else if (r == C67_FP)
89ad24e7 gus knight2015-07-29 16:53:57 -0400352 return 0x0; // set to FP (A15) A side
bf45336a bellard2004-10-05 17:55:18 +0000353 else
354 ALWAYS_ASSERT(FALSE);
355
356 return 0;
357}
358
359int C67_map_S12(char *s)
360{
361 if (strstr(s, ".S1") != NULL)
362 return 0;
363 else if (strcmp(s, ".S2"))
364 return 1;
365 else
366 ALWAYS_ASSERT(FALSE);
367
368 return 0;
369}
370
371int C67_map_D12(char *s)
372{
373 if (strstr(s, ".D1") != NULL)
374 return 0;
375 else if (strcmp(s, ".D2"))
376 return 1;
377 else
378 ALWAYS_ASSERT(FALSE);
379
380 return 0;
381}
382
383
384
385void C67_asm(char *s, int a, int b, int c)
386{
387 BOOL xpath;
388
389#ifdef ASSEMBLY_LISTING_C67
390 if (!f) {
391 f = fopen("TCC67_out.txt", "wt");
392 }
393 fprintf(f, "%04X ", ind);
394#endif
395
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
411 (1 << 2) | //opcode
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
89ad24e7 gus knight2015-07-29 16:53:57 -0400421 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000422 (1 << 2) | //opcode
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
433 (1 << 2) | //opcode
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
89ad24e7 gus knight2015-07-29 16:53:57 -0400443 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000444 (1 << 2) | //opcode
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
455 (1 << 2) | //opcode
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
89ad24e7 gus knight2015-07-29 16:53:57 -0400465 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000466 (1 << 2) | //opcode
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
472 (0 << 13) | //cst5
473 (1 << 9) | //mode 1 = pos cst offset
474 (0 << 8) | //r (LDDW bit 0)
475 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
89ad24e7 gus knight2015-07-29 16:53:57 -0400476 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000477 (1 << 2) | //opcode
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
483 (0 << 13) | //cst5
484 (1 << 9) | //mode 1 = pos cst offset
485 (0 << 8) | //r (LDDW bit 0)
486 (C67_map_regs(b) << 7) | //y D1/D2 base reg side
89ad24e7 gus knight2015-07-29 16:53:57 -0400487 (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000488 (1 << 2) | //opcode
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
494 (0 << 13) | //cst5
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
89ad24e7 gus knight2015-07-29 16:53:57 -0400498 (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000499 (1 << 2) | //opcode
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
506 (c << 13) | //cst5
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
89ad24e7 gus knight2015-07-29 16:53:57 -0400510 (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000511 (1 << 2) | //opcode
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
522 (1 << 2) | //opcode
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
533 (1 << 2) | //opcode
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
544 (1 << 2) | //opcode
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
555 (1 << 2) | //opcode
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
566 (1 << 2) | //opcode
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
577 (1 << 2) | //opcode
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
588 (1 << 2) | //opcode
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
599 (1 << 2) | //opcode
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
605 (0 << 13) | //cst5
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
610 (1 << 2) | //opcode
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
616 (0 << 13) | //cst5
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
621 (1 << 2) | //opcode
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
627 (0 << 13) | //cst5
628 (1 << 9) | //mode 1 = pos cst offset
629 (0 << 8) | //r (LDDW bit 0)
630 (C67_map_regs(a) << 7) | //y D1/D2 src side
631 (4 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
632 (1 << 2) | //opcode
633 (C67_map_regs(b) << 1) | //side of dst
634 (0 << 0)); //parallel
635 } else if (strstr(s, "LDB.D *") == s) {
636 C67_g((C67_map_regn(b) << 23) | //dst
637 (C67_map_regn(a) << 18) | //base reg A15
638 (0 << 13) | //cst5
639 (1 << 9) | //mode 1 = pos cst offset
640 (0 << 8) | //r (LDDW bit 0)
641 (C67_map_regs(a) << 7) | //y D1/D2 src side
89ad24e7 gus knight2015-07-29 16:53:57 -0400642 (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000643 (1 << 2) | //opcode
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
649 (0 << 13) | //cst5
650 (1 << 9) | //mode 1 = pos cst offset
651 (0 << 8) | //r (LDDW bit 0)
652 (C67_map_regs(a) << 7) | //y D1/D2 src side
89ad24e7 gus knight2015-07-29 16:53:57 -0400653 (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000654 (1 << 2) | //opcode
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
660 (0 << 13) | //cst5
661 (1 << 9) | //mode 1 = pos cst offset
662 (0 << 8) | //r (LDDW bit 0)
663 (C67_map_regs(a) << 7) | //y D1/D2 src side
664 (1 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
665 (1 << 2) | //opcode
666 (C67_map_regs(b) << 1) | //side of dst
667 (0 << 0)); //parallel
668 } else if (strstr(s, "LDW.D +*") == s) {
669 C67_g((C67_map_regn(b) << 23) | //dst
670 (C67_map_regn(a) << 18) | //base reg A15
671 (1 << 13) | //cst5
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
89ad24e7 gus knight2015-07-29 16:53:57 -0400675 (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
bf45336a bellard2004-10-05 17:55:18 +0000676 (1 << 2) | //opcode
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));
682
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));
694
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));
706
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
715 }
716
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));
720
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));
732
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));
744
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));
756
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));
768
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));
780
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));
792
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));
804
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
815 (0 << 28) | //z
816 (a << 7) | //cnst
817 (0x4 << 2) | //opcode fixed
818 (0 << 1) | //S0/S1
819 (0 << 0)); //parallel
820 } else if (strstr(s, "B.") == s) {
821 xpath = C67_map_regs(c) ^ 1;
822
823 C67_g((C67_map_regc(b) << 29) | //creg
824 (a << 28) | //inv
825 (0 << 23) | //dst
826 (C67_map_regn(c) << 18) | //src2
827 (0 << 13) | //
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);
835
836 C67_g((0 << 29) | //creg
837 (0 << 28) | //inv
838 (C67_map_regn(c) << 23) | //dst
839 (C67_map_regn(b) << 18) | //src2
840 (0 << 13) | //src1 (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);
848
849 C67_g((0 << 29) | //creg
850 (0 << 28) | //inv
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);
861
862 C67_g((0 << 29) | //creg
863 (0 << 28) | //inv
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);
874
875 C67_g((0 << 29) | //creg
876 (0 << 28) | //inv
877 (C67_map_regn(c) << 23) | //dst
89ad24e7 gus knight2015-07-29 16:53:57 -0400878 (C67_map_regn(b) << 18) | //src2
bf45336a bellard2004-10-05 17:55:18 +0000879 (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);
887
888 C67_g((0 << 29) | //creg
889 (0 << 28) | //inv
890 (C67_map_regn(c) << 23) | //dst
89ad24e7 gus knight2015-07-29 16:53:57 -0400891 (C67_map_regn(b) << 18) | //src2
bf45336a bellard2004-10-05 17:55:18 +0000892 (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);
900
901 C67_g((0 << 29) | //creg
902 (0 << 28) | //inv
903 (C67_map_regn(c) << 23) | //dst
89ad24e7 gus knight2015-07-29 16:53:57 -0400904 (C67_map_regn(b) << 18) | //src2
bf45336a bellard2004-10-05 17:55:18 +0000905 (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);
913
914 C67_g((0 << 29) | //creg
915 (0 << 28) | //inv
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);
926
927 C67_g((0 << 29) | //creg
928 (0 << 28) | //inv
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));
939
940 C67_g((0 << 29) | //creg
941 (0 << 28) | //inv
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);
952
953 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
954
955 C67_g((0 << 29) | //creg
956 (0 << 28) | //inv
957 (C67_map_regn(c) << 23) | //dst
958 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -0400959 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +0000960 (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);
967
968 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
969
970 C67_g((0 << 29) | //creg
971 (0 << 28) | //inv
972 (C67_map_regn(c) << 23) | //dst
973 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -0400974 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +0000975 (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);
982
983 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
984
985 C67_g((0 << 29) | //creg
986 (0 << 28) | //inv
987 (C67_map_regn(c) << 23) | //dst
988 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -0400989 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +0000990 (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);
997
998 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
999
1000 C67_g((0 << 29) | //creg
1001 (0 << 28) | //inv
1002 (C67_map_regn(c) << 23) | //dst
1003 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -04001004 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001005 (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);
1012
1013 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1014
1015 C67_g((0 << 29) | //creg
1016 (0 << 28) | //inv
1017 (C67_map_regn(c) << 23) | //dst
1018 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -04001019 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001020 (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);
1027
1028 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1029
1030 C67_g((0 << 29) | //creg
1031 (0 << 28) | //inv
1032 (C67_map_regn(c) << 23) | //dst
1033 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -04001034 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001035 (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);
1042
1043 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1044
1045 C67_g((0 << 29) | //creg
1046 (0 << 28) | //inv
1047 (C67_map_regn(c) << 23) | //dst
1048 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -04001049 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001050 (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);
1057
1058 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1059
1060 C67_g((0 << 29) | //creg
1061 (0 << 28) | //inv
1062 (C67_map_regn(c) << 23) | //dst
1063 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -04001064 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001065 (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);
1072
1073 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1074
1075 C67_g((0 << 29) | //creg
1076 (0 << 28) | //inv
1077 (C67_map_regn(c) << 23) | //dst
1078 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -04001079 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001080 (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);
1087
1088 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1089
1090 C67_g((0 << 29) | //creg
1091 (0 << 28) | //inv
1092 (C67_map_regn(c) << 23) | //dst
1093 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -04001094 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001095 (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);
1102
1103 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1104
1105 C67_g((0 << 29) | //creg
1106 (0 << 28) | //inv
1107 (C67_map_regn(c) << 23) | //dst
1108 (C67_map_regn(b) << 18) | //src2 (possible x path)
89ad24e7 gus knight2015-07-29 16:53:57 -04001109 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001110 (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);
1117
1118 ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1119
1120 C67_g((0 << 29) | //creg
1121 (0 << 28) | //inv
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);
1132
1133 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1134
1135 C67_g((0 << 29) | //creg
1136 (0 << 28) | //inv
1137 (C67_map_regn(c) << 23) | //dst
1138 (C67_map_regn(b) << 18) | //src2
89ad24e7 gus knight2015-07-29 16:53:57 -04001139 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001140 (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);
1147
1148 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1149
1150 C67_g((0 << 29) | //creg
1151 (0 << 28) | //inv
1152 (C67_map_regn(c) << 23) | //dst
1153 (C67_map_regn(b) << 18) | //src2
89ad24e7 gus knight2015-07-29 16:53:57 -04001154 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001155 (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);
1162
1163 ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1164
1165 C67_g((0 << 29) | //creg
1166 (0 << 28) | //inv
1167 (C67_map_regn(c) << 23) | //dst
1168 (C67_map_regn(b) << 18) | //src2
89ad24e7 gus knight2015-07-29 16:53:57 -04001169 (C67_map_regn(a) << 13) | //src1
bf45336a bellard2004-10-05 17:55:18 +00001170 (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
1177
1178 C67_g((0 << 29) | //creg
1179 (0 << 28) | //inv
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
1187
1188 C67_g((0 << 29) | //creg
1189 (0 << 28) | //inv
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
1198 } else
1199 ALWAYS_ASSERT(FALSE);
1200
1201#ifdef ASSEMBLY_LISTING_C67
1202 fprintf(f, " %s %d %d %d\n", s, a, b, c);
1203#endif
1204
1205}
1206
1207//r=reg to load, fr=from reg, symbol for relocation, constant
1208
1209void C67_MVKL(int r, int fc)
1210{
1211 C67_asm("MVKL.", fc, r, 0);
1212}
1213
1214void C67_MVKH(int r, int fc)
1215{
1216 C67_asm("MVKH.", fc, r, 0);
1217}
1218
1219void C67_STB_SP_A0(int r)
1220{
1221 C67_asm("STB.D *+SP[A0]", r, 0, 0); // STB r,*+SP[A0]
1222}
1223
1224void C67_STH_SP_A0(int r)
1225{
1226 C67_asm("STH.D *+SP[A0]", r, 0, 0); // STH r,*+SP[A0]
1227}
1228
1229void C67_STW_SP_A0(int r)
1230{
1231 C67_asm("STW.D *+SP[A0]", r, 0, 0); // STW r,*+SP[A0]
1232}
1233
1234void C67_STB_PTR(int r, int r2)
1235{
1236 C67_asm("STB.D *", r, r2, 0); // STB r, *r2
1237}
1238
1239void C67_STH_PTR(int r, int r2)
1240{
1241 C67_asm("STH.D *", r, r2, 0); // STH r, *r2
1242}
1243
1244void C67_STW_PTR(int r, int r2)
1245{
1246 C67_asm("STW.D *", r, r2, 0); // STW r, *r2
1247}
1248
1249void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1250{
1251 C67_asm("STW.D +*", r, r2, n); // STW r, *+r2
1252}
1253
1254void C67_PUSH(int r)
1255{
1256 C67_asm("STW.D SP POST DEC", r, 0, 0); // STW r,*SP--
1257}
1258
1259void C67_LDW_SP_A0(int r)
1260{
1261 C67_asm("LDW.D *+SP[A0]", r, 0, 0); // LDW *+SP[A0],r
1262}
1263
1264void C67_LDDW_SP_A0(int r)
1265{
1266 C67_asm("LDDW.D *+SP[A0]", r, 0, 0); // LDDW *+SP[A0],r
1267}
1268
1269void C67_LDH_SP_A0(int r)
1270{
1271 C67_asm("LDH.D *+SP[A0]", r, 0, 0); // LDH *+SP[A0],r
1272}
1273
1274void C67_LDB_SP_A0(int r)
1275{
1276 C67_asm("LDB.D *+SP[A0]", r, 0, 0); // LDB *+SP[A0],r
1277}
1278
1279void C67_LDHU_SP_A0(int r)
1280{
1281 C67_asm("LDHU.D *+SP[A0]", r, 0, 0); // LDHU *+SP[A0],r
1282}
1283
1284void C67_LDBU_SP_A0(int r)
1285{
1286 C67_asm("LDBU.D *+SP[A0]", r, 0, 0); // LDBU *+SP[A0],r
1287}
1288
1289void C67_LDW_PTR(int r, int r2)
1290{
1291 C67_asm("LDW.D *", r, r2, 0); // LDW *r,r2
1292}
1293
1294void C67_LDDW_PTR(int r, int r2)
1295{
1296 C67_asm("LDDW.D *", r, r2, 0); // LDDW *r,r2
1297}
1298
1299void C67_LDH_PTR(int r, int r2)
1300{
1301 C67_asm("LDH.D *", r, r2, 0); // LDH *r,r2
1302}
1303
1304void C67_LDB_PTR(int r, int r2)
1305{
1306 C67_asm("LDB.D *", r, r2, 0); // LDB *r,r2
1307}
1308
1309void C67_LDHU_PTR(int r, int r2)
1310{
1311 C67_asm("LDHU.D *", r, r2, 0); // LDHU *r,r2
1312}
1313
1314void C67_LDBU_PTR(int r, int r2)
1315{
1316 C67_asm("LDBU.D *", r, r2, 0); // LDBU *r,r2
1317}
1318
1319void C67_LDW_PTR_PRE_INC(int r, int r2)
1320{
1321 C67_asm("LDW.D +*", r, r2, 0); // LDW *+r,r2
1322}
1323
1324void C67_POP(int r)
1325{
1326 C67_asm("LDW.D SP PRE INC", r, 0, 0); // LDW *++SP,r
1327}
1328
1329void C67_POP_DW(int r)
1330{
1331 C67_asm("LDDW.D SP PRE INC", r, 0, 0); // LDDW *++SP,r
1332}
1333
1334void C67_CMPLT(int s1, int s2, int dst)
1335{
1336 C67_asm("CMPLT.L1", s1, s2, dst);
1337}
1338
1339void C67_CMPGT(int s1, int s2, int dst)
1340{
1341 C67_asm("CMPGT.L1", s1, s2, dst);
1342}
1343
1344void C67_CMPEQ(int s1, int s2, int dst)
1345{
1346 C67_asm("CMPEQ.L1", s1, s2, dst);
1347}
1348
1349void C67_CMPLTU(int s1, int s2, int dst)
1350{
1351 C67_asm("CMPLTU.L1", s1, s2, dst);
1352}
1353
1354void C67_CMPGTU(int s1, int s2, int dst)
1355{
1356 C67_asm("CMPGTU.L1", s1, s2, dst);
1357}
1358
1359
1360void C67_CMPLTSP(int s1, int s2, int dst)
1361{
1362 C67_asm("CMPLTSP.S1", s1, s2, dst);
1363}
1364
1365void C67_CMPGTSP(int s1, int s2, int dst)
1366{
1367 C67_asm("CMPGTSP.S1", s1, s2, dst);
1368}
1369
1370void C67_CMPEQSP(int s1, int s2, int dst)
1371{
1372 C67_asm("CMPEQSP.S1", s1, s2, dst);
1373}
1374
1375void C67_CMPLTDP(int s1, int s2, int dst)
1376{
1377 C67_asm("CMPLTDP.S1", s1, s2, dst);
1378}
1379
1380void C67_CMPGTDP(int s1, int s2, int dst)
1381{
1382 C67_asm("CMPGTDP.S1", s1, s2, dst);
1383}
1384
1385void C67_CMPEQDP(int s1, int s2, int dst)
1386{
1387 C67_asm("CMPEQDP.S1", s1, s2, dst);
1388}
1389
1390
1391void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2
1392{
1393 C67_asm("B.S2", inv, r1, r2);
1394}
1395
1396
1397// call with how many 32 bit words to skip
1398// (0 would branch to the branch instruction)
1399
1400void C67_B_DISP(int disp) // B +2 Branch with constant displacement
1401{
1402 // Branch point is relative to the 8 word fetch packet
1403 //
1404 // we will assume the text section always starts on an 8 word (32 byte boundary)
1405 //
1406 // so add in how many words into the fetch packet the branch is
1407
1408
1409 C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1410}
1411
1412void C67_NOP(int n)
1413{
1414 C67_asm("NOP", n, 0, 0);
1415}
1416
1417void C67_ADDK(int n, int r)
1418{
1419 ALWAYS_ASSERT(abs(n) < 32767);
1420
1421 C67_asm("ADDK", n, r, 0);
1422}
1423
1424void C67_ADDK_PARALLEL(int n, int r)
1425{
1426 ALWAYS_ASSERT(abs(n) < 32767);
1427
1428 C67_asm("||ADDK", n, r, 0);
1429}
1430
1431void C67_Adjust_ADDK(int *inst, int n)
1432{
1433 ALWAYS_ASSERT(abs(n) < 32767);
1434
1435 *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1436}
1437
1438void C67_MV(int r, int v)
1439{
1440 C67_asm("MV.L", 0, r, v);
1441}
1442
1443
1444void C67_DPTRUNC(int r, int v)
1445{
1446 C67_asm("DPTRUNC.L", 0, r, v);
1447}
1448
1449void C67_SPTRUNC(int r, int v)
1450{
1451 C67_asm("SPTRUNC.L", 0, r, v);
1452}
1453
1454void C67_INTSP(int r, int v)
1455{
1456 C67_asm("INTSP.L", 0, r, v);
1457}
1458
1459void C67_INTDP(int r, int v)
1460{
1461 C67_asm("INTDP.L", 0, r, v);
1462}
1463
1464void C67_INTSPU(int r, int v)
1465{
1466 C67_asm("INTSPU.L", 0, r, v);
1467}
1468
1469void C67_INTDPU(int r, int v)
1470{
1471 C67_asm("INTDPU.L", 0, r, v);
1472}
1473
1474void C67_SPDP(int r, int v)
1475{
1476 C67_asm("SPDP.L", 0, r, v);
1477}
1478
1479void C67_DPSP(int r, int v) // note regs must be on the same side
1480{
1481 C67_asm("DPSP.L", 0, r, v);
1482}
1483
1484void C67_ADD(int r, int v)
1485{
1486 C67_asm("ADD.L", v, r, v);
1487}
1488
1489void C67_SUB(int r, int v)
1490{
1491 C67_asm("SUB.L", v, r, v);
1492}
1493
1494void C67_AND(int r, int v)
1495{
1496 C67_asm("AND.L", v, r, v);
1497}
1498
1499void C67_OR(int r, int v)
1500{
1501 C67_asm("OR.L", v, r, v);
1502}
1503
1504void C67_XOR(int r, int v)
1505{
1506 C67_asm("XOR.L", v, r, v);
1507}
1508
1509void C67_ADDSP(int r, int v)
1510{
1511 C67_asm("ADDSP.L", v, r, v);
1512}
1513
1514void C67_SUBSP(int r, int v)
1515{
1516 C67_asm("SUBSP.L", v, r, v);
1517}
1518
1519void C67_MPYSP(int r, int v)
1520{
1521 C67_asm("MPYSP.M", v, r, v);
1522}
1523
1524void C67_ADDDP(int r, int v)
1525{
1526 C67_asm("ADDDP.L", v, r, v);
1527}
1528
1529void C67_SUBDP(int r, int v)
1530{
1531 C67_asm("SUBDP.L", v, r, v);
1532}
1533
1534void C67_MPYDP(int r, int v)
1535{
1536 C67_asm("MPYDP.M", v, r, v);
1537}
1538
1539void C67_MPYI(int r, int v)
1540{
1541 C67_asm("MPYI.M", v, r, v);
1542}
1543
1544void C67_SHL(int r, int v)
1545{
1546 C67_asm("SHL.S", r, v, v);
1547}
1548
1549void C67_SHRU(int r, int v)
1550{
1551 C67_asm("SHRU.S", r, v, v);
1552}
1553
1554void C67_SHR(int r, int v)
1555{
1556 C67_asm("SHR.S", r, v, v);
1557}
1558
1559
1560
1561/* load 'r' from value 'sv' */
1562void load(int r, SValue * sv)
1563{
6bbfb8f6 bellard2004-11-07 15:43:15 +00001564 int v, t, ft, fc, fr, size = 0, element;
263dc93c grischka2013-02-04 15:10:08 +01001565 BOOL Unsigned = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00001566 SValue v1;
1567
1568 fr = sv->r;
1569 ft = sv->type.t;
1570 fc = sv->c.ul;
1571
1572 v = fr & VT_VALMASK;
1573 if (fr & VT_LVAL) {
1574 if (v == VT_LLOCAL) {
1575 v1.type.t = VT_INT;
1576 v1.r = VT_LOCAL | VT_LVAL;
1577 v1.c.ul = fc;
1578 load(r, &v1);
1579 fr = r;
1580 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
bf374a5f grischka2011-08-11 17:07:56 +02001581 tcc_error("long double not supported");
bf45336a bellard2004-10-05 17:55:18 +00001582 } else if ((ft & VT_TYPE) == VT_BYTE) {
1583 size = 1;
1584 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1585 size = 1;
1586 Unsigned = TRUE;
1587 } else if ((ft & VT_TYPE) == VT_SHORT) {
1588 size = 2;
1589 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1590 size = 2;
1591 Unsigned = TRUE;
1592 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1593 size = 8;
1594 } else {
1595 size = 4;
1596 }
1597
89ad24e7 gus knight2015-07-29 16:53:57 -04001598 // check if fc is a positive reference on the stack,
bf45336a bellard2004-10-05 17:55:18 +00001599 // 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.
1601
1602
1603 if (v == VT_LOCAL && fc > 0) {
1604 int stack_pos = 8;
1605
1606 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1607 if (fc == stack_pos)
1608 break;
1609
1610 stack_pos += TranslateStackToReg[t];
1611 }
1612
1613 // param has been pushed on stack, get it like a local var
1614
1615 fc = ParamLocOnStack[t] - 8;
1616 }
1617
1618 if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect
1619 {
1620 if (size == 1) {
1621 if (Unsigned)
1622 C67_LDBU_PTR(v, r); // LDBU *v,r
1623 else
1624 C67_LDB_PTR(v, r); // LDB *v,r
1625 } else if (size == 2) {
1626 if (Unsigned)
1627 C67_LDHU_PTR(v, r); // LDHU *v,r
1628 else
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
1634 }
1635
1636 C67_NOP(4); // NOP 4
1637 return;
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);
1641
1642
1643 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1644 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1645
1646
1647 if (size == 1) {
1648 if (Unsigned)
1649 C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r
1650 else
1651 C67_LDB_PTR(C67_A0, r); // LDB *A0,r
1652 } else if (size == 2) {
1653 if (Unsigned)
1654 C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r
1655 else
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
1661 }
1662
1663 C67_NOP(4); // NOP 4
1664 return;
1665 } else {
1666 element = size;
1667
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
1671
1672 if (size == 1) {
1673 if (Unsigned)
1674 C67_LDBU_SP_A0(r); // LDBU r, SP[A0]
1675 else
1676 C67_LDB_SP_A0(r); // LDB r, SP[A0]
1677 } else if (size == 2) {
1678 if (Unsigned)
1679 C67_LDHU_SP_A0(r); // LDHU r, SP[A0]
1680 else
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]
1686 }
1687
1688
1689 C67_NOP(4); // NOP 4
1690 return;
1691 }
1692 } else {
1693 if (v == VT_CONST) {
1694 if (fr & VT_SYM) {
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);
1697 }
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) {
1707 t = v & 1;
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
1715
1716 if ((ft & VT_BTYPE) == VT_DOUBLE)
1717 C67_MV(v + 1, r + 1); // MV v,r v -> r
1718 }
1719 }
1720}
1721
1722
1723/* store register 'r' in lvalue 'v' */
1724void store(int r, SValue * v)
1725{
1726 int fr, bt, ft, fc, size, t, element;
1727
1728 ft = v->type.t;
1729 fc = v->c.ul;
1730 fr = v->r & VT_VALMASK;
1731 bt = ft & VT_BTYPE;
1732 /* XXX: incorrect if float reg to reg */
1733
1734 if (bt == VT_LDOUBLE) {
bf374a5f grischka2011-08-11 17:07:56 +02001735 tcc_error("long double not supported");
bf45336a bellard2004-10-05 17:55:18 +00001736 } else {
1737 if (bt == VT_SHORT)
1738 size = 2;
1739 else if (bt == VT_BYTE)
1740 size = 1;
1741 else if (bt == VT_DOUBLE)
1742 size = 8;
1743 else
1744 size = 4;
1745
1746 if ((v->r & VT_VALMASK) == VT_CONST) {
1747 /* constant memory reference */
1748
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);
1752 }
1753 C67_MVKL(C67_A0, fc); //r=reg to load, constant
1754 C67_MVKH(C67_A0, fc); //r=reg to load, constant
1755
1756 if (size == 1)
1757 C67_STB_PTR(r, C67_A0); // STB r, *A0
1758 else if (size == 2)
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
1762
1763 if (size == 8)
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
1771
1772 if (fc > 0) // argument ??
1773 {
1774 // walk through sizes and figure which param
1775
1776 int stack_pos = 8;
1777
1778 for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1779 if (fc == stack_pos)
1780 break;
1781
1782 stack_pos += TranslateStackToReg[t];
1783 }
1784
1785 // param has been pushed on stack, get it like a local var
1786 fc = ParamLocOnStack[t] - 8;
1787 }
1788
1789 if (size == 8)
1790 element = 4;
1791 else
1792 element = size;
1793
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
1797
1798
1799
1800 if (size == 1)
1801 C67_STB_SP_A0(r); // STB r, SP[A0]
1802 else if (size == 2)
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]
1806
1807 if (size == 8) {
1808 C67_ADDK(1, C67_A0); // ADDK 1,A0
1809 C67_STW_SP_A0(r + 1); // STW r, SP[A0]
1810 }
1811 } else {
1812 if (size == 1)
1813 C67_STB_PTR(r, fr); // STB r, *fr
1814 else if (size == 2)
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
1818
1819 if (size == 8) {
1820 C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1]
1821 }
1822 }
1823 }
1824}
1825
1826/* 'is_jmp' is '1' if it is a jump */
1827static void gcall_or_jmp(int is_jmp)
1828{
1829 int r;
1830 Sym *sym;
1831
1832 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1833 /* constant case */
1834 if (vtop->r & VT_SYM) {
1835 /* relocation case */
1836
1837 // get add into A0, then start the jump B3
1838
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);
1841
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
1845
1846 if (is_jmp) {
1847 C67_NOP(5); // simple jump, just put NOP
1848 } else {
1849 // Call, must load return address into B3 during delay slots
1850
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
1857 }
1858 } else {
1859 /* put an empty PC32 relocation */
1860 ALWAYS_ASSERT(FALSE);
1861 }
1862 } else {
1863 /* otherwise, indirect call */
1864 r = gv(RC_INT);
1865 C67_IREG_B_REG(0, C67_CREG_ZERO, r); // B.S2x r
1866
1867 if (is_jmp) {
1868 C67_NOP(5); // simple jump, just put NOP
1869 } else {
1870 // Call, must load return address into B3 during delay slots
1871
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
1878 }
1879 }
1880}
1881
dcec8673
TP
Thomas Preud'homme2013-11-22 09:27:15 +08001882/* Return the number of registers needed to return the struct, or 0 if
1883 returning via struct pointer. */
ef3d38c5 gus knight2015-07-29 16:57:41 -04001884ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
55ea6d3f James Lyon2013-04-19 00:40:48 +01001885 *ret_align = 1; // Never have to re-align return values for x86-64
dcec8673 Thomas Preud'homme2013-11-22 09:27:15 +08001886 return 0;
55ea6d3f
JL
James Lyon2013-04-19 00:40:48 +01001887}
1888
bf45336a bellard2004-10-05 17:55:18 +00001889/* generate function call with address in (vtop->t, vtop->c) and free function
1890 context. Stack entry is popped */
1891void gfunc_call(int nb_args)
1892{
6bbfb8f6 bellard2004-11-07 15:43:15 +00001893 int i, r, size = 0;
bf45336a bellard2004-10-05 17:55:18 +00001894 int args_sizes[NoCallArgsPassedOnStack];
1895
1896 if (nb_args > NoCallArgsPassedOnStack) {
bf374a5f grischka2011-08-11 17:07:56 +02001897 tcc_error("more than 10 function params not currently supported");
bf45336a bellard2004-10-05 17:55:18 +00001898 // handle more than 10, put some on the stack
1899 }
1900
1901 for (i = 0; i < nb_args; i++) {
1902 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1903 ALWAYS_ASSERT(FALSE);
bf45336a bellard2004-10-05 17:55:18 +00001904 } else {
1905 /* simple type (currently always same size) */
1906 /* XXX: implicit cast ? */
1907
1908
1909 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
bf374a5f grischka2011-08-11 17:07:56 +02001910 tcc_error("long long not supported");
bf45336a bellard2004-10-05 17:55:18 +00001911 } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
bf374a5f grischka2011-08-11 17:07:56 +02001912 tcc_error("long double not supported");
bf45336a bellard2004-10-05 17:55:18 +00001913 } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1914 size = 8;
1915 } else {
1916 size = 4;
1917 }
1918
1919 // put the parameter into the corresponding reg (pair)
1920
1921 r = gv(RC_C67_A4 << (2 * i));
1922
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
1925
1926 C67_PUSH(r);
1927
1928 if (size == 8) {
1929 C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3); // STW r, *+SP[3] (go back and put the other)
1930 }
1931 args_sizes[i] = size;
1932 }
1933 vtop--;
1934 }
1935 // POP all the params on the stack into registers for the
1936 // immediate call (in reverse order)
1937
1938 for (i = nb_args - 1; i >= 0; i--) {
1939
1940 if (args_sizes[i] == 8)
1941 C67_POP_DW(TREG_C67_A4 + i * 2);
1942 else
1943 C67_POP(TREG_C67_A4 + i * 2);
1944 }
1945 gcall_or_jmp(0);
1946 vtop--;
1947}
1948
1949
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.
1954//
1955// When a call is made, if the caller has its parameters
89ad24e7 gus knight2015-07-29 16:53:57 -04001956// in regs A4-B13 these must be saved before/as the call
bf45336a bellard2004-10-05 17:55:18 +00001957// parameters are loaded and restored upon return (or if/when needed).
1958
1959/* generate function prolog of type 't' */
1960void gfunc_prolog(CType * func_type)
1961{
1962 int addr, align, size, func_call, i;
1963 Sym *sym;
1964 CType *type;
1965
1966 sym = func_type->ref;
1967 func_call = sym->r;
1968 addr = 8;
1969 /* if the function returns a structure, then add an
1970 implicit pointer parameter */
1971 func_vt = sym->type;
8efaa711 Thomas Preud'homme2014-01-06 22:27:39 +08001972 func_var = (sym->c == FUNC_ELLIPSIS);
bf45336a bellard2004-10-05 17:55:18 +00001973 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1974 func_vc = addr;
1975 addr += 4;
1976 }
1977
1978 NoOfCurFuncArgs = 0;
1979
1980 /* define parameters */
1981 while ((sym = sym->next) != NULL) {
1982 type = &sym->type;
2c657f66 Daniel Glöckner2008-08-20 01:44:12 +02001983 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
bf45336a bellard2004-10-05 17:55:18 +00001984 size = type_size(type, &align);
1985 size = (size + 3) & ~3;
1986
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
1990
1991 TranslateStackToReg[NoOfCurFuncArgs] = size;
1992 NoOfCurFuncArgs++;
1993
1994#ifdef FUNC_STRUCT_PARAM_AS_PTR
1995 /* structs are passed as pointer */
1996 if ((type->t & VT_BTYPE) == VT_STRUCT) {
1997 size = 4;
1998 }
1999#endif
2000 addr += size;
2001 }
2002 func_ret_sub = 0;
2003 /* pascal type call ? */
2004 if (func_call == FUNC_STDCALL)
2005 func_ret_sub = addr - 8;
2006
2007 C67_MV(C67_FP, C67_A0); // move FP -> A0
2008 C67_MV(C67_SP, C67_FP); // move SP -> FP
2009
2010 // place all the args passed in regs onto the stack
2011
2012 loc = 0;
2013 for (i = 0; i < NoOfCurFuncArgs; i++) {
2014
2015 ParamLocOnStack[i] = loc; // remember where the param is
2016 loc += -8;
2017
2018 C67_PUSH(TREG_C67_A4 + i * 2);
2019
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)
2022 }
2023 }
2024
2025 TotalBytesPushedOnStack = -loc;
2026
89ad24e7 gus knight2015-07-29 16:53:57 -04002027 func_sub_sp_offset = ind; // remember where we put the stack instruction
bf45336a bellard2004-10-05 17:55:18 +00002028 C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily)
2029
2030 C67_PUSH(C67_A0);
2031 C67_PUSH(C67_B3);
2032}
2033
2034/* generate function epilog */
2035void gfunc_epilog(void)
2036{
2037 {
2038 int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
2039 C67_POP(C67_B3);
2040 C67_NOP(4); // NOP wait for load
2041 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3
2042 C67_POP(C67_FP);
89ad24e7 gus knight2015-07-29 16:53:57 -04002043 C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP
bf45336a bellard2004-10-05 17:55:18 +00002044 C67_Adjust_ADDK((int *) (cur_text_section->data +
2045 func_sub_sp_offset),
2046 -local + TotalBytesPushedOnStack);
89ad24e7 gus knight2015-07-29 16:53:57 -04002047 C67_NOP(3); // NOP
bf45336a bellard2004-10-05 17:55:18 +00002048 }
2049}
2050
2051/* generate a jump to a label */
2052int gjmp(int t)
2053{
2054 int ind1 = ind;
2055
2056 C67_MVKL(C67_A0, t); //r=reg to load, constant
2057 C67_MVKH(C67_A0, t); //r=reg to load, constant
2058 C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0); // [!R] B.S2x A0
2059 C67_NOP(5);
2060 return ind1;
2061}
2062
2063/* generate a jump to a fixed address */
2064void gjmp_addr(int a)
2065{
2066 Sym *sym;
2067 // I guess this routine is used for relative short
2068 // local jumps, for now just handle it as the general
2069 // case
2070
2071 // define a label that will be relocated
2072
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);
2076
2077 gjmp(0); // place a zero there later the symbol will be added to it
2078}
2079
2080/* generate a test. set 'inv' to invert test. Stack entry is popped */
2081int gtst(int inv, int t)
2082{
2083 int ind1, n;
2084 int v, *p;
2085
2086 v = vtop->r & VT_VALMASK;
2087 if (v == VT_CMP) {
2088 /* fast case : can jump directly since flags are set */
2089 // C67 uses B2 sort of as flags register
2090 ind1 = ind;
2091 C67_MVKL(C67_A0, t); //r=reg to load, constant
2092 C67_MVKH(C67_A0, t); //r=reg to load, constant
2093
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;
2099 }
2100
2101 C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0); // [!R] B.S2x A0
2102 C67_NOP(5);
2103 t = ind1; //return where we need to patch
2104
2437ccdc seyko2015-03-03 15:51:09 +03002105 } else if (v == VT_JMP || v == VT_JMPI) {
bf45336a bellard2004-10-05 17:55:18 +00002106 /* && or || optimization */
2107 if ((v & 1) == inv) {
2108 /* insert vtop->c jump list in t */
2109 p = &vtop->c.i;
2110
2111 // I guess the idea is to traverse to the
2112 // null at the end of the list and store t
2113 // there
2114
2115 n = *p;
2116 while (n != 0) {
2117 p = (int *) (cur_text_section->data + n);
2118
2119 // extract 32 bit address from MVKH/MVKL
2120 n = ((*p >> 7) & 0xffff);
2121 n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2122 }
2123 *p |= (t & 0xffff) << 7;
2124 *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2125 t = vtop->c.i;
2126
2127 } else {
2128 t = gjmp(t);
2129 gsym(vtop->c.i);
2130 }
bf45336a bellard2004-10-05 17:55:18 +00002131 }
2132 vtop--;
2133 return t;
2134}
2135
2136/* generate an integer binary operation */
2137void gen_opi(int op)
2138{
2139 int r, fr, opc, t;
2140
2141 switch (op) {
2142 case '+':
2143 case TOK_ADDC1: /* add with carry generation */
2144 opc = 0;
2145 gen_op8:
2146
2147
2148// C67 can't do const compares, must load into a reg
2149// so just go to gv2 directly - tktk
2150
2151
2152
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
2155 else
2156 gv2(RC_INT, RC_INT);
2157
2158 r = vtop[-1].r;
2159 fr = vtop[0].r;
2160
2161 C67_compare_reg = C67_B2;
2162
2163
2164 if (op == TOK_LT) {
2165 C67_CMPLT(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002166 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002167 } else if (op == TOK_GE) {
2168 C67_CMPLT(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002169 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002170 } else if (op == TOK_GT) {
2171 C67_CMPGT(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002172 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002173 } else if (op == TOK_LE) {
2174 C67_CMPGT(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002175 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002176 } else if (op == TOK_EQ) {
2177 C67_CMPEQ(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002178 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002179 } else if (op == TOK_NE) {
2180 C67_CMPEQ(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002181 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002182 } else if (op == TOK_ULT) {
2183 C67_CMPLTU(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002184 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002185 } else if (op == TOK_UGE) {
2186 C67_CMPLTU(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002187 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002188 } else if (op == TOK_UGT) {
2189 C67_CMPGTU(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002190 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002191 } else if (op == TOK_ULE) {
2192 C67_CMPGTU(r, fr, C67_B2);
263dc93c grischka2013-02-04 15:10:08 +01002193 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002194 } else if (op == '+')
2195 C67_ADD(fr, r); // ADD r,fr,r
2196 else if (op == '-')
2197 C67_SUB(fr, r); // SUB r,fr,r
2198 else if (op == '&')
2199 C67_AND(fr, r); // AND r,fr,r
2200 else if (op == '|')
2201 C67_OR(fr, r); // OR r,fr,r
2202 else if (op == '^')
2203 C67_XOR(fr, r); // XOR r,fr,r
2204 else
2205 ALWAYS_ASSERT(FALSE);
2206
2207 vtop--;
2208 if (op >= TOK_ULT && op <= TOK_GT) {
2209 vtop->r = VT_CMP;
2210 vtop->c.i = op;
2211 }
2212 break;
2213 case '-':
2214 case TOK_SUBC1: /* sub with carry generation */
2215 opc = 5;
2216 goto gen_op8;
2217 case TOK_ADDC2: /* add with carry use */
2218 opc = 2;
2219 goto gen_op8;
2220 case TOK_SUBC2: /* sub with carry use */
2221 opc = 3;
2222 goto gen_op8;
2223 case '&':
2224 opc = 4;
2225 goto gen_op8;
2226 case '^':
2227 opc = 6;
2228 goto gen_op8;
2229 case '|':
2230 opc = 1;
2231 goto gen_op8;
2232 case '*':
2233 case TOK_UMULL:
2234 gv2(RC_INT, RC_INT);
2235 r = vtop[-1].r;
2236 fr = vtop[0].r;
2237 vtop--;
2238 C67_MPYI(fr, r); // 32 bit bultiply fr,r,fr
2239 C67_NOP(8); // NOP 8 for worst case
2240 break;
2241 case TOK_SHL:
2242 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2243 r = vtop[-1].r;
2244 fr = vtop[0].r;
2245 vtop--;
2246 C67_SHL(fr, r); // arithmetic/logical shift
2247 break;
2248
2249 case TOK_SHR:
2250 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2251 r = vtop[-1].r;
2252 fr = vtop[0].r;
2253 vtop--;
2254 C67_SHRU(fr, r); // logical shift
2255 break;
2256
2257 case TOK_SAR:
2258 gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
2259 r = vtop[-1].r;
2260 fr = vtop[0].r;
2261 vtop--;
2262 C67_SHR(fr, r); // arithmetic shift
2263 break;
2264
2265 case '/':
ec7d3632 bellard2004-10-05 22:33:55 +00002266 t = TOK__divi;
bf45336a bellard2004-10-05 17:55:18 +00002267 call_func:
2268 vswap();
2269 /* call generic idiv function */
2270 vpush_global_sym(&func_old_type, t);
2271 vrott(3);
2272 gfunc_call(2);
2273 vpushi(0);
2274 vtop->r = REG_IRET;
2275 vtop->r2 = VT_CONST;
2276 break;
2277 case TOK_UDIV:
2278 case TOK_PDIV:
ec7d3632 bellard2004-10-05 22:33:55 +00002279 t = TOK__divu;
bf45336a bellard2004-10-05 17:55:18 +00002280 goto call_func;
2281 case '%':
ec7d3632 bellard2004-10-05 22:33:55 +00002282 t = TOK__remi;
bf45336a bellard2004-10-05 17:55:18 +00002283 goto call_func;
2284 case TOK_UMOD:
ec7d3632 bellard2004-10-05 22:33:55 +00002285 t = TOK__remu;
bf45336a bellard2004-10-05 17:55:18 +00002286 goto call_func;
2287
2288 default:
2289 opc = 7;
2290 goto gen_op8;
2291 }
2292}
2293
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 */
2297void gen_opf(int op)
2298{
2299 int ft, fc, fr, r;
2300
2301 if (op >= TOK_ULT && op <= TOK_GT)
2302 gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
2303 else
2304 gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
2305
2306 ft = vtop->type.t;
2307 fc = vtop->c.ul;
2308 r = vtop->r;
2309 fr = vtop[-1].r;
2310
2311
2312 if ((ft & VT_BTYPE) == VT_LDOUBLE)
bf374a5f grischka2011-08-11 17:07:56 +02002313 tcc_error("long doubles not supported");
bf45336a bellard2004-10-05 17:55:18 +00002314
2315 if (op >= TOK_ULT && op <= TOK_GT) {
2316
2317 r = vtop[-1].r;
2318 fr = vtop[0].r;
2319
2320 C67_compare_reg = C67_B2;
2321
2322 if (op == TOK_LT) {
2323 if ((ft & VT_BTYPE) == VT_DOUBLE)
2324 C67_CMPLTDP(r, fr, C67_B2);
2325 else
2326 C67_CMPLTSP(r, fr, C67_B2);
2327
263dc93c grischka2013-02-04 15:10:08 +01002328 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002329 } else if (op == TOK_GE) {
2330 if ((ft & VT_BTYPE) == VT_DOUBLE)
2331 C67_CMPLTDP(r, fr, C67_B2);
2332 else
2333 C67_CMPLTSP(r, fr, C67_B2);
2334
263dc93c grischka2013-02-04 15:10:08 +01002335 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002336 } else if (op == TOK_GT) {
2337 if ((ft & VT_BTYPE) == VT_DOUBLE)
2338 C67_CMPGTDP(r, fr, C67_B2);
2339 else
2340 C67_CMPGTSP(r, fr, C67_B2);
2341
263dc93c grischka2013-02-04 15:10:08 +01002342 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002343 } else if (op == TOK_LE) {
2344 if ((ft & VT_BTYPE) == VT_DOUBLE)
2345 C67_CMPGTDP(r, fr, C67_B2);
2346 else
2347 C67_CMPGTSP(r, fr, C67_B2);
2348
263dc93c grischka2013-02-04 15:10:08 +01002349 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002350 } else if (op == TOK_EQ) {
2351 if ((ft & VT_BTYPE) == VT_DOUBLE)
2352 C67_CMPEQDP(r, fr, C67_B2);
2353 else
2354 C67_CMPEQSP(r, fr, C67_B2);
2355
263dc93c grischka2013-02-04 15:10:08 +01002356 C67_invert_test = FALSE;
bf45336a bellard2004-10-05 17:55:18 +00002357 } else if (op == TOK_NE) {
2358 if ((ft & VT_BTYPE) == VT_DOUBLE)
2359 C67_CMPEQDP(r, fr, C67_B2);
2360 else
2361 C67_CMPEQSP(r, fr, C67_B2);
2362
263dc93c grischka2013-02-04 15:10:08 +01002363 C67_invert_test = TRUE;
bf45336a bellard2004-10-05 17:55:18 +00002364 } else {
2365 ALWAYS_ASSERT(FALSE);
2366 }
2367 vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2
2368 } else {
2369 if (op == '+') {
2370 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2371 C67_ADDDP(r, fr); // ADD fr,r,fr
2372 C67_NOP(6);
2373 } else {
2374 C67_ADDSP(r, fr); // ADD fr,r,fr
2375 C67_NOP(3);
2376 }
2377 vtop--;
2378 } else if (op == '-') {
2379 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2380 C67_SUBDP(r, fr); // SUB fr,r,fr
2381 C67_NOP(6);
2382 } else {
2383 C67_SUBSP(r, fr); // SUB fr,r,fr
2384 C67_NOP(3);
2385 }
2386 vtop--;
2387 } else if (op == '*') {
2388 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2389 C67_MPYDP(r, fr); // MPY fr,r,fr
2390 C67_NOP(9);
2391 } else {
2392 C67_MPYSP(r, fr); // MPY fr,r,fr
2393 C67_NOP(3);
2394 }
2395 vtop--;
2396 } else if (op == '/') {
2397 if ((ft & VT_BTYPE) == VT_DOUBLE) {
2398 // must call intrinsic DP floating point divide
2399 vswap();
2400 /* call generic idiv function */
ec7d3632 bellard2004-10-05 22:33:55 +00002401 vpush_global_sym(&func_old_type, TOK__divd);
bf45336a bellard2004-10-05 17:55:18 +00002402 vrott(3);
2403 gfunc_call(2);
2404 vpushi(0);
2405 vtop->r = REG_FRET;
2406 vtop->r2 = REG_LRET;
2407
2408 } else {
2409 // must call intrinsic SP floating point divide
2410 vswap();
2411 /* call generic idiv function */
ec7d3632 bellard2004-10-05 22:33:55 +00002412 vpush_global_sym(&func_old_type, TOK__divf);
bf45336a bellard2004-10-05 17:55:18 +00002413 vrott(3);
2414 gfunc_call(2);
2415 vpushi(0);
2416 vtop->r = REG_FRET;
2417 vtop->r2 = VT_CONST;
2418 }
2419 } else
2420 ALWAYS_ASSERT(FALSE);
2421
2422
2423 }
2424}
2425
2426
2427/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2428 and 'long long' cases. */
2429void gen_cvt_itof(int t)
2430{
2431 int r;
2432
2433 gv(RC_INT);
2434 r = vtop->r;
2435
2436 if ((t & VT_BTYPE) == VT_DOUBLE) {
2437 if (t & VT_UNSIGNED)
2438 C67_INTDPU(r, r);
2439 else
2440 C67_INTDP(r, r);
2441
2442 C67_NOP(4);
2443 vtop->type.t = VT_DOUBLE;
2444 } else {
2445 if (t & VT_UNSIGNED)
2446 C67_INTSPU(r, r);
2447 else
2448 C67_INTSP(r, r);
2449 C67_NOP(3);
2450 vtop->type.t = VT_FLOAT;
2451 }
2452
2453}
2454
2455/* convert fp to int 't' type */
2456/* XXX: handle long long case */
2457void gen_cvt_ftoi(int t)
2458{
2459 int r;
2460
2461 gv(RC_FLOAT);
2462 r = vtop->r;
2463
2464 if (t != VT_INT)
bf374a5f grischka2011-08-11 17:07:56 +02002465 tcc_error("long long not supported");
bf45336a bellard2004-10-05 17:55:18 +00002466 else {
2467 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2468 C67_DPTRUNC(r, r);
2469 C67_NOP(3);
2470 } else {
2471 C67_SPTRUNC(r, r);
2472 C67_NOP(3);
2473 }
2474
2475 vtop->type.t = VT_INT;
2476
2477 }
2478}
2479
2480/* convert from one floating point type to another */
2481void gen_cvt_ftof(int t)
2482{
2483 int r, r2;
2484
2485 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2486 (t & VT_BTYPE) == VT_FLOAT) {
2487 // convert double to float
2488
2489 gv(RC_FLOAT); // get it in a register pair
2490
2491 r = vtop->r;
2492
2493 C67_DPSP(r, r); // convert it to SP same register
2494 C67_NOP(3);
2495
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
2501
2502 gv(RC_FLOAT); // get it in a register
2503
2504 r = vtop->r;
2505
6bbfb8f6 bellard2004-11-07 15:43:15 +00002506 if (r == TREG_EAX) { // make sure the paired reg is avail
bf45336a bellard2004-10-05 17:55:18 +00002507 r2 = get_reg(RC_ECX);
6bbfb8f6 bellard2004-11-07 15:43:15 +00002508 } else if (r == TREG_EDX) {
bf45336a bellard2004-10-05 17:55:18 +00002509 r2 = get_reg(RC_ST0);
6bbfb8f6 bellard2004-11-07 15:43:15 +00002510 } else {
bf45336a bellard2004-10-05 17:55:18 +00002511 ALWAYS_ASSERT(FALSE);
6bbfb8f6 bellard2004-11-07 15:43:15 +00002512 r2 = 0; /* avoid warning */
2513 }
bf45336a bellard2004-10-05 17:55:18 +00002514
2515 C67_SPDP(r, r); // convert it to DP same register
2516 C67_NOP(1);
2517
2518 vtop->type.t = VT_DOUBLE;
2519 vtop->r2 = r2; // set this as unused
2520 } else {
2521 ALWAYS_ASSERT(FALSE);
2522 }
2523}
2524
2525/* computed goto support */
2526void ggoto(void)
2527{
2528 gcall_or_jmp(1);
2529 vtop--;
2530}
2531
41b3c7a5
JL
James Lyon2013-04-27 20:39:34 +01002532/* Save the stack pointer onto the stack and return the location of its address */
2533ST_FUNC void gen_vla_sp_save(int addr) {
2534 tcc_error("variable length arrays unsupported for this target");
2535}
2536
2537/* Restore the SP from a location on the stack */
2538ST_FUNC void gen_vla_sp_restore(int addr) {
2539 tcc_error("variable length arrays unsupported for this target");
2540}
2541
2542/* Subtract from the stack pointer, and push the resulting value onto the stack */
2543ST_FUNC void gen_vla_alloc(CType *type, int align) {
2544 tcc_error("variable length arrays unsupported for this target");
2545}
2546
88a3ccab grischka2009-12-20 01:53:49 +01002547/* end of C67 code generator */
2548/*************************************************************/
2549#endif
bf45336a bellard2004-10-05 17:55:18 +00002550/*************************************************************/