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