]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/ppc/tcg-target.c
kqemu API change - allow use of kqemu with 32 bit QEMU on a 64 bit host
[mirror_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
2662e13f 869 switch (cond) {
f3f478a7
FB
870 case TCG_COND_EQ:
871 case TCG_COND_NE:
872 if (const_arg2) {
873 if ((int16_t) arg2 == arg2) {
874 op = CMPI;
875 imm = 1;
876 break;
877 }
878 else if ((uint16_t) arg2 == arg2) {
879 op = CMPLI;
880 imm = 1;
881 break;
882 }
883 }
884 op = CMPL;
885 imm = 0;
886 break;
887
888 case TCG_COND_LT:
889 case TCG_COND_GE:
890 case TCG_COND_LE:
891 case TCG_COND_GT:
892 if (const_arg2) {
893 if ((int16_t) arg2 == arg2) {
894 op = CMPI;
895 imm = 1;
896 break;
897 }
898 }
899 op = CMP;
900 imm = 0;
901 break;
902
903 case TCG_COND_LTU:
904 case TCG_COND_GEU:
905 case TCG_COND_LEU:
906 case TCG_COND_GTU:
907 if (const_arg2) {
908 if ((uint16_t) arg2 == arg2) {
909 op = CMPLI;
910 imm = 1;
911 break;
912 }
913 }
914 op = CMPL;
915 imm = 0;
916 break;
917
2662e13f
FB
918 default:
919 tcg_abort ();
920 }
921 op |= BF (7);
922
923 if (imm)
924 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
925 else {
926 if (const_arg2) {
927 tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
928 tcg_out32 (s, op | RA (arg1) | RB (0));
929 }
930 else
931 tcg_out32 (s, op | RA (arg1) | RB (arg2));
932 }
933
934 if (l->has_value) {
935 tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr,
936 l->u.value));
937 }
938 else {
939 tcg_out32 (s, tcg_to_bc[cond]);
940 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
941 }
942}
943
944/* brcond2 is taken verbatim from i386 tcg-target */
945/* XXX: we implement it at the target level to avoid having to
946 handle cross basic blocks temporaries */
947static void tcg_out_brcond2(TCGContext *s,
948 const TCGArg *args, const int *const_args)
949{
950 int label_next;
951 label_next = gen_new_label();
952 switch(args[4]) {
953 case TCG_COND_EQ:
954 tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], label_next);
955 tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3], args[5]);
956 break;
957 case TCG_COND_NE:
958 tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], args[5]);
959 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], args[5]);
960 break;
961 case TCG_COND_LT:
962 tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
963 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
964 tcg_out_brcond(s, TCG_COND_LT, args[0], args[2], const_args[2], args[5]);
965 break;
966 case TCG_COND_LE:
967 tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
968 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
969 tcg_out_brcond(s, TCG_COND_LE, args[0], args[2], const_args[2], args[5]);
970 break;
971 case TCG_COND_GT:
972 tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
973 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
974 tcg_out_brcond(s, TCG_COND_GT, args[0], args[2], const_args[2], args[5]);
975 break;
976 case TCG_COND_GE:
977 tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
978 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
979 tcg_out_brcond(s, TCG_COND_GE, args[0], args[2], const_args[2], args[5]);
980 break;
981 case TCG_COND_LTU:
982 tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
983 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
984 tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
985 break;
986 case TCG_COND_LEU:
987 tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
988 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
989 tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
990 break;
991 case TCG_COND_GTU:
992 tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
993 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
994 tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
995 break;
996 case TCG_COND_GEU:
997 tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
998 tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
999 tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
1000 break;
1001 default:
1002 tcg_abort();
1003 }
1004 tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
1005}
1006
1007static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1008 const int *const_args)
1009{
1010 switch (opc) {
1011 case INDEX_op_exit_tb:
1012 tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
1013 tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, (tcg_target_long) tb_ret_addr));
1014 break;
1015 case INDEX_op_goto_tb:
1016 if (s->tb_jmp_offset) {
1017 /* direct jump method */
1018 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1019 tcg_out32 (s, B | 4);
1020 } else {
1021 tcg_abort ();
1022 }
1023 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1024 break;
1025 case INDEX_op_br:
1026 {
1027 TCGLabel *l = &s->labels[args[0]];
1028
1029 if (l->has_value) {
1030 tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, l->u.value));
1031 }
1032 else {
1033 tcg_out32 (s, B);
1034 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1035 }
1036 }
1037 break;
1038 case INDEX_op_call:
1039 if (const_args[0]) {
1040 tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, args[0]) | LK);
1041 }
1042 else {
1043 tcg_out32 (s, MTSPR | RS (args[0]) | LR);
1044 tcg_out32 (s, BCLR | BO_ALWAYS | LK);
1045 }
1046 break;
1047 case INDEX_op_jmp:
1048 if (const_args[0]) {
1049 tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, args[0]));
1050 }
1051 else {
1052 tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
1053 tcg_out32 (s, BCCTR | BO_ALWAYS);
1054 }
1055 break;
1056 case INDEX_op_movi_i32:
1057 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1058 break;
1059 case INDEX_op_ld8u_i32:
1060 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1061 break;
1062 case INDEX_op_ld8s_i32:
1063 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1064 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1065 break;
1066 case INDEX_op_ld16u_i32:
1067 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1068 break;
1069 case INDEX_op_ld16s_i32:
1070 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1071 break;
1072 case INDEX_op_ld_i32:
1073 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1074 break;
1075 case INDEX_op_st8_i32:
1076 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1077 break;
1078 case INDEX_op_st16_i32:
1079 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1080 break;
1081 case INDEX_op_st_i32:
1082 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1083 break;
1084
1085 case INDEX_op_add_i32:
1086 if (const_args[2])
1087 ppc_addi (s, args[0], args[1], args[2]);
1088 else
1089 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1090 break;
1091 case INDEX_op_sub_i32:
1092 if (const_args[2])
1093 ppc_addi (s, args[0], args[1], -args[2]);
1094 else
1095 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1096 break;
1097
1098 case INDEX_op_and_i32:
1099 if (const_args[2]) {
1100 if (!args[2])
1101 tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
1102 else {
1103 if ((args[2] & 0xffff) == args[2])
1104 tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]);
1105 else if ((args[2] & 0xffff0000) == args[2])
1106 tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
1107 | ((args[2] >> 16) & 0xffff));
1108 else if (args[2] == 0xffffffff) {
1109 if (args[0] != args[1])
1110 tcg_out_mov (s, args[0], args[1]);
1111 }
1112 else {
1113 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1114 tcg_out32 (s, AND | SAB (args[1], args[0], 0));
1115 }
1116 }
1117 }
1118 else
1119 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1120 break;
1121 case INDEX_op_or_i32:
1122 if (const_args[2]) {
1123 if (args[2]) {
1124 if (args[2] & 0xffff) {
1125 tcg_out32 (s, ORI | RS (args[1]) | RA (args[0]) | (args[2] & 0xffff));
1126 if (args[2] >> 16)
1127 tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
1128 | ((args[2] >> 16) & 0xffff));
1129 }
1130 else {
1131 tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0])
1132 | ((args[2] >> 16) & 0xffff));
1133 }
1134 }
1135 else {
1136 if (args[0] != args[1])
1137 tcg_out_mov (s, args[0], args[1]);
1138 }
1139 }
1140 else
1141 tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1142 break;
1143 case INDEX_op_xor_i32:
1144 if (const_args[2]) {
1145 if (args[2]) {
1146 if ((args[2] & 0xffff) == args[2])
1147 tcg_out32 (s, XORI | RS (args[1]) | RA (args[0])
1148 | (args[2] & 0xffff));
1149 else if ((args[2] & 0xffff0000) == args[2])
1150 tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0])
1151 | ((args[2] >> 16) & 0xffff));
1152 else {
1153 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1154 tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
1155 }
1156 }
1157 else {
1158 if (args[0] != args[1])
1159 tcg_out_mov (s, args[0], args[1]);
1160 }
1161 }
1162 else
1163 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1164 break;
1165
1166 case INDEX_op_mul_i32:
1167 if (const_args[2]) {
1168 if (args[2] == (int16_t) args[2])
1169 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1170 | (args[2] & 0xffff));
1171 else {
1172 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1173 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1174 }
1175 }
1176 else
1177 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1178 break;
1179 case INDEX_op_mulu2_i32:
1180 if (args[0] == args[2] || args[0] == args[3]) {
1181 tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
1182 tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1183 tcg_out_mov (s, args[0], 0);
1184 }
1185 else {
1186 tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
1187 tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1188 }
1189 break;
1190 case INDEX_op_div2_i32:
1191 if (args[0] == args[2] || args[0] == args[3]) {
1192 tcg_out32 (s, DIVW | TAB (0, args[2], args[3]));
1193 tcg_out32 (s, MULLW | TAB (0, 0, args[3]));
1194 tcg_out32 (s, SUBF | TAB (0, 0, args[2]));
1195 tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3]));
1196 tcg_out_mov (s, args[1], 0);
1197 }
1198 else {
1199 tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3]));
1200 tcg_out32 (s, MULLW | TAB (0, args[0], args[3]));
1201 tcg_out32 (s, SUBF | TAB (args[1], 0, args[2]));
1202 }
1203 break;
1204 case INDEX_op_divu2_i32:
1205 if (args[0] == args[2] || args[0] == args[3]) {
1206 tcg_out32 (s, DIVWU | TAB (0, args[2], args[3]));
1207 tcg_out32 (s, MULLW | TAB (0, 0, args[3]));
1208 tcg_out32 (s, SUBF | TAB (0, 0, args[2]));
1209 tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3]));
1210 tcg_out_mov (s, args[1], 0);
1211 }
1212 else {
1213 tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3]));
1214 tcg_out32 (s, MULLW | TAB (0, args[0], args[3]));
1215 tcg_out32 (s, SUBF | TAB (args[1], 0, args[2]));
1216 }
1217 break;
1218
1219 case INDEX_op_shl_i32:
1220 if (const_args[2]) {
1221 if (args[2])
1222 tcg_out32 (s, (RLWINM
1223 | RA (args[0])
1224 | RS (args[1])
1225 | SH (args[2])
1226 | MB (0)
1227 | ME (31 - args[2])
1228 )
1229 );
1230 else
1231 tcg_out_mov (s, args[0], args[1]);
1232 }
1233 else
1234 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
1235 break;
1236 case INDEX_op_shr_i32:
1237 if (const_args[2]) {
1238 if (args[2])
1239 tcg_out32 (s, (RLWINM
1240 | RA (args[0])
1241 | RS (args[1])
1242 | SH (32 - args[2])
1243 | MB (args[2])
1244 | ME (31)
1245 )
1246 );
1247 else
1248 tcg_out_mov (s, args[0], args[1]);
1249 }
1250 else
1251 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
1252 break;
1253 case INDEX_op_sar_i32:
1254 if (const_args[2])
1255 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1256 else
1257 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1258 break;
1259
1260 case INDEX_op_add2_i32:
1261 if (args[0] == args[3] || args[0] == args[5]) {
1262 tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
1263 tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1264 tcg_out_mov (s, args[0], 0);
1265 }
1266 else {
1267 tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
1268 tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1269 }
1270 break;
1271 case INDEX_op_sub2_i32:
1272 if (args[0] == args[3] || args[0] == args[5]) {
1273 tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
1274 tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1275 tcg_out_mov (s, args[0], 0);
1276 }
1277 else {
1278 tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
1279 tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1280 }
1281 break;
1282
1283 case INDEX_op_brcond_i32:
1284 /*
1285 args[0] = r0
1286 args[1] = r1
1287 args[2] = cond
1288 args[3] = r1 is const
1289 args[4] = label_index
1290 */
1291 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
1292 break;
1293 case INDEX_op_brcond2_i32:
1294 tcg_out_brcond2(s, args, const_args);
1295 break;
1296
1297 case INDEX_op_neg_i32:
1298 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1299 break;
1300
1301 case INDEX_op_qemu_ld8u:
1302 tcg_out_qemu_ld(s, args, 0);
1303 break;
1304 case INDEX_op_qemu_ld8s:
1305 tcg_out_qemu_ld(s, args, 0 | 4);
1306 break;
1307 case INDEX_op_qemu_ld16u:
1308 tcg_out_qemu_ld(s, args, 1);
1309 break;
1310 case INDEX_op_qemu_ld16s:
1311 tcg_out_qemu_ld(s, args, 1 | 4);
1312 break;
1313 case INDEX_op_qemu_ld32u:
1314 tcg_out_qemu_ld(s, args, 2);
1315 break;
1316 case INDEX_op_qemu_ld64:
1317 tcg_out_qemu_ld(s, args, 3);
1318 break;
1319 case INDEX_op_qemu_st8:
1320 tcg_out_qemu_st(s, args, 0);
1321 break;
1322 case INDEX_op_qemu_st16:
1323 tcg_out_qemu_st(s, args, 1);
1324 break;
1325 case INDEX_op_qemu_st32:
1326 tcg_out_qemu_st(s, args, 2);
1327 break;
1328 case INDEX_op_qemu_st64:
1329 tcg_out_qemu_st(s, args, 3);
1330 break;
1331
1332 default:
1333 tcg_dump_ops (s, stderr);
1334 tcg_abort ();
1335 }
1336}
1337
1338static const TCGTargetOpDef ppc_op_defs[] = {
1339 { INDEX_op_exit_tb, { } },
1340 { INDEX_op_goto_tb, { } },
1341 { INDEX_op_call, { "rJ" } },
1342 { INDEX_op_jmp, { "rJ" } },
1343 { INDEX_op_br, { } },
1344
1345 { INDEX_op_mov_i32, { "r", "r" } },
1346 { INDEX_op_movi_i32, { "r" } },
1347 { INDEX_op_ld8u_i32, { "r", "r" } },
1348 { INDEX_op_ld8s_i32, { "r", "r" } },
1349 { INDEX_op_ld16u_i32, { "r", "r" } },
1350 { INDEX_op_ld16s_i32, { "r", "r" } },
1351 { INDEX_op_ld_i32, { "r", "r" } },
1352 { INDEX_op_st8_i32, { "r", "r" } },
1353 { INDEX_op_st16_i32, { "r", "r" } },
1354 { INDEX_op_st_i32, { "r", "r" } },
1355
1356 { INDEX_op_add_i32, { "r", "r", "ri" } },
1357 { INDEX_op_mul_i32, { "r", "r", "ri" } },
1358 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1359 { INDEX_op_div2_i32, { "r", "r", "r", "r", "r" } },
1360 { INDEX_op_divu2_i32, { "r", "r", "r", "r", "r" } },
1361 { INDEX_op_sub_i32, { "r", "r", "ri" } },
1362 { INDEX_op_and_i32, { "r", "r", "ri" } },
1363 { INDEX_op_or_i32, { "r", "r", "ri" } },
1364 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1365
1366 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1367 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1368 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1369
1370 { INDEX_op_brcond_i32, { "r", "ri" } },
1371
1372 { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1373 { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1374 { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1375
1376 { INDEX_op_neg_i32, { "r", "r" } },
1377
1378#if TARGET_LONG_BITS == 32
1379 { INDEX_op_qemu_ld8u, { "r", "L" } },
1380 { INDEX_op_qemu_ld8s, { "r", "L" } },
1381 { INDEX_op_qemu_ld16u, { "r", "L" } },
1382 { INDEX_op_qemu_ld16s, { "r", "L" } },
1383 { INDEX_op_qemu_ld32u, { "r", "L" } },
1384 { INDEX_op_qemu_ld32s, { "r", "L" } },
1385 { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1386
1387 { INDEX_op_qemu_st8, { "K", "K" } },
1388 { INDEX_op_qemu_st16, { "K", "K" } },
1389 { INDEX_op_qemu_st32, { "K", "K" } },
1390 { INDEX_op_qemu_st64, { "M", "M", "M" } },
1391#else
1392 { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1393 { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1394 { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1395 { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1396 { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1397 { INDEX_op_qemu_ld32s, { "r", "L", "L" } },
1398 { INDEX_op_qemu_ld64, { "r", "L", "L", "L" } },
1399
1400 { INDEX_op_qemu_st8, { "K", "K", "K" } },
1401 { INDEX_op_qemu_st16, { "K", "K", "K" } },
1402 { INDEX_op_qemu_st32, { "K", "K", "K" } },
1403 { INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
1404#endif
1405
1406 { -1 },
1407};
1408
1409void tcg_target_init(TCGContext *s)
1410{
1411 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1412 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1413 (1 << TCG_REG_R0) |
1414 (1 << TCG_REG_R3) |
1415 (1 << TCG_REG_R4) |
1416 (1 << TCG_REG_R5) |
1417 (1 << TCG_REG_R6) |
1418 (1 << TCG_REG_R7) |
1419 (1 << TCG_REG_R8) |
1420 (1 << TCG_REG_R9) |
1421 (1 << TCG_REG_R10) |
1422 (1 << TCG_REG_R11) |
1423 (1 << TCG_REG_R12)
1424 );
1425
1426 tcg_regset_clear(s->reserved_regs);
1427 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
1428 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
1429 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
1430
1431 tcg_add_target_add_op_defs(ppc_op_defs);
1432}