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