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