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