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