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