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