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