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