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