]> git.proxmox.com Git - qemu.git/blame - tcg/ppc64/tcg-target.c
tcg-ppc64: Improve and_i32 with constant
[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
fe6f943f 30
810260a8 31static uint8_t *tb_ret_addr;
32
33#define FAST_PATH
34
810260a8 35#if TARGET_LONG_BITS == 32
36#define LD_ADDR LWZU
e924bbec 37#define CMP_L 0
810260a8 38#else
39#define LD_ADDR LDU
e924bbec 40#define CMP_L (1<<21)
810260a8 41#endif
42
f6548c0a 43#ifndef GUEST_BASE
44#define GUEST_BASE 0
45#endif
46
47#ifdef CONFIG_USE_GUEST_BASE
48#define TCG_GUEST_BASE_REG 30
49#else
50#define TCG_GUEST_BASE_REG 0
51#endif
52
d4a9eb1f 53#ifndef NDEBUG
810260a8 54static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
55 "r0",
56 "r1",
98926b0a 57 "r2",
810260a8 58 "r3",
59 "r4",
60 "r5",
61 "r6",
62 "r7",
63 "r8",
64 "r9",
65 "r10",
66 "r11",
67 "r12",
68 "r13",
69 "r14",
70 "r15",
71 "r16",
72 "r17",
73 "r18",
74 "r19",
75 "r20",
76 "r21",
77 "r22",
78 "r23",
79 "r24",
80 "r25",
81 "r26",
82 "r27",
83 "r28",
84 "r29",
85 "r30",
86 "r31"
87};
d4a9eb1f 88#endif
810260a8 89
90static const int tcg_target_reg_alloc_order[] = {
91 TCG_REG_R14,
92 TCG_REG_R15,
93 TCG_REG_R16,
94 TCG_REG_R17,
95 TCG_REG_R18,
96 TCG_REG_R19,
97 TCG_REG_R20,
98 TCG_REG_R21,
99 TCG_REG_R22,
100 TCG_REG_R23,
101 TCG_REG_R28,
102 TCG_REG_R29,
103 TCG_REG_R30,
104 TCG_REG_R31,
5d7ff5bb
AF
105#ifdef __APPLE__
106 TCG_REG_R2,
107#endif
810260a8 108 TCG_REG_R3,
109 TCG_REG_R4,
110 TCG_REG_R5,
111 TCG_REG_R6,
112 TCG_REG_R7,
113 TCG_REG_R8,
114 TCG_REG_R9,
115 TCG_REG_R10,
5d7ff5bb 116#ifndef __APPLE__
810260a8 117 TCG_REG_R11,
5d7ff5bb 118#endif
810260a8 119 TCG_REG_R12,
810260a8 120 TCG_REG_R24,
121 TCG_REG_R25,
122 TCG_REG_R26,
123 TCG_REG_R27
124};
125
126static const int tcg_target_call_iarg_regs[] = {
127 TCG_REG_R3,
128 TCG_REG_R4,
129 TCG_REG_R5,
130 TCG_REG_R6,
131 TCG_REG_R7,
132 TCG_REG_R8,
133 TCG_REG_R9,
134 TCG_REG_R10
135};
136
be9c4183 137static const int tcg_target_call_oarg_regs[] = {
810260a8 138 TCG_REG_R3
139};
140
141static const int tcg_target_callee_save_regs[] = {
5d7ff5bb
AF
142#ifdef __APPLE__
143 TCG_REG_R11,
144#endif
810260a8 145 TCG_REG_R14,
146 TCG_REG_R15,
147 TCG_REG_R16,
148 TCG_REG_R17,
149 TCG_REG_R18,
150 TCG_REG_R19,
151 TCG_REG_R20,
152 TCG_REG_R21,
153 TCG_REG_R22,
154 TCG_REG_R23,
095271d4 155 TCG_REG_R24,
156 TCG_REG_R25,
157 TCG_REG_R26,
cea5f9a2 158 TCG_REG_R27, /* currently used for the global env */
810260a8 159 TCG_REG_R28,
160 TCG_REG_R29,
161 TCG_REG_R30,
162 TCG_REG_R31
163};
164
165static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
166{
167 tcg_target_long disp;
168
169 disp = target - (tcg_target_long) pc;
170 if ((disp << 38) >> 38 != disp)
171 tcg_abort ();
172
173 return disp & 0x3fffffc;
174}
175
176static void reloc_pc24 (void *pc, tcg_target_long target)
177{
178 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
179 | reloc_pc24_val (pc, target);
180}
181
182static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
183{
184 tcg_target_long disp;
185
186 disp = target - (tcg_target_long) pc;
187 if (disp != (int16_t) disp)
188 tcg_abort ();
189
190 return disp & 0xfffc;
191}
192
193static void reloc_pc14 (void *pc, tcg_target_long target)
194{
195 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
196 | reloc_pc14_val (pc, target);
197}
198
199static void patch_reloc (uint8_t *code_ptr, int type,
200 tcg_target_long value, tcg_target_long addend)
201{
202 value += addend;
203 switch (type) {
204 case R_PPC_REL14:
205 reloc_pc14 (code_ptr, value);
206 break;
207 case R_PPC_REL24:
208 reloc_pc24 (code_ptr, value);
209 break;
210 default:
211 tcg_abort ();
212 }
213}
214
810260a8 215/* parse target specific constraints */
216static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str)
217{
218 const char *ct_str;
219
220 ct_str = *pct_str;
221 switch (ct_str[0]) {
222 case 'A': case 'B': case 'C': case 'D':
223 ct->ct |= TCG_CT_REG;
224 tcg_regset_set_reg (ct->u.regs, 3 + ct_str[0] - 'A');
225 break;
226 case 'r':
227 ct->ct |= TCG_CT_REG;
228 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
229 break;
230 case 'L': /* qemu_ld constraint */
231 ct->ct |= TCG_CT_REG;
232 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
233 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
735ee40d 234#ifdef CONFIG_SOFTMMU
810260a8 235 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
f4f7d01a 236 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5);
735ee40d 237#endif
810260a8 238 break;
c070355d 239 case 'S': /* qemu_st constraint */
810260a8 240 ct->ct |= TCG_CT_REG;
241 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
242 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
735ee40d 243#ifdef CONFIG_SOFTMMU
810260a8 244 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
245 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5);
f4f7d01a 246 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R6);
735ee40d 247#endif
810260a8 248 break;
3d582c61
RH
249 case 'I':
250 ct->ct |= TCG_CT_CONST_S16;
251 break;
252 case 'J':
253 ct->ct |= TCG_CT_CONST_U16;
254 break;
255 case 'T':
256 ct->ct |= TCG_CT_CONST_S32;
257 break;
258 case 'U':
fe6f943f 259 ct->ct |= TCG_CT_CONST_U32;
260 break;
3d582c61
RH
261 case 'Z':
262 ct->ct |= TCG_CT_CONST_ZERO;
263 break;
810260a8 264 default:
265 return -1;
266 }
267 ct_str++;
268 *pct_str = ct_str;
269 return 0;
270}
271
272/* test if a constant matches the constraint */
273static int tcg_target_const_match (tcg_target_long val,
274 const TCGArgConstraint *arg_ct)
275{
3d582c61
RH
276 int ct = arg_ct->ct;
277 if (ct & TCG_CT_CONST) {
278 return 1;
279 } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
280 return 1;
281 } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
810260a8 282 return 1;
3d582c61 283 } else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
fe6f943f 284 return 1;
3d582c61
RH
285 } else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
286 return 1;
287 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
288 return 1;
289 }
810260a8 290 return 0;
291}
292
293#define OPCD(opc) ((opc)<<26)
294#define XO19(opc) (OPCD(19)|((opc)<<1))
295#define XO30(opc) (OPCD(30)|((opc)<<2))
296#define XO31(opc) (OPCD(31)|((opc)<<1))
297#define XO58(opc) (OPCD(58)|(opc))
298#define XO62(opc) (OPCD(62)|(opc))
299
300#define B OPCD( 18)
301#define BC OPCD( 16)
302#define LBZ OPCD( 34)
303#define LHZ OPCD( 40)
304#define LHA OPCD( 42)
305#define LWZ OPCD( 32)
306#define STB OPCD( 38)
307#define STH OPCD( 44)
308#define STW OPCD( 36)
309
310#define STD XO62( 0)
311#define STDU XO62( 1)
312#define STDX XO31(149)
313
314#define LD XO58( 0)
315#define LDX XO31( 21)
316#define LDU XO58( 1)
301f6d90 317#define LWA XO58( 2)
810260a8 318#define LWAX XO31(341)
319
1cd62ae9 320#define ADDIC OPCD( 12)
810260a8 321#define ADDI OPCD( 14)
322#define ADDIS OPCD( 15)
323#define ORI OPCD( 24)
324#define ORIS OPCD( 25)
325#define XORI OPCD( 26)
326#define XORIS OPCD( 27)
327#define ANDI OPCD( 28)
328#define ANDIS OPCD( 29)
329#define MULLI OPCD( 7)
330#define CMPLI OPCD( 10)
331#define CMPI OPCD( 11)
148bdd23 332#define SUBFIC OPCD( 8)
810260a8 333
334#define LWZU OPCD( 33)
335#define STWU OPCD( 37)
336
337#define RLWINM OPCD( 21)
338
339#define RLDICL XO30( 0)
340#define RLDICR XO30( 1)
3ee1b855 341#define RLDIMI XO30( 3)
810260a8 342
343#define BCLR XO19( 16)
344#define BCCTR XO19(528)
345#define CRAND XO19(257)
346#define CRANDC XO19(129)
347#define CRNAND XO19(225)
348#define CROR XO19(449)
1cd62ae9 349#define CRNOR XO19( 33)
810260a8 350
351#define EXTSB XO31(954)
352#define EXTSH XO31(922)
353#define EXTSW XO31(986)
354#define ADD XO31(266)
355#define ADDE XO31(138)
356#define ADDC XO31( 10)
357#define AND XO31( 28)
358#define SUBF XO31( 40)
359#define SUBFC XO31( 8)
360#define SUBFE XO31(136)
361#define OR XO31(444)
362#define XOR XO31(316)
363#define MULLW XO31(235)
364#define MULHWU XO31( 11)
365#define DIVW XO31(491)
366#define DIVWU XO31(459)
367#define CMP XO31( 0)
368#define CMPL XO31( 32)
369#define LHBRX XO31(790)
370#define LWBRX XO31(534)
371#define STHBRX XO31(918)
372#define STWBRX XO31(662)
373#define MFSPR XO31(339)
374#define MTSPR XO31(467)
375#define SRAWI XO31(824)
376#define NEG XO31(104)
1cd62ae9 377#define MFCR XO31( 19)
157f2662 378#define NOR XO31(124)
1cd62ae9 379#define CNTLZW XO31( 26)
380#define CNTLZD XO31( 58)
810260a8 381
382#define MULLD XO31(233)
383#define MULHD XO31( 73)
384#define MULHDU XO31( 9)
385#define DIVD XO31(489)
386#define DIVDU XO31(457)
387
388#define LBZX XO31( 87)
4f4a67ae 389#define LHZX XO31(279)
810260a8 390#define LHAX XO31(343)
391#define LWZX XO31( 23)
392#define STBX XO31(215)
393#define STHX XO31(407)
394#define STWX XO31(151)
395
396#define SPR(a,b) ((((a)<<5)|(b))<<11)
397#define LR SPR(8, 0)
398#define CTR SPR(9, 0)
399
400#define SLW XO31( 24)
401#define SRW XO31(536)
402#define SRAW XO31(792)
403
404#define SLD XO31( 27)
405#define SRD XO31(539)
406#define SRAD XO31(794)
fe6f943f 407#define SRADI XO31(413<<1)
810260a8 408
810260a8 409#define TW XO31( 4)
410#define TRAP (TW | TO (31))
411
412#define RT(r) ((r)<<21)
413#define RS(r) ((r)<<21)
414#define RA(r) ((r)<<16)
415#define RB(r) ((r)<<11)
416#define TO(t) ((t)<<21)
417#define SH(s) ((s)<<11)
418#define MB(b) ((b)<<6)
419#define ME(e) ((e)<<1)
420#define BO(o) ((o)<<21)
421#define MB64(b) ((b)<<5)
422
423#define LK 1
424
2fd8eddc
RH
425#define TAB(t, a, b) (RT(t) | RA(a) | RB(b))
426#define SAB(s, a, b) (RS(s) | RA(a) | RB(b))
427#define TAI(s, a, i) (RT(s) | RA(a) | ((i) & 0xffff))
428#define SAI(s, a, i) (RS(s) | RA(a) | ((i) & 0xffff))
810260a8 429
430#define BF(n) ((n)<<23)
431#define BI(n, c) (((c)+((n)*4))<<16)
432#define BT(n, c) (((c)+((n)*4))<<21)
433#define BA(n, c) (((c)+((n)*4))<<16)
434#define BB(n, c) (((c)+((n)*4))<<11)
435
436#define BO_COND_TRUE BO (12)
437#define BO_COND_FALSE BO ( 4)
438#define BO_ALWAYS BO (20)
439
440enum {
441 CR_LT,
442 CR_GT,
443 CR_EQ,
444 CR_SO
445};
446
0aed257f 447static const uint32_t tcg_to_bc[] = {
810260a8 448 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
449 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
450 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
451 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
452 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
453 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
454 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
455 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
456 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
457 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
458};
459
aceac8d6
RH
460static inline void tcg_out_mov(TCGContext *s, TCGType type,
461 TCGReg ret, TCGReg arg)
810260a8 462{
463 tcg_out32 (s, OR | SAB (arg, ret, arg));
464}
465
aceac8d6
RH
466static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
467 int sh, int mb)
810260a8 468{
469 sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1);
470 mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f));
471 tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb);
472}
473
9e555b73
RH
474static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
475 int sh, int mb, int me)
476{
477 tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
478}
479
6e5e0602
RH
480static inline void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
481{
482 tcg_out_rld(s, RLDICL, dst, src, 0, 32);
483}
484
0a9564b9
RH
485static inline void tcg_out_shli64(TCGContext *s, TCGReg dst, TCGReg src, int c)
486{
487 tcg_out_rld(s, RLDICR, dst, src, c, 63 - c);
488}
489
5e916c28
RH
490static inline void tcg_out_shri64(TCGContext *s, TCGReg dst, TCGReg src, int c)
491{
492 tcg_out_rld(s, RLDICL, dst, src, 64 - c, c);
493}
494
aceac8d6 495static void tcg_out_movi32(TCGContext *s, TCGReg ret, int32_t arg)
810260a8 496{
2fd8eddc
RH
497 if (arg == (int16_t) arg) {
498 tcg_out32(s, ADDI | TAI(ret, 0, arg));
499 } else {
500 tcg_out32(s, ADDIS | TAI(ret, 0, arg >> 16));
501 if (arg & 0xffff) {
502 tcg_out32(s, ORI | SAI(ret, ret, arg));
503 }
810260a8 504 }
505}
506
421233a1
RH
507static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
508 tcg_target_long arg)
810260a8 509{
421233a1
RH
510 if (type == TCG_TYPE_I32 || arg == (int32_t)arg) {
511 tcg_out_movi32(s, ret, arg);
512 } else if (arg == (uint32_t)arg && !(arg & 0x8000)) {
513 tcg_out32(s, ADDI | TAI(ret, 0, arg));
514 tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
515 } else {
516 int32_t high = arg >> 32;
517 tcg_out_movi32(s, ret, high);
518 if (high) {
0a9564b9 519 tcg_out_shli64(s, ret, ret, 32);
421233a1
RH
520 }
521 if (arg & 0xffff0000) {
522 tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
523 }
524 if (arg & 0xffff) {
525 tcg_out32(s, ORI | SAI(ret, ret, arg));
810260a8 526 }
527 }
528}
529
a9249dff
RH
530static inline bool mask_operand(uint32_t c, int *mb, int *me)
531{
532 uint32_t lsb, test;
533
534 /* Accept a bit pattern like:
535 0....01....1
536 1....10....0
537 0..01..10..0
538 Keep track of the transitions. */
539 if (c == 0 || c == -1) {
540 return false;
541 }
542 test = c;
543 lsb = test & -test;
544 test += lsb;
545 if (test & (test - 1)) {
546 return false;
547 }
548
549 *me = clz32(lsb);
550 *mb = test ? clz32(test & -test) + 1 : 0;
551 return true;
552}
553
554static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
555{
556 int mb, me;
557
558 if ((c & 0xffff) == c) {
559 tcg_out32(s, ANDI | SAI(src, dst, c));
560 return;
561 } else if ((c & 0xffff0000) == c) {
562 tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
563 return;
564 } else if (mask_operand(c, &mb, &me)) {
565 tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
566 } else {
567 tcg_out_movi(s, TCG_TYPE_I32, 0, c);
568 tcg_out32(s, AND | SAB(src, dst, 0));
569 }
570}
571
dce74c57
RH
572static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
573 int op_lo, int op_hi)
574{
575 if (c >> 16) {
576 tcg_out32(s, op_hi | SAI(src, dst, c >> 16));
577 src = dst;
578 }
579 if (c & 0xffff) {
580 tcg_out32(s, op_lo | SAI(src, dst, c));
581 src = dst;
582 }
583}
584
585static void tcg_out_ori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
586{
587 tcg_out_zori32(s, dst, src, c, ORI, ORIS);
588}
589
590static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
591{
592 tcg_out_zori32(s, dst, src, c, XORI, XORIS);
593}
594
5d7ff5bb
AF
595static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
596{
597 tcg_target_long disp;
598
599 disp = target - (tcg_target_long) s->code_ptr;
600 if ((disp << 38) >> 38 == disp)
601 tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
602 else {
603 tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target);
604 tcg_out32 (s, MTSPR | RS (0) | CTR);
605 tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
606 }
607}
608
810260a8 609static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
610{
5d7ff5bb
AF
611#ifdef __APPLE__
612 if (const_arg) {
613 tcg_out_b (s, LK, arg);
614 }
615 else {
616 tcg_out32 (s, MTSPR | RS (arg) | LR);
617 tcg_out32 (s, BCLR | BO_ALWAYS | LK);
618 }
619#else
810260a8 620 int reg;
621
622 if (const_arg) {
623 reg = 2;
624 tcg_out_movi (s, TCG_TYPE_I64, reg, arg);
625 }
626 else reg = arg;
627
628 tcg_out32 (s, LD | RT (0) | RA (reg));
629 tcg_out32 (s, MTSPR | RA (0) | CTR);
630 tcg_out32 (s, LD | RT (11) | RA (reg) | 16);
631 tcg_out32 (s, LD | RT (2) | RA (reg) | 8);
632 tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
5d7ff5bb 633#endif
810260a8 634}
635
aceac8d6
RH
636static void tcg_out_ldst(TCGContext *s, TCGReg ret, TCGReg addr,
637 int offset, int op1, int op2)
810260a8 638{
2fd8eddc
RH
639 if (offset == (int16_t) offset) {
640 tcg_out32(s, op1 | TAI(ret, addr, offset));
641 } else {
642 tcg_out_movi(s, TCG_TYPE_I64, 0, offset);
643 tcg_out32(s, op2 | TAB(ret, addr, 0));
810260a8 644 }
645}
646
aceac8d6
RH
647static void tcg_out_ldsta(TCGContext *s, TCGReg ret, TCGReg addr,
648 int offset, int op1, int op2)
828808f5 649{
2fd8eddc
RH
650 if (offset == (int16_t) (offset & ~3)) {
651 tcg_out32(s, op1 | TAI(ret, addr, offset));
652 } else {
653 tcg_out_movi(s, TCG_TYPE_I64, 0, offset);
654 tcg_out32(s, op2 | TAB(ret, addr, 0));
828808f5 655 }
656}
657
810260a8 658#if defined (CONFIG_SOFTMMU)
79383c9c 659
022c62cb 660#include "exec/softmmu_defs.h"
810260a8 661
e141ab52
BS
662/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
663 int mmu_idx) */
664static const void * const qemu_ld_helpers[4] = {
665 helper_ldb_mmu,
666 helper_ldw_mmu,
667 helper_ldl_mmu,
668 helper_ldq_mmu,
669};
670
671/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
672 uintxx_t val, int mmu_idx) */
673static const void * const qemu_st_helpers[4] = {
674 helper_stb_mmu,
675 helper_stw_mmu,
676 helper_stl_mmu,
677 helper_stq_mmu,
678};
810260a8 679
aceac8d6
RH
680static void tcg_out_tlb_read(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
681 TCGReg addr_reg, int s_bits, int offset)
810260a8 682{
880e52b8 683#if TARGET_LONG_BITS == 32
6e5e0602 684 tcg_out_ext32u(s, addr_reg, addr_reg);
810260a8 685
9e555b73
RH
686 tcg_out_rlw(s, RLWINM, r0, addr_reg,
687 32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
688 32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
689 31 - CPU_TLB_ENTRY_BITS);
2fd8eddc
RH
690 tcg_out32(s, ADD | TAB(r0, r0, TCG_AREG0));
691 tcg_out32(s, LWZU | TAI(r1, r0, offset));
9e555b73
RH
692 tcg_out_rlw(s, RLWINM, r2, addr_reg, 0,
693 (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
4a40e231 694#else
810260a8 695 tcg_out_rld (s, RLDICL, r0, addr_reg,
696 64 - TARGET_PAGE_BITS,
697 64 - CPU_TLB_BITS);
0a9564b9 698 tcg_out_shli64(s, r0, r0, CPU_TLB_ENTRY_BITS);
810260a8 699
2fd8eddc
RH
700 tcg_out32(s, ADD | TAB(r0, r0, TCG_AREG0));
701 tcg_out32(s, LD_ADDR | TAI(r1, r0, offset));
810260a8 702
4a40e231 703 if (!s_bits) {
704 tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS);
705 }
706 else {
707 tcg_out_rld (s, RLDICL, r2, addr_reg,
708 64 - TARGET_PAGE_BITS,
709 TARGET_PAGE_BITS - s_bits);
710 tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0);
711 }
712#endif
810260a8 713}
a2a546b3 714#endif
810260a8 715
716static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
717{
aceac8d6
RH
718 TCGReg addr_reg, data_reg, r0, r1, rbase;
719 int bswap;
810260a8 720#ifdef CONFIG_SOFTMMU
aceac8d6
RH
721 TCGReg r2, ir;
722 int mem_index, s_bits;
810260a8 723 void *label1_ptr, *label2_ptr;
724#endif
725
726 data_reg = *args++;
727 addr_reg = *args++;
9df3b45d
DG
728
729#ifdef CONFIG_SOFTMMU
810260a8 730 mem_index = *args;
731 s_bits = opc & 3;
732
810260a8 733 r0 = 3;
734 r1 = 4;
735 r2 = 0;
f6548c0a 736 rbase = 0;
810260a8 737
738 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits,
9349b4f9 739 offsetof (CPUArchState, tlb_table[mem_index][0].addr_read));
810260a8 740
e924bbec 741 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
810260a8 742
743 label1_ptr = s->code_ptr;
744#ifdef FAST_PATH
745 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
746#endif
747
748 /* slow path */
c82e5848 749 ir = 3;
f4f7d01a 750 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
c82e5848
AF
751 tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
752 tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
810260a8 753
754 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
755
756 switch (opc) {
757 case 0|4:
758 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
759 break;
760 case 1|4:
761 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
762 break;
763 case 2|4:
764 tcg_out32 (s, EXTSW | RA (data_reg) | RS (3));
765 break;
766 case 0:
767 case 1:
768 case 2:
769 case 3:
770 if (data_reg != 3)
3b6dac34 771 tcg_out_mov (s, TCG_TYPE_I64, data_reg, 3);
810260a8 772 break;
773 }
774 label2_ptr = s->code_ptr;
775 tcg_out32 (s, B);
776
777 /* label1: fast path */
778#ifdef FAST_PATH
779 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
780#endif
781
782 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
2fd8eddc
RH
783 tcg_out32(s, LD | TAI(r0, r0,
784 offsetof(CPUTLBEntry, addend)
785 - offsetof(CPUTLBEntry, addr_read)));
810260a8 786 /* r0 = env->tlb_table[mem_index][index].addend */
2fd8eddc 787 tcg_out32(s, ADD | TAB(r0, r0, addr_reg));
810260a8 788 /* r0 = env->tlb_table[mem_index][index].addend + addr */
789
790#else /* !CONFIG_SOFTMMU */
0b7c1d89 791#if TARGET_LONG_BITS == 32
6e5e0602 792 tcg_out_ext32u(s, addr_reg, addr_reg);
0b7c1d89 793#endif
810260a8 794 r0 = addr_reg;
735ee40d 795 r1 = 3;
f6548c0a 796 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
810260a8 797#endif
798
799#ifdef TARGET_WORDS_BIGENDIAN
800 bswap = 0;
801#else
802 bswap = 1;
803#endif
804 switch (opc) {
805 default:
806 case 0:
f6548c0a 807 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
810260a8 808 break;
809 case 0|4:
f6548c0a 810 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
810260a8 811 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
812 break;
813 case 1:
f6548c0a 814 if (bswap)
815 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
816 else
817 tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0));
810260a8 818 break;
819 case 1|4:
820 if (bswap) {
f6548c0a 821 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
810260a8 822 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
823 }
f6548c0a 824 else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0));
810260a8 825 break;
826 case 2:
f6548c0a 827 if (bswap)
828 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
829 else
830 tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0));
810260a8 831 break;
832 case 2|4:
833 if (bswap) {
f6548c0a 834 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
450e62e7 835 tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg));
810260a8 836 }
f6548c0a 837 else tcg_out32 (s, LWAX | TAB (data_reg, rbase, r0));
810260a8 838 break;
839 case 3:
f6548c0a 840#ifdef CONFIG_USE_GUEST_BASE
841 if (bswap) {
2fd8eddc 842 tcg_out32(s, ADDI | TAI(r1, r0, 4));
f6548c0a 843 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
844 tcg_out32 (s, LWBRX | TAB ( r1, rbase, r1));
845 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
846 }
847 else tcg_out32 (s, LDX | TAB (data_reg, rbase, r0));
848#else
810260a8 849 if (bswap) {
b1d6d51d 850 tcg_out_movi32 (s, 0, 4);
3ee1b855 851 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
852 tcg_out32 (s, LWBRX | RT ( r1) | RA (r0));
853 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
810260a8 854 }
855 else tcg_out32 (s, LD | RT (data_reg) | RA (r0));
f6548c0a 856#endif
810260a8 857 break;
858 }
859
860#ifdef CONFIG_SOFTMMU
861 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
862#endif
863}
864
865static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
866{
aceac8d6
RH
867 TCGReg addr_reg, r0, r1, rbase, data_reg;
868 int bswap;
810260a8 869#ifdef CONFIG_SOFTMMU
aceac8d6
RH
870 TCGReg r2, ir;
871 int mem_index;
810260a8 872 void *label1_ptr, *label2_ptr;
873#endif
874
875 data_reg = *args++;
876 addr_reg = *args++;
810260a8 877
878#ifdef CONFIG_SOFTMMU
9df3b45d
DG
879 mem_index = *args;
880
810260a8 881 r0 = 3;
882 r1 = 4;
883 r2 = 0;
f6548c0a 884 rbase = 0;
810260a8 885
886 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc,
9349b4f9 887 offsetof (CPUArchState, tlb_table[mem_index][0].addr_write));
810260a8 888
e924bbec 889 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
810260a8 890
891 label1_ptr = s->code_ptr;
892#ifdef FAST_PATH
893 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
894#endif
895
896 /* slow path */
c82e5848 897 ir = 3;
f4f7d01a 898 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
c82e5848
AF
899 tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
900 tcg_out_rld (s, RLDICL, ir++, data_reg, 0, 64 - (1 << (3 + opc)));
901 tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
810260a8 902
903 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
904
905 label2_ptr = s->code_ptr;
906 tcg_out32 (s, B);
907
908 /* label1: fast path */
909#ifdef FAST_PATH
910 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
911#endif
912
355b1943 913 tcg_out32 (s, (LD
810260a8 914 | RT (r0)
915 | RA (r0)
916 | (offsetof (CPUTLBEntry, addend)
917 - offsetof (CPUTLBEntry, addr_write))
918 ));
919 /* r0 = env->tlb_table[mem_index][index].addend */
2fd8eddc 920 tcg_out32(s, ADD | TAB(r0, r0, addr_reg));
810260a8 921 /* r0 = env->tlb_table[mem_index][index].addend + addr */
922
923#else /* !CONFIG_SOFTMMU */
0b7c1d89 924#if TARGET_LONG_BITS == 32
6e5e0602 925 tcg_out_ext32u(s, addr_reg, addr_reg);
0b7c1d89 926#endif
735ee40d 927 r1 = 3;
810260a8 928 r0 = addr_reg;
f6548c0a 929 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
810260a8 930#endif
931
932#ifdef TARGET_WORDS_BIGENDIAN
933 bswap = 0;
934#else
935 bswap = 1;
936#endif
937 switch (opc) {
938 case 0:
f6548c0a 939 tcg_out32 (s, STBX | SAB (data_reg, rbase, r0));
810260a8 940 break;
941 case 1:
f6548c0a 942 if (bswap)
943 tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0));
944 else
945 tcg_out32 (s, STHX | SAB (data_reg, rbase, r0));
810260a8 946 break;
947 case 2:
f6548c0a 948 if (bswap)
949 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
950 else
951 tcg_out32 (s, STWX | SAB (data_reg, rbase, r0));
810260a8 952 break;
953 case 3:
954 if (bswap) {
f6548c0a 955 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
2fd8eddc 956 tcg_out32(s, ADDI | TAI(r1, r0, 4));
5e916c28 957 tcg_out_shri64(s, 0, data_reg, 32);
f6548c0a 958 tcg_out32 (s, STWBRX | SAB (0, rbase, r1));
810260a8 959 }
f6548c0a 960 else tcg_out32 (s, STDX | SAB (data_reg, rbase, r0));
810260a8 961 break;
962 }
963
964#ifdef CONFIG_SOFTMMU
965 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
966#endif
967}
968
e4d58b41 969static void tcg_target_qemu_prologue (TCGContext *s)
810260a8 970{
971 int i, frame_size;
5d7ff5bb 972#ifndef __APPLE__
a69abbe0 973 uint64_t addr;
5d7ff5bb 974#endif
810260a8 975
976 frame_size = 0
977 + 8 /* back chain */
978 + 8 /* CR */
979 + 8 /* LR */
980 + 8 /* compiler doubleword */
981 + 8 /* link editor doubleword */
982 + 8 /* TOC save area */
983 + TCG_STATIC_CALL_ARGS_SIZE
984 + ARRAY_SIZE (tcg_target_callee_save_regs) * 8
136a0b5a 985 + CPU_TEMP_BUF_NLONGS * sizeof(long)
810260a8 986 ;
987 frame_size = (frame_size + 15) & ~15;
988
f6af014e 989 tcg_set_frame (s, TCG_REG_CALL_STACK, frame_size
990 - CPU_TEMP_BUF_NLONGS * sizeof (long),
991 CPU_TEMP_BUF_NLONGS * sizeof (long));
136a0b5a 992
5d7ff5bb 993#ifndef __APPLE__
a69abbe0 994 /* First emit adhoc function descriptor */
995 addr = (uint64_t) s->code_ptr + 24;
996 tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */
997 s->code_ptr += 16; /* skip TOC and environment pointer */
5d7ff5bb 998#endif
a69abbe0 999
1000 /* Prologue */
810260a8 1001 tcg_out32 (s, MFSPR | RT (0) | LR);
1002 tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff));
1003 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
1004 tcg_out32 (s, (STD
1005 | RS (tcg_target_callee_save_regs[i])
1006 | RA (1)
1007 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
1008 )
1009 );
e03ae7f9 1010 tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16));
810260a8 1011
f6548c0a 1012#ifdef CONFIG_USE_GUEST_BASE
b9e946c7
RH
1013 if (GUEST_BASE) {
1014 tcg_out_movi (s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE);
f6af014e 1015 tcg_regset_set_reg (s->reserved_regs, TCG_GUEST_BASE_REG);
b9e946c7 1016 }
f6548c0a 1017#endif
1018
cea5f9a2
BS
1019 tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1020 tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
810260a8 1021 tcg_out32 (s, BCCTR | BO_ALWAYS);
a69abbe0 1022
1023 /* Epilogue */
810260a8 1024 tb_ret_addr = s->code_ptr;
1025
1026 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
1027 tcg_out32 (s, (LD
1028 | RT (tcg_target_callee_save_regs[i])
1029 | RA (1)
1030 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
1031 )
1032 );
2fd8eddc
RH
1033 tcg_out32(s, LD | TAI(0, 1, frame_size + 16));
1034 tcg_out32(s, MTSPR | RS(0) | LR);
1035 tcg_out32(s, ADDI | TAI(1, 1, frame_size));
1036 tcg_out32(s, BCLR | BO_ALWAYS);
810260a8 1037}
1038
2a534aff 1039static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
810260a8 1040 tcg_target_long arg2)
1041{
1042 if (type == TCG_TYPE_I32)
1043 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
1044 else
828808f5 1045 tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
810260a8 1046}
1047
2a534aff 1048static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
810260a8 1049 tcg_target_long arg2)
1050{
1051 if (type == TCG_TYPE_I32)
1052 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
1053 else
828808f5 1054 tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX);
810260a8 1055}
1056
810260a8 1057static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
e924bbec 1058 int const_arg2, int cr, int arch64)
810260a8 1059{
1060 int imm;
1061 uint32_t op;
1062
1063 switch (cond) {
1064 case TCG_COND_EQ:
1065 case TCG_COND_NE:
1066 if (const_arg2) {
1067 if ((int16_t) arg2 == arg2) {
1068 op = CMPI;
1069 imm = 1;
1070 break;
1071 }
1072 else if ((uint16_t) arg2 == arg2) {
1073 op = CMPLI;
1074 imm = 1;
1075 break;
1076 }
1077 }
1078 op = CMPL;
1079 imm = 0;
1080 break;
1081
1082 case TCG_COND_LT:
1083 case TCG_COND_GE:
1084 case TCG_COND_LE:
1085 case TCG_COND_GT:
1086 if (const_arg2) {
1087 if ((int16_t) arg2 == arg2) {
1088 op = CMPI;
1089 imm = 1;
1090 break;
1091 }
1092 }
1093 op = CMP;
1094 imm = 0;
1095 break;
1096
1097 case TCG_COND_LTU:
1098 case TCG_COND_GEU:
1099 case TCG_COND_LEU:
1100 case TCG_COND_GTU:
1101 if (const_arg2) {
1102 if ((uint16_t) arg2 == arg2) {
1103 op = CMPLI;
1104 imm = 1;
1105 break;
1106 }
1107 }
1108 op = CMPL;
1109 imm = 0;
1110 break;
1111
1112 default:
1113 tcg_abort ();
1114 }
e924bbec 1115 op |= BF (cr) | (arch64 << 21);
810260a8 1116
1117 if (imm)
1118 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
1119 else {
1120 if (const_arg2) {
1121 tcg_out_movi (s, TCG_TYPE_I64, 0, arg2);
1122 tcg_out32 (s, op | RA (arg1) | RB (0));
1123 }
1124 else
1125 tcg_out32 (s, op | RA (arg1) | RB (arg2));
1126 }
1127
1128}
1129
8a56e840
RH
1130static void tcg_out_setcond (TCGContext *s, TCGType type, TCGCond cond,
1131 TCGArg arg0, TCGArg arg1, TCGArg arg2,
1132 int const_arg2)
1cd62ae9 1133{
1134 int crop, sh, arg;
1135
1136 switch (cond) {
1137 case TCG_COND_EQ:
1138 if (const_arg2) {
1139 if (!arg2) {
1140 arg = arg1;
1141 }
1142 else {
1143 arg = 0;
1144 if ((uint16_t) arg2 == arg2) {
2fd8eddc 1145 tcg_out32(s, XORI | SAI(arg1, 0, arg2));
1cd62ae9 1146 }
1147 else {
1148 tcg_out_movi (s, type, 0, arg2);
1149 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1150 }
1151 }
1152 }
1153 else {
1154 arg = 0;
1155 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1156 }
1157
1158 if (type == TCG_TYPE_I64) {
1159 tcg_out32 (s, CNTLZD | RS (arg) | RA (0));
1160 tcg_out_rld (s, RLDICL, arg0, 0, 58, 6);
1161 }
1162 else {
1163 tcg_out32 (s, CNTLZW | RS (arg) | RA (0));
9e555b73 1164 tcg_out_rlw(s, RLWINM, arg0, 0, 27, 5, 31);
1cd62ae9 1165 }
1166 break;
1167
1168 case TCG_COND_NE:
1169 if (const_arg2) {
1170 if (!arg2) {
1171 arg = arg1;
1172 }
1173 else {
1174 arg = 0;
1175 if ((uint16_t) arg2 == arg2) {
2fd8eddc
RH
1176 tcg_out32(s, XORI | SAI(arg1, 0, arg2));
1177 } else {
1cd62ae9 1178 tcg_out_movi (s, type, 0, arg2);
1179 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1180 }
1181 }
1182 }
1183 else {
1184 arg = 0;
1185 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1186 }
1187
752c1fdb
RH
1188 /* Make sure and discard the high 32-bits of the input. */
1189 if (type == TCG_TYPE_I32) {
1190 tcg_out32(s, EXTSW | RA(TCG_REG_R0) | RS(arg));
1191 arg = TCG_REG_R0;
1192 }
1193
1cd62ae9 1194 if (arg == arg1 && arg1 == arg0) {
2fd8eddc
RH
1195 tcg_out32(s, ADDIC | TAI(0, arg, -1));
1196 tcg_out32(s, SUBFE | TAB(arg0, 0, arg));
1cd62ae9 1197 }
1198 else {
2fd8eddc
RH
1199 tcg_out32(s, ADDIC | TAI(arg0, arg, -1));
1200 tcg_out32(s, SUBFE | TAB(arg0, arg0, arg));
1cd62ae9 1201 }
1202 break;
1203
1204 case TCG_COND_GT:
1205 case TCG_COND_GTU:
1206 sh = 30;
1207 crop = 0;
1208 goto crtest;
1209
1210 case TCG_COND_LT:
1211 case TCG_COND_LTU:
1212 sh = 29;
1213 crop = 0;
1214 goto crtest;
1215
1216 case TCG_COND_GE:
1217 case TCG_COND_GEU:
1218 sh = 31;
1219 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
1220 goto crtest;
1221
1222 case TCG_COND_LE:
1223 case TCG_COND_LEU:
1224 sh = 31;
1225 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
1226 crtest:
1227 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, type == TCG_TYPE_I64);
1228 if (crop) tcg_out32 (s, crop);
1229 tcg_out32 (s, MFCR | RT (0));
9e555b73 1230 tcg_out_rlw(s, RLWINM, arg0, 0, sh, 31, 31);
1cd62ae9 1231 break;
1232
1233 default:
1234 tcg_abort ();
1235 }
1236}
1237
810260a8 1238static void tcg_out_bc (TCGContext *s, int bc, int label_index)
1239{
1240 TCGLabel *l = &s->labels[label_index];
1241
1242 if (l->has_value)
1243 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
1244 else {
1245 uint16_t val = *(uint16_t *) &s->code_ptr[2];
1246
1247 /* Thanks to Andrzej Zaborowski */
1248 tcg_out32 (s, bc | (val & 0xfffc));
1249 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
1250 }
1251}
1252
8a56e840 1253static void tcg_out_brcond (TCGContext *s, TCGCond cond,
810260a8 1254 TCGArg arg1, TCGArg arg2, int const_arg2,
e924bbec 1255 int label_index, int arch64)
810260a8 1256{
e924bbec 1257 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, arch64);
810260a8 1258 tcg_out_bc (s, tcg_to_bc[cond], label_index);
1259}
1260
1261void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
1262{
1263 TCGContext s;
1264 unsigned long patch_size;
1265
1266 s.code_ptr = (uint8_t *) jmp_addr;
1267 tcg_out_b (&s, 0, addr);
1268 patch_size = s.code_ptr - (uint8_t *) jmp_addr;
1269 flush_icache_range (jmp_addr, jmp_addr + patch_size);
1270}
1271
a9751609 1272static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
810260a8 1273 const int *const_args)
1274{
ee924fa6 1275 TCGArg a0, a1, a2;
e46b9681 1276 int c;
1277
810260a8 1278 switch (opc) {
1279 case INDEX_op_exit_tb:
1280 tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
1281 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
1282 break;
1283 case INDEX_op_goto_tb:
1284 if (s->tb_jmp_offset) {
1285 /* direct jump method */
1286
1287 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
5424fd10 1288 s->code_ptr += 28;
810260a8 1289 }
1290 else {
1291 tcg_abort ();
1292 }
1293 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1294 break;
1295 case INDEX_op_br:
1296 {
1297 TCGLabel *l = &s->labels[args[0]];
1298
1299 if (l->has_value) {
1300 tcg_out_b (s, 0, l->u.value);
1301 }
1302 else {
1303 uint32_t val = *(uint32_t *) s->code_ptr;
1304
1305 /* Thanks to Andrzej Zaborowski */
1306 tcg_out32 (s, B | (val & 0x3fffffc));
1307 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1308 }
1309 }
1310 break;
1311 case INDEX_op_call:
1312 tcg_out_call (s, args[0], const_args[0]);
1313 break;
810260a8 1314 case INDEX_op_movi_i32:
1315 tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]);
1316 break;
1317 case INDEX_op_movi_i64:
1318 tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]);
1319 break;
1320 case INDEX_op_ld8u_i32:
1321 case INDEX_op_ld8u_i64:
1322 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1323 break;
1324 case INDEX_op_ld8s_i32:
1325 case INDEX_op_ld8s_i64:
1326 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1327 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1328 break;
1329 case INDEX_op_ld16u_i32:
1330 case INDEX_op_ld16u_i64:
1331 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1332 break;
1333 case INDEX_op_ld16s_i32:
1334 case INDEX_op_ld16s_i64:
1335 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1336 break;
1337 case INDEX_op_ld_i32:
1338 case INDEX_op_ld32u_i64:
1339 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1340 break;
1341 case INDEX_op_ld32s_i64:
828808f5 1342 tcg_out_ldsta (s, args[0], args[1], args[2], LWA, LWAX);
810260a8 1343 break;
1344 case INDEX_op_ld_i64:
828808f5 1345 tcg_out_ldsta (s, args[0], args[1], args[2], LD, LDX);
810260a8 1346 break;
1347 case INDEX_op_st8_i32:
1348 case INDEX_op_st8_i64:
1349 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1350 break;
1351 case INDEX_op_st16_i32:
1352 case INDEX_op_st16_i64:
1353 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1354 break;
1355 case INDEX_op_st_i32:
1356 case INDEX_op_st32_i64:
1357 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1358 break;
1359 case INDEX_op_st_i64:
828808f5 1360 tcg_out_ldsta (s, args[0], args[1], args[2], STD, STDX);
810260a8 1361 break;
1362
1363 case INDEX_op_add_i32:
ee924fa6
RH
1364 a0 = args[0], a1 = args[1], a2 = args[2];
1365 if (const_args[2]) {
1366 int32_t l, h;
1367 do_addi_32:
1368 l = (int16_t)a2;
1369 h = a2 - l;
1370 if (h) {
1371 tcg_out32(s, ADDIS | TAI(a0, a1, h >> 16));
1372 a1 = a0;
1373 }
1374 if (l || a0 != a1) {
1375 tcg_out32(s, ADDI | TAI(a0, a1, l));
1376 }
1377 } else {
1378 tcg_out32(s, ADD | TAB(a0, a1, a2));
1379 }
810260a8 1380 break;
1381 case INDEX_op_sub_i32:
ee924fa6 1382 a0 = args[0], a1 = args[1], a2 = args[2];
148bdd23
RH
1383 if (const_args[1]) {
1384 if (const_args[2]) {
1385 tcg_out_movi(s, TCG_TYPE_I32, a0, a1 - a2);
1386 } else {
1387 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
1388 }
1389 } else if (const_args[2]) {
ee924fa6
RH
1390 a2 = -a2;
1391 goto do_addi_32;
1392 } else {
1393 tcg_out32(s, SUBF | TAB(a0, a2, a1));
1394 }
810260a8 1395 break;
1396
1397 case INDEX_op_and_i32:
a9249dff
RH
1398 if (const_args[2]) {
1399 tcg_out_andi32(s, args[0], args[1], args[2]);
1400 } else {
1401 tcg_out32(s, AND | SAB(args[1], args[0], args[2]));
1402 }
1403 break;
1404 case INDEX_op_and_i64:
810260a8 1405 if (const_args[2]) {
2fd8eddc
RH
1406 if ((args[2] & 0xffff) == args[2]) {
1407 tcg_out32(s, ANDI | SAI(args[1], args[0], args[2]));
1408 } else if ((args[2] & 0xffff0000) == args[2]) {
1409 tcg_out32(s, ANDIS | SAI(args[1], args[0], args[2] >> 16));
1410 } else {
fe6f943f 1411 tcg_out_movi (s, (opc == INDEX_op_and_i32
1412 ? TCG_TYPE_I32
1413 : TCG_TYPE_I64),
1414 0, args[2]);
000a2d86 1415 tcg_out32 (s, AND | SAB (args[1], args[0], 0));
810260a8 1416 }
1417 }
1418 else
1419 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1420 break;
fe6f943f 1421 case INDEX_op_or_i64:
810260a8 1422 case INDEX_op_or_i32:
dce74c57 1423 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 1424 if (const_args[2]) {
dce74c57
RH
1425 tcg_out_ori32(s, a0, a1, a2);
1426 } else {
1427 tcg_out32(s, OR | SAB(a1, a0, a2));
810260a8 1428 }
810260a8 1429 break;
fe6f943f 1430 case INDEX_op_xor_i64:
810260a8 1431 case INDEX_op_xor_i32:
dce74c57 1432 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 1433 if (const_args[2]) {
dce74c57
RH
1434 tcg_out_xori32(s, a0, a1, a2);
1435 } else {
1436 tcg_out32(s, XOR | SAB(a1, a0, a2));
810260a8 1437 }
810260a8 1438 break;
1439
1440 case INDEX_op_mul_i32:
1441 if (const_args[2]) {
1442 if (args[2] == (int16_t) args[2])
1443 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1444 | (args[2] & 0xffff));
1445 else {
1446 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1447 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1448 }
1449 }
1450 else
1451 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1452 break;
1453
1454 case INDEX_op_div_i32:
1455 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1456 break;
1457
1458 case INDEX_op_divu_i32:
1459 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1460 break;
1461
1462 case INDEX_op_rem_i32:
1463 tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1464 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1465 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1466 break;
1467
1468 case INDEX_op_remu_i32:
1469 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1470 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1471 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1472 break;
1473
1474 case INDEX_op_shl_i32:
1475 if (const_args[2]) {
9e555b73
RH
1476 tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
1477 } else {
810260a8 1478 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
9e555b73 1479 }
810260a8 1480 break;
1481 case INDEX_op_shr_i32:
1482 if (const_args[2]) {
9e555b73
RH
1483 tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], args[2], 31);
1484 } else {
810260a8 1485 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
9e555b73 1486 }
810260a8 1487 break;
1488 case INDEX_op_sar_i32:
1489 if (const_args[2])
1490 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1491 else
1492 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1493 break;
1494
1495 case INDEX_op_brcond_i32:
e924bbec 1496 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 0);
1497 break;
1498
810260a8 1499 case INDEX_op_brcond_i64:
e924bbec 1500 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 1);
810260a8 1501 break;
1502
1503 case INDEX_op_neg_i32:
810260a8 1504 case INDEX_op_neg_i64:
1505 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1506 break;
1507
157f2662 1508 case INDEX_op_not_i32:
1509 case INDEX_op_not_i64:
1510 tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
1511 break;
1512
810260a8 1513 case INDEX_op_add_i64:
ee924fa6
RH
1514 a0 = args[0], a1 = args[1], a2 = args[2];
1515 if (const_args[2]) {
1516 int32_t l0, h1, h2;
1517 do_addi_64:
1518 /* We can always split any 32-bit signed constant into 3 pieces.
1519 Note the positive 0x80000000 coming from the sub_i64 path,
1520 handled with the same code we need for eg 0x7fff8000. */
1521 assert(a2 == (int32_t)a2 || a2 == 0x80000000);
1522 l0 = (int16_t)a2;
1523 h1 = a2 - l0;
1524 h2 = 0;
1525 if (h1 < 0 && (int64_t)a2 > 0) {
1526 h2 = 0x40000000;
1527 h1 = a2 - h2 - l0;
1528 }
1529 assert((TCGArg)h2 + h1 + l0 == a2);
1530
1531 if (h2) {
1532 tcg_out32(s, ADDIS | TAI(a0, a1, h2 >> 16));
1533 a1 = a0;
1534 }
1535 if (h1) {
1536 tcg_out32(s, ADDIS | TAI(a0, a1, h1 >> 16));
1537 a1 = a0;
1538 }
1539 if (l0 || a0 != a1) {
1540 tcg_out32(s, ADDI | TAI(a0, a1, l0));
1541 }
1542 } else {
1543 tcg_out32(s, ADD | TAB(a0, a1, a2));
1544 }
810260a8 1545 break;
1546 case INDEX_op_sub_i64:
ee924fa6 1547 a0 = args[0], a1 = args[1], a2 = args[2];
148bdd23
RH
1548 if (const_args[1]) {
1549 if (const_args[2]) {
1550 tcg_out_movi(s, TCG_TYPE_I64, a0, a1 - a2);
1551 } else {
1552 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
1553 }
1554 } else if (const_args[2]) {
ee924fa6
RH
1555 a2 = -a2;
1556 goto do_addi_64;
1557 } else {
1558 tcg_out32(s, SUBF | TAB(a0, a2, a1));
1559 }
810260a8 1560 break;
1561
1562 case INDEX_op_shl_i64:
fe6f943f 1563 if (const_args[2])
0a9564b9 1564 tcg_out_shli64(s, args[0], args[1], args[2]);
fe6f943f 1565 else
1566 tcg_out32 (s, SLD | SAB (args[1], args[0], args[2]));
810260a8 1567 break;
1568 case INDEX_op_shr_i64:
fe6f943f 1569 if (const_args[2])
5e916c28 1570 tcg_out_shri64(s, args[0], args[1], args[2]);
fe6f943f 1571 else
1572 tcg_out32 (s, SRD | SAB (args[1], args[0], args[2]));
810260a8 1573 break;
1574 case INDEX_op_sar_i64:
fe6f943f 1575 if (const_args[2]) {
1576 int sh = SH (args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
1577 tcg_out32 (s, SRADI | RA (args[0]) | RS (args[1]) | sh);
1578 }
1579 else
1580 tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2]));
810260a8 1581 break;
1582
1583 case INDEX_op_mul_i64:
1584 tcg_out32 (s, MULLD | TAB (args[0], args[1], args[2]));
1585 break;
1586 case INDEX_op_div_i64:
1587 tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2]));
1588 break;
1589 case INDEX_op_divu_i64:
1590 tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
1591 break;
1592 case INDEX_op_rem_i64:
1593 tcg_out32 (s, DIVD | TAB (0, args[1], args[2]));
1594 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1595 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1596 break;
1597 case INDEX_op_remu_i64:
1598 tcg_out32 (s, DIVDU | TAB (0, args[1], args[2]));
1599 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1600 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1601 break;
1602
1603 case INDEX_op_qemu_ld8u:
1604 tcg_out_qemu_ld (s, args, 0);
1605 break;
1606 case INDEX_op_qemu_ld8s:
1607 tcg_out_qemu_ld (s, args, 0 | 4);
1608 break;
1609 case INDEX_op_qemu_ld16u:
1610 tcg_out_qemu_ld (s, args, 1);
1611 break;
1612 case INDEX_op_qemu_ld16s:
1613 tcg_out_qemu_ld (s, args, 1 | 4);
1614 break;
86feb1c8 1615 case INDEX_op_qemu_ld32:
810260a8 1616 case INDEX_op_qemu_ld32u:
1617 tcg_out_qemu_ld (s, args, 2);
1618 break;
1619 case INDEX_op_qemu_ld32s:
1620 tcg_out_qemu_ld (s, args, 2 | 4);
1621 break;
1622 case INDEX_op_qemu_ld64:
1623 tcg_out_qemu_ld (s, args, 3);
1624 break;
1625 case INDEX_op_qemu_st8:
1626 tcg_out_qemu_st (s, args, 0);
1627 break;
1628 case INDEX_op_qemu_st16:
1629 tcg_out_qemu_st (s, args, 1);
1630 break;
1631 case INDEX_op_qemu_st32:
1632 tcg_out_qemu_st (s, args, 2);
1633 break;
1634 case INDEX_op_qemu_st64:
1635 tcg_out_qemu_st (s, args, 3);
1636 break;
1637
e46b9681 1638 case INDEX_op_ext8s_i32:
1639 case INDEX_op_ext8s_i64:
1640 c = EXTSB;
1641 goto gen_ext;
1642 case INDEX_op_ext16s_i32:
1643 case INDEX_op_ext16s_i64:
1644 c = EXTSH;
1645 goto gen_ext;
1646 case INDEX_op_ext32s_i64:
1647 c = EXTSW;
1648 goto gen_ext;
1649 gen_ext:
1650 tcg_out32 (s, c | RS (args[1]) | RA (args[0]));
1651 break;
1652
157f2662 1653 case INDEX_op_ext32u_i64:
6e5e0602 1654 tcg_out_ext32u(s, args[0], args[1]);
157f2662 1655 break;
1656
1cd62ae9 1657 case INDEX_op_setcond_i32:
1658 tcg_out_setcond (s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
1659 const_args[2]);
1660 break;
1661 case INDEX_op_setcond_i64:
1662 tcg_out_setcond (s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
1663 const_args[2]);
1664 break;
1665
810260a8 1666 default:
affe5189 1667 tcg_dump_ops (s);
810260a8 1668 tcg_abort ();
1669 }
1670}
1671
1672static const TCGTargetOpDef ppc_op_defs[] = {
1673 { INDEX_op_exit_tb, { } },
1674 { INDEX_op_goto_tb, { } },
1675 { INDEX_op_call, { "ri" } },
810260a8 1676 { INDEX_op_br, { } },
1677
1678 { INDEX_op_mov_i32, { "r", "r" } },
1679 { INDEX_op_mov_i64, { "r", "r" } },
1680 { INDEX_op_movi_i32, { "r" } },
1681 { INDEX_op_movi_i64, { "r" } },
1682
1683 { INDEX_op_ld8u_i32, { "r", "r" } },
1684 { INDEX_op_ld8s_i32, { "r", "r" } },
1685 { INDEX_op_ld16u_i32, { "r", "r" } },
1686 { INDEX_op_ld16s_i32, { "r", "r" } },
1687 { INDEX_op_ld_i32, { "r", "r" } },
1688 { INDEX_op_ld_i64, { "r", "r" } },
1689 { INDEX_op_st8_i32, { "r", "r" } },
1690 { INDEX_op_st8_i64, { "r", "r" } },
1691 { INDEX_op_st16_i32, { "r", "r" } },
1692 { INDEX_op_st16_i64, { "r", "r" } },
1693 { INDEX_op_st_i32, { "r", "r" } },
1694 { INDEX_op_st_i64, { "r", "r" } },
1695 { INDEX_op_st32_i64, { "r", "r" } },
1696
1697 { INDEX_op_ld8u_i64, { "r", "r" } },
1698 { INDEX_op_ld8s_i64, { "r", "r" } },
1699 { INDEX_op_ld16u_i64, { "r", "r" } },
1700 { INDEX_op_ld16s_i64, { "r", "r" } },
1701 { INDEX_op_ld32u_i64, { "r", "r" } },
1702 { INDEX_op_ld32s_i64, { "r", "r" } },
810260a8 1703
1704 { INDEX_op_add_i32, { "r", "r", "ri" } },
1705 { INDEX_op_mul_i32, { "r", "r", "ri" } },
1706 { INDEX_op_div_i32, { "r", "r", "r" } },
1707 { INDEX_op_divu_i32, { "r", "r", "r" } },
1708 { INDEX_op_rem_i32, { "r", "r", "r" } },
1709 { INDEX_op_remu_i32, { "r", "r", "r" } },
148bdd23 1710 { INDEX_op_sub_i32, { "r", "rI", "ri" } },
810260a8 1711 { INDEX_op_and_i32, { "r", "r", "ri" } },
1712 { INDEX_op_or_i32, { "r", "r", "ri" } },
1713 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1714
1715 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1716 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1717 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1718
1719 { INDEX_op_brcond_i32, { "r", "ri" } },
1720 { INDEX_op_brcond_i64, { "r", "ri" } },
1721
1722 { INDEX_op_neg_i32, { "r", "r" } },
157f2662 1723 { INDEX_op_not_i32, { "r", "r" } },
810260a8 1724
ee924fa6 1725 { INDEX_op_add_i64, { "r", "r", "rT" } },
148bdd23 1726 { INDEX_op_sub_i64, { "r", "rI", "rT" } },
3d582c61
RH
1727 { INDEX_op_and_i64, { "r", "r", "rU" } },
1728 { INDEX_op_or_i64, { "r", "r", "rU" } },
1729 { INDEX_op_xor_i64, { "r", "r", "rU" } },
810260a8 1730
fe6f943f 1731 { INDEX_op_shl_i64, { "r", "r", "ri" } },
1732 { INDEX_op_shr_i64, { "r", "r", "ri" } },
1733 { INDEX_op_sar_i64, { "r", "r", "ri" } },
810260a8 1734
1d58ee9f 1735 { INDEX_op_mul_i64, { "r", "r", "r" } },
810260a8 1736 { INDEX_op_div_i64, { "r", "r", "r" } },
1737 { INDEX_op_divu_i64, { "r", "r", "r" } },
1738 { INDEX_op_rem_i64, { "r", "r", "r" } },
1739 { INDEX_op_remu_i64, { "r", "r", "r" } },
1740
1741 { INDEX_op_neg_i64, { "r", "r" } },
157f2662 1742 { INDEX_op_not_i64, { "r", "r" } },
810260a8 1743
1744 { INDEX_op_qemu_ld8u, { "r", "L" } },
1745 { INDEX_op_qemu_ld8s, { "r", "L" } },
1746 { INDEX_op_qemu_ld16u, { "r", "L" } },
1747 { INDEX_op_qemu_ld16s, { "r", "L" } },
86feb1c8 1748 { INDEX_op_qemu_ld32, { "r", "L" } },
810260a8 1749 { INDEX_op_qemu_ld32u, { "r", "L" } },
1750 { INDEX_op_qemu_ld32s, { "r", "L" } },
b01d9fea 1751 { INDEX_op_qemu_ld64, { "r", "L" } },
810260a8 1752
c070355d 1753 { INDEX_op_qemu_st8, { "S", "S" } },
1754 { INDEX_op_qemu_st16, { "S", "S" } },
1755 { INDEX_op_qemu_st32, { "S", "S" } },
016b2b28 1756 { INDEX_op_qemu_st64, { "S", "S" } },
810260a8 1757
e46b9681 1758 { INDEX_op_ext8s_i32, { "r", "r" } },
1759 { INDEX_op_ext16s_i32, { "r", "r" } },
1760 { INDEX_op_ext8s_i64, { "r", "r" } },
1761 { INDEX_op_ext16s_i64, { "r", "r" } },
1762 { INDEX_op_ext32s_i64, { "r", "r" } },
157f2662 1763 { INDEX_op_ext32u_i64, { "r", "r" } },
e46b9681 1764
1cd62ae9 1765 { INDEX_op_setcond_i32, { "r", "r", "ri" } },
1766 { INDEX_op_setcond_i64, { "r", "r", "ri" } },
1767
810260a8 1768 { -1 },
1769};
1770
e4d58b41 1771static void tcg_target_init (TCGContext *s)
810260a8 1772{
1773 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1774 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1775 tcg_regset_set32 (tcg_target_call_clobber_regs, 0,
1776 (1 << TCG_REG_R0) |
5d7ff5bb
AF
1777#ifdef __APPLE__
1778 (1 << TCG_REG_R2) |
1779#endif
810260a8 1780 (1 << TCG_REG_R3) |
1781 (1 << TCG_REG_R4) |
1782 (1 << TCG_REG_R5) |
1783 (1 << TCG_REG_R6) |
1784 (1 << TCG_REG_R7) |
1785 (1 << TCG_REG_R8) |
1786 (1 << TCG_REG_R9) |
1787 (1 << TCG_REG_R10) |
1788 (1 << TCG_REG_R11) |
1789 (1 << TCG_REG_R12)
1790 );
1791
1792 tcg_regset_clear (s->reserved_regs);
1793 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0);
1794 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1);
5d7ff5bb 1795#ifndef __APPLE__
810260a8 1796 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2);
5d7ff5bb 1797#endif
810260a8 1798 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13);
1799
1800 tcg_add_target_add_op_defs (ppc_op_defs);
1801}