]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/ppc/tcg-target.c
tcg/ppc: Don't hardcode register numbers
[mirror_qemu.git] / tcg / ppc / tcg-target.c
CommitLineData
2662e13f
FB
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
25static uint8_t *tb_ret_addr;
26
6ec85236 27#ifdef _CALL_DARWIN
bf6bca52 28#define LINKAGE_AREA_SIZE 24
2946898b 29#define LR_OFFSET 8
6ec85236 30#elif defined _CALL_AIX
b29fe3ed 31#define LINKAGE_AREA_SIZE 52
32#define LR_OFFSET 8
f9bf2987 33#else
34#define LINKAGE_AREA_SIZE 8
2946898b 35#define LR_OFFSET 4
f9bf2987 36#endif
37
2662e13f 38#define FAST_PATH
35f6b599 39
f6548c0a 40#ifndef GUEST_BASE
41#define GUEST_BASE 0
42#endif
43
44#ifdef CONFIG_USE_GUEST_BASE
45#define TCG_GUEST_BASE_REG 30
46#else
47#define TCG_GUEST_BASE_REG 0
48#endif
49
d4a9eb1f 50#ifndef NDEBUG
2662e13f
FB
51static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
52 "r0",
53 "r1",
f7e2aca8 54 "r2",
2662e13f
FB
55 "r3",
56 "r4",
57 "r5",
58 "r6",
59 "r7",
60 "r8",
61 "r9",
62 "r10",
63 "r11",
64 "r12",
65 "r13",
66 "r14",
67 "r15",
68 "r16",
69 "r17",
70 "r18",
71 "r19",
72 "r20",
73 "r21",
74 "r22",
75 "r23",
76 "r24",
77 "r25",
78 "r26",
79 "r27",
80 "r28",
81 "r29",
82 "r30",
83 "r31"
84};
d4a9eb1f 85#endif
2662e13f
FB
86
87static const int tcg_target_reg_alloc_order[] = {
a35e86c5 88 TCG_REG_R14,
89 TCG_REG_R15,
90 TCG_REG_R16,
91 TCG_REG_R17,
92 TCG_REG_R18,
93 TCG_REG_R19,
94 TCG_REG_R20,
95 TCG_REG_R21,
96 TCG_REG_R22,
97 TCG_REG_R23,
98 TCG_REG_R28,
99 TCG_REG_R29,
100 TCG_REG_R30,
101 TCG_REG_R31,
6ec85236 102#ifdef _CALL_DARWIN
f9bf2987 103 TCG_REG_R2,
104#endif
2662e13f
FB
105 TCG_REG_R3,
106 TCG_REG_R4,
107 TCG_REG_R5,
108 TCG_REG_R6,
109 TCG_REG_R7,
110 TCG_REG_R8,
111 TCG_REG_R9,
112 TCG_REG_R10,
6ec85236 113#ifndef _CALL_DARWIN
2662e13f 114 TCG_REG_R11,
f9bf2987 115#endif
2662e13f 116 TCG_REG_R12,
6ec85236 117#ifndef _CALL_SYSV
2662e13f 118 TCG_REG_R13,
5db3ee79 119#endif
2662e13f
FB
120 TCG_REG_R24,
121 TCG_REG_R25,
122 TCG_REG_R26,
a35e86c5 123 TCG_REG_R27
2662e13f
FB
124};
125
126static const int tcg_target_call_iarg_regs[] = {
127 TCG_REG_R3,
128 TCG_REG_R4,
129 TCG_REG_R5,
130 TCG_REG_R6,
131 TCG_REG_R7,
132 TCG_REG_R8,
133 TCG_REG_R9,
134 TCG_REG_R10
135};
136
137static const int tcg_target_call_oarg_regs[2] = {
138 TCG_REG_R3,
139 TCG_REG_R4
140};
141
142static const int tcg_target_callee_save_regs[] = {
6ec85236 143#ifdef _CALL_DARWIN
f9bf2987 144 TCG_REG_R11,
145 TCG_REG_R13,
b29fe3ed 146#endif
6ec85236 147#ifdef _CALL_AIX
b29fe3ed 148 TCG_REG_R13,
f9bf2987 149#endif
2662e13f
FB
150 TCG_REG_R14,
151 TCG_REG_R15,
152 TCG_REG_R16,
153 TCG_REG_R17,
154 TCG_REG_R18,
155 TCG_REG_R19,
156 TCG_REG_R20,
157 TCG_REG_R21,
158 TCG_REG_R22,
159 TCG_REG_R23,
eb2eb1dc 160 TCG_REG_R24,
161 TCG_REG_R25,
162 TCG_REG_R26,
cea5f9a2 163 TCG_REG_R27, /* currently used for the global env */
2662e13f
FB
164 TCG_REG_R28,
165 TCG_REG_R29,
166 TCG_REG_R30,
167 TCG_REG_R31
168};
169
170static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
171{
932a6909
FB
172 tcg_target_long disp;
173
174 disp = target - (tcg_target_long) pc;
175 if ((disp << 6) >> 6 != disp)
176 tcg_abort ();
177
178 return disp & 0x3fffffc;
2662e13f
FB
179}
180
181static void reloc_pc24 (void *pc, tcg_target_long target)
182{
183 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
184 | reloc_pc24_val (pc, target);
185}
186
187static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
188{
932a6909
FB
189 tcg_target_long disp;
190
191 disp = target - (tcg_target_long) pc;
192 if (disp != (int16_t) disp)
193 tcg_abort ();
194
195 return disp & 0xfffc;
2662e13f
FB
196}
197
198static void reloc_pc14 (void *pc, tcg_target_long target)
199{
200 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
201 | reloc_pc14_val (pc, target);
202}
203
204static void patch_reloc(uint8_t *code_ptr, int type,
205 tcg_target_long value, tcg_target_long addend)
206{
207 value += addend;
208 switch (type) {
209 case R_PPC_REL14:
210 reloc_pc14 (code_ptr, value);
211 break;
212 case R_PPC_REL24:
213 reloc_pc24 (code_ptr, value);
214 break;
215 default:
216 tcg_abort();
217 }
218}
219
220/* maximum number of register used for input function arguments */
221static int tcg_target_get_call_iarg_regs_count(int flags)
222{
b1503cda 223 return ARRAY_SIZE (tcg_target_call_iarg_regs);
2662e13f
FB
224}
225
226/* parse target specific constraints */
227static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
228{
229 const char *ct_str;
230
231 ct_str = *pct_str;
232 switch (ct_str[0]) {
398ce98e 233 case 'A': case 'B': case 'C': case 'D':
234 ct->ct |= TCG_CT_REG;
235 tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
236 break;
2662e13f
FB
237 case 'r':
238 ct->ct |= TCG_CT_REG;
239 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
240 break;
70fa887c 241#ifdef CONFIG_SOFTMMU
2662e13f
FB
242 case 'L': /* qemu_ld constraint */
243 ct->ct |= TCG_CT_REG;
244 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
245 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
246 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
247 break;
248 case 'K': /* qemu_st[8..32] constraint */
249 ct->ct |= TCG_CT_REG;
250 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
251 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
252 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
253 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
254#if TARGET_LONG_BITS == 64
255 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
256#endif
257 break;
258 case 'M': /* qemu_st64 constraint */
259 ct->ct |= TCG_CT_REG;
260 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
261 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
262 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
263 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
264 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
265 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
266 break;
70fa887c 267#else
268 case 'L':
269 case 'K':
270 ct->ct |= TCG_CT_REG;
271 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
272 break;
273 case 'M':
274 ct->ct |= TCG_CT_REG;
275 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
276 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
277 break;
278#endif
2662e13f
FB
279 default:
280 return -1;
281 }
282 ct_str++;
283 *pct_str = ct_str;
284 return 0;
285}
286
287/* test if a constant matches the constraint */
288static int tcg_target_const_match(tcg_target_long val,
289 const TCGArgConstraint *arg_ct)
290{
291 int ct;
292
293 ct = arg_ct->ct;
294 if (ct & TCG_CT_CONST)
295 return 1;
2662e13f
FB
296 return 0;
297}
298
299#define OPCD(opc) ((opc)<<26)
300#define XO31(opc) (OPCD(31)|((opc)<<1))
301#define XO19(opc) (OPCD(19)|((opc)<<1))
302
303#define B OPCD(18)
304#define BC OPCD(16)
305#define LBZ OPCD(34)
306#define LHZ OPCD(40)
307#define LHA OPCD(42)
308#define LWZ OPCD(32)
309#define STB OPCD(38)
310#define STH OPCD(44)
311#define STW OPCD(36)
312
b0809bf7 313#define ADDIC OPCD(12)
2662e13f
FB
314#define ADDI OPCD(14)
315#define ADDIS OPCD(15)
316#define ORI OPCD(24)
317#define ORIS OPCD(25)
318#define XORI OPCD(26)
319#define XORIS OPCD(27)
320#define ANDI OPCD(28)
321#define ANDIS OPCD(29)
322#define MULLI OPCD( 7)
323#define CMPLI OPCD(10)
324#define CMPI OPCD(11)
d616cf1d 325#define SUBFIC OPCD( 8)
2662e13f
FB
326
327#define LWZU OPCD(33)
328#define STWU OPCD(37)
329
a884dcb8 330#define RLWIMI OPCD(20)
2662e13f 331#define RLWINM OPCD(21)
65fe043e 332#define RLWNM OPCD(23)
2662e13f 333
c596defd 334#define BCLR XO19( 16)
2662e13f
FB
335#define BCCTR XO19(528)
336#define CRAND XO19(257)
c596defd 337#define CRANDC XO19(129)
338#define CRNAND XO19(225)
339#define CROR XO19(449)
b0809bf7 340#define CRNOR XO19( 33)
2662e13f
FB
341
342#define EXTSB XO31(954)
343#define EXTSH XO31(922)
344#define ADD XO31(266)
345#define ADDE XO31(138)
346#define ADDC XO31( 10)
347#define AND XO31( 28)
348#define SUBF XO31( 40)
349#define SUBFC XO31( 8)
350#define SUBFE XO31(136)
351#define OR XO31(444)
352#define XOR XO31(316)
353#define MULLW XO31(235)
354#define MULHWU XO31( 11)
355#define DIVW XO31(491)
356#define DIVWU XO31(459)
357#define CMP XO31( 0)
358#define CMPL XO31( 32)
359#define LHBRX XO31(790)
360#define LWBRX XO31(534)
361#define STHBRX XO31(918)
362#define STWBRX XO31(662)
363#define MFSPR XO31(339)
364#define MTSPR XO31(467)
365#define SRAWI XO31(824)
366#define NEG XO31(104)
b0809bf7 367#define MFCR XO31( 19)
368#define CNTLZW XO31( 26)
65fe043e 369#define NOR XO31(124)
370#define ANDC XO31( 60)
371#define ORC XO31(412)
aa77bebd 372#define EQV XO31(284)
373#define NAND XO31(476)
2662e13f
FB
374
375#define LBZX XO31( 87)
4f4a67ae 376#define LHZX XO31(279)
2662e13f
FB
377#define LHAX XO31(343)
378#define LWZX XO31( 23)
379#define STBX XO31(215)
380#define STHX XO31(407)
381#define STWX XO31(151)
382
383#define SPR(a,b) ((((a)<<5)|(b))<<11)
384#define LR SPR(8, 0)
385#define CTR SPR(9, 0)
386
387#define SLW XO31( 24)
388#define SRW XO31(536)
389#define SRAW XO31(792)
390
2662e13f
FB
391#define TW XO31(4)
392#define TRAP (TW | TO (31))
393
394#define RT(r) ((r)<<21)
395#define RS(r) ((r)<<21)
396#define RA(r) ((r)<<16)
397#define RB(r) ((r)<<11)
398#define TO(t) ((t)<<21)
399#define SH(s) ((s)<<11)
400#define MB(b) ((b)<<6)
401#define ME(e) ((e)<<1)
402#define BO(o) ((o)<<21)
403
404#define LK 1
405
406#define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
407#define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
408
409#define BF(n) ((n)<<23)
410#define BI(n, c) (((c)+((n)*4))<<16)
411#define BT(n, c) (((c)+((n)*4))<<21)
412#define BA(n, c) (((c)+((n)*4))<<16)
413#define BB(n, c) (((c)+((n)*4))<<11)
414
415#define BO_COND_TRUE BO (12)
416#define BO_COND_FALSE BO (4)
417#define BO_ALWAYS BO (20)
418
419enum {
420 CR_LT,
421 CR_GT,
422 CR_EQ,
423 CR_SO
424};
425
426static const uint32_t tcg_to_bc[10] = {
427 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
428 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
429 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
430 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
431 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
432 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
433 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
434 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
435 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
436 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
437};
438
2a534aff 439static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
2662e13f
FB
440{
441 tcg_out32 (s, OR | SAB (arg, ret, arg));
442}
443
444static void tcg_out_movi(TCGContext *s, TCGType type,
2a534aff 445 TCGReg ret, tcg_target_long arg)
2662e13f
FB
446{
447 if (arg == (int16_t) arg)
448 tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
449 else {
450 tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
451 if (arg & 0xffff)
0a878c47 452 tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
2662e13f
FB
453 }
454}
455
456static void tcg_out_ldst (TCGContext *s, int ret, int addr,
457 int offset, int op1, int op2)
458{
459 if (offset == (int16_t) offset)
460 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
461 else {
462 tcg_out_movi (s, TCG_TYPE_I32, 0, offset);
463 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
464 }
465}
466
932a6909
FB
467static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
468{
469 tcg_target_long disp;
470
471 disp = target - (tcg_target_long) s->code_ptr;
472 if ((disp << 6) >> 6 == disp)
8c5e95d8 473 tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
932a6909
FB
474 else {
475 tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target);
476 tcg_out32 (s, MTSPR | RS (0) | CTR);
477 tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
478 }
479}
480
b29fe3ed 481static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
482{
6ec85236 483#ifdef _CALL_AIX
b29fe3ed 484 int reg;
485
486 if (const_arg) {
487 reg = 2;
488 tcg_out_movi (s, TCG_TYPE_I32, reg, arg);
489 }
490 else reg = arg;
491
492 tcg_out32 (s, LWZ | RT (0) | RA (reg));
493 tcg_out32 (s, MTSPR | RA (0) | CTR);
494 tcg_out32 (s, LWZ | RT (2) | RA (reg) | 4);
495 tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
d9370327 496#else
497 if (const_arg) {
498 tcg_out_b (s, LK, arg);
499 }
500 else {
501 tcg_out32 (s, MTSPR | RS (arg) | LR);
502 tcg_out32 (s, BCLR | BO_ALWAYS | LK);
503 }
b29fe3ed 504#endif
d9370327 505}
b29fe3ed 506
2662e13f 507#if defined(CONFIG_SOFTMMU)
79383c9c
BS
508
509#include "../../softmmu_defs.h"
2662e13f 510
e141ab52 511#ifdef CONFIG_TCG_PASS_AREG0
f05ae537 512#error CONFIG_TCG_PASS_AREG0 is not supported
e141ab52
BS
513/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
514 int mmu_idx) */
515static const void * const qemu_ld_helpers[4] = {
516 helper_ldb_mmu,
517 helper_ldw_mmu,
518 helper_ldl_mmu,
519 helper_ldq_mmu,
520};
521
522/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
523 uintxx_t val, int mmu_idx) */
524static const void * const qemu_st_helpers[4] = {
525 helper_stb_mmu,
526 helper_stw_mmu,
527 helper_stl_mmu,
528 helper_stq_mmu,
529};
530#else
531/* legacy helper signature: __ld_mmu(target_ulong addr, int
532 mmu_idx) */
2662e13f
FB
533static void *qemu_ld_helpers[4] = {
534 __ldb_mmu,
535 __ldw_mmu,
536 __ldl_mmu,
537 __ldq_mmu,
538};
539
e141ab52
BS
540/* legacy helper signature: __ld_mmu(target_ulong addr, int
541 mmu_idx) */
2662e13f
FB
542static void *qemu_st_helpers[4] = {
543 __stb_mmu,
544 __stw_mmu,
545 __stl_mmu,
546 __stq_mmu,
547};
548#endif
e141ab52 549#endif
2662e13f
FB
550
551static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
552{
70d705fd 553 int addr_reg, data_reg, data_reg2, r0, r1, rbase, bswap;
2662e13f 554#ifdef CONFIG_SOFTMMU
d831fdb0 555 int mem_index, s_bits, r2, ir;
2662e13f 556 void *label1_ptr, *label2_ptr;
2662e13f
FB
557#if TARGET_LONG_BITS == 64
558 int addr_reg2;
70d705fd 559#endif
2662e13f
FB
560#endif
561
562 data_reg = *args++;
563 if (opc == 3)
564 data_reg2 = *args++;
565 else
566 data_reg2 = 0;
567 addr_reg = *args++;
70d705fd
PM
568
569#ifdef CONFIG_SOFTMMU
2662e13f
FB
570#if TARGET_LONG_BITS == 64
571 addr_reg2 = *args++;
572#endif
573 mem_index = *args;
574 s_bits = opc & 3;
2662e13f
FB
575 r0 = 3;
576 r1 = 4;
577 r2 = 0;
f6548c0a 578 rbase = 0;
2662e13f
FB
579
580 tcg_out32 (s, (RLWINM
581 | RA (r0)
582 | RS (addr_reg)
583 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
584 | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
585 | ME (31 - CPU_TLB_ENTRY_BITS)
586 )
587 );
588 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
589 tcg_out32 (s, (LWZU
590 | RT (r1)
591 | RA (r0)
9349b4f9 592 | offsetof (CPUArchState, tlb_table[mem_index][0].addr_read)
2662e13f
FB
593 )
594 );
595 tcg_out32 (s, (RLWINM
596 | RA (r2)
597 | RS (addr_reg)
598 | SH (0)
599 | MB ((32 - s_bits) & 31)
600 | ME (31 - TARGET_PAGE_BITS)
601 )
602 );
603
604 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
605#if TARGET_LONG_BITS == 64
606 tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
607 tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
608 tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
609#endif
610
611 label1_ptr = s->code_ptr;
612#ifdef FAST_PATH
613 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
614#endif
615
616 /* slow path */
d831fdb0 617 ir = 3;
2662e13f 618#if TARGET_LONG_BITS == 32
d831fdb0 619 tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
2662e13f 620#else
d831fdb0
AF
621#ifdef TCG_TARGET_CALL_ALIGN_ARGS
622 ir |= 1;
623#endif
624 tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg2);
625 tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
2662e13f 626#endif
d831fdb0 627 tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
2662e13f 628
b29fe3ed 629 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
2662e13f
FB
630 switch (opc) {
631 case 0|4:
632 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
633 break;
634 case 1|4:
635 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
636 break;
637 case 0:
638 case 1:
639 case 2:
640 if (data_reg != 3)
3b6dac34 641 tcg_out_mov (s, TCG_TYPE_I32, data_reg, 3);
2662e13f
FB
642 break;
643 case 3:
644 if (data_reg == 3) {
645 if (data_reg2 == 4) {
3b6dac34
RH
646 tcg_out_mov (s, TCG_TYPE_I32, 0, 4);
647 tcg_out_mov (s, TCG_TYPE_I32, 4, 3);
648 tcg_out_mov (s, TCG_TYPE_I32, 3, 0);
2662e13f
FB
649 }
650 else {
3b6dac34
RH
651 tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
652 tcg_out_mov (s, TCG_TYPE_I32, 3, 4);
2662e13f
FB
653 }
654 }
655 else {
3b6dac34
RH
656 if (data_reg != 4) tcg_out_mov (s, TCG_TYPE_I32, data_reg, 4);
657 if (data_reg2 != 3) tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
2662e13f
FB
658 }
659 break;
660 }
661 label2_ptr = s->code_ptr;
662 tcg_out32 (s, B);
663
664 /* label1: fast path */
665#ifdef FAST_PATH
666 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
667#endif
668
669 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
670 tcg_out32 (s, (LWZ
671 | RT (r0)
672 | RA (r0)
355b1943 673 | (offsetof (CPUTLBEntry, addend)
2662e13f
FB
674 - offsetof (CPUTLBEntry, addr_read))
675 ));
676 /* r0 = env->tlb_table[mem_index][index].addend */
677 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
678 /* r0 = env->tlb_table[mem_index][index].addend + addr */
679
680#else /* !CONFIG_SOFTMMU */
681 r0 = addr_reg;
f8edcbaa 682 r1 = 3;
f6548c0a 683 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
2662e13f
FB
684#endif
685
686#ifdef TARGET_WORDS_BIGENDIAN
687 bswap = 0;
688#else
689 bswap = 1;
690#endif
f6548c0a 691
2662e13f
FB
692 switch (opc) {
693 default:
694 case 0:
f6548c0a 695 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
2662e13f
FB
696 break;
697 case 0|4:
f6548c0a 698 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
2662e13f
FB
699 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
700 break;
701 case 1:
f6548c0a 702 if (bswap)
703 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
704 else
705 tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0));
2662e13f
FB
706 break;
707 case 1|4:
708 if (bswap) {
f6548c0a 709 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
2662e13f
FB
710 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
711 }
f6548c0a 712 else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0));
2662e13f
FB
713 break;
714 case 2:
f6548c0a 715 if (bswap)
716 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
717 else
718 tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0));
2662e13f
FB
719 break;
720 case 3:
721 if (bswap) {
f6548c0a 722 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
723 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
724 tcg_out32 (s, LWBRX | TAB (data_reg2, rbase, r1));
2662e13f
FB
725 }
726 else {
f6548c0a 727#ifdef CONFIG_USE_GUEST_BASE
728 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
729 tcg_out32 (s, LWZX | TAB (data_reg2, rbase, r0));
730 tcg_out32 (s, LWZX | TAB (data_reg, rbase, r1));
731#else
2662e13f
FB
732 if (r0 == data_reg2) {
733 tcg_out32 (s, LWZ | RT (0) | RA (r0));
734 tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
3b6dac34 735 tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 0);
2662e13f
FB
736 }
737 else {
738 tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
739 tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
740 }
f6548c0a 741#endif
2662e13f
FB
742 }
743 break;
744 }
745
746#ifdef CONFIG_SOFTMMU
747 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
748#endif
749}
750
751static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
752{
70d705fd 753 int addr_reg, r0, r1, data_reg, data_reg2, bswap, rbase;
2662e13f 754#ifdef CONFIG_SOFTMMU
70d705fd 755 int mem_index, r2, ir;
2662e13f 756 void *label1_ptr, *label2_ptr;
2662e13f
FB
757#if TARGET_LONG_BITS == 64
758 int addr_reg2;
70d705fd 759#endif
2662e13f
FB
760#endif
761
762 data_reg = *args++;
763 if (opc == 3)
764 data_reg2 = *args++;
765 else
766 data_reg2 = 0;
767 addr_reg = *args++;
70d705fd
PM
768
769#ifdef CONFIG_SOFTMMU
2662e13f
FB
770#if TARGET_LONG_BITS == 64
771 addr_reg2 = *args++;
772#endif
773 mem_index = *args;
2662e13f
FB
774 r0 = 3;
775 r1 = 4;
776 r2 = 0;
f6548c0a 777 rbase = 0;
2662e13f
FB
778
779 tcg_out32 (s, (RLWINM
780 | RA (r0)
781 | RS (addr_reg)
782 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
783 | MB (32 - (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS))
784 | ME (31 - CPU_TLB_ENTRY_BITS)
785 )
786 );
787 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
788 tcg_out32 (s, (LWZU
789 | RT (r1)
790 | RA (r0)
9349b4f9 791 | offsetof (CPUArchState, tlb_table[mem_index][0].addr_write)
2662e13f
FB
792 )
793 );
794 tcg_out32 (s, (RLWINM
795 | RA (r2)
796 | RS (addr_reg)
797 | SH (0)
798 | MB ((32 - opc) & 31)
799 | ME (31 - TARGET_PAGE_BITS)
800 )
801 );
802
803 tcg_out32 (s, CMP | (7 << 23) | RA (r2) | RB (r1));
804#if TARGET_LONG_BITS == 64
805 tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
806 tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
807 tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
808#endif
809
810 label1_ptr = s->code_ptr;
811#ifdef FAST_PATH
812 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
813#endif
814
815 /* slow path */
d831fdb0 816 ir = 3;
2662e13f 817#if TARGET_LONG_BITS == 32
d831fdb0 818 tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
2662e13f 819#else
d831fdb0
AF
820#ifdef TCG_TARGET_CALL_ALIGN_ARGS
821 ir |= 1;
822#endif
823 tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg2);
824 tcg_out_mov (s, TCG_TYPE_I32, ir++, addr_reg);
2662e13f
FB
825#endif
826
827 switch (opc) {
828 case 0:
829 tcg_out32 (s, (RLWINM
830 | RA (ir)
831 | RS (data_reg)
832 | SH (0)
833 | MB (24)
834 | ME (31)));
835 break;
836 case 1:
837 tcg_out32 (s, (RLWINM
838 | RA (ir)
839 | RS (data_reg)
840 | SH (0)
841 | MB (16)
842 | ME (31)));
843 break;
844 case 2:
3b6dac34 845 tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
2662e13f
FB
846 break;
847 case 3:
f9bf2987 848#ifdef TCG_TARGET_CALL_ALIGN_ARGS
d831fdb0 849 ir |= 1;
f9bf2987 850#endif
3b6dac34
RH
851 tcg_out_mov (s, TCG_TYPE_I32, ir++, data_reg2);
852 tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
2662e13f
FB
853 break;
854 }
855 ir++;
856
857 tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
b29fe3ed 858 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
2662e13f
FB
859 label2_ptr = s->code_ptr;
860 tcg_out32 (s, B);
861
862 /* label1: fast path */
863#ifdef FAST_PATH
864 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
865#endif
866
867 tcg_out32 (s, (LWZ
868 | RT (r0)
869 | RA (r0)
355b1943 870 | (offsetof (CPUTLBEntry, addend)
2662e13f
FB
871 - offsetof (CPUTLBEntry, addr_write))
872 ));
873 /* r0 = env->tlb_table[mem_index][index].addend */
874 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
875 /* r0 = env->tlb_table[mem_index][index].addend + addr */
876
877#else /* !CONFIG_SOFTMMU */
2662e13f 878 r0 = addr_reg;
f6548c0a 879 r1 = 3;
a71836de 880 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
2662e13f
FB
881#endif
882
883#ifdef TARGET_WORDS_BIGENDIAN
884 bswap = 0;
885#else
886 bswap = 1;
887#endif
888 switch (opc) {
889 case 0:
f6548c0a 890 tcg_out32 (s, STBX | SAB (data_reg, rbase, r0));
2662e13f
FB
891 break;
892 case 1:
f6548c0a 893 if (bswap)
894 tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0));
895 else
896 tcg_out32 (s, STHX | SAB (data_reg, rbase, r0));
2662e13f
FB
897 break;
898 case 2:
f6548c0a 899 if (bswap)
900 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
901 else
902 tcg_out32 (s, STWX | SAB (data_reg, rbase, r0));
2662e13f
FB
903 break;
904 case 3:
905 if (bswap) {
906 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
f6548c0a 907 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
908 tcg_out32 (s, STWBRX | SAB (data_reg2, rbase, r1));
2662e13f
FB
909 }
910 else {
f6548c0a 911#ifdef CONFIG_USE_GUEST_BASE
912 tcg_out32 (s, STWX | SAB (data_reg2, rbase, r0));
913 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
914 tcg_out32 (s, STWX | SAB (data_reg, rbase, r1));
915#else
2662e13f
FB
916 tcg_out32 (s, STW | RS (data_reg2) | RA (r0));
917 tcg_out32 (s, STW | RS (data_reg) | RA (r0) | 4);
f6548c0a 918#endif
2662e13f
FB
919 }
920 break;
921 }
922
923#ifdef CONFIG_SOFTMMU
924 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
925#endif
926}
927
e4d58b41 928static void tcg_target_qemu_prologue (TCGContext *s)
2662e13f 929{
0d5bd363 930 int i, frame_size;
2662e13f
FB
931
932 frame_size = 0
f9bf2987 933 + LINKAGE_AREA_SIZE
2662e13f
FB
934 + TCG_STATIC_CALL_ARGS_SIZE
935 + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
136a0b5a 936 + CPU_TEMP_BUF_NLONGS * sizeof(long)
2662e13f
FB
937 ;
938 frame_size = (frame_size + 15) & ~15;
939
136a0b5a
BS
940 tcg_set_frame(s, TCG_REG_CALL_STACK, frame_size
941 - CPU_TEMP_BUF_NLONGS * sizeof(long),
942 CPU_TEMP_BUF_NLONGS * sizeof(long));
943
6ec85236 944#ifdef _CALL_AIX
b29fe3ed 945 {
946 uint32_t addr;
947
948 /* First emit adhoc function descriptor */
949 addr = (uint32_t) s->code_ptr + 12;
950 tcg_out32 (s, addr); /* entry point */
951 s->code_ptr += 8; /* skip TOC and environment pointer */
952 }
953#endif
2662e13f
FB
954 tcg_out32 (s, MFSPR | RT (0) | LR);
955 tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
956 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
957 tcg_out32 (s, (STW
958 | RS (tcg_target_callee_save_regs[i])
959 | RA (1)
f9bf2987 960 | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
2662e13f
FB
961 )
962 );
2946898b 963 tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size + LR_OFFSET));
2662e13f 964
f6548c0a 965#ifdef CONFIG_USE_GUEST_BASE
b9e946c7
RH
966 if (GUEST_BASE) {
967 tcg_out_movi (s, TCG_TYPE_I32, TCG_GUEST_BASE_REG, GUEST_BASE);
968 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
969 }
f6548c0a 970#endif
971
cea5f9a2
BS
972 tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
973 tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
2662e13f
FB
974 tcg_out32 (s, BCCTR | BO_ALWAYS);
975 tb_ret_addr = s->code_ptr;
976
977 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
978 tcg_out32 (s, (LWZ
979 | RT (tcg_target_callee_save_regs[i])
980 | RA (1)
f9bf2987 981 | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
2662e13f
FB
982 )
983 );
2946898b 984 tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size + LR_OFFSET));
2662e13f
FB
985 tcg_out32 (s, MTSPR | RS (0) | LR);
986 tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
987 tcg_out32 (s, BCLR | BO_ALWAYS);
988}
989
2a534aff 990static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
2662e13f
FB
991 tcg_target_long arg2)
992{
993 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
994}
995
2a534aff 996static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
2662e13f
FB
997 tcg_target_long arg2)
998{
999 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
1000}
1001
1002static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
1003{
1004 if (!si && rt == ra)
1005 return;
1006
1007 if (si == (int16_t) si)
1008 tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
1009 else {
1010 uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
1011 tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
1012 tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
1013 }
1014}
1015
c596defd 1016static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
1017 int const_arg2, int cr)
2662e13f 1018{
2662e13f
FB
1019 int imm;
1020 uint32_t op;
1021
2662e13f 1022 switch (cond) {
f3f478a7
FB
1023 case TCG_COND_EQ:
1024 case TCG_COND_NE:
1025 if (const_arg2) {
1026 if ((int16_t) arg2 == arg2) {
1027 op = CMPI;
1028 imm = 1;
1029 break;
1030 }
1031 else if ((uint16_t) arg2 == arg2) {
1032 op = CMPLI;
1033 imm = 1;
1034 break;
1035 }
1036 }
1037 op = CMPL;
1038 imm = 0;
1039 break;
1040
1041 case TCG_COND_LT:
1042 case TCG_COND_GE:
1043 case TCG_COND_LE:
1044 case TCG_COND_GT:
1045 if (const_arg2) {
1046 if ((int16_t) arg2 == arg2) {
1047 op = CMPI;
1048 imm = 1;
1049 break;
1050 }
1051 }
1052 op = CMP;
1053 imm = 0;
1054 break;
1055
1056 case TCG_COND_LTU:
1057 case TCG_COND_GEU:
1058 case TCG_COND_LEU:
1059 case TCG_COND_GTU:
1060 if (const_arg2) {
1061 if ((uint16_t) arg2 == arg2) {
1062 op = CMPLI;
1063 imm = 1;
1064 break;
1065 }
1066 }
1067 op = CMPL;
1068 imm = 0;
1069 break;
1070
2662e13f
FB
1071 default:
1072 tcg_abort ();
1073 }
c596defd 1074 op |= BF (cr);
2662e13f
FB
1075
1076 if (imm)
1077 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
1078 else {
1079 if (const_arg2) {
1080 tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
1081 tcg_out32 (s, op | RA (arg1) | RB (0));
1082 }
1083 else
1084 tcg_out32 (s, op | RA (arg1) | RB (arg2));
1085 }
1086
c596defd 1087}
1088
1089static void tcg_out_bc (TCGContext *s, int bc, int label_index)
1090{
1091 TCGLabel *l = &s->labels[label_index];
1092
0a878c47 1093 if (l->has_value)
c596defd 1094 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
2662e13f 1095 else {
0a878c47 1096 uint16_t val = *(uint16_t *) &s->code_ptr[2];
1097
1098 /* Thanks to Andrzej Zaborowski */
c596defd 1099 tcg_out32 (s, bc | (val & 0xfffc));
2662e13f
FB
1100 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
1101 }
1102}
1103
b0809bf7 1104static void tcg_out_cr7eq_from_cond (TCGContext *s, const TCGArg *args,
1105 const int *const_args)
c596defd 1106{
8a56e840
RH
1107 TCGCond cond = args[4];
1108 int op;
c596defd 1109 struct { int bit1; int bit2; int cond2; } bits[] = {
1110 [TCG_COND_LT ] = { CR_LT, CR_LT, TCG_COND_LT },
1111 [TCG_COND_LE ] = { CR_LT, CR_GT, TCG_COND_LT },
1112 [TCG_COND_GT ] = { CR_GT, CR_GT, TCG_COND_GT },
1113 [TCG_COND_GE ] = { CR_GT, CR_LT, TCG_COND_GT },
1114 [TCG_COND_LTU] = { CR_LT, CR_LT, TCG_COND_LTU },
1115 [TCG_COND_LEU] = { CR_LT, CR_GT, TCG_COND_LTU },
1116 [TCG_COND_GTU] = { CR_GT, CR_GT, TCG_COND_GTU },
1117 [TCG_COND_GEU] = { CR_GT, CR_LT, TCG_COND_GTU },
1118 }, *b = &bits[cond];
1119
1120 switch (cond) {
2662e13f 1121 case TCG_COND_EQ:
2662e13f 1122 case TCG_COND_NE:
e924c485 1123 op = (cond == TCG_COND_EQ) ? CRAND : CRNAND;
1124 tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 6);
1125 tcg_out_cmp (s, cond, args[1], args[3], const_args[3], 7);
1126 tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
2662e13f
FB
1127 break;
1128 case TCG_COND_LT:
2662e13f 1129 case TCG_COND_LE:
2662e13f 1130 case TCG_COND_GT:
2662e13f 1131 case TCG_COND_GE:
2662e13f 1132 case TCG_COND_LTU:
2662e13f 1133 case TCG_COND_LEU:
2662e13f 1134 case TCG_COND_GTU:
2662e13f 1135 case TCG_COND_GEU:
c596defd 1136 op = (b->bit1 != b->bit2) ? CRANDC : CRAND;
1137 tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5);
efe72c8d 1138 tcg_out_cmp (s, tcg_unsigned_cond (cond), args[0], args[2],
1139 const_args[2], 7);
606257c6 1140 tcg_out32 (s, op | BT (7, CR_EQ) | BA (5, CR_EQ) | BB (7, b->bit2));
c596defd 1141 tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ));
2662e13f
FB
1142 break;
1143 default:
1144 tcg_abort();
1145 }
b0809bf7 1146}
1147
8a56e840 1148static void tcg_out_setcond (TCGContext *s, TCGCond cond, TCGArg arg0,
b0809bf7 1149 TCGArg arg1, TCGArg arg2, int const_arg2)
1150{
1151 int crop, sh, arg;
1152
1153 switch (cond) {
1154 case TCG_COND_EQ:
1155 if (const_arg2) {
1156 if (!arg2) {
1157 arg = arg1;
1158 }
1159 else {
1160 arg = 0;
1161 if ((uint16_t) arg2 == arg2) {
1162 tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
1163 }
1164 else {
1165 tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
1166 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1167 }
1168 }
1169 }
1170 else {
1171 arg = 0;
1172 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1173 }
1174 tcg_out32 (s, CNTLZW | RS (arg) | RA (0));
1175 tcg_out32 (s, (RLWINM
1176 | RA (arg0)
1177 | RS (0)
1178 | SH (27)
1179 | MB (5)
1180 | ME (31)
1181 )
1182 );
27a7797b 1183 break;
b0809bf7 1184
1185 case TCG_COND_NE:
1186 if (const_arg2) {
1187 if (!arg2) {
1188 arg = arg1;
1189 }
1190 else {
1191 arg = 0;
1192 if ((uint16_t) arg2 == arg2) {
1193 tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
1194 }
1195 else {
1196 tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
1197 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1198 }
1199 }
1200 }
1201 else {
1202 arg = 0;
1203 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1204 }
1205
1206 if (arg == arg1 && arg1 == arg0) {
1207 tcg_out32 (s, ADDIC | RT (0) | RA (arg) | 0xffff);
1208 tcg_out32 (s, SUBFE | TAB (arg0, 0, arg));
1209 }
1210 else {
1211 tcg_out32 (s, ADDIC | RT (arg0) | RA (arg) | 0xffff);
1212 tcg_out32 (s, SUBFE | TAB (arg0, arg0, arg));
1213 }
27a7797b 1214 break;
1215
1216 case TCG_COND_GT:
1217 case TCG_COND_GTU:
1218 sh = 30;
1219 crop = 0;
1220 goto crtest;
b0809bf7 1221
b0809bf7 1222 case TCG_COND_LT:
27a7797b 1223 case TCG_COND_LTU:
b0809bf7 1224 sh = 29;
1225 crop = 0;
27a7797b 1226 goto crtest;
b0809bf7 1227
b0809bf7 1228 case TCG_COND_GE:
27a7797b 1229 case TCG_COND_GEU:
b0809bf7 1230 sh = 31;
1231 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
27a7797b 1232 goto crtest;
b0809bf7 1233
b0809bf7 1234 case TCG_COND_LE:
27a7797b 1235 case TCG_COND_LEU:
b0809bf7 1236 sh = 31;
1237 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
27a7797b 1238 crtest:
1239 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
1240 if (crop) tcg_out32 (s, crop);
1241 tcg_out32 (s, MFCR | RT (0));
1242 tcg_out32 (s, (RLWINM
1243 | RA (arg0)
1244 | RS (0)
1245 | SH (sh)
1246 | MB (31)
1247 | ME (31)
1248 )
1249 );
b0809bf7 1250 break;
1251
1252 default:
1253 tcg_abort ();
1254 }
b0809bf7 1255}
1256
1257static void tcg_out_setcond2 (TCGContext *s, const TCGArg *args,
1258 const int *const_args)
1259{
1260 tcg_out_cr7eq_from_cond (s, args + 1, const_args + 1);
1261 tcg_out32 (s, MFCR | RT (0));
1262 tcg_out32 (s, (RLWINM
1263 | RA (args[0])
1264 | RS (0)
1265 | SH (31)
1266 | MB (31)
1267 | ME (31)
1268 )
1269 );
1270}
1271
8a56e840 1272static void tcg_out_brcond (TCGContext *s, TCGCond cond,
b0809bf7 1273 TCGArg arg1, TCGArg arg2, int const_arg2,
1274 int label_index)
1275{
1276 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
1277 tcg_out_bc (s, tcg_to_bc[cond], label_index);
1278}
1279
1280/* XXX: we implement it at the target level to avoid having to
1281 handle cross basic blocks temporaries */
1282static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
1283 const int *const_args)
1284{
1285 tcg_out_cr7eq_from_cond (s, args, const_args);
1286 tcg_out_bc (s, (BC | BI (7, CR_EQ) | BO_COND_TRUE), args[5]);
2662e13f
FB
1287}
1288
52781543 1289void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
1290{
1291 uint32_t *ptr;
1292 long disp = addr - jmp_addr;
1293 unsigned long patch_size;
1294
1295 ptr = (uint32_t *)jmp_addr;
1296
1297 if ((disp << 6) >> 6 != disp) {
1298 ptr[0] = 0x3c000000 | (addr >> 16); /* lis 0,addr@ha */
1299 ptr[1] = 0x60000000 | (addr & 0xffff); /* la 0,addr@l(0) */
1300 ptr[2] = 0x7c0903a6; /* mtctr 0 */
1301 ptr[3] = 0x4e800420; /* brctr */
1302 patch_size = 16;
1303 } else {
1304 /* patch the branch destination */
1305 if (disp != 16) {
1306 *ptr = 0x48000000 | (disp & 0x03fffffc); /* b disp */
1307 patch_size = 4;
1308 } else {
1309 ptr[0] = 0x60000000; /* nop */
1310 ptr[1] = 0x60000000;
1311 ptr[2] = 0x60000000;
1312 ptr[3] = 0x60000000;
1313 patch_size = 16;
1314 }
1315 }
1316 /* flush icache */
1317 flush_icache_range(jmp_addr, jmp_addr + patch_size);
1318}
1319
a9751609 1320static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
2662e13f
FB
1321 const int *const_args)
1322{
1323 switch (opc) {
1324 case INDEX_op_exit_tb:
1325 tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
932a6909 1326 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
2662e13f
FB
1327 break;
1328 case INDEX_op_goto_tb:
1329 if (s->tb_jmp_offset) {
1330 /* direct jump method */
932a6909 1331
2662e13f 1332 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
0a878c47 1333 s->code_ptr += 16;
932a6909
FB
1334 }
1335 else {
2662e13f
FB
1336 tcg_abort ();
1337 }
1338 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1339 break;
1340 case INDEX_op_br:
1341 {
1342 TCGLabel *l = &s->labels[args[0]];
1343
1344 if (l->has_value) {
932a6909 1345 tcg_out_b (s, 0, l->u.value);
2662e13f
FB
1346 }
1347 else {
0a878c47 1348 uint32_t val = *(uint32_t *) s->code_ptr;
1349
1350 /* Thanks to Andrzej Zaborowski */
1351 tcg_out32 (s, B | (val & 0x3fffffc));
2662e13f
FB
1352 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1353 }
1354 }
1355 break;
1356 case INDEX_op_call:
b29fe3ed 1357 tcg_out_call (s, args[0], const_args[0]);
2662e13f
FB
1358 break;
1359 case INDEX_op_jmp:
1360 if (const_args[0]) {
932a6909 1361 tcg_out_b (s, 0, args[0]);
2662e13f
FB
1362 }
1363 else {
1364 tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
1365 tcg_out32 (s, BCCTR | BO_ALWAYS);
1366 }
1367 break;
1368 case INDEX_op_movi_i32:
1369 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1370 break;
1371 case INDEX_op_ld8u_i32:
1372 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1373 break;
1374 case INDEX_op_ld8s_i32:
1375 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1376 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1377 break;
1378 case INDEX_op_ld16u_i32:
1379 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1380 break;
1381 case INDEX_op_ld16s_i32:
1382 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1383 break;
1384 case INDEX_op_ld_i32:
1385 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1386 break;
1387 case INDEX_op_st8_i32:
1388 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1389 break;
1390 case INDEX_op_st16_i32:
1391 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1392 break;
1393 case INDEX_op_st_i32:
1394 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1395 break;
1396
1397 case INDEX_op_add_i32:
1398 if (const_args[2])
1399 ppc_addi (s, args[0], args[1], args[2]);
1400 else
1401 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1402 break;
1403 case INDEX_op_sub_i32:
1404 if (const_args[2])
1405 ppc_addi (s, args[0], args[1], -args[2]);
1406 else
1407 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1408 break;
1409
1410 case INDEX_op_and_i32:
1411 if (const_args[2]) {
c45851c4 1412 uint32_t c;
1413
1414 c = args[2];
1415
1416 if (!c) {
1417 tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
1418 break;
1419 }
1420#ifdef __PPU__
1421 uint32_t t, n;
1422 int mb, me;
1423
1424 n = c ^ -(c & 1);
1425 t = n + (n & -n);
1426
1427 if ((t & (t - 1)) == 0) {
1428 int lzc, tzc;
1429
1430 if ((c & 0x80000001) == 0x80000001) {
1431 lzc = clz32 (n);
1432 tzc = ctz32 (n);
1433
1434 mb = 32 - tzc;
1435 me = lzc - 1;
1436 }
1437 else {
1438 lzc = clz32 (c);
1439 tzc = ctz32 (c);
1440
1441 mb = lzc;
1442 me = 31 - tzc;
1443 }
1444
1445 tcg_out32 (s, (RLWINM
1446 | RA (args[0])
1447 | RS (args[1])
1448 | SH (0)
1449 | MB (mb)
1450 | ME (me)
1451 )
1452 );
1453 }
1454 else
1455#endif /* !__PPU__ */
1456 {
1457 if ((c & 0xffff) == c)
1458 tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | c);
1459 else if ((c & 0xffff0000) == c)
1460 tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
1461 | ((c >> 16) & 0xffff));
1462 else {
1463 tcg_out_movi (s, TCG_TYPE_I32, 0, c);
1464 tcg_out32 (s, AND | SAB (args[1], args[0], 0));
1465 }
2662e13f
FB
1466 }
1467 }
1468 else
1469 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1470 break;
1471 case INDEX_op_or_i32:
1472 if (const_args[2]) {
000a2d86 1473 if (args[2] & 0xffff) {
1474 tcg_out32 (s, ORI | RS (args[1]) | RA (args[0])
1475 | (args[2] & 0xffff));
1476 if (args[2] >> 16)
1477 tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
2662e13f 1478 | ((args[2] >> 16) & 0xffff));
2662e13f
FB
1479 }
1480 else {
000a2d86 1481 tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0])
1482 | ((args[2] >> 16) & 0xffff));
2662e13f
FB
1483 }
1484 }
1485 else
1486 tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1487 break;
1488 case INDEX_op_xor_i32:
1489 if (const_args[2]) {
000a2d86 1490 if ((args[2] & 0xffff) == args[2])
1491 tcg_out32 (s, XORI | RS (args[1]) | RA (args[0])
1492 | (args[2] & 0xffff));
1493 else if ((args[2] & 0xffff0000) == args[2])
1494 tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0])
1495 | ((args[2] >> 16) & 0xffff));
2662e13f 1496 else {
000a2d86 1497 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1498 tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
2662e13f
FB
1499 }
1500 }
1501 else
1502 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1503 break;
65fe043e 1504 case INDEX_op_andc_i32:
1505 tcg_out32 (s, ANDC | SAB (args[1], args[0], args[2]));
1506 break;
1507 case INDEX_op_orc_i32:
1508 tcg_out32 (s, ORC | SAB (args[1], args[0], args[2]));
1509 break;
aa77bebd 1510 case INDEX_op_eqv_i32:
1511 tcg_out32 (s, EQV | SAB (args[1], args[0], args[2]));
1512 break;
1513 case INDEX_op_nand_i32:
1514 tcg_out32 (s, NAND | SAB (args[1], args[0], args[2]));
1515 break;
1516 case INDEX_op_nor_i32:
1517 tcg_out32 (s, NOR | SAB (args[1], args[0], args[2]));
1518 break;
2662e13f
FB
1519
1520 case INDEX_op_mul_i32:
1521 if (const_args[2]) {
1522 if (args[2] == (int16_t) args[2])
1523 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1524 | (args[2] & 0xffff));
1525 else {
1526 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1527 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1528 }
1529 }
1530 else
1531 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1532 break;
77b73de6 1533
1534 case INDEX_op_div_i32:
1535 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1536 break;
1537
1538 case INDEX_op_divu_i32:
1539 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1540 break;
1541
1542 case INDEX_op_rem_i32:
1543 tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1544 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1545 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1546 break;
1547
1548 case INDEX_op_remu_i32:
1549 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1550 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1551 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1552 break;
1553
2662e13f
FB
1554 case INDEX_op_mulu2_i32:
1555 if (args[0] == args[2] || args[0] == args[3]) {
1556 tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
1557 tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
3b6dac34 1558 tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
2662e13f
FB
1559 }
1560 else {
1561 tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
1562 tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1563 }
1564 break;
2662e13f
FB
1565
1566 case INDEX_op_shl_i32:
1567 if (const_args[2]) {
000a2d86 1568 tcg_out32 (s, (RLWINM
1569 | RA (args[0])
1570 | RS (args[1])
1571 | SH (args[2])
1572 | MB (0)
1573 | ME (31 - args[2])
1574 )
1575 );
2662e13f
FB
1576 }
1577 else
1578 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
1579 break;
1580 case INDEX_op_shr_i32:
1581 if (const_args[2]) {
000a2d86 1582 tcg_out32 (s, (RLWINM
1583 | RA (args[0])
1584 | RS (args[1])
1585 | SH (32 - args[2])
1586 | MB (args[2])
1587 | ME (31)
1588 )
1589 );
2662e13f
FB
1590 }
1591 else
1592 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
1593 break;
1594 case INDEX_op_sar_i32:
1595 if (const_args[2])
1596 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1597 else
1598 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1599 break;
65fe043e 1600 case INDEX_op_rotl_i32:
1601 {
1602 int op = 0
1603 | RA (args[0])
1604 | RS (args[1])
1605 | MB (0)
1606 | ME (31)
1607 | (const_args[2] ? RLWINM | SH (args[2])
1608 : RLWNM | RB (args[2]))
1609 ;
1610 tcg_out32 (s, op);
1611 }
1612 break;
1613 case INDEX_op_rotr_i32:
1614 if (const_args[2]) {
1615 if (!args[2]) {
3b6dac34 1616 tcg_out_mov (s, TCG_TYPE_I32, args[0], args[1]);
65fe043e 1617 }
1618 else {
1619 tcg_out32 (s, RLWINM
1620 | RA (args[0])
1621 | RS (args[1])
1622 | SH (32 - args[2])
1623 | MB (0)
1624 | ME (31)
1625 );
1626 }
1627 }
1628 else {
d616cf1d 1629 tcg_out32 (s, SUBFIC | RT (0) | RA (args[2]) | 32);
65fe043e 1630 tcg_out32 (s, RLWNM
1631 | RA (args[0])
1632 | RS (args[1])
1633 | RB (0)
1634 | MB (0)
1635 | ME (31)
1636 );
1637 }
1638 break;
2662e13f
FB
1639
1640 case INDEX_op_add2_i32:
1641 if (args[0] == args[3] || args[0] == args[5]) {
1642 tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
1643 tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
3b6dac34 1644 tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
2662e13f
FB
1645 }
1646 else {
1647 tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
1648 tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1649 }
1650 break;
1651 case INDEX_op_sub2_i32:
1652 if (args[0] == args[3] || args[0] == args[5]) {
1653 tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
1654 tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
3b6dac34 1655 tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
2662e13f
FB
1656 }
1657 else {
1658 tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
1659 tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1660 }
1661 break;
1662
1663 case INDEX_op_brcond_i32:
1664 /*
1665 args[0] = r0
1666 args[1] = r1
1667 args[2] = cond
1668 args[3] = r1 is const
1669 args[4] = label_index
1670 */
1671 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
1672 break;
1673 case INDEX_op_brcond2_i32:
1674 tcg_out_brcond2(s, args, const_args);
1675 break;
1676
1677 case INDEX_op_neg_i32:
1678 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1679 break;
1680
65fe043e 1681 case INDEX_op_not_i32:
36368cf0 1682 tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
65fe043e 1683 break;
1684
2662e13f
FB
1685 case INDEX_op_qemu_ld8u:
1686 tcg_out_qemu_ld(s, args, 0);
1687 break;
1688 case INDEX_op_qemu_ld8s:
1689 tcg_out_qemu_ld(s, args, 0 | 4);
1690 break;
1691 case INDEX_op_qemu_ld16u:
1692 tcg_out_qemu_ld(s, args, 1);
1693 break;
1694 case INDEX_op_qemu_ld16s:
1695 tcg_out_qemu_ld(s, args, 1 | 4);
1696 break;
86feb1c8 1697 case INDEX_op_qemu_ld32:
2662e13f
FB
1698 tcg_out_qemu_ld(s, args, 2);
1699 break;
1700 case INDEX_op_qemu_ld64:
1701 tcg_out_qemu_ld(s, args, 3);
1702 break;
1703 case INDEX_op_qemu_st8:
1704 tcg_out_qemu_st(s, args, 0);
1705 break;
1706 case INDEX_op_qemu_st16:
1707 tcg_out_qemu_st(s, args, 1);
1708 break;
1709 case INDEX_op_qemu_st32:
1710 tcg_out_qemu_st(s, args, 2);
1711 break;
1712 case INDEX_op_qemu_st64:
1713 tcg_out_qemu_st(s, args, 3);
1714 break;
1715
e46b9681 1716 case INDEX_op_ext8s_i32:
1717 tcg_out32 (s, EXTSB | RS (args[1]) | RA (args[0]));
1718 break;
65fe043e 1719 case INDEX_op_ext8u_i32:
1720 tcg_out32 (s, RLWINM
1721 | RA (args[0])
1722 | RS (args[1])
1723 | SH (0)
1724 | MB (24)
1725 | ME (31)
1726 );
1727 break;
e46b9681 1728 case INDEX_op_ext16s_i32:
1729 tcg_out32 (s, EXTSH | RS (args[1]) | RA (args[0]));
1730 break;
65fe043e 1731 case INDEX_op_ext16u_i32:
1732 tcg_out32 (s, RLWINM
1733 | RA (args[0])
1734 | RS (args[1])
1735 | SH (0)
1736 | MB (16)
1737 | ME (31)
1738 );
1739 break;
e46b9681 1740
b0809bf7 1741 case INDEX_op_setcond_i32:
1742 tcg_out_setcond (s, args[3], args[0], args[1], args[2], const_args[2]);
1743 break;
1744 case INDEX_op_setcond2_i32:
1745 tcg_out_setcond2 (s, args, const_args);
1746 break;
1747
a884dcb8 1748 case INDEX_op_bswap16_i32:
1749 /* Stolen from gcc's builtin_bswap16 */
1750
1751 /* a1 = abcd */
1752
1753 /* r0 = (a1 << 8) & 0xff00 # 00d0 */
1754 tcg_out32 (s, RLWINM
1755 | RA (0)
1756 | RS (args[1])
1757 | SH (8)
1758 | MB (16)
1759 | ME (23)
1760 );
1761
1762 /* a0 = rotate_left (a1, 24) & 0xff # 000c */
1763 tcg_out32 (s, RLWINM
1764 | RA (args[0])
1765 | RS (args[1])
1766 | SH (24)
1767 | MB (24)
1768 | ME (31)
1769 );
1770
1771 /* a0 = a0 | r0 # 00dc */
1772 tcg_out32 (s, OR | SAB (0, args[0], args[0]));
1773 break;
1774
1775 case INDEX_op_bswap32_i32:
1776 /* Stolen from gcc's builtin_bswap32 */
1777 {
1778 int a0 = args[0];
1779
1780 /* a1 = args[1] # abcd */
1781
1782 if (a0 == args[1]) {
1783 a0 = 0;
1784 }
1785
1786 /* a0 = rotate_left (a1, 8) # bcda */
1787 tcg_out32 (s, RLWINM
1788 | RA (a0)
1789 | RS (args[1])
1790 | SH (8)
1791 | MB (0)
1792 | ME (31)
1793 );
1794
1795 /* a0 = (a0 & ~0xff000000) | ((a1 << 24) & 0xff000000) # dcda */
1796 tcg_out32 (s, RLWIMI
1797 | RA (a0)
1798 | RS (args[1])
1799 | SH (24)
1800 | MB (0)
1801 | ME (7)
1802 );
1803
1804 /* a0 = (a0 & ~0x0000ff00) | ((a1 << 24) & 0x0000ff00) # dcba */
1805 tcg_out32 (s, RLWIMI
1806 | RA (a0)
1807 | RS (args[1])
1808 | SH (24)
1809 | MB (16)
1810 | ME (23)
1811 );
1812
1813 if (!a0) {
3b6dac34 1814 tcg_out_mov (s, TCG_TYPE_I32, args[0], a0);
a884dcb8 1815 }
1816 }
1817 break;
1818
350dba6c 1819 case INDEX_op_deposit_i32:
1820 tcg_out32 (s, RLWIMI
1821 | RA (args[0])
1822 | RS (args[2])
1823 | SH (args[3])
1824 | MB (32 - args[3] - args[4])
1825 | ME (31 - args[3])
1826 );
1827 break;
1828
2662e13f
FB
1829 default:
1830 tcg_dump_ops (s, stderr);
1831 tcg_abort ();
1832 }
1833}
1834
1835static const TCGTargetOpDef ppc_op_defs[] = {
1836 { INDEX_op_exit_tb, { } },
1837 { INDEX_op_goto_tb, { } },
932a6909
FB
1838 { INDEX_op_call, { "ri" } },
1839 { INDEX_op_jmp, { "ri" } },
2662e13f
FB
1840 { INDEX_op_br, { } },
1841
1842 { INDEX_op_mov_i32, { "r", "r" } },
1843 { INDEX_op_movi_i32, { "r" } },
1844 { INDEX_op_ld8u_i32, { "r", "r" } },
1845 { INDEX_op_ld8s_i32, { "r", "r" } },
1846 { INDEX_op_ld16u_i32, { "r", "r" } },
1847 { INDEX_op_ld16s_i32, { "r", "r" } },
1848 { INDEX_op_ld_i32, { "r", "r" } },
1849 { INDEX_op_st8_i32, { "r", "r" } },
1850 { INDEX_op_st16_i32, { "r", "r" } },
1851 { INDEX_op_st_i32, { "r", "r" } },
1852
1853 { INDEX_op_add_i32, { "r", "r", "ri" } },
1854 { INDEX_op_mul_i32, { "r", "r", "ri" } },
77b73de6 1855 { INDEX_op_div_i32, { "r", "r", "r" } },
1856 { INDEX_op_divu_i32, { "r", "r", "r" } },
1857 { INDEX_op_rem_i32, { "r", "r", "r" } },
1858 { INDEX_op_remu_i32, { "r", "r", "r" } },
2662e13f 1859 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
2662e13f
FB
1860 { INDEX_op_sub_i32, { "r", "r", "ri" } },
1861 { INDEX_op_and_i32, { "r", "r", "ri" } },
1862 { INDEX_op_or_i32, { "r", "r", "ri" } },
1863 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1864
1865 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1866 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1867 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1868
65fe043e 1869 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1870 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1871
2662e13f
FB
1872 { INDEX_op_brcond_i32, { "r", "ri" } },
1873
1874 { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1875 { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1876 { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1877
1878 { INDEX_op_neg_i32, { "r", "r" } },
65fe043e 1879 { INDEX_op_not_i32, { "r", "r" } },
1880
1881 { INDEX_op_andc_i32, { "r", "r", "r" } },
1882 { INDEX_op_orc_i32, { "r", "r", "r" } },
aa77bebd 1883 { INDEX_op_eqv_i32, { "r", "r", "r" } },
1884 { INDEX_op_nand_i32, { "r", "r", "r" } },
1885 { INDEX_op_nor_i32, { "r", "r", "r" } },
2662e13f 1886
b0809bf7 1887 { INDEX_op_setcond_i32, { "r", "r", "ri" } },
1888 { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1889
a884dcb8 1890 { INDEX_op_bswap16_i32, { "r", "r" } },
1891 { INDEX_op_bswap32_i32, { "r", "r" } },
1892
2662e13f
FB
1893#if TARGET_LONG_BITS == 32
1894 { INDEX_op_qemu_ld8u, { "r", "L" } },
1895 { INDEX_op_qemu_ld8s, { "r", "L" } },
1896 { INDEX_op_qemu_ld16u, { "r", "L" } },
1897 { INDEX_op_qemu_ld16s, { "r", "L" } },
86feb1c8 1898 { INDEX_op_qemu_ld32, { "r", "L" } },
2662e13f
FB
1899 { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1900
1901 { INDEX_op_qemu_st8, { "K", "K" } },
1902 { INDEX_op_qemu_st16, { "K", "K" } },
1903 { INDEX_op_qemu_st32, { "K", "K" } },
1904 { INDEX_op_qemu_st64, { "M", "M", "M" } },
1905#else
1906 { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1907 { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1908 { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1909 { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
86feb1c8 1910 { INDEX_op_qemu_ld32, { "r", "L", "L" } },
2662e13f
FB
1911 { INDEX_op_qemu_ld64, { "r", "L", "L", "L" } },
1912
1913 { INDEX_op_qemu_st8, { "K", "K", "K" } },
1914 { INDEX_op_qemu_st16, { "K", "K", "K" } },
1915 { INDEX_op_qemu_st32, { "K", "K", "K" } },
1916 { INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
1917#endif
1918
e46b9681 1919 { INDEX_op_ext8s_i32, { "r", "r" } },
65fe043e 1920 { INDEX_op_ext8u_i32, { "r", "r" } },
e46b9681 1921 { INDEX_op_ext16s_i32, { "r", "r" } },
65fe043e 1922 { INDEX_op_ext16u_i32, { "r", "r" } },
e46b9681 1923
350dba6c 1924 { INDEX_op_deposit_i32, { "r", "0", "r" } },
1925
2662e13f
FB
1926 { -1 },
1927};
1928
e4d58b41 1929static void tcg_target_init(TCGContext *s)
2662e13f
FB
1930{
1931 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1932 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1933 (1 << TCG_REG_R0) |
6ec85236 1934#ifdef _CALL_DARWIN
f9bf2987 1935 (1 << TCG_REG_R2) |
1936#endif
2662e13f
FB
1937 (1 << TCG_REG_R3) |
1938 (1 << TCG_REG_R4) |
1939 (1 << TCG_REG_R5) |
1940 (1 << TCG_REG_R6) |
1941 (1 << TCG_REG_R7) |
1942 (1 << TCG_REG_R8) |
1943 (1 << TCG_REG_R9) |
1944 (1 << TCG_REG_R10) |
1945 (1 << TCG_REG_R11) |
1946 (1 << TCG_REG_R12)
1947 );
1948
1949 tcg_regset_clear(s->reserved_regs);
1950 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
1951 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
6ec85236 1952#ifndef _CALL_DARWIN
2662e13f 1953 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
f9bf2987 1954#endif
6ec85236 1955#ifdef _CALL_SYSV
5db3ee79 1956 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13);
1957#endif
2662e13f
FB
1958
1959 tcg_add_target_add_op_defs(ppc_op_defs);
1960}