]> git.proxmox.com Git - qemu.git/blame - tcg/ppc/tcg-target.c
Relax qemu_ld/st constraints for !SOFTMMU case
[qemu.git] / tcg / ppc / tcg-target.c
CommitLineData
2662e13f
FB
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
25static uint8_t *tb_ret_addr;
26
f9bf2987 27#ifdef __APPLE__
bf6bca52 28#define LINKAGE_AREA_SIZE 24
f9bf2987 29#define BACK_CHAIN_OFFSET 8
30#else
31#define LINKAGE_AREA_SIZE 8
32#define BACK_CHAIN_OFFSET 4
33#endif
34
2662e13f
FB
35#define FAST_PATH
36#if TARGET_PHYS_ADDR_BITS <= 32
37#define ADDEND_OFFSET 0
38#else
39#define ADDEND_OFFSET 4
40#endif
41
42static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
43 "r0",
44 "r1",
45 "rp",
46 "r3",
47 "r4",
48 "r5",
49 "r6",
50 "r7",
51 "r8",
52 "r9",
53 "r10",
54 "r11",
55 "r12",
56 "r13",
57 "r14",
58 "r15",
59 "r16",
60 "r17",
61 "r18",
62 "r19",
63 "r20",
64 "r21",
65 "r22",
66 "r23",
67 "r24",
68 "r25",
69 "r26",
70 "r27",
71 "r28",
72 "r29",
73 "r30",
74 "r31"
75};
76
77static const int tcg_target_reg_alloc_order[] = {
a35e86c5 78 TCG_REG_R14,
79 TCG_REG_R15,
80 TCG_REG_R16,
81 TCG_REG_R17,
82 TCG_REG_R18,
83 TCG_REG_R19,
84 TCG_REG_R20,
85 TCG_REG_R21,
86 TCG_REG_R22,
87 TCG_REG_R23,
88 TCG_REG_R28,
89 TCG_REG_R29,
90 TCG_REG_R30,
91 TCG_REG_R31,
f9bf2987 92#ifdef __APPLE__
93 TCG_REG_R2,
94#endif
2662e13f
FB
95 TCG_REG_R3,
96 TCG_REG_R4,
97 TCG_REG_R5,
98 TCG_REG_R6,
99 TCG_REG_R7,
100 TCG_REG_R8,
101 TCG_REG_R9,
102 TCG_REG_R10,
f9bf2987 103#ifndef __APPLE__
2662e13f 104 TCG_REG_R11,
f9bf2987 105#endif
2662e13f
FB
106 TCG_REG_R12,
107 TCG_REG_R13,
a35e86c5 108 TCG_REG_R0,
109 TCG_REG_R1,
110 TCG_REG_R2,
2662e13f
FB
111 TCG_REG_R24,
112 TCG_REG_R25,
113 TCG_REG_R26,
a35e86c5 114 TCG_REG_R27
2662e13f
FB
115};
116
117static const int tcg_target_call_iarg_regs[] = {
118 TCG_REG_R3,
119 TCG_REG_R4,
120 TCG_REG_R5,
121 TCG_REG_R6,
122 TCG_REG_R7,
123 TCG_REG_R8,
124 TCG_REG_R9,
125 TCG_REG_R10
126};
127
128static const int tcg_target_call_oarg_regs[2] = {
129 TCG_REG_R3,
130 TCG_REG_R4
131};
132
133static const int tcg_target_callee_save_regs[] = {
f9bf2987 134#ifdef __APPLE__
135 TCG_REG_R11,
136 TCG_REG_R13,
137#endif
2662e13f
FB
138 TCG_REG_R14,
139 TCG_REG_R15,
140 TCG_REG_R16,
141 TCG_REG_R17,
142 TCG_REG_R18,
143 TCG_REG_R19,
144 TCG_REG_R20,
145 TCG_REG_R21,
146 TCG_REG_R22,
147 TCG_REG_R23,
148 TCG_REG_R28,
149 TCG_REG_R29,
150 TCG_REG_R30,
151 TCG_REG_R31
152};
153
154static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
155{
932a6909
FB
156 tcg_target_long disp;
157
158 disp = target - (tcg_target_long) pc;
159 if ((disp << 6) >> 6 != disp)
160 tcg_abort ();
161
162 return disp & 0x3fffffc;
2662e13f
FB
163}
164
165static void reloc_pc24 (void *pc, tcg_target_long target)
166{
167 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
168 | reloc_pc24_val (pc, target);
169}
170
171static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
172{
932a6909
FB
173 tcg_target_long disp;
174
175 disp = target - (tcg_target_long) pc;
176 if (disp != (int16_t) disp)
177 tcg_abort ();
178
179 return disp & 0xfffc;
2662e13f
FB
180}
181
182static void reloc_pc14 (void *pc, tcg_target_long target)
183{
184 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
185 | reloc_pc14_val (pc, target);
186}
187
188static void patch_reloc(uint8_t *code_ptr, int type,
189 tcg_target_long value, tcg_target_long addend)
190{
191 value += addend;
192 switch (type) {
193 case R_PPC_REL14:
194 reloc_pc14 (code_ptr, value);
195 break;
196 case R_PPC_REL24:
197 reloc_pc24 (code_ptr, value);
198 break;
199 default:
200 tcg_abort();
201 }
202}
203
204/* maximum number of register used for input function arguments */
205static int tcg_target_get_call_iarg_regs_count(int flags)
206{
207 return sizeof (tcg_target_call_iarg_regs) / sizeof (tcg_target_call_iarg_regs[0]);
208}
209
210/* parse target specific constraints */
211static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
212{
213 const char *ct_str;
214
215 ct_str = *pct_str;
216 switch (ct_str[0]) {
398ce98e 217 case 'A': case 'B': case 'C': case 'D':
218 ct->ct |= TCG_CT_REG;
219 tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
220 break;
2662e13f
FB
221 case 'r':
222 ct->ct |= TCG_CT_REG;
223 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
224 break;
70fa887c 225#ifdef CONFIG_SOFTMMU
2662e13f
FB
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);
230 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
231 break;
232 case 'K': /* qemu_st[8..32] 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);
236 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
237 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
238#if TARGET_LONG_BITS == 64
239 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
240#endif
241 break;
242 case 'M': /* qemu_st64 constraint */
243 ct->ct |= TCG_CT_REG;
244 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
245 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
246 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
247 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
248 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
249 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
250 break;
70fa887c 251#else
252 case 'L':
253 case 'K':
254 ct->ct |= TCG_CT_REG;
255 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
256 break;
257 case 'M':
258 ct->ct |= TCG_CT_REG;
259 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
260 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
261 break;
262#endif
2662e13f
FB
263 default:
264 return -1;
265 }
266 ct_str++;
267 *pct_str = ct_str;
268 return 0;
269}
270
271/* test if a constant matches the constraint */
272static int tcg_target_const_match(tcg_target_long val,
273 const TCGArgConstraint *arg_ct)
274{
275 int ct;
276
277 ct = arg_ct->ct;
278 if (ct & TCG_CT_CONST)
279 return 1;
2662e13f
FB
280 return 0;
281}
282
283#define OPCD(opc) ((opc)<<26)
284#define XO31(opc) (OPCD(31)|((opc)<<1))
285#define XO19(opc) (OPCD(19)|((opc)<<1))
286
287#define B OPCD(18)
288#define BC OPCD(16)
289#define LBZ OPCD(34)
290#define LHZ OPCD(40)
291#define LHA OPCD(42)
292#define LWZ OPCD(32)
293#define STB OPCD(38)
294#define STH OPCD(44)
295#define STW OPCD(36)
296
297#define ADDI OPCD(14)
298#define ADDIS OPCD(15)
299#define ORI OPCD(24)
300#define ORIS OPCD(25)
301#define XORI OPCD(26)
302#define XORIS OPCD(27)
303#define ANDI OPCD(28)
304#define ANDIS OPCD(29)
305#define MULLI OPCD( 7)
306#define CMPLI OPCD(10)
307#define CMPI OPCD(11)
308
309#define LWZU OPCD(33)
310#define STWU OPCD(37)
311
312#define RLWINM OPCD(21)
313
c596defd 314#define BCLR XO19( 16)
2662e13f
FB
315#define BCCTR XO19(528)
316#define CRAND XO19(257)
c596defd 317#define CRANDC XO19(129)
318#define CRNAND XO19(225)
319#define CROR XO19(449)
2662e13f
FB
320
321#define EXTSB XO31(954)
322#define EXTSH XO31(922)
323#define ADD XO31(266)
324#define ADDE XO31(138)
325#define ADDC XO31( 10)
326#define AND XO31( 28)
327#define SUBF XO31( 40)
328#define SUBFC XO31( 8)
329#define SUBFE XO31(136)
330#define OR XO31(444)
331#define XOR XO31(316)
332#define MULLW XO31(235)
333#define MULHWU XO31( 11)
334#define DIVW XO31(491)
335#define DIVWU XO31(459)
336#define CMP XO31( 0)
337#define CMPL XO31( 32)
338#define LHBRX XO31(790)
339#define LWBRX XO31(534)
340#define STHBRX XO31(918)
341#define STWBRX XO31(662)
342#define MFSPR XO31(339)
343#define MTSPR XO31(467)
344#define SRAWI XO31(824)
345#define NEG XO31(104)
346
347#define LBZX XO31( 87)
348#define LHZX XO31(276)
349#define LHAX XO31(343)
350#define LWZX XO31( 23)
351#define STBX XO31(215)
352#define STHX XO31(407)
353#define STWX XO31(151)
354
355#define SPR(a,b) ((((a)<<5)|(b))<<11)
356#define LR SPR(8, 0)
357#define CTR SPR(9, 0)
358
359#define SLW XO31( 24)
360#define SRW XO31(536)
361#define SRAW XO31(792)
362
363#define LMW OPCD(46)
364#define STMW OPCD(47)
365
366#define TW XO31(4)
367#define TRAP (TW | TO (31))
368
369#define RT(r) ((r)<<21)
370#define RS(r) ((r)<<21)
371#define RA(r) ((r)<<16)
372#define RB(r) ((r)<<11)
373#define TO(t) ((t)<<21)
374#define SH(s) ((s)<<11)
375#define MB(b) ((b)<<6)
376#define ME(e) ((e)<<1)
377#define BO(o) ((o)<<21)
378
379#define LK 1
380
381#define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
382#define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
383
384#define BF(n) ((n)<<23)
385#define BI(n, c) (((c)+((n)*4))<<16)
386#define BT(n, c) (((c)+((n)*4))<<21)
387#define BA(n, c) (((c)+((n)*4))<<16)
388#define BB(n, c) (((c)+((n)*4))<<11)
389
390#define BO_COND_TRUE BO (12)
391#define BO_COND_FALSE BO (4)
392#define BO_ALWAYS BO (20)
393
394enum {
395 CR_LT,
396 CR_GT,
397 CR_EQ,
398 CR_SO
399};
400
401static const uint32_t tcg_to_bc[10] = {
402 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
403 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
404 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
405 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
406 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
407 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
408 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
409 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
410 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
411 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
412};
413
414static void tcg_out_mov(TCGContext *s, int ret, int arg)
415{
416 tcg_out32 (s, OR | SAB (arg, ret, arg));
417}
418
419static void tcg_out_movi(TCGContext *s, TCGType type,
420 int ret, tcg_target_long arg)
421{
422 if (arg == (int16_t) arg)
423 tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
424 else {
425 tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
426 if (arg & 0xffff)
0a878c47 427 tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
2662e13f
FB
428 }
429}
430
431static void tcg_out_ldst (TCGContext *s, int ret, int addr,
432 int offset, int op1, int op2)
433{
434 if (offset == (int16_t) offset)
435 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
436 else {
437 tcg_out_movi (s, TCG_TYPE_I32, 0, offset);
438 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
439 }
440}
441
932a6909
FB
442static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
443{
444 tcg_target_long disp;
445
446 disp = target - (tcg_target_long) s->code_ptr;
447 if ((disp << 6) >> 6 == disp)
8c5e95d8 448 tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
932a6909
FB
449 else {
450 tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target);
451 tcg_out32 (s, MTSPR | RS (0) | CTR);
452 tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
453 }
454}
455
2662e13f
FB
456#if defined(CONFIG_SOFTMMU)
457extern void __ldb_mmu(void);
458extern void __ldw_mmu(void);
459extern void __ldl_mmu(void);
460extern void __ldq_mmu(void);
461
462extern void __stb_mmu(void);
463extern void __stw_mmu(void);
464extern void __stl_mmu(void);
465extern void __stq_mmu(void);
466
467static void *qemu_ld_helpers[4] = {
468 __ldb_mmu,
469 __ldw_mmu,
470 __ldl_mmu,
471 __ldq_mmu,
472};
473
474static void *qemu_st_helpers[4] = {
475 __stb_mmu,
476 __stw_mmu,
477 __stl_mmu,
478 __stq_mmu,
479};
480#endif
481
482static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
483{
484 int addr_reg, data_reg, data_reg2, r0, mem_index, s_bits, bswap;
485#ifdef CONFIG_SOFTMMU
486 int r1, r2;
487 void *label1_ptr, *label2_ptr;
488#endif
489#if TARGET_LONG_BITS == 64
490 int addr_reg2;
491#endif
492
493 data_reg = *args++;
494 if (opc == 3)
495 data_reg2 = *args++;
496 else
497 data_reg2 = 0;
498 addr_reg = *args++;
499#if TARGET_LONG_BITS == 64
500 addr_reg2 = *args++;
501#endif
502 mem_index = *args;
503 s_bits = opc & 3;
504
505#ifdef CONFIG_SOFTMMU
506 r0 = 3;
507 r1 = 4;
508 r2 = 0;
509
510 tcg_out32 (s, (RLWINM
511 | RA (r0)
512 | RS (addr_reg)
513 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
514 | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
515 | ME (31 - CPU_TLB_ENTRY_BITS)
516 )
517 );
518 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
519 tcg_out32 (s, (LWZU
520 | RT (r1)
521 | RA (r0)
522 | offsetof (CPUState, tlb_table[mem_index][0].addr_read)
523 )
524 );
525 tcg_out32 (s, (RLWINM
526 | RA (r2)
527 | RS (addr_reg)
528 | SH (0)
529 | MB ((32 - s_bits) & 31)
530 | ME (31 - TARGET_PAGE_BITS)
531 )
532 );
533
534 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
535#if TARGET_LONG_BITS == 64
536 tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
537 tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
538 tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
539#endif
540
541 label1_ptr = s->code_ptr;
542#ifdef FAST_PATH
543 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
544#endif
545
546 /* slow path */
547#if TARGET_LONG_BITS == 32
548 tcg_out_mov (s, 3, addr_reg);
549 tcg_out_movi (s, TCG_TYPE_I32, 4, mem_index);
550#else
551 tcg_out_mov (s, 3, addr_reg2);
552 tcg_out_mov (s, 4, addr_reg);
553 tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
554#endif
555
932a6909 556 tcg_out_b (s, LK, (tcg_target_long) qemu_ld_helpers[s_bits]);
2662e13f
FB
557 switch (opc) {
558 case 0|4:
559 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
560 break;
561 case 1|4:
562 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
563 break;
564 case 0:
565 case 1:
566 case 2:
567 if (data_reg != 3)
568 tcg_out_mov (s, data_reg, 3);
569 break;
570 case 3:
571 if (data_reg == 3) {
572 if (data_reg2 == 4) {
573 tcg_out_mov (s, 0, 4);
574 tcg_out_mov (s, 4, 3);
575 tcg_out_mov (s, 3, 0);
576 }
577 else {
578 tcg_out_mov (s, data_reg2, 3);
579 tcg_out_mov (s, 3, 4);
580 }
581 }
582 else {
583 if (data_reg != 4) tcg_out_mov (s, data_reg, 4);
584 if (data_reg2 != 3) tcg_out_mov (s, data_reg2, 3);
585 }
586 break;
587 }
588 label2_ptr = s->code_ptr;
589 tcg_out32 (s, B);
590
591 /* label1: fast path */
592#ifdef FAST_PATH
593 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
594#endif
595
596 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
597 tcg_out32 (s, (LWZ
598 | RT (r0)
599 | RA (r0)
600 | (ADDEND_OFFSET + offsetof (CPUTLBEntry, addend)
601 - offsetof (CPUTLBEntry, addr_read))
602 ));
603 /* r0 = env->tlb_table[mem_index][index].addend */
604 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
605 /* r0 = env->tlb_table[mem_index][index].addend + addr */
606
607#else /* !CONFIG_SOFTMMU */
608 r0 = addr_reg;
609#endif
610
611#ifdef TARGET_WORDS_BIGENDIAN
612 bswap = 0;
613#else
614 bswap = 1;
615#endif
616 switch (opc) {
617 default:
618 case 0:
619 tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
620 break;
621 case 0|4:
622 tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
623 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
624 break;
625 case 1:
626 if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
627 else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0));
628 break;
629 case 1|4:
630 if (bswap) {
631 tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
632 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
633 }
634 else tcg_out32 (s, LHA | RT (data_reg) | RA (r0));
635 break;
636 case 2:
637 if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
638 else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0));
639 break;
640 case 3:
641 if (bswap) {
642 if (r0 == data_reg) {
643 tcg_out32 (s, LWBRX | RT (0) | RB (r0));
644 tcg_out32 (s, ADDI | RT (r0) | RA (r0) | 4);
645 tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
646 tcg_out_mov (s, data_reg, 0);
647 }
648 else {
649 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
650 tcg_out32 (s, ADDI | RT (r0) | RA (r0) | 4);
651 tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
652 }
653 }
654 else {
655 if (r0 == data_reg2) {
656 tcg_out32 (s, LWZ | RT (0) | RA (r0));
657 tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
658 tcg_out_mov (s, data_reg2, 0);
659 }
660 else {
661 tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
662 tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
663 }
664 }
665 break;
666 }
667
668#ifdef CONFIG_SOFTMMU
669 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
670#endif
671}
672
673static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
674{
675 int addr_reg, r0, r1, data_reg, data_reg2, mem_index, bswap;
676#ifdef CONFIG_SOFTMMU
677 int r2, ir;
678 void *label1_ptr, *label2_ptr;
679#endif
680#if TARGET_LONG_BITS == 64
681 int addr_reg2;
682#endif
683
684 data_reg = *args++;
685 if (opc == 3)
686 data_reg2 = *args++;
687 else
688 data_reg2 = 0;
689 addr_reg = *args++;
690#if TARGET_LONG_BITS == 64
691 addr_reg2 = *args++;
692#endif
693 mem_index = *args;
694
695#ifdef CONFIG_SOFTMMU
696 r0 = 3;
697 r1 = 4;
698 r2 = 0;
699
700 tcg_out32 (s, (RLWINM
701 | RA (r0)
702 | RS (addr_reg)
703 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
704 | MB (32 - (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS))
705 | ME (31 - CPU_TLB_ENTRY_BITS)
706 )
707 );
708 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
709 tcg_out32 (s, (LWZU
710 | RT (r1)
711 | RA (r0)
712 | offsetof (CPUState, tlb_table[mem_index][0].addr_write)
713 )
714 );
715 tcg_out32 (s, (RLWINM
716 | RA (r2)
717 | RS (addr_reg)
718 | SH (0)
719 | MB ((32 - opc) & 31)
720 | ME (31 - TARGET_PAGE_BITS)
721 )
722 );
723
724 tcg_out32 (s, CMP | (7 << 23) | RA (r2) | RB (r1));
725#if TARGET_LONG_BITS == 64
726 tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
727 tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
728 tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
729#endif
730
731 label1_ptr = s->code_ptr;
732#ifdef FAST_PATH
733 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
734#endif
735
736 /* slow path */
737#if TARGET_LONG_BITS == 32
738 tcg_out_mov (s, 3, addr_reg);
739 ir = 4;
740#else
741 tcg_out_mov (s, 3, addr_reg2);
742 tcg_out_mov (s, 4, addr_reg);
f9bf2987 743#ifdef TCG_TARGET_CALL_ALIGN_ARGS
2662e13f 744 ir = 5;
f9bf2987 745#else
746 ir = 4;
747#endif
2662e13f
FB
748#endif
749
750 switch (opc) {
751 case 0:
752 tcg_out32 (s, (RLWINM
753 | RA (ir)
754 | RS (data_reg)
755 | SH (0)
756 | MB (24)
757 | ME (31)));
758 break;
759 case 1:
760 tcg_out32 (s, (RLWINM
761 | RA (ir)
762 | RS (data_reg)
763 | SH (0)
764 | MB (16)
765 | ME (31)));
766 break;
767 case 2:
768 tcg_out_mov (s, ir, data_reg);
769 break;
770 case 3:
f9bf2987 771#ifdef TCG_TARGET_CALL_ALIGN_ARGS
772 ir = 5;
773#endif
774 tcg_out_mov (s, ir++, data_reg2);
775 tcg_out_mov (s, ir, data_reg);
2662e13f
FB
776 break;
777 }
778 ir++;
779
780 tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
932a6909 781 tcg_out_b (s, LK, (tcg_target_long) qemu_st_helpers[opc]);
2662e13f
FB
782 label2_ptr = s->code_ptr;
783 tcg_out32 (s, B);
784
785 /* label1: fast path */
786#ifdef FAST_PATH
787 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
788#endif
789
790 tcg_out32 (s, (LWZ
791 | RT (r0)
792 | RA (r0)
793 | (ADDEND_OFFSET + offsetof (CPUTLBEntry, addend)
794 - offsetof (CPUTLBEntry, addr_write))
795 ));
796 /* r0 = env->tlb_table[mem_index][index].addend */
797 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
798 /* r0 = env->tlb_table[mem_index][index].addend + addr */
799
800#else /* !CONFIG_SOFTMMU */
70fa887c 801 r1 = 3;
2662e13f
FB
802 r0 = addr_reg;
803#endif
804
805#ifdef TARGET_WORDS_BIGENDIAN
806 bswap = 0;
807#else
808 bswap = 1;
809#endif
810 switch (opc) {
811 case 0:
812 tcg_out32 (s, STB | RS (data_reg) | RA (r0));
813 break;
814 case 1:
815 if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0));
816 else tcg_out32 (s, STH | RS (data_reg) | RA (r0));
817 break;
818 case 2:
819 if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
820 else tcg_out32 (s, STW | RS (data_reg) | RA (r0));
821 break;
822 case 3:
823 if (bswap) {
824 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
825 tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
826 tcg_out32 (s, STWBRX | RS (data_reg2) | RA (0) | RB (r1));
827 }
828 else {
829 tcg_out32 (s, STW | RS (data_reg2) | RA (r0));
830 tcg_out32 (s, STW | RS (data_reg) | RA (r0) | 4);
831 }
832 break;
833 }
834
835#ifdef CONFIG_SOFTMMU
836 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
837#endif
838}
839
840void tcg_target_qemu_prologue (TCGContext *s)
841{
0d5bd363 842 int i, frame_size;
2662e13f
FB
843
844 frame_size = 0
f9bf2987 845 + LINKAGE_AREA_SIZE
2662e13f
FB
846 + TCG_STATIC_CALL_ARGS_SIZE
847 + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
848 ;
849 frame_size = (frame_size + 15) & ~15;
850
851 tcg_out32 (s, MFSPR | RT (0) | LR);
852 tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
853 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
854 tcg_out32 (s, (STW
855 | RS (tcg_target_callee_save_regs[i])
856 | RA (1)
f9bf2987 857 | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
2662e13f
FB
858 )
859 );
f9bf2987 860 tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size + BACK_CHAIN_OFFSET));
2662e13f
FB
861
862 tcg_out32 (s, MTSPR | RS (3) | CTR);
863 tcg_out32 (s, BCCTR | BO_ALWAYS);
864 tb_ret_addr = s->code_ptr;
865
866 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
867 tcg_out32 (s, (LWZ
868 | RT (tcg_target_callee_save_regs[i])
869 | RA (1)
f9bf2987 870 | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
2662e13f
FB
871 )
872 );
f9bf2987 873 tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size + BACK_CHAIN_OFFSET));
2662e13f
FB
874 tcg_out32 (s, MTSPR | RS (0) | LR);
875 tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
876 tcg_out32 (s, BCLR | BO_ALWAYS);
877}
878
879static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
880 tcg_target_long arg2)
881{
882 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
883}
884
885static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
886 tcg_target_long arg2)
887{
888 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
889}
890
891static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
892{
893 if (!si && rt == ra)
894 return;
895
896 if (si == (int16_t) si)
897 tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
898 else {
899 uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
900 tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
901 tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
902 }
903}
904
905static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
906{
907 ppc_addi (s, reg, reg, val);
908}
909
c596defd 910static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
911 int const_arg2, int cr)
2662e13f 912{
2662e13f
FB
913 int imm;
914 uint32_t op;
915
2662e13f 916 switch (cond) {
f3f478a7
FB
917 case TCG_COND_EQ:
918 case TCG_COND_NE:
919 if (const_arg2) {
920 if ((int16_t) arg2 == arg2) {
921 op = CMPI;
922 imm = 1;
923 break;
924 }
925 else if ((uint16_t) arg2 == arg2) {
926 op = CMPLI;
927 imm = 1;
928 break;
929 }
930 }
931 op = CMPL;
932 imm = 0;
933 break;
934
935 case TCG_COND_LT:
936 case TCG_COND_GE:
937 case TCG_COND_LE:
938 case TCG_COND_GT:
939 if (const_arg2) {
940 if ((int16_t) arg2 == arg2) {
941 op = CMPI;
942 imm = 1;
943 break;
944 }
945 }
946 op = CMP;
947 imm = 0;
948 break;
949
950 case TCG_COND_LTU:
951 case TCG_COND_GEU:
952 case TCG_COND_LEU:
953 case TCG_COND_GTU:
954 if (const_arg2) {
955 if ((uint16_t) arg2 == arg2) {
956 op = CMPLI;
957 imm = 1;
958 break;
959 }
960 }
961 op = CMPL;
962 imm = 0;
963 break;
964
2662e13f
FB
965 default:
966 tcg_abort ();
967 }
c596defd 968 op |= BF (cr);
2662e13f
FB
969
970 if (imm)
971 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
972 else {
973 if (const_arg2) {
974 tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
975 tcg_out32 (s, op | RA (arg1) | RB (0));
976 }
977 else
978 tcg_out32 (s, op | RA (arg1) | RB (arg2));
979 }
980
c596defd 981}
982
983static void tcg_out_bc (TCGContext *s, int bc, int label_index)
984{
985 TCGLabel *l = &s->labels[label_index];
986
0a878c47 987 if (l->has_value)
c596defd 988 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
2662e13f 989 else {
0a878c47 990 uint16_t val = *(uint16_t *) &s->code_ptr[2];
991
992 /* Thanks to Andrzej Zaborowski */
c596defd 993 tcg_out32 (s, bc | (val & 0xfffc));
2662e13f
FB
994 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
995 }
996}
997
c596defd 998static void tcg_out_brcond (TCGContext *s, int cond,
999 TCGArg arg1, TCGArg arg2, int const_arg2,
1000 int label_index)
1001{
1002 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
1003 tcg_out_bc (s, tcg_to_bc[cond], label_index);
1004}
1005
2662e13f
FB
1006/* XXX: we implement it at the target level to avoid having to
1007 handle cross basic blocks temporaries */
c596defd 1008static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
1009 const int *const_args)
2662e13f 1010{
c596defd 1011 int cond = args[4], label_index = args[5], op;
1012 struct { int bit1; int bit2; int cond2; } bits[] = {
1013 [TCG_COND_LT ] = { CR_LT, CR_LT, TCG_COND_LT },
1014 [TCG_COND_LE ] = { CR_LT, CR_GT, TCG_COND_LT },
1015 [TCG_COND_GT ] = { CR_GT, CR_GT, TCG_COND_GT },
1016 [TCG_COND_GE ] = { CR_GT, CR_LT, TCG_COND_GT },
1017 [TCG_COND_LTU] = { CR_LT, CR_LT, TCG_COND_LTU },
1018 [TCG_COND_LEU] = { CR_LT, CR_GT, TCG_COND_LTU },
1019 [TCG_COND_GTU] = { CR_GT, CR_GT, TCG_COND_GTU },
1020 [TCG_COND_GEU] = { CR_GT, CR_LT, TCG_COND_GTU },
1021 }, *b = &bits[cond];
1022
1023 switch (cond) {
2662e13f 1024 case TCG_COND_EQ:
2662e13f 1025 case TCG_COND_NE:
e924c485 1026 op = (cond == TCG_COND_EQ) ? CRAND : CRNAND;
1027 tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 6);
1028 tcg_out_cmp (s, cond, args[1], args[3], const_args[3], 7);
1029 tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
2662e13f
FB
1030 break;
1031 case TCG_COND_LT:
2662e13f 1032 case TCG_COND_LE:
2662e13f 1033 case TCG_COND_GT:
2662e13f 1034 case TCG_COND_GE:
2662e13f 1035 case TCG_COND_LTU:
2662e13f 1036 case TCG_COND_LEU:
2662e13f 1037 case TCG_COND_GTU:
2662e13f 1038 case TCG_COND_GEU:
c596defd 1039 op = (b->bit1 != b->bit2) ? CRANDC : CRAND;
1040 tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5);
1041 tcg_out_cmp (s, TCG_COND_EQ, args[1], args[3], const_args[3], 6);
1042 tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 7);
1043 tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, b->bit2));
1044 tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ));
2662e13f
FB
1045 break;
1046 default:
1047 tcg_abort();
1048 }
c596defd 1049
1050 tcg_out_bc (s, (BC | BI (7, CR_EQ) | BO_COND_TRUE), label_index);
2662e13f
FB
1051}
1052
52781543 1053void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
1054{
1055 uint32_t *ptr;
1056 long disp = addr - jmp_addr;
1057 unsigned long patch_size;
1058
1059 ptr = (uint32_t *)jmp_addr;
1060
1061 if ((disp << 6) >> 6 != disp) {
1062 ptr[0] = 0x3c000000 | (addr >> 16); /* lis 0,addr@ha */
1063 ptr[1] = 0x60000000 | (addr & 0xffff); /* la 0,addr@l(0) */
1064 ptr[2] = 0x7c0903a6; /* mtctr 0 */
1065 ptr[3] = 0x4e800420; /* brctr */
1066 patch_size = 16;
1067 } else {
1068 /* patch the branch destination */
1069 if (disp != 16) {
1070 *ptr = 0x48000000 | (disp & 0x03fffffc); /* b disp */
1071 patch_size = 4;
1072 } else {
1073 ptr[0] = 0x60000000; /* nop */
1074 ptr[1] = 0x60000000;
1075 ptr[2] = 0x60000000;
1076 ptr[3] = 0x60000000;
1077 patch_size = 16;
1078 }
1079 }
1080 /* flush icache */
1081 flush_icache_range(jmp_addr, jmp_addr + patch_size);
1082}
1083
2662e13f
FB
1084static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1085 const int *const_args)
1086{
1087 switch (opc) {
1088 case INDEX_op_exit_tb:
1089 tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
932a6909 1090 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
2662e13f
FB
1091 break;
1092 case INDEX_op_goto_tb:
1093 if (s->tb_jmp_offset) {
1094 /* direct jump method */
932a6909 1095
2662e13f 1096 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
0a878c47 1097 s->code_ptr += 16;
932a6909
FB
1098 }
1099 else {
2662e13f
FB
1100 tcg_abort ();
1101 }
1102 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1103 break;
1104 case INDEX_op_br:
1105 {
1106 TCGLabel *l = &s->labels[args[0]];
1107
1108 if (l->has_value) {
932a6909 1109 tcg_out_b (s, 0, l->u.value);
2662e13f
FB
1110 }
1111 else {
0a878c47 1112 uint32_t val = *(uint32_t *) s->code_ptr;
1113
1114 /* Thanks to Andrzej Zaborowski */
1115 tcg_out32 (s, B | (val & 0x3fffffc));
2662e13f
FB
1116 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1117 }
1118 }
1119 break;
1120 case INDEX_op_call:
1121 if (const_args[0]) {
932a6909 1122 tcg_out_b (s, LK, args[0]);
2662e13f
FB
1123 }
1124 else {
1125 tcg_out32 (s, MTSPR | RS (args[0]) | LR);
1126 tcg_out32 (s, BCLR | BO_ALWAYS | LK);
1127 }
1128 break;
1129 case INDEX_op_jmp:
1130 if (const_args[0]) {
932a6909 1131 tcg_out_b (s, 0, args[0]);
2662e13f
FB
1132 }
1133 else {
1134 tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
1135 tcg_out32 (s, BCCTR | BO_ALWAYS);
1136 }
1137 break;
1138 case INDEX_op_movi_i32:
1139 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1140 break;
1141 case INDEX_op_ld8u_i32:
1142 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1143 break;
1144 case INDEX_op_ld8s_i32:
1145 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1146 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1147 break;
1148 case INDEX_op_ld16u_i32:
1149 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1150 break;
1151 case INDEX_op_ld16s_i32:
1152 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1153 break;
1154 case INDEX_op_ld_i32:
1155 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1156 break;
1157 case INDEX_op_st8_i32:
1158 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1159 break;
1160 case INDEX_op_st16_i32:
1161 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1162 break;
1163 case INDEX_op_st_i32:
1164 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1165 break;
1166
1167 case INDEX_op_add_i32:
1168 if (const_args[2])
1169 ppc_addi (s, args[0], args[1], args[2]);
1170 else
1171 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1172 break;
1173 case INDEX_op_sub_i32:
1174 if (const_args[2])
1175 ppc_addi (s, args[0], args[1], -args[2]);
1176 else
1177 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1178 break;
1179
1180 case INDEX_op_and_i32:
1181 if (const_args[2]) {
000a2d86 1182 if ((args[2] & 0xffff) == args[2])
1183 tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]);
1184 else if ((args[2] & 0xffff0000) == args[2])
1185 tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
1186 | ((args[2] >> 16) & 0xffff));
2662e13f 1187 else {
000a2d86 1188 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1189 tcg_out32 (s, AND | SAB (args[1], args[0], 0));
2662e13f
FB
1190 }
1191 }
1192 else
1193 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1194 break;
1195 case INDEX_op_or_i32:
1196 if (const_args[2]) {
000a2d86 1197 if (args[2] & 0xffff) {
1198 tcg_out32 (s, ORI | RS (args[1]) | RA (args[0])
1199 | (args[2] & 0xffff));
1200 if (args[2] >> 16)
1201 tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
2662e13f 1202 | ((args[2] >> 16) & 0xffff));
2662e13f
FB
1203 }
1204 else {
000a2d86 1205 tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0])
1206 | ((args[2] >> 16) & 0xffff));
2662e13f
FB
1207 }
1208 }
1209 else
1210 tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1211 break;
1212 case INDEX_op_xor_i32:
1213 if (const_args[2]) {
000a2d86 1214 if ((args[2] & 0xffff) == args[2])
1215 tcg_out32 (s, XORI | RS (args[1]) | RA (args[0])
1216 | (args[2] & 0xffff));
1217 else if ((args[2] & 0xffff0000) == args[2])
1218 tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0])
1219 | ((args[2] >> 16) & 0xffff));
2662e13f 1220 else {
000a2d86 1221 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1222 tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
2662e13f
FB
1223 }
1224 }
1225 else
1226 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1227 break;
1228
1229 case INDEX_op_mul_i32:
1230 if (const_args[2]) {
1231 if (args[2] == (int16_t) args[2])
1232 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1233 | (args[2] & 0xffff));
1234 else {
1235 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1236 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1237 }
1238 }
1239 else
1240 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1241 break;
77b73de6 1242
1243 case INDEX_op_div_i32:
1244 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1245 break;
1246
1247 case INDEX_op_divu_i32:
1248 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1249 break;
1250
1251 case INDEX_op_rem_i32:
1252 tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1253 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1254 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1255 break;
1256
1257 case INDEX_op_remu_i32:
1258 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1259 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1260 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1261 break;
1262
2662e13f
FB
1263 case INDEX_op_mulu2_i32:
1264 if (args[0] == args[2] || args[0] == args[3]) {
1265 tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
1266 tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1267 tcg_out_mov (s, args[0], 0);
1268 }
1269 else {
1270 tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
1271 tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1272 }
1273 break;
2662e13f
FB
1274
1275 case INDEX_op_shl_i32:
1276 if (const_args[2]) {
000a2d86 1277 tcg_out32 (s, (RLWINM
1278 | RA (args[0])
1279 | RS (args[1])
1280 | SH (args[2])
1281 | MB (0)
1282 | ME (31 - args[2])
1283 )
1284 );
2662e13f
FB
1285 }
1286 else
1287 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
1288 break;
1289 case INDEX_op_shr_i32:
1290 if (const_args[2]) {
000a2d86 1291 tcg_out32 (s, (RLWINM
1292 | RA (args[0])
1293 | RS (args[1])
1294 | SH (32 - args[2])
1295 | MB (args[2])
1296 | ME (31)
1297 )
1298 );
2662e13f
FB
1299 }
1300 else
1301 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
1302 break;
1303 case INDEX_op_sar_i32:
1304 if (const_args[2])
1305 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1306 else
1307 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1308 break;
1309
1310 case INDEX_op_add2_i32:
1311 if (args[0] == args[3] || args[0] == args[5]) {
1312 tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
1313 tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1314 tcg_out_mov (s, args[0], 0);
1315 }
1316 else {
1317 tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
1318 tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1319 }
1320 break;
1321 case INDEX_op_sub2_i32:
1322 if (args[0] == args[3] || args[0] == args[5]) {
1323 tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
1324 tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1325 tcg_out_mov (s, args[0], 0);
1326 }
1327 else {
1328 tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
1329 tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1330 }
1331 break;
1332
1333 case INDEX_op_brcond_i32:
1334 /*
1335 args[0] = r0
1336 args[1] = r1
1337 args[2] = cond
1338 args[3] = r1 is const
1339 args[4] = label_index
1340 */
1341 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
1342 break;
1343 case INDEX_op_brcond2_i32:
1344 tcg_out_brcond2(s, args, const_args);
1345 break;
1346
1347 case INDEX_op_neg_i32:
1348 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1349 break;
1350
1351 case INDEX_op_qemu_ld8u:
1352 tcg_out_qemu_ld(s, args, 0);
1353 break;
1354 case INDEX_op_qemu_ld8s:
1355 tcg_out_qemu_ld(s, args, 0 | 4);
1356 break;
1357 case INDEX_op_qemu_ld16u:
1358 tcg_out_qemu_ld(s, args, 1);
1359 break;
1360 case INDEX_op_qemu_ld16s:
1361 tcg_out_qemu_ld(s, args, 1 | 4);
1362 break;
1363 case INDEX_op_qemu_ld32u:
1364 tcg_out_qemu_ld(s, args, 2);
1365 break;
1366 case INDEX_op_qemu_ld64:
1367 tcg_out_qemu_ld(s, args, 3);
1368 break;
1369 case INDEX_op_qemu_st8:
1370 tcg_out_qemu_st(s, args, 0);
1371 break;
1372 case INDEX_op_qemu_st16:
1373 tcg_out_qemu_st(s, args, 1);
1374 break;
1375 case INDEX_op_qemu_st32:
1376 tcg_out_qemu_st(s, args, 2);
1377 break;
1378 case INDEX_op_qemu_st64:
1379 tcg_out_qemu_st(s, args, 3);
1380 break;
1381
e46b9681 1382 case INDEX_op_ext8s_i32:
1383 tcg_out32 (s, EXTSB | RS (args[1]) | RA (args[0]));
1384 break;
1385 case INDEX_op_ext16s_i32:
1386 tcg_out32 (s, EXTSH | RS (args[1]) | RA (args[0]));
1387 break;
1388
2662e13f
FB
1389 default:
1390 tcg_dump_ops (s, stderr);
1391 tcg_abort ();
1392 }
1393}
1394
1395static const TCGTargetOpDef ppc_op_defs[] = {
1396 { INDEX_op_exit_tb, { } },
1397 { INDEX_op_goto_tb, { } },
932a6909
FB
1398 { INDEX_op_call, { "ri" } },
1399 { INDEX_op_jmp, { "ri" } },
2662e13f
FB
1400 { INDEX_op_br, { } },
1401
1402 { INDEX_op_mov_i32, { "r", "r" } },
1403 { INDEX_op_movi_i32, { "r" } },
1404 { INDEX_op_ld8u_i32, { "r", "r" } },
1405 { INDEX_op_ld8s_i32, { "r", "r" } },
1406 { INDEX_op_ld16u_i32, { "r", "r" } },
1407 { INDEX_op_ld16s_i32, { "r", "r" } },
1408 { INDEX_op_ld_i32, { "r", "r" } },
1409 { INDEX_op_st8_i32, { "r", "r" } },
1410 { INDEX_op_st16_i32, { "r", "r" } },
1411 { INDEX_op_st_i32, { "r", "r" } },
1412
1413 { INDEX_op_add_i32, { "r", "r", "ri" } },
1414 { INDEX_op_mul_i32, { "r", "r", "ri" } },
77b73de6 1415 { INDEX_op_div_i32, { "r", "r", "r" } },
1416 { INDEX_op_divu_i32, { "r", "r", "r" } },
1417 { INDEX_op_rem_i32, { "r", "r", "r" } },
1418 { INDEX_op_remu_i32, { "r", "r", "r" } },
2662e13f 1419 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
2662e13f
FB
1420 { INDEX_op_sub_i32, { "r", "r", "ri" } },
1421 { INDEX_op_and_i32, { "r", "r", "ri" } },
1422 { INDEX_op_or_i32, { "r", "r", "ri" } },
1423 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1424
1425 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1426 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1427 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1428
1429 { INDEX_op_brcond_i32, { "r", "ri" } },
1430
1431 { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1432 { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1433 { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1434
1435 { INDEX_op_neg_i32, { "r", "r" } },
1436
1437#if TARGET_LONG_BITS == 32
1438 { INDEX_op_qemu_ld8u, { "r", "L" } },
1439 { INDEX_op_qemu_ld8s, { "r", "L" } },
1440 { INDEX_op_qemu_ld16u, { "r", "L" } },
1441 { INDEX_op_qemu_ld16s, { "r", "L" } },
1442 { INDEX_op_qemu_ld32u, { "r", "L" } },
1443 { INDEX_op_qemu_ld32s, { "r", "L" } },
1444 { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1445
1446 { INDEX_op_qemu_st8, { "K", "K" } },
1447 { INDEX_op_qemu_st16, { "K", "K" } },
1448 { INDEX_op_qemu_st32, { "K", "K" } },
1449 { INDEX_op_qemu_st64, { "M", "M", "M" } },
1450#else
1451 { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1452 { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1453 { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1454 { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1455 { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1456 { INDEX_op_qemu_ld32s, { "r", "L", "L" } },
1457 { INDEX_op_qemu_ld64, { "r", "L", "L", "L" } },
1458
1459 { INDEX_op_qemu_st8, { "K", "K", "K" } },
1460 { INDEX_op_qemu_st16, { "K", "K", "K" } },
1461 { INDEX_op_qemu_st32, { "K", "K", "K" } },
1462 { INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
1463#endif
1464
e46b9681 1465 { INDEX_op_ext8s_i32, { "r", "r" } },
1466 { INDEX_op_ext16s_i32, { "r", "r" } },
1467
2662e13f
FB
1468 { -1 },
1469};
1470
1471void tcg_target_init(TCGContext *s)
1472{
1473 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1474 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1475 (1 << TCG_REG_R0) |
f9bf2987 1476#ifdef __APPLE__
1477 (1 << TCG_REG_R2) |
1478#endif
2662e13f
FB
1479 (1 << TCG_REG_R3) |
1480 (1 << TCG_REG_R4) |
1481 (1 << TCG_REG_R5) |
1482 (1 << TCG_REG_R6) |
1483 (1 << TCG_REG_R7) |
1484 (1 << TCG_REG_R8) |
1485 (1 << TCG_REG_R9) |
1486 (1 << TCG_REG_R10) |
1487 (1 << TCG_REG_R11) |
1488 (1 << TCG_REG_R12)
1489 );
1490
1491 tcg_regset_clear(s->reserved_regs);
1492 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
1493 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
f9bf2987 1494#ifndef __APPLE__
2662e13f 1495 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
f9bf2987 1496#endif
2662e13f
FB
1497
1498 tcg_add_target_add_op_defs(ppc_op_defs);
1499}