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