]> git.proxmox.com Git - qemu.git/blame - tcg/ppc64/tcg-target.c
tcg-ppc64: Introduce and use tcg_out_rlw
[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
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
404#define BF(n) ((n)<<23)
405#define BI(n, c) (((c)+((n)*4))<<16)
406#define BT(n, c) (((c)+((n)*4))<<21)
407#define BA(n, c) (((c)+((n)*4))<<16)
408#define BB(n, c) (((c)+((n)*4))<<11)
409
410#define BO_COND_TRUE BO (12)
411#define BO_COND_FALSE BO ( 4)
412#define BO_ALWAYS BO (20)
413
414enum {
415 CR_LT,
416 CR_GT,
417 CR_EQ,
418 CR_SO
419};
420
0aed257f 421static const uint32_t tcg_to_bc[] = {
810260a8 422 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
423 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
424 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
425 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
426 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
427 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
428 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
429 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
430 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
431 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
432};
433
aceac8d6
RH
434static inline void tcg_out_mov(TCGContext *s, TCGType type,
435 TCGReg ret, TCGReg arg)
810260a8 436{
437 tcg_out32 (s, OR | SAB (arg, ret, arg));
438}
439
aceac8d6
RH
440static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
441 int sh, int mb)
810260a8 442{
443 sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1);
444 mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f));
445 tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb);
446}
447
9e555b73
RH
448static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
449 int sh, int mb, int me)
450{
451 tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
452}
453
aceac8d6 454static void tcg_out_movi32(TCGContext *s, TCGReg ret, int32_t arg)
810260a8 455{
456 if (arg == (int16_t) arg)
457 tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
458 else {
459 tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
460 if (arg & 0xffff)
461 tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
462 }
463}
464
465static void tcg_out_movi (TCGContext *s, TCGType type,
2a534aff 466 TCGReg ret, tcg_target_long arg)
810260a8 467{
468 int32_t arg32 = arg;
591d6f1d 469 arg = type == TCG_TYPE_I32 ? arg & 0xffffffff : arg;
810260a8 470
591d6f1d 471 if (arg == arg32) {
810260a8 472 tcg_out_movi32 (s, ret, arg32);
473 }
474 else {
475 if ((uint64_t) arg >> 32) {
6fc9dbcc 476 uint16_t h16 = arg >> 16;
477 uint16_t l16 = arg;
478
95153fde 479 tcg_out_movi32 (s, ret, arg >> 32);
810260a8 480 tcg_out_rld (s, RLDICR, ret, ret, 32, 31);
6fc9dbcc 481 if (h16) tcg_out32 (s, ORIS | RS (ret) | RA (ret) | h16);
482 if (l16) tcg_out32 (s, ORI | RS (ret) | RA (ret) | l16);
810260a8 483 }
484 else {
485 tcg_out_movi32 (s, ret, arg32);
6fc9dbcc 486 if (arg32 < 0)
487 tcg_out_rld (s, RLDICL, ret, ret, 0, 32);
810260a8 488 }
489 }
490}
491
5d7ff5bb
AF
492static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
493{
494 tcg_target_long disp;
495
496 disp = target - (tcg_target_long) s->code_ptr;
497 if ((disp << 38) >> 38 == disp)
498 tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
499 else {
500 tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target);
501 tcg_out32 (s, MTSPR | RS (0) | CTR);
502 tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
503 }
504}
505
810260a8 506static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
507{
5d7ff5bb
AF
508#ifdef __APPLE__
509 if (const_arg) {
510 tcg_out_b (s, LK, arg);
511 }
512 else {
513 tcg_out32 (s, MTSPR | RS (arg) | LR);
514 tcg_out32 (s, BCLR | BO_ALWAYS | LK);
515 }
516#else
810260a8 517 int reg;
518
519 if (const_arg) {
520 reg = 2;
521 tcg_out_movi (s, TCG_TYPE_I64, reg, arg);
522 }
523 else reg = arg;
524
525 tcg_out32 (s, LD | RT (0) | RA (reg));
526 tcg_out32 (s, MTSPR | RA (0) | CTR);
527 tcg_out32 (s, LD | RT (11) | RA (reg) | 16);
528 tcg_out32 (s, LD | RT (2) | RA (reg) | 8);
529 tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
5d7ff5bb 530#endif
810260a8 531}
532
aceac8d6
RH
533static void tcg_out_ldst(TCGContext *s, TCGReg ret, TCGReg addr,
534 int offset, int op1, int op2)
810260a8 535{
536 if (offset == (int16_t) offset)
537 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
538 else {
539 tcg_out_movi (s, TCG_TYPE_I64, 0, offset);
540 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
541 }
542}
543
aceac8d6
RH
544static void tcg_out_ldsta(TCGContext *s, TCGReg ret, TCGReg addr,
545 int offset, int op1, int op2)
828808f5 546{
547 if (offset == (int16_t) (offset & ~3))
548 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
549 else {
550 tcg_out_movi (s, TCG_TYPE_I64, 0, offset);
551 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
552 }
553}
554
810260a8 555#if defined (CONFIG_SOFTMMU)
79383c9c 556
022c62cb 557#include "exec/softmmu_defs.h"
810260a8 558
e141ab52
BS
559/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
560 int mmu_idx) */
561static const void * const qemu_ld_helpers[4] = {
562 helper_ldb_mmu,
563 helper_ldw_mmu,
564 helper_ldl_mmu,
565 helper_ldq_mmu,
566};
567
568/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
569 uintxx_t val, int mmu_idx) */
570static const void * const qemu_st_helpers[4] = {
571 helper_stb_mmu,
572 helper_stw_mmu,
573 helper_stl_mmu,
574 helper_stq_mmu,
575};
810260a8 576
aceac8d6
RH
577static void tcg_out_tlb_read(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
578 TCGReg addr_reg, int s_bits, int offset)
810260a8 579{
880e52b8 580#if TARGET_LONG_BITS == 32
810260a8 581 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32);
810260a8 582
9e555b73
RH
583 tcg_out_rlw(s, RLWINM, r0, addr_reg,
584 32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
585 32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
586 31 - CPU_TLB_ENTRY_BITS);
4a40e231 587 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
588 tcg_out32 (s, (LWZU | RT (r1) | RA (r0) | offset));
9e555b73
RH
589 tcg_out_rlw(s, RLWINM, r2, addr_reg, 0,
590 (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
4a40e231 591#else
810260a8 592 tcg_out_rld (s, RLDICL, r0, addr_reg,
593 64 - TARGET_PAGE_BITS,
594 64 - CPU_TLB_BITS);
595 tcg_out_rld (s, RLDICR, r0, r0,
596 CPU_TLB_ENTRY_BITS,
597 63 - CPU_TLB_ENTRY_BITS);
598
599 tcg_out32 (s, ADD | TAB (r0, r0, TCG_AREG0));
600 tcg_out32 (s, LD_ADDR | RT (r1) | RA (r0) | offset);
601
4a40e231 602 if (!s_bits) {
603 tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS);
604 }
605 else {
606 tcg_out_rld (s, RLDICL, r2, addr_reg,
607 64 - TARGET_PAGE_BITS,
608 TARGET_PAGE_BITS - s_bits);
609 tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0);
610 }
611#endif
810260a8 612}
a2a546b3 613#endif
810260a8 614
615static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
616{
aceac8d6
RH
617 TCGReg addr_reg, data_reg, r0, r1, rbase;
618 int bswap;
810260a8 619#ifdef CONFIG_SOFTMMU
aceac8d6
RH
620 TCGReg r2, ir;
621 int mem_index, s_bits;
810260a8 622 void *label1_ptr, *label2_ptr;
623#endif
624
625 data_reg = *args++;
626 addr_reg = *args++;
9df3b45d
DG
627
628#ifdef CONFIG_SOFTMMU
810260a8 629 mem_index = *args;
630 s_bits = opc & 3;
631
810260a8 632 r0 = 3;
633 r1 = 4;
634 r2 = 0;
f6548c0a 635 rbase = 0;
810260a8 636
637 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits,
9349b4f9 638 offsetof (CPUArchState, tlb_table[mem_index][0].addr_read));
810260a8 639
e924bbec 640 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
810260a8 641
642 label1_ptr = s->code_ptr;
643#ifdef FAST_PATH
644 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
645#endif
646
647 /* slow path */
c82e5848 648 ir = 3;
f4f7d01a 649 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
c82e5848
AF
650 tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
651 tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
810260a8 652
653 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
654
655 switch (opc) {
656 case 0|4:
657 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
658 break;
659 case 1|4:
660 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
661 break;
662 case 2|4:
663 tcg_out32 (s, EXTSW | RA (data_reg) | RS (3));
664 break;
665 case 0:
666 case 1:
667 case 2:
668 case 3:
669 if (data_reg != 3)
3b6dac34 670 tcg_out_mov (s, TCG_TYPE_I64, data_reg, 3);
810260a8 671 break;
672 }
673 label2_ptr = s->code_ptr;
674 tcg_out32 (s, B);
675
676 /* label1: fast path */
677#ifdef FAST_PATH
678 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
679#endif
680
681 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
355b1943 682 tcg_out32 (s, (LD
810260a8 683 | RT (r0)
684 | RA (r0)
685 | (offsetof (CPUTLBEntry, addend)
686 - offsetof (CPUTLBEntry, addr_read))
687 ));
688 /* r0 = env->tlb_table[mem_index][index].addend */
689 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
690 /* r0 = env->tlb_table[mem_index][index].addend + addr */
691
692#else /* !CONFIG_SOFTMMU */
0b7c1d89 693#if TARGET_LONG_BITS == 32
694 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32);
695#endif
810260a8 696 r0 = addr_reg;
735ee40d 697 r1 = 3;
f6548c0a 698 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
810260a8 699#endif
700
701#ifdef TARGET_WORDS_BIGENDIAN
702 bswap = 0;
703#else
704 bswap = 1;
705#endif
706 switch (opc) {
707 default:
708 case 0:
f6548c0a 709 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
810260a8 710 break;
711 case 0|4:
f6548c0a 712 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
810260a8 713 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
714 break;
715 case 1:
f6548c0a 716 if (bswap)
717 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
718 else
719 tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0));
810260a8 720 break;
721 case 1|4:
722 if (bswap) {
f6548c0a 723 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
810260a8 724 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
725 }
f6548c0a 726 else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0));
810260a8 727 break;
728 case 2:
f6548c0a 729 if (bswap)
730 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
731 else
732 tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0));
810260a8 733 break;
734 case 2|4:
735 if (bswap) {
f6548c0a 736 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
450e62e7 737 tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg));
810260a8 738 }
f6548c0a 739 else tcg_out32 (s, LWAX | TAB (data_reg, rbase, r0));
810260a8 740 break;
741 case 3:
f6548c0a 742#ifdef CONFIG_USE_GUEST_BASE
743 if (bswap) {
744 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
745 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
746 tcg_out32 (s, LWBRX | TAB ( r1, rbase, r1));
747 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
748 }
749 else tcg_out32 (s, LDX | TAB (data_reg, rbase, r0));
750#else
810260a8 751 if (bswap) {
b1d6d51d 752 tcg_out_movi32 (s, 0, 4);
3ee1b855 753 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
754 tcg_out32 (s, LWBRX | RT ( r1) | RA (r0));
755 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
810260a8 756 }
757 else tcg_out32 (s, LD | RT (data_reg) | RA (r0));
f6548c0a 758#endif
810260a8 759 break;
760 }
761
762#ifdef CONFIG_SOFTMMU
763 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
764#endif
765}
766
767static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
768{
aceac8d6
RH
769 TCGReg addr_reg, r0, r1, rbase, data_reg;
770 int bswap;
810260a8 771#ifdef CONFIG_SOFTMMU
aceac8d6
RH
772 TCGReg r2, ir;
773 int mem_index;
810260a8 774 void *label1_ptr, *label2_ptr;
775#endif
776
777 data_reg = *args++;
778 addr_reg = *args++;
810260a8 779
780#ifdef CONFIG_SOFTMMU
9df3b45d
DG
781 mem_index = *args;
782
810260a8 783 r0 = 3;
784 r1 = 4;
785 r2 = 0;
f6548c0a 786 rbase = 0;
810260a8 787
788 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc,
9349b4f9 789 offsetof (CPUArchState, tlb_table[mem_index][0].addr_write));
810260a8 790
e924bbec 791 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
810260a8 792
793 label1_ptr = s->code_ptr;
794#ifdef FAST_PATH
795 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
796#endif
797
798 /* slow path */
c82e5848 799 ir = 3;
f4f7d01a 800 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
c82e5848
AF
801 tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
802 tcg_out_rld (s, RLDICL, ir++, data_reg, 0, 64 - (1 << (3 + opc)));
803 tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
810260a8 804
805 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
806
807 label2_ptr = s->code_ptr;
808 tcg_out32 (s, B);
809
810 /* label1: fast path */
811#ifdef FAST_PATH
812 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
813#endif
814
355b1943 815 tcg_out32 (s, (LD
810260a8 816 | RT (r0)
817 | RA (r0)
818 | (offsetof (CPUTLBEntry, addend)
819 - offsetof (CPUTLBEntry, addr_write))
820 ));
821 /* r0 = env->tlb_table[mem_index][index].addend */
822 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
823 /* r0 = env->tlb_table[mem_index][index].addend + addr */
824
825#else /* !CONFIG_SOFTMMU */
0b7c1d89 826#if TARGET_LONG_BITS == 32
827 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32);
828#endif
735ee40d 829 r1 = 3;
810260a8 830 r0 = addr_reg;
f6548c0a 831 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
810260a8 832#endif
833
834#ifdef TARGET_WORDS_BIGENDIAN
835 bswap = 0;
836#else
837 bswap = 1;
838#endif
839 switch (opc) {
840 case 0:
f6548c0a 841 tcg_out32 (s, STBX | SAB (data_reg, rbase, r0));
810260a8 842 break;
843 case 1:
f6548c0a 844 if (bswap)
845 tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0));
846 else
847 tcg_out32 (s, STHX | SAB (data_reg, rbase, r0));
810260a8 848 break;
849 case 2:
f6548c0a 850 if (bswap)
851 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
852 else
853 tcg_out32 (s, STWX | SAB (data_reg, rbase, r0));
810260a8 854 break;
855 case 3:
856 if (bswap) {
f6548c0a 857 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
109719ec 858 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
810260a8 859 tcg_out_rld (s, RLDICL, 0, data_reg, 32, 0);
f6548c0a 860 tcg_out32 (s, STWBRX | SAB (0, rbase, r1));
810260a8 861 }
f6548c0a 862 else tcg_out32 (s, STDX | SAB (data_reg, rbase, r0));
810260a8 863 break;
864 }
865
866#ifdef CONFIG_SOFTMMU
867 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
868#endif
869}
870
e4d58b41 871static void tcg_target_qemu_prologue (TCGContext *s)
810260a8 872{
873 int i, frame_size;
5d7ff5bb 874#ifndef __APPLE__
a69abbe0 875 uint64_t addr;
5d7ff5bb 876#endif
810260a8 877
878 frame_size = 0
879 + 8 /* back chain */
880 + 8 /* CR */
881 + 8 /* LR */
882 + 8 /* compiler doubleword */
883 + 8 /* link editor doubleword */
884 + 8 /* TOC save area */
885 + TCG_STATIC_CALL_ARGS_SIZE
886 + ARRAY_SIZE (tcg_target_callee_save_regs) * 8
136a0b5a 887 + CPU_TEMP_BUF_NLONGS * sizeof(long)
810260a8 888 ;
889 frame_size = (frame_size + 15) & ~15;
890
f6af014e 891 tcg_set_frame (s, TCG_REG_CALL_STACK, frame_size
892 - CPU_TEMP_BUF_NLONGS * sizeof (long),
893 CPU_TEMP_BUF_NLONGS * sizeof (long));
136a0b5a 894
5d7ff5bb 895#ifndef __APPLE__
a69abbe0 896 /* First emit adhoc function descriptor */
897 addr = (uint64_t) s->code_ptr + 24;
898 tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */
899 s->code_ptr += 16; /* skip TOC and environment pointer */
5d7ff5bb 900#endif
a69abbe0 901
902 /* Prologue */
810260a8 903 tcg_out32 (s, MFSPR | RT (0) | LR);
904 tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff));
905 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
906 tcg_out32 (s, (STD
907 | RS (tcg_target_callee_save_regs[i])
908 | RA (1)
909 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
910 )
911 );
e03ae7f9 912 tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16));
810260a8 913
f6548c0a 914#ifdef CONFIG_USE_GUEST_BASE
b9e946c7
RH
915 if (GUEST_BASE) {
916 tcg_out_movi (s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE);
f6af014e 917 tcg_regset_set_reg (s->reserved_regs, TCG_GUEST_BASE_REG);
b9e946c7 918 }
f6548c0a 919#endif
920
cea5f9a2
BS
921 tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
922 tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
810260a8 923 tcg_out32 (s, BCCTR | BO_ALWAYS);
a69abbe0 924
925 /* Epilogue */
810260a8 926 tb_ret_addr = s->code_ptr;
927
928 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
929 tcg_out32 (s, (LD
930 | RT (tcg_target_callee_save_regs[i])
931 | RA (1)
932 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
933 )
934 );
e03ae7f9 935 tcg_out32 (s, LD | RT (0) | RA (1) | (frame_size + 16));
810260a8 936 tcg_out32 (s, MTSPR | RS (0) | LR);
937 tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
938 tcg_out32 (s, BCLR | BO_ALWAYS);
939}
940
2a534aff 941static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
810260a8 942 tcg_target_long arg2)
943{
944 if (type == TCG_TYPE_I32)
945 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
946 else
828808f5 947 tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
810260a8 948}
949
2a534aff 950static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
810260a8 951 tcg_target_long arg2)
952{
953 if (type == TCG_TYPE_I32)
954 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
955 else
828808f5 956 tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX);
810260a8 957}
958
aceac8d6 959static void ppc_addi32(TCGContext *s, TCGReg rt, TCGReg ra, tcg_target_long si)
810260a8 960{
961 if (!si && rt == ra)
962 return;
963
964 if (si == (int16_t) si)
965 tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
966 else {
967 uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
968 tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
969 tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
970 }
971}
972
aceac8d6 973static void ppc_addi64(TCGContext *s, TCGReg rt, TCGReg ra, tcg_target_long si)
810260a8 974{
fe6f943f 975 /* XXX: suboptimal */
976 if (si == (int16_t) si
8421d9e5 977 || ((((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0))
fe6f943f 978 ppc_addi32 (s, rt, ra, si);
979 else {
980 tcg_out_movi (s, TCG_TYPE_I64, 0, si);
981 tcg_out32 (s, ADD | RT (rt) | RA (ra));
982 }
810260a8 983}
984
810260a8 985static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
e924bbec 986 int const_arg2, int cr, int arch64)
810260a8 987{
988 int imm;
989 uint32_t op;
990
991 switch (cond) {
992 case TCG_COND_EQ:
993 case TCG_COND_NE:
994 if (const_arg2) {
995 if ((int16_t) arg2 == arg2) {
996 op = CMPI;
997 imm = 1;
998 break;
999 }
1000 else if ((uint16_t) arg2 == arg2) {
1001 op = CMPLI;
1002 imm = 1;
1003 break;
1004 }
1005 }
1006 op = CMPL;
1007 imm = 0;
1008 break;
1009
1010 case TCG_COND_LT:
1011 case TCG_COND_GE:
1012 case TCG_COND_LE:
1013 case TCG_COND_GT:
1014 if (const_arg2) {
1015 if ((int16_t) arg2 == arg2) {
1016 op = CMPI;
1017 imm = 1;
1018 break;
1019 }
1020 }
1021 op = CMP;
1022 imm = 0;
1023 break;
1024
1025 case TCG_COND_LTU:
1026 case TCG_COND_GEU:
1027 case TCG_COND_LEU:
1028 case TCG_COND_GTU:
1029 if (const_arg2) {
1030 if ((uint16_t) arg2 == arg2) {
1031 op = CMPLI;
1032 imm = 1;
1033 break;
1034 }
1035 }
1036 op = CMPL;
1037 imm = 0;
1038 break;
1039
1040 default:
1041 tcg_abort ();
1042 }
e924bbec 1043 op |= BF (cr) | (arch64 << 21);
810260a8 1044
1045 if (imm)
1046 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
1047 else {
1048 if (const_arg2) {
1049 tcg_out_movi (s, TCG_TYPE_I64, 0, arg2);
1050 tcg_out32 (s, op | RA (arg1) | RB (0));
1051 }
1052 else
1053 tcg_out32 (s, op | RA (arg1) | RB (arg2));
1054 }
1055
1056}
1057
8a56e840
RH
1058static void tcg_out_setcond (TCGContext *s, TCGType type, TCGCond cond,
1059 TCGArg arg0, TCGArg arg1, TCGArg arg2,
1060 int const_arg2)
1cd62ae9 1061{
1062 int crop, sh, arg;
1063
1064 switch (cond) {
1065 case TCG_COND_EQ:
1066 if (const_arg2) {
1067 if (!arg2) {
1068 arg = arg1;
1069 }
1070 else {
1071 arg = 0;
1072 if ((uint16_t) arg2 == arg2) {
1073 tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
1074 }
1075 else {
1076 tcg_out_movi (s, type, 0, arg2);
1077 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1078 }
1079 }
1080 }
1081 else {
1082 arg = 0;
1083 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1084 }
1085
1086 if (type == TCG_TYPE_I64) {
1087 tcg_out32 (s, CNTLZD | RS (arg) | RA (0));
1088 tcg_out_rld (s, RLDICL, arg0, 0, 58, 6);
1089 }
1090 else {
1091 tcg_out32 (s, CNTLZW | RS (arg) | RA (0));
9e555b73 1092 tcg_out_rlw(s, RLWINM, arg0, 0, 27, 5, 31);
1cd62ae9 1093 }
1094 break;
1095
1096 case TCG_COND_NE:
1097 if (const_arg2) {
1098 if (!arg2) {
1099 arg = arg1;
1100 }
1101 else {
1102 arg = 0;
1103 if ((uint16_t) arg2 == arg2) {
1104 tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
1105 }
1106 else {
1107 tcg_out_movi (s, type, 0, arg2);
1108 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1109 }
1110 }
1111 }
1112 else {
1113 arg = 0;
1114 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1115 }
1116
1117 if (arg == arg1 && arg1 == arg0) {
1118 tcg_out32 (s, ADDIC | RT (0) | RA (arg) | 0xffff);
1119 tcg_out32 (s, SUBFE | TAB (arg0, 0, arg));
1120 }
1121 else {
1122 tcg_out32 (s, ADDIC | RT (arg0) | RA (arg) | 0xffff);
1123 tcg_out32 (s, SUBFE | TAB (arg0, arg0, arg));
1124 }
1125 break;
1126
1127 case TCG_COND_GT:
1128 case TCG_COND_GTU:
1129 sh = 30;
1130 crop = 0;
1131 goto crtest;
1132
1133 case TCG_COND_LT:
1134 case TCG_COND_LTU:
1135 sh = 29;
1136 crop = 0;
1137 goto crtest;
1138
1139 case TCG_COND_GE:
1140 case TCG_COND_GEU:
1141 sh = 31;
1142 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
1143 goto crtest;
1144
1145 case TCG_COND_LE:
1146 case TCG_COND_LEU:
1147 sh = 31;
1148 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
1149 crtest:
1150 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, type == TCG_TYPE_I64);
1151 if (crop) tcg_out32 (s, crop);
1152 tcg_out32 (s, MFCR | RT (0));
9e555b73 1153 tcg_out_rlw(s, RLWINM, arg0, 0, sh, 31, 31);
1cd62ae9 1154 break;
1155
1156 default:
1157 tcg_abort ();
1158 }
1159}
1160
810260a8 1161static void tcg_out_bc (TCGContext *s, int bc, int label_index)
1162{
1163 TCGLabel *l = &s->labels[label_index];
1164
1165 if (l->has_value)
1166 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
1167 else {
1168 uint16_t val = *(uint16_t *) &s->code_ptr[2];
1169
1170 /* Thanks to Andrzej Zaborowski */
1171 tcg_out32 (s, bc | (val & 0xfffc));
1172 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
1173 }
1174}
1175
8a56e840 1176static void tcg_out_brcond (TCGContext *s, TCGCond cond,
810260a8 1177 TCGArg arg1, TCGArg arg2, int const_arg2,
e924bbec 1178 int label_index, int arch64)
810260a8 1179{
e924bbec 1180 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, arch64);
810260a8 1181 tcg_out_bc (s, tcg_to_bc[cond], label_index);
1182}
1183
1184void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
1185{
1186 TCGContext s;
1187 unsigned long patch_size;
1188
1189 s.code_ptr = (uint8_t *) jmp_addr;
1190 tcg_out_b (&s, 0, addr);
1191 patch_size = s.code_ptr - (uint8_t *) jmp_addr;
1192 flush_icache_range (jmp_addr, jmp_addr + patch_size);
1193}
1194
a9751609 1195static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
810260a8 1196 const int *const_args)
1197{
e46b9681 1198 int c;
1199
810260a8 1200 switch (opc) {
1201 case INDEX_op_exit_tb:
1202 tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
1203 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
1204 break;
1205 case INDEX_op_goto_tb:
1206 if (s->tb_jmp_offset) {
1207 /* direct jump method */
1208
1209 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
5424fd10 1210 s->code_ptr += 28;
810260a8 1211 }
1212 else {
1213 tcg_abort ();
1214 }
1215 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1216 break;
1217 case INDEX_op_br:
1218 {
1219 TCGLabel *l = &s->labels[args[0]];
1220
1221 if (l->has_value) {
1222 tcg_out_b (s, 0, l->u.value);
1223 }
1224 else {
1225 uint32_t val = *(uint32_t *) s->code_ptr;
1226
1227 /* Thanks to Andrzej Zaborowski */
1228 tcg_out32 (s, B | (val & 0x3fffffc));
1229 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1230 }
1231 }
1232 break;
1233 case INDEX_op_call:
1234 tcg_out_call (s, args[0], const_args[0]);
1235 break;
810260a8 1236 case INDEX_op_movi_i32:
1237 tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]);
1238 break;
1239 case INDEX_op_movi_i64:
1240 tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]);
1241 break;
1242 case INDEX_op_ld8u_i32:
1243 case INDEX_op_ld8u_i64:
1244 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1245 break;
1246 case INDEX_op_ld8s_i32:
1247 case INDEX_op_ld8s_i64:
1248 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1249 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1250 break;
1251 case INDEX_op_ld16u_i32:
1252 case INDEX_op_ld16u_i64:
1253 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1254 break;
1255 case INDEX_op_ld16s_i32:
1256 case INDEX_op_ld16s_i64:
1257 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1258 break;
1259 case INDEX_op_ld_i32:
1260 case INDEX_op_ld32u_i64:
1261 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1262 break;
1263 case INDEX_op_ld32s_i64:
828808f5 1264 tcg_out_ldsta (s, args[0], args[1], args[2], LWA, LWAX);
810260a8 1265 break;
1266 case INDEX_op_ld_i64:
828808f5 1267 tcg_out_ldsta (s, args[0], args[1], args[2], LD, LDX);
810260a8 1268 break;
1269 case INDEX_op_st8_i32:
1270 case INDEX_op_st8_i64:
1271 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1272 break;
1273 case INDEX_op_st16_i32:
1274 case INDEX_op_st16_i64:
1275 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1276 break;
1277 case INDEX_op_st_i32:
1278 case INDEX_op_st32_i64:
1279 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1280 break;
1281 case INDEX_op_st_i64:
828808f5 1282 tcg_out_ldsta (s, args[0], args[1], args[2], STD, STDX);
810260a8 1283 break;
1284
1285 case INDEX_op_add_i32:
1286 if (const_args[2])
1287 ppc_addi32 (s, args[0], args[1], args[2]);
1288 else
1289 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1290 break;
1291 case INDEX_op_sub_i32:
1292 if (const_args[2])
1293 ppc_addi32 (s, args[0], args[1], -args[2]);
1294 else
1295 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1296 break;
1297
fe6f943f 1298 case INDEX_op_and_i64:
810260a8 1299 case INDEX_op_and_i32:
1300 if (const_args[2]) {
000a2d86 1301 if ((args[2] & 0xffff) == args[2])
1302 tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]);
1303 else if ((args[2] & 0xffff0000) == args[2])
1304 tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
1305 | ((args[2] >> 16) & 0xffff));
810260a8 1306 else {
fe6f943f 1307 tcg_out_movi (s, (opc == INDEX_op_and_i32
1308 ? TCG_TYPE_I32
1309 : TCG_TYPE_I64),
1310 0, args[2]);
000a2d86 1311 tcg_out32 (s, AND | SAB (args[1], args[0], 0));
810260a8 1312 }
1313 }
1314 else
1315 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1316 break;
fe6f943f 1317 case INDEX_op_or_i64:
810260a8 1318 case INDEX_op_or_i32:
1319 if (const_args[2]) {
000a2d86 1320 if (args[2] & 0xffff) {
1321 tcg_out32 (s, ORI | RS (args[1]) | RA (args[0])
1322 | (args[2] & 0xffff));
1323 if (args[2] >> 16)
1324 tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
810260a8 1325 | ((args[2] >> 16) & 0xffff));
810260a8 1326 }
1327 else {
000a2d86 1328 tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0])
1329 | ((args[2] >> 16) & 0xffff));
810260a8 1330 }
1331 }
1332 else
1333 tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1334 break;
fe6f943f 1335 case INDEX_op_xor_i64:
810260a8 1336 case INDEX_op_xor_i32:
1337 if (const_args[2]) {
000a2d86 1338 if ((args[2] & 0xffff) == args[2])
1339 tcg_out32 (s, XORI | RS (args[1]) | RA (args[0])
1340 | (args[2] & 0xffff));
1341 else if ((args[2] & 0xffff0000) == args[2])
1342 tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0])
1343 | ((args[2] >> 16) & 0xffff));
810260a8 1344 else {
fe6f943f 1345 tcg_out_movi (s, (opc == INDEX_op_and_i32
1346 ? TCG_TYPE_I32
1347 : TCG_TYPE_I64),
1348 0, args[2]);
000a2d86 1349 tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
810260a8 1350 }
1351 }
1352 else
1353 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1354 break;
1355
1356 case INDEX_op_mul_i32:
1357 if (const_args[2]) {
1358 if (args[2] == (int16_t) args[2])
1359 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1360 | (args[2] & 0xffff));
1361 else {
1362 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1363 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1364 }
1365 }
1366 else
1367 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1368 break;
1369
1370 case INDEX_op_div_i32:
1371 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1372 break;
1373
1374 case INDEX_op_divu_i32:
1375 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1376 break;
1377
1378 case INDEX_op_rem_i32:
1379 tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1380 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1381 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1382 break;
1383
1384 case INDEX_op_remu_i32:
1385 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1386 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1387 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1388 break;
1389
1390 case INDEX_op_shl_i32:
1391 if (const_args[2]) {
9e555b73
RH
1392 tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
1393 } else {
810260a8 1394 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
9e555b73 1395 }
810260a8 1396 break;
1397 case INDEX_op_shr_i32:
1398 if (const_args[2]) {
9e555b73
RH
1399 tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], args[2], 31);
1400 } else {
810260a8 1401 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
9e555b73 1402 }
810260a8 1403 break;
1404 case INDEX_op_sar_i32:
1405 if (const_args[2])
1406 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1407 else
1408 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1409 break;
1410
1411 case INDEX_op_brcond_i32:
e924bbec 1412 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 0);
1413 break;
1414
810260a8 1415 case INDEX_op_brcond_i64:
e924bbec 1416 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 1);
810260a8 1417 break;
1418
1419 case INDEX_op_neg_i32:
810260a8 1420 case INDEX_op_neg_i64:
1421 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1422 break;
1423
157f2662 1424 case INDEX_op_not_i32:
1425 case INDEX_op_not_i64:
1426 tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
1427 break;
1428
810260a8 1429 case INDEX_op_add_i64:
fe6f943f 1430 if (const_args[2])
1431 ppc_addi64 (s, args[0], args[1], args[2]);
1432 else
1433 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
810260a8 1434 break;
1435 case INDEX_op_sub_i64:
fe6f943f 1436 if (const_args[2])
1437 ppc_addi64 (s, args[0], args[1], -args[2]);
1438 else
1439 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
810260a8 1440 break;
1441
1442 case INDEX_op_shl_i64:
fe6f943f 1443 if (const_args[2])
1444 tcg_out_rld (s, RLDICR, args[0], args[1], args[2], 63 - args[2]);
1445 else
1446 tcg_out32 (s, SLD | SAB (args[1], args[0], args[2]));
810260a8 1447 break;
1448 case INDEX_op_shr_i64:
fe6f943f 1449 if (const_args[2])
1450 tcg_out_rld (s, RLDICL, args[0], args[1], 64 - args[2], args[2]);
1451 else
1452 tcg_out32 (s, SRD | SAB (args[1], args[0], args[2]));
810260a8 1453 break;
1454 case INDEX_op_sar_i64:
fe6f943f 1455 if (const_args[2]) {
1456 int sh = SH (args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
1457 tcg_out32 (s, SRADI | RA (args[0]) | RS (args[1]) | sh);
1458 }
1459 else
1460 tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2]));
810260a8 1461 break;
1462
1463 case INDEX_op_mul_i64:
1464 tcg_out32 (s, MULLD | TAB (args[0], args[1], args[2]));
1465 break;
1466 case INDEX_op_div_i64:
1467 tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2]));
1468 break;
1469 case INDEX_op_divu_i64:
1470 tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
1471 break;
1472 case INDEX_op_rem_i64:
1473 tcg_out32 (s, DIVD | TAB (0, args[1], args[2]));
1474 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1475 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1476 break;
1477 case INDEX_op_remu_i64:
1478 tcg_out32 (s, DIVDU | TAB (0, args[1], args[2]));
1479 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1480 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1481 break;
1482
1483 case INDEX_op_qemu_ld8u:
1484 tcg_out_qemu_ld (s, args, 0);
1485 break;
1486 case INDEX_op_qemu_ld8s:
1487 tcg_out_qemu_ld (s, args, 0 | 4);
1488 break;
1489 case INDEX_op_qemu_ld16u:
1490 tcg_out_qemu_ld (s, args, 1);
1491 break;
1492 case INDEX_op_qemu_ld16s:
1493 tcg_out_qemu_ld (s, args, 1 | 4);
1494 break;
86feb1c8 1495 case INDEX_op_qemu_ld32:
810260a8 1496 case INDEX_op_qemu_ld32u:
1497 tcg_out_qemu_ld (s, args, 2);
1498 break;
1499 case INDEX_op_qemu_ld32s:
1500 tcg_out_qemu_ld (s, args, 2 | 4);
1501 break;
1502 case INDEX_op_qemu_ld64:
1503 tcg_out_qemu_ld (s, args, 3);
1504 break;
1505 case INDEX_op_qemu_st8:
1506 tcg_out_qemu_st (s, args, 0);
1507 break;
1508 case INDEX_op_qemu_st16:
1509 tcg_out_qemu_st (s, args, 1);
1510 break;
1511 case INDEX_op_qemu_st32:
1512 tcg_out_qemu_st (s, args, 2);
1513 break;
1514 case INDEX_op_qemu_st64:
1515 tcg_out_qemu_st (s, args, 3);
1516 break;
1517
e46b9681 1518 case INDEX_op_ext8s_i32:
1519 case INDEX_op_ext8s_i64:
1520 c = EXTSB;
1521 goto gen_ext;
1522 case INDEX_op_ext16s_i32:
1523 case INDEX_op_ext16s_i64:
1524 c = EXTSH;
1525 goto gen_ext;
1526 case INDEX_op_ext32s_i64:
1527 c = EXTSW;
1528 goto gen_ext;
1529 gen_ext:
1530 tcg_out32 (s, c | RS (args[1]) | RA (args[0]));
1531 break;
1532
157f2662 1533 case INDEX_op_ext32u_i64:
e89720b1 1534 tcg_out_rld (s, RLDICL, args[0], args[1], 0, 32);
157f2662 1535 break;
1536
1cd62ae9 1537 case INDEX_op_setcond_i32:
1538 tcg_out_setcond (s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
1539 const_args[2]);
1540 break;
1541 case INDEX_op_setcond_i64:
1542 tcg_out_setcond (s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
1543 const_args[2]);
1544 break;
1545
810260a8 1546 default:
affe5189 1547 tcg_dump_ops (s);
810260a8 1548 tcg_abort ();
1549 }
1550}
1551
1552static const TCGTargetOpDef ppc_op_defs[] = {
1553 { INDEX_op_exit_tb, { } },
1554 { INDEX_op_goto_tb, { } },
1555 { INDEX_op_call, { "ri" } },
810260a8 1556 { INDEX_op_br, { } },
1557
1558 { INDEX_op_mov_i32, { "r", "r" } },
1559 { INDEX_op_mov_i64, { "r", "r" } },
1560 { INDEX_op_movi_i32, { "r" } },
1561 { INDEX_op_movi_i64, { "r" } },
1562
1563 { INDEX_op_ld8u_i32, { "r", "r" } },
1564 { INDEX_op_ld8s_i32, { "r", "r" } },
1565 { INDEX_op_ld16u_i32, { "r", "r" } },
1566 { INDEX_op_ld16s_i32, { "r", "r" } },
1567 { INDEX_op_ld_i32, { "r", "r" } },
1568 { INDEX_op_ld_i64, { "r", "r" } },
1569 { INDEX_op_st8_i32, { "r", "r" } },
1570 { INDEX_op_st8_i64, { "r", "r" } },
1571 { INDEX_op_st16_i32, { "r", "r" } },
1572 { INDEX_op_st16_i64, { "r", "r" } },
1573 { INDEX_op_st_i32, { "r", "r" } },
1574 { INDEX_op_st_i64, { "r", "r" } },
1575 { INDEX_op_st32_i64, { "r", "r" } },
1576
1577 { INDEX_op_ld8u_i64, { "r", "r" } },
1578 { INDEX_op_ld8s_i64, { "r", "r" } },
1579 { INDEX_op_ld16u_i64, { "r", "r" } },
1580 { INDEX_op_ld16s_i64, { "r", "r" } },
1581 { INDEX_op_ld32u_i64, { "r", "r" } },
1582 { INDEX_op_ld32s_i64, { "r", "r" } },
810260a8 1583
1584 { INDEX_op_add_i32, { "r", "r", "ri" } },
1585 { INDEX_op_mul_i32, { "r", "r", "ri" } },
1586 { INDEX_op_div_i32, { "r", "r", "r" } },
1587 { INDEX_op_divu_i32, { "r", "r", "r" } },
1588 { INDEX_op_rem_i32, { "r", "r", "r" } },
1589 { INDEX_op_remu_i32, { "r", "r", "r" } },
1590 { INDEX_op_sub_i32, { "r", "r", "ri" } },
1591 { INDEX_op_and_i32, { "r", "r", "ri" } },
1592 { INDEX_op_or_i32, { "r", "r", "ri" } },
1593 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1594
1595 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1596 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1597 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1598
1599 { INDEX_op_brcond_i32, { "r", "ri" } },
1600 { INDEX_op_brcond_i64, { "r", "ri" } },
1601
1602 { INDEX_op_neg_i32, { "r", "r" } },
157f2662 1603 { INDEX_op_not_i32, { "r", "r" } },
810260a8 1604
fe6f943f 1605 { INDEX_op_add_i64, { "r", "r", "ri" } },
1606 { INDEX_op_sub_i64, { "r", "r", "ri" } },
1607 { INDEX_op_and_i64, { "r", "r", "rZ" } },
1608 { INDEX_op_or_i64, { "r", "r", "rZ" } },
1609 { INDEX_op_xor_i64, { "r", "r", "rZ" } },
810260a8 1610
fe6f943f 1611 { INDEX_op_shl_i64, { "r", "r", "ri" } },
1612 { INDEX_op_shr_i64, { "r", "r", "ri" } },
1613 { INDEX_op_sar_i64, { "r", "r", "ri" } },
810260a8 1614
1d58ee9f 1615 { INDEX_op_mul_i64, { "r", "r", "r" } },
810260a8 1616 { INDEX_op_div_i64, { "r", "r", "r" } },
1617 { INDEX_op_divu_i64, { "r", "r", "r" } },
1618 { INDEX_op_rem_i64, { "r", "r", "r" } },
1619 { INDEX_op_remu_i64, { "r", "r", "r" } },
1620
1621 { INDEX_op_neg_i64, { "r", "r" } },
157f2662 1622 { INDEX_op_not_i64, { "r", "r" } },
810260a8 1623
1624 { INDEX_op_qemu_ld8u, { "r", "L" } },
1625 { INDEX_op_qemu_ld8s, { "r", "L" } },
1626 { INDEX_op_qemu_ld16u, { "r", "L" } },
1627 { INDEX_op_qemu_ld16s, { "r", "L" } },
86feb1c8 1628 { INDEX_op_qemu_ld32, { "r", "L" } },
810260a8 1629 { INDEX_op_qemu_ld32u, { "r", "L" } },
1630 { INDEX_op_qemu_ld32s, { "r", "L" } },
b01d9fea 1631 { INDEX_op_qemu_ld64, { "r", "L" } },
810260a8 1632
c070355d 1633 { INDEX_op_qemu_st8, { "S", "S" } },
1634 { INDEX_op_qemu_st16, { "S", "S" } },
1635 { INDEX_op_qemu_st32, { "S", "S" } },
016b2b28 1636 { INDEX_op_qemu_st64, { "S", "S" } },
810260a8 1637
e46b9681 1638 { INDEX_op_ext8s_i32, { "r", "r" } },
1639 { INDEX_op_ext16s_i32, { "r", "r" } },
1640 { INDEX_op_ext8s_i64, { "r", "r" } },
1641 { INDEX_op_ext16s_i64, { "r", "r" } },
1642 { INDEX_op_ext32s_i64, { "r", "r" } },
157f2662 1643 { INDEX_op_ext32u_i64, { "r", "r" } },
e46b9681 1644
1cd62ae9 1645 { INDEX_op_setcond_i32, { "r", "r", "ri" } },
1646 { INDEX_op_setcond_i64, { "r", "r", "ri" } },
1647
810260a8 1648 { -1 },
1649};
1650
e4d58b41 1651static void tcg_target_init (TCGContext *s)
810260a8 1652{
1653 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1654 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1655 tcg_regset_set32 (tcg_target_call_clobber_regs, 0,
1656 (1 << TCG_REG_R0) |
5d7ff5bb
AF
1657#ifdef __APPLE__
1658 (1 << TCG_REG_R2) |
1659#endif
810260a8 1660 (1 << TCG_REG_R3) |
1661 (1 << TCG_REG_R4) |
1662 (1 << TCG_REG_R5) |
1663 (1 << TCG_REG_R6) |
1664 (1 << TCG_REG_R7) |
1665 (1 << TCG_REG_R8) |
1666 (1 << TCG_REG_R9) |
1667 (1 << TCG_REG_R10) |
1668 (1 << TCG_REG_R11) |
1669 (1 << TCG_REG_R12)
1670 );
1671
1672 tcg_regset_clear (s->reserved_regs);
1673 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0);
1674 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1);
5d7ff5bb 1675#ifndef __APPLE__
810260a8 1676 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2);
5d7ff5bb 1677#endif
810260a8 1678 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13);
1679
1680 tcg_add_target_add_op_defs (ppc_op_defs);
1681}