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