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