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