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