]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/ppc64/tcg-target.c
tcg-ppc64: Merge ppc32 brcond2, setcond2, muluh
[mirror_qemu.git] / tcg / ppc64 / tcg-target.c
CommitLineData
810260a8 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
ffcfbece
RH
27#if defined _CALL_DARWIN || defined __APPLE__
28#define TCG_TARGET_CALL_DARWIN
29#endif
30
de3d636d
RH
31/* Shorthand for size of a pointer. Avoid promotion to unsigned. */
32#define SZP ((int)sizeof(void *))
33
4c3831a0
RH
34/* Shorthand for size of a register. */
35#define SZR (TCG_TARGET_REG_BITS / 8)
36
3d582c61
RH
37#define TCG_CT_CONST_S16 0x100
38#define TCG_CT_CONST_U16 0x200
39#define TCG_CT_CONST_S32 0x400
40#define TCG_CT_CONST_U32 0x800
41#define TCG_CT_CONST_ZERO 0x1000
6c858762 42#define TCG_CT_CONST_MONE 0x2000
fe6f943f 43
e083c4a2 44static tcg_insn_unit *tb_ret_addr;
810260a8 45
f6548c0a 46#ifndef GUEST_BASE
47#define GUEST_BASE 0
48#endif
49
cd629de1 50#include "elf.h"
1e6e9aca
RH
51static bool have_isa_2_06;
52#define HAVE_ISA_2_06 have_isa_2_06
53#define HAVE_ISEL have_isa_2_06
49d9870a 54
f6548c0a 55#ifdef CONFIG_USE_GUEST_BASE
56#define TCG_GUEST_BASE_REG 30
57#else
58#define TCG_GUEST_BASE_REG 0
59#endif
60
d4a9eb1f 61#ifndef NDEBUG
810260a8 62static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
63 "r0",
64 "r1",
98926b0a 65 "r2",
810260a8 66 "r3",
67 "r4",
68 "r5",
69 "r6",
70 "r7",
71 "r8",
72 "r9",
73 "r10",
74 "r11",
75 "r12",
76 "r13",
77 "r14",
78 "r15",
79 "r16",
80 "r17",
81 "r18",
82 "r19",
83 "r20",
84 "r21",
85 "r22",
86 "r23",
87 "r24",
88 "r25",
89 "r26",
90 "r27",
91 "r28",
92 "r29",
93 "r30",
94 "r31"
95};
d4a9eb1f 96#endif
810260a8 97
98static const int tcg_target_reg_alloc_order[] = {
5e1702b0 99 TCG_REG_R14, /* call saved registers */
810260a8 100 TCG_REG_R15,
101 TCG_REG_R16,
102 TCG_REG_R17,
103 TCG_REG_R18,
104 TCG_REG_R19,
105 TCG_REG_R20,
106 TCG_REG_R21,
107 TCG_REG_R22,
108 TCG_REG_R23,
5e1702b0
RH
109 TCG_REG_R24,
110 TCG_REG_R25,
111 TCG_REG_R26,
112 TCG_REG_R27,
810260a8 113 TCG_REG_R28,
114 TCG_REG_R29,
115 TCG_REG_R30,
116 TCG_REG_R31,
5e1702b0
RH
117 TCG_REG_R12, /* call clobbered, non-arguments */
118 TCG_REG_R11,
5e1702b0 119 TCG_REG_R10, /* call clobbered, arguments */
810260a8 120 TCG_REG_R9,
5e1702b0
RH
121 TCG_REG_R8,
122 TCG_REG_R7,
123 TCG_REG_R6,
124 TCG_REG_R5,
125 TCG_REG_R4,
126 TCG_REG_R3,
810260a8 127};
128
129static const int tcg_target_call_iarg_regs[] = {
130 TCG_REG_R3,
131 TCG_REG_R4,
132 TCG_REG_R5,
133 TCG_REG_R6,
134 TCG_REG_R7,
135 TCG_REG_R8,
136 TCG_REG_R9,
137 TCG_REG_R10
138};
139
be9c4183 140static const int tcg_target_call_oarg_regs[] = {
810260a8 141 TCG_REG_R3
142};
143
144static const int tcg_target_callee_save_regs[] = {
5d7ff5bb
AF
145#ifdef __APPLE__
146 TCG_REG_R11,
147#endif
810260a8 148 TCG_REG_R14,
149 TCG_REG_R15,
150 TCG_REG_R16,
151 TCG_REG_R17,
152 TCG_REG_R18,
153 TCG_REG_R19,
154 TCG_REG_R20,
155 TCG_REG_R21,
156 TCG_REG_R22,
157 TCG_REG_R23,
095271d4 158 TCG_REG_R24,
159 TCG_REG_R25,
160 TCG_REG_R26,
cea5f9a2 161 TCG_REG_R27, /* currently used for the global env */
810260a8 162 TCG_REG_R28,
163 TCG_REG_R29,
164 TCG_REG_R30,
165 TCG_REG_R31
166};
167
b0940da0
RH
168static inline bool in_range_b(tcg_target_long target)
169{
170 return target == sextract64(target, 0, 26);
171}
172
e083c4a2 173static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target)
810260a8 174{
e083c4a2 175 ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
b0940da0 176 assert(in_range_b(disp));
810260a8 177 return disp & 0x3fffffc;
178}
179
e083c4a2 180static void reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target)
810260a8 181{
e083c4a2 182 *pc = (*pc & ~0x3fffffc) | reloc_pc24_val(pc, target);
810260a8 183}
184
e083c4a2 185static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target)
810260a8 186{
e083c4a2
RH
187 ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
188 assert(disp == (int16_t) disp);
810260a8 189 return disp & 0xfffc;
190}
191
e083c4a2 192static void reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
810260a8 193{
e083c4a2 194 *pc = (*pc & ~0xfffc) | reloc_pc14_val(pc, target);
810260a8 195}
196
c7ca6a2b
RH
197static inline void tcg_out_b_noaddr(TCGContext *s, int insn)
198{
e083c4a2 199 unsigned retrans = *s->code_ptr & 0x3fffffc;
c7ca6a2b
RH
200 tcg_out32(s, insn | retrans);
201}
202
203static inline void tcg_out_bc_noaddr(TCGContext *s, int insn)
204{
e083c4a2 205 unsigned retrans = *s->code_ptr & 0xfffc;
c7ca6a2b
RH
206 tcg_out32(s, insn | retrans);
207}
208
e083c4a2 209static void patch_reloc(tcg_insn_unit *code_ptr, int type,
541dd4ce 210 intptr_t value, intptr_t addend)
810260a8 211{
e083c4a2
RH
212 tcg_insn_unit *target = (tcg_insn_unit *)value;
213
214 assert(addend == 0);
810260a8 215 switch (type) {
216 case R_PPC_REL14:
e083c4a2 217 reloc_pc14(code_ptr, target);
810260a8 218 break;
219 case R_PPC_REL24:
e083c4a2 220 reloc_pc24(code_ptr, target);
810260a8 221 break;
222 default:
541dd4ce 223 tcg_abort();
810260a8 224 }
225}
226
810260a8 227/* parse target specific constraints */
541dd4ce 228static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
810260a8 229{
230 const char *ct_str;
231
232 ct_str = *pct_str;
233 switch (ct_str[0]) {
234 case 'A': case 'B': case 'C': case 'D':
235 ct->ct |= TCG_CT_REG;
541dd4ce 236 tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
810260a8 237 break;
238 case 'r':
239 ct->ct |= TCG_CT_REG;
541dd4ce 240 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
810260a8 241 break;
242 case 'L': /* qemu_ld constraint */
243 ct->ct |= TCG_CT_REG;
541dd4ce
RH
244 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
245 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
735ee40d 246#ifdef CONFIG_SOFTMMU
541dd4ce
RH
247 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
248 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
735ee40d 249#endif
810260a8 250 break;
c070355d 251 case 'S': /* qemu_st constraint */
810260a8 252 ct->ct |= TCG_CT_REG;
541dd4ce
RH
253 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
254 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
735ee40d 255#ifdef CONFIG_SOFTMMU
541dd4ce
RH
256 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
257 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
258 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
735ee40d 259#endif
810260a8 260 break;
3d582c61
RH
261 case 'I':
262 ct->ct |= TCG_CT_CONST_S16;
263 break;
264 case 'J':
265 ct->ct |= TCG_CT_CONST_U16;
266 break;
6c858762
RH
267 case 'M':
268 ct->ct |= TCG_CT_CONST_MONE;
269 break;
3d582c61
RH
270 case 'T':
271 ct->ct |= TCG_CT_CONST_S32;
272 break;
273 case 'U':
fe6f943f 274 ct->ct |= TCG_CT_CONST_U32;
275 break;
3d582c61
RH
276 case 'Z':
277 ct->ct |= TCG_CT_CONST_ZERO;
278 break;
810260a8 279 default:
280 return -1;
281 }
282 ct_str++;
283 *pct_str = ct_str;
284 return 0;
285}
286
287/* test if a constant matches the constraint */
f6c6afc1 288static int tcg_target_const_match(tcg_target_long val, TCGType type,
541dd4ce 289 const TCGArgConstraint *arg_ct)
810260a8 290{
3d582c61
RH
291 int ct = arg_ct->ct;
292 if (ct & TCG_CT_CONST) {
293 return 1;
1194dcba
RH
294 }
295
296 /* The only 32-bit constraint we use aside from
297 TCG_CT_CONST is TCG_CT_CONST_S16. */
298 if (type == TCG_TYPE_I32) {
299 val = (int32_t)val;
300 }
301
302 if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
3d582c61
RH
303 return 1;
304 } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
810260a8 305 return 1;
3d582c61 306 } else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
fe6f943f 307 return 1;
3d582c61
RH
308 } else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
309 return 1;
310 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
311 return 1;
6c858762
RH
312 } else if ((ct & TCG_CT_CONST_MONE) && val == -1) {
313 return 1;
3d582c61 314 }
810260a8 315 return 0;
316}
317
318#define OPCD(opc) ((opc)<<26)
319#define XO19(opc) (OPCD(19)|((opc)<<1))
8a94cfb0
AB
320#define MD30(opc) (OPCD(30)|((opc)<<2))
321#define MDS30(opc) (OPCD(30)|((opc)<<1))
810260a8 322#define XO31(opc) (OPCD(31)|((opc)<<1))
323#define XO58(opc) (OPCD(58)|(opc))
324#define XO62(opc) (OPCD(62)|(opc))
325
326#define B OPCD( 18)
327#define BC OPCD( 16)
328#define LBZ OPCD( 34)
329#define LHZ OPCD( 40)
330#define LHA OPCD( 42)
331#define LWZ OPCD( 32)
332#define STB OPCD( 38)
333#define STH OPCD( 44)
334#define STW OPCD( 36)
335
336#define STD XO62( 0)
337#define STDU XO62( 1)
338#define STDX XO31(149)
339
340#define LD XO58( 0)
341#define LDX XO31( 21)
342#define LDU XO58( 1)
301f6d90 343#define LWA XO58( 2)
810260a8 344#define LWAX XO31(341)
345
1cd62ae9 346#define ADDIC OPCD( 12)
810260a8 347#define ADDI OPCD( 14)
348#define ADDIS OPCD( 15)
349#define ORI OPCD( 24)
350#define ORIS OPCD( 25)
351#define XORI OPCD( 26)
352#define XORIS OPCD( 27)
353#define ANDI OPCD( 28)
354#define ANDIS OPCD( 29)
355#define MULLI OPCD( 7)
356#define CMPLI OPCD( 10)
357#define CMPI OPCD( 11)
148bdd23 358#define SUBFIC OPCD( 8)
810260a8 359
360#define LWZU OPCD( 33)
361#define STWU OPCD( 37)
362
313d91c7 363#define RLWIMI OPCD( 20)
810260a8 364#define RLWINM OPCD( 21)
313d91c7 365#define RLWNM OPCD( 23)
810260a8 366
8a94cfb0
AB
367#define RLDICL MD30( 0)
368#define RLDICR MD30( 1)
369#define RLDIMI MD30( 3)
370#define RLDCL MDS30( 8)
810260a8 371
372#define BCLR XO19( 16)
373#define BCCTR XO19(528)
374#define CRAND XO19(257)
375#define CRANDC XO19(129)
376#define CRNAND XO19(225)
377#define CROR XO19(449)
1cd62ae9 378#define CRNOR XO19( 33)
810260a8 379
380#define EXTSB XO31(954)
381#define EXTSH XO31(922)
382#define EXTSW XO31(986)
383#define ADD XO31(266)
384#define ADDE XO31(138)
6c858762
RH
385#define ADDME XO31(234)
386#define ADDZE XO31(202)
810260a8 387#define ADDC XO31( 10)
388#define AND XO31( 28)
389#define SUBF XO31( 40)
390#define SUBFC XO31( 8)
391#define SUBFE XO31(136)
6c858762
RH
392#define SUBFME XO31(232)
393#define SUBFZE XO31(200)
810260a8 394#define OR XO31(444)
395#define XOR XO31(316)
396#define MULLW XO31(235)
397#define MULHWU XO31( 11)
398#define DIVW XO31(491)
399#define DIVWU XO31(459)
400#define CMP XO31( 0)
401#define CMPL XO31( 32)
402#define LHBRX XO31(790)
403#define LWBRX XO31(534)
49d9870a 404#define LDBRX XO31(532)
810260a8 405#define STHBRX XO31(918)
406#define STWBRX XO31(662)
49d9870a 407#define STDBRX XO31(660)
810260a8 408#define MFSPR XO31(339)
409#define MTSPR XO31(467)
410#define SRAWI XO31(824)
411#define NEG XO31(104)
1cd62ae9 412#define MFCR XO31( 19)
6995a4a0 413#define MFOCRF (MFCR | (1u << 20))
157f2662 414#define NOR XO31(124)
1cd62ae9 415#define CNTLZW XO31( 26)
416#define CNTLZD XO31( 58)
ce1010d6
RH
417#define ANDC XO31( 60)
418#define ORC XO31(412)
419#define EQV XO31(284)
420#define NAND XO31(476)
70fac59a 421#define ISEL XO31( 15)
810260a8 422
423#define MULLD XO31(233)
424#define MULHD XO31( 73)
425#define MULHDU XO31( 9)
426#define DIVD XO31(489)
427#define DIVDU XO31(457)
428
429#define LBZX XO31( 87)
4f4a67ae 430#define LHZX XO31(279)
810260a8 431#define LHAX XO31(343)
432#define LWZX XO31( 23)
433#define STBX XO31(215)
434#define STHX XO31(407)
435#define STWX XO31(151)
436
541dd4ce 437#define SPR(a, b) ((((a)<<5)|(b))<<11)
810260a8 438#define LR SPR(8, 0)
439#define CTR SPR(9, 0)
440
441#define SLW XO31( 24)
442#define SRW XO31(536)
443#define SRAW XO31(792)
444
445#define SLD XO31( 27)
446#define SRD XO31(539)
447#define SRAD XO31(794)
fe6f943f 448#define SRADI XO31(413<<1)
810260a8 449
810260a8 450#define TW XO31( 4)
541dd4ce 451#define TRAP (TW | TO(31))
810260a8 452
453#define RT(r) ((r)<<21)
454#define RS(r) ((r)<<21)
455#define RA(r) ((r)<<16)
456#define RB(r) ((r)<<11)
457#define TO(t) ((t)<<21)
458#define SH(s) ((s)<<11)
459#define MB(b) ((b)<<6)
460#define ME(e) ((e)<<1)
461#define BO(o) ((o)<<21)
462#define MB64(b) ((b)<<5)
6995a4a0 463#define FXM(b) (1 << (19 - (b)))
810260a8 464
465#define LK 1
466
2fd8eddc
RH
467#define TAB(t, a, b) (RT(t) | RA(a) | RB(b))
468#define SAB(s, a, b) (RS(s) | RA(a) | RB(b))
469#define TAI(s, a, i) (RT(s) | RA(a) | ((i) & 0xffff))
470#define SAI(s, a, i) (RS(s) | RA(a) | ((i) & 0xffff))
810260a8 471
472#define BF(n) ((n)<<23)
473#define BI(n, c) (((c)+((n)*4))<<16)
474#define BT(n, c) (((c)+((n)*4))<<21)
475#define BA(n, c) (((c)+((n)*4))<<16)
476#define BB(n, c) (((c)+((n)*4))<<11)
70fac59a 477#define BC_(n, c) (((c)+((n)*4))<<6)
810260a8 478
541dd4ce
RH
479#define BO_COND_TRUE BO(12)
480#define BO_COND_FALSE BO( 4)
481#define BO_ALWAYS BO(20)
810260a8 482
483enum {
484 CR_LT,
485 CR_GT,
486 CR_EQ,
487 CR_SO
488};
489
0aed257f 490static const uint32_t tcg_to_bc[] = {
541dd4ce
RH
491 [TCG_COND_EQ] = BC | BI(7, CR_EQ) | BO_COND_TRUE,
492 [TCG_COND_NE] = BC | BI(7, CR_EQ) | BO_COND_FALSE,
493 [TCG_COND_LT] = BC | BI(7, CR_LT) | BO_COND_TRUE,
494 [TCG_COND_GE] = BC | BI(7, CR_LT) | BO_COND_FALSE,
495 [TCG_COND_LE] = BC | BI(7, CR_GT) | BO_COND_FALSE,
496 [TCG_COND_GT] = BC | BI(7, CR_GT) | BO_COND_TRUE,
497 [TCG_COND_LTU] = BC | BI(7, CR_LT) | BO_COND_TRUE,
498 [TCG_COND_GEU] = BC | BI(7, CR_LT) | BO_COND_FALSE,
499 [TCG_COND_LEU] = BC | BI(7, CR_GT) | BO_COND_FALSE,
500 [TCG_COND_GTU] = BC | BI(7, CR_GT) | BO_COND_TRUE,
810260a8 501};
502
70fac59a
RH
503/* The low bit here is set if the RA and RB fields must be inverted. */
504static const uint32_t tcg_to_isel[] = {
505 [TCG_COND_EQ] = ISEL | BC_(7, CR_EQ),
506 [TCG_COND_NE] = ISEL | BC_(7, CR_EQ) | 1,
507 [TCG_COND_LT] = ISEL | BC_(7, CR_LT),
508 [TCG_COND_GE] = ISEL | BC_(7, CR_LT) | 1,
509 [TCG_COND_LE] = ISEL | BC_(7, CR_GT) | 1,
510 [TCG_COND_GT] = ISEL | BC_(7, CR_GT),
511 [TCG_COND_LTU] = ISEL | BC_(7, CR_LT),
512 [TCG_COND_GEU] = ISEL | BC_(7, CR_LT) | 1,
513 [TCG_COND_LEU] = ISEL | BC_(7, CR_GT) | 1,
514 [TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
515};
516
796f1a68 517static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
810260a8 518{
796f1a68 519 tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
f8b84129
RH
520 if (ret != arg) {
521 tcg_out32(s, OR | SAB(arg, ret, arg));
522 }
810260a8 523}
524
aceac8d6
RH
525static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
526 int sh, int mb)
810260a8 527{
541dd4ce
RH
528 sh = SH(sh & 0x1f) | (((sh >> 5) & 1) << 1);
529 mb = MB64((mb >> 5) | ((mb << 1) & 0x3f));
530 tcg_out32(s, op | RA(ra) | RS(rs) | sh | mb);
810260a8 531}
532
9e555b73
RH
533static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
534 int sh, int mb, int me)
535{
536 tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
537}
538
6e5e0602
RH
539static inline void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
540{
541 tcg_out_rld(s, RLDICL, dst, src, 0, 32);
542}
543
0a9564b9
RH
544static inline void tcg_out_shli64(TCGContext *s, TCGReg dst, TCGReg src, int c)
545{
546 tcg_out_rld(s, RLDICR, dst, src, c, 63 - c);
547}
548
5e916c28
RH
549static inline void tcg_out_shri64(TCGContext *s, TCGReg dst, TCGReg src, int c)
550{
551 tcg_out_rld(s, RLDICL, dst, src, 64 - c, c);
552}
553
aceac8d6 554static void tcg_out_movi32(TCGContext *s, TCGReg ret, int32_t arg)
810260a8 555{
2fd8eddc
RH
556 if (arg == (int16_t) arg) {
557 tcg_out32(s, ADDI | TAI(ret, 0, arg));
558 } else {
559 tcg_out32(s, ADDIS | TAI(ret, 0, arg >> 16));
560 if (arg & 0xffff) {
561 tcg_out32(s, ORI | SAI(ret, ret, arg));
562 }
810260a8 563 }
564}
565
421233a1
RH
566static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
567 tcg_target_long arg)
810260a8 568{
796f1a68 569 tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
421233a1
RH
570 if (type == TCG_TYPE_I32 || arg == (int32_t)arg) {
571 tcg_out_movi32(s, ret, arg);
572 } else if (arg == (uint32_t)arg && !(arg & 0x8000)) {
573 tcg_out32(s, ADDI | TAI(ret, 0, arg));
574 tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
575 } else {
796f1a68 576 int32_t high = arg >> 31 >> 1;
421233a1
RH
577 tcg_out_movi32(s, ret, high);
578 if (high) {
0a9564b9 579 tcg_out_shli64(s, ret, ret, 32);
421233a1
RH
580 }
581 if (arg & 0xffff0000) {
582 tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
583 }
584 if (arg & 0xffff) {
585 tcg_out32(s, ORI | SAI(ret, ret, arg));
810260a8 586 }
587 }
588}
589
637af30c 590static bool mask_operand(uint32_t c, int *mb, int *me)
a9249dff
RH
591{
592 uint32_t lsb, test;
593
594 /* Accept a bit pattern like:
595 0....01....1
596 1....10....0
597 0..01..10..0
598 Keep track of the transitions. */
599 if (c == 0 || c == -1) {
600 return false;
601 }
602 test = c;
603 lsb = test & -test;
604 test += lsb;
605 if (test & (test - 1)) {
606 return false;
607 }
608
609 *me = clz32(lsb);
610 *mb = test ? clz32(test & -test) + 1 : 0;
611 return true;
612}
613
637af30c
RH
614static bool mask64_operand(uint64_t c, int *mb, int *me)
615{
616 uint64_t lsb;
617
618 if (c == 0) {
619 return false;
620 }
621
622 lsb = c & -c;
623 /* Accept 1..10..0. */
624 if (c == -lsb) {
625 *mb = 0;
626 *me = clz64(lsb);
627 return true;
628 }
629 /* Accept 0..01..1. */
630 if (lsb == 1 && (c & (c + 1)) == 0) {
631 *mb = clz64(c + 1) + 1;
632 *me = 63;
633 return true;
634 }
635 return false;
636}
637
a9249dff
RH
638static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
639{
640 int mb, me;
641
642 if ((c & 0xffff) == c) {
643 tcg_out32(s, ANDI | SAI(src, dst, c));
644 return;
645 } else if ((c & 0xffff0000) == c) {
646 tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
647 return;
648 } else if (mask_operand(c, &mb, &me)) {
649 tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
650 } else {
8327a470
RH
651 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R0, c);
652 tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
a9249dff
RH
653 }
654}
655
637af30c
RH
656static void tcg_out_andi64(TCGContext *s, TCGReg dst, TCGReg src, uint64_t c)
657{
658 int mb, me;
659
660 if ((c & 0xffff) == c) {
661 tcg_out32(s, ANDI | SAI(src, dst, c));
662 return;
663 } else if ((c & 0xffff0000) == c) {
664 tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
665 return;
666 } else if (mask64_operand(c, &mb, &me)) {
667 if (mb == 0) {
668 tcg_out_rld(s, RLDICR, dst, src, 0, me);
669 } else {
670 tcg_out_rld(s, RLDICL, dst, src, 0, mb);
671 }
672 } else {
8327a470
RH
673 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, c);
674 tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
637af30c
RH
675 }
676}
677
dce74c57
RH
678static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
679 int op_lo, int op_hi)
680{
681 if (c >> 16) {
682 tcg_out32(s, op_hi | SAI(src, dst, c >> 16));
683 src = dst;
684 }
685 if (c & 0xffff) {
686 tcg_out32(s, op_lo | SAI(src, dst, c));
687 src = dst;
688 }
689}
690
691static void tcg_out_ori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
692{
693 tcg_out_zori32(s, dst, src, c, ORI, ORIS);
694}
695
696static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
697{
698 tcg_out_zori32(s, dst, src, c, XORI, XORIS);
699}
700
e083c4a2 701static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
5d7ff5bb 702{
e083c4a2 703 ptrdiff_t disp = tcg_pcrel_diff(s, target);
b0940da0 704 if (in_range_b(disp)) {
541dd4ce
RH
705 tcg_out32(s, B | (disp & 0x3fffffc) | mask);
706 } else {
de3d636d 707 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, (uintptr_t)target);
8327a470 708 tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
541dd4ce 709 tcg_out32(s, BCCTR | BO_ALWAYS | mask);
5d7ff5bb
AF
710 }
711}
712
b18d5d2b
RH
713static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
714 TCGReg base, tcg_target_long offset)
810260a8 715{
b18d5d2b 716 tcg_target_long orig = offset, l0, l1, extra = 0, align = 0;
de7761a3 717 bool is_store = false;
b18d5d2b
RH
718 TCGReg rs = TCG_REG_R2;
719
b18d5d2b
RH
720 switch (opi) {
721 case LD: case LWA:
722 align = 3;
723 /* FALLTHRU */
724 default:
725 if (rt != TCG_REG_R0) {
726 rs = rt;
de7761a3 727 break;
b18d5d2b
RH
728 }
729 break;
730 case STD:
731 align = 3;
de7761a3 732 /* FALLTHRU */
b18d5d2b 733 case STB: case STH: case STW:
de7761a3 734 is_store = true;
b18d5d2b 735 break;
810260a8 736 }
810260a8 737
b18d5d2b
RH
738 /* For unaligned, or very large offsets, use the indexed form. */
739 if (offset & align || offset != (int32_t)offset) {
de7761a3
RH
740 tcg_debug_assert(rs != base && (!is_store || rs != rt));
741 tcg_out_movi(s, TCG_TYPE_PTR, rs, orig);
742 tcg_out32(s, opx | TAB(rt, base, rs));
b18d5d2b
RH
743 return;
744 }
745
746 l0 = (int16_t)offset;
747 offset = (offset - l0) >> 16;
748 l1 = (int16_t)offset;
749
750 if (l1 < 0 && orig >= 0) {
751 extra = 0x4000;
752 l1 = (int16_t)(offset - 0x4000);
753 }
754 if (l1) {
755 tcg_out32(s, ADDIS | TAI(rs, base, l1));
756 base = rs;
757 }
758 if (extra) {
759 tcg_out32(s, ADDIS | TAI(rs, base, extra));
760 base = rs;
761 }
762 if (opi != ADDI || base != rt || l0 != 0) {
763 tcg_out32(s, opi | TAI(rt, base, l0));
828808f5 764 }
765}
766
d604f1a9
RH
767static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
768 TCGReg arg1, intptr_t arg2)
769{
770 int opi, opx;
810260a8 771
d604f1a9
RH
772 if (type == TCG_TYPE_I32) {
773 opi = LWZ, opx = LWZX;
774 } else {
775 opi = LD, opx = LDX;
776 }
777 tcg_out_mem_long(s, opi, opx, ret, arg1, arg2);
778}
fedee3e7 779
d604f1a9
RH
780static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
781 TCGReg arg1, intptr_t arg2)
810260a8 782{
d604f1a9 783 int opi, opx;
fedee3e7 784
d604f1a9
RH
785 if (type == TCG_TYPE_I32) {
786 opi = STW, opx = STWX;
fedee3e7 787 } else {
d604f1a9 788 opi = STD, opx = STDX;
fedee3e7 789 }
d604f1a9
RH
790 tcg_out_mem_long(s, opi, opx, arg, arg1, arg2);
791}
810260a8 792
d604f1a9
RH
793static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
794 int const_arg2, int cr, TCGType type)
795{
796 int imm;
797 uint32_t op;
810260a8 798
abcf61c4
RH
799 tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
800
d604f1a9
RH
801 /* Simplify the comparisons below wrt CMPI. */
802 if (type == TCG_TYPE_I32) {
803 arg2 = (int32_t)arg2;
4a40e231 804 }
fedee3e7 805
d604f1a9
RH
806 switch (cond) {
807 case TCG_COND_EQ:
808 case TCG_COND_NE:
809 if (const_arg2) {
810 if ((int16_t) arg2 == arg2) {
811 op = CMPI;
812 imm = 1;
813 break;
814 } else if ((uint16_t) arg2 == arg2) {
815 op = CMPLI;
816 imm = 1;
817 break;
818 }
819 }
820 op = CMPL;
821 imm = 0;
822 break;
fedee3e7 823
d604f1a9
RH
824 case TCG_COND_LT:
825 case TCG_COND_GE:
826 case TCG_COND_LE:
827 case TCG_COND_GT:
828 if (const_arg2) {
829 if ((int16_t) arg2 == arg2) {
830 op = CMPI;
831 imm = 1;
832 break;
833 }
834 }
835 op = CMP;
836 imm = 0;
837 break;
fedee3e7 838
d604f1a9
RH
839 case TCG_COND_LTU:
840 case TCG_COND_GEU:
841 case TCG_COND_LEU:
842 case TCG_COND_GTU:
843 if (const_arg2) {
844 if ((uint16_t) arg2 == arg2) {
845 op = CMPLI;
846 imm = 1;
847 break;
848 }
849 }
850 op = CMPL;
851 imm = 0;
852 break;
fedee3e7 853
d604f1a9
RH
854 default:
855 tcg_abort();
fedee3e7 856 }
d604f1a9 857 op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
fedee3e7 858
d604f1a9
RH
859 if (imm) {
860 tcg_out32(s, op | RA(arg1) | (arg2 & 0xffff));
861 } else {
862 if (const_arg2) {
863 tcg_out_movi(s, type, TCG_REG_R0, arg2);
864 arg2 = TCG_REG_R0;
865 }
866 tcg_out32(s, op | RA(arg1) | RB(arg2));
867 }
810260a8 868}
869
d604f1a9
RH
870static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
871 TCGReg dst, TCGReg src)
7f12d649 872{
d604f1a9
RH
873 tcg_out32(s, (type == TCG_TYPE_I64 ? CNTLZD : CNTLZW) | RS(src) | RA(dst));
874 tcg_out_shri64(s, dst, dst, type == TCG_TYPE_I64 ? 6 : 5);
7f12d649
RH
875}
876
d604f1a9 877static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src)
7f12d649 878{
d604f1a9
RH
879 /* X != 0 implies X + -1 generates a carry. Extra addition
880 trickery means: R = X-1 + ~X + C = X-1 + (-X+1) + C = C. */
881 if (dst != src) {
882 tcg_out32(s, ADDIC | TAI(dst, src, -1));
883 tcg_out32(s, SUBFE | TAB(dst, dst, src));
7f12d649 884 } else {
d604f1a9
RH
885 tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
886 tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src));
7f12d649 887 }
d604f1a9 888}
7f12d649 889
d604f1a9
RH
890static TCGReg tcg_gen_setcond_xor(TCGContext *s, TCGReg arg1, TCGArg arg2,
891 bool const_arg2)
892{
893 if (const_arg2) {
894 if ((uint32_t)arg2 == arg2) {
895 tcg_out_xori32(s, TCG_REG_R0, arg1, arg2);
896 } else {
897 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, arg2);
898 tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, TCG_REG_R0));
899 }
900 } else {
901 tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, arg2));
902 }
903 return TCG_REG_R0;
7f12d649
RH
904}
905
d604f1a9
RH
906static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
907 TCGArg arg0, TCGArg arg1, TCGArg arg2,
908 int const_arg2)
7f12d649 909{
d604f1a9 910 int crop, sh;
7f12d649 911
d604f1a9
RH
912 /* Ignore high bits of a potential constant arg2. */
913 if (type == TCG_TYPE_I32) {
914 arg2 = (uint32_t)arg2;
915 }
7f12d649 916
d604f1a9
RH
917 /* Handle common and trivial cases before handling anything else. */
918 if (arg2 == 0) {
919 switch (cond) {
920 case TCG_COND_EQ:
921 tcg_out_setcond_eq0(s, type, arg0, arg1);
922 return;
923 case TCG_COND_NE:
924 if (type == TCG_TYPE_I32) {
925 tcg_out_ext32u(s, TCG_REG_R0, arg1);
926 arg1 = TCG_REG_R0;
927 }
928 tcg_out_setcond_ne0(s, arg0, arg1);
929 return;
930 case TCG_COND_GE:
931 tcg_out32(s, NOR | SAB(arg1, arg0, arg1));
932 arg1 = arg0;
933 /* FALLTHRU */
934 case TCG_COND_LT:
935 /* Extract the sign bit. */
936 tcg_out_rld(s, RLDICL, arg0, arg1,
937 type == TCG_TYPE_I64 ? 1 : 33, 63);
938 return;
939 default:
940 break;
941 }
942 }
7f12d649 943
d604f1a9
RH
944 /* If we have ISEL, we can implement everything with 3 or 4 insns.
945 All other cases below are also at least 3 insns, so speed up the
946 code generator by not considering them and always using ISEL. */
947 if (HAVE_ISEL) {
948 int isel, tab;
7f12d649 949
d604f1a9 950 tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
7f12d649 951
d604f1a9 952 isel = tcg_to_isel[cond];
7f12d649 953
d604f1a9
RH
954 tcg_out_movi(s, type, arg0, 1);
955 if (isel & 1) {
956 /* arg0 = (bc ? 0 : 1) */
957 tab = TAB(arg0, 0, arg0);
958 isel &= ~1;
959 } else {
960 /* arg0 = (bc ? 1 : 0) */
961 tcg_out_movi(s, type, TCG_REG_R0, 0);
962 tab = TAB(arg0, arg0, TCG_REG_R0);
963 }
964 tcg_out32(s, isel | tab);
965 return;
966 }
49d9870a 967
d604f1a9
RH
968 switch (cond) {
969 case TCG_COND_EQ:
970 arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
971 tcg_out_setcond_eq0(s, type, arg0, arg1);
972 return;
810260a8 973
d604f1a9
RH
974 case TCG_COND_NE:
975 arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
976 /* Discard the high bits only once, rather than both inputs. */
977 if (type == TCG_TYPE_I32) {
978 tcg_out_ext32u(s, TCG_REG_R0, arg1);
979 arg1 = TCG_REG_R0;
980 }
981 tcg_out_setcond_ne0(s, arg0, arg1);
982 return;
810260a8 983
d604f1a9
RH
984 case TCG_COND_GT:
985 case TCG_COND_GTU:
986 sh = 30;
987 crop = 0;
988 goto crtest;
810260a8 989
d604f1a9
RH
990 case TCG_COND_LT:
991 case TCG_COND_LTU:
992 sh = 29;
993 crop = 0;
994 goto crtest;
810260a8 995
d604f1a9
RH
996 case TCG_COND_GE:
997 case TCG_COND_GEU:
998 sh = 31;
999 crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_LT) | BB(7, CR_LT);
1000 goto crtest;
810260a8 1001
d604f1a9
RH
1002 case TCG_COND_LE:
1003 case TCG_COND_LEU:
1004 sh = 31;
1005 crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_GT) | BB(7, CR_GT);
1006 crtest:
1007 tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
1008 if (crop) {
1009 tcg_out32(s, crop);
1010 }
1011 tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
1012 tcg_out_rlw(s, RLWINM, arg0, TCG_REG_R0, sh, 31, 31);
1013 break;
1014
1015 default:
1016 tcg_abort();
1017 }
810260a8 1018}
1019
d604f1a9 1020static void tcg_out_bc(TCGContext *s, int bc, int label_index)
810260a8 1021{
d604f1a9 1022 TCGLabel *l = &s->labels[label_index];
810260a8 1023
d604f1a9
RH
1024 if (l->has_value) {
1025 tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
49d9870a 1026 } else {
d604f1a9
RH
1027 tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
1028 tcg_out_bc_noaddr(s, bc);
810260a8 1029 }
810260a8 1030}
1031
d604f1a9
RH
1032static void tcg_out_brcond(TCGContext *s, TCGCond cond,
1033 TCGArg arg1, TCGArg arg2, int const_arg2,
1034 int label_index, TCGType type)
810260a8 1035{
d604f1a9
RH
1036 tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
1037 tcg_out_bc(s, tcg_to_bc[cond], label_index);
1038}
fa94c3be 1039
d604f1a9
RH
1040static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
1041 TCGArg dest, TCGArg c1, TCGArg c2, TCGArg v1,
1042 TCGArg v2, bool const_c2)
1043{
1044 /* If for some reason both inputs are zero, don't produce bad code. */
1045 if (v1 == 0 && v2 == 0) {
1046 tcg_out_movi(s, type, dest, 0);
1047 return;
b9e946c7 1048 }
f6548c0a 1049
d604f1a9 1050 tcg_out_cmp(s, cond, c1, c2, const_c2, 7, type);
a69abbe0 1051
d604f1a9
RH
1052 if (HAVE_ISEL) {
1053 int isel = tcg_to_isel[cond];
810260a8 1054
d604f1a9
RH
1055 /* Swap the V operands if the operation indicates inversion. */
1056 if (isel & 1) {
1057 int t = v1;
1058 v1 = v2;
1059 v2 = t;
1060 isel &= ~1;
1061 }
1062 /* V1 == 0 is handled by isel; V2 == 0 must be handled by hand. */
1063 if (v2 == 0) {
1064 tcg_out_movi(s, type, TCG_REG_R0, 0);
1065 }
1066 tcg_out32(s, isel | TAB(dest, v1, v2));
1067 } else {
1068 if (dest == v2) {
1069 cond = tcg_invert_cond(cond);
1070 v2 = v1;
1071 } else if (dest != v1) {
1072 if (v1 == 0) {
1073 tcg_out_movi(s, type, dest, 0);
1074 } else {
1075 tcg_out_mov(s, type, dest, v1);
1076 }
1077 }
1078 /* Branch forward over one insn */
1079 tcg_out32(s, tcg_to_bc[cond] | 8);
1080 if (v2 == 0) {
1081 tcg_out_movi(s, type, dest, 0);
1082 } else {
1083 tcg_out_mov(s, type, dest, v2);
1084 }
29b69198 1085 }
810260a8 1086}
1087
abcf61c4
RH
1088static void tcg_out_cmp2(TCGContext *s, const TCGArg *args,
1089 const int *const_args)
1090{
1091 static const struct { uint8_t bit1, bit2; } bits[] = {
1092 [TCG_COND_LT ] = { CR_LT, CR_LT },
1093 [TCG_COND_LE ] = { CR_LT, CR_GT },
1094 [TCG_COND_GT ] = { CR_GT, CR_GT },
1095 [TCG_COND_GE ] = { CR_GT, CR_LT },
1096 [TCG_COND_LTU] = { CR_LT, CR_LT },
1097 [TCG_COND_LEU] = { CR_LT, CR_GT },
1098 [TCG_COND_GTU] = { CR_GT, CR_GT },
1099 [TCG_COND_GEU] = { CR_GT, CR_LT },
1100 };
1101
1102 TCGCond cond = args[4], cond2;
1103 TCGArg al, ah, bl, bh;
1104 int blconst, bhconst;
1105 int op, bit1, bit2;
1106
1107 al = args[0];
1108 ah = args[1];
1109 bl = args[2];
1110 bh = args[3];
1111 blconst = const_args[2];
1112 bhconst = const_args[3];
1113
1114 switch (cond) {
1115 case TCG_COND_EQ:
1116 op = CRAND;
1117 goto do_equality;
1118 case TCG_COND_NE:
1119 op = CRNAND;
1120 do_equality:
1121 tcg_out_cmp(s, cond, al, bl, blconst, 6, TCG_TYPE_I32);
1122 tcg_out_cmp(s, cond, ah, bh, bhconst, 7, TCG_TYPE_I32);
1123 tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
1124 break;
1125
1126 case TCG_COND_LT:
1127 case TCG_COND_LE:
1128 case TCG_COND_GT:
1129 case TCG_COND_GE:
1130 case TCG_COND_LTU:
1131 case TCG_COND_LEU:
1132 case TCG_COND_GTU:
1133 case TCG_COND_GEU:
1134 bit1 = bits[cond].bit1;
1135 bit2 = bits[cond].bit2;
1136 op = (bit1 != bit2 ? CRANDC : CRAND);
1137 cond2 = tcg_unsigned_cond(cond);
1138
1139 tcg_out_cmp(s, cond, ah, bh, bhconst, 6, TCG_TYPE_I32);
1140 tcg_out_cmp(s, cond2, al, bl, blconst, 7, TCG_TYPE_I32);
1141 tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, bit2));
1142 tcg_out32(s, CROR | BT(7, CR_EQ) | BA(6, bit1) | BB(7, CR_EQ));
1143 break;
1144
1145 default:
1146 tcg_abort();
1147 }
1148}
1149
1150static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
1151 const int *const_args)
1152{
1153 tcg_out_cmp2(s, args + 1, const_args + 1);
1154 tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
1155 tcg_out_rlw(s, RLWINM, args[0], TCG_REG_R0, 31, 31, 31);
1156}
1157
1158static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
1159 const int *const_args)
1160{
1161 tcg_out_cmp2(s, args, const_args);
1162 tcg_out_bc(s, BC | BI(7, CR_EQ) | BO_COND_TRUE, args[5]);
1163}
1164
d604f1a9 1165void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
810260a8 1166{
d604f1a9 1167 TCGContext s;
b18d5d2b 1168
d604f1a9
RH
1169 s.code_buf = s.code_ptr = (tcg_insn_unit *)jmp_addr;
1170 tcg_out_b(&s, 0, (tcg_insn_unit *)addr);
1171 flush_icache_range(jmp_addr, jmp_addr + tcg_current_code_size(&s));
810260a8 1172}
1173
d604f1a9 1174static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
810260a8 1175{
eaf7d1cf 1176#ifdef _CALL_AIX
d604f1a9
RH
1177 /* Look through the descriptor. If the branch is in range, and we
1178 don't have to spend too much effort on building the toc. */
1179 void *tgt = ((void **)target)[0];
1180 uintptr_t toc = ((uintptr_t *)target)[1];
1181 intptr_t diff = tcg_pcrel_diff(s, tgt);
b18d5d2b 1182
d604f1a9
RH
1183 if (in_range_b(diff) && toc == (uint32_t)toc) {
1184 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, toc);
1185 tcg_out_b(s, LK, tgt);
541dd4ce 1186 } else {
d604f1a9
RH
1187 /* Fold the low bits of the constant into the addresses below. */
1188 intptr_t arg = (intptr_t)target;
1189 int ofs = (int16_t)arg;
1190
1191 if (ofs + 8 < 0x8000) {
1192 arg -= ofs;
1193 } else {
1194 ofs = 0;
1195 }
1196 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg);
4c3831a0 1197 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R2, ofs);
d604f1a9 1198 tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
4c3831a0 1199 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_REG_R2, ofs + SZP);
d604f1a9 1200 tcg_out32(s, BCCTR | BO_ALWAYS | LK);
541dd4ce 1201 }
77e58d0d
UW
1202#elif defined(_CALL_ELF) && _CALL_ELF == 2
1203 intptr_t diff;
1204
1205 /* In the ELFv2 ABI, we have to set up r12 to contain the destination
1206 address, which the callee uses to compute its TOC address. */
1207 /* FIXME: when the branch is in range, we could avoid r12 load if we
1208 knew that the destination uses the same TOC, and what its local
1209 entry point offset is. */
1210 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R12, (intptr_t)target);
1211
1212 diff = tcg_pcrel_diff(s, target);
1213 if (in_range_b(diff)) {
1214 tcg_out_b(s, LK, target);
1215 } else {
1216 tcg_out32(s, MTSPR | RS(TCG_REG_R12) | CTR);
1217 tcg_out32(s, BCCTR | BO_ALWAYS | LK);
1218 }
eaf7d1cf
RH
1219#else
1220 tcg_out_b(s, LK, target);
d604f1a9 1221#endif
810260a8 1222}
1223
d604f1a9
RH
1224static const uint32_t qemu_ldx_opc[16] = {
1225 [MO_UB] = LBZX,
1226 [MO_UW] = LHZX,
1227 [MO_UL] = LWZX,
1228 [MO_Q] = LDX,
1229 [MO_SW] = LHAX,
1230 [MO_SL] = LWAX,
1231 [MO_BSWAP | MO_UB] = LBZX,
1232 [MO_BSWAP | MO_UW] = LHBRX,
1233 [MO_BSWAP | MO_UL] = LWBRX,
1234 [MO_BSWAP | MO_Q] = LDBRX,
1235};
810260a8 1236
d604f1a9
RH
1237static const uint32_t qemu_stx_opc[16] = {
1238 [MO_UB] = STBX,
1239 [MO_UW] = STHX,
1240 [MO_UL] = STWX,
1241 [MO_Q] = STDX,
1242 [MO_BSWAP | MO_UB] = STBX,
1243 [MO_BSWAP | MO_UW] = STHBRX,
1244 [MO_BSWAP | MO_UL] = STWBRX,
1245 [MO_BSWAP | MO_Q] = STDBRX,
1246};
991041a4 1247
d604f1a9
RH
1248static const uint32_t qemu_exts_opc[4] = {
1249 EXTSB, EXTSH, EXTSW, 0
1250};
810260a8 1251
d604f1a9
RH
1252#if defined (CONFIG_SOFTMMU)
1253/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
1254 * int mmu_idx, uintptr_t ra)
1255 */
1256static void * const qemu_ld_helpers[16] = {
1257 [MO_UB] = helper_ret_ldub_mmu,
1258 [MO_LEUW] = helper_le_lduw_mmu,
1259 [MO_LEUL] = helper_le_ldul_mmu,
1260 [MO_LEQ] = helper_le_ldq_mmu,
1261 [MO_BEUW] = helper_be_lduw_mmu,
1262 [MO_BEUL] = helper_be_ldul_mmu,
1263 [MO_BEQ] = helper_be_ldq_mmu,
1264};
810260a8 1265
d604f1a9
RH
1266/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
1267 * uintxx_t val, int mmu_idx, uintptr_t ra)
1268 */
1269static void * const qemu_st_helpers[16] = {
1270 [MO_UB] = helper_ret_stb_mmu,
1271 [MO_LEUW] = helper_le_stw_mmu,
1272 [MO_LEUL] = helper_le_stl_mmu,
1273 [MO_LEQ] = helper_le_stq_mmu,
1274 [MO_BEUW] = helper_be_stw_mmu,
1275 [MO_BEUL] = helper_be_stl_mmu,
1276 [MO_BEQ] = helper_be_stq_mmu,
1277};
810260a8 1278
d604f1a9
RH
1279/* Perform the TLB load and compare. Places the result of the comparison
1280 in CR7, loads the addend of the TLB into R3, and returns the register
1281 containing the guest address (zero-extended into R4). Clobbers R0 and R2. */
1282
1283static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
1284 int mem_index, bool is_read)
1285{
1286 int cmp_off
1287 = (is_read
1288 ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1289 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1290 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1291 TCGReg base = TCG_AREG0;
1292
1293 /* Extract the page index, shifted into place for tlb index. */
1294 if (TARGET_LONG_BITS == 32) {
1295 /* Zero-extend the address into a place helpful for further use. */
1296 tcg_out_ext32u(s, TCG_REG_R4, addr_reg);
1297 addr_reg = TCG_REG_R4;
1298 } else {
1299 tcg_out_rld(s, RLDICL, TCG_REG_R3, addr_reg,
1300 64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);
810260a8 1301 }
810260a8 1302
d604f1a9
RH
1303 /* Compensate for very large offsets. */
1304 if (add_off >= 0x8000) {
1305 /* Most target env are smaller than 32k; none are larger than 64k.
1306 Simplify the logic here merely to offset by 0x7ff0, giving us a
1307 range just shy of 64k. Check this assumption. */
1308 QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
1309 tlb_table[NB_MMU_MODES - 1][1])
1310 > 0x7ff0 + 0x7fff);
1311 tcg_out32(s, ADDI | TAI(TCG_REG_R2, base, 0x7ff0));
1312 base = TCG_REG_R2;
1313 cmp_off -= 0x7ff0;
1314 add_off -= 0x7ff0;
1315 }
1316
1317 /* Extraction and shifting, part 2. */
1318 if (TARGET_LONG_BITS == 32) {
1319 tcg_out_rlw(s, RLWINM, TCG_REG_R3, addr_reg,
1320 32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
1321 32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
1322 31 - CPU_TLB_ENTRY_BITS);
4c314da6 1323 } else {
d604f1a9 1324 tcg_out_shli64(s, TCG_REG_R3, TCG_REG_R3, CPU_TLB_ENTRY_BITS);
810260a8 1325 }
810260a8 1326
d604f1a9 1327 tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));
1cd62ae9 1328
d604f1a9 1329 /* Load the tlb comparator. */
4c3831a0 1330 tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_R2, TCG_REG_R3, cmp_off);
d604f1a9
RH
1331
1332 /* Load the TLB addend for use on the fast path. Do this asap
1333 to minimize any load use delay. */
4c3831a0 1334 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_REG_R3, add_off);
d604f1a9
RH
1335
1336 /* Clear the non-page, non-alignment bits from the address. */
1337 if (TARGET_LONG_BITS == 32) {
1338 tcg_out_rlw(s, RLWINM, TCG_REG_R0, addr_reg, 0,
1339 (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
1340 } else if (!s_bits) {
1341 tcg_out_rld(s, RLDICR, TCG_REG_R0, addr_reg, 0, 63 - TARGET_PAGE_BITS);
70fac59a 1342 } else {
d604f1a9
RH
1343 tcg_out_rld(s, RLDICL, TCG_REG_R0, addr_reg,
1344 64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
1345 tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
70fac59a 1346 }
d604f1a9 1347
4c3831a0 1348 tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_R2, 0, 7, TCG_TYPE_TL);
d604f1a9
RH
1349
1350 return addr_reg;
70fac59a 1351}
1cd62ae9 1352
d604f1a9
RH
1353/* Record the context of a call to the out of line helper code for the slow
1354 path for a load or store, so that we can later generate the correct
1355 helper code. */
1356static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
1357 int data_reg, int addr_reg, int mem_index,
1358 tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
70fac59a 1359{
d604f1a9
RH
1360 TCGLabelQemuLdst *label = new_ldst_label(s);
1361
1362 label->is_ld = is_ld;
1363 label->opc = opc;
1364 label->datalo_reg = data_reg;
1365 label->addrlo_reg = addr_reg;
1366 label->mem_index = mem_index;
1367 label->raddr = raddr;
1368 label->label_ptr[0] = label_ptr;
70fac59a 1369}
1cd62ae9 1370
d604f1a9 1371static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
70fac59a 1372{
d604f1a9 1373 TCGMemOp opc = lb->opc;
70fac59a 1374
d604f1a9 1375 reloc_pc14(lb->label_ptr[0], s->code_ptr);
70fac59a 1376
d604f1a9 1377 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
1cd62ae9 1378
d604f1a9
RH
1379 /* If the address needed to be zero-extended, we'll have already
1380 placed it in R4. The only remaining case is 64-bit guest. */
1381 tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
752c1fdb 1382
d604f1a9
RH
1383 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, lb->mem_index);
1384 tcg_out32(s, MFSPR | RT(TCG_REG_R6) | LR);
70fac59a 1385
d604f1a9 1386 tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
70fac59a 1387
d604f1a9
RH
1388 if (opc & MO_SIGN) {
1389 uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
1390 tcg_out32(s, insn | RA(lb->datalo_reg) | RS(TCG_REG_R3));
1391 } else {
1392 tcg_out_mov(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_R3);
70fac59a
RH
1393 }
1394
d604f1a9
RH
1395 tcg_out_b(s, 0, lb->raddr);
1396}
70fac59a 1397
d604f1a9
RH
1398static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1399{
1400 TCGMemOp opc = lb->opc;
1401 TCGMemOp s_bits = opc & MO_SIZE;
1cd62ae9 1402
d604f1a9 1403 reloc_pc14(lb->label_ptr[0], s->code_ptr);
1cd62ae9 1404
d604f1a9 1405 tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, TCG_AREG0);
1cd62ae9 1406
d604f1a9
RH
1407 /* If the address needed to be zero-extended, we'll have already
1408 placed it in R4. The only remaining case is 64-bit guest. */
1409 tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
1cd62ae9 1410
d604f1a9
RH
1411 tcg_out_rld(s, RLDICL, TCG_REG_R5, lb->datalo_reg,
1412 0, 64 - (1 << (3 + s_bits)));
1413 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
1414 tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
1cd62ae9 1415
d604f1a9
RH
1416 tcg_out_call(s, qemu_st_helpers[opc]);
1417
1418 tcg_out_b(s, 0, lb->raddr);
1cd62ae9 1419}
d604f1a9 1420#endif /* SOFTMMU */
1cd62ae9 1421
d604f1a9
RH
1422static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1423 TCGMemOp opc, int mem_index)
810260a8 1424{
d604f1a9
RH
1425 TCGReg rbase;
1426 uint32_t insn;
1427 TCGMemOp s_bits = opc & MO_SIZE;
1428#ifdef CONFIG_SOFTMMU
1429 tcg_insn_unit *label_ptr;
1430#endif
810260a8 1431
d604f1a9
RH
1432#ifdef CONFIG_SOFTMMU
1433 addr_reg = tcg_out_tlb_read(s, s_bits, addr_reg, mem_index, true);
1434
1435 /* Load a pointer into the current opcode w/conditional branch-link. */
1436 label_ptr = s->code_ptr;
1437 tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
1438
1439 rbase = TCG_REG_R3;
1440#else /* !CONFIG_SOFTMMU */
1441 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
1442 if (TARGET_LONG_BITS == 32) {
1443 tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
1444 addr_reg = TCG_REG_R2;
1445 }
1446#endif
1447
1448 insn = qemu_ldx_opc[opc];
1449 if (!HAVE_ISA_2_06 && insn == LDBRX) {
1450 tcg_out32(s, ADDI | TAI(TCG_REG_R0, addr_reg, 4));
1451 tcg_out32(s, LWBRX | TAB(data_reg, rbase, addr_reg));
1452 tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
1453 tcg_out_rld(s, RLDIMI, data_reg, TCG_REG_R0, 32, 0);
1454 } else if (insn) {
1455 tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
541dd4ce 1456 } else {
d604f1a9
RH
1457 insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
1458 tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
1459 insn = qemu_exts_opc[s_bits];
1460 tcg_out32(s, insn | RA(data_reg) | RS(data_reg));
810260a8 1461 }
810260a8 1462
d604f1a9
RH
1463#ifdef CONFIG_SOFTMMU
1464 add_qemu_ldst_label(s, true, opc, data_reg, addr_reg, mem_index,
1465 s->code_ptr, label_ptr);
1466#endif
810260a8 1467}
1468
d604f1a9
RH
1469static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1470 TCGMemOp opc, int mem_index)
027ffea9 1471{
d604f1a9
RH
1472 TCGReg rbase;
1473 uint32_t insn;
1474#ifdef CONFIG_SOFTMMU
1475 tcg_insn_unit *label_ptr;
1476#endif
027ffea9 1477
d604f1a9
RH
1478#ifdef CONFIG_SOFTMMU
1479 addr_reg = tcg_out_tlb_read(s, opc & MO_SIZE, addr_reg, mem_index, false);
027ffea9 1480
d604f1a9
RH
1481 /* Load a pointer into the current opcode w/conditional branch-link. */
1482 label_ptr = s->code_ptr;
1483 tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
027ffea9 1484
d604f1a9
RH
1485 rbase = TCG_REG_R3;
1486#else /* !CONFIG_SOFTMMU */
1487 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
1488 if (TARGET_LONG_BITS == 32) {
1489 tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
1490 addr_reg = TCG_REG_R2;
1491 }
1492#endif
1493
1494 insn = qemu_stx_opc[opc];
1495 if (!HAVE_ISA_2_06 && insn == STDBRX) {
1496 tcg_out32(s, STWBRX | SAB(data_reg, rbase, addr_reg));
1497 tcg_out32(s, ADDI | TAI(TCG_REG_R2, addr_reg, 4));
1498 tcg_out_shri64(s, TCG_REG_R0, data_reg, 32);
1499 tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_R2));
027ffea9 1500 } else {
d604f1a9 1501 tcg_out32(s, insn | SAB(data_reg, rbase, addr_reg));
027ffea9 1502 }
d604f1a9
RH
1503
1504#ifdef CONFIG_SOFTMMU
1505 add_qemu_ldst_label(s, false, opc, data_reg, addr_reg, mem_index,
1506 s->code_ptr, label_ptr);
1507#endif
027ffea9
RH
1508}
1509
a921fddc
RH
1510/* Parameters for function call generation, used in tcg.c. */
1511#define TCG_TARGET_STACK_ALIGN 16
a921fddc
RH
1512#define TCG_TARGET_EXTEND_ARGS 1
1513
802ca56e
RH
1514#ifdef _CALL_AIX
1515# define LINK_AREA_SIZE (6 * SZR)
1516# define LR_OFFSET (1 * SZR)
1517# define TCG_TARGET_CALL_STACK_OFFSET (LINK_AREA_SIZE + 8 * SZR)
ffcfbece
RH
1518#elif TCG_TARGET_REG_BITS == 64
1519# if defined(_CALL_ELF) && _CALL_ELF == 2
1520# define LINK_AREA_SIZE (4 * SZR)
1521# define LR_OFFSET (1 * SZR)
1522# endif
1523#else /* TCG_TARGET_REG_BITS == 32 */
1524# if defined(_CALL_SYSV)
1525# define TCG_TARGET_CALL_ALIGN_ARGS 1
1526# define LINK_AREA_SIZE (2 * SZR)
1527# define LR_OFFSET (1 * SZR)
1528# elif defined(TCG_TARGET_CALL_DARWIN)
1529# define LINK_AREA_SIZE 24
1530# define LR_OFFSET 8
1531# endif
1532#endif
1533#ifndef LR_OFFSET
1534# error "Unhandled abi"
1535#endif
1536#ifndef TCG_TARGET_CALL_STACK_OFFSET
a2a98f80 1537# define TCG_TARGET_CALL_STACK_OFFSET LINK_AREA_SIZE
802ca56e
RH
1538#endif
1539
1540#define CPU_TEMP_BUF_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
1541#define REG_SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * SZR)
d604f1a9 1542
802ca56e
RH
1543#define FRAME_SIZE ((TCG_TARGET_CALL_STACK_OFFSET \
1544 + TCG_STATIC_CALL_ARGS_SIZE \
1545 + CPU_TEMP_BUF_SIZE \
1546 + REG_SAVE_SIZE \
1547 + TCG_TARGET_STACK_ALIGN - 1) \
1548 & -TCG_TARGET_STACK_ALIGN)
1549
1550#define REG_SAVE_BOT (FRAME_SIZE - REG_SAVE_SIZE)
d604f1a9
RH
1551
1552static void tcg_target_qemu_prologue(TCGContext *s)
810260a8 1553{
d604f1a9 1554 int i;
810260a8 1555
802ca56e
RH
1556 tcg_set_frame(s, TCG_REG_CALL_STACK, REG_SAVE_BOT - CPU_TEMP_BUF_SIZE,
1557 CPU_TEMP_BUF_SIZE);
d604f1a9 1558
802ca56e
RH
1559#ifdef _CALL_AIX
1560 {
1561 void **desc = (void **)s->code_ptr;
1562 desc[0] = desc + 2; /* entry point */
1563 desc[1] = 0; /* environment pointer */
1564 s->code_ptr = (void *)(desc + 2); /* skip over descriptor */
1565 }
d604f1a9
RH
1566#endif
1567
1568 /* Prologue */
1569 tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
ffcfbece
RH
1570 tcg_out32(s, (SZR == 8 ? STDU : STWU)
1571 | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
802ca56e 1572
d604f1a9 1573 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
4c3831a0
RH
1574 tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
1575 TCG_REG_R1, REG_SAVE_BOT + i * SZR);
d604f1a9 1576 }
802ca56e 1577 tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
d604f1a9
RH
1578
1579#ifdef CONFIG_USE_GUEST_BASE
1580 if (GUEST_BASE) {
1581 tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
1582 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
1583 }
1584#endif
1585
1586 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1587 tcg_out32(s, MTSPR | RS(tcg_target_call_iarg_regs[1]) | CTR);
1588 tcg_out32(s, BCCTR | BO_ALWAYS);
1589
1590 /* Epilogue */
1591 tb_ret_addr = s->code_ptr;
1592
802ca56e 1593 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
d604f1a9 1594 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
4c3831a0
RH
1595 tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
1596 TCG_REG_R1, REG_SAVE_BOT + i * SZR);
d604f1a9 1597 }
d604f1a9
RH
1598 tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
1599 tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
1600 tcg_out32(s, BCLR | BO_ALWAYS);
810260a8 1601}
1602
541dd4ce
RH
1603static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
1604 const int *const_args)
810260a8 1605{
ee924fa6 1606 TCGArg a0, a1, a2;
e46b9681 1607 int c;
1608
810260a8 1609 switch (opc) {
1610 case INDEX_op_exit_tb:
de3d636d 1611 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, args[0]);
e083c4a2 1612 tcg_out_b(s, 0, tb_ret_addr);
810260a8 1613 break;
1614 case INDEX_op_goto_tb:
1615 if (s->tb_jmp_offset) {
541dd4ce 1616 /* Direct jump method. */
e083c4a2
RH
1617 s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
1618 s->code_ptr += 7;
541dd4ce
RH
1619 } else {
1620 /* Indirect jump method. */
1621 tcg_abort();
810260a8 1622 }
e083c4a2 1623 s->tb_next_offset[args[0]] = tcg_current_code_size(s);
810260a8 1624 break;
1625 case INDEX_op_br:
1626 {
1627 TCGLabel *l = &s->labels[args[0]];
1628
1629 if (l->has_value) {
e083c4a2 1630 tcg_out_b(s, 0, l->u.value_ptr);
541dd4ce 1631 } else {
c7ca6a2b
RH
1632 tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, args[0], 0);
1633 tcg_out_b_noaddr(s, B);
810260a8 1634 }
1635 }
1636 break;
810260a8 1637 case INDEX_op_ld8u_i32:
1638 case INDEX_op_ld8u_i64:
b18d5d2b 1639 tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
810260a8 1640 break;
1641 case INDEX_op_ld8s_i32:
1642 case INDEX_op_ld8s_i64:
b18d5d2b 1643 tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
541dd4ce 1644 tcg_out32(s, EXTSB | RS(args[0]) | RA(args[0]));
810260a8 1645 break;
1646 case INDEX_op_ld16u_i32:
1647 case INDEX_op_ld16u_i64:
b18d5d2b 1648 tcg_out_mem_long(s, LHZ, LHZX, args[0], args[1], args[2]);
810260a8 1649 break;
1650 case INDEX_op_ld16s_i32:
1651 case INDEX_op_ld16s_i64:
b18d5d2b 1652 tcg_out_mem_long(s, LHA, LHAX, args[0], args[1], args[2]);
810260a8 1653 break;
1654 case INDEX_op_ld_i32:
1655 case INDEX_op_ld32u_i64:
b18d5d2b 1656 tcg_out_mem_long(s, LWZ, LWZX, args[0], args[1], args[2]);
810260a8 1657 break;
1658 case INDEX_op_ld32s_i64:
b18d5d2b 1659 tcg_out_mem_long(s, LWA, LWAX, args[0], args[1], args[2]);
810260a8 1660 break;
1661 case INDEX_op_ld_i64:
b18d5d2b 1662 tcg_out_mem_long(s, LD, LDX, args[0], args[1], args[2]);
810260a8 1663 break;
1664 case INDEX_op_st8_i32:
1665 case INDEX_op_st8_i64:
b18d5d2b 1666 tcg_out_mem_long(s, STB, STBX, args[0], args[1], args[2]);
810260a8 1667 break;
1668 case INDEX_op_st16_i32:
1669 case INDEX_op_st16_i64:
b18d5d2b 1670 tcg_out_mem_long(s, STH, STHX, args[0], args[1], args[2]);
810260a8 1671 break;
1672 case INDEX_op_st_i32:
1673 case INDEX_op_st32_i64:
b18d5d2b 1674 tcg_out_mem_long(s, STW, STWX, args[0], args[1], args[2]);
810260a8 1675 break;
1676 case INDEX_op_st_i64:
b18d5d2b 1677 tcg_out_mem_long(s, STD, STDX, args[0], args[1], args[2]);
810260a8 1678 break;
1679
1680 case INDEX_op_add_i32:
ee924fa6
RH
1681 a0 = args[0], a1 = args[1], a2 = args[2];
1682 if (const_args[2]) {
ee924fa6 1683 do_addi_32:
b18d5d2b 1684 tcg_out_mem_long(s, ADDI, ADD, a0, a1, (int32_t)a2);
ee924fa6
RH
1685 } else {
1686 tcg_out32(s, ADD | TAB(a0, a1, a2));
1687 }
810260a8 1688 break;
1689 case INDEX_op_sub_i32:
ee924fa6 1690 a0 = args[0], a1 = args[1], a2 = args[2];
148bdd23
RH
1691 if (const_args[1]) {
1692 if (const_args[2]) {
1693 tcg_out_movi(s, TCG_TYPE_I32, a0, a1 - a2);
1694 } else {
1695 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
1696 }
1697 } else if (const_args[2]) {
ee924fa6
RH
1698 a2 = -a2;
1699 goto do_addi_32;
1700 } else {
1701 tcg_out32(s, SUBF | TAB(a0, a2, a1));
1702 }
810260a8 1703 break;
1704
1705 case INDEX_op_and_i32:
37251b98 1706 a0 = args[0], a1 = args[1], a2 = args[2];
a9249dff 1707 if (const_args[2]) {
37251b98 1708 tcg_out_andi32(s, a0, a1, a2);
a9249dff 1709 } else {
37251b98 1710 tcg_out32(s, AND | SAB(a1, a0, a2));
a9249dff
RH
1711 }
1712 break;
1713 case INDEX_op_and_i64:
37251b98 1714 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 1715 if (const_args[2]) {
37251b98 1716 tcg_out_andi64(s, a0, a1, a2);
637af30c 1717 } else {
37251b98 1718 tcg_out32(s, AND | SAB(a1, a0, a2));
810260a8 1719 }
810260a8 1720 break;
fe6f943f 1721 case INDEX_op_or_i64:
810260a8 1722 case INDEX_op_or_i32:
dce74c57 1723 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 1724 if (const_args[2]) {
dce74c57
RH
1725 tcg_out_ori32(s, a0, a1, a2);
1726 } else {
1727 tcg_out32(s, OR | SAB(a1, a0, a2));
810260a8 1728 }
810260a8 1729 break;
fe6f943f 1730 case INDEX_op_xor_i64:
810260a8 1731 case INDEX_op_xor_i32:
dce74c57 1732 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 1733 if (const_args[2]) {
dce74c57
RH
1734 tcg_out_xori32(s, a0, a1, a2);
1735 } else {
1736 tcg_out32(s, XOR | SAB(a1, a0, a2));
810260a8 1737 }
810260a8 1738 break;
ce1010d6 1739 case INDEX_op_andc_i32:
37251b98
RH
1740 a0 = args[0], a1 = args[1], a2 = args[2];
1741 if (const_args[2]) {
1742 tcg_out_andi32(s, a0, a1, ~a2);
1743 } else {
1744 tcg_out32(s, ANDC | SAB(a1, a0, a2));
1745 }
1746 break;
ce1010d6 1747 case INDEX_op_andc_i64:
37251b98
RH
1748 a0 = args[0], a1 = args[1], a2 = args[2];
1749 if (const_args[2]) {
1750 tcg_out_andi64(s, a0, a1, ~a2);
1751 } else {
1752 tcg_out32(s, ANDC | SAB(a1, a0, a2));
1753 }
ce1010d6
RH
1754 break;
1755 case INDEX_op_orc_i32:
37251b98
RH
1756 if (const_args[2]) {
1757 tcg_out_ori32(s, args[0], args[1], ~args[2]);
1758 break;
1759 }
1760 /* FALLTHRU */
ce1010d6
RH
1761 case INDEX_op_orc_i64:
1762 tcg_out32(s, ORC | SAB(args[1], args[0], args[2]));
1763 break;
1764 case INDEX_op_eqv_i32:
37251b98
RH
1765 if (const_args[2]) {
1766 tcg_out_xori32(s, args[0], args[1], ~args[2]);
1767 break;
1768 }
1769 /* FALLTHRU */
ce1010d6
RH
1770 case INDEX_op_eqv_i64:
1771 tcg_out32(s, EQV | SAB(args[1], args[0], args[2]));
1772 break;
1773 case INDEX_op_nand_i32:
1774 case INDEX_op_nand_i64:
1775 tcg_out32(s, NAND | SAB(args[1], args[0], args[2]));
1776 break;
1777 case INDEX_op_nor_i32:
1778 case INDEX_op_nor_i64:
1779 tcg_out32(s, NOR | SAB(args[1], args[0], args[2]));
1780 break;
810260a8 1781
1782 case INDEX_op_mul_i32:
ef809300 1783 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 1784 if (const_args[2]) {
ef809300
RH
1785 tcg_out32(s, MULLI | TAI(a0, a1, a2));
1786 } else {
1787 tcg_out32(s, MULLW | TAB(a0, a1, a2));
810260a8 1788 }
810260a8 1789 break;
1790
1791 case INDEX_op_div_i32:
541dd4ce 1792 tcg_out32(s, DIVW | TAB(args[0], args[1], args[2]));
810260a8 1793 break;
1794
1795 case INDEX_op_divu_i32:
541dd4ce 1796 tcg_out32(s, DIVWU | TAB(args[0], args[1], args[2]));
810260a8 1797 break;
1798
810260a8 1799 case INDEX_op_shl_i32:
1800 if (const_args[2]) {
9e555b73
RH
1801 tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
1802 } else {
541dd4ce 1803 tcg_out32(s, SLW | SAB(args[1], args[0], args[2]));
9e555b73 1804 }
810260a8 1805 break;
1806 case INDEX_op_shr_i32:
1807 if (const_args[2]) {
9e555b73
RH
1808 tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], args[2], 31);
1809 } else {
541dd4ce 1810 tcg_out32(s, SRW | SAB(args[1], args[0], args[2]));
9e555b73 1811 }
810260a8 1812 break;
1813 case INDEX_op_sar_i32:
541dd4ce
RH
1814 if (const_args[2]) {
1815 tcg_out32(s, SRAWI | RS(args[1]) | RA(args[0]) | SH(args[2]));
1816 } else {
1817 tcg_out32(s, SRAW | SAB(args[1], args[0], args[2]));
1818 }
810260a8 1819 break;
313d91c7
RH
1820 case INDEX_op_rotl_i32:
1821 if (const_args[2]) {
1822 tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31);
1823 } else {
1824 tcg_out32(s, RLWNM | SAB(args[1], args[0], args[2])
1825 | MB(0) | ME(31));
1826 }
1827 break;
1828 case INDEX_op_rotr_i32:
1829 if (const_args[2]) {
1830 tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], 0, 31);
1831 } else {
8327a470
RH
1832 tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 32));
1833 tcg_out32(s, RLWNM | SAB(args[1], args[0], TCG_REG_R0)
313d91c7
RH
1834 | MB(0) | ME(31));
1835 }
1836 break;
810260a8 1837
1838 case INDEX_op_brcond_i32:
4c314da6
RH
1839 tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1840 args[3], TCG_TYPE_I32);
e924bbec 1841 break;
810260a8 1842 case INDEX_op_brcond_i64:
4c314da6
RH
1843 tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1844 args[3], TCG_TYPE_I64);
810260a8 1845 break;
abcf61c4
RH
1846 case INDEX_op_brcond2_i32:
1847 tcg_out_brcond2(s, args, const_args);
1848 break;
810260a8 1849
1850 case INDEX_op_neg_i32:
810260a8 1851 case INDEX_op_neg_i64:
541dd4ce 1852 tcg_out32(s, NEG | RT(args[0]) | RA(args[1]));
810260a8 1853 break;
1854
157f2662 1855 case INDEX_op_not_i32:
1856 case INDEX_op_not_i64:
541dd4ce 1857 tcg_out32(s, NOR | SAB(args[1], args[0], args[1]));
157f2662 1858 break;
1859
810260a8 1860 case INDEX_op_add_i64:
ee924fa6
RH
1861 a0 = args[0], a1 = args[1], a2 = args[2];
1862 if (const_args[2]) {
ee924fa6 1863 do_addi_64:
b18d5d2b 1864 tcg_out_mem_long(s, ADDI, ADD, a0, a1, a2);
ee924fa6
RH
1865 } else {
1866 tcg_out32(s, ADD | TAB(a0, a1, a2));
1867 }
810260a8 1868 break;
1869 case INDEX_op_sub_i64:
ee924fa6 1870 a0 = args[0], a1 = args[1], a2 = args[2];
148bdd23
RH
1871 if (const_args[1]) {
1872 if (const_args[2]) {
1873 tcg_out_movi(s, TCG_TYPE_I64, a0, a1 - a2);
1874 } else {
1875 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
1876 }
1877 } else if (const_args[2]) {
ee924fa6
RH
1878 a2 = -a2;
1879 goto do_addi_64;
1880 } else {
1881 tcg_out32(s, SUBF | TAB(a0, a2, a1));
1882 }
810260a8 1883 break;
1884
1885 case INDEX_op_shl_i64:
541dd4ce 1886 if (const_args[2]) {
0a9564b9 1887 tcg_out_shli64(s, args[0], args[1], args[2]);
541dd4ce
RH
1888 } else {
1889 tcg_out32(s, SLD | SAB(args[1], args[0], args[2]));
1890 }
810260a8 1891 break;
1892 case INDEX_op_shr_i64:
541dd4ce 1893 if (const_args[2]) {
5e916c28 1894 tcg_out_shri64(s, args[0], args[1], args[2]);
541dd4ce
RH
1895 } else {
1896 tcg_out32(s, SRD | SAB(args[1], args[0], args[2]));
1897 }
810260a8 1898 break;
1899 case INDEX_op_sar_i64:
fe6f943f 1900 if (const_args[2]) {
541dd4ce
RH
1901 int sh = SH(args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
1902 tcg_out32(s, SRADI | RA(args[0]) | RS(args[1]) | sh);
1903 } else {
1904 tcg_out32(s, SRAD | SAB(args[1], args[0], args[2]));
fe6f943f 1905 }
810260a8 1906 break;
313d91c7
RH
1907 case INDEX_op_rotl_i64:
1908 if (const_args[2]) {
1909 tcg_out_rld(s, RLDICL, args[0], args[1], args[2], 0);
1910 } else {
1911 tcg_out32(s, RLDCL | SAB(args[1], args[0], args[2]) | MB64(0));
1912 }
1913 break;
1914 case INDEX_op_rotr_i64:
1915 if (const_args[2]) {
1916 tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 0);
1917 } else {
8327a470
RH
1918 tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 64));
1919 tcg_out32(s, RLDCL | SAB(args[1], args[0], TCG_REG_R0) | MB64(0));
313d91c7
RH
1920 }
1921 break;
810260a8 1922
1923 case INDEX_op_mul_i64:
ef809300
RH
1924 a0 = args[0], a1 = args[1], a2 = args[2];
1925 if (const_args[2]) {
1926 tcg_out32(s, MULLI | TAI(a0, a1, a2));
1927 } else {
1928 tcg_out32(s, MULLD | TAB(a0, a1, a2));
1929 }
810260a8 1930 break;
1931 case INDEX_op_div_i64:
541dd4ce 1932 tcg_out32(s, DIVD | TAB(args[0], args[1], args[2]));
810260a8 1933 break;
1934 case INDEX_op_divu_i64:
541dd4ce 1935 tcg_out32(s, DIVDU | TAB(args[0], args[1], args[2]));
810260a8 1936 break;
810260a8 1937
1768ec06
RH
1938 case INDEX_op_qemu_ld_i32:
1939 case INDEX_op_qemu_ld_i64:
1940 tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3]);
810260a8 1941 break;
1768ec06
RH
1942 case INDEX_op_qemu_st_i32:
1943 case INDEX_op_qemu_st_i64:
1944 tcg_out_qemu_st(s, args[0], args[1], args[2], args[3]);
810260a8 1945 break;
1946
e46b9681 1947 case INDEX_op_ext8s_i32:
1948 case INDEX_op_ext8s_i64:
1949 c = EXTSB;
1950 goto gen_ext;
1951 case INDEX_op_ext16s_i32:
1952 case INDEX_op_ext16s_i64:
1953 c = EXTSH;
1954 goto gen_ext;
1955 case INDEX_op_ext32s_i64:
1956 c = EXTSW;
1957 goto gen_ext;
1958 gen_ext:
541dd4ce 1959 tcg_out32(s, c | RS(args[1]) | RA(args[0]));
e46b9681 1960 break;
1961
1cd62ae9 1962 case INDEX_op_setcond_i32:
541dd4ce
RH
1963 tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
1964 const_args[2]);
1cd62ae9 1965 break;
1966 case INDEX_op_setcond_i64:
541dd4ce
RH
1967 tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
1968 const_args[2]);
1cd62ae9 1969 break;
abcf61c4
RH
1970 case INDEX_op_setcond2_i32:
1971 tcg_out_setcond2(s, args, const_args);
1972 break;
1cd62ae9 1973
5d221582
RH
1974 case INDEX_op_bswap16_i32:
1975 case INDEX_op_bswap16_i64:
1976 a0 = args[0], a1 = args[1];
1977 /* a1 = abcd */
1978 if (a0 != a1) {
1979 /* a0 = (a1 r<< 24) & 0xff # 000c */
1980 tcg_out_rlw(s, RLWINM, a0, a1, 24, 24, 31);
1981 /* a0 = (a0 & ~0xff00) | (a1 r<< 8) & 0xff00 # 00dc */
1982 tcg_out_rlw(s, RLWIMI, a0, a1, 8, 16, 23);
1983 } else {
1984 /* r0 = (a1 r<< 8) & 0xff00 # 00d0 */
1985 tcg_out_rlw(s, RLWINM, TCG_REG_R0, a1, 8, 16, 23);
1986 /* a0 = (a1 r<< 24) & 0xff # 000c */
1987 tcg_out_rlw(s, RLWINM, a0, a1, 24, 24, 31);
1988 /* a0 = a0 | r0 # 00dc */
1989 tcg_out32(s, OR | SAB(TCG_REG_R0, a0, a0));
1990 }
1991 break;
1992
1993 case INDEX_op_bswap32_i32:
1994 case INDEX_op_bswap32_i64:
1995 /* Stolen from gcc's builtin_bswap32 */
1996 a1 = args[1];
1997 a0 = args[0] == a1 ? TCG_REG_R0 : args[0];
1998
1999 /* a1 = args[1] # abcd */
2000 /* a0 = rotate_left (a1, 8) # bcda */
2001 tcg_out_rlw(s, RLWINM, a0, a1, 8, 0, 31);
2002 /* a0 = (a0 & ~0xff000000) | ((a1 r<< 24) & 0xff000000) # dcda */
2003 tcg_out_rlw(s, RLWIMI, a0, a1, 24, 0, 7);
2004 /* a0 = (a0 & ~0x0000ff00) | ((a1 r<< 24) & 0x0000ff00) # dcba */
2005 tcg_out_rlw(s, RLWIMI, a0, a1, 24, 16, 23);
2006
2007 if (a0 == TCG_REG_R0) {
de3d636d 2008 tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
5d221582
RH
2009 }
2010 break;
2011
68aebd45 2012 case INDEX_op_bswap64_i64:
8327a470 2013 a0 = args[0], a1 = args[1], a2 = TCG_REG_R0;
68aebd45 2014 if (a0 == a1) {
8327a470 2015 a0 = TCG_REG_R0;
68aebd45
RH
2016 a2 = a1;
2017 }
2018
2019 /* a1 = # abcd efgh */
2020 /* a0 = rl32(a1, 8) # 0000 fghe */
2021 tcg_out_rlw(s, RLWINM, a0, a1, 8, 0, 31);
2022 /* a0 = dep(a0, rl32(a1, 24), 0xff000000) # 0000 hghe */
2023 tcg_out_rlw(s, RLWIMI, a0, a1, 24, 0, 7);
2024 /* a0 = dep(a0, rl32(a1, 24), 0x0000ff00) # 0000 hgfe */
2025 tcg_out_rlw(s, RLWIMI, a0, a1, 24, 16, 23);
2026
2027 /* a0 = rl64(a0, 32) # hgfe 0000 */
2028 /* a2 = rl64(a1, 32) # efgh abcd */
2029 tcg_out_rld(s, RLDICL, a0, a0, 32, 0);
2030 tcg_out_rld(s, RLDICL, a2, a1, 32, 0);
2031
2032 /* a0 = dep(a0, rl32(a2, 8), 0xffffffff) # hgfe bcda */
2033 tcg_out_rlw(s, RLWIMI, a0, a2, 8, 0, 31);
2034 /* a0 = dep(a0, rl32(a2, 24), 0xff000000) # hgfe dcda */
2035 tcg_out_rlw(s, RLWIMI, a0, a2, 24, 0, 7);
2036 /* a0 = dep(a0, rl32(a2, 24), 0x0000ff00) # hgfe dcba */
2037 tcg_out_rlw(s, RLWIMI, a0, a2, 24, 16, 23);
2038
2039 if (a0 == 0) {
de3d636d 2040 tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
68aebd45
RH
2041 }
2042 break;
2043
33de9ed2 2044 case INDEX_op_deposit_i32:
39dc85b9
RH
2045 if (const_args[2]) {
2046 uint32_t mask = ((2u << (args[4] - 1)) - 1) << args[3];
2047 tcg_out_andi32(s, args[0], args[0], ~mask);
2048 } else {
2049 tcg_out_rlw(s, RLWIMI, args[0], args[2], args[3],
2050 32 - args[3] - args[4], 31 - args[3]);
2051 }
33de9ed2
RH
2052 break;
2053 case INDEX_op_deposit_i64:
39dc85b9
RH
2054 if (const_args[2]) {
2055 uint64_t mask = ((2ull << (args[4] - 1)) - 1) << args[3];
2056 tcg_out_andi64(s, args[0], args[0], ~mask);
2057 } else {
2058 tcg_out_rld(s, RLDIMI, args[0], args[2], args[3],
2059 64 - args[3] - args[4]);
2060 }
33de9ed2
RH
2061 break;
2062
027ffea9
RH
2063 case INDEX_op_movcond_i32:
2064 tcg_out_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1], args[2],
2065 args[3], args[4], const_args[2]);
2066 break;
2067 case INDEX_op_movcond_i64:
2068 tcg_out_movcond(s, TCG_TYPE_I64, args[5], args[0], args[1], args[2],
2069 args[3], args[4], const_args[2]);
2070 break;
2071
796f1a68 2072#if TCG_TARGET_REG_BITS == 64
6c858762 2073 case INDEX_op_add2_i64:
796f1a68
RH
2074#else
2075 case INDEX_op_add2_i32:
2076#endif
6c858762
RH
2077 /* Note that the CA bit is defined based on the word size of the
2078 environment. So in 64-bit mode it's always carry-out of bit 63.
2079 The fallback code using deposit works just as well for 32-bit. */
2080 a0 = args[0], a1 = args[1];
84247357 2081 if (a0 == args[3] || (!const_args[5] && a0 == args[5])) {
6c858762
RH
2082 a0 = TCG_REG_R0;
2083 }
84247357
AB
2084 if (const_args[4]) {
2085 tcg_out32(s, ADDIC | TAI(a0, args[2], args[4]));
6c858762 2086 } else {
84247357 2087 tcg_out32(s, ADDC | TAB(a0, args[2], args[4]));
6c858762
RH
2088 }
2089 if (const_args[5]) {
84247357 2090 tcg_out32(s, (args[5] ? ADDME : ADDZE) | RT(a1) | RA(args[3]));
6c858762 2091 } else {
84247357 2092 tcg_out32(s, ADDE | TAB(a1, args[3], args[5]));
6c858762
RH
2093 }
2094 if (a0 != args[0]) {
de3d636d 2095 tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
6c858762
RH
2096 }
2097 break;
2098
796f1a68 2099#if TCG_TARGET_REG_BITS == 64
6c858762 2100 case INDEX_op_sub2_i64:
796f1a68
RH
2101#else
2102 case INDEX_op_sub2_i32:
2103#endif
6c858762 2104 a0 = args[0], a1 = args[1];
b31284ce 2105 if (a0 == args[5] || (!const_args[3] && a0 == args[3])) {
6c858762
RH
2106 a0 = TCG_REG_R0;
2107 }
2108 if (const_args[2]) {
b31284ce 2109 tcg_out32(s, SUBFIC | TAI(a0, args[4], args[2]));
6c858762 2110 } else {
b31284ce 2111 tcg_out32(s, SUBFC | TAB(a0, args[4], args[2]));
6c858762 2112 }
b31284ce
RH
2113 if (const_args[3]) {
2114 tcg_out32(s, (args[3] ? SUBFME : SUBFZE) | RT(a1) | RA(args[5]));
6c858762 2115 } else {
b31284ce 2116 tcg_out32(s, SUBFE | TAB(a1, args[5], args[3]));
6c858762
RH
2117 }
2118 if (a0 != args[0]) {
de3d636d 2119 tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
6c858762
RH
2120 }
2121 break;
2122
abcf61c4
RH
2123 case INDEX_op_muluh_i32:
2124 tcg_out32(s, MULHWU | TAB(args[0], args[1], args[2]));
2125 break;
32f5717f
RH
2126 case INDEX_op_muluh_i64:
2127 tcg_out32(s, MULHDU | TAB(args[0], args[1], args[2]));
2128 break;
2129 case INDEX_op_mulsh_i64:
2130 tcg_out32(s, MULHD | TAB(args[0], args[1], args[2]));
6645c147
RH
2131 break;
2132
96d0ee7f
RH
2133 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
2134 case INDEX_op_mov_i64:
2135 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
2136 case INDEX_op_movi_i64:
2137 case INDEX_op_call: /* Always emitted via tcg_out_call. */
810260a8 2138 default:
541dd4ce 2139 tcg_abort();
810260a8 2140 }
2141}
2142
2143static const TCGTargetOpDef ppc_op_defs[] = {
2144 { INDEX_op_exit_tb, { } },
2145 { INDEX_op_goto_tb, { } },
810260a8 2146 { INDEX_op_br, { } },
2147
810260a8 2148 { INDEX_op_ld8u_i32, { "r", "r" } },
2149 { INDEX_op_ld8s_i32, { "r", "r" } },
2150 { INDEX_op_ld16u_i32, { "r", "r" } },
2151 { INDEX_op_ld16s_i32, { "r", "r" } },
2152 { INDEX_op_ld_i32, { "r", "r" } },
796f1a68 2153
810260a8 2154 { INDEX_op_st8_i32, { "r", "r" } },
810260a8 2155 { INDEX_op_st16_i32, { "r", "r" } },
810260a8 2156 { INDEX_op_st_i32, { "r", "r" } },
810260a8 2157
2158 { INDEX_op_add_i32, { "r", "r", "ri" } },
ef809300 2159 { INDEX_op_mul_i32, { "r", "r", "rI" } },
810260a8 2160 { INDEX_op_div_i32, { "r", "r", "r" } },
2161 { INDEX_op_divu_i32, { "r", "r", "r" } },
148bdd23 2162 { INDEX_op_sub_i32, { "r", "rI", "ri" } },
810260a8 2163 { INDEX_op_and_i32, { "r", "r", "ri" } },
2164 { INDEX_op_or_i32, { "r", "r", "ri" } },
2165 { INDEX_op_xor_i32, { "r", "r", "ri" } },
37251b98
RH
2166 { INDEX_op_andc_i32, { "r", "r", "ri" } },
2167 { INDEX_op_orc_i32, { "r", "r", "ri" } },
2168 { INDEX_op_eqv_i32, { "r", "r", "ri" } },
ce1010d6
RH
2169 { INDEX_op_nand_i32, { "r", "r", "r" } },
2170 { INDEX_op_nor_i32, { "r", "r", "r" } },
810260a8 2171
2172 { INDEX_op_shl_i32, { "r", "r", "ri" } },
2173 { INDEX_op_shr_i32, { "r", "r", "ri" } },
2174 { INDEX_op_sar_i32, { "r", "r", "ri" } },
313d91c7
RH
2175 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
2176 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
810260a8 2177
810260a8 2178 { INDEX_op_neg_i32, { "r", "r" } },
157f2662 2179 { INDEX_op_not_i32, { "r", "r" } },
796f1a68
RH
2180 { INDEX_op_ext8s_i32, { "r", "r" } },
2181 { INDEX_op_ext16s_i32, { "r", "r" } },
2182 { INDEX_op_bswap16_i32, { "r", "r" } },
2183 { INDEX_op_bswap32_i32, { "r", "r" } },
2184
2185 { INDEX_op_brcond_i32, { "r", "ri" } },
2186 { INDEX_op_setcond_i32, { "r", "r", "ri" } },
2187 { INDEX_op_movcond_i32, { "r", "r", "ri", "rZ", "rZ" } },
2188
2189 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
2190
abcf61c4
RH
2191 { INDEX_op_muluh_i32, { "r", "r", "r" } },
2192
796f1a68
RH
2193#if TCG_TARGET_REG_BITS == 64
2194 { INDEX_op_ld8u_i64, { "r", "r" } },
2195 { INDEX_op_ld8s_i64, { "r", "r" } },
2196 { INDEX_op_ld16u_i64, { "r", "r" } },
2197 { INDEX_op_ld16s_i64, { "r", "r" } },
2198 { INDEX_op_ld32u_i64, { "r", "r" } },
2199 { INDEX_op_ld32s_i64, { "r", "r" } },
2200 { INDEX_op_ld_i64, { "r", "r" } },
2201
2202 { INDEX_op_st8_i64, { "r", "r" } },
2203 { INDEX_op_st16_i64, { "r", "r" } },
2204 { INDEX_op_st32_i64, { "r", "r" } },
2205 { INDEX_op_st_i64, { "r", "r" } },
810260a8 2206
ee924fa6 2207 { INDEX_op_add_i64, { "r", "r", "rT" } },
148bdd23 2208 { INDEX_op_sub_i64, { "r", "rI", "rT" } },
37251b98 2209 { INDEX_op_and_i64, { "r", "r", "ri" } },
3d582c61
RH
2210 { INDEX_op_or_i64, { "r", "r", "rU" } },
2211 { INDEX_op_xor_i64, { "r", "r", "rU" } },
37251b98 2212 { INDEX_op_andc_i64, { "r", "r", "ri" } },
ce1010d6
RH
2213 { INDEX_op_orc_i64, { "r", "r", "r" } },
2214 { INDEX_op_eqv_i64, { "r", "r", "r" } },
2215 { INDEX_op_nand_i64, { "r", "r", "r" } },
2216 { INDEX_op_nor_i64, { "r", "r", "r" } },
810260a8 2217
fe6f943f 2218 { INDEX_op_shl_i64, { "r", "r", "ri" } },
2219 { INDEX_op_shr_i64, { "r", "r", "ri" } },
2220 { INDEX_op_sar_i64, { "r", "r", "ri" } },
313d91c7
RH
2221 { INDEX_op_rotl_i64, { "r", "r", "ri" } },
2222 { INDEX_op_rotr_i64, { "r", "r", "ri" } },
810260a8 2223
ef809300 2224 { INDEX_op_mul_i64, { "r", "r", "rI" } },
810260a8 2225 { INDEX_op_div_i64, { "r", "r", "r" } },
2226 { INDEX_op_divu_i64, { "r", "r", "r" } },
810260a8 2227
2228 { INDEX_op_neg_i64, { "r", "r" } },
157f2662 2229 { INDEX_op_not_i64, { "r", "r" } },
e46b9681 2230 { INDEX_op_ext8s_i64, { "r", "r" } },
2231 { INDEX_op_ext16s_i64, { "r", "r" } },
2232 { INDEX_op_ext32s_i64, { "r", "r" } },
5d221582 2233 { INDEX_op_bswap16_i64, { "r", "r" } },
5d221582 2234 { INDEX_op_bswap32_i64, { "r", "r" } },
68aebd45 2235 { INDEX_op_bswap64_i64, { "r", "r" } },
5d221582 2236
796f1a68
RH
2237 { INDEX_op_brcond_i64, { "r", "ri" } },
2238 { INDEX_op_setcond_i64, { "r", "r", "ri" } },
2239 { INDEX_op_movcond_i64, { "r", "r", "ri", "rZ", "rZ" } },
2240
39dc85b9 2241 { INDEX_op_deposit_i64, { "r", "0", "rZ" } },
33de9ed2 2242
32f5717f
RH
2243 { INDEX_op_mulsh_i64, { "r", "r", "r" } },
2244 { INDEX_op_muluh_i64, { "r", "r", "r" } },
796f1a68
RH
2245#endif
2246
abcf61c4
RH
2247#if TCG_TARGET_REG_BITS == 32
2248 { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
2249 { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
2250#endif
2251
796f1a68
RH
2252#if TCG_TARGET_REG_BITS == 64
2253 { INDEX_op_add2_i64, { "r", "r", "r", "r", "rI", "rZM" } },
2254 { INDEX_op_sub2_i64, { "r", "r", "rI", "rZM", "r", "r" } },
2255#else
2256 { INDEX_op_add2_i32, { "r", "r", "r", "r", "rI", "rZM" } },
2257 { INDEX_op_sub2_i32, { "r", "r", "rI", "rZM", "r", "r" } },
2258#endif
2259
2260#if TCG_TARGET_REG_BITS == 64
2261 { INDEX_op_qemu_ld_i32, { "r", "L" } },
2262 { INDEX_op_qemu_st_i32, { "S", "S" } },
2263 { INDEX_op_qemu_ld_i64, { "r", "L" } },
2264 { INDEX_op_qemu_st_i64, { "S", "S" } },
2265#elif TARGET_LONG_BITS == 32
2266 { INDEX_op_qemu_ld_i32, { "r", "L" } },
2267 { INDEX_op_qemu_st_i32, { "S", "S" } },
2268 { INDEX_op_qemu_ld_i64, { "r", "r", "L" } },
2269 { INDEX_op_qemu_st_i64, { "S", "S", "S" } },
2270#else
2271 { INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
2272 { INDEX_op_qemu_st_i32, { "S", "S", "S" } },
2273 { INDEX_op_qemu_ld_i64, { "r", "r", "L", "L" } },
2274 { INDEX_op_qemu_st_i64, { "S", "S", "S", "S" } },
2275#endif
6c858762 2276
810260a8 2277 { -1 },
2278};
2279
541dd4ce 2280static void tcg_target_init(TCGContext *s)
810260a8 2281{
cd629de1 2282 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
1e6e9aca
RH
2283 if (hwcap & PPC_FEATURE_ARCH_2_06) {
2284 have_isa_2_06 = true;
2285 }
1e6e9aca 2286
541dd4ce
RH
2287 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
2288 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
2289 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
810260a8 2290 (1 << TCG_REG_R0) |
5d7ff5bb 2291 (1 << TCG_REG_R2) |
810260a8 2292 (1 << TCG_REG_R3) |
2293 (1 << TCG_REG_R4) |
2294 (1 << TCG_REG_R5) |
2295 (1 << TCG_REG_R6) |
2296 (1 << TCG_REG_R7) |
2297 (1 << TCG_REG_R8) |
2298 (1 << TCG_REG_R9) |
2299 (1 << TCG_REG_R10) |
2300 (1 << TCG_REG_R11) |
5e1702b0 2301 (1 << TCG_REG_R12));
810260a8 2302
541dd4ce 2303 tcg_regset_clear(s->reserved_regs);
5e1702b0
RH
2304 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* tcg temp */
2305 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* stack pointer */
b18d5d2b 2306 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* mem temp */
5e1702b0
RH
2307#ifdef __APPLE__
2308 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R11); /* ??? */
5d7ff5bb 2309#endif
5e1702b0 2310 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
810260a8 2311
541dd4ce 2312 tcg_add_target_add_op_defs(ppc_op_defs);
810260a8 2313}
fa94c3be 2314
ffcfbece 2315#ifdef __ELF__
fa94c3be
RH
2316typedef struct {
2317 DebugFrameCIE cie;
2318 DebugFrameFDEHeader fde;
2319 uint8_t fde_def_cfa[4];
2320 uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2 + 3];
2321} DebugFrame;
2322
2323/* We're expecting a 2 byte uleb128 encoded value. */
2324QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
2325
ffcfbece
RH
2326#if TCG_TARGET_REG_BITS == 64
2327# define ELF_HOST_MACHINE EM_PPC64
2328#else
2329# define ELF_HOST_MACHINE EM_PPC
2330#endif
fa94c3be
RH
2331
2332static DebugFrame debug_frame = {
2333 .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
2334 .cie.id = -1,
2335 .cie.version = 1,
2336 .cie.code_align = 1,
802ca56e 2337 .cie.data_align = (-SZR & 0x7f), /* sleb128 -SZR */
fa94c3be
RH
2338 .cie.return_column = 65,
2339
2340 /* Total FDE size does not include the "len" member. */
2341 .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
2342
2343 .fde_def_cfa = {
802ca56e 2344 12, TCG_REG_R1, /* DW_CFA_def_cfa r1, ... */
fa94c3be
RH
2345 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2346 (FRAME_SIZE >> 7)
2347 },
2348 .fde_reg_ofs = {
802ca56e
RH
2349 /* DW_CFA_offset_extended_sf, lr, LR_OFFSET */
2350 0x11, 65, (LR_OFFSET / -SZR) & 0x7f,
fa94c3be
RH
2351 }
2352};
2353
2354void tcg_register_jit(void *buf, size_t buf_size)
2355{
2356 uint8_t *p = &debug_frame.fde_reg_ofs[3];
2357 int i;
2358
2359 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i, p += 2) {
2360 p[0] = 0x80 + tcg_target_callee_save_regs[i];
802ca56e 2361 p[1] = (FRAME_SIZE - (REG_SAVE_BOT + i * SZR)) / SZR;
fa94c3be
RH
2362 }
2363
802ca56e 2364 debug_frame.fde.func_start = (uintptr_t)buf;
fa94c3be
RH
2365 debug_frame.fde.func_len = buf_size;
2366
2367 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2368}
ffcfbece 2369#endif /* __ELF__ */