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