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