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