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