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