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