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