]> git.proxmox.com Git - qemu.git/blame - tcg/ppc64/tcg-target.c
tcg-ppc64: Use automatic implementation of ext32u_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
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
637af30c 530static bool mask_operand(uint32_t c, int *mb, int *me)
a9249dff
RH
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
637af30c
RH
554static bool mask64_operand(uint64_t c, int *mb, int *me)
555{
556 uint64_t lsb;
557
558 if (c == 0) {
559 return false;
560 }
561
562 lsb = c & -c;
563 /* Accept 1..10..0. */
564 if (c == -lsb) {
565 *mb = 0;
566 *me = clz64(lsb);
567 return true;
568 }
569 /* Accept 0..01..1. */
570 if (lsb == 1 && (c & (c + 1)) == 0) {
571 *mb = clz64(c + 1) + 1;
572 *me = 63;
573 return true;
574 }
575 return false;
576}
577
a9249dff
RH
578static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
579{
580 int mb, me;
581
582 if ((c & 0xffff) == c) {
583 tcg_out32(s, ANDI | SAI(src, dst, c));
584 return;
585 } else if ((c & 0xffff0000) == c) {
586 tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
587 return;
588 } else if (mask_operand(c, &mb, &me)) {
589 tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
590 } else {
591 tcg_out_movi(s, TCG_TYPE_I32, 0, c);
592 tcg_out32(s, AND | SAB(src, dst, 0));
593 }
594}
595
637af30c
RH
596static void tcg_out_andi64(TCGContext *s, TCGReg dst, TCGReg src, uint64_t c)
597{
598 int mb, me;
599
600 if ((c & 0xffff) == c) {
601 tcg_out32(s, ANDI | SAI(src, dst, c));
602 return;
603 } else if ((c & 0xffff0000) == c) {
604 tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
605 return;
606 } else if (mask64_operand(c, &mb, &me)) {
607 if (mb == 0) {
608 tcg_out_rld(s, RLDICR, dst, src, 0, me);
609 } else {
610 tcg_out_rld(s, RLDICL, dst, src, 0, mb);
611 }
612 } else {
613 tcg_out_movi(s, TCG_TYPE_I64, 0, c);
614 tcg_out32(s, AND | SAB(src, dst, 0));
615 }
616}
617
dce74c57
RH
618static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
619 int op_lo, int op_hi)
620{
621 if (c >> 16) {
622 tcg_out32(s, op_hi | SAI(src, dst, c >> 16));
623 src = dst;
624 }
625 if (c & 0xffff) {
626 tcg_out32(s, op_lo | SAI(src, dst, c));
627 src = dst;
628 }
629}
630
631static void tcg_out_ori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
632{
633 tcg_out_zori32(s, dst, src, c, ORI, ORIS);
634}
635
636static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
637{
638 tcg_out_zori32(s, dst, src, c, XORI, XORIS);
639}
640
5d7ff5bb
AF
641static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
642{
643 tcg_target_long disp;
644
645 disp = target - (tcg_target_long) s->code_ptr;
646 if ((disp << 38) >> 38 == disp)
647 tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
648 else {
649 tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target);
650 tcg_out32 (s, MTSPR | RS (0) | CTR);
651 tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
652 }
653}
654
810260a8 655static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
656{
5d7ff5bb
AF
657#ifdef __APPLE__
658 if (const_arg) {
659 tcg_out_b (s, LK, arg);
660 }
661 else {
662 tcg_out32 (s, MTSPR | RS (arg) | LR);
663 tcg_out32 (s, BCLR | BO_ALWAYS | LK);
664 }
665#else
810260a8 666 int reg;
667
668 if (const_arg) {
669 reg = 2;
670 tcg_out_movi (s, TCG_TYPE_I64, reg, arg);
671 }
672 else reg = arg;
673
674 tcg_out32 (s, LD | RT (0) | RA (reg));
675 tcg_out32 (s, MTSPR | RA (0) | CTR);
676 tcg_out32 (s, LD | RT (11) | RA (reg) | 16);
677 tcg_out32 (s, LD | RT (2) | RA (reg) | 8);
678 tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
5d7ff5bb 679#endif
810260a8 680}
681
aceac8d6
RH
682static void tcg_out_ldst(TCGContext *s, TCGReg ret, TCGReg addr,
683 int offset, int op1, int op2)
810260a8 684{
2fd8eddc
RH
685 if (offset == (int16_t) offset) {
686 tcg_out32(s, op1 | TAI(ret, addr, offset));
687 } else {
688 tcg_out_movi(s, TCG_TYPE_I64, 0, offset);
689 tcg_out32(s, op2 | TAB(ret, addr, 0));
810260a8 690 }
691}
692
aceac8d6
RH
693static void tcg_out_ldsta(TCGContext *s, TCGReg ret, TCGReg addr,
694 int offset, int op1, int op2)
828808f5 695{
2fd8eddc
RH
696 if (offset == (int16_t) (offset & ~3)) {
697 tcg_out32(s, op1 | TAI(ret, addr, offset));
698 } else {
699 tcg_out_movi(s, TCG_TYPE_I64, 0, offset);
700 tcg_out32(s, op2 | TAB(ret, addr, 0));
828808f5 701 }
702}
703
810260a8 704#if defined (CONFIG_SOFTMMU)
79383c9c 705
022c62cb 706#include "exec/softmmu_defs.h"
810260a8 707
e141ab52
BS
708/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
709 int mmu_idx) */
710static const void * const qemu_ld_helpers[4] = {
711 helper_ldb_mmu,
712 helper_ldw_mmu,
713 helper_ldl_mmu,
714 helper_ldq_mmu,
715};
716
717/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
718 uintxx_t val, int mmu_idx) */
719static const void * const qemu_st_helpers[4] = {
720 helper_stb_mmu,
721 helper_stw_mmu,
722 helper_stl_mmu,
723 helper_stq_mmu,
724};
810260a8 725
aceac8d6
RH
726static void tcg_out_tlb_read(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
727 TCGReg addr_reg, int s_bits, int offset)
810260a8 728{
880e52b8 729#if TARGET_LONG_BITS == 32
6e5e0602 730 tcg_out_ext32u(s, addr_reg, addr_reg);
810260a8 731
9e555b73
RH
732 tcg_out_rlw(s, RLWINM, r0, addr_reg,
733 32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
734 32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
735 31 - CPU_TLB_ENTRY_BITS);
2fd8eddc
RH
736 tcg_out32(s, ADD | TAB(r0, r0, TCG_AREG0));
737 tcg_out32(s, LWZU | TAI(r1, r0, offset));
9e555b73
RH
738 tcg_out_rlw(s, RLWINM, r2, addr_reg, 0,
739 (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
4a40e231 740#else
810260a8 741 tcg_out_rld (s, RLDICL, r0, addr_reg,
742 64 - TARGET_PAGE_BITS,
743 64 - CPU_TLB_BITS);
0a9564b9 744 tcg_out_shli64(s, r0, r0, CPU_TLB_ENTRY_BITS);
810260a8 745
2fd8eddc
RH
746 tcg_out32(s, ADD | TAB(r0, r0, TCG_AREG0));
747 tcg_out32(s, LD_ADDR | TAI(r1, r0, offset));
810260a8 748
4a40e231 749 if (!s_bits) {
750 tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS);
751 }
752 else {
753 tcg_out_rld (s, RLDICL, r2, addr_reg,
754 64 - TARGET_PAGE_BITS,
755 TARGET_PAGE_BITS - s_bits);
756 tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0);
757 }
758#endif
810260a8 759}
a2a546b3 760#endif
810260a8 761
762static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
763{
aceac8d6
RH
764 TCGReg addr_reg, data_reg, r0, r1, rbase;
765 int bswap;
810260a8 766#ifdef CONFIG_SOFTMMU
aceac8d6
RH
767 TCGReg r2, ir;
768 int mem_index, s_bits;
810260a8 769 void *label1_ptr, *label2_ptr;
770#endif
771
772 data_reg = *args++;
773 addr_reg = *args++;
9df3b45d
DG
774
775#ifdef CONFIG_SOFTMMU
810260a8 776 mem_index = *args;
777 s_bits = opc & 3;
778
810260a8 779 r0 = 3;
780 r1 = 4;
781 r2 = 0;
f6548c0a 782 rbase = 0;
810260a8 783
784 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits,
9349b4f9 785 offsetof (CPUArchState, tlb_table[mem_index][0].addr_read));
810260a8 786
e924bbec 787 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
810260a8 788
789 label1_ptr = s->code_ptr;
790#ifdef FAST_PATH
791 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
792#endif
793
794 /* slow path */
c82e5848 795 ir = 3;
f4f7d01a 796 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
c82e5848
AF
797 tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
798 tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
810260a8 799
800 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
801
802 switch (opc) {
803 case 0|4:
804 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
805 break;
806 case 1|4:
807 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
808 break;
809 case 2|4:
810 tcg_out32 (s, EXTSW | RA (data_reg) | RS (3));
811 break;
812 case 0:
813 case 1:
814 case 2:
815 case 3:
816 if (data_reg != 3)
3b6dac34 817 tcg_out_mov (s, TCG_TYPE_I64, data_reg, 3);
810260a8 818 break;
819 }
820 label2_ptr = s->code_ptr;
821 tcg_out32 (s, B);
822
823 /* label1: fast path */
824#ifdef FAST_PATH
825 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
826#endif
827
828 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
2fd8eddc
RH
829 tcg_out32(s, LD | TAI(r0, r0,
830 offsetof(CPUTLBEntry, addend)
831 - offsetof(CPUTLBEntry, addr_read)));
810260a8 832 /* r0 = env->tlb_table[mem_index][index].addend */
2fd8eddc 833 tcg_out32(s, ADD | TAB(r0, r0, addr_reg));
810260a8 834 /* r0 = env->tlb_table[mem_index][index].addend + addr */
835
836#else /* !CONFIG_SOFTMMU */
0b7c1d89 837#if TARGET_LONG_BITS == 32
6e5e0602 838 tcg_out_ext32u(s, addr_reg, addr_reg);
0b7c1d89 839#endif
810260a8 840 r0 = addr_reg;
735ee40d 841 r1 = 3;
f6548c0a 842 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
810260a8 843#endif
844
845#ifdef TARGET_WORDS_BIGENDIAN
846 bswap = 0;
847#else
848 bswap = 1;
849#endif
850 switch (opc) {
851 default:
852 case 0:
f6548c0a 853 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
810260a8 854 break;
855 case 0|4:
f6548c0a 856 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
810260a8 857 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
858 break;
859 case 1:
f6548c0a 860 if (bswap)
861 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
862 else
863 tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0));
810260a8 864 break;
865 case 1|4:
866 if (bswap) {
f6548c0a 867 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
810260a8 868 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
869 }
f6548c0a 870 else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0));
810260a8 871 break;
872 case 2:
f6548c0a 873 if (bswap)
874 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
875 else
876 tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0));
810260a8 877 break;
878 case 2|4:
879 if (bswap) {
f6548c0a 880 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
450e62e7 881 tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg));
810260a8 882 }
f6548c0a 883 else tcg_out32 (s, LWAX | TAB (data_reg, rbase, r0));
810260a8 884 break;
885 case 3:
f6548c0a 886#ifdef CONFIG_USE_GUEST_BASE
887 if (bswap) {
2fd8eddc 888 tcg_out32(s, ADDI | TAI(r1, r0, 4));
f6548c0a 889 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
890 tcg_out32 (s, LWBRX | TAB ( r1, rbase, r1));
891 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
892 }
893 else tcg_out32 (s, LDX | TAB (data_reg, rbase, r0));
894#else
810260a8 895 if (bswap) {
b1d6d51d 896 tcg_out_movi32 (s, 0, 4);
3ee1b855 897 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
898 tcg_out32 (s, LWBRX | RT ( r1) | RA (r0));
899 tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
810260a8 900 }
901 else tcg_out32 (s, LD | RT (data_reg) | RA (r0));
f6548c0a 902#endif
810260a8 903 break;
904 }
905
906#ifdef CONFIG_SOFTMMU
907 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
908#endif
909}
910
911static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
912{
aceac8d6
RH
913 TCGReg addr_reg, r0, r1, rbase, data_reg;
914 int bswap;
810260a8 915#ifdef CONFIG_SOFTMMU
aceac8d6
RH
916 TCGReg r2, ir;
917 int mem_index;
810260a8 918 void *label1_ptr, *label2_ptr;
919#endif
920
921 data_reg = *args++;
922 addr_reg = *args++;
810260a8 923
924#ifdef CONFIG_SOFTMMU
9df3b45d
DG
925 mem_index = *args;
926
810260a8 927 r0 = 3;
928 r1 = 4;
929 r2 = 0;
f6548c0a 930 rbase = 0;
810260a8 931
932 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc,
9349b4f9 933 offsetof (CPUArchState, tlb_table[mem_index][0].addr_write));
810260a8 934
e924bbec 935 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
810260a8 936
937 label1_ptr = s->code_ptr;
938#ifdef FAST_PATH
939 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
940#endif
941
942 /* slow path */
c82e5848 943 ir = 3;
f4f7d01a 944 tcg_out_mov (s, TCG_TYPE_I64, ir++, TCG_AREG0);
c82e5848
AF
945 tcg_out_mov (s, TCG_TYPE_I64, ir++, addr_reg);
946 tcg_out_rld (s, RLDICL, ir++, data_reg, 0, 64 - (1 << (3 + opc)));
947 tcg_out_movi (s, TCG_TYPE_I64, ir++, mem_index);
810260a8 948
949 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
950
951 label2_ptr = s->code_ptr;
952 tcg_out32 (s, B);
953
954 /* label1: fast path */
955#ifdef FAST_PATH
956 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
957#endif
958
355b1943 959 tcg_out32 (s, (LD
810260a8 960 | RT (r0)
961 | RA (r0)
962 | (offsetof (CPUTLBEntry, addend)
963 - offsetof (CPUTLBEntry, addr_write))
964 ));
965 /* r0 = env->tlb_table[mem_index][index].addend */
2fd8eddc 966 tcg_out32(s, ADD | TAB(r0, r0, addr_reg));
810260a8 967 /* r0 = env->tlb_table[mem_index][index].addend + addr */
968
969#else /* !CONFIG_SOFTMMU */
0b7c1d89 970#if TARGET_LONG_BITS == 32
6e5e0602 971 tcg_out_ext32u(s, addr_reg, addr_reg);
0b7c1d89 972#endif
735ee40d 973 r1 = 3;
810260a8 974 r0 = addr_reg;
f6548c0a 975 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
810260a8 976#endif
977
978#ifdef TARGET_WORDS_BIGENDIAN
979 bswap = 0;
980#else
981 bswap = 1;
982#endif
983 switch (opc) {
984 case 0:
f6548c0a 985 tcg_out32 (s, STBX | SAB (data_reg, rbase, r0));
810260a8 986 break;
987 case 1:
f6548c0a 988 if (bswap)
989 tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0));
990 else
991 tcg_out32 (s, STHX | SAB (data_reg, rbase, r0));
810260a8 992 break;
993 case 2:
f6548c0a 994 if (bswap)
995 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
996 else
997 tcg_out32 (s, STWX | SAB (data_reg, rbase, r0));
810260a8 998 break;
999 case 3:
1000 if (bswap) {
f6548c0a 1001 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
2fd8eddc 1002 tcg_out32(s, ADDI | TAI(r1, r0, 4));
5e916c28 1003 tcg_out_shri64(s, 0, data_reg, 32);
f6548c0a 1004 tcg_out32 (s, STWBRX | SAB (0, rbase, r1));
810260a8 1005 }
f6548c0a 1006 else tcg_out32 (s, STDX | SAB (data_reg, rbase, r0));
810260a8 1007 break;
1008 }
1009
1010#ifdef CONFIG_SOFTMMU
1011 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
1012#endif
1013}
1014
e4d58b41 1015static void tcg_target_qemu_prologue (TCGContext *s)
810260a8 1016{
1017 int i, frame_size;
5d7ff5bb 1018#ifndef __APPLE__
a69abbe0 1019 uint64_t addr;
5d7ff5bb 1020#endif
810260a8 1021
1022 frame_size = 0
1023 + 8 /* back chain */
1024 + 8 /* CR */
1025 + 8 /* LR */
1026 + 8 /* compiler doubleword */
1027 + 8 /* link editor doubleword */
1028 + 8 /* TOC save area */
1029 + TCG_STATIC_CALL_ARGS_SIZE
1030 + ARRAY_SIZE (tcg_target_callee_save_regs) * 8
136a0b5a 1031 + CPU_TEMP_BUF_NLONGS * sizeof(long)
810260a8 1032 ;
1033 frame_size = (frame_size + 15) & ~15;
1034
f6af014e 1035 tcg_set_frame (s, TCG_REG_CALL_STACK, frame_size
1036 - CPU_TEMP_BUF_NLONGS * sizeof (long),
1037 CPU_TEMP_BUF_NLONGS * sizeof (long));
136a0b5a 1038
5d7ff5bb 1039#ifndef __APPLE__
a69abbe0 1040 /* First emit adhoc function descriptor */
1041 addr = (uint64_t) s->code_ptr + 24;
1042 tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */
1043 s->code_ptr += 16; /* skip TOC and environment pointer */
5d7ff5bb 1044#endif
a69abbe0 1045
1046 /* Prologue */
810260a8 1047 tcg_out32 (s, MFSPR | RT (0) | LR);
1048 tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff));
1049 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
1050 tcg_out32 (s, (STD
1051 | RS (tcg_target_callee_save_regs[i])
1052 | RA (1)
1053 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
1054 )
1055 );
e03ae7f9 1056 tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16));
810260a8 1057
f6548c0a 1058#ifdef CONFIG_USE_GUEST_BASE
b9e946c7
RH
1059 if (GUEST_BASE) {
1060 tcg_out_movi (s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE);
f6af014e 1061 tcg_regset_set_reg (s->reserved_regs, TCG_GUEST_BASE_REG);
b9e946c7 1062 }
f6548c0a 1063#endif
1064
cea5f9a2
BS
1065 tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1066 tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
810260a8 1067 tcg_out32 (s, BCCTR | BO_ALWAYS);
a69abbe0 1068
1069 /* Epilogue */
810260a8 1070 tb_ret_addr = s->code_ptr;
1071
1072 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
1073 tcg_out32 (s, (LD
1074 | RT (tcg_target_callee_save_regs[i])
1075 | RA (1)
1076 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
1077 )
1078 );
2fd8eddc
RH
1079 tcg_out32(s, LD | TAI(0, 1, frame_size + 16));
1080 tcg_out32(s, MTSPR | RS(0) | LR);
1081 tcg_out32(s, ADDI | TAI(1, 1, frame_size));
1082 tcg_out32(s, BCLR | BO_ALWAYS);
810260a8 1083}
1084
2a534aff 1085static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
810260a8 1086 tcg_target_long arg2)
1087{
1088 if (type == TCG_TYPE_I32)
1089 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
1090 else
828808f5 1091 tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
810260a8 1092}
1093
2a534aff 1094static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
810260a8 1095 tcg_target_long arg2)
1096{
1097 if (type == TCG_TYPE_I32)
1098 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
1099 else
828808f5 1100 tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX);
810260a8 1101}
1102
810260a8 1103static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
e924bbec 1104 int const_arg2, int cr, int arch64)
810260a8 1105{
1106 int imm;
1107 uint32_t op;
1108
1109 switch (cond) {
1110 case TCG_COND_EQ:
1111 case TCG_COND_NE:
1112 if (const_arg2) {
1113 if ((int16_t) arg2 == arg2) {
1114 op = CMPI;
1115 imm = 1;
1116 break;
1117 }
1118 else if ((uint16_t) arg2 == arg2) {
1119 op = CMPLI;
1120 imm = 1;
1121 break;
1122 }
1123 }
1124 op = CMPL;
1125 imm = 0;
1126 break;
1127
1128 case TCG_COND_LT:
1129 case TCG_COND_GE:
1130 case TCG_COND_LE:
1131 case TCG_COND_GT:
1132 if (const_arg2) {
1133 if ((int16_t) arg2 == arg2) {
1134 op = CMPI;
1135 imm = 1;
1136 break;
1137 }
1138 }
1139 op = CMP;
1140 imm = 0;
1141 break;
1142
1143 case TCG_COND_LTU:
1144 case TCG_COND_GEU:
1145 case TCG_COND_LEU:
1146 case TCG_COND_GTU:
1147 if (const_arg2) {
1148 if ((uint16_t) arg2 == arg2) {
1149 op = CMPLI;
1150 imm = 1;
1151 break;
1152 }
1153 }
1154 op = CMPL;
1155 imm = 0;
1156 break;
1157
1158 default:
1159 tcg_abort ();
1160 }
e924bbec 1161 op |= BF (cr) | (arch64 << 21);
810260a8 1162
1163 if (imm)
1164 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
1165 else {
1166 if (const_arg2) {
1167 tcg_out_movi (s, TCG_TYPE_I64, 0, arg2);
1168 tcg_out32 (s, op | RA (arg1) | RB (0));
1169 }
1170 else
1171 tcg_out32 (s, op | RA (arg1) | RB (arg2));
1172 }
1173
1174}
1175
8a56e840
RH
1176static void tcg_out_setcond (TCGContext *s, TCGType type, TCGCond cond,
1177 TCGArg arg0, TCGArg arg1, TCGArg arg2,
1178 int const_arg2)
1cd62ae9 1179{
1180 int crop, sh, arg;
1181
1182 switch (cond) {
1183 case TCG_COND_EQ:
1184 if (const_arg2) {
1185 if (!arg2) {
1186 arg = arg1;
1187 }
1188 else {
1189 arg = 0;
1190 if ((uint16_t) arg2 == arg2) {
2fd8eddc 1191 tcg_out32(s, XORI | SAI(arg1, 0, arg2));
1cd62ae9 1192 }
1193 else {
1194 tcg_out_movi (s, type, 0, arg2);
1195 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1196 }
1197 }
1198 }
1199 else {
1200 arg = 0;
1201 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1202 }
1203
1204 if (type == TCG_TYPE_I64) {
1205 tcg_out32 (s, CNTLZD | RS (arg) | RA (0));
1206 tcg_out_rld (s, RLDICL, arg0, 0, 58, 6);
1207 }
1208 else {
1209 tcg_out32 (s, CNTLZW | RS (arg) | RA (0));
9e555b73 1210 tcg_out_rlw(s, RLWINM, arg0, 0, 27, 5, 31);
1cd62ae9 1211 }
1212 break;
1213
1214 case TCG_COND_NE:
1215 if (const_arg2) {
1216 if (!arg2) {
1217 arg = arg1;
1218 }
1219 else {
1220 arg = 0;
1221 if ((uint16_t) arg2 == arg2) {
2fd8eddc
RH
1222 tcg_out32(s, XORI | SAI(arg1, 0, arg2));
1223 } else {
1cd62ae9 1224 tcg_out_movi (s, type, 0, arg2);
1225 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1226 }
1227 }
1228 }
1229 else {
1230 arg = 0;
1231 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1232 }
1233
752c1fdb
RH
1234 /* Make sure and discard the high 32-bits of the input. */
1235 if (type == TCG_TYPE_I32) {
1236 tcg_out32(s, EXTSW | RA(TCG_REG_R0) | RS(arg));
1237 arg = TCG_REG_R0;
1238 }
1239
1cd62ae9 1240 if (arg == arg1 && arg1 == arg0) {
2fd8eddc
RH
1241 tcg_out32(s, ADDIC | TAI(0, arg, -1));
1242 tcg_out32(s, SUBFE | TAB(arg0, 0, arg));
1cd62ae9 1243 }
1244 else {
2fd8eddc
RH
1245 tcg_out32(s, ADDIC | TAI(arg0, arg, -1));
1246 tcg_out32(s, SUBFE | TAB(arg0, arg0, arg));
1cd62ae9 1247 }
1248 break;
1249
1250 case TCG_COND_GT:
1251 case TCG_COND_GTU:
1252 sh = 30;
1253 crop = 0;
1254 goto crtest;
1255
1256 case TCG_COND_LT:
1257 case TCG_COND_LTU:
1258 sh = 29;
1259 crop = 0;
1260 goto crtest;
1261
1262 case TCG_COND_GE:
1263 case TCG_COND_GEU:
1264 sh = 31;
1265 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
1266 goto crtest;
1267
1268 case TCG_COND_LE:
1269 case TCG_COND_LEU:
1270 sh = 31;
1271 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
1272 crtest:
1273 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, type == TCG_TYPE_I64);
1274 if (crop) tcg_out32 (s, crop);
1275 tcg_out32 (s, MFCR | RT (0));
9e555b73 1276 tcg_out_rlw(s, RLWINM, arg0, 0, sh, 31, 31);
1cd62ae9 1277 break;
1278
1279 default:
1280 tcg_abort ();
1281 }
1282}
1283
810260a8 1284static void tcg_out_bc (TCGContext *s, int bc, int label_index)
1285{
1286 TCGLabel *l = &s->labels[label_index];
1287
1288 if (l->has_value)
1289 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
1290 else {
1291 uint16_t val = *(uint16_t *) &s->code_ptr[2];
1292
1293 /* Thanks to Andrzej Zaborowski */
1294 tcg_out32 (s, bc | (val & 0xfffc));
1295 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
1296 }
1297}
1298
8a56e840 1299static void tcg_out_brcond (TCGContext *s, TCGCond cond,
810260a8 1300 TCGArg arg1, TCGArg arg2, int const_arg2,
e924bbec 1301 int label_index, int arch64)
810260a8 1302{
e924bbec 1303 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, arch64);
810260a8 1304 tcg_out_bc (s, tcg_to_bc[cond], label_index);
1305}
1306
1307void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
1308{
1309 TCGContext s;
1310 unsigned long patch_size;
1311
1312 s.code_ptr = (uint8_t *) jmp_addr;
1313 tcg_out_b (&s, 0, addr);
1314 patch_size = s.code_ptr - (uint8_t *) jmp_addr;
1315 flush_icache_range (jmp_addr, jmp_addr + patch_size);
1316}
1317
a9751609 1318static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
810260a8 1319 const int *const_args)
1320{
ee924fa6 1321 TCGArg a0, a1, a2;
e46b9681 1322 int c;
1323
810260a8 1324 switch (opc) {
1325 case INDEX_op_exit_tb:
1326 tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
1327 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
1328 break;
1329 case INDEX_op_goto_tb:
1330 if (s->tb_jmp_offset) {
1331 /* direct jump method */
1332
1333 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
5424fd10 1334 s->code_ptr += 28;
810260a8 1335 }
1336 else {
1337 tcg_abort ();
1338 }
1339 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1340 break;
1341 case INDEX_op_br:
1342 {
1343 TCGLabel *l = &s->labels[args[0]];
1344
1345 if (l->has_value) {
1346 tcg_out_b (s, 0, l->u.value);
1347 }
1348 else {
1349 uint32_t val = *(uint32_t *) s->code_ptr;
1350
1351 /* Thanks to Andrzej Zaborowski */
1352 tcg_out32 (s, B | (val & 0x3fffffc));
1353 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1354 }
1355 }
1356 break;
1357 case INDEX_op_call:
1358 tcg_out_call (s, args[0], const_args[0]);
1359 break;
810260a8 1360 case INDEX_op_movi_i32:
1361 tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]);
1362 break;
1363 case INDEX_op_movi_i64:
1364 tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]);
1365 break;
1366 case INDEX_op_ld8u_i32:
1367 case INDEX_op_ld8u_i64:
1368 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1369 break;
1370 case INDEX_op_ld8s_i32:
1371 case INDEX_op_ld8s_i64:
1372 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1373 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1374 break;
1375 case INDEX_op_ld16u_i32:
1376 case INDEX_op_ld16u_i64:
1377 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1378 break;
1379 case INDEX_op_ld16s_i32:
1380 case INDEX_op_ld16s_i64:
1381 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1382 break;
1383 case INDEX_op_ld_i32:
1384 case INDEX_op_ld32u_i64:
1385 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1386 break;
1387 case INDEX_op_ld32s_i64:
828808f5 1388 tcg_out_ldsta (s, args[0], args[1], args[2], LWA, LWAX);
810260a8 1389 break;
1390 case INDEX_op_ld_i64:
828808f5 1391 tcg_out_ldsta (s, args[0], args[1], args[2], LD, LDX);
810260a8 1392 break;
1393 case INDEX_op_st8_i32:
1394 case INDEX_op_st8_i64:
1395 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1396 break;
1397 case INDEX_op_st16_i32:
1398 case INDEX_op_st16_i64:
1399 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1400 break;
1401 case INDEX_op_st_i32:
1402 case INDEX_op_st32_i64:
1403 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1404 break;
1405 case INDEX_op_st_i64:
828808f5 1406 tcg_out_ldsta (s, args[0], args[1], args[2], STD, STDX);
810260a8 1407 break;
1408
1409 case INDEX_op_add_i32:
ee924fa6
RH
1410 a0 = args[0], a1 = args[1], a2 = args[2];
1411 if (const_args[2]) {
1412 int32_t l, h;
1413 do_addi_32:
1414 l = (int16_t)a2;
1415 h = a2 - l;
1416 if (h) {
1417 tcg_out32(s, ADDIS | TAI(a0, a1, h >> 16));
1418 a1 = a0;
1419 }
1420 if (l || a0 != a1) {
1421 tcg_out32(s, ADDI | TAI(a0, a1, l));
1422 }
1423 } else {
1424 tcg_out32(s, ADD | TAB(a0, a1, a2));
1425 }
810260a8 1426 break;
1427 case INDEX_op_sub_i32:
ee924fa6 1428 a0 = args[0], a1 = args[1], a2 = args[2];
148bdd23
RH
1429 if (const_args[1]) {
1430 if (const_args[2]) {
1431 tcg_out_movi(s, TCG_TYPE_I32, a0, a1 - a2);
1432 } else {
1433 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
1434 }
1435 } else if (const_args[2]) {
ee924fa6
RH
1436 a2 = -a2;
1437 goto do_addi_32;
1438 } else {
1439 tcg_out32(s, SUBF | TAB(a0, a2, a1));
1440 }
810260a8 1441 break;
1442
1443 case INDEX_op_and_i32:
a9249dff
RH
1444 if (const_args[2]) {
1445 tcg_out_andi32(s, args[0], args[1], args[2]);
1446 } else {
1447 tcg_out32(s, AND | SAB(args[1], args[0], args[2]));
1448 }
1449 break;
1450 case INDEX_op_and_i64:
810260a8 1451 if (const_args[2]) {
637af30c
RH
1452 tcg_out_andi64(s, args[0], args[1], args[2]);
1453 } else {
1454 tcg_out32(s, AND | SAB(args[1], args[0], args[2]));
810260a8 1455 }
810260a8 1456 break;
fe6f943f 1457 case INDEX_op_or_i64:
810260a8 1458 case INDEX_op_or_i32:
dce74c57 1459 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 1460 if (const_args[2]) {
dce74c57
RH
1461 tcg_out_ori32(s, a0, a1, a2);
1462 } else {
1463 tcg_out32(s, OR | SAB(a1, a0, a2));
810260a8 1464 }
810260a8 1465 break;
fe6f943f 1466 case INDEX_op_xor_i64:
810260a8 1467 case INDEX_op_xor_i32:
dce74c57 1468 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 1469 if (const_args[2]) {
dce74c57
RH
1470 tcg_out_xori32(s, a0, a1, a2);
1471 } else {
1472 tcg_out32(s, XOR | SAB(a1, a0, a2));
810260a8 1473 }
810260a8 1474 break;
1475
1476 case INDEX_op_mul_i32:
1477 if (const_args[2]) {
1478 if (args[2] == (int16_t) args[2])
1479 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1480 | (args[2] & 0xffff));
1481 else {
1482 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1483 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1484 }
1485 }
1486 else
1487 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1488 break;
1489
1490 case INDEX_op_div_i32:
1491 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1492 break;
1493
1494 case INDEX_op_divu_i32:
1495 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1496 break;
1497
1498 case INDEX_op_rem_i32:
1499 tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1500 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1501 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1502 break;
1503
1504 case INDEX_op_remu_i32:
1505 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1506 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1507 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1508 break;
1509
1510 case INDEX_op_shl_i32:
1511 if (const_args[2]) {
9e555b73
RH
1512 tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
1513 } else {
810260a8 1514 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
9e555b73 1515 }
810260a8 1516 break;
1517 case INDEX_op_shr_i32:
1518 if (const_args[2]) {
9e555b73
RH
1519 tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], args[2], 31);
1520 } else {
810260a8 1521 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
9e555b73 1522 }
810260a8 1523 break;
1524 case INDEX_op_sar_i32:
1525 if (const_args[2])
1526 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1527 else
1528 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1529 break;
1530
1531 case INDEX_op_brcond_i32:
e924bbec 1532 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 0);
1533 break;
1534
810260a8 1535 case INDEX_op_brcond_i64:
e924bbec 1536 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 1);
810260a8 1537 break;
1538
1539 case INDEX_op_neg_i32:
810260a8 1540 case INDEX_op_neg_i64:
1541 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1542 break;
1543
157f2662 1544 case INDEX_op_not_i32:
1545 case INDEX_op_not_i64:
1546 tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
1547 break;
1548
810260a8 1549 case INDEX_op_add_i64:
ee924fa6
RH
1550 a0 = args[0], a1 = args[1], a2 = args[2];
1551 if (const_args[2]) {
1552 int32_t l0, h1, h2;
1553 do_addi_64:
1554 /* We can always split any 32-bit signed constant into 3 pieces.
1555 Note the positive 0x80000000 coming from the sub_i64 path,
1556 handled with the same code we need for eg 0x7fff8000. */
1557 assert(a2 == (int32_t)a2 || a2 == 0x80000000);
1558 l0 = (int16_t)a2;
1559 h1 = a2 - l0;
1560 h2 = 0;
1561 if (h1 < 0 && (int64_t)a2 > 0) {
1562 h2 = 0x40000000;
1563 h1 = a2 - h2 - l0;
1564 }
1565 assert((TCGArg)h2 + h1 + l0 == a2);
1566
1567 if (h2) {
1568 tcg_out32(s, ADDIS | TAI(a0, a1, h2 >> 16));
1569 a1 = a0;
1570 }
1571 if (h1) {
1572 tcg_out32(s, ADDIS | TAI(a0, a1, h1 >> 16));
1573 a1 = a0;
1574 }
1575 if (l0 || a0 != a1) {
1576 tcg_out32(s, ADDI | TAI(a0, a1, l0));
1577 }
1578 } else {
1579 tcg_out32(s, ADD | TAB(a0, a1, a2));
1580 }
810260a8 1581 break;
1582 case INDEX_op_sub_i64:
ee924fa6 1583 a0 = args[0], a1 = args[1], a2 = args[2];
148bdd23
RH
1584 if (const_args[1]) {
1585 if (const_args[2]) {
1586 tcg_out_movi(s, TCG_TYPE_I64, a0, a1 - a2);
1587 } else {
1588 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
1589 }
1590 } else if (const_args[2]) {
ee924fa6
RH
1591 a2 = -a2;
1592 goto do_addi_64;
1593 } else {
1594 tcg_out32(s, SUBF | TAB(a0, a2, a1));
1595 }
810260a8 1596 break;
1597
1598 case INDEX_op_shl_i64:
fe6f943f 1599 if (const_args[2])
0a9564b9 1600 tcg_out_shli64(s, args[0], args[1], args[2]);
fe6f943f 1601 else
1602 tcg_out32 (s, SLD | SAB (args[1], args[0], args[2]));
810260a8 1603 break;
1604 case INDEX_op_shr_i64:
fe6f943f 1605 if (const_args[2])
5e916c28 1606 tcg_out_shri64(s, args[0], args[1], args[2]);
fe6f943f 1607 else
1608 tcg_out32 (s, SRD | SAB (args[1], args[0], args[2]));
810260a8 1609 break;
1610 case INDEX_op_sar_i64:
fe6f943f 1611 if (const_args[2]) {
1612 int sh = SH (args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
1613 tcg_out32 (s, SRADI | RA (args[0]) | RS (args[1]) | sh);
1614 }
1615 else
1616 tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2]));
810260a8 1617 break;
1618
1619 case INDEX_op_mul_i64:
1620 tcg_out32 (s, MULLD | TAB (args[0], args[1], args[2]));
1621 break;
1622 case INDEX_op_div_i64:
1623 tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2]));
1624 break;
1625 case INDEX_op_divu_i64:
1626 tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
1627 break;
1628 case INDEX_op_rem_i64:
1629 tcg_out32 (s, DIVD | TAB (0, args[1], args[2]));
1630 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1631 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1632 break;
1633 case INDEX_op_remu_i64:
1634 tcg_out32 (s, DIVDU | TAB (0, args[1], args[2]));
1635 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1636 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1637 break;
1638
1639 case INDEX_op_qemu_ld8u:
1640 tcg_out_qemu_ld (s, args, 0);
1641 break;
1642 case INDEX_op_qemu_ld8s:
1643 tcg_out_qemu_ld (s, args, 0 | 4);
1644 break;
1645 case INDEX_op_qemu_ld16u:
1646 tcg_out_qemu_ld (s, args, 1);
1647 break;
1648 case INDEX_op_qemu_ld16s:
1649 tcg_out_qemu_ld (s, args, 1 | 4);
1650 break;
86feb1c8 1651 case INDEX_op_qemu_ld32:
810260a8 1652 case INDEX_op_qemu_ld32u:
1653 tcg_out_qemu_ld (s, args, 2);
1654 break;
1655 case INDEX_op_qemu_ld32s:
1656 tcg_out_qemu_ld (s, args, 2 | 4);
1657 break;
1658 case INDEX_op_qemu_ld64:
1659 tcg_out_qemu_ld (s, args, 3);
1660 break;
1661 case INDEX_op_qemu_st8:
1662 tcg_out_qemu_st (s, args, 0);
1663 break;
1664 case INDEX_op_qemu_st16:
1665 tcg_out_qemu_st (s, args, 1);
1666 break;
1667 case INDEX_op_qemu_st32:
1668 tcg_out_qemu_st (s, args, 2);
1669 break;
1670 case INDEX_op_qemu_st64:
1671 tcg_out_qemu_st (s, args, 3);
1672 break;
1673
e46b9681 1674 case INDEX_op_ext8s_i32:
1675 case INDEX_op_ext8s_i64:
1676 c = EXTSB;
1677 goto gen_ext;
1678 case INDEX_op_ext16s_i32:
1679 case INDEX_op_ext16s_i64:
1680 c = EXTSH;
1681 goto gen_ext;
1682 case INDEX_op_ext32s_i64:
1683 c = EXTSW;
1684 goto gen_ext;
1685 gen_ext:
1686 tcg_out32 (s, c | RS (args[1]) | RA (args[0]));
1687 break;
1688
1cd62ae9 1689 case INDEX_op_setcond_i32:
1690 tcg_out_setcond (s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
1691 const_args[2]);
1692 break;
1693 case INDEX_op_setcond_i64:
1694 tcg_out_setcond (s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
1695 const_args[2]);
1696 break;
1697
810260a8 1698 default:
affe5189 1699 tcg_dump_ops (s);
810260a8 1700 tcg_abort ();
1701 }
1702}
1703
1704static const TCGTargetOpDef ppc_op_defs[] = {
1705 { INDEX_op_exit_tb, { } },
1706 { INDEX_op_goto_tb, { } },
1707 { INDEX_op_call, { "ri" } },
810260a8 1708 { INDEX_op_br, { } },
1709
1710 { INDEX_op_mov_i32, { "r", "r" } },
1711 { INDEX_op_mov_i64, { "r", "r" } },
1712 { INDEX_op_movi_i32, { "r" } },
1713 { INDEX_op_movi_i64, { "r" } },
1714
1715 { INDEX_op_ld8u_i32, { "r", "r" } },
1716 { INDEX_op_ld8s_i32, { "r", "r" } },
1717 { INDEX_op_ld16u_i32, { "r", "r" } },
1718 { INDEX_op_ld16s_i32, { "r", "r" } },
1719 { INDEX_op_ld_i32, { "r", "r" } },
1720 { INDEX_op_ld_i64, { "r", "r" } },
1721 { INDEX_op_st8_i32, { "r", "r" } },
1722 { INDEX_op_st8_i64, { "r", "r" } },
1723 { INDEX_op_st16_i32, { "r", "r" } },
1724 { INDEX_op_st16_i64, { "r", "r" } },
1725 { INDEX_op_st_i32, { "r", "r" } },
1726 { INDEX_op_st_i64, { "r", "r" } },
1727 { INDEX_op_st32_i64, { "r", "r" } },
1728
1729 { INDEX_op_ld8u_i64, { "r", "r" } },
1730 { INDEX_op_ld8s_i64, { "r", "r" } },
1731 { INDEX_op_ld16u_i64, { "r", "r" } },
1732 { INDEX_op_ld16s_i64, { "r", "r" } },
1733 { INDEX_op_ld32u_i64, { "r", "r" } },
1734 { INDEX_op_ld32s_i64, { "r", "r" } },
810260a8 1735
1736 { INDEX_op_add_i32, { "r", "r", "ri" } },
1737 { INDEX_op_mul_i32, { "r", "r", "ri" } },
1738 { INDEX_op_div_i32, { "r", "r", "r" } },
1739 { INDEX_op_divu_i32, { "r", "r", "r" } },
1740 { INDEX_op_rem_i32, { "r", "r", "r" } },
1741 { INDEX_op_remu_i32, { "r", "r", "r" } },
148bdd23 1742 { INDEX_op_sub_i32, { "r", "rI", "ri" } },
810260a8 1743 { INDEX_op_and_i32, { "r", "r", "ri" } },
1744 { INDEX_op_or_i32, { "r", "r", "ri" } },
1745 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1746
1747 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1748 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1749 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1750
1751 { INDEX_op_brcond_i32, { "r", "ri" } },
1752 { INDEX_op_brcond_i64, { "r", "ri" } },
1753
1754 { INDEX_op_neg_i32, { "r", "r" } },
157f2662 1755 { INDEX_op_not_i32, { "r", "r" } },
810260a8 1756
ee924fa6 1757 { INDEX_op_add_i64, { "r", "r", "rT" } },
148bdd23 1758 { INDEX_op_sub_i64, { "r", "rI", "rT" } },
3d582c61
RH
1759 { INDEX_op_and_i64, { "r", "r", "rU" } },
1760 { INDEX_op_or_i64, { "r", "r", "rU" } },
1761 { INDEX_op_xor_i64, { "r", "r", "rU" } },
810260a8 1762
fe6f943f 1763 { INDEX_op_shl_i64, { "r", "r", "ri" } },
1764 { INDEX_op_shr_i64, { "r", "r", "ri" } },
1765 { INDEX_op_sar_i64, { "r", "r", "ri" } },
810260a8 1766
1d58ee9f 1767 { INDEX_op_mul_i64, { "r", "r", "r" } },
810260a8 1768 { INDEX_op_div_i64, { "r", "r", "r" } },
1769 { INDEX_op_divu_i64, { "r", "r", "r" } },
1770 { INDEX_op_rem_i64, { "r", "r", "r" } },
1771 { INDEX_op_remu_i64, { "r", "r", "r" } },
1772
1773 { INDEX_op_neg_i64, { "r", "r" } },
157f2662 1774 { INDEX_op_not_i64, { "r", "r" } },
810260a8 1775
1776 { INDEX_op_qemu_ld8u, { "r", "L" } },
1777 { INDEX_op_qemu_ld8s, { "r", "L" } },
1778 { INDEX_op_qemu_ld16u, { "r", "L" } },
1779 { INDEX_op_qemu_ld16s, { "r", "L" } },
86feb1c8 1780 { INDEX_op_qemu_ld32, { "r", "L" } },
810260a8 1781 { INDEX_op_qemu_ld32u, { "r", "L" } },
1782 { INDEX_op_qemu_ld32s, { "r", "L" } },
b01d9fea 1783 { INDEX_op_qemu_ld64, { "r", "L" } },
810260a8 1784
c070355d 1785 { INDEX_op_qemu_st8, { "S", "S" } },
1786 { INDEX_op_qemu_st16, { "S", "S" } },
1787 { INDEX_op_qemu_st32, { "S", "S" } },
016b2b28 1788 { INDEX_op_qemu_st64, { "S", "S" } },
810260a8 1789
e46b9681 1790 { INDEX_op_ext8s_i32, { "r", "r" } },
1791 { INDEX_op_ext16s_i32, { "r", "r" } },
1792 { INDEX_op_ext8s_i64, { "r", "r" } },
1793 { INDEX_op_ext16s_i64, { "r", "r" } },
1794 { INDEX_op_ext32s_i64, { "r", "r" } },
1795
1cd62ae9 1796 { INDEX_op_setcond_i32, { "r", "r", "ri" } },
1797 { INDEX_op_setcond_i64, { "r", "r", "ri" } },
1798
810260a8 1799 { -1 },
1800};
1801
e4d58b41 1802static void tcg_target_init (TCGContext *s)
810260a8 1803{
1804 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1805 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1806 tcg_regset_set32 (tcg_target_call_clobber_regs, 0,
1807 (1 << TCG_REG_R0) |
5d7ff5bb
AF
1808#ifdef __APPLE__
1809 (1 << TCG_REG_R2) |
1810#endif
810260a8 1811 (1 << TCG_REG_R3) |
1812 (1 << TCG_REG_R4) |
1813 (1 << TCG_REG_R5) |
1814 (1 << TCG_REG_R6) |
1815 (1 << TCG_REG_R7) |
1816 (1 << TCG_REG_R8) |
1817 (1 << TCG_REG_R9) |
1818 (1 << TCG_REG_R10) |
1819 (1 << TCG_REG_R11) |
1820 (1 << TCG_REG_R12)
1821 );
1822
1823 tcg_regset_clear (s->reserved_regs);
1824 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0);
1825 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1);
5d7ff5bb 1826#ifndef __APPLE__
810260a8 1827 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2);
5d7ff5bb 1828#endif
810260a8 1829 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13);
1830
1831 tcg_add_target_add_op_defs (ppc_op_defs);
1832}