|
1 /* |
|
2 * Tiny Code Generator for QEMU |
|
3 * |
|
4 * Copyright (c) 2008 Fabrice Bellard |
|
5 * |
|
6 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 * of this software and associated documentation files (the "Software"), to deal |
|
8 * in the Software without restriction, including without limitation the rights |
|
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 * copies of the Software, and to permit persons to whom the Software is |
|
11 * furnished to do so, subject to the following conditions: |
|
12 * |
|
13 * The above copyright notice and this permission notice shall be included in |
|
14 * all copies or substantial portions of the Software. |
|
15 * |
|
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 * THE SOFTWARE. |
|
23 */ |
|
24 |
|
25 #define TCG_CT_CONST_U32 0x100 |
|
26 |
|
27 static uint8_t *tb_ret_addr; |
|
28 |
|
29 #define FAST_PATH |
|
30 |
|
31 #if TARGET_PHYS_ADDR_BITS == 32 |
|
32 #define LD_ADDEND LWZ |
|
33 #else |
|
34 #define LD_ADDEND LD |
|
35 #endif |
|
36 |
|
37 #if TARGET_LONG_BITS == 32 |
|
38 #define LD_ADDR LWZU |
|
39 #define CMP_L 0 |
|
40 #else |
|
41 #define LD_ADDR LDU |
|
42 #define CMP_L (1<<21) |
|
43 #endif |
|
44 |
|
45 #ifndef NDEBUG |
|
46 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { |
|
47 "r0", |
|
48 "r1", |
|
49 "rp", |
|
50 "r3", |
|
51 "r4", |
|
52 "r5", |
|
53 "r6", |
|
54 "r7", |
|
55 "r8", |
|
56 "r9", |
|
57 "r10", |
|
58 "r11", |
|
59 "r12", |
|
60 "r13", |
|
61 "r14", |
|
62 "r15", |
|
63 "r16", |
|
64 "r17", |
|
65 "r18", |
|
66 "r19", |
|
67 "r20", |
|
68 "r21", |
|
69 "r22", |
|
70 "r23", |
|
71 "r24", |
|
72 "r25", |
|
73 "r26", |
|
74 "r27", |
|
75 "r28", |
|
76 "r29", |
|
77 "r30", |
|
78 "r31" |
|
79 }; |
|
80 #endif |
|
81 |
|
82 static const int tcg_target_reg_alloc_order[] = { |
|
83 TCG_REG_R14, |
|
84 TCG_REG_R15, |
|
85 TCG_REG_R16, |
|
86 TCG_REG_R17, |
|
87 TCG_REG_R18, |
|
88 TCG_REG_R19, |
|
89 TCG_REG_R20, |
|
90 TCG_REG_R21, |
|
91 TCG_REG_R22, |
|
92 TCG_REG_R23, |
|
93 TCG_REG_R28, |
|
94 TCG_REG_R29, |
|
95 TCG_REG_R30, |
|
96 TCG_REG_R31, |
|
97 TCG_REG_R3, |
|
98 TCG_REG_R4, |
|
99 TCG_REG_R5, |
|
100 TCG_REG_R6, |
|
101 TCG_REG_R7, |
|
102 TCG_REG_R8, |
|
103 TCG_REG_R9, |
|
104 TCG_REG_R10, |
|
105 TCG_REG_R11, |
|
106 TCG_REG_R12, |
|
107 TCG_REG_R13, |
|
108 TCG_REG_R0, |
|
109 TCG_REG_R1, |
|
110 TCG_REG_R2, |
|
111 TCG_REG_R24, |
|
112 TCG_REG_R25, |
|
113 TCG_REG_R26, |
|
114 TCG_REG_R27 |
|
115 }; |
|
116 |
|
117 static const int tcg_target_call_iarg_regs[] = { |
|
118 TCG_REG_R3, |
|
119 TCG_REG_R4, |
|
120 TCG_REG_R5, |
|
121 TCG_REG_R6, |
|
122 TCG_REG_R7, |
|
123 TCG_REG_R8, |
|
124 TCG_REG_R9, |
|
125 TCG_REG_R10 |
|
126 }; |
|
127 |
|
128 static const int tcg_target_call_oarg_regs[2] = { |
|
129 TCG_REG_R3 |
|
130 }; |
|
131 |
|
132 static const int tcg_target_callee_save_regs[] = { |
|
133 TCG_REG_R14, |
|
134 TCG_REG_R15, |
|
135 TCG_REG_R16, |
|
136 TCG_REG_R17, |
|
137 TCG_REG_R18, |
|
138 TCG_REG_R19, |
|
139 TCG_REG_R20, |
|
140 TCG_REG_R21, |
|
141 TCG_REG_R22, |
|
142 TCG_REG_R23, |
|
143 TCG_REG_R28, |
|
144 TCG_REG_R29, |
|
145 TCG_REG_R30, |
|
146 TCG_REG_R31 |
|
147 }; |
|
148 |
|
149 static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) |
|
150 { |
|
151 tcg_target_long disp; |
|
152 |
|
153 disp = target - (tcg_target_long) pc; |
|
154 if ((disp << 38) >> 38 != disp) |
|
155 tcg_abort (); |
|
156 |
|
157 return disp & 0x3fffffc; |
|
158 } |
|
159 |
|
160 static void reloc_pc24 (void *pc, tcg_target_long target) |
|
161 { |
|
162 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc) |
|
163 | reloc_pc24_val (pc, target); |
|
164 } |
|
165 |
|
166 static uint16_t reloc_pc14_val (void *pc, tcg_target_long target) |
|
167 { |
|
168 tcg_target_long disp; |
|
169 |
|
170 disp = target - (tcg_target_long) pc; |
|
171 if (disp != (int16_t) disp) |
|
172 tcg_abort (); |
|
173 |
|
174 return disp & 0xfffc; |
|
175 } |
|
176 |
|
177 static void reloc_pc14 (void *pc, tcg_target_long target) |
|
178 { |
|
179 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc) |
|
180 | reloc_pc14_val (pc, target); |
|
181 } |
|
182 |
|
183 static void patch_reloc (uint8_t *code_ptr, int type, |
|
184 tcg_target_long value, tcg_target_long addend) |
|
185 { |
|
186 value += addend; |
|
187 switch (type) { |
|
188 case R_PPC_REL14: |
|
189 reloc_pc14 (code_ptr, value); |
|
190 break; |
|
191 case R_PPC_REL24: |
|
192 reloc_pc24 (code_ptr, value); |
|
193 break; |
|
194 default: |
|
195 tcg_abort (); |
|
196 } |
|
197 } |
|
198 |
|
199 /* maximum number of register used for input function arguments */ |
|
200 static int tcg_target_get_call_iarg_regs_count (int flags) |
|
201 { |
|
202 return ARRAY_SIZE (tcg_target_call_iarg_regs); |
|
203 } |
|
204 |
|
205 /* parse target specific constraints */ |
|
206 static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str) |
|
207 { |
|
208 const char *ct_str; |
|
209 |
|
210 ct_str = *pct_str; |
|
211 switch (ct_str[0]) { |
|
212 case 'A': case 'B': case 'C': case 'D': |
|
213 ct->ct |= TCG_CT_REG; |
|
214 tcg_regset_set_reg (ct->u.regs, 3 + ct_str[0] - 'A'); |
|
215 break; |
|
216 case 'r': |
|
217 ct->ct |= TCG_CT_REG; |
|
218 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); |
|
219 break; |
|
220 case 'L': /* qemu_ld constraint */ |
|
221 ct->ct |= TCG_CT_REG; |
|
222 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); |
|
223 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); |
|
224 #ifdef CONFIG_SOFTMMU |
|
225 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); |
|
226 #endif |
|
227 break; |
|
228 case 'S': /* qemu_st constraint */ |
|
229 ct->ct |= TCG_CT_REG; |
|
230 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); |
|
231 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); |
|
232 #ifdef CONFIG_SOFTMMU |
|
233 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); |
|
234 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5); |
|
235 #endif |
|
236 break; |
|
237 case 'Z': |
|
238 ct->ct |= TCG_CT_CONST_U32; |
|
239 break; |
|
240 default: |
|
241 return -1; |
|
242 } |
|
243 ct_str++; |
|
244 *pct_str = ct_str; |
|
245 return 0; |
|
246 } |
|
247 |
|
248 /* test if a constant matches the constraint */ |
|
249 static int tcg_target_const_match (tcg_target_long val, |
|
250 const TCGArgConstraint *arg_ct) |
|
251 { |
|
252 int ct; |
|
253 |
|
254 ct = arg_ct->ct; |
|
255 if (ct & TCG_CT_CONST) |
|
256 return 1; |
|
257 else if ((ct & TCG_CT_CONST_U32) && (val == (uint32_t) val)) |
|
258 return 1; |
|
259 return 0; |
|
260 } |
|
261 |
|
262 #define OPCD(opc) ((opc)<<26) |
|
263 #define XO19(opc) (OPCD(19)|((opc)<<1)) |
|
264 #define XO30(opc) (OPCD(30)|((opc)<<2)) |
|
265 #define XO31(opc) (OPCD(31)|((opc)<<1)) |
|
266 #define XO58(opc) (OPCD(58)|(opc)) |
|
267 #define XO62(opc) (OPCD(62)|(opc)) |
|
268 |
|
269 #define B OPCD( 18) |
|
270 #define BC OPCD( 16) |
|
271 #define LBZ OPCD( 34) |
|
272 #define LHZ OPCD( 40) |
|
273 #define LHA OPCD( 42) |
|
274 #define LWZ OPCD( 32) |
|
275 #define STB OPCD( 38) |
|
276 #define STH OPCD( 44) |
|
277 #define STW OPCD( 36) |
|
278 |
|
279 #define STD XO62( 0) |
|
280 #define STDU XO62( 1) |
|
281 #define STDX XO31(149) |
|
282 |
|
283 #define LD XO58( 0) |
|
284 #define LDX XO31( 21) |
|
285 #define LDU XO58( 1) |
|
286 #define LWA XO58( 2) |
|
287 #define LWAX XO31(341) |
|
288 |
|
289 #define ADDI OPCD( 14) |
|
290 #define ADDIS OPCD( 15) |
|
291 #define ORI OPCD( 24) |
|
292 #define ORIS OPCD( 25) |
|
293 #define XORI OPCD( 26) |
|
294 #define XORIS OPCD( 27) |
|
295 #define ANDI OPCD( 28) |
|
296 #define ANDIS OPCD( 29) |
|
297 #define MULLI OPCD( 7) |
|
298 #define CMPLI OPCD( 10) |
|
299 #define CMPI OPCD( 11) |
|
300 |
|
301 #define LWZU OPCD( 33) |
|
302 #define STWU OPCD( 37) |
|
303 |
|
304 #define RLWINM OPCD( 21) |
|
305 |
|
306 #define RLDICL XO30( 0) |
|
307 #define RLDICR XO30( 1) |
|
308 #define RLDIMI XO30( 3) |
|
309 |
|
310 #define BCLR XO19( 16) |
|
311 #define BCCTR XO19(528) |
|
312 #define CRAND XO19(257) |
|
313 #define CRANDC XO19(129) |
|
314 #define CRNAND XO19(225) |
|
315 #define CROR XO19(449) |
|
316 |
|
317 #define EXTSB XO31(954) |
|
318 #define EXTSH XO31(922) |
|
319 #define EXTSW XO31(986) |
|
320 #define ADD XO31(266) |
|
321 #define ADDE XO31(138) |
|
322 #define ADDC XO31( 10) |
|
323 #define AND XO31( 28) |
|
324 #define SUBF XO31( 40) |
|
325 #define SUBFC XO31( 8) |
|
326 #define SUBFE XO31(136) |
|
327 #define OR XO31(444) |
|
328 #define XOR XO31(316) |
|
329 #define MULLW XO31(235) |
|
330 #define MULHWU XO31( 11) |
|
331 #define DIVW XO31(491) |
|
332 #define DIVWU XO31(459) |
|
333 #define CMP XO31( 0) |
|
334 #define CMPL XO31( 32) |
|
335 #define LHBRX XO31(790) |
|
336 #define LWBRX XO31(534) |
|
337 #define STHBRX XO31(918) |
|
338 #define STWBRX XO31(662) |
|
339 #define MFSPR XO31(339) |
|
340 #define MTSPR XO31(467) |
|
341 #define SRAWI XO31(824) |
|
342 #define NEG XO31(104) |
|
343 |
|
344 #define MULLD XO31(233) |
|
345 #define MULHD XO31( 73) |
|
346 #define MULHDU XO31( 9) |
|
347 #define DIVD XO31(489) |
|
348 #define DIVDU XO31(457) |
|
349 |
|
350 #define LBZX XO31( 87) |
|
351 #define LHZX XO31(276) |
|
352 #define LHAX XO31(343) |
|
353 #define LWZX XO31( 23) |
|
354 #define STBX XO31(215) |
|
355 #define STHX XO31(407) |
|
356 #define STWX XO31(151) |
|
357 |
|
358 #define SPR(a,b) ((((a)<<5)|(b))<<11) |
|
359 #define LR SPR(8, 0) |
|
360 #define CTR SPR(9, 0) |
|
361 |
|
362 #define SLW XO31( 24) |
|
363 #define SRW XO31(536) |
|
364 #define SRAW XO31(792) |
|
365 |
|
366 #define SLD XO31( 27) |
|
367 #define SRD XO31(539) |
|
368 #define SRAD XO31(794) |
|
369 #define SRADI XO31(413<<1) |
|
370 |
|
371 #define LMW OPCD( 46) |
|
372 #define STMW OPCD( 47) |
|
373 |
|
374 #define TW XO31( 4) |
|
375 #define TRAP (TW | TO (31)) |
|
376 |
|
377 #define RT(r) ((r)<<21) |
|
378 #define RS(r) ((r)<<21) |
|
379 #define RA(r) ((r)<<16) |
|
380 #define RB(r) ((r)<<11) |
|
381 #define TO(t) ((t)<<21) |
|
382 #define SH(s) ((s)<<11) |
|
383 #define MB(b) ((b)<<6) |
|
384 #define ME(e) ((e)<<1) |
|
385 #define BO(o) ((o)<<21) |
|
386 #define MB64(b) ((b)<<5) |
|
387 |
|
388 #define LK 1 |
|
389 |
|
390 #define TAB(t,a,b) (RT(t) | RA(a) | RB(b)) |
|
391 #define SAB(s,a,b) (RS(s) | RA(a) | RB(b)) |
|
392 |
|
393 #define BF(n) ((n)<<23) |
|
394 #define BI(n, c) (((c)+((n)*4))<<16) |
|
395 #define BT(n, c) (((c)+((n)*4))<<21) |
|
396 #define BA(n, c) (((c)+((n)*4))<<16) |
|
397 #define BB(n, c) (((c)+((n)*4))<<11) |
|
398 |
|
399 #define BO_COND_TRUE BO (12) |
|
400 #define BO_COND_FALSE BO ( 4) |
|
401 #define BO_ALWAYS BO (20) |
|
402 |
|
403 enum { |
|
404 CR_LT, |
|
405 CR_GT, |
|
406 CR_EQ, |
|
407 CR_SO |
|
408 }; |
|
409 |
|
410 static const uint32_t tcg_to_bc[10] = { |
|
411 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE, |
|
412 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, |
|
413 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, |
|
414 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE, |
|
415 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE, |
|
416 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE, |
|
417 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE, |
|
418 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE, |
|
419 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE, |
|
420 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE, |
|
421 }; |
|
422 |
|
423 static void tcg_out_mov (TCGContext *s, int ret, int arg) |
|
424 { |
|
425 tcg_out32 (s, OR | SAB (arg, ret, arg)); |
|
426 } |
|
427 |
|
428 static void tcg_out_rld (TCGContext *s, int op, int ra, int rs, int sh, int mb) |
|
429 { |
|
430 sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1); |
|
431 mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f)); |
|
432 tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb); |
|
433 } |
|
434 |
|
435 static void tcg_out_movi32 (TCGContext *s, int ret, int32_t arg) |
|
436 { |
|
437 if (arg == (int16_t) arg) |
|
438 tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff)); |
|
439 else { |
|
440 tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff)); |
|
441 if (arg & 0xffff) |
|
442 tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff)); |
|
443 } |
|
444 } |
|
445 |
|
446 static void tcg_out_movi (TCGContext *s, TCGType type, |
|
447 int ret, tcg_target_long arg) |
|
448 { |
|
449 int32_t arg32 = arg; |
|
450 |
|
451 if (type == TCG_TYPE_I32 || arg == arg32) { |
|
452 tcg_out_movi32 (s, ret, arg32); |
|
453 } |
|
454 else { |
|
455 if ((uint64_t) arg >> 32) { |
|
456 uint16_t h16 = arg >> 16; |
|
457 uint16_t l16 = arg; |
|
458 |
|
459 tcg_out_movi32 (s, ret, arg >> 32); |
|
460 tcg_out_rld (s, RLDICR, ret, ret, 32, 31); |
|
461 if (h16) tcg_out32 (s, ORIS | RS (ret) | RA (ret) | h16); |
|
462 if (l16) tcg_out32 (s, ORI | RS (ret) | RA (ret) | l16); |
|
463 } |
|
464 else { |
|
465 tcg_out_movi32 (s, ret, arg32); |
|
466 if (arg32 < 0) |
|
467 tcg_out_rld (s, RLDICL, ret, ret, 0, 32); |
|
468 } |
|
469 } |
|
470 } |
|
471 |
|
472 static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg) |
|
473 { |
|
474 int reg; |
|
475 |
|
476 if (const_arg) { |
|
477 reg = 2; |
|
478 tcg_out_movi (s, TCG_TYPE_I64, reg, arg); |
|
479 } |
|
480 else reg = arg; |
|
481 |
|
482 tcg_out32 (s, LD | RT (0) | RA (reg)); |
|
483 tcg_out32 (s, MTSPR | RA (0) | CTR); |
|
484 tcg_out32 (s, LD | RT (11) | RA (reg) | 16); |
|
485 tcg_out32 (s, LD | RT (2) | RA (reg) | 8); |
|
486 tcg_out32 (s, BCCTR | BO_ALWAYS | LK); |
|
487 } |
|
488 |
|
489 static void tcg_out_ldst (TCGContext *s, int ret, int addr, |
|
490 int offset, int op1, int op2) |
|
491 { |
|
492 if (offset == (int16_t) offset) |
|
493 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff)); |
|
494 else { |
|
495 tcg_out_movi (s, TCG_TYPE_I64, 0, offset); |
|
496 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0)); |
|
497 } |
|
498 } |
|
499 |
|
500 static void tcg_out_ldsta (TCGContext *s, int ret, int addr, |
|
501 int offset, int op1, int op2) |
|
502 { |
|
503 if (offset == (int16_t) (offset & ~3)) |
|
504 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff)); |
|
505 else { |
|
506 tcg_out_movi (s, TCG_TYPE_I64, 0, offset); |
|
507 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0)); |
|
508 } |
|
509 } |
|
510 |
|
511 static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target) |
|
512 { |
|
513 tcg_target_long disp; |
|
514 |
|
515 disp = target - (tcg_target_long) s->code_ptr; |
|
516 if ((disp << 38) >> 38 == disp) |
|
517 tcg_out32 (s, B | (disp & 0x3fffffc) | mask); |
|
518 else { |
|
519 tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target); |
|
520 tcg_out32 (s, MTSPR | RS (0) | CTR); |
|
521 tcg_out32 (s, BCCTR | BO_ALWAYS | mask); |
|
522 } |
|
523 } |
|
524 |
|
525 #if defined (CONFIG_SOFTMMU) |
|
526 |
|
527 #include "../../softmmu_defs.h" |
|
528 |
|
529 static void *qemu_ld_helpers[4] = { |
|
530 __ldb_mmu, |
|
531 __ldw_mmu, |
|
532 __ldl_mmu, |
|
533 __ldq_mmu, |
|
534 }; |
|
535 |
|
536 static void *qemu_st_helpers[4] = { |
|
537 __stb_mmu, |
|
538 __stw_mmu, |
|
539 __stl_mmu, |
|
540 __stq_mmu, |
|
541 }; |
|
542 |
|
543 static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2, |
|
544 int addr_reg, int s_bits, int offset) |
|
545 { |
|
546 #if TARGET_LONG_BITS == 32 |
|
547 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); |
|
548 |
|
549 tcg_out32 (s, (RLWINM |
|
550 | RA (r0) |
|
551 | RS (addr_reg) |
|
552 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS)) |
|
553 | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS)) |
|
554 | ME (31 - CPU_TLB_ENTRY_BITS) |
|
555 ) |
|
556 ); |
|
557 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0)); |
|
558 tcg_out32 (s, (LWZU | RT (r1) | RA (r0) | offset)); |
|
559 tcg_out32 (s, (RLWINM |
|
560 | RA (r2) |
|
561 | RS (addr_reg) |
|
562 | SH (0) |
|
563 | MB ((32 - s_bits) & 31) |
|
564 | ME (31 - TARGET_PAGE_BITS) |
|
565 ) |
|
566 ); |
|
567 #else |
|
568 tcg_out_rld (s, RLDICL, r0, addr_reg, |
|
569 64 - TARGET_PAGE_BITS, |
|
570 64 - CPU_TLB_BITS); |
|
571 tcg_out_rld (s, RLDICR, r0, r0, |
|
572 CPU_TLB_ENTRY_BITS, |
|
573 63 - CPU_TLB_ENTRY_BITS); |
|
574 |
|
575 tcg_out32 (s, ADD | TAB (r0, r0, TCG_AREG0)); |
|
576 tcg_out32 (s, LD_ADDR | RT (r1) | RA (r0) | offset); |
|
577 |
|
578 if (!s_bits) { |
|
579 tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS); |
|
580 } |
|
581 else { |
|
582 tcg_out_rld (s, RLDICL, r2, addr_reg, |
|
583 64 - TARGET_PAGE_BITS, |
|
584 TARGET_PAGE_BITS - s_bits); |
|
585 tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0); |
|
586 } |
|
587 #endif |
|
588 } |
|
589 #endif |
|
590 |
|
591 static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) |
|
592 { |
|
593 int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap; |
|
594 #ifdef CONFIG_SOFTMMU |
|
595 int r2; |
|
596 void *label1_ptr, *label2_ptr; |
|
597 #endif |
|
598 |
|
599 data_reg = *args++; |
|
600 addr_reg = *args++; |
|
601 mem_index = *args; |
|
602 s_bits = opc & 3; |
|
603 |
|
604 #ifdef CONFIG_SOFTMMU |
|
605 r0 = 3; |
|
606 r1 = 4; |
|
607 r2 = 0; |
|
608 |
|
609 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits, |
|
610 offsetof (CPUState, tlb_table[mem_index][0].addr_read)); |
|
611 |
|
612 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L); |
|
613 |
|
614 label1_ptr = s->code_ptr; |
|
615 #ifdef FAST_PATH |
|
616 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); |
|
617 #endif |
|
618 |
|
619 /* slow path */ |
|
620 tcg_out_mov (s, 3, addr_reg); |
|
621 tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index); |
|
622 |
|
623 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1); |
|
624 |
|
625 switch (opc) { |
|
626 case 0|4: |
|
627 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3)); |
|
628 break; |
|
629 case 1|4: |
|
630 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3)); |
|
631 break; |
|
632 case 2|4: |
|
633 tcg_out32 (s, EXTSW | RA (data_reg) | RS (3)); |
|
634 break; |
|
635 case 0: |
|
636 case 1: |
|
637 case 2: |
|
638 case 3: |
|
639 if (data_reg != 3) |
|
640 tcg_out_mov (s, data_reg, 3); |
|
641 break; |
|
642 } |
|
643 label2_ptr = s->code_ptr; |
|
644 tcg_out32 (s, B); |
|
645 |
|
646 /* label1: fast path */ |
|
647 #ifdef FAST_PATH |
|
648 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); |
|
649 #endif |
|
650 |
|
651 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */ |
|
652 tcg_out32 (s, (LD_ADDEND |
|
653 | RT (r0) |
|
654 | RA (r0) |
|
655 | (offsetof (CPUTLBEntry, addend) |
|
656 - offsetof (CPUTLBEntry, addr_read)) |
|
657 )); |
|
658 /* r0 = env->tlb_table[mem_index][index].addend */ |
|
659 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg)); |
|
660 /* r0 = env->tlb_table[mem_index][index].addend + addr */ |
|
661 |
|
662 #else /* !CONFIG_SOFTMMU */ |
|
663 #if TARGET_LONG_BITS == 32 |
|
664 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); |
|
665 #endif |
|
666 r0 = addr_reg; |
|
667 r1 = 3; |
|
668 #endif |
|
669 |
|
670 #ifdef TARGET_WORDS_BIGENDIAN |
|
671 bswap = 0; |
|
672 #else |
|
673 bswap = 1; |
|
674 #endif |
|
675 switch (opc) { |
|
676 default: |
|
677 case 0: |
|
678 tcg_out32 (s, LBZ | RT (data_reg) | RA (r0)); |
|
679 break; |
|
680 case 0|4: |
|
681 tcg_out32 (s, LBZ | RT (data_reg) | RA (r0)); |
|
682 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg)); |
|
683 break; |
|
684 case 1: |
|
685 if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0)); |
|
686 else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0)); |
|
687 break; |
|
688 case 1|4: |
|
689 if (bswap) { |
|
690 tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0)); |
|
691 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg)); |
|
692 } |
|
693 else tcg_out32 (s, LHA | RT (data_reg) | RA (r0)); |
|
694 break; |
|
695 case 2: |
|
696 if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); |
|
697 else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0)); |
|
698 break; |
|
699 case 2|4: |
|
700 if (bswap) { |
|
701 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); |
|
702 tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg)); |
|
703 } |
|
704 else tcg_out32 (s, LWA | RT (data_reg)| RA (r0)); |
|
705 break; |
|
706 case 3: |
|
707 if (bswap) { |
|
708 tcg_out_movi32 (s, 0, 4); |
|
709 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); |
|
710 tcg_out32 (s, LWBRX | RT ( r1) | RA (r0)); |
|
711 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0); |
|
712 } |
|
713 else tcg_out32 (s, LD | RT (data_reg) | RA (r0)); |
|
714 break; |
|
715 } |
|
716 |
|
717 #ifdef CONFIG_SOFTMMU |
|
718 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); |
|
719 #endif |
|
720 } |
|
721 |
|
722 static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) |
|
723 { |
|
724 int addr_reg, r0, r1, data_reg, mem_index, bswap; |
|
725 #ifdef CONFIG_SOFTMMU |
|
726 int r2; |
|
727 void *label1_ptr, *label2_ptr; |
|
728 #endif |
|
729 |
|
730 data_reg = *args++; |
|
731 addr_reg = *args++; |
|
732 mem_index = *args; |
|
733 |
|
734 #ifdef CONFIG_SOFTMMU |
|
735 r0 = 3; |
|
736 r1 = 4; |
|
737 r2 = 0; |
|
738 |
|
739 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc, |
|
740 offsetof (CPUState, tlb_table[mem_index][0].addr_write)); |
|
741 |
|
742 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L); |
|
743 |
|
744 label1_ptr = s->code_ptr; |
|
745 #ifdef FAST_PATH |
|
746 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); |
|
747 #endif |
|
748 |
|
749 /* slow path */ |
|
750 tcg_out_mov (s, 3, addr_reg); |
|
751 tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc))); |
|
752 tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index); |
|
753 |
|
754 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1); |
|
755 |
|
756 label2_ptr = s->code_ptr; |
|
757 tcg_out32 (s, B); |
|
758 |
|
759 /* label1: fast path */ |
|
760 #ifdef FAST_PATH |
|
761 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); |
|
762 #endif |
|
763 |
|
764 tcg_out32 (s, (LD_ADDEND |
|
765 | RT (r0) |
|
766 | RA (r0) |
|
767 | (offsetof (CPUTLBEntry, addend) |
|
768 - offsetof (CPUTLBEntry, addr_write)) |
|
769 )); |
|
770 /* r0 = env->tlb_table[mem_index][index].addend */ |
|
771 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg)); |
|
772 /* r0 = env->tlb_table[mem_index][index].addend + addr */ |
|
773 |
|
774 #else /* !CONFIG_SOFTMMU */ |
|
775 #if TARGET_LONG_BITS == 32 |
|
776 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); |
|
777 #endif |
|
778 r1 = 3; |
|
779 r0 = addr_reg; |
|
780 #endif |
|
781 |
|
782 #ifdef TARGET_WORDS_BIGENDIAN |
|
783 bswap = 0; |
|
784 #else |
|
785 bswap = 1; |
|
786 #endif |
|
787 switch (opc) { |
|
788 case 0: |
|
789 tcg_out32 (s, STB | RS (data_reg) | RA (r0)); |
|
790 break; |
|
791 case 1: |
|
792 if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0)); |
|
793 else tcg_out32 (s, STH | RS (data_reg) | RA (r0)); |
|
794 break; |
|
795 case 2: |
|
796 if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0)); |
|
797 else tcg_out32 (s, STW | RS (data_reg) | RA (r0)); |
|
798 break; |
|
799 case 3: |
|
800 if (bswap) { |
|
801 tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0)); |
|
802 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4); |
|
803 tcg_out_rld (s, RLDICL, 0, data_reg, 32, 0); |
|
804 tcg_out32 (s, STWBRX | RS (0) | RA (0) | RB (r1)); |
|
805 } |
|
806 else tcg_out32 (s, STD | RS (data_reg) | RA (r0)); |
|
807 break; |
|
808 } |
|
809 |
|
810 #ifdef CONFIG_SOFTMMU |
|
811 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); |
|
812 #endif |
|
813 } |
|
814 |
|
815 void tcg_target_qemu_prologue (TCGContext *s) |
|
816 { |
|
817 int i, frame_size; |
|
818 uint64_t addr; |
|
819 |
|
820 frame_size = 0 |
|
821 + 8 /* back chain */ |
|
822 + 8 /* CR */ |
|
823 + 8 /* LR */ |
|
824 + 8 /* compiler doubleword */ |
|
825 + 8 /* link editor doubleword */ |
|
826 + 8 /* TOC save area */ |
|
827 + TCG_STATIC_CALL_ARGS_SIZE |
|
828 + ARRAY_SIZE (tcg_target_callee_save_regs) * 8 |
|
829 ; |
|
830 frame_size = (frame_size + 15) & ~15; |
|
831 |
|
832 /* First emit adhoc function descriptor */ |
|
833 addr = (uint64_t) s->code_ptr + 24; |
|
834 tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */ |
|
835 s->code_ptr += 16; /* skip TOC and environment pointer */ |
|
836 |
|
837 /* Prologue */ |
|
838 tcg_out32 (s, MFSPR | RT (0) | LR); |
|
839 tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff)); |
|
840 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i) |
|
841 tcg_out32 (s, (STD |
|
842 | RS (tcg_target_callee_save_regs[i]) |
|
843 | RA (1) |
|
844 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE) |
|
845 ) |
|
846 ); |
|
847 tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16)); |
|
848 |
|
849 tcg_out32 (s, MTSPR | RS (3) | CTR); |
|
850 tcg_out32 (s, BCCTR | BO_ALWAYS); |
|
851 |
|
852 /* Epilogue */ |
|
853 tb_ret_addr = s->code_ptr; |
|
854 |
|
855 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i) |
|
856 tcg_out32 (s, (LD |
|
857 | RT (tcg_target_callee_save_regs[i]) |
|
858 | RA (1) |
|
859 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE) |
|
860 ) |
|
861 ); |
|
862 tcg_out32 (s, LD | RT (0) | RA (1) | (frame_size + 16)); |
|
863 tcg_out32 (s, MTSPR | RS (0) | LR); |
|
864 tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); |
|
865 tcg_out32 (s, BCLR | BO_ALWAYS); |
|
866 } |
|
867 |
|
868 static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, |
|
869 tcg_target_long arg2) |
|
870 { |
|
871 if (type == TCG_TYPE_I32) |
|
872 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX); |
|
873 else |
|
874 tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX); |
|
875 } |
|
876 |
|
877 static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1, |
|
878 tcg_target_long arg2) |
|
879 { |
|
880 if (type == TCG_TYPE_I32) |
|
881 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX); |
|
882 else |
|
883 tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX); |
|
884 } |
|
885 |
|
886 static void ppc_addi32 (TCGContext *s, int rt, int ra, tcg_target_long si) |
|
887 { |
|
888 if (!si && rt == ra) |
|
889 return; |
|
890 |
|
891 if (si == (int16_t) si) |
|
892 tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff)); |
|
893 else { |
|
894 uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15); |
|
895 tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h); |
|
896 tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff)); |
|
897 } |
|
898 } |
|
899 |
|
900 static void ppc_addi64 (TCGContext *s, int rt, int ra, tcg_target_long si) |
|
901 { |
|
902 /* XXX: suboptimal */ |
|
903 if (si == (int16_t) si |
|
904 || ((((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0)) |
|
905 ppc_addi32 (s, rt, ra, si); |
|
906 else { |
|
907 tcg_out_movi (s, TCG_TYPE_I64, 0, si); |
|
908 tcg_out32 (s, ADD | RT (rt) | RA (ra)); |
|
909 } |
|
910 } |
|
911 |
|
912 static void tcg_out_addi (TCGContext *s, int reg, tcg_target_long val) |
|
913 { |
|
914 ppc_addi64 (s, reg, reg, val); |
|
915 } |
|
916 |
|
917 static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2, |
|
918 int const_arg2, int cr, int arch64) |
|
919 { |
|
920 int imm; |
|
921 uint32_t op; |
|
922 |
|
923 switch (cond) { |
|
924 case TCG_COND_EQ: |
|
925 case TCG_COND_NE: |
|
926 if (const_arg2) { |
|
927 if ((int16_t) arg2 == arg2) { |
|
928 op = CMPI; |
|
929 imm = 1; |
|
930 break; |
|
931 } |
|
932 else if ((uint16_t) arg2 == arg2) { |
|
933 op = CMPLI; |
|
934 imm = 1; |
|
935 break; |
|
936 } |
|
937 } |
|
938 op = CMPL; |
|
939 imm = 0; |
|
940 break; |
|
941 |
|
942 case TCG_COND_LT: |
|
943 case TCG_COND_GE: |
|
944 case TCG_COND_LE: |
|
945 case TCG_COND_GT: |
|
946 if (const_arg2) { |
|
947 if ((int16_t) arg2 == arg2) { |
|
948 op = CMPI; |
|
949 imm = 1; |
|
950 break; |
|
951 } |
|
952 } |
|
953 op = CMP; |
|
954 imm = 0; |
|
955 break; |
|
956 |
|
957 case TCG_COND_LTU: |
|
958 case TCG_COND_GEU: |
|
959 case TCG_COND_LEU: |
|
960 case TCG_COND_GTU: |
|
961 if (const_arg2) { |
|
962 if ((uint16_t) arg2 == arg2) { |
|
963 op = CMPLI; |
|
964 imm = 1; |
|
965 break; |
|
966 } |
|
967 } |
|
968 op = CMPL; |
|
969 imm = 0; |
|
970 break; |
|
971 |
|
972 default: |
|
973 tcg_abort (); |
|
974 } |
|
975 op |= BF (cr) | (arch64 << 21); |
|
976 |
|
977 if (imm) |
|
978 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff)); |
|
979 else { |
|
980 if (const_arg2) { |
|
981 tcg_out_movi (s, TCG_TYPE_I64, 0, arg2); |
|
982 tcg_out32 (s, op | RA (arg1) | RB (0)); |
|
983 } |
|
984 else |
|
985 tcg_out32 (s, op | RA (arg1) | RB (arg2)); |
|
986 } |
|
987 |
|
988 } |
|
989 |
|
990 static void tcg_out_bc (TCGContext *s, int bc, int label_index) |
|
991 { |
|
992 TCGLabel *l = &s->labels[label_index]; |
|
993 |
|
994 if (l->has_value) |
|
995 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value)); |
|
996 else { |
|
997 uint16_t val = *(uint16_t *) &s->code_ptr[2]; |
|
998 |
|
999 /* Thanks to Andrzej Zaborowski */ |
|
1000 tcg_out32 (s, bc | (val & 0xfffc)); |
|
1001 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0); |
|
1002 } |
|
1003 } |
|
1004 |
|
1005 static void tcg_out_brcond (TCGContext *s, int cond, |
|
1006 TCGArg arg1, TCGArg arg2, int const_arg2, |
|
1007 int label_index, int arch64) |
|
1008 { |
|
1009 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, arch64); |
|
1010 tcg_out_bc (s, tcg_to_bc[cond], label_index); |
|
1011 } |
|
1012 |
|
1013 void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr) |
|
1014 { |
|
1015 TCGContext s; |
|
1016 unsigned long patch_size; |
|
1017 |
|
1018 s.code_ptr = (uint8_t *) jmp_addr; |
|
1019 tcg_out_b (&s, 0, addr); |
|
1020 patch_size = s.code_ptr - (uint8_t *) jmp_addr; |
|
1021 flush_icache_range (jmp_addr, jmp_addr + patch_size); |
|
1022 } |
|
1023 |
|
1024 static void tcg_out_op (TCGContext *s, int opc, const TCGArg *args, |
|
1025 const int *const_args) |
|
1026 { |
|
1027 int c; |
|
1028 |
|
1029 switch (opc) { |
|
1030 case INDEX_op_exit_tb: |
|
1031 tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]); |
|
1032 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr); |
|
1033 break; |
|
1034 case INDEX_op_goto_tb: |
|
1035 if (s->tb_jmp_offset) { |
|
1036 /* direct jump method */ |
|
1037 |
|
1038 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; |
|
1039 s->code_ptr += 28; |
|
1040 } |
|
1041 else { |
|
1042 tcg_abort (); |
|
1043 } |
|
1044 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; |
|
1045 break; |
|
1046 case INDEX_op_br: |
|
1047 { |
|
1048 TCGLabel *l = &s->labels[args[0]]; |
|
1049 |
|
1050 if (l->has_value) { |
|
1051 tcg_out_b (s, 0, l->u.value); |
|
1052 } |
|
1053 else { |
|
1054 uint32_t val = *(uint32_t *) s->code_ptr; |
|
1055 |
|
1056 /* Thanks to Andrzej Zaborowski */ |
|
1057 tcg_out32 (s, B | (val & 0x3fffffc)); |
|
1058 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0); |
|
1059 } |
|
1060 } |
|
1061 break; |
|
1062 case INDEX_op_call: |
|
1063 tcg_out_call (s, args[0], const_args[0]); |
|
1064 break; |
|
1065 case INDEX_op_jmp: |
|
1066 if (const_args[0]) { |
|
1067 tcg_out_b (s, 0, args[0]); |
|
1068 } |
|
1069 else { |
|
1070 tcg_out32 (s, MTSPR | RS (args[0]) | CTR); |
|
1071 tcg_out32 (s, BCCTR | BO_ALWAYS); |
|
1072 } |
|
1073 break; |
|
1074 case INDEX_op_movi_i32: |
|
1075 tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]); |
|
1076 break; |
|
1077 case INDEX_op_movi_i64: |
|
1078 tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]); |
|
1079 break; |
|
1080 case INDEX_op_ld8u_i32: |
|
1081 case INDEX_op_ld8u_i64: |
|
1082 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX); |
|
1083 break; |
|
1084 case INDEX_op_ld8s_i32: |
|
1085 case INDEX_op_ld8s_i64: |
|
1086 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX); |
|
1087 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0])); |
|
1088 break; |
|
1089 case INDEX_op_ld16u_i32: |
|
1090 case INDEX_op_ld16u_i64: |
|
1091 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX); |
|
1092 break; |
|
1093 case INDEX_op_ld16s_i32: |
|
1094 case INDEX_op_ld16s_i64: |
|
1095 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX); |
|
1096 break; |
|
1097 case INDEX_op_ld_i32: |
|
1098 case INDEX_op_ld32u_i64: |
|
1099 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX); |
|
1100 break; |
|
1101 case INDEX_op_ld32s_i64: |
|
1102 tcg_out_ldsta (s, args[0], args[1], args[2], LWA, LWAX); |
|
1103 break; |
|
1104 case INDEX_op_ld_i64: |
|
1105 tcg_out_ldsta (s, args[0], args[1], args[2], LD, LDX); |
|
1106 break; |
|
1107 case INDEX_op_st8_i32: |
|
1108 case INDEX_op_st8_i64: |
|
1109 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX); |
|
1110 break; |
|
1111 case INDEX_op_st16_i32: |
|
1112 case INDEX_op_st16_i64: |
|
1113 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX); |
|
1114 break; |
|
1115 case INDEX_op_st_i32: |
|
1116 case INDEX_op_st32_i64: |
|
1117 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX); |
|
1118 break; |
|
1119 case INDEX_op_st_i64: |
|
1120 tcg_out_ldsta (s, args[0], args[1], args[2], STD, STDX); |
|
1121 break; |
|
1122 |
|
1123 case INDEX_op_add_i32: |
|
1124 if (const_args[2]) |
|
1125 ppc_addi32 (s, args[0], args[1], args[2]); |
|
1126 else |
|
1127 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); |
|
1128 break; |
|
1129 case INDEX_op_sub_i32: |
|
1130 if (const_args[2]) |
|
1131 ppc_addi32 (s, args[0], args[1], -args[2]); |
|
1132 else |
|
1133 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); |
|
1134 break; |
|
1135 |
|
1136 case INDEX_op_and_i64: |
|
1137 case INDEX_op_and_i32: |
|
1138 if (const_args[2]) { |
|
1139 if ((args[2] & 0xffff) == args[2]) |
|
1140 tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]); |
|
1141 else if ((args[2] & 0xffff0000) == args[2]) |
|
1142 tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0]) |
|
1143 | ((args[2] >> 16) & 0xffff)); |
|
1144 else { |
|
1145 tcg_out_movi (s, (opc == INDEX_op_and_i32 |
|
1146 ? TCG_TYPE_I32 |
|
1147 : TCG_TYPE_I64), |
|
1148 0, args[2]); |
|
1149 tcg_out32 (s, AND | SAB (args[1], args[0], 0)); |
|
1150 } |
|
1151 } |
|
1152 else |
|
1153 tcg_out32 (s, AND | SAB (args[1], args[0], args[2])); |
|
1154 break; |
|
1155 case INDEX_op_or_i64: |
|
1156 case INDEX_op_or_i32: |
|
1157 if (const_args[2]) { |
|
1158 if (args[2] & 0xffff) { |
|
1159 tcg_out32 (s, ORI | RS (args[1]) | RA (args[0]) |
|
1160 | (args[2] & 0xffff)); |
|
1161 if (args[2] >> 16) |
|
1162 tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0]) |
|
1163 | ((args[2] >> 16) & 0xffff)); |
|
1164 } |
|
1165 else { |
|
1166 tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0]) |
|
1167 | ((args[2] >> 16) & 0xffff)); |
|
1168 } |
|
1169 } |
|
1170 else |
|
1171 tcg_out32 (s, OR | SAB (args[1], args[0], args[2])); |
|
1172 break; |
|
1173 case INDEX_op_xor_i64: |
|
1174 case INDEX_op_xor_i32: |
|
1175 if (const_args[2]) { |
|
1176 if ((args[2] & 0xffff) == args[2]) |
|
1177 tcg_out32 (s, XORI | RS (args[1]) | RA (args[0]) |
|
1178 | (args[2] & 0xffff)); |
|
1179 else if ((args[2] & 0xffff0000) == args[2]) |
|
1180 tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0]) |
|
1181 | ((args[2] >> 16) & 0xffff)); |
|
1182 else { |
|
1183 tcg_out_movi (s, (opc == INDEX_op_and_i32 |
|
1184 ? TCG_TYPE_I32 |
|
1185 : TCG_TYPE_I64), |
|
1186 0, args[2]); |
|
1187 tcg_out32 (s, XOR | SAB (args[1], args[0], 0)); |
|
1188 } |
|
1189 } |
|
1190 else |
|
1191 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2])); |
|
1192 break; |
|
1193 |
|
1194 case INDEX_op_mul_i32: |
|
1195 if (const_args[2]) { |
|
1196 if (args[2] == (int16_t) args[2]) |
|
1197 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1]) |
|
1198 | (args[2] & 0xffff)); |
|
1199 else { |
|
1200 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]); |
|
1201 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0)); |
|
1202 } |
|
1203 } |
|
1204 else |
|
1205 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2])); |
|
1206 break; |
|
1207 |
|
1208 case INDEX_op_div_i32: |
|
1209 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2])); |
|
1210 break; |
|
1211 |
|
1212 case INDEX_op_divu_i32: |
|
1213 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2])); |
|
1214 break; |
|
1215 |
|
1216 case INDEX_op_rem_i32: |
|
1217 tcg_out32 (s, DIVW | TAB (0, args[1], args[2])); |
|
1218 tcg_out32 (s, MULLW | TAB (0, 0, args[2])); |
|
1219 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); |
|
1220 break; |
|
1221 |
|
1222 case INDEX_op_remu_i32: |
|
1223 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2])); |
|
1224 tcg_out32 (s, MULLW | TAB (0, 0, args[2])); |
|
1225 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); |
|
1226 break; |
|
1227 |
|
1228 case INDEX_op_shl_i32: |
|
1229 if (const_args[2]) { |
|
1230 tcg_out32 (s, (RLWINM |
|
1231 | RA (args[0]) |
|
1232 | RS (args[1]) |
|
1233 | SH (args[2]) |
|
1234 | MB (0) |
|
1235 | ME (31 - args[2]) |
|
1236 ) |
|
1237 ); |
|
1238 } |
|
1239 else |
|
1240 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2])); |
|
1241 break; |
|
1242 case INDEX_op_shr_i32: |
|
1243 if (const_args[2]) { |
|
1244 tcg_out32 (s, (RLWINM |
|
1245 | RA (args[0]) |
|
1246 | RS (args[1]) |
|
1247 | SH (32 - args[2]) |
|
1248 | MB (args[2]) |
|
1249 | ME (31) |
|
1250 ) |
|
1251 ); |
|
1252 } |
|
1253 else |
|
1254 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2])); |
|
1255 break; |
|
1256 case INDEX_op_sar_i32: |
|
1257 if (const_args[2]) |
|
1258 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2])); |
|
1259 else |
|
1260 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2])); |
|
1261 break; |
|
1262 |
|
1263 case INDEX_op_brcond_i32: |
|
1264 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 0); |
|
1265 break; |
|
1266 |
|
1267 case INDEX_op_brcond_i64: |
|
1268 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 1); |
|
1269 break; |
|
1270 |
|
1271 case INDEX_op_neg_i32: |
|
1272 case INDEX_op_neg_i64: |
|
1273 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1])); |
|
1274 break; |
|
1275 |
|
1276 case INDEX_op_add_i64: |
|
1277 if (const_args[2]) |
|
1278 ppc_addi64 (s, args[0], args[1], args[2]); |
|
1279 else |
|
1280 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); |
|
1281 break; |
|
1282 case INDEX_op_sub_i64: |
|
1283 if (const_args[2]) |
|
1284 ppc_addi64 (s, args[0], args[1], -args[2]); |
|
1285 else |
|
1286 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); |
|
1287 break; |
|
1288 |
|
1289 case INDEX_op_shl_i64: |
|
1290 if (const_args[2]) |
|
1291 tcg_out_rld (s, RLDICR, args[0], args[1], args[2], 63 - args[2]); |
|
1292 else |
|
1293 tcg_out32 (s, SLD | SAB (args[1], args[0], args[2])); |
|
1294 break; |
|
1295 case INDEX_op_shr_i64: |
|
1296 if (const_args[2]) |
|
1297 tcg_out_rld (s, RLDICL, args[0], args[1], 64 - args[2], args[2]); |
|
1298 else |
|
1299 tcg_out32 (s, SRD | SAB (args[1], args[0], args[2])); |
|
1300 break; |
|
1301 case INDEX_op_sar_i64: |
|
1302 if (const_args[2]) { |
|
1303 int sh = SH (args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1); |
|
1304 tcg_out32 (s, SRADI | RA (args[0]) | RS (args[1]) | sh); |
|
1305 } |
|
1306 else |
|
1307 tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2])); |
|
1308 break; |
|
1309 |
|
1310 case INDEX_op_mul_i64: |
|
1311 tcg_out32 (s, MULLD | TAB (args[0], args[1], args[2])); |
|
1312 break; |
|
1313 case INDEX_op_div_i64: |
|
1314 tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2])); |
|
1315 break; |
|
1316 case INDEX_op_divu_i64: |
|
1317 tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2])); |
|
1318 break; |
|
1319 case INDEX_op_rem_i64: |
|
1320 tcg_out32 (s, DIVD | TAB (0, args[1], args[2])); |
|
1321 tcg_out32 (s, MULLD | TAB (0, 0, args[2])); |
|
1322 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); |
|
1323 break; |
|
1324 case INDEX_op_remu_i64: |
|
1325 tcg_out32 (s, DIVDU | TAB (0, args[1], args[2])); |
|
1326 tcg_out32 (s, MULLD | TAB (0, 0, args[2])); |
|
1327 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); |
|
1328 break; |
|
1329 |
|
1330 case INDEX_op_qemu_ld8u: |
|
1331 tcg_out_qemu_ld (s, args, 0); |
|
1332 break; |
|
1333 case INDEX_op_qemu_ld8s: |
|
1334 tcg_out_qemu_ld (s, args, 0 | 4); |
|
1335 break; |
|
1336 case INDEX_op_qemu_ld16u: |
|
1337 tcg_out_qemu_ld (s, args, 1); |
|
1338 break; |
|
1339 case INDEX_op_qemu_ld16s: |
|
1340 tcg_out_qemu_ld (s, args, 1 | 4); |
|
1341 break; |
|
1342 case INDEX_op_qemu_ld32u: |
|
1343 tcg_out_qemu_ld (s, args, 2); |
|
1344 break; |
|
1345 case INDEX_op_qemu_ld32s: |
|
1346 tcg_out_qemu_ld (s, args, 2 | 4); |
|
1347 break; |
|
1348 case INDEX_op_qemu_ld64: |
|
1349 tcg_out_qemu_ld (s, args, 3); |
|
1350 break; |
|
1351 case INDEX_op_qemu_st8: |
|
1352 tcg_out_qemu_st (s, args, 0); |
|
1353 break; |
|
1354 case INDEX_op_qemu_st16: |
|
1355 tcg_out_qemu_st (s, args, 1); |
|
1356 break; |
|
1357 case INDEX_op_qemu_st32: |
|
1358 tcg_out_qemu_st (s, args, 2); |
|
1359 break; |
|
1360 case INDEX_op_qemu_st64: |
|
1361 tcg_out_qemu_st (s, args, 3); |
|
1362 break; |
|
1363 |
|
1364 case INDEX_op_ext8s_i32: |
|
1365 case INDEX_op_ext8s_i64: |
|
1366 c = EXTSB; |
|
1367 goto gen_ext; |
|
1368 case INDEX_op_ext16s_i32: |
|
1369 case INDEX_op_ext16s_i64: |
|
1370 c = EXTSH; |
|
1371 goto gen_ext; |
|
1372 case INDEX_op_ext32s_i64: |
|
1373 c = EXTSW; |
|
1374 goto gen_ext; |
|
1375 gen_ext: |
|
1376 tcg_out32 (s, c | RS (args[1]) | RA (args[0])); |
|
1377 break; |
|
1378 |
|
1379 default: |
|
1380 tcg_dump_ops (s, stderr); |
|
1381 tcg_abort (); |
|
1382 } |
|
1383 } |
|
1384 |
|
1385 static const TCGTargetOpDef ppc_op_defs[] = { |
|
1386 { INDEX_op_exit_tb, { } }, |
|
1387 { INDEX_op_goto_tb, { } }, |
|
1388 { INDEX_op_call, { "ri" } }, |
|
1389 { INDEX_op_jmp, { "ri" } }, |
|
1390 { INDEX_op_br, { } }, |
|
1391 |
|
1392 { INDEX_op_mov_i32, { "r", "r" } }, |
|
1393 { INDEX_op_mov_i64, { "r", "r" } }, |
|
1394 { INDEX_op_movi_i32, { "r" } }, |
|
1395 { INDEX_op_movi_i64, { "r" } }, |
|
1396 |
|
1397 { INDEX_op_ld8u_i32, { "r", "r" } }, |
|
1398 { INDEX_op_ld8s_i32, { "r", "r" } }, |
|
1399 { INDEX_op_ld16u_i32, { "r", "r" } }, |
|
1400 { INDEX_op_ld16s_i32, { "r", "r" } }, |
|
1401 { INDEX_op_ld_i32, { "r", "r" } }, |
|
1402 { INDEX_op_ld_i64, { "r", "r" } }, |
|
1403 { INDEX_op_st8_i32, { "r", "r" } }, |
|
1404 { INDEX_op_st8_i64, { "r", "r" } }, |
|
1405 { INDEX_op_st16_i32, { "r", "r" } }, |
|
1406 { INDEX_op_st16_i64, { "r", "r" } }, |
|
1407 { INDEX_op_st_i32, { "r", "r" } }, |
|
1408 { INDEX_op_st_i64, { "r", "r" } }, |
|
1409 { INDEX_op_st32_i64, { "r", "r" } }, |
|
1410 |
|
1411 { INDEX_op_ld8u_i64, { "r", "r" } }, |
|
1412 { INDEX_op_ld8s_i64, { "r", "r" } }, |
|
1413 { INDEX_op_ld16u_i64, { "r", "r" } }, |
|
1414 { INDEX_op_ld16s_i64, { "r", "r" } }, |
|
1415 { INDEX_op_ld32u_i64, { "r", "r" } }, |
|
1416 { INDEX_op_ld32s_i64, { "r", "r" } }, |
|
1417 { INDEX_op_ld_i64, { "r", "r" } }, |
|
1418 |
|
1419 { INDEX_op_add_i32, { "r", "r", "ri" } }, |
|
1420 { INDEX_op_mul_i32, { "r", "r", "ri" } }, |
|
1421 { INDEX_op_div_i32, { "r", "r", "r" } }, |
|
1422 { INDEX_op_divu_i32, { "r", "r", "r" } }, |
|
1423 { INDEX_op_rem_i32, { "r", "r", "r" } }, |
|
1424 { INDEX_op_remu_i32, { "r", "r", "r" } }, |
|
1425 { INDEX_op_sub_i32, { "r", "r", "ri" } }, |
|
1426 { INDEX_op_and_i32, { "r", "r", "ri" } }, |
|
1427 { INDEX_op_or_i32, { "r", "r", "ri" } }, |
|
1428 { INDEX_op_xor_i32, { "r", "r", "ri" } }, |
|
1429 |
|
1430 { INDEX_op_shl_i32, { "r", "r", "ri" } }, |
|
1431 { INDEX_op_shr_i32, { "r", "r", "ri" } }, |
|
1432 { INDEX_op_sar_i32, { "r", "r", "ri" } }, |
|
1433 |
|
1434 { INDEX_op_brcond_i32, { "r", "ri" } }, |
|
1435 { INDEX_op_brcond_i64, { "r", "ri" } }, |
|
1436 |
|
1437 { INDEX_op_neg_i32, { "r", "r" } }, |
|
1438 |
|
1439 { INDEX_op_add_i64, { "r", "r", "ri" } }, |
|
1440 { INDEX_op_sub_i64, { "r", "r", "ri" } }, |
|
1441 { INDEX_op_and_i64, { "r", "r", "rZ" } }, |
|
1442 { INDEX_op_or_i64, { "r", "r", "rZ" } }, |
|
1443 { INDEX_op_xor_i64, { "r", "r", "rZ" } }, |
|
1444 |
|
1445 { INDEX_op_shl_i64, { "r", "r", "ri" } }, |
|
1446 { INDEX_op_shr_i64, { "r", "r", "ri" } }, |
|
1447 { INDEX_op_sar_i64, { "r", "r", "ri" } }, |
|
1448 |
|
1449 { INDEX_op_mul_i64, { "r", "r", "r" } }, |
|
1450 { INDEX_op_div_i64, { "r", "r", "r" } }, |
|
1451 { INDEX_op_divu_i64, { "r", "r", "r" } }, |
|
1452 { INDEX_op_rem_i64, { "r", "r", "r" } }, |
|
1453 { INDEX_op_remu_i64, { "r", "r", "r" } }, |
|
1454 |
|
1455 { INDEX_op_neg_i64, { "r", "r" } }, |
|
1456 |
|
1457 { INDEX_op_qemu_ld8u, { "r", "L" } }, |
|
1458 { INDEX_op_qemu_ld8s, { "r", "L" } }, |
|
1459 { INDEX_op_qemu_ld16u, { "r", "L" } }, |
|
1460 { INDEX_op_qemu_ld16s, { "r", "L" } }, |
|
1461 { INDEX_op_qemu_ld32u, { "r", "L" } }, |
|
1462 { INDEX_op_qemu_ld32s, { "r", "L" } }, |
|
1463 { INDEX_op_qemu_ld64, { "r", "L" } }, |
|
1464 |
|
1465 { INDEX_op_qemu_st8, { "S", "S" } }, |
|
1466 { INDEX_op_qemu_st16, { "S", "S" } }, |
|
1467 { INDEX_op_qemu_st32, { "S", "S" } }, |
|
1468 { INDEX_op_qemu_st64, { "S", "S", "S" } }, |
|
1469 |
|
1470 { INDEX_op_ext8s_i32, { "r", "r" } }, |
|
1471 { INDEX_op_ext16s_i32, { "r", "r" } }, |
|
1472 { INDEX_op_ext8s_i64, { "r", "r" } }, |
|
1473 { INDEX_op_ext16s_i64, { "r", "r" } }, |
|
1474 { INDEX_op_ext32s_i64, { "r", "r" } }, |
|
1475 |
|
1476 { -1 }, |
|
1477 }; |
|
1478 |
|
1479 void tcg_target_init (TCGContext *s) |
|
1480 { |
|
1481 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); |
|
1482 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); |
|
1483 tcg_regset_set32 (tcg_target_call_clobber_regs, 0, |
|
1484 (1 << TCG_REG_R0) | |
|
1485 (1 << TCG_REG_R3) | |
|
1486 (1 << TCG_REG_R4) | |
|
1487 (1 << TCG_REG_R5) | |
|
1488 (1 << TCG_REG_R6) | |
|
1489 (1 << TCG_REG_R7) | |
|
1490 (1 << TCG_REG_R8) | |
|
1491 (1 << TCG_REG_R9) | |
|
1492 (1 << TCG_REG_R10) | |
|
1493 (1 << TCG_REG_R11) | |
|
1494 (1 << TCG_REG_R12) |
|
1495 ); |
|
1496 |
|
1497 tcg_regset_clear (s->reserved_regs); |
|
1498 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0); |
|
1499 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1); |
|
1500 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2); |
|
1501 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13); |
|
1502 |
|
1503 tcg_add_target_add_op_defs (ppc_op_defs); |
|
1504 } |