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