|
|
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,
154: /* TCG_REG_R27, */ /* currently used for the global env, so no
155: need to save */
156: TCG_REG_R28,
157: TCG_REG_R29,
158: TCG_REG_R30,
159: TCG_REG_R31
160: };
161:
162: static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
163: {
164: tcg_target_long disp;
165:
166: disp = target - (tcg_target_long) pc;
167: if ((disp << 38) >> 38 != disp)
168: tcg_abort ();
169:
170: return disp & 0x3fffffc;
171: }
172:
173: static void reloc_pc24 (void *pc, tcg_target_long target)
174: {
175: *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
176: | reloc_pc24_val (pc, target);
177: }
178:
179: static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
180: {
181: tcg_target_long disp;
182:
183: disp = target - (tcg_target_long) pc;
184: if (disp != (int16_t) disp)
185: tcg_abort ();
186:
187: return disp & 0xfffc;
188: }
189:
190: static void reloc_pc14 (void *pc, tcg_target_long target)
191: {
192: *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
193: | reloc_pc14_val (pc, target);
194: }
195:
196: static void patch_reloc (uint8_t *code_ptr, int type,
197: tcg_target_long value, tcg_target_long addend)
198: {
199: value += addend;
200: switch (type) {
201: case R_PPC_REL14:
202: reloc_pc14 (code_ptr, value);
203: break;
204: case R_PPC_REL24:
205: reloc_pc24 (code_ptr, value);
206: break;
207: default:
208: tcg_abort ();
209: }
210: }
211:
212: /* maximum number of register used for input function arguments */
213: static int tcg_target_get_call_iarg_regs_count (int flags)
214: {
215: return ARRAY_SIZE (tcg_target_call_iarg_regs);
216: }
217:
218: /* parse target specific constraints */
219: static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str)
220: {
221: const char *ct_str;
222:
223: ct_str = *pct_str;
224: switch (ct_str[0]) {
225: case 'A': case 'B': case 'C': case 'D':
226: ct->ct |= TCG_CT_REG;
227: tcg_regset_set_reg (ct->u.regs, 3 + ct_str[0] - 'A');
228: break;
229: case 'r':
230: ct->ct |= TCG_CT_REG;
231: tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
232: break;
233: case 'L': /* qemu_ld constraint */
234: ct->ct |= TCG_CT_REG;
235: tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
236: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
237: #ifdef CONFIG_SOFTMMU
238: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
239: #endif
240: break;
241: case 'S': /* qemu_st constraint */
242: ct->ct |= TCG_CT_REG;
243: tcg_regset_set32 (ct->u.regs, 0, 0xffffffff);
244: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
245: #ifdef CONFIG_SOFTMMU
246: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4);
247: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5);
248: #endif
249: break;
250: case 'Z':
251: ct->ct |= TCG_CT_CONST_U32;
252: break;
253: default:
254: return -1;
255: }
256: ct_str++;
257: *pct_str = ct_str;
258: return 0;
259: }
260:
261: /* test if a constant matches the constraint */
262: static int tcg_target_const_match (tcg_target_long val,
263: const TCGArgConstraint *arg_ct)
264: {
265: int ct;
266:
267: ct = arg_ct->ct;
268: if (ct & TCG_CT_CONST)
269: return 1;
270: else if ((ct & TCG_CT_CONST_U32) && (val == (uint32_t) val))
271: return 1;
272: return 0;
273: }
274:
275: #define OPCD(opc) ((opc)<<26)
276: #define XO19(opc) (OPCD(19)|((opc)<<1))
277: #define XO30(opc) (OPCD(30)|((opc)<<2))
278: #define XO31(opc) (OPCD(31)|((opc)<<1))
279: #define XO58(opc) (OPCD(58)|(opc))
280: #define XO62(opc) (OPCD(62)|(opc))
281:
282: #define B OPCD( 18)
283: #define BC OPCD( 16)
284: #define LBZ OPCD( 34)
285: #define LHZ OPCD( 40)
286: #define LHA OPCD( 42)
287: #define LWZ OPCD( 32)
288: #define STB OPCD( 38)
289: #define STH OPCD( 44)
290: #define STW OPCD( 36)
291:
292: #define STD XO62( 0)
293: #define STDU XO62( 1)
294: #define STDX XO31(149)
295:
296: #define LD XO58( 0)
297: #define LDX XO31( 21)
298: #define LDU XO58( 1)
299: #define LWA XO58( 2)
300: #define LWAX XO31(341)
301:
1.1.1.4 root 302: #define ADDIC OPCD( 12)
1.1 root 303: #define ADDI OPCD( 14)
304: #define ADDIS OPCD( 15)
305: #define ORI OPCD( 24)
306: #define ORIS OPCD( 25)
307: #define XORI OPCD( 26)
308: #define XORIS OPCD( 27)
309: #define ANDI OPCD( 28)
310: #define ANDIS OPCD( 29)
311: #define MULLI OPCD( 7)
312: #define CMPLI OPCD( 10)
313: #define CMPI OPCD( 11)
314:
315: #define LWZU OPCD( 33)
316: #define STWU OPCD( 37)
317:
318: #define RLWINM OPCD( 21)
319:
320: #define RLDICL XO30( 0)
321: #define RLDICR XO30( 1)
322: #define RLDIMI XO30( 3)
323:
324: #define BCLR XO19( 16)
325: #define BCCTR XO19(528)
326: #define CRAND XO19(257)
327: #define CRANDC XO19(129)
328: #define CRNAND XO19(225)
329: #define CROR XO19(449)
1.1.1.4 root 330: #define CRNOR XO19( 33)
1.1 root 331:
332: #define EXTSB XO31(954)
333: #define EXTSH XO31(922)
334: #define EXTSW XO31(986)
335: #define ADD XO31(266)
336: #define ADDE XO31(138)
337: #define ADDC XO31( 10)
338: #define AND XO31( 28)
339: #define SUBF XO31( 40)
340: #define SUBFC XO31( 8)
341: #define SUBFE XO31(136)
342: #define OR XO31(444)
343: #define XOR XO31(316)
344: #define MULLW XO31(235)
345: #define MULHWU XO31( 11)
346: #define DIVW XO31(491)
347: #define DIVWU XO31(459)
348: #define CMP XO31( 0)
349: #define CMPL XO31( 32)
350: #define LHBRX XO31(790)
351: #define LWBRX XO31(534)
352: #define STHBRX XO31(918)
353: #define STWBRX XO31(662)
354: #define MFSPR XO31(339)
355: #define MTSPR XO31(467)
356: #define SRAWI XO31(824)
357: #define NEG XO31(104)
1.1.1.4 root 358: #define MFCR XO31( 19)
359: #define CNTLZW XO31( 26)
360: #define CNTLZD XO31( 58)
1.1 root 361:
362: #define MULLD XO31(233)
363: #define MULHD XO31( 73)
364: #define MULHDU XO31( 9)
365: #define DIVD XO31(489)
366: #define DIVDU XO31(457)
367:
368: #define LBZX XO31( 87)
1.1.1.3 root 369: #define LHZX XO31(279)
1.1 root 370: #define LHAX XO31(343)
371: #define LWZX XO31( 23)
372: #define STBX XO31(215)
373: #define STHX XO31(407)
374: #define STWX XO31(151)
375:
376: #define SPR(a,b) ((((a)<<5)|(b))<<11)
377: #define LR SPR(8, 0)
378: #define CTR SPR(9, 0)
379:
380: #define SLW XO31( 24)
381: #define SRW XO31(536)
382: #define SRAW XO31(792)
383:
384: #define SLD XO31( 27)
385: #define SRD XO31(539)
386: #define SRAD XO31(794)
387: #define SRADI XO31(413<<1)
388:
389: #define TW XO31( 4)
390: #define TRAP (TW | TO (31))
391:
392: #define RT(r) ((r)<<21)
393: #define RS(r) ((r)<<21)
394: #define RA(r) ((r)<<16)
395: #define RB(r) ((r)<<11)
396: #define TO(t) ((t)<<21)
397: #define SH(s) ((s)<<11)
398: #define MB(b) ((b)<<6)
399: #define ME(e) ((e)<<1)
400: #define BO(o) ((o)<<21)
401: #define MB64(b) ((b)<<5)
402:
403: #define LK 1
404:
405: #define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
406: #define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
407:
408: #define BF(n) ((n)<<23)
409: #define BI(n, c) (((c)+((n)*4))<<16)
410: #define BT(n, c) (((c)+((n)*4))<<21)
411: #define BA(n, c) (((c)+((n)*4))<<16)
412: #define BB(n, c) (((c)+((n)*4))<<11)
413:
414: #define BO_COND_TRUE BO (12)
415: #define BO_COND_FALSE BO ( 4)
416: #define BO_ALWAYS BO (20)
417:
418: enum {
419: CR_LT,
420: CR_GT,
421: CR_EQ,
422: CR_SO
423: };
424:
425: static const uint32_t tcg_to_bc[10] = {
426: [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
427: [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
428: [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
429: [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
430: [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
431: [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
432: [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
433: [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
434: [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
435: [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
436: };
437:
1.1.1.4 root 438: static void tcg_out_mov (TCGContext *s, TCGType type, int ret, int arg)
1.1 root 439: {
440: tcg_out32 (s, OR | SAB (arg, ret, arg));
441: }
442:
443: static void tcg_out_rld (TCGContext *s, int op, int ra, int rs, int sh, int mb)
444: {
445: sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1);
446: mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f));
447: tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb);
448: }
449:
450: static void tcg_out_movi32 (TCGContext *s, int ret, int32_t arg)
451: {
452: if (arg == (int16_t) arg)
453: tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
454: else {
455: tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
456: if (arg & 0xffff)
457: tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
458: }
459: }
460:
461: static void tcg_out_movi (TCGContext *s, TCGType type,
462: int ret, tcg_target_long arg)
463: {
464: int32_t arg32 = arg;
1.1.1.4 root 465: arg = type == TCG_TYPE_I32 ? arg & 0xffffffff : arg;
1.1 root 466:
1.1.1.4 root 467: if (arg == arg32) {
1.1 root 468: tcg_out_movi32 (s, ret, arg32);
469: }
470: else {
471: if ((uint64_t) arg >> 32) {
472: uint16_t h16 = arg >> 16;
473: uint16_t l16 = arg;
474:
475: tcg_out_movi32 (s, ret, arg >> 32);
476: tcg_out_rld (s, RLDICR, ret, ret, 32, 31);
477: if (h16) tcg_out32 (s, ORIS | RS (ret) | RA (ret) | h16);
478: if (l16) tcg_out32 (s, ORI | RS (ret) | RA (ret) | l16);
479: }
480: else {
481: tcg_out_movi32 (s, ret, arg32);
482: if (arg32 < 0)
483: tcg_out_rld (s, RLDICL, ret, ret, 0, 32);
484: }
485: }
486: }
487:
1.1.1.4 root 488: static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
489: {
490: tcg_target_long disp;
491:
492: disp = target - (tcg_target_long) s->code_ptr;
493: if ((disp << 38) >> 38 == disp)
494: tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
495: else {
496: tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target);
497: tcg_out32 (s, MTSPR | RS (0) | CTR);
498: tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
499: }
500: }
501:
1.1 root 502: static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
503: {
1.1.1.4 root 504: #ifdef __APPLE__
505: if (const_arg) {
506: tcg_out_b (s, LK, arg);
507: }
508: else {
509: tcg_out32 (s, MTSPR | RS (arg) | LR);
510: tcg_out32 (s, BCLR | BO_ALWAYS | LK);
511: }
512: #else
1.1 root 513: int reg;
514:
515: if (const_arg) {
516: reg = 2;
517: tcg_out_movi (s, TCG_TYPE_I64, reg, arg);
518: }
519: else reg = arg;
520:
521: tcg_out32 (s, LD | RT (0) | RA (reg));
522: tcg_out32 (s, MTSPR | RA (0) | CTR);
523: tcg_out32 (s, LD | RT (11) | RA (reg) | 16);
524: tcg_out32 (s, LD | RT (2) | RA (reg) | 8);
525: tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
1.1.1.4 root 526: #endif
1.1 root 527: }
528:
529: static void tcg_out_ldst (TCGContext *s, int ret, int addr,
530: int offset, int op1, int op2)
531: {
532: if (offset == (int16_t) offset)
533: tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
534: else {
535: tcg_out_movi (s, TCG_TYPE_I64, 0, offset);
536: tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
537: }
538: }
539:
540: static void tcg_out_ldsta (TCGContext *s, int ret, int addr,
541: int offset, int op1, int op2)
542: {
543: if (offset == (int16_t) (offset & ~3))
544: tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
545: else {
546: tcg_out_movi (s, TCG_TYPE_I64, 0, offset);
547: tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
548: }
549: }
550:
551: #if defined (CONFIG_SOFTMMU)
552:
553: #include "../../softmmu_defs.h"
554:
555: static void *qemu_ld_helpers[4] = {
556: __ldb_mmu,
557: __ldw_mmu,
558: __ldl_mmu,
559: __ldq_mmu,
560: };
561:
562: static void *qemu_st_helpers[4] = {
563: __stb_mmu,
564: __stw_mmu,
565: __stl_mmu,
566: __stq_mmu,
567: };
568:
569: static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2,
570: int addr_reg, int s_bits, int offset)
571: {
572: #if TARGET_LONG_BITS == 32
573: tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32);
574:
575: tcg_out32 (s, (RLWINM
576: | RA (r0)
577: | RS (addr_reg)
578: | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
579: | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
580: | ME (31 - CPU_TLB_ENTRY_BITS)
581: )
582: );
583: tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
584: tcg_out32 (s, (LWZU | RT (r1) | RA (r0) | offset));
585: tcg_out32 (s, (RLWINM
586: | RA (r2)
587: | RS (addr_reg)
588: | SH (0)
589: | MB ((32 - s_bits) & 31)
590: | ME (31 - TARGET_PAGE_BITS)
591: )
592: );
593: #else
594: tcg_out_rld (s, RLDICL, r0, addr_reg,
595: 64 - TARGET_PAGE_BITS,
596: 64 - CPU_TLB_BITS);
597: tcg_out_rld (s, RLDICR, r0, r0,
598: CPU_TLB_ENTRY_BITS,
599: 63 - CPU_TLB_ENTRY_BITS);
600:
601: tcg_out32 (s, ADD | TAB (r0, r0, TCG_AREG0));
602: tcg_out32 (s, LD_ADDR | RT (r1) | RA (r0) | offset);
603:
604: if (!s_bits) {
605: tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS);
606: }
607: else {
608: tcg_out_rld (s, RLDICL, r2, addr_reg,
609: 64 - TARGET_PAGE_BITS,
610: TARGET_PAGE_BITS - s_bits);
611: tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0);
612: }
613: #endif
614: }
615: #endif
616:
617: static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
618: {
1.1.1.3 root 619: int addr_reg, data_reg, r0, r1, rbase, mem_index, s_bits, bswap;
1.1 root 620: #ifdef CONFIG_SOFTMMU
621: int r2;
622: void *label1_ptr, *label2_ptr;
623: #endif
624:
625: data_reg = *args++;
626: addr_reg = *args++;
627: mem_index = *args;
628: s_bits = opc & 3;
629:
630: #ifdef CONFIG_SOFTMMU
631: r0 = 3;
632: r1 = 4;
633: r2 = 0;
1.1.1.3 root 634: rbase = 0;
1.1 root 635:
636: tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits,
637: offsetof (CPUState, tlb_table[mem_index][0].addr_read));
638:
639: tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
640:
641: label1_ptr = s->code_ptr;
642: #ifdef FAST_PATH
643: tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
644: #endif
645:
646: /* slow path */
1.1.1.4 root 647: tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg);
1.1 root 648: tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index);
649:
650: tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
651:
652: switch (opc) {
653: case 0|4:
654: tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
655: break;
656: case 1|4:
657: tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
658: break;
659: case 2|4:
660: tcg_out32 (s, EXTSW | RA (data_reg) | RS (3));
661: break;
662: case 0:
663: case 1:
664: case 2:
665: case 3:
666: if (data_reg != 3)
1.1.1.4 root 667: tcg_out_mov (s, TCG_TYPE_I64, data_reg, 3);
1.1 root 668: break;
669: }
670: label2_ptr = s->code_ptr;
671: tcg_out32 (s, B);
672:
673: /* label1: fast path */
674: #ifdef FAST_PATH
675: reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
676: #endif
677:
678: /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
1.1.1.4 root 679: tcg_out32 (s, (LD
1.1 root 680: | RT (r0)
681: | RA (r0)
682: | (offsetof (CPUTLBEntry, addend)
683: - offsetof (CPUTLBEntry, addr_read))
684: ));
685: /* r0 = env->tlb_table[mem_index][index].addend */
686: tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
687: /* r0 = env->tlb_table[mem_index][index].addend + addr */
688:
689: #else /* !CONFIG_SOFTMMU */
690: #if TARGET_LONG_BITS == 32
691: tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32);
692: #endif
693: r0 = addr_reg;
694: r1 = 3;
1.1.1.3 root 695: rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
1.1 root 696: #endif
697:
698: #ifdef TARGET_WORDS_BIGENDIAN
699: bswap = 0;
700: #else
701: bswap = 1;
702: #endif
703: switch (opc) {
704: default:
705: case 0:
1.1.1.3 root 706: tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
1.1 root 707: break;
708: case 0|4:
1.1.1.3 root 709: tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
1.1 root 710: tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
711: break;
712: case 1:
1.1.1.3 root 713: if (bswap)
714: tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
715: else
716: tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0));
1.1 root 717: break;
718: case 1|4:
719: if (bswap) {
1.1.1.3 root 720: tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
1.1 root 721: tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
722: }
1.1.1.3 root 723: else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0));
1.1 root 724: break;
725: case 2:
1.1.1.3 root 726: if (bswap)
727: tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
728: else
729: tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0));
1.1 root 730: break;
731: case 2|4:
732: if (bswap) {
1.1.1.3 root 733: tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
1.1 root 734: tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg));
735: }
1.1.1.3 root 736: else tcg_out32 (s, LWAX | TAB (data_reg, rbase, r0));
1.1 root 737: break;
738: case 3:
1.1.1.3 root 739: #ifdef CONFIG_USE_GUEST_BASE
740: if (bswap) {
741: tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
742: tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
743: tcg_out32 (s, LWBRX | TAB ( r1, rbase, r1));
744: tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
745: }
746: else tcg_out32 (s, LDX | TAB (data_reg, rbase, r0));
747: #else
1.1 root 748: if (bswap) {
1.1.1.5 ! root 749: tcg_out_movi32 (s, 0, 4);
1.1 root 750: tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
751: tcg_out32 (s, LWBRX | RT ( r1) | RA (r0));
752: tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
753: }
754: else tcg_out32 (s, LD | RT (data_reg) | RA (r0));
1.1.1.3 root 755: #endif
1.1 root 756: break;
757: }
758:
759: #ifdef CONFIG_SOFTMMU
760: reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
761: #endif
762: }
763:
764: static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
765: {
1.1.1.3 root 766: int addr_reg, r0, r1, rbase, data_reg, mem_index, bswap;
1.1 root 767: #ifdef CONFIG_SOFTMMU
768: int r2;
769: void *label1_ptr, *label2_ptr;
770: #endif
771:
772: data_reg = *args++;
773: addr_reg = *args++;
774: mem_index = *args;
775:
776: #ifdef CONFIG_SOFTMMU
777: r0 = 3;
778: r1 = 4;
779: r2 = 0;
1.1.1.3 root 780: rbase = 0;
1.1 root 781:
782: tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc,
783: offsetof (CPUState, tlb_table[mem_index][0].addr_write));
784:
785: tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L);
786:
787: label1_ptr = s->code_ptr;
788: #ifdef FAST_PATH
789: tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
790: #endif
791:
792: /* slow path */
1.1.1.4 root 793: tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg);
1.1 root 794: tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc)));
795: tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index);
796:
797: tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
798:
799: label2_ptr = s->code_ptr;
800: tcg_out32 (s, B);
801:
802: /* label1: fast path */
803: #ifdef FAST_PATH
804: reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
805: #endif
806:
1.1.1.4 root 807: tcg_out32 (s, (LD
1.1 root 808: | RT (r0)
809: | RA (r0)
810: | (offsetof (CPUTLBEntry, addend)
811: - offsetof (CPUTLBEntry, addr_write))
812: ));
813: /* r0 = env->tlb_table[mem_index][index].addend */
814: tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
815: /* r0 = env->tlb_table[mem_index][index].addend + addr */
816:
817: #else /* !CONFIG_SOFTMMU */
818: #if TARGET_LONG_BITS == 32
819: tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32);
820: #endif
821: r1 = 3;
822: r0 = addr_reg;
1.1.1.3 root 823: rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
1.1 root 824: #endif
825:
826: #ifdef TARGET_WORDS_BIGENDIAN
827: bswap = 0;
828: #else
829: bswap = 1;
830: #endif
831: switch (opc) {
832: case 0:
1.1.1.3 root 833: tcg_out32 (s, STBX | SAB (data_reg, rbase, r0));
1.1 root 834: break;
835: case 1:
1.1.1.3 root 836: if (bswap)
837: tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0));
838: else
839: tcg_out32 (s, STHX | SAB (data_reg, rbase, r0));
1.1 root 840: break;
841: case 2:
1.1.1.3 root 842: if (bswap)
843: tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
844: else
845: tcg_out32 (s, STWX | SAB (data_reg, rbase, r0));
1.1 root 846: break;
847: case 3:
848: if (bswap) {
1.1.1.3 root 849: tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
1.1 root 850: tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
851: tcg_out_rld (s, RLDICL, 0, data_reg, 32, 0);
1.1.1.3 root 852: tcg_out32 (s, STWBRX | SAB (0, rbase, r1));
1.1 root 853: }
1.1.1.3 root 854: else tcg_out32 (s, STDX | SAB (data_reg, rbase, r0));
1.1 root 855: break;
856: }
857:
858: #ifdef CONFIG_SOFTMMU
859: reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
860: #endif
861: }
862:
1.1.1.4 root 863: static void tcg_target_qemu_prologue (TCGContext *s)
1.1 root 864: {
865: int i, frame_size;
1.1.1.4 root 866: #ifndef __APPLE__
1.1 root 867: uint64_t addr;
1.1.1.4 root 868: #endif
1.1 root 869:
870: frame_size = 0
871: + 8 /* back chain */
872: + 8 /* CR */
873: + 8 /* LR */
874: + 8 /* compiler doubleword */
875: + 8 /* link editor doubleword */
876: + 8 /* TOC save area */
877: + TCG_STATIC_CALL_ARGS_SIZE
878: + ARRAY_SIZE (tcg_target_callee_save_regs) * 8
879: ;
880: frame_size = (frame_size + 15) & ~15;
881:
1.1.1.4 root 882: #ifndef __APPLE__
1.1 root 883: /* First emit adhoc function descriptor */
884: addr = (uint64_t) s->code_ptr + 24;
885: tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */
886: s->code_ptr += 16; /* skip TOC and environment pointer */
1.1.1.4 root 887: #endif
1.1 root 888:
889: /* Prologue */
890: tcg_out32 (s, MFSPR | RT (0) | LR);
891: tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff));
892: for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
893: tcg_out32 (s, (STD
894: | RS (tcg_target_callee_save_regs[i])
895: | RA (1)
896: | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
897: )
898: );
899: tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16));
900:
1.1.1.3 root 901: #ifdef CONFIG_USE_GUEST_BASE
1.1.1.4 root 902: if (GUEST_BASE) {
903: tcg_out_movi (s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE);
904: tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
905: }
1.1.1.3 root 906: #endif
907:
1.1 root 908: tcg_out32 (s, MTSPR | RS (3) | CTR);
909: tcg_out32 (s, BCCTR | BO_ALWAYS);
910:
911: /* Epilogue */
912: tb_ret_addr = s->code_ptr;
913:
914: for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
915: tcg_out32 (s, (LD
916: | RT (tcg_target_callee_save_regs[i])
917: | RA (1)
918: | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE)
919: )
920: );
921: tcg_out32 (s, LD | RT (0) | RA (1) | (frame_size + 16));
922: tcg_out32 (s, MTSPR | RS (0) | LR);
923: tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
924: tcg_out32 (s, BCLR | BO_ALWAYS);
925: }
926:
927: static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
928: tcg_target_long arg2)
929: {
930: if (type == TCG_TYPE_I32)
931: tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
932: else
933: tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
934: }
935:
936: static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
937: tcg_target_long arg2)
938: {
939: if (type == TCG_TYPE_I32)
940: tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
941: else
942: tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX);
943: }
944:
945: static void ppc_addi32 (TCGContext *s, int rt, int ra, tcg_target_long si)
946: {
947: if (!si && rt == ra)
948: return;
949:
950: if (si == (int16_t) si)
951: tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
952: else {
953: uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
954: tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
955: tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
956: }
957: }
958:
959: static void ppc_addi64 (TCGContext *s, int rt, int ra, tcg_target_long si)
960: {
961: /* XXX: suboptimal */
962: if (si == (int16_t) si
963: || ((((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0))
964: ppc_addi32 (s, rt, ra, si);
965: else {
966: tcg_out_movi (s, TCG_TYPE_I64, 0, si);
967: tcg_out32 (s, ADD | RT (rt) | RA (ra));
968: }
969: }
970:
971: static void tcg_out_addi (TCGContext *s, int reg, tcg_target_long val)
972: {
973: ppc_addi64 (s, reg, reg, val);
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.