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