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