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