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