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