Fix preprocessor guard condition
[qemu/mini2440.git] / tcg / ppc64 / tcg-target.c
blob4d1d1ec2bb4a79b559792ff6cc20613a6713b29b
1 /*
2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
25 static uint8_t *tb_ret_addr;
27 #define FAST_PATH
29 #if TARGET_PHYS_ADDR_BITS == 32
30 #define LD_ADDEND LWZ
31 #else
32 #define LD_ADDEND LD
33 #endif
35 #if TARGET_LONG_BITS == 32
36 #define LD_ADDR LWZU
37 #else
38 #define LD_ADDR LDU
39 #endif
41 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
42 "r0",
43 "r1",
44 "rp",
45 "r3",
46 "r4",
47 "r5",
48 "r6",
49 "r7",
50 "r8",
51 "r9",
52 "r10",
53 "r11",
54 "r12",
55 "r13",
56 "r14",
57 "r15",
58 "r16",
59 "r17",
60 "r18",
61 "r19",
62 "r20",
63 "r21",
64 "r22",
65 "r23",
66 "r24",
67 "r25",
68 "r26",
69 "r27",
70 "r28",
71 "r29",
72 "r30",
73 "r31"
76 static const int tcg_target_reg_alloc_order[] = {
77 TCG_REG_R14,
78 TCG_REG_R15,
79 TCG_REG_R16,
80 TCG_REG_R17,
81 TCG_REG_R18,
82 TCG_REG_R19,
83 TCG_REG_R20,
84 TCG_REG_R21,
85 TCG_REG_R22,
86 TCG_REG_R23,
87 TCG_REG_R28,
88 TCG_REG_R29,
89 TCG_REG_R30,
90 TCG_REG_R31,
91 TCG_REG_R3,
92 TCG_REG_R4,
93 TCG_REG_R5,
94 TCG_REG_R6,
95 TCG_REG_R7,
96 TCG_REG_R8,
97 TCG_REG_R9,
98 TCG_REG_R10,
99 TCG_REG_R11,
100 TCG_REG_R12,
101 TCG_REG_R13,
102 TCG_REG_R0,
103 TCG_REG_R1,
104 TCG_REG_R2,
105 TCG_REG_R24,
106 TCG_REG_R25,
107 TCG_REG_R26,
108 TCG_REG_R27
111 static const int tcg_target_call_iarg_regs[] = {
112 TCG_REG_R3,
113 TCG_REG_R4,
114 TCG_REG_R5,
115 TCG_REG_R6,
116 TCG_REG_R7,
117 TCG_REG_R8,
118 TCG_REG_R9,
119 TCG_REG_R10
122 static const int tcg_target_call_oarg_regs[2] = {
123 TCG_REG_R3
126 static const int tcg_target_callee_save_regs[] = {
127 TCG_REG_R14,
128 TCG_REG_R15,
129 TCG_REG_R16,
130 TCG_REG_R17,
131 TCG_REG_R18,
132 TCG_REG_R19,
133 TCG_REG_R20,
134 TCG_REG_R21,
135 TCG_REG_R22,
136 TCG_REG_R23,
137 TCG_REG_R28,
138 TCG_REG_R29,
139 TCG_REG_R30,
140 TCG_REG_R31
143 static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
145 tcg_target_long disp;
147 disp = target - (tcg_target_long) pc;
148 if ((disp << 38) >> 38 != disp)
149 tcg_abort ();
151 return disp & 0x3fffffc;
154 static void reloc_pc24 (void *pc, tcg_target_long target)
156 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
157 | reloc_pc24_val (pc, target);
160 static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
162 tcg_target_long disp;
164 disp = target - (tcg_target_long) pc;
165 if (disp != (int16_t) disp)
166 tcg_abort ();
168 return disp & 0xfffc;
171 static void reloc_pc14 (void *pc, tcg_target_long target)
173 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
174 | reloc_pc14_val (pc, target);
177 static void patch_reloc (uint8_t *code_ptr, int type,
178 tcg_target_long value, tcg_target_long addend)
180 value += addend;
181 switch (type) {
182 case R_PPC_REL14:
183 reloc_pc14 (code_ptr, value);
184 break;
185 case R_PPC_REL24:
186 reloc_pc24 (code_ptr, value);
187 break;
188 default:
189 tcg_abort ();
193 /* maximum number of register used for input function arguments */
194 static int tcg_target_get_call_iarg_regs_count (int flags)
196 return sizeof (tcg_target_call_iarg_regs) / sizeof (tcg_target_call_iarg_regs[0]);
199 /* parse target specific constraints */
200 static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str)
202 const char *ct_str;
204 ct_str = *pct_str;
205 switch (ct_str[0]) {
206 case 'A': case 'B': case 'C': case 'D':
207 ct->ct |= TCG_CT_REG;
208 tcg_regset_set_reg (ct->u.regs, 3 + ct_str[0] - 'A');
209 break;
210 case 'r':
211 ct->ct |= TCG_CT_REG;
212 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
213 break;
214 case 'L': /* qemu_ld constraint */
215 ct->ct |= TCG_CT_REG;
216 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
217 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
218 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
219 break;
220 case 'S': /* qemu_st constraint */
221 ct->ct |= TCG_CT_REG;
222 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
223 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
224 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
225 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5);
226 break;
227 default:
228 return -1;
230 ct_str++;
231 *pct_str = ct_str;
232 return 0;
235 /* test if a constant matches the constraint */
236 static int tcg_target_const_match (tcg_target_long val,
237 const TCGArgConstraint *arg_ct)
239 int ct;
241 ct = arg_ct->ct;
242 if (ct & TCG_CT_CONST)
243 return 1;
244 return 0;
247 #define OPCD(opc) ((opc)<<26)
248 #define XO19(opc) (OPCD(19)|((opc)<<1))
249 #define XO30(opc) (OPCD(30)|((opc)<<2))
250 #define XO31(opc) (OPCD(31)|((opc)<<1))
251 #define XO58(opc) (OPCD(58)|(opc))
252 #define XO62(opc) (OPCD(62)|(opc))
254 #define B OPCD( 18)
255 #define BC OPCD( 16)
256 #define LBZ OPCD( 34)
257 #define LHZ OPCD( 40)
258 #define LHA OPCD( 42)
259 #define LWZ OPCD( 32)
260 #define STB OPCD( 38)
261 #define STH OPCD( 44)
262 #define STW OPCD( 36)
264 #define STD XO62( 0)
265 #define STDU XO62( 1)
266 #define STDX XO31(149)
268 #define LD XO58( 0)
269 #define LDX XO31( 21)
270 #define LDU XO58( 1)
271 #define LWA XO58( 2)
272 #define LWAX XO31(341)
274 #define ADDI OPCD( 14)
275 #define ADDIS OPCD( 15)
276 #define ORI OPCD( 24)
277 #define ORIS OPCD( 25)
278 #define XORI OPCD( 26)
279 #define XORIS OPCD( 27)
280 #define ANDI OPCD( 28)
281 #define ANDIS OPCD( 29)
282 #define MULLI OPCD( 7)
283 #define CMPLI OPCD( 10)
284 #define CMPI OPCD( 11)
286 #define LWZU OPCD( 33)
287 #define STWU OPCD( 37)
289 #define RLWINM OPCD( 21)
291 #define RLDICL XO30( 0)
292 #define RLDICR XO30( 1)
294 #define BCLR XO19( 16)
295 #define BCCTR XO19(528)
296 #define CRAND XO19(257)
297 #define CRANDC XO19(129)
298 #define CRNAND XO19(225)
299 #define CROR XO19(449)
301 #define EXTSB XO31(954)
302 #define EXTSH XO31(922)
303 #define EXTSW XO31(986)
304 #define ADD XO31(266)
305 #define ADDE XO31(138)
306 #define ADDC XO31( 10)
307 #define AND XO31( 28)
308 #define SUBF XO31( 40)
309 #define SUBFC XO31( 8)
310 #define SUBFE XO31(136)
311 #define OR XO31(444)
312 #define XOR XO31(316)
313 #define MULLW XO31(235)
314 #define MULHWU XO31( 11)
315 #define DIVW XO31(491)
316 #define DIVWU XO31(459)
317 #define CMP XO31( 0)
318 #define CMPL XO31( 32)
319 #define LHBRX XO31(790)
320 #define LWBRX XO31(534)
321 #define STHBRX XO31(918)
322 #define STWBRX XO31(662)
323 #define MFSPR XO31(339)
324 #define MTSPR XO31(467)
325 #define SRAWI XO31(824)
326 #define NEG XO31(104)
328 #define MULLD XO31(233)
329 #define MULHD XO31( 73)
330 #define MULHDU XO31( 9)
331 #define DIVD XO31(489)
332 #define DIVDU XO31(457)
334 #define LBZX XO31( 87)
335 #define LHZX XO31(276)
336 #define LHAX XO31(343)
337 #define LWZX XO31( 23)
338 #define STBX XO31(215)
339 #define STHX XO31(407)
340 #define STWX XO31(151)
342 #define SPR(a,b) ((((a)<<5)|(b))<<11)
343 #define LR SPR(8, 0)
344 #define CTR SPR(9, 0)
346 #define SLW XO31( 24)
347 #define SRW XO31(536)
348 #define SRAW XO31(792)
350 #define SLD XO31( 27)
351 #define SRD XO31(539)
352 #define SRAD XO31(794)
354 #define LMW OPCD( 46)
355 #define STMW OPCD( 47)
357 #define TW XO31( 4)
358 #define TRAP (TW | TO (31))
360 #define RT(r) ((r)<<21)
361 #define RS(r) ((r)<<21)
362 #define RA(r) ((r)<<16)
363 #define RB(r) ((r)<<11)
364 #define TO(t) ((t)<<21)
365 #define SH(s) ((s)<<11)
366 #define MB(b) ((b)<<6)
367 #define ME(e) ((e)<<1)
368 #define BO(o) ((o)<<21)
369 #define MB64(b) ((b)<<5)
371 #define LK 1
373 #define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
374 #define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
376 #define BF(n) ((n)<<23)
377 #define BI(n, c) (((c)+((n)*4))<<16)
378 #define BT(n, c) (((c)+((n)*4))<<21)
379 #define BA(n, c) (((c)+((n)*4))<<16)
380 #define BB(n, c) (((c)+((n)*4))<<11)
382 #define BO_COND_TRUE BO (12)
383 #define BO_COND_FALSE BO ( 4)
384 #define BO_ALWAYS BO (20)
386 enum {
387 CR_LT,
388 CR_GT,
389 CR_EQ,
390 CR_SO
393 static const uint32_t tcg_to_bc[10] = {
394 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
395 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
396 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
397 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
398 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
399 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
400 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
401 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
402 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
403 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
406 static void tcg_out_mov (TCGContext *s, int ret, int arg)
408 tcg_out32 (s, OR | SAB (arg, ret, arg));
411 static void tcg_out_rld (TCGContext *s, int op, int ra, int rs, int sh, int mb)
413 sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1);
414 mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f));
415 tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb);
418 static void tcg_out_movi32 (TCGContext *s, int ret, int32_t arg)
420 if (arg == (int16_t) arg)
421 tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
422 else {
423 tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
424 if (arg & 0xffff)
425 tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
429 static void tcg_out_movi (TCGContext *s, TCGType type,
430 int ret, tcg_target_long arg)
432 int32_t arg32 = arg;
434 if (type == TCG_TYPE_I32 || arg == arg32) {
435 tcg_out_movi32 (s, ret, arg32);
437 else {
438 if ((uint64_t) arg >> 32) {
439 uint16_t h16 = arg >> 16;
440 uint16_t l16 = arg;
442 tcg_out_movi32 (s, ret, arg >> 32);
443 tcg_out_rld (s, RLDICR, ret, ret, 32, 31);
444 if (h16) tcg_out32 (s, ORIS | RS (ret) | RA (ret) | h16);
445 if (l16) tcg_out32 (s, ORI | RS (ret) | RA (ret) | l16);
447 else {
448 tcg_out_movi32 (s, ret, arg32);
449 if (arg32 < 0)
450 tcg_out_rld (s, RLDICL, ret, ret, 0, 32);
455 static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
457 int reg;
459 if (const_arg) {
460 reg = 2;
461 tcg_out_movi (s, TCG_TYPE_I64, reg, arg);
463 else reg = arg;
465 tcg_out32 (s, LD | RT (0) | RA (reg));
466 tcg_out32 (s, MTSPR | RA (0) | CTR);
467 tcg_out32 (s, LD | RT (11) | RA (reg) | 16);
468 tcg_out32 (s, LD | RT (2) | RA (reg) | 8);
469 tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
472 static void tcg_out_ldst (TCGContext *s, int ret, int addr,
473 int offset, int op1, int op2)
475 if (offset == (int16_t) offset)
476 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
477 else {
478 tcg_out_movi (s, TCG_TYPE_I64, 0, offset);
479 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
483 static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
485 tcg_target_long disp;
487 disp = target - (tcg_target_long) s->code_ptr;
488 if ((disp << 38) >> 38 == disp)
489 tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
490 else {
491 tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target);
492 tcg_out32 (s, MTSPR | RS (0) | CTR);
493 tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
497 #if defined (CONFIG_SOFTMMU)
498 extern void __ldb_mmu(void);
499 extern void __ldw_mmu(void);
500 extern void __ldl_mmu(void);
501 extern void __ldq_mmu(void);
503 extern void __stb_mmu(void);
504 extern void __stw_mmu(void);
505 extern void __stl_mmu(void);
506 extern void __stq_mmu(void);
508 static void *qemu_ld_helpers[4] = {
509 __ldb_mmu,
510 __ldw_mmu,
511 __ldl_mmu,
512 __ldq_mmu,
515 static void *qemu_st_helpers[4] = {
516 __stb_mmu,
517 __stw_mmu,
518 __stl_mmu,
519 __stq_mmu,
521 #endif
523 static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2,
524 int addr_reg, int s_bits, int offset)
526 #if TARGET_LONG_BITS == 32
527 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32);
529 tcg_out32 (s, (RLWINM
530 | RA (r0)
531 | RS (addr_reg)
532 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
533 | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
534 | ME (31 - CPU_TLB_ENTRY_BITS)
537 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
538 tcg_out32 (s, (LWZU | RT (r1) | RA (r0) | offset));
539 tcg_out32 (s, (RLWINM
540 | RA (r2)
541 | RS (addr_reg)
542 | SH (0)
543 | MB ((32 - s_bits) & 31)
544 | ME (31 - TARGET_PAGE_BITS)
547 #else
548 tcg_out_rld (s, RLDICL, r0, addr_reg,
549 64 - TARGET_PAGE_BITS,
550 64 - CPU_TLB_BITS);
551 tcg_out_rld (s, RLDICR, r0, r0,
552 CPU_TLB_ENTRY_BITS,
553 63 - CPU_TLB_ENTRY_BITS);
555 tcg_out32 (s, ADD | TAB (r0, r0, TCG_AREG0));
556 tcg_out32 (s, LD_ADDR | RT (r1) | RA (r0) | offset);
558 if (!s_bits) {
559 tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS);
561 else {
562 tcg_out_rld (s, RLDICL, r2, addr_reg,
563 64 - TARGET_PAGE_BITS,
564 TARGET_PAGE_BITS - s_bits);
565 tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0);
567 #endif
570 static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
572 int addr_reg, data_reg, r0, mem_index, s_bits, bswap;
573 #ifdef CONFIG_SOFTMMU
574 int r1, r2;
575 void *label1_ptr, *label2_ptr;
576 #endif
578 data_reg = *args++;
579 addr_reg = *args++;
580 mem_index = *args;
581 s_bits = opc & 3;
583 #ifdef CONFIG_SOFTMMU
584 r0 = 3;
585 r1 = 4;
586 r2 = 0;
588 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits,
589 offsetof (CPUState, tlb_table[mem_index][0].addr_read));
591 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
593 label1_ptr = s->code_ptr;
594 #ifdef FAST_PATH
595 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
596 #endif
598 /* slow path */
599 tcg_out_mov (s, 3, addr_reg);
600 tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index);
602 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
604 switch (opc) {
605 case 0|4:
606 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
607 break;
608 case 1|4:
609 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
610 break;
611 case 2|4:
612 tcg_out32 (s, EXTSW | RA (data_reg) | RS (3));
613 break;
614 case 0:
615 case 1:
616 case 2:
617 case 3:
618 if (data_reg != 3)
619 tcg_out_mov (s, data_reg, 3);
620 break;
622 label2_ptr = s->code_ptr;
623 tcg_out32 (s, B);
625 /* label1: fast path */
626 #ifdef FAST_PATH
627 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
628 #endif
630 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
631 tcg_out32 (s, (LD_ADDEND
632 | RT (r0)
633 | RA (r0)
634 | (offsetof (CPUTLBEntry, addend)
635 - offsetof (CPUTLBEntry, addr_read))
637 /* r0 = env->tlb_table[mem_index][index].addend */
638 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
639 /* r0 = env->tlb_table[mem_index][index].addend + addr */
641 #else /* !CONFIG_SOFTMMU */
642 r0 = addr_reg;
643 #endif
645 #ifdef TARGET_WORDS_BIGENDIAN
646 bswap = 0;
647 #else
648 bswap = 1;
649 #endif
650 switch (opc) {
651 default:
652 case 0:
653 tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
654 break;
655 case 0|4:
656 tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
657 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
658 break;
659 case 1:
660 if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
661 else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0));
662 break;
663 case 1|4:
664 if (bswap) {
665 tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
666 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
668 else tcg_out32 (s, LHA | RT (data_reg) | RA (r0));
669 break;
670 case 2:
671 if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
672 else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0));
673 break;
674 case 2|4:
675 if (bswap) {
676 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
677 tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg));
679 else tcg_out32 (s, LWA | RT (data_reg)| RA (r0));
680 break;
681 case 3:
682 if (bswap) {
683 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
684 tcg_out32 (s, ADDI | RT (r0) | RA (r0) | 4);
685 tcg_out32 (s, LWBRX | RT (r0) | RB (r0));
686 tcg_out_rld (s, RLDICR, r0, r0, 32, 31);
687 tcg_out32 (s, OR | SAB (r0, data_reg, data_reg));
689 else tcg_out32 (s, LD | RT (data_reg) | RA (r0));
690 break;
693 #ifdef CONFIG_SOFTMMU
694 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
695 #endif
698 static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
700 int addr_reg, r0, r1, data_reg, mem_index, bswap;
701 #ifdef CONFIG_SOFTMMU
702 int r2;
703 void *label1_ptr, *label2_ptr;
704 #endif
706 data_reg = *args++;
707 addr_reg = *args++;
708 mem_index = *args;
710 #ifdef CONFIG_SOFTMMU
711 r0 = 3;
712 r1 = 4;
713 r2 = 0;
715 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc,
716 offsetof (CPUState, tlb_table[mem_index][0].addr_write));
718 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
720 label1_ptr = s->code_ptr;
721 #ifdef FAST_PATH
722 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
723 #endif
725 /* slow path */
726 tcg_out_mov (s, 3, addr_reg);
727 tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc)));
728 tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index);
730 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
732 label2_ptr = s->code_ptr;
733 tcg_out32 (s, B);
735 /* label1: fast path */
736 #ifdef FAST_PATH
737 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
738 #endif
740 tcg_out32 (s, (LD_ADDEND
741 | RT (r0)
742 | RA (r0)
743 | (offsetof (CPUTLBEntry, addend)
744 - offsetof (CPUTLBEntry, addr_write))
746 /* r0 = env->tlb_table[mem_index][index].addend */
747 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
748 /* r0 = env->tlb_table[mem_index][index].addend + addr */
750 #else /* !CONFIG_SOFTMMU */
751 r1 = 4;
752 r0 = addr_reg;
753 #endif
755 #ifdef TARGET_WORDS_BIGENDIAN
756 bswap = 0;
757 #else
758 bswap = 1;
759 #endif
760 switch (opc) {
761 case 0:
762 tcg_out32 (s, STB | RS (data_reg) | RA (r0));
763 break;
764 case 1:
765 if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0));
766 else tcg_out32 (s, STH | RS (data_reg) | RA (r0));
767 break;
768 case 2:
769 if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
770 else tcg_out32 (s, STW | RS (data_reg) | RA (r0));
771 break;
772 case 3:
773 if (bswap) {
774 tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
775 tcg_out32 (s, ADDI | RT (r0) | RA (r0) | 4);
776 tcg_out_rld (s, RLDICL, 0, data_reg, 32, 0);
777 tcg_out32 (s, STWBRX | RS (0) | RA (0) | RB (r0));
779 else tcg_out32 (s, STD | RS (data_reg) | RA (r0));
780 break;
783 #ifdef CONFIG_SOFTMMU
784 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
785 #endif
788 void tcg_target_qemu_prologue (TCGContext *s)
790 int i, frame_size;
791 uint64_t addr;
793 frame_size = 0
794 + 8 /* back chain */
795 + 8 /* CR */
796 + 8 /* LR */
797 + 8 /* compiler doubleword */
798 + 8 /* link editor doubleword */
799 + 8 /* TOC save area */
800 + TCG_STATIC_CALL_ARGS_SIZE
801 + ARRAY_SIZE (tcg_target_callee_save_regs) * 8
803 frame_size = (frame_size + 15) & ~15;
805 /* First emit adhoc function descriptor */
806 addr = (uint64_t) s->code_ptr + 24;
807 tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */
808 s->code_ptr += 16; /* skip TOC and environment pointer */
810 /* Prologue */
811 tcg_out32 (s, MFSPR | RT (0) | LR);
812 tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff));
813 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
814 tcg_out32 (s, (STD
815 | RS (tcg_target_callee_save_regs[i])
816 | RA (1)
817 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
820 tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16));
822 tcg_out32 (s, MTSPR | RS (3) | CTR);
823 tcg_out32 (s, BCCTR | BO_ALWAYS);
825 /* Epilogue */
826 tb_ret_addr = s->code_ptr;
828 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
829 tcg_out32 (s, (LD
830 | RT (tcg_target_callee_save_regs[i])
831 | RA (1)
832 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
835 tcg_out32 (s, LD | RT (0) | RA (1) | (frame_size + 16));
836 tcg_out32 (s, MTSPR | RS (0) | LR);
837 tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
838 tcg_out32 (s, BCLR | BO_ALWAYS);
841 static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
842 tcg_target_long arg2)
844 if (type == TCG_TYPE_I32)
845 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
846 else
847 tcg_out_ldst (s, ret, arg1, arg2, LD, LDX);
850 static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
851 tcg_target_long arg2)
853 if (type == TCG_TYPE_I32)
854 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
855 else
856 tcg_out_ldst (s, arg, arg1, arg2, STD, STDX);
859 static void ppc_addi32 (TCGContext *s, int rt, int ra, tcg_target_long si)
861 if (!si && rt == ra)
862 return;
864 if (si == (int16_t) si)
865 tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
866 else {
867 uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
868 tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
869 tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
873 static void ppc_addi64 (TCGContext *s, int rt, int ra, tcg_target_long si)
875 tcg_out_movi (s, TCG_TYPE_I64, 0, si);
876 tcg_out32 (s, ADD | RT (rt) | RA (ra));
879 static void tcg_out_addi (TCGContext *s, int reg, tcg_target_long val)
881 ppc_addi64 (s, reg, reg, val);
884 static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
885 int const_arg2, int cr)
887 int imm;
888 uint32_t op;
890 switch (cond) {
891 case TCG_COND_EQ:
892 case TCG_COND_NE:
893 if (const_arg2) {
894 if ((int16_t) arg2 == arg2) {
895 op = CMPI;
896 imm = 1;
897 break;
899 else if ((uint16_t) arg2 == arg2) {
900 op = CMPLI;
901 imm = 1;
902 break;
905 op = CMPL;
906 imm = 0;
907 break;
909 case TCG_COND_LT:
910 case TCG_COND_GE:
911 case TCG_COND_LE:
912 case TCG_COND_GT:
913 if (const_arg2) {
914 if ((int16_t) arg2 == arg2) {
915 op = CMPI;
916 imm = 1;
917 break;
920 op = CMP;
921 imm = 0;
922 break;
924 case TCG_COND_LTU:
925 case TCG_COND_GEU:
926 case TCG_COND_LEU:
927 case TCG_COND_GTU:
928 if (const_arg2) {
929 if ((uint16_t) arg2 == arg2) {
930 op = CMPLI;
931 imm = 1;
932 break;
935 op = CMPL;
936 imm = 0;
937 break;
939 default:
940 tcg_abort ();
942 op |= BF (cr);
944 if (imm)
945 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
946 else {
947 if (const_arg2) {
948 tcg_out_movi (s, TCG_TYPE_I64, 0, arg2);
949 tcg_out32 (s, op | RA (arg1) | RB (0));
951 else
952 tcg_out32 (s, op | RA (arg1) | RB (arg2));
957 static void tcg_out_bc (TCGContext *s, int bc, int label_index)
959 TCGLabel *l = &s->labels[label_index];
961 if (l->has_value)
962 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
963 else {
964 uint16_t val = *(uint16_t *) &s->code_ptr[2];
966 /* Thanks to Andrzej Zaborowski */
967 tcg_out32 (s, bc | (val & 0xfffc));
968 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
972 static void tcg_out_brcond (TCGContext *s, int cond,
973 TCGArg arg1, TCGArg arg2, int const_arg2,
974 int label_index)
976 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
977 tcg_out_bc (s, tcg_to_bc[cond], label_index);
980 void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
982 TCGContext s;
983 unsigned long patch_size;
985 s.code_ptr = (uint8_t *) jmp_addr;
986 tcg_out_b (&s, 0, addr);
987 patch_size = s.code_ptr - (uint8_t *) jmp_addr;
988 flush_icache_range (jmp_addr, jmp_addr + patch_size);
991 static void tcg_out_op (TCGContext *s, int opc, const TCGArg *args,
992 const int *const_args)
994 int c;
996 switch (opc) {
997 case INDEX_op_exit_tb:
998 tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
999 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
1000 break;
1001 case INDEX_op_goto_tb:
1002 if (s->tb_jmp_offset) {
1003 /* direct jump method */
1005 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1006 s->code_ptr += 28;
1008 else {
1009 tcg_abort ();
1011 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1012 break;
1013 case INDEX_op_br:
1015 TCGLabel *l = &s->labels[args[0]];
1017 if (l->has_value) {
1018 tcg_out_b (s, 0, l->u.value);
1020 else {
1021 uint32_t val = *(uint32_t *) s->code_ptr;
1023 /* Thanks to Andrzej Zaborowski */
1024 tcg_out32 (s, B | (val & 0x3fffffc));
1025 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1028 break;
1029 case INDEX_op_call:
1030 tcg_out_call (s, args[0], const_args[0]);
1031 break;
1032 case INDEX_op_jmp:
1033 if (const_args[0]) {
1034 tcg_out_b (s, 0, args[0]);
1036 else {
1037 tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
1038 tcg_out32 (s, BCCTR | BO_ALWAYS);
1040 break;
1041 case INDEX_op_movi_i32:
1042 tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]);
1043 break;
1044 case INDEX_op_movi_i64:
1045 tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]);
1046 break;
1047 case INDEX_op_ld8u_i32:
1048 case INDEX_op_ld8u_i64:
1049 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1050 break;
1051 case INDEX_op_ld8s_i32:
1052 case INDEX_op_ld8s_i64:
1053 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1054 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1055 break;
1056 case INDEX_op_ld16u_i32:
1057 case INDEX_op_ld16u_i64:
1058 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1059 break;
1060 case INDEX_op_ld16s_i32:
1061 case INDEX_op_ld16s_i64:
1062 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1063 break;
1064 case INDEX_op_ld_i32:
1065 case INDEX_op_ld32u_i64:
1066 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1067 break;
1068 case INDEX_op_ld32s_i64:
1069 tcg_out_ldst (s, args[0], args[1], args[2], LWA, LWAX);
1070 break;
1071 case INDEX_op_ld_i64:
1072 tcg_out_ldst (s, args[0], args[1], args[2], LD, LDX);
1073 break;
1074 case INDEX_op_st8_i32:
1075 case INDEX_op_st8_i64:
1076 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1077 break;
1078 case INDEX_op_st16_i32:
1079 case INDEX_op_st16_i64:
1080 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1081 break;
1082 case INDEX_op_st_i32:
1083 case INDEX_op_st32_i64:
1084 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1085 break;
1086 case INDEX_op_st_i64:
1087 tcg_out_ldst (s, args[0], args[1], args[2], STD, STDX);
1088 break;
1090 case INDEX_op_add_i32:
1091 if (const_args[2])
1092 ppc_addi32 (s, args[0], args[1], args[2]);
1093 else
1094 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1095 break;
1096 case INDEX_op_sub_i32:
1097 if (const_args[2])
1098 ppc_addi32 (s, args[0], args[1], -args[2]);
1099 else
1100 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1101 break;
1103 case INDEX_op_and_i32:
1104 if (const_args[2]) {
1105 if (!args[2])
1106 tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
1107 else {
1108 if ((args[2] & 0xffff) == args[2])
1109 tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]);
1110 else if ((args[2] & 0xffff0000) == args[2])
1111 tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
1112 | ((args[2] >> 16) & 0xffff));
1113 else if (args[2] == 0xffffffff) {
1114 if (args[0] != args[1])
1115 tcg_out_mov (s, args[0], args[1]);
1117 else {
1118 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1119 tcg_out32 (s, AND | SAB (args[1], args[0], 0));
1123 else
1124 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1125 break;
1126 case INDEX_op_or_i32:
1127 if (const_args[2]) {
1128 if (args[2]) {
1129 if (args[2] & 0xffff) {
1130 tcg_out32 (s, ORI | RS (args[1]) | RA (args[0])
1131 | (args[2] & 0xffff));
1132 if (args[2] >> 16)
1133 tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
1134 | ((args[2] >> 16) & 0xffff));
1136 else {
1137 tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0])
1138 | ((args[2] >> 16) & 0xffff));
1141 else {
1142 if (args[0] != args[1])
1143 tcg_out_mov (s, args[0], args[1]);
1146 else
1147 tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1148 break;
1149 case INDEX_op_xor_i32:
1150 if (const_args[2]) {
1151 if (args[2]) {
1152 if ((args[2] & 0xffff) == args[2])
1153 tcg_out32 (s, XORI | RS (args[1]) | RA (args[0])
1154 | (args[2] & 0xffff));
1155 else if ((args[2] & 0xffff0000) == args[2])
1156 tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0])
1157 | ((args[2] >> 16) & 0xffff));
1158 else {
1159 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1160 tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
1163 else {
1164 if (args[0] != args[1])
1165 tcg_out_mov (s, args[0], args[1]);
1168 else
1169 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1170 break;
1172 case INDEX_op_mul_i32:
1173 if (const_args[2]) {
1174 if (args[2] == (int16_t) args[2])
1175 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1176 | (args[2] & 0xffff));
1177 else {
1178 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1179 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1182 else
1183 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1184 break;
1186 case INDEX_op_div_i32:
1187 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1188 break;
1190 case INDEX_op_divu_i32:
1191 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1192 break;
1194 case INDEX_op_rem_i32:
1195 tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1196 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1197 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1198 break;
1200 case INDEX_op_remu_i32:
1201 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1202 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1203 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1204 break;
1206 case INDEX_op_shl_i32:
1207 if (const_args[2]) {
1208 if (args[2])
1209 tcg_out32 (s, (RLWINM
1210 | RA (args[0])
1211 | RS (args[1])
1212 | SH (args[2])
1213 | MB (0)
1214 | ME (31 - args[2])
1217 else
1218 tcg_out_mov (s, args[0], args[1]);
1220 else
1221 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
1222 break;
1223 case INDEX_op_shr_i32:
1224 if (const_args[2]) {
1225 if (args[2])
1226 tcg_out32 (s, (RLWINM
1227 | RA (args[0])
1228 | RS (args[1])
1229 | SH (32 - args[2])
1230 | MB (args[2])
1231 | ME (31)
1234 else
1235 tcg_out_mov (s, args[0], args[1]);
1237 else
1238 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
1239 break;
1240 case INDEX_op_sar_i32:
1241 if (const_args[2])
1242 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1243 else
1244 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1245 break;
1247 case INDEX_op_brcond_i32:
1248 case INDEX_op_brcond_i64:
1249 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
1250 break;
1252 case INDEX_op_neg_i32:
1253 case INDEX_op_neg_i64:
1254 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1255 break;
1257 case INDEX_op_add_i64:
1258 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1259 break;
1260 case INDEX_op_sub_i64:
1261 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1262 break;
1264 case INDEX_op_and_i64:
1265 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1266 break;
1267 case INDEX_op_or_i64:
1268 tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1269 break;
1270 case INDEX_op_xor_i64:
1271 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1272 break;
1274 case INDEX_op_shl_i64:
1275 tcg_out32 (s, SLD | SAB (args[1], args[0], args[2]));
1276 break;
1277 case INDEX_op_shr_i64:
1278 tcg_out32 (s, SRD | SAB (args[1], args[0], args[2]));
1279 break;
1280 case INDEX_op_sar_i64:
1281 tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2]));
1282 break;
1284 case INDEX_op_mul_i64:
1285 tcg_out32 (s, MULLD | TAB (args[0], args[1], args[2]));
1286 break;
1287 case INDEX_op_div_i64:
1288 tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2]));
1289 break;
1290 case INDEX_op_divu_i64:
1291 tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
1292 break;
1293 case INDEX_op_rem_i64:
1294 tcg_out32 (s, DIVD | TAB (0, args[1], args[2]));
1295 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1296 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1297 break;
1298 case INDEX_op_remu_i64:
1299 tcg_out32 (s, DIVDU | TAB (0, args[1], args[2]));
1300 tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
1301 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1302 break;
1304 case INDEX_op_qemu_ld8u:
1305 tcg_out_qemu_ld (s, args, 0);
1306 break;
1307 case INDEX_op_qemu_ld8s:
1308 tcg_out_qemu_ld (s, args, 0 | 4);
1309 break;
1310 case INDEX_op_qemu_ld16u:
1311 tcg_out_qemu_ld (s, args, 1);
1312 break;
1313 case INDEX_op_qemu_ld16s:
1314 tcg_out_qemu_ld (s, args, 1 | 4);
1315 break;
1316 case INDEX_op_qemu_ld32u:
1317 tcg_out_qemu_ld (s, args, 2);
1318 break;
1319 case INDEX_op_qemu_ld32s:
1320 tcg_out_qemu_ld (s, args, 2 | 4);
1321 break;
1322 case INDEX_op_qemu_ld64:
1323 tcg_out_qemu_ld (s, args, 3);
1324 break;
1325 case INDEX_op_qemu_st8:
1326 tcg_out_qemu_st (s, args, 0);
1327 break;
1328 case INDEX_op_qemu_st16:
1329 tcg_out_qemu_st (s, args, 1);
1330 break;
1331 case INDEX_op_qemu_st32:
1332 tcg_out_qemu_st (s, args, 2);
1333 break;
1334 case INDEX_op_qemu_st64:
1335 tcg_out_qemu_st (s, args, 3);
1336 break;
1338 case INDEX_op_ext8s_i32:
1339 case INDEX_op_ext8s_i64:
1340 c = EXTSB;
1341 goto gen_ext;
1342 case INDEX_op_ext16s_i32:
1343 case INDEX_op_ext16s_i64:
1344 c = EXTSH;
1345 goto gen_ext;
1346 case INDEX_op_ext32s_i64:
1347 c = EXTSW;
1348 goto gen_ext;
1349 gen_ext:
1350 tcg_out32 (s, c | RS (args[1]) | RA (args[0]));
1351 break;
1353 default:
1354 tcg_dump_ops (s, stderr);
1355 tcg_abort ();
1359 static const TCGTargetOpDef ppc_op_defs[] = {
1360 { INDEX_op_exit_tb, { } },
1361 { INDEX_op_goto_tb, { } },
1362 { INDEX_op_call, { "ri" } },
1363 { INDEX_op_jmp, { "ri" } },
1364 { INDEX_op_br, { } },
1366 { INDEX_op_mov_i32, { "r", "r" } },
1367 { INDEX_op_mov_i64, { "r", "r" } },
1368 { INDEX_op_movi_i32, { "r" } },
1369 { INDEX_op_movi_i64, { "r" } },
1371 { INDEX_op_ld8u_i32, { "r", "r" } },
1372 { INDEX_op_ld8s_i32, { "r", "r" } },
1373 { INDEX_op_ld16u_i32, { "r", "r" } },
1374 { INDEX_op_ld16s_i32, { "r", "r" } },
1375 { INDEX_op_ld_i32, { "r", "r" } },
1376 { INDEX_op_ld_i64, { "r", "r" } },
1377 { INDEX_op_st8_i32, { "r", "r" } },
1378 { INDEX_op_st8_i64, { "r", "r" } },
1379 { INDEX_op_st16_i32, { "r", "r" } },
1380 { INDEX_op_st16_i64, { "r", "r" } },
1381 { INDEX_op_st_i32, { "r", "r" } },
1382 { INDEX_op_st_i64, { "r", "r" } },
1383 { INDEX_op_st32_i64, { "r", "r" } },
1385 { INDEX_op_ld8u_i64, { "r", "r" } },
1386 { INDEX_op_ld8s_i64, { "r", "r" } },
1387 { INDEX_op_ld16u_i64, { "r", "r" } },
1388 { INDEX_op_ld16s_i64, { "r", "r" } },
1389 { INDEX_op_ld32u_i64, { "r", "r" } },
1390 { INDEX_op_ld32s_i64, { "r", "r" } },
1391 { INDEX_op_ld_i64, { "r", "r" } },
1393 { INDEX_op_add_i32, { "r", "r", "ri" } },
1394 { INDEX_op_mul_i32, { "r", "r", "ri" } },
1395 { INDEX_op_div_i32, { "r", "r", "r" } },
1396 { INDEX_op_divu_i32, { "r", "r", "r" } },
1397 { INDEX_op_rem_i32, { "r", "r", "r" } },
1398 { INDEX_op_remu_i32, { "r", "r", "r" } },
1399 { INDEX_op_sub_i32, { "r", "r", "ri" } },
1400 { INDEX_op_and_i32, { "r", "r", "ri" } },
1401 { INDEX_op_or_i32, { "r", "r", "ri" } },
1402 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1404 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1405 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1406 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1408 { INDEX_op_brcond_i32, { "r", "ri" } },
1409 { INDEX_op_brcond_i64, { "r", "ri" } },
1411 { INDEX_op_neg_i32, { "r", "r" } },
1413 { INDEX_op_add_i64, { "r", "r", "r" } },
1414 { INDEX_op_sub_i64, { "r", "r", "r" } },
1415 { INDEX_op_and_i64, { "r", "r", "r" } },
1416 { INDEX_op_or_i64, { "r", "r", "r" } },
1417 { INDEX_op_xor_i64, { "r", "r", "r" } },
1419 { INDEX_op_shl_i64, { "r", "r", "r" } },
1420 { INDEX_op_shr_i64, { "r", "r", "r" } },
1421 { INDEX_op_sar_i64, { "r", "r", "r" } },
1423 { INDEX_op_mul_i64, { "r", "r", "r" } },
1424 { INDEX_op_div_i64, { "r", "r", "r" } },
1425 { INDEX_op_divu_i64, { "r", "r", "r" } },
1426 { INDEX_op_rem_i64, { "r", "r", "r" } },
1427 { INDEX_op_remu_i64, { "r", "r", "r" } },
1429 { INDEX_op_neg_i64, { "r", "r" } },
1431 { INDEX_op_qemu_ld8u, { "r", "L" } },
1432 { INDEX_op_qemu_ld8s, { "r", "L" } },
1433 { INDEX_op_qemu_ld16u, { "r", "L" } },
1434 { INDEX_op_qemu_ld16s, { "r", "L" } },
1435 { INDEX_op_qemu_ld32u, { "r", "L" } },
1436 { INDEX_op_qemu_ld32s, { "r", "L" } },
1437 { INDEX_op_qemu_ld64, { "r", "L" } },
1439 { INDEX_op_qemu_st8, { "S", "S" } },
1440 { INDEX_op_qemu_st16, { "S", "S" } },
1441 { INDEX_op_qemu_st32, { "S", "S" } },
1442 { INDEX_op_qemu_st64, { "S", "S", "S" } },
1444 { INDEX_op_ext8s_i32, { "r", "r" } },
1445 { INDEX_op_ext16s_i32, { "r", "r" } },
1446 { INDEX_op_ext8s_i64, { "r", "r" } },
1447 { INDEX_op_ext16s_i64, { "r", "r" } },
1448 { INDEX_op_ext32s_i64, { "r", "r" } },
1450 { -1 },
1453 void tcg_target_init (TCGContext *s)
1455 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1456 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1457 tcg_regset_set32 (tcg_target_call_clobber_regs, 0,
1458 (1 << TCG_REG_R0) |
1459 (1 << TCG_REG_R3) |
1460 (1 << TCG_REG_R4) |
1461 (1 << TCG_REG_R5) |
1462 (1 << TCG_REG_R6) |
1463 (1 << TCG_REG_R7) |
1464 (1 << TCG_REG_R8) |
1465 (1 << TCG_REG_R9) |
1466 (1 << TCG_REG_R10) |
1467 (1 << TCG_REG_R11) |
1468 (1 << TCG_REG_R12)
1471 tcg_regset_clear (s->reserved_regs);
1472 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0);
1473 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1);
1474 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2);
1475 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13);
1477 tcg_add_target_add_op_defs (ppc_op_defs);