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