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