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