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