]> git.proxmox.com Git - qemu.git/blob - tcg/ppc64/tcg-target.c
tcg-ppc64: Improve and_i32 with constant
[qemu.git] / tcg / ppc64 / tcg-target.c
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_S16 0x100
26 #define TCG_CT_CONST_U16 0x200
27 #define TCG_CT_CONST_S32 0x400
28 #define TCG_CT_CONST_U32 0x800
29 #define TCG_CT_CONST_ZERO 0x1000
30
31 static uint8_t *tb_ret_addr;
32
33 #define FAST_PATH
34
35 #if TARGET_LONG_BITS == 32
36 #define LD_ADDR LWZU
37 #define CMP_L 0
38 #else
39 #define LD_ADDR LDU
40 #define CMP_L (1<<21)
41 #endif
42
43 #ifndef GUEST_BASE
44 #define GUEST_BASE 0
45 #endif
46
47 #ifdef CONFIG_USE_GUEST_BASE
48 #define TCG_GUEST_BASE_REG 30
49 #else
50 #define TCG_GUEST_BASE_REG 0
51 #endif
52
53 #ifndef NDEBUG
54 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
55 "r0",
56 "r1",
57 "r2",
58 "r3",
59 "r4",
60 "r5",
61 "r6",
62 "r7",
63 "r8",
64 "r9",
65 "r10",
66 "r11",
67 "r12",
68 "r13",
69 "r14",
70 "r15",
71 "r16",
72 "r17",
73 "r18",
74 "r19",
75 "r20",
76 "r21",
77 "r22",
78 "r23",
79 "r24",
80 "r25",
81 "r26",
82 "r27",
83 "r28",
84 "r29",
85 "r30",
86 "r31"
87 };
88 #endif
89
90 static const int tcg_target_reg_alloc_order[] = {
91 TCG_REG_R14,
92 TCG_REG_R15,
93 TCG_REG_R16,
94 TCG_REG_R17,
95 TCG_REG_R18,
96 TCG_REG_R19,
97 TCG_REG_R20,
98 TCG_REG_R21,
99 TCG_REG_R22,
100 TCG_REG_R23,
101 TCG_REG_R28,
102 TCG_REG_R29,
103 TCG_REG_R30,
104 TCG_REG_R31,
105 #ifdef __APPLE__
106 TCG_REG_R2,
107 #endif
108 TCG_REG_R3,
109 TCG_REG_R4,
110 TCG_REG_R5,
111 TCG_REG_R6,
112 TCG_REG_R7,
113 TCG_REG_R8,
114 TCG_REG_R9,
115 TCG_REG_R10,
116 #ifndef __APPLE__
117 TCG_REG_R11,
118 #endif
119 TCG_REG_R12,
120 TCG_REG_R24,
121 TCG_REG_R25,
122 TCG_REG_R26,
123 TCG_REG_R27
124 };
125
126 static const int tcg_target_call_iarg_regs[] = {
127 TCG_REG_R3,
128 TCG_REG_R4,
129 TCG_REG_R5,
130 TCG_REG_R6,
131 TCG_REG_R7,
132 TCG_REG_R8,
133 TCG_REG_R9,
134 TCG_REG_R10
135 };
136
137 static const int tcg_target_call_oarg_regs[] = {
138 TCG_REG_R3
139 };
140
141 static const int tcg_target_callee_save_regs[] = {
142 #ifdef __APPLE__
143 TCG_REG_R11,
144 #endif
145 TCG_REG_R14,
146 TCG_REG_R15,
147 TCG_REG_R16,
148 TCG_REG_R17,
149 TCG_REG_R18,
150 TCG_REG_R19,
151 TCG_REG_R20,
152 TCG_REG_R21,
153 TCG_REG_R22,
154 TCG_REG_R23,
155 TCG_REG_R24,
156 TCG_REG_R25,
157 TCG_REG_R26,
158 TCG_REG_R27, /* currently used for the global env */
159 TCG_REG_R28,
160 TCG_REG_R29,
161 TCG_REG_R30,
162 TCG_REG_R31
163 };
164
165 static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
166 {
167 tcg_target_long disp;
168
169 disp = target - (tcg_target_long) pc;
170 if ((disp << 38) >> 38 != disp)
171 tcg_abort ();
172
173 return disp & 0x3fffffc;
174 }
175
176 static void reloc_pc24 (void *pc, tcg_target_long target)
177 {
178 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
179 | reloc_pc24_val (pc, target);
180 }
181
182 static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
183 {
184 tcg_target_long disp;
185
186 disp = target - (tcg_target_long) pc;
187 if (disp != (int16_t) disp)
188 tcg_abort ();
189
190 return disp & 0xfffc;
191 }
192
193 static void reloc_pc14 (void *pc, tcg_target_long target)
194 {
195 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
196 | reloc_pc14_val (pc, target);
197 }
198
199 static void patch_reloc (uint8_t *code_ptr, int type,
200 tcg_target_long value, tcg_target_long addend)
201 {
202 value += addend;
203 switch (type) {
204 case R_PPC_REL14:
205 reloc_pc14 (code_ptr, value);
206 break;
207 case R_PPC_REL24:
208 reloc_pc24 (code_ptr, value);
209 break;
210 default:
211 tcg_abort ();
212 }
213 }
214
215 /* parse target specific constraints */
216 static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str)
217 {
218 const char *ct_str;
219
220 ct_str = *pct_str;
221 switch (ct_str[0]) {
222 case 'A': case 'B': case 'C': case 'D':
223 ct->ct |= TCG_CT_REG;
224 tcg_regset_set_reg (ct->u.regs, 3 + ct_str[0] - 'A');
225 break;
226 case 'r':
227 ct->ct |= TCG_CT_REG;
228 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
229 break;
230 case 'L': /* qemu_ld constraint */
231 ct->ct |= TCG_CT_REG;
232 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
233 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
234 #ifdef CONFIG_SOFTMMU
235 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
236 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5);
237 #endif
238 break;
239 case 'S': /* qemu_st constraint */
240 ct->ct |= TCG_CT_REG;
241 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
242 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
243 #ifdef CONFIG_SOFTMMU
244 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
245 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5);
246 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R6);
247 #endif
248 break;
249 case 'I':
250 ct->ct |= TCG_CT_CONST_S16;
251 break;
252 case 'J':
253 ct->ct |= TCG_CT_CONST_U16;
254 break;
255 case 'T':
256 ct->ct |= TCG_CT_CONST_S32;
257 break;
258 case 'U':
259 ct->ct |= TCG_CT_CONST_U32;
260 break;
261 case 'Z':
262 ct->ct |= TCG_CT_CONST_ZERO;
263 break;
264 default:
265 return -1;
266 }
267 ct_str++;
268 *pct_str = ct_str;
269 return 0;
270 }
271
272 /* test if a constant matches the constraint */
273 static int tcg_target_const_match (tcg_target_long val,
274 const TCGArgConstraint *arg_ct)
275 {
276 int ct = arg_ct->ct;
277 if (ct & TCG_CT_CONST) {
278 return 1;
279 } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
280 return 1;
281 } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
282 return 1;
283 } else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
284 return 1;
285 } else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
286 return 1;
287 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
288 return 1;
289 }
290 return 0;
291 }
292
293 #define OPCD(opc) ((opc)<<26)
294 #define XO19(opc) (OPCD(19)|((opc)<<1))
295 #define XO30(opc) (OPCD(30)|((opc)<<2))
296 #define XO31(opc) (OPCD(31)|((opc)<<1))
297 #define XO58(opc) (OPCD(58)|(opc))
298 #define XO62(opc) (OPCD(62)|(opc))
299
300 #define B OPCD( 18)
301 #define BC OPCD( 16)
302 #define LBZ OPCD( 34)
303 #define LHZ OPCD( 40)
304 #define LHA OPCD( 42)
305 #define LWZ OPCD( 32)
306 #define STB OPCD( 38)
307 #define STH OPCD( 44)
308 #define STW OPCD( 36)
309
310 #define STD XO62( 0)
311 #define STDU XO62( 1)
312 #define STDX XO31(149)
313
314 #define LD XO58( 0)
315 #define LDX XO31( 21)
316 #define LDU XO58( 1)
317 #define LWA XO58( 2)
318 #define LWAX XO31(341)
319
320 #define ADDIC OPCD( 12)
321 #define ADDI OPCD( 14)
322 #define ADDIS OPCD( 15)
323 #define ORI OPCD( 24)
324 #define ORIS OPCD( 25)
325 #define XORI OPCD( 26)
326 #define XORIS OPCD( 27)
327 #define ANDI OPCD( 28)
328 #define ANDIS OPCD( 29)
329 #define MULLI OPCD( 7)
330 #define CMPLI OPCD( 10)
331 #define CMPI OPCD( 11)
332 #define SUBFIC OPCD( 8)
333
334 #define LWZU OPCD( 33)
335 #define STWU OPCD( 37)
336
337 #define RLWINM OPCD( 21)
338
339 #define RLDICL XO30( 0)
340 #define RLDICR XO30( 1)
341 #define RLDIMI XO30( 3)
342
343 #define BCLR XO19( 16)
344 #define BCCTR XO19(528)
345 #define CRAND XO19(257)
346 #define CRANDC XO19(129)
347 #define CRNAND XO19(225)
348 #define CROR XO19(449)
349 #define CRNOR XO19( 33)
350
351 #define EXTSB XO31(954)
352 #define EXTSH XO31(922)
353 #define EXTSW XO31(986)
354 #define ADD XO31(266)
355 #define ADDE XO31(138)
356 #define ADDC XO31( 10)
357 #define AND XO31( 28)
358 #define SUBF XO31( 40)
359 #define SUBFC XO31( 8)
360 #define SUBFE XO31(136)
361 #define OR XO31(444)
362 #define XOR XO31(316)
363 #define MULLW XO31(235)
364 #define MULHWU XO31( 11)
365 #define DIVW XO31(491)
366 #define DIVWU XO31(459)
367 #define CMP XO31( 0)
368 #define CMPL XO31( 32)
369 #define LHBRX XO31(790)
370 #define LWBRX XO31(534)
371 #define STHBRX XO31(918)
372 #define STWBRX XO31(662)
373 #define MFSPR XO31(339)
374 #define MTSPR XO31(467)
375 #define SRAWI XO31(824)
376 #define NEG XO31(104)
377 #define MFCR XO31( 19)
378 #define NOR XO31(124)
379 #define CNTLZW XO31( 26)
380 #define CNTLZD XO31( 58)
381
382 #define MULLD XO31(233)
383 #define MULHD XO31( 73)
384 #define MULHDU XO31( 9)
385 #define DIVD XO31(489)
386 #define DIVDU XO31(457)
387
388 #define LBZX XO31( 87)
389 #define LHZX XO31(279)
390 #define LHAX XO31(343)
391 #define LWZX XO31( 23)
392 #define STBX XO31(215)
393 #define STHX XO31(407)
394 #define STWX XO31(151)
395
396 #define SPR(a,b) ((((a)<<5)|(b))<<11)
397 #define LR SPR(8, 0)
398 #define CTR SPR(9, 0)
399
400 #define SLW XO31( 24)
401 #define SRW XO31(536)
402 #define SRAW XO31(792)
403
404 #define SLD XO31( 27)
405 #define SRD XO31(539)
406 #define SRAD XO31(794)
407 #define SRADI XO31(413<<1)
408
409 #define TW XO31( 4)
410 #define TRAP (TW | TO (31))
411
412 #define RT(r) ((r)<<21)
413 #define RS(r) ((r)<<21)
414 #define RA(r) ((r)<<16)
415 #define RB(r) ((r)<<11)
416 #define TO(t) ((t)<<21)
417 #define SH(s) ((s)<<11)
418 #define MB(b) ((b)<<6)
419 #define ME(e) ((e)<<1)
420 #define BO(o) ((o)<<21)
421 #define MB64(b) ((b)<<5)
422
423 #define LK 1
424
425 #define TAB(t, a, b) (RT(t) | RA(a) | RB(b))
426 #define SAB(s, a, b) (RS(s) | RA(a) | RB(b))
427 #define TAI(s, a, i) (RT(s) | RA(a) | ((i) & 0xffff))
428 #define SAI(s, a, i) (RS(s) | RA(a) | ((i) & 0xffff))
429
430 #define BF(n) ((n)<<23)
431 #define BI(n, c) (((c)+((n)*4))<<16)
432 #define BT(n, c) (((c)+((n)*4))<<21)
433 #define BA(n, c) (((c)+((n)*4))<<16)
434 #define BB(n, c) (((c)+((n)*4))<<11)
435
436 #define BO_COND_TRUE BO (12)
437 #define BO_COND_FALSE BO ( 4)
438 #define BO_ALWAYS BO (20)
439
440 enum {
441 CR_LT,
442 CR_GT,
443 CR_EQ,
444 CR_SO
445 };
446
447 static const uint32_t tcg_to_bc[] = {
448 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
449 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
450 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
451 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
452 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
453 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
454 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
455 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
456 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
457 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
458 };
459
460 static inline void tcg_out_mov(TCGContext *s, TCGType type,
461 TCGReg ret, TCGReg arg)
462 {
463 tcg_out32 (s, OR | SAB (arg, ret, arg));
464 }
465
466 static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
467 int sh, int mb)
468 {
469 sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1);
470 mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f));
471 tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb);
472 }
473
474 static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
475 int sh, int mb, int me)
476 {
477 tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
478 }
479
480 static inline void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
481 {
482 tcg_out_rld(s, RLDICL, dst, src, 0, 32);
483 }
484
485 static inline void tcg_out_shli64(TCGContext *s, TCGReg dst, TCGReg src, int c)
486 {
487 tcg_out_rld(s, RLDICR, dst, src, c, 63 - c);
488 }
489
490 static inline void tcg_out_shri64(TCGContext *s, TCGReg dst, TCGReg src, int c)
491 {
492 tcg_out_rld(s, RLDICL, dst, src, 64 - c, c);
493 }
494
495 static void tcg_out_movi32(TCGContext *s, TCGReg ret, int32_t arg)
496 {
497 if (arg == (int16_t) arg) {
498 tcg_out32(s, ADDI | TAI(ret, 0, arg));
499 } else {
500 tcg_out32(s, ADDIS | TAI(ret, 0, arg >> 16));
501 if (arg & 0xffff) {
502 tcg_out32(s, ORI | SAI(ret, ret, arg));
503 }
504 }
505 }
506
507 static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
508 tcg_target_long arg)
509 {
510 if (type == TCG_TYPE_I32 || arg == (int32_t)arg) {
511 tcg_out_movi32(s, ret, arg);
512 } else if (arg == (uint32_t)arg && !(arg & 0x8000)) {
513 tcg_out32(s, ADDI | TAI(ret, 0, arg));
514 tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
515 } else {
516 int32_t high = arg >> 32;
517 tcg_out_movi32(s, ret, high);
518 if (high) {
519 tcg_out_shli64(s, ret, ret, 32);
520 }
521 if (arg & 0xffff0000) {
522 tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
523 }
524 if (arg & 0xffff) {
525 tcg_out32(s, ORI | SAI(ret, ret, arg));
526 }
527 }
528 }
529
530 static inline bool mask_operand(uint32_t c, int *mb, int *me)
531 {
532 uint32_t lsb, test;
533
534 /* Accept a bit pattern like:
535 0....01....1
536 1....10....0
537 0..01..10..0
538 Keep track of the transitions. */
539 if (c == 0 || c == -1) {
540 return false;
541 }
542 test = c;
543 lsb = test & -test;
544 test += lsb;
545 if (test & (test - 1)) {
546 return false;
547 }
548
549 *me = clz32(lsb);
550 *mb = test ? clz32(test & -test) + 1 : 0;
551 return true;
552 }
553
554 static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
555 {
556 int mb, me;
557
558 if ((c & 0xffff) == c) {
559 tcg_out32(s, ANDI | SAI(src, dst, c));
560 return;
561 } else if ((c & 0xffff0000) == c) {
562 tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
563 return;
564 } else if (mask_operand(c, &mb, &me)) {
565 tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
566 } else {
567 tcg_out_movi(s, TCG_TYPE_I32, 0, c);
568 tcg_out32(s, AND | SAB(src, dst, 0));
569 }
570 }
571
572 static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
573 int op_lo, int op_hi)
574 {
575 if (c >> 16) {
576 tcg_out32(s, op_hi | SAI(src, dst, c >> 16));
577 src = dst;
578 }
579 if (c & 0xffff) {
580 tcg_out32(s, op_lo | SAI(src, dst, c));
581 src = dst;
582 }
583 }
584
585 static void tcg_out_ori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
586 {
587 tcg_out_zori32(s, dst, src, c, ORI, ORIS);
588 }
589
590 static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
591 {
592 tcg_out_zori32(s, dst, src, c, XORI, XORIS);
593 }
594
595 static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
596 {
597 tcg_target_long disp;
598
599 disp = target - (tcg_target_long) s->code_ptr;
600 if ((disp << 38) >> 38 == disp)
601 tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
602 else {
603 tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target);
604 tcg_out32 (s, MTSPR | RS (0) | CTR);
605 tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
606 }
607 }
608
609 static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
610 {
611 #ifdef __APPLE__
612 if (const_arg) {
613 tcg_out_b (s, LK, arg);
614 }
615 else {
616 tcg_out32 (s, MTSPR | RS (arg) | LR);
617 tcg_out32 (s, BCLR | BO_ALWAYS | LK);
618 }
619 #else
620 int reg;
621
622 if (const_arg) {
623 reg = 2;
624 tcg_out_movi (s, TCG_TYPE_I64, reg, arg);
625 }
626 else reg = arg;
627
628 tcg_out32 (s, LD | RT (0) | RA (reg));
629 tcg_out32 (s, MTSPR | RA (0) | CTR);
630 tcg_out32 (s, LD | RT (11) | RA (reg) | 16);
631 tcg_out32 (s, LD | RT (2) | RA (reg) | 8);
632 tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
633 #endif
634 }
635
636 static void tcg_out_ldst(TCGContext *s, TCGReg ret, TCGReg addr,
637 int offset, int op1, int op2)
638 {
639 if (offset == (int16_t) offset) {
640 tcg_out32(s, op1 | TAI(ret, addr, offset));
641 } else {
642 tcg_out_movi(s, TCG_TYPE_I64, 0, offset);
643 tcg_out32(s, op2 | TAB(ret, addr, 0));
644 }
645 }
646
647 static void tcg_out_ldsta(TCGContext *s, TCGReg ret, TCGReg addr,
648 int offset, int op1, int op2)
649 {
650 if (offset == (int16_t) (offset & ~3)) {
651 tcg_out32(s, op1 | TAI(ret, addr, offset));
652 } else {
653 tcg_out_movi(s, TCG_TYPE_I64, 0, offset);
654 tcg_out32(s, op2 | TAB(ret, addr, 0));
655 }
656 }
657
658 #if defined (CONFIG_SOFTMMU)
659
660 #include "exec/softmmu_defs.h"
661
662 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
663 int mmu_idx) */
664 static const void * const qemu_ld_helpers[4] = {
665 helper_ldb_mmu,
666 helper_ldw_mmu,
667 helper_ldl_mmu,
668 helper_ldq_mmu,
669 };
670
671 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
672 uintxx_t val, int mmu_idx) */
673 static const void * const qemu_st_helpers[4] = {
674 helper_stb_mmu,
675 helper_stw_mmu,
676 helper_stl_mmu,
677 helper_stq_mmu,
678 };
679
680 static void tcg_out_tlb_read(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
681 TCGReg addr_reg, int s_bits, int offset)
682 {
683 #if TARGET_LONG_BITS == 32
684 tcg_out_ext32u(s, addr_reg, addr_reg);
685
686 tcg_out_rlw(s, RLWINM, r0, addr_reg,
687 32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
688 32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
689 31 - CPU_TLB_ENTRY_BITS);
690 tcg_out32(s, ADD | TAB(r0, r0, TCG_AREG0));
691 tcg_out32(s, LWZU | TAI(r1, r0, offset));
692 tcg_out_rlw(s, RLWINM, r2, addr_reg, 0,
693 (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
694 #else
695 tcg_out_rld (s, RLDICL, r0, addr_reg,
696 64 - TARGET_PAGE_BITS,
697 64 - CPU_TLB_BITS);
698 tcg_out_shli64(s, r0, r0, CPU_TLB_ENTRY_BITS);
699
700 tcg_out32(s, ADD | TAB(r0, r0, TCG_AREG0));
701 tcg_out32(s, LD_ADDR | TAI(r1, r0, offset));
702
703 if (!s_bits) {
704 tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS);
705 }
706 else {
707 tcg_out_rld (s, RLDICL, r2, addr_reg,
708 64 - TARGET_PAGE_BITS,
709 TARGET_PAGE_BITS - s_bits);
710 tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0);
711 }
712 #endif
713 }
714 #endif
715
716 static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
717 {
718 TCGReg addr_reg, data_reg, r0, r1, rbase;
719 int bswap;
720 #ifdef CONFIG_SOFTMMU
721 TCGReg r2, ir;
722 int mem_index, s_bits;
723 void *label1_ptr, *label2_ptr;
724 #endif
725
726 data_reg = *args++;
727 addr_reg = *args++;
728
729 #ifdef CONFIG_SOFTMMU
730 mem_index = *args;
731 s_bits = opc & 3;
732
733 r0 = 3;
734 r1 = 4;
735 r2 = 0;
736 rbase = 0;
737
738 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits,
739 offsetof (CPUArchState, tlb_table[mem_index][0].addr_read));
740
741 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
742
743 label1_ptr = s->code_ptr;
744 #ifdef FAST_PATH
745 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
746 #endif
747
748 /* slow path */
749 ir = 3;
750 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
751 tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
752 tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
753
754 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
755
756 switch (opc) {
757 case 0|4:
758 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
759 break;
760 case 1|4:
761 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
762 break;
763 case 2|4:
764 tcg_out32 (s, EXTSW | RA (data_reg) | RS (3));
765 break;
766 case 0:
767 case 1:
768 case 2:
769 case 3:
770 if (data_reg != 3)
771 tcg_out_mov (s, TCG_TYPE_I64, data_reg, 3);
772 break;
773 }
774 label2_ptr = s->code_ptr;
775 tcg_out32 (s, B);
776
777 /* label1: fast path */
778 #ifdef FAST_PATH
779 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
780 #endif
781
782 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
783 tcg_out32(s, LD | TAI(r0, r0,
784 offsetof(CPUTLBEntry, addend)
785 - offsetof(CPUTLBEntry, addr_read)));
786 /* r0 = env->tlb_table[mem_index][index].addend */
787 tcg_out32(s, ADD | TAB(r0, r0, addr_reg));
788 /* r0 = env->tlb_table[mem_index][index].addend + addr */
789
790 #else /* !CONFIG_SOFTMMU */
791 #if TARGET_LONG_BITS == 32
792 tcg_out_ext32u(s, addr_reg, addr_reg);
793 #endif
794 r0 = addr_reg;
795 r1 = 3;
796 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
797 #endif
798
799 #ifdef TARGET_WORDS_BIGENDIAN
800 bswap = 0;
801 #else
802 bswap = 1;
803 #endif
804 switch (opc) {
805 default:
806 case 0:
807 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
808 break;
809 case 0|4:
810 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
811 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
812 break;
813 case 1:
814 if (bswap)
815 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
816 else
817 tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0));
818 break;
819 case 1|4:
820 if (bswap) {
821 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
822 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
823 }
824 else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0));
825 break;
826 case 2:
827 if (bswap)
828 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
829 else
830 tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0));
831 break;
832 case 2|4:
833 if (bswap) {
834 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
835 tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg));
836 }
837 else tcg_out32 (s, LWAX | TAB (data_reg, rbase, r0));
838 break;
839 case 3:
840 #ifdef CONFIG_USE_GUEST_BASE
841 if (bswap) {
842 tcg_out32(s, ADDI | TAI(r1, r0, 4));
843 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
844 tcg_out32 (s, LWBRX | TAB ( r1, rbase, r1));
845 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
846 }
847 else tcg_out32 (s, LDX | TAB (data_reg, rbase, r0));
848 #else
849 if (bswap) {
850 tcg_out_movi32 (s, 0, 4);
851 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
852 tcg_out32 (s, LWBRX | RT ( r1) | RA (r0));
853 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
854 }
855 else tcg_out32 (s, LD | RT (data_reg) | RA (r0));
856 #endif
857 break;
858 }
859
860 #ifdef CONFIG_SOFTMMU
861 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
862 #endif
863 }
864
865 static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
866 {
867 TCGReg addr_reg, r0, r1, rbase, data_reg;
868 int bswap;
869 #ifdef CONFIG_SOFTMMU
870 TCGReg r2, ir;
871 int mem_index;
872 void *label1_ptr, *label2_ptr;
873 #endif
874
875 data_reg = *args++;
876 addr_reg = *args++;
877
878 #ifdef CONFIG_SOFTMMU
879 mem_index = *args;
880
881 r0 = 3;
882 r1 = 4;
883 r2 = 0;
884 rbase = 0;
885
886 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc,
887 offsetof (CPUArchState, tlb_table[mem_index][0].addr_write));
888
889 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
890
891 label1_ptr = s->code_ptr;
892 #ifdef FAST_PATH
893 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
894 #endif
895
896 /* slow path */
897 ir = 3;
898 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
899 tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
900 tcg_out_rld (s, RLDICL, ir++, data_reg, 0, 64 - (1 << (3 + opc)));
901 tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
902
903 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
904
905 label2_ptr = s->code_ptr;
906 tcg_out32 (s, B);
907
908 /* label1: fast path */
909 #ifdef FAST_PATH
910 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
911 #endif
912
913 tcg_out32 (s, (LD
914 | RT (r0)
915 | RA (r0)
916 | (offsetof (CPUTLBEntry, addend)
917 - offsetof (CPUTLBEntry, addr_write))
918 ));
919 /* r0 = env->tlb_table[mem_index][index].addend */
920 tcg_out32(s, ADD | TAB(r0, r0, addr_reg));
921 /* r0 = env->tlb_table[mem_index][index].addend + addr */
922
923 #else /* !CONFIG_SOFTMMU */
924 #if TARGET_LONG_BITS == 32
925 tcg_out_ext32u(s, addr_reg, addr_reg);
926 #endif
927 r1 = 3;
928 r0 = addr_reg;
929 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
930 #endif
931
932 #ifdef TARGET_WORDS_BIGENDIAN
933 bswap = 0;
934 #else
935 bswap = 1;
936 #endif
937 switch (opc) {
938 case 0:
939 tcg_out32 (s, STBX | SAB (data_reg, rbase, r0));
940 break;
941 case 1:
942 if (bswap)
943 tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0));
944 else
945 tcg_out32 (s, STHX | SAB (data_reg, rbase, r0));
946 break;
947 case 2:
948 if (bswap)
949 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
950 else
951 tcg_out32 (s, STWX | SAB (data_reg, rbase, r0));
952 break;
953 case 3:
954 if (bswap) {
955 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
956 tcg_out32(s, ADDI | TAI(r1, r0, 4));
957 tcg_out_shri64(s, 0, data_reg, 32);
958 tcg_out32 (s, STWBRX | SAB (0, rbase, r1));
959 }
960 else tcg_out32 (s, STDX | SAB (data_reg, rbase, r0));
961 break;
962 }
963
964 #ifdef CONFIG_SOFTMMU
965 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
966 #endif
967 }
968
969 static void tcg_target_qemu_prologue (TCGContext *s)
970 {
971 int i, frame_size;
972 #ifndef __APPLE__
973 uint64_t addr;
974 #endif
975
976 frame_size = 0
977 + 8 /* back chain */
978 + 8 /* CR */
979 + 8 /* LR */
980 + 8 /* compiler doubleword */
981 + 8 /* link editor doubleword */
982 + 8 /* TOC save area */
983 + TCG_STATIC_CALL_ARGS_SIZE
984 + ARRAY_SIZE (tcg_target_callee_save_regs) * 8
985 + CPU_TEMP_BUF_NLONGS * sizeof(long)
986 ;
987 frame_size = (frame_size + 15) & ~15;
988
989 tcg_set_frame (s, TCG_REG_CALL_STACK, frame_size
990 - CPU_TEMP_BUF_NLONGS * sizeof (long),
991 CPU_TEMP_BUF_NLONGS * sizeof (long));
992
993 #ifndef __APPLE__
994 /* First emit adhoc function descriptor */
995 addr = (uint64_t) s->code_ptr + 24;
996 tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */
997 s->code_ptr += 16; /* skip TOC and environment pointer */
998 #endif
999
1000 /* Prologue */
1001 tcg_out32 (s, MFSPR | RT (0) | LR);
1002 tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff));
1003 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
1004 tcg_out32 (s, (STD
1005 | RS (tcg_target_callee_save_regs[i])
1006 | RA (1)
1007 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
1008 )
1009 );
1010 tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16));
1011
1012 #ifdef CONFIG_USE_GUEST_BASE
1013 if (GUEST_BASE) {
1014 tcg_out_movi (s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE);
1015 tcg_regset_set_reg (s->reserved_regs, TCG_GUEST_BASE_REG);
1016 }
1017 #endif
1018
1019 tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1020 tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
1021 tcg_out32 (s, BCCTR | BO_ALWAYS);
1022
1023 /* Epilogue */
1024 tb_ret_addr = s->code_ptr;
1025
1026 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
1027 tcg_out32 (s, (LD
1028 | RT (tcg_target_callee_save_regs[i])
1029 | RA (1)
1030 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
1031 )
1032 );
1033 tcg_out32(s, LD | TAI(0, 1, frame_size + 16));
1034 tcg_out32(s, MTSPR | RS(0) | LR);
1035 tcg_out32(s, ADDI | TAI(1, 1, frame_size));
1036 tcg_out32(s, BCLR | BO_ALWAYS);
1037 }
1038
1039 static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
1040 tcg_target_long arg2)
1041 {
1042 if (type == TCG_TYPE_I32)
1043 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
1044 else
1045 tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
1046 }
1047
1048 static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
1049 tcg_target_long arg2)
1050 {
1051 if (type == TCG_TYPE_I32)
1052 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
1053 else
1054 tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX);
1055 }
1056
1057 static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
1058 int const_arg2, int cr, int arch64)
1059 {
1060 int imm;
1061 uint32_t op;
1062
1063 switch (cond) {
1064 case TCG_COND_EQ:
1065 case TCG_COND_NE:
1066 if (const_arg2) {
1067 if ((int16_t) arg2 == arg2) {
1068 op = CMPI;
1069 imm = 1;
1070 break;
1071 }
1072 else if ((uint16_t) arg2 == arg2) {
1073 op = CMPLI;
1074 imm = 1;
1075 break;
1076 }
1077 }
1078 op = CMPL;
1079 imm = 0;
1080 break;
1081
1082 case TCG_COND_LT:
1083 case TCG_COND_GE:
1084 case TCG_COND_LE:
1085 case TCG_COND_GT:
1086 if (const_arg2) {
1087 if ((int16_t) arg2 == arg2) {
1088 op = CMPI;
1089 imm = 1;
1090 break;
1091 }
1092 }
1093 op = CMP;
1094 imm = 0;
1095 break;
1096
1097 case TCG_COND_LTU:
1098 case TCG_COND_GEU:
1099 case TCG_COND_LEU:
1100 case TCG_COND_GTU:
1101 if (const_arg2) {
1102 if ((uint16_t) arg2 == arg2) {
1103 op = CMPLI;
1104 imm = 1;
1105 break;
1106 }
1107 }
1108 op = CMPL;
1109 imm = 0;
1110 break;
1111
1112 default:
1113 tcg_abort ();
1114 }
1115 op |= BF (cr) | (arch64 << 21);
1116
1117 if (imm)
1118 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
1119 else {
1120 if (const_arg2) {
1121 tcg_out_movi (s, TCG_TYPE_I64, 0, arg2);
1122 tcg_out32 (s, op | RA (arg1) | RB (0));
1123 }
1124 else
1125 tcg_out32 (s, op | RA (arg1) | RB (arg2));
1126 }
1127
1128 }
1129
1130 static void tcg_out_setcond (TCGContext *s, TCGType type, TCGCond cond,
1131 TCGArg arg0, TCGArg arg1, TCGArg arg2,
1132 int const_arg2)
1133 {
1134 int crop, sh, arg;
1135
1136 switch (cond) {
1137 case TCG_COND_EQ:
1138 if (const_arg2) {
1139 if (!arg2) {
1140 arg = arg1;
1141 }
1142 else {
1143 arg = 0;
1144 if ((uint16_t) arg2 == arg2) {
1145 tcg_out32(s, XORI | SAI(arg1, 0, arg2));
1146 }
1147 else {
1148 tcg_out_movi (s, type, 0, arg2);
1149 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1150 }
1151 }
1152 }
1153 else {
1154 arg = 0;
1155 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1156 }
1157
1158 if (type == TCG_TYPE_I64) {
1159 tcg_out32 (s, CNTLZD | RS (arg) | RA (0));
1160 tcg_out_rld (s, RLDICL, arg0, 0, 58, 6);
1161 }
1162 else {
1163 tcg_out32 (s, CNTLZW | RS (arg) | RA (0));
1164 tcg_out_rlw(s, RLWINM, arg0, 0, 27, 5, 31);
1165 }
1166 break;
1167
1168 case TCG_COND_NE:
1169 if (const_arg2) {
1170 if (!arg2) {
1171 arg = arg1;
1172 }
1173 else {
1174 arg = 0;
1175 if ((uint16_t) arg2 == arg2) {
1176 tcg_out32(s, XORI | SAI(arg1, 0, arg2));
1177 } else {
1178 tcg_out_movi (s, type, 0, arg2);
1179 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1180 }
1181 }
1182 }
1183 else {
1184 arg = 0;
1185 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1186 }
1187
1188 /* Make sure and discard the high 32-bits of the input. */
1189 if (type == TCG_TYPE_I32) {
1190 tcg_out32(s, EXTSW | RA(TCG_REG_R0) | RS(arg));
1191 arg = TCG_REG_R0;
1192 }
1193
1194 if (arg == arg1 && arg1 == arg0) {
1195 tcg_out32(s, ADDIC | TAI(0, arg, -1));
1196 tcg_out32(s, SUBFE | TAB(arg0, 0, arg));
1197 }
1198 else {
1199 tcg_out32(s, ADDIC | TAI(arg0, arg, -1));
1200 tcg_out32(s, SUBFE | TAB(arg0, arg0, arg));
1201 }
1202 break;
1203
1204 case TCG_COND_GT:
1205 case TCG_COND_GTU:
1206 sh = 30;
1207 crop = 0;
1208 goto crtest;
1209
1210 case TCG_COND_LT:
1211 case TCG_COND_LTU:
1212 sh = 29;
1213 crop = 0;
1214 goto crtest;
1215
1216 case TCG_COND_GE:
1217 case TCG_COND_GEU:
1218 sh = 31;
1219 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
1220 goto crtest;
1221
1222 case TCG_COND_LE:
1223 case TCG_COND_LEU:
1224 sh = 31;
1225 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
1226 crtest:
1227 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, type == TCG_TYPE_I64);
1228 if (crop) tcg_out32 (s, crop);
1229 tcg_out32 (s, MFCR | RT (0));
1230 tcg_out_rlw(s, RLWINM, arg0, 0, sh, 31, 31);
1231 break;
1232
1233 default:
1234 tcg_abort ();
1235 }
1236 }
1237
1238 static void tcg_out_bc (TCGContext *s, int bc, int label_index)
1239 {
1240 TCGLabel *l = &s->labels[label_index];
1241
1242 if (l->has_value)
1243 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
1244 else {
1245 uint16_t val = *(uint16_t *) &s->code_ptr[2];
1246
1247 /* Thanks to Andrzej Zaborowski */
1248 tcg_out32 (s, bc | (val & 0xfffc));
1249 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
1250 }
1251 }
1252
1253 static void tcg_out_brcond (TCGContext *s, TCGCond cond,
1254 TCGArg arg1, TCGArg arg2, int const_arg2,
1255 int label_index, int arch64)
1256 {
1257 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, arch64);
1258 tcg_out_bc (s, tcg_to_bc[cond], label_index);
1259 }
1260
1261 void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
1262 {
1263 TCGContext s;
1264 unsigned long patch_size;
1265
1266 s.code_ptr = (uint8_t *) jmp_addr;
1267 tcg_out_b (&s, 0, addr);
1268 patch_size = s.code_ptr - (uint8_t *) jmp_addr;
1269 flush_icache_range (jmp_addr, jmp_addr + patch_size);
1270 }
1271
1272 static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
1273 const int *const_args)
1274 {
1275 TCGArg a0, a1, a2;
1276 int c;
1277
1278 switch (opc) {
1279 case INDEX_op_exit_tb:
1280 tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
1281 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
1282 break;
1283 case INDEX_op_goto_tb:
1284 if (s->tb_jmp_offset) {
1285 /* direct jump method */
1286
1287 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1288 s->code_ptr += 28;
1289 }
1290 else {
1291 tcg_abort ();
1292 }
1293 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1294 break;
1295 case INDEX_op_br:
1296 {
1297 TCGLabel *l = &s->labels[args[0]];
1298
1299 if (l->has_value) {
1300 tcg_out_b (s, 0, l->u.value);
1301 }
1302 else {
1303 uint32_t val = *(uint32_t *) s->code_ptr;
1304
1305 /* Thanks to Andrzej Zaborowski */
1306 tcg_out32 (s, B | (val & 0x3fffffc));
1307 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1308 }
1309 }
1310 break;
1311 case INDEX_op_call:
1312 tcg_out_call (s, args[0], const_args[0]);
1313 break;
1314 case INDEX_op_movi_i32:
1315 tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]);
1316 break;
1317 case INDEX_op_movi_i64:
1318 tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]);
1319 break;
1320 case INDEX_op_ld8u_i32:
1321 case INDEX_op_ld8u_i64:
1322 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1323 break;
1324 case INDEX_op_ld8s_i32:
1325 case INDEX_op_ld8s_i64:
1326 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1327 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1328 break;
1329 case INDEX_op_ld16u_i32:
1330 case INDEX_op_ld16u_i64:
1331 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1332 break;
1333 case INDEX_op_ld16s_i32:
1334 case INDEX_op_ld16s_i64:
1335 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1336 break;
1337 case INDEX_op_ld_i32:
1338 case INDEX_op_ld32u_i64:
1339 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1340 break;
1341 case INDEX_op_ld32s_i64:
1342 tcg_out_ldsta (s, args[0], args[1], args[2], LWA, LWAX);
1343 break;
1344 case INDEX_op_ld_i64:
1345 tcg_out_ldsta (s, args[0], args[1], args[2], LD, LDX);
1346 break;
1347 case INDEX_op_st8_i32:
1348 case INDEX_op_st8_i64:
1349 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1350 break;
1351 case INDEX_op_st16_i32:
1352 case INDEX_op_st16_i64:
1353 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1354 break;
1355 case INDEX_op_st_i32:
1356 case INDEX_op_st32_i64:
1357 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1358 break;
1359 case INDEX_op_st_i64:
1360 tcg_out_ldsta (s, args[0], args[1], args[2], STD, STDX);
1361 break;
1362
1363 case INDEX_op_add_i32:
1364 a0 = args[0], a1 = args[1], a2 = args[2];
1365 if (const_args[2]) {
1366 int32_t l, h;
1367 do_addi_32:
1368 l = (int16_t)a2;
1369 h = a2 - l;
1370 if (h) {
1371 tcg_out32(s, ADDIS | TAI(a0, a1, h >> 16));
1372 a1 = a0;
1373 }
1374 if (l || a0 != a1) {
1375 tcg_out32(s, ADDI | TAI(a0, a1, l));
1376 }
1377 } else {
1378 tcg_out32(s, ADD | TAB(a0, a1, a2));
1379 }
1380 break;
1381 case INDEX_op_sub_i32:
1382 a0 = args[0], a1 = args[1], a2 = args[2];
1383 if (const_args[1]) {
1384 if (const_args[2]) {
1385 tcg_out_movi(s, TCG_TYPE_I32, a0, a1 - a2);
1386 } else {
1387 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
1388 }
1389 } else if (const_args[2]) {
1390 a2 = -a2;
1391 goto do_addi_32;
1392 } else {
1393 tcg_out32(s, SUBF | TAB(a0, a2, a1));
1394 }
1395 break;
1396
1397 case INDEX_op_and_i32:
1398 if (const_args[2]) {
1399 tcg_out_andi32(s, args[0], args[1], args[2]);
1400 } else {
1401 tcg_out32(s, AND | SAB(args[1], args[0], args[2]));
1402 }
1403 break;
1404 case INDEX_op_and_i64:
1405 if (const_args[2]) {
1406 if ((args[2] & 0xffff) == args[2]) {
1407 tcg_out32(s, ANDI | SAI(args[1], args[0], args[2]));
1408 } else if ((args[2] & 0xffff0000) == args[2]) {
1409 tcg_out32(s, ANDIS | SAI(args[1], args[0], args[2] >> 16));
1410 } else {
1411 tcg_out_movi (s, (opc == INDEX_op_and_i32
1412 ? TCG_TYPE_I32
1413 : TCG_TYPE_I64),
1414 0, args[2]);
1415 tcg_out32 (s, AND | SAB (args[1], args[0], 0));
1416 }
1417 }
1418 else
1419 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1420 break;
1421 case INDEX_op_or_i64:
1422 case INDEX_op_or_i32:
1423 a0 = args[0], a1 = args[1], a2 = args[2];
1424 if (const_args[2]) {
1425 tcg_out_ori32(s, a0, a1, a2);
1426 } else {
1427 tcg_out32(s, OR | SAB(a1, a0, a2));
1428 }
1429 break;
1430 case INDEX_op_xor_i64:
1431 case INDEX_op_xor_i32:
1432 a0 = args[0], a1 = args[1], a2 = args[2];
1433 if (const_args[2]) {
1434 tcg_out_xori32(s, a0, a1, a2);
1435 } else {
1436 tcg_out32(s, XOR | SAB(a1, a0, a2));
1437 }
1438 break;
1439
1440 case INDEX_op_mul_i32:
1441 if (const_args[2]) {
1442 if (args[2] == (int16_t) args[2])
1443 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1444 | (args[2] & 0xffff));
1445 else {
1446 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1447 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1448 }
1449 }
1450 else
1451 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1452 break;
1453
1454 case INDEX_op_div_i32:
1455 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1456 break;
1457
1458 case INDEX_op_divu_i32:
1459 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1460 break;
1461
1462 case INDEX_op_rem_i32:
1463 tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1464 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1465 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1466 break;
1467
1468 case INDEX_op_remu_i32:
1469 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1470 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1471 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1472 break;
1473
1474 case INDEX_op_shl_i32:
1475 if (const_args[2]) {
1476 tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
1477 } else {
1478 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
1479 }
1480 break;
1481 case INDEX_op_shr_i32:
1482 if (const_args[2]) {
1483 tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], args[2], 31);
1484 } else {
1485 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
1486 }
1487 break;
1488 case INDEX_op_sar_i32:
1489 if (const_args[2])
1490 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1491 else
1492 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1493 break;
1494
1495 case INDEX_op_brcond_i32:
1496 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 0);
1497 break;
1498
1499 case INDEX_op_brcond_i64:
1500 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 1);
1501 break;
1502
1503 case INDEX_op_neg_i32:
1504 case INDEX_op_neg_i64:
1505 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1506 break;
1507
1508 case INDEX_op_not_i32:
1509 case INDEX_op_not_i64:
1510 tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
1511 break;
1512
1513 case INDEX_op_add_i64:
1514 a0 = args[0], a1 = args[1], a2 = args[2];
1515 if (const_args[2]) {
1516 int32_t l0, h1, h2;
1517 do_addi_64:
1518 /* We can always split any 32-bit signed constant into 3 pieces.
1519 Note the positive 0x80000000 coming from the sub_i64 path,
1520 handled with the same code we need for eg 0x7fff8000. */
1521 assert(a2 == (int32_t)a2 || a2 == 0x80000000);
1522 l0 = (int16_t)a2;
1523 h1 = a2 - l0;
1524 h2 = 0;
1525 if (h1 < 0 && (int64_t)a2 > 0) {
1526 h2 = 0x40000000;
1527 h1 = a2 - h2 - l0;
1528 }
1529 assert((TCGArg)h2 + h1 + l0 == a2);
1530
1531 if (h2) {
1532 tcg_out32(s, ADDIS | TAI(a0, a1, h2 >> 16));
1533 a1 = a0;
1534 }
1535 if (h1) {
1536 tcg_out32(s, ADDIS | TAI(a0, a1, h1 >> 16));
1537 a1 = a0;
1538 }
1539 if (l0 || a0 != a1) {
1540 tcg_out32(s, ADDI | TAI(a0, a1, l0));
1541 }
1542 } else {
1543 tcg_out32(s, ADD | TAB(a0, a1, a2));
1544 }
1545 break;
1546 case INDEX_op_sub_i64:
1547 a0 = args[0], a1 = args[1], a2 = args[2];
1548 if (const_args[1]) {
1549 if (const_args[2]) {
1550 tcg_out_movi(s, TCG_TYPE_I64, a0, a1 - a2);
1551 } else {
1552 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
1553 }
1554 } else if (const_args[2]) {
1555 a2 = -a2;
1556 goto do_addi_64;
1557 } else {
1558 tcg_out32(s, SUBF | TAB(a0, a2, a1));
1559 }
1560 break;
1561
1562 case INDEX_op_shl_i64:
1563 if (const_args[2])
1564 tcg_out_shli64(s, args[0], args[1], args[2]);
1565 else
1566 tcg_out32 (s, SLD | SAB (args[1], args[0], args[2]));
1567 break;
1568 case INDEX_op_shr_i64:
1569 if (const_args[2])
1570 tcg_out_shri64(s, args[0], args[1], args[2]);
1571 else
1572 tcg_out32 (s, SRD | SAB (args[1], args[0], args[2]));
1573 break;
1574 case INDEX_op_sar_i64:
1575 if (const_args[2]) {
1576 int sh = SH (args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
1577 tcg_out32 (s, SRADI | RA (args[0]) | RS (args[1]) | sh);
1578 }
1579 else
1580 tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2]));
1581 break;
1582
1583 case INDEX_op_mul_i64:
1584 tcg_out32 (s, MULLD | TAB (args[0], args[1], args[2]));
1585 break;
1586 case INDEX_op_div_i64:
1587 tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2]));
1588 break;
1589 case INDEX_op_divu_i64:
1590 tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
1591 break;
1592 case INDEX_op_rem_i64:
1593 tcg_out32 (s, DIVD | TAB (0, args[1], args[2]));
1594 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1595 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1596 break;
1597 case INDEX_op_remu_i64:
1598 tcg_out32 (s, DIVDU | TAB (0, args[1], args[2]));
1599 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1600 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1601 break;
1602
1603 case INDEX_op_qemu_ld8u:
1604 tcg_out_qemu_ld (s, args, 0);
1605 break;
1606 case INDEX_op_qemu_ld8s:
1607 tcg_out_qemu_ld (s, args, 0 | 4);
1608 break;
1609 case INDEX_op_qemu_ld16u:
1610 tcg_out_qemu_ld (s, args, 1);
1611 break;
1612 case INDEX_op_qemu_ld16s:
1613 tcg_out_qemu_ld (s, args, 1 | 4);
1614 break;
1615 case INDEX_op_qemu_ld32:
1616 case INDEX_op_qemu_ld32u:
1617 tcg_out_qemu_ld (s, args, 2);
1618 break;
1619 case INDEX_op_qemu_ld32s:
1620 tcg_out_qemu_ld (s, args, 2 | 4);
1621 break;
1622 case INDEX_op_qemu_ld64:
1623 tcg_out_qemu_ld (s, args, 3);
1624 break;
1625 case INDEX_op_qemu_st8:
1626 tcg_out_qemu_st (s, args, 0);
1627 break;
1628 case INDEX_op_qemu_st16:
1629 tcg_out_qemu_st (s, args, 1);
1630 break;
1631 case INDEX_op_qemu_st32:
1632 tcg_out_qemu_st (s, args, 2);
1633 break;
1634 case INDEX_op_qemu_st64:
1635 tcg_out_qemu_st (s, args, 3);
1636 break;
1637
1638 case INDEX_op_ext8s_i32:
1639 case INDEX_op_ext8s_i64:
1640 c = EXTSB;
1641 goto gen_ext;
1642 case INDEX_op_ext16s_i32:
1643 case INDEX_op_ext16s_i64:
1644 c = EXTSH;
1645 goto gen_ext;
1646 case INDEX_op_ext32s_i64:
1647 c = EXTSW;
1648 goto gen_ext;
1649 gen_ext:
1650 tcg_out32 (s, c | RS (args[1]) | RA (args[0]));
1651 break;
1652
1653 case INDEX_op_ext32u_i64:
1654 tcg_out_ext32u(s, args[0], args[1]);
1655 break;
1656
1657 case INDEX_op_setcond_i32:
1658 tcg_out_setcond (s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
1659 const_args[2]);
1660 break;
1661 case INDEX_op_setcond_i64:
1662 tcg_out_setcond (s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
1663 const_args[2]);
1664 break;
1665
1666 default:
1667 tcg_dump_ops (s);
1668 tcg_abort ();
1669 }
1670 }
1671
1672 static const TCGTargetOpDef ppc_op_defs[] = {
1673 { INDEX_op_exit_tb, { } },
1674 { INDEX_op_goto_tb, { } },
1675 { INDEX_op_call, { "ri" } },
1676 { INDEX_op_br, { } },
1677
1678 { INDEX_op_mov_i32, { "r", "r" } },
1679 { INDEX_op_mov_i64, { "r", "r" } },
1680 { INDEX_op_movi_i32, { "r" } },
1681 { INDEX_op_movi_i64, { "r" } },
1682
1683 { INDEX_op_ld8u_i32, { "r", "r" } },
1684 { INDEX_op_ld8s_i32, { "r", "r" } },
1685 { INDEX_op_ld16u_i32, { "r", "r" } },
1686 { INDEX_op_ld16s_i32, { "r", "r" } },
1687 { INDEX_op_ld_i32, { "r", "r" } },
1688 { INDEX_op_ld_i64, { "r", "r" } },
1689 { INDEX_op_st8_i32, { "r", "r" } },
1690 { INDEX_op_st8_i64, { "r", "r" } },
1691 { INDEX_op_st16_i32, { "r", "r" } },
1692 { INDEX_op_st16_i64, { "r", "r" } },
1693 { INDEX_op_st_i32, { "r", "r" } },
1694 { INDEX_op_st_i64, { "r", "r" } },
1695 { INDEX_op_st32_i64, { "r", "r" } },
1696
1697 { INDEX_op_ld8u_i64, { "r", "r" } },
1698 { INDEX_op_ld8s_i64, { "r", "r" } },
1699 { INDEX_op_ld16u_i64, { "r", "r" } },
1700 { INDEX_op_ld16s_i64, { "r", "r" } },
1701 { INDEX_op_ld32u_i64, { "r", "r" } },
1702 { INDEX_op_ld32s_i64, { "r", "r" } },
1703
1704 { INDEX_op_add_i32, { "r", "r", "ri" } },
1705 { INDEX_op_mul_i32, { "r", "r", "ri" } },
1706 { INDEX_op_div_i32, { "r", "r", "r" } },
1707 { INDEX_op_divu_i32, { "r", "r", "r" } },
1708 { INDEX_op_rem_i32, { "r", "r", "r" } },
1709 { INDEX_op_remu_i32, { "r", "r", "r" } },
1710 { INDEX_op_sub_i32, { "r", "rI", "ri" } },
1711 { INDEX_op_and_i32, { "r", "r", "ri" } },
1712 { INDEX_op_or_i32, { "r", "r", "ri" } },
1713 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1714
1715 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1716 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1717 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1718
1719 { INDEX_op_brcond_i32, { "r", "ri" } },
1720 { INDEX_op_brcond_i64, { "r", "ri" } },
1721
1722 { INDEX_op_neg_i32, { "r", "r" } },
1723 { INDEX_op_not_i32, { "r", "r" } },
1724
1725 { INDEX_op_add_i64, { "r", "r", "rT" } },
1726 { INDEX_op_sub_i64, { "r", "rI", "rT" } },
1727 { INDEX_op_and_i64, { "r", "r", "rU" } },
1728 { INDEX_op_or_i64, { "r", "r", "rU" } },
1729 { INDEX_op_xor_i64, { "r", "r", "rU" } },
1730
1731 { INDEX_op_shl_i64, { "r", "r", "ri" } },
1732 { INDEX_op_shr_i64, { "r", "r", "ri" } },
1733 { INDEX_op_sar_i64, { "r", "r", "ri" } },
1734
1735 { INDEX_op_mul_i64, { "r", "r", "r" } },
1736 { INDEX_op_div_i64, { "r", "r", "r" } },
1737 { INDEX_op_divu_i64, { "r", "r", "r" } },
1738 { INDEX_op_rem_i64, { "r", "r", "r" } },
1739 { INDEX_op_remu_i64, { "r", "r", "r" } },
1740
1741 { INDEX_op_neg_i64, { "r", "r" } },
1742 { INDEX_op_not_i64, { "r", "r" } },
1743
1744 { INDEX_op_qemu_ld8u, { "r", "L" } },
1745 { INDEX_op_qemu_ld8s, { "r", "L" } },
1746 { INDEX_op_qemu_ld16u, { "r", "L" } },
1747 { INDEX_op_qemu_ld16s, { "r", "L" } },
1748 { INDEX_op_qemu_ld32, { "r", "L" } },
1749 { INDEX_op_qemu_ld32u, { "r", "L" } },
1750 { INDEX_op_qemu_ld32s, { "r", "L" } },
1751 { INDEX_op_qemu_ld64, { "r", "L" } },
1752
1753 { INDEX_op_qemu_st8, { "S", "S" } },
1754 { INDEX_op_qemu_st16, { "S", "S" } },
1755 { INDEX_op_qemu_st32, { "S", "S" } },
1756 { INDEX_op_qemu_st64, { "S", "S" } },
1757
1758 { INDEX_op_ext8s_i32, { "r", "r" } },
1759 { INDEX_op_ext16s_i32, { "r", "r" } },
1760 { INDEX_op_ext8s_i64, { "r", "r" } },
1761 { INDEX_op_ext16s_i64, { "r", "r" } },
1762 { INDEX_op_ext32s_i64, { "r", "r" } },
1763 { INDEX_op_ext32u_i64, { "r", "r" } },
1764
1765 { INDEX_op_setcond_i32, { "r", "r", "ri" } },
1766 { INDEX_op_setcond_i64, { "r", "r", "ri" } },
1767
1768 { -1 },
1769 };
1770
1771 static void tcg_target_init (TCGContext *s)
1772 {
1773 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1774 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1775 tcg_regset_set32 (tcg_target_call_clobber_regs, 0,
1776 (1 << TCG_REG_R0) |
1777 #ifdef __APPLE__
1778 (1 << TCG_REG_R2) |
1779 #endif
1780 (1 << TCG_REG_R3) |
1781 (1 << TCG_REG_R4) |
1782 (1 << TCG_REG_R5) |
1783 (1 << TCG_REG_R6) |
1784 (1 << TCG_REG_R7) |
1785 (1 << TCG_REG_R8) |
1786 (1 << TCG_REG_R9) |
1787 (1 << TCG_REG_R10) |
1788 (1 << TCG_REG_R11) |
1789 (1 << TCG_REG_R12)
1790 );
1791
1792 tcg_regset_clear (s->reserved_regs);
1793 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0);
1794 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1);
1795 #ifndef __APPLE__
1796 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2);
1797 #endif
1798 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13);
1799
1800 tcg_add_target_add_op_defs (ppc_op_defs);
1801 }