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