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