|
|
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: #ifndef NDEBUG
26: static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
27: "%r0",
28: "%r1",
29: "%rp",
30: "%r3",
31: "%r4",
32: "%r5",
33: "%r6",
34: "%r7",
35: "%r8",
36: "%r9",
37: "%r10",
38: "%r11",
39: "%r12",
40: "%r13",
41: "%r14",
42: "%r15",
43: "%r16",
44: "%r17",
45: "%r18",
46: "%r19",
47: "%r20",
48: "%r21",
49: "%r22",
50: "%r23",
51: "%r24",
52: "%r25",
53: "%r26",
54: "%dp",
55: "%ret0",
56: "%ret1",
57: "%sp",
58: "%r31",
59: };
60: #endif
61:
62: static const int tcg_target_reg_alloc_order[] = {
63: TCG_REG_R4,
64: TCG_REG_R5,
65: TCG_REG_R6,
66: TCG_REG_R7,
67: TCG_REG_R8,
68: TCG_REG_R9,
69: TCG_REG_R10,
70: TCG_REG_R11,
71: TCG_REG_R12,
72: TCG_REG_R13,
73:
74: TCG_REG_R17,
75: TCG_REG_R14,
76: TCG_REG_R15,
77: TCG_REG_R16,
78: };
79:
80: static const int tcg_target_call_iarg_regs[4] = {
81: TCG_REG_R26,
82: TCG_REG_R25,
83: TCG_REG_R24,
84: TCG_REG_R23,
85: };
86:
87: static const int tcg_target_call_oarg_regs[2] = {
88: TCG_REG_RET0,
89: TCG_REG_RET1,
90: };
91:
92: static void patch_reloc(uint8_t *code_ptr, int type,
93: tcg_target_long value, tcg_target_long addend)
94: {
95: switch (type) {
96: case R_PARISC_PCREL17F:
97: hppa_patch17f((uint32_t *)code_ptr, value, addend);
98: break;
99: default:
100: tcg_abort();
101: }
102: }
103:
104: /* maximum number of register used for input function arguments */
105: static inline int tcg_target_get_call_iarg_regs_count(int flags)
106: {
107: return 4;
108: }
109:
110: /* parse target specific constraints */
111: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
112: {
113: const char *ct_str;
114:
115: ct_str = *pct_str;
116: switch (ct_str[0]) {
117: case 'r':
118: ct->ct |= TCG_CT_REG;
119: tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
120: break;
121: case 'L': /* qemu_ld/st constraint */
122: ct->ct |= TCG_CT_REG;
123: tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
124: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R26);
125: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R25);
126: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R24);
127: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R23);
128: break;
129: default:
130: return -1;
131: }
132: ct_str++;
133: *pct_str = ct_str;
134: return 0;
135: }
136:
137: /* test if a constant matches the constraint */
138: static inline int tcg_target_const_match(tcg_target_long val,
139: const TCGArgConstraint *arg_ct)
140: {
141: int ct;
142:
143: ct = arg_ct->ct;
144:
145: /* TODO */
146:
147: return 0;
148: }
149:
150: #define INSN_OP(x) ((x) << 26)
151: #define INSN_EXT3BR(x) ((x) << 13)
152: #define INSN_EXT3SH(x) ((x) << 10)
153: #define INSN_EXT4(x) ((x) << 6)
154: #define INSN_EXT5(x) (x)
155: #define INSN_EXT6(x) ((x) << 6)
156: #define INSN_EXT7(x) ((x) << 6)
157: #define INSN_EXT8A(x) ((x) << 6)
158: #define INSN_EXT8B(x) ((x) << 5)
159: #define INSN_T(x) (x)
160: #define INSN_R1(x) ((x) << 16)
161: #define INSN_R2(x) ((x) << 21)
162: #define INSN_DEP_LEN(x) (32 - (x))
163: #define INSN_SHDEP_CP(x) ((31 - (x)) << 5)
164: #define INSN_SHDEP_P(x) ((x) << 5)
165: #define INSN_COND(x) ((x) << 13)
166:
167: #define COND_NEVER 0
168: #define COND_EQUAL 1
169: #define COND_LT 2
170: #define COND_LTEQ 3
171: #define COND_LTU 4
172: #define COND_LTUEQ 5
173: #define COND_SV 6
174: #define COND_OD 7
175:
176:
177: /* Logical ADD */
178: #define ARITH_ADD (INSN_OP(0x02) | INSN_EXT6(0x28))
179: #define ARITH_AND (INSN_OP(0x02) | INSN_EXT6(0x08))
180: #define ARITH_OR (INSN_OP(0x02) | INSN_EXT6(0x09))
181: #define ARITH_XOR (INSN_OP(0x02) | INSN_EXT6(0x0a))
182: #define ARITH_SUB (INSN_OP(0x02) | INSN_EXT6(0x10))
183:
184: #define SHD (INSN_OP(0x34) | INSN_EXT3SH(2))
185: #define VSHD (INSN_OP(0x34) | INSN_EXT3SH(0))
186: #define DEP (INSN_OP(0x35) | INSN_EXT3SH(3))
187: #define ZDEP (INSN_OP(0x35) | INSN_EXT3SH(2))
188: #define ZVDEP (INSN_OP(0x35) | INSN_EXT3SH(0))
189: #define EXTRU (INSN_OP(0x34) | INSN_EXT3SH(6))
190: #define EXTRS (INSN_OP(0x34) | INSN_EXT3SH(7))
191: #define VEXTRS (INSN_OP(0x34) | INSN_EXT3SH(5))
192:
193: #define SUBI (INSN_OP(0x25))
194: #define MTCTL (INSN_OP(0x00) | INSN_EXT8B(0xc2))
195:
196: #define BL (INSN_OP(0x3a) | INSN_EXT3BR(0))
197: #define BLE_SR4 (INSN_OP(0x39) | (1 << 13))
198: #define BV (INSN_OP(0x3a) | INSN_EXT3BR(6))
199: #define BV_N (INSN_OP(0x3a) | INSN_EXT3BR(6) | 2)
200: #define LDIL (INSN_OP(0x08))
201: #define LDO (INSN_OP(0x0d))
202:
203: #define LDB (INSN_OP(0x10))
204: #define LDH (INSN_OP(0x11))
205: #define LDW (INSN_OP(0x12))
206: #define LDWM (INSN_OP(0x13))
207:
208: #define STB (INSN_OP(0x18))
209: #define STH (INSN_OP(0x19))
210: #define STW (INSN_OP(0x1a))
211: #define STWM (INSN_OP(0x1b))
212:
213: #define COMBT (INSN_OP(0x20))
214: #define COMBF (INSN_OP(0x22))
215:
216: static int lowsignext(uint32_t val, int start, int length)
217: {
218: return (((val << 1) & ~(~0 << length)) |
219: ((val >> (length - 1)) & 1)) << start;
220: }
221:
222: static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
223: {
224: /* PA1.1 defines COPY as OR r,0,t */
225: tcg_out32(s, ARITH_OR | INSN_T(ret) | INSN_R1(arg) | INSN_R2(TCG_REG_R0));
226:
227: /* PA2.0 defines COPY as LDO 0(r),t
228: * but hppa-dis.c is unaware of this definition */
229: /* tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(arg) | reassemble_14(0)); */
230: }
231:
232: static inline void tcg_out_movi(TCGContext *s, TCGType type,
233: int ret, tcg_target_long arg)
234: {
235: if (arg == (arg & 0x1fff)) {
236: tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(TCG_REG_R0) |
237: reassemble_14(arg));
238: } else {
239: tcg_out32(s, LDIL | INSN_R2(ret) |
240: reassemble_21(lrsel((uint32_t)arg, 0)));
241: if (arg & 0x7ff)
242: tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(ret) |
243: reassemble_14(rrsel((uint32_t)arg, 0)));
244: }
245: }
246:
247: static inline void tcg_out_ld_raw(TCGContext *s, int ret,
248: tcg_target_long arg)
249: {
250: tcg_out32(s, LDIL | INSN_R2(ret) |
251: reassemble_21(lrsel((uint32_t)arg, 0)));
252: tcg_out32(s, LDW | INSN_R1(ret) | INSN_R2(ret) |
253: reassemble_14(rrsel((uint32_t)arg, 0)));
254: }
255:
256: static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
257: tcg_target_long arg)
258: {
259: tcg_out_ld_raw(s, ret, arg);
260: }
261:
262: static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset,
263: int op)
264: {
265: if (offset == (offset & 0xfff))
266: tcg_out32(s, op | INSN_R1(ret) | INSN_R2(addr) |
267: reassemble_14(offset));
268: else {
269: fprintf(stderr, "unimplemented %s with offset %d\n", __func__, offset);
270: tcg_abort();
271: }
272: }
273:
274: static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
275: int arg1, tcg_target_long arg2)
276: {
277: fprintf(stderr, "unimplemented %s\n", __func__);
278: tcg_abort();
279: }
280:
281: static inline void tcg_out_st(TCGContext *s, TCGType type, int ret,
282: int arg1, tcg_target_long arg2)
283: {
284: fprintf(stderr, "unimplemented %s\n", __func__);
285: tcg_abort();
286: }
287:
288: static inline void tcg_out_arith(TCGContext *s, int t, int r1, int r2, int op)
289: {
290: tcg_out32(s, op | INSN_T(t) | INSN_R1(r1) | INSN_R2(r2));
291: }
292:
293: static inline void tcg_out_arithi(TCGContext *s, int t, int r1,
294: tcg_target_long val, int op)
295: {
296: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R20, val);
297: tcg_out_arith(s, t, r1, TCG_REG_R20, op);
298: }
299:
300: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
301: {
302: tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
303: }
304:
305: static inline void tcg_out_nop(TCGContext *s)
306: {
307: tcg_out32(s, ARITH_OR | INSN_T(TCG_REG_R0) | INSN_R1(TCG_REG_R0) |
308: INSN_R2(TCG_REG_R0));
309: }
310:
311: static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg) {
312: tcg_out32(s, EXTRS | INSN_R1(ret) | INSN_R2(arg) |
313: INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
314: }
315:
316: static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg) {
317: tcg_out32(s, EXTRS | INSN_R1(ret) | INSN_R2(arg) |
318: INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
319: }
320:
321: static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg) {
322: if(ret != arg)
323: tcg_out_mov(s, ret, arg);
324: tcg_out32(s, DEP | INSN_R2(ret) | INSN_R1(ret) |
325: INSN_SHDEP_CP(15) | INSN_DEP_LEN(8));
326: tcg_out32(s, SHD | INSN_T(ret) | INSN_R1(TCG_REG_R0) |
327: INSN_R2(ret) | INSN_SHDEP_CP(8));
328: }
329:
330: static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg, int temp) {
331: tcg_out32(s, SHD | INSN_T(temp) | INSN_R1(arg) |
332: INSN_R2(arg) | INSN_SHDEP_CP(16));
333: tcg_out32(s, DEP | INSN_R2(temp) | INSN_R1(temp) |
334: INSN_SHDEP_CP(15) | INSN_DEP_LEN(8));
335: tcg_out32(s, SHD | INSN_T(ret) | INSN_R1(arg) |
336: INSN_R2(temp) | INSN_SHDEP_CP(8));
337: }
338:
339: static inline void tcg_out_call(TCGContext *s, void *func)
340: {
341: uint32_t val = (uint32_t)__canonicalize_funcptr_for_compare(func);
342: tcg_out32(s, LDIL | INSN_R2(TCG_REG_R20) |
343: reassemble_21(lrsel(val, 0)));
344: tcg_out32(s, BLE_SR4 | INSN_R2(TCG_REG_R20) |
345: reassemble_17(rrsel(val, 0) >> 2));
346: tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
347: }
348:
349: #if defined(CONFIG_SOFTMMU)
350:
351: #include "../../softmmu_defs.h"
352:
353: static void *qemu_ld_helpers[4] = {
354: __ldb_mmu,
355: __ldw_mmu,
356: __ldl_mmu,
357: __ldq_mmu,
358: };
359:
360: static void *qemu_st_helpers[4] = {
361: __stb_mmu,
362: __stw_mmu,
363: __stl_mmu,
364: __stq_mmu,
365: };
366: #endif
367:
368: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
369: {
370: int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
371: #if defined(CONFIG_SOFTMMU)
372: uint32_t *label1_ptr, *label2_ptr;
373: #endif
374: #if TARGET_LONG_BITS == 64
375: #if defined(CONFIG_SOFTMMU)
376: uint32_t *label3_ptr;
377: #endif
378: int addr_reg2;
379: #endif
380:
381: data_reg = *args++;
382: if (opc == 3)
383: data_reg2 = *args++;
384: else
1.1.1.2 ! root 385: data_reg2 = 0; /* suppress warning */
1.1 root 386: addr_reg = *args++;
387: #if TARGET_LONG_BITS == 64
388: addr_reg2 = *args++;
389: #endif
390: mem_index = *args;
391: s_bits = opc & 3;
392:
393: r0 = TCG_REG_R26;
394: r1 = TCG_REG_R25;
395:
396: #if defined(CONFIG_SOFTMMU)
397: tcg_out_mov(s, r1, addr_reg);
398:
399: tcg_out_mov(s, r0, addr_reg);
400:
401: tcg_out32(s, SHD | INSN_T(r1) | INSN_R1(TCG_REG_R0) | INSN_R2(r1) |
402: INSN_SHDEP_CP(TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS));
403:
404: tcg_out_arithi(s, r0, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
405: ARITH_AND);
406:
407: tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
408: ARITH_AND);
409:
410: tcg_out_arith(s, r1, r1, TCG_AREG0, ARITH_ADD);
411: tcg_out_arithi(s, r1, r1,
412: offsetof(CPUState, tlb_table[mem_index][0].addr_read),
413: ARITH_ADD);
414:
415: tcg_out_ldst(s, TCG_REG_R20, r1, 0, LDW);
416:
417: #if TARGET_LONG_BITS == 32
418: /* if equal, jump to label1 */
419: label1_ptr = (uint32_t *)s->code_ptr;
420: tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
421: INSN_COND(COND_EQUAL));
422: tcg_out_mov(s, r0, addr_reg); /* delay slot */
423: #else
424: /* if not equal, jump to label3 */
425: label3_ptr = (uint32_t *)s->code_ptr;
426: tcg_out32(s, COMBF | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
427: INSN_COND(COND_EQUAL));
428: tcg_out_mov(s, r0, addr_reg); /* delay slot */
429:
430: tcg_out_ldst(s, TCG_REG_R20, r1, 4, LDW);
431:
432: /* if equal, jump to label1 */
433: label1_ptr = (uint32_t *)s->code_ptr;
434: tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(addr_reg2) |
435: INSN_COND(COND_EQUAL));
436: tcg_out_nop(s); /* delay slot */
437:
438: /* label3: */
439: *label3_ptr |= reassemble_12((uint32_t *)s->code_ptr - label3_ptr - 2);
440: #endif
441:
442: #if TARGET_LONG_BITS == 32
443: tcg_out_mov(s, TCG_REG_R26, addr_reg);
444: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R25, mem_index);
445: #else
446: tcg_out_mov(s, TCG_REG_R26, addr_reg);
447: tcg_out_mov(s, TCG_REG_R25, addr_reg2);
448: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R24, mem_index);
449: #endif
450:
451: tcg_out_call(s, qemu_ld_helpers[s_bits]);
452:
453: switch(opc) {
454: case 0 | 4:
455: tcg_out_ext8s(s, data_reg, TCG_REG_RET0);
456: break;
457: case 1 | 4:
458: tcg_out_ext16s(s, data_reg, TCG_REG_RET0);
459: break;
460: case 0:
461: case 1:
462: case 2:
463: default:
464: tcg_out_mov(s, data_reg, TCG_REG_RET0);
465: break;
466: case 3:
467: tcg_abort();
468: tcg_out_mov(s, data_reg, TCG_REG_RET0);
469: tcg_out_mov(s, data_reg2, TCG_REG_RET1);
470: break;
471: }
472:
473: /* jump to label2 */
474: label2_ptr = (uint32_t *)s->code_ptr;
475: tcg_out32(s, BL | INSN_R2(TCG_REG_R0) | 2);
476:
477: /* label1: */
478: *label1_ptr |= reassemble_12((uint32_t *)s->code_ptr - label1_ptr - 2);
479:
480: tcg_out_arithi(s, TCG_REG_R20, r1,
481: offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_read),
482: ARITH_ADD);
483: tcg_out_ldst(s, TCG_REG_R20, TCG_REG_R20, 0, LDW);
484: tcg_out_arith(s, r0, r0, TCG_REG_R20, ARITH_ADD);
485: #else
486: r0 = addr_reg;
487: #endif
488:
489: #ifdef TARGET_WORDS_BIGENDIAN
490: bswap = 0;
491: #else
492: bswap = 1;
493: #endif
494: switch (opc) {
495: case 0:
496: tcg_out_ldst(s, data_reg, r0, 0, LDB);
497: break;
498: case 0 | 4:
499: tcg_out_ldst(s, data_reg, r0, 0, LDB);
500: tcg_out_ext8s(s, data_reg, data_reg);
501: break;
502: case 1:
503: tcg_out_ldst(s, data_reg, r0, 0, LDH);
504: if (bswap)
505: tcg_out_bswap16(s, data_reg, data_reg);
506: break;
507: case 1 | 4:
508: tcg_out_ldst(s, data_reg, r0, 0, LDH);
509: if (bswap)
510: tcg_out_bswap16(s, data_reg, data_reg);
511: tcg_out_ext16s(s, data_reg, data_reg);
512: break;
513: case 2:
514: tcg_out_ldst(s, data_reg, r0, 0, LDW);
515: if (bswap)
516: tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
517: break;
518: case 3:
519: tcg_abort();
520: if (!bswap) {
521: tcg_out_ldst(s, data_reg, r0, 0, LDW);
522: tcg_out_ldst(s, data_reg2, r0, 4, LDW);
523: } else {
524: tcg_out_ldst(s, data_reg, r0, 4, LDW);
525: tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
526: tcg_out_ldst(s, data_reg2, r0, 0, LDW);
527: tcg_out_bswap32(s, data_reg2, data_reg2, TCG_REG_R20);
528: }
529: break;
530: default:
531: tcg_abort();
532: }
533:
534: #if defined(CONFIG_SOFTMMU)
535: /* label2: */
536: *label2_ptr |= reassemble_17((uint32_t *)s->code_ptr - label2_ptr - 2);
537: #endif
538: }
539:
540: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
541: {
542: int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
543: #if defined(CONFIG_SOFTMMU)
544: uint32_t *label1_ptr, *label2_ptr;
545: #endif
546: #if TARGET_LONG_BITS == 64
547: #if defined(CONFIG_SOFTMMU)
548: uint32_t *label3_ptr;
549: #endif
550: int addr_reg2;
551: #endif
552:
553: data_reg = *args++;
554: if (opc == 3)
555: data_reg2 = *args++;
556: else
1.1.1.2 ! root 557: data_reg2 = 0; /* suppress warning */
1.1 root 558: addr_reg = *args++;
559: #if TARGET_LONG_BITS == 64
560: addr_reg2 = *args++;
561: #endif
562: mem_index = *args;
563:
564: s_bits = opc;
565:
566: r0 = TCG_REG_R26;
567: r1 = TCG_REG_R25;
568:
569: #if defined(CONFIG_SOFTMMU)
570: tcg_out_mov(s, r1, addr_reg);
571:
572: tcg_out_mov(s, r0, addr_reg);
573:
574: tcg_out32(s, SHD | INSN_T(r1) | INSN_R1(TCG_REG_R0) | INSN_R2(r1) |
575: INSN_SHDEP_CP(TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS));
576:
577: tcg_out_arithi(s, r0, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
578: ARITH_AND);
579:
580: tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
581: ARITH_AND);
582:
583: tcg_out_arith(s, r1, r1, TCG_AREG0, ARITH_ADD);
584: tcg_out_arithi(s, r1, r1,
585: offsetof(CPUState, tlb_table[mem_index][0].addr_write),
586: ARITH_ADD);
587:
588: tcg_out_ldst(s, TCG_REG_R20, r1, 0, LDW);
589:
590: #if TARGET_LONG_BITS == 32
591: /* if equal, jump to label1 */
592: label1_ptr = (uint32_t *)s->code_ptr;
593: tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
594: INSN_COND(COND_EQUAL));
595: tcg_out_mov(s, r0, addr_reg); /* delay slot */
596: #else
597: /* if not equal, jump to label3 */
598: label3_ptr = (uint32_t *)s->code_ptr;
599: tcg_out32(s, COMBF | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
600: INSN_COND(COND_EQUAL));
601: tcg_out_mov(s, r0, addr_reg); /* delay slot */
602:
603: tcg_out_ldst(s, TCG_REG_R20, r1, 4, LDW);
604:
605: /* if equal, jump to label1 */
606: label1_ptr = (uint32_t *)s->code_ptr;
607: tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(addr_reg2) |
608: INSN_COND(COND_EQUAL));
609: tcg_out_nop(s); /* delay slot */
610:
611: /* label3: */
612: *label3_ptr |= reassemble_12((uint32_t *)s->code_ptr - label3_ptr - 2);
613: #endif
614:
615: tcg_out_mov(s, TCG_REG_R26, addr_reg);
616: #if TARGET_LONG_BITS == 64
617: tcg_out_mov(s, TCG_REG_R25, addr_reg2);
618: if (opc == 3) {
619: tcg_abort();
620: tcg_out_mov(s, TCG_REG_R24, data_reg);
621: tcg_out_mov(s, TCG_REG_R23, data_reg2);
622: /* TODO: push mem_index */
623: tcg_abort();
624: } else {
625: switch(opc) {
626: case 0:
627: tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R24) | INSN_R2(data_reg) |
628: INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
629: break;
630: case 1:
631: tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R24) | INSN_R2(data_reg) |
632: INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
633: break;
634: case 2:
635: tcg_out_mov(s, TCG_REG_R24, data_reg);
636: break;
637: }
638: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R23, mem_index);
639: }
640: #else
641: if (opc == 3) {
642: tcg_abort();
643: tcg_out_mov(s, TCG_REG_R25, data_reg);
644: tcg_out_mov(s, TCG_REG_R24, data_reg2);
645: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R23, mem_index);
646: } else {
647: switch(opc) {
648: case 0:
649: tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R25) | INSN_R2(data_reg) |
650: INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
651: break;
652: case 1:
653: tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R25) | INSN_R2(data_reg) |
654: INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
655: break;
656: case 2:
657: tcg_out_mov(s, TCG_REG_R25, data_reg);
658: break;
659: }
660: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R24, mem_index);
661: }
662: #endif
663: tcg_out_call(s, qemu_st_helpers[s_bits]);
664:
665: /* jump to label2 */
666: label2_ptr = (uint32_t *)s->code_ptr;
667: tcg_out32(s, BL | INSN_R2(TCG_REG_R0) | 2);
668:
669: /* label1: */
670: *label1_ptr |= reassemble_12((uint32_t *)s->code_ptr - label1_ptr - 2);
671:
672: tcg_out_arithi(s, TCG_REG_R20, r1,
673: offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_write),
674: ARITH_ADD);
675: tcg_out_ldst(s, TCG_REG_R20, TCG_REG_R20, 0, LDW);
676: tcg_out_arith(s, r0, r0, TCG_REG_R20, ARITH_ADD);
677: #else
678: r0 = addr_reg;
679: #endif
680:
681: #ifdef TARGET_WORDS_BIGENDIAN
682: bswap = 0;
683: #else
684: bswap = 1;
685: #endif
686: switch (opc) {
687: case 0:
688: tcg_out_ldst(s, data_reg, r0, 0, STB);
689: break;
690: case 1:
691: if (bswap) {
692: tcg_out_bswap16(s, TCG_REG_R20, data_reg);
693: data_reg = TCG_REG_R20;
694: }
695: tcg_out_ldst(s, data_reg, r0, 0, STH);
696: break;
697: case 2:
698: if (bswap) {
699: tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
700: data_reg = TCG_REG_R20;
701: }
702: tcg_out_ldst(s, data_reg, r0, 0, STW);
703: break;
704: case 3:
705: tcg_abort();
706: if (!bswap) {
707: tcg_out_ldst(s, data_reg, r0, 0, STW);
708: tcg_out_ldst(s, data_reg2, r0, 4, STW);
709: } else {
710: tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
711: tcg_out_ldst(s, TCG_REG_R20, r0, 4, STW);
712: tcg_out_bswap32(s, TCG_REG_R20, data_reg2, TCG_REG_R20);
713: tcg_out_ldst(s, TCG_REG_R20, r0, 0, STW);
714: }
715: break;
716: default:
717: tcg_abort();
718: }
719:
720: #if defined(CONFIG_SOFTMMU)
721: /* label2: */
722: *label2_ptr |= reassemble_17((uint32_t *)s->code_ptr - label2_ptr - 2);
723: #endif
724: }
725:
726: static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
727: const int *const_args)
728: {
729: int c;
730:
731: switch (opc) {
732: case INDEX_op_exit_tb:
733: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RET0, args[0]);
734: tcg_out32(s, BV_N | INSN_R2(TCG_REG_R18));
735: break;
736: case INDEX_op_goto_tb:
737: if (s->tb_jmp_offset) {
738: /* direct jump method */
739: fprintf(stderr, "goto_tb direct\n");
740: tcg_abort();
741: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R20, args[0]);
742: tcg_out32(s, BV_N | INSN_R2(TCG_REG_R20));
743: s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
744: } else {
745: /* indirect jump method */
746: tcg_out_ld_ptr(s, TCG_REG_R20,
747: (tcg_target_long)(s->tb_next + args[0]));
748: tcg_out32(s, BV_N | INSN_R2(TCG_REG_R20));
749: }
750: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
751: break;
752: case INDEX_op_call:
753: tcg_out32(s, BLE_SR4 | INSN_R2(args[0]));
754: tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
755: break;
756: case INDEX_op_jmp:
757: fprintf(stderr, "unimplemented jmp\n");
758: tcg_abort();
759: break;
760: case INDEX_op_br:
761: fprintf(stderr, "unimplemented br\n");
762: tcg_abort();
763: break;
764: case INDEX_op_movi_i32:
765: tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
766: break;
767:
768: case INDEX_op_ld8u_i32:
769: tcg_out_ldst(s, args[0], args[1], args[2], LDB);
770: break;
771: case INDEX_op_ld8s_i32:
772: tcg_out_ldst(s, args[0], args[1], args[2], LDB);
773: tcg_out_ext8s(s, args[0], args[0]);
774: break;
775: case INDEX_op_ld16u_i32:
776: tcg_out_ldst(s, args[0], args[1], args[2], LDH);
777: break;
778: case INDEX_op_ld16s_i32:
779: tcg_out_ldst(s, args[0], args[1], args[2], LDH);
780: tcg_out_ext16s(s, args[0], args[0]);
781: break;
782: case INDEX_op_ld_i32:
783: tcg_out_ldst(s, args[0], args[1], args[2], LDW);
784: break;
785:
786: case INDEX_op_st8_i32:
787: tcg_out_ldst(s, args[0], args[1], args[2], STB);
788: break;
789: case INDEX_op_st16_i32:
790: tcg_out_ldst(s, args[0], args[1], args[2], STH);
791: break;
792: case INDEX_op_st_i32:
793: tcg_out_ldst(s, args[0], args[1], args[2], STW);
794: break;
795:
796: case INDEX_op_sub_i32:
797: c = ARITH_SUB;
798: goto gen_arith;
799: case INDEX_op_and_i32:
800: c = ARITH_AND;
801: goto gen_arith;
802: case INDEX_op_or_i32:
803: c = ARITH_OR;
804: goto gen_arith;
805: case INDEX_op_xor_i32:
806: c = ARITH_XOR;
807: goto gen_arith;
808: case INDEX_op_add_i32:
809: c = ARITH_ADD;
810: goto gen_arith;
811:
812: case INDEX_op_shl_i32:
813: tcg_out32(s, SUBI | INSN_R1(TCG_REG_R20) | INSN_R2(args[2]) |
814: lowsignext(0x1f, 0, 11));
815: tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(TCG_REG_R20));
816: tcg_out32(s, ZVDEP | INSN_R2(args[0]) | INSN_R1(args[1]) |
817: INSN_DEP_LEN(32));
818: break;
819: case INDEX_op_shr_i32:
820: tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(args[2]));
821: tcg_out32(s, VSHD | INSN_T(args[0]) | INSN_R1(TCG_REG_R0) |
822: INSN_R2(args[1]));
823: break;
824: case INDEX_op_sar_i32:
825: tcg_out32(s, SUBI | INSN_R1(TCG_REG_R20) | INSN_R2(args[2]) |
826: lowsignext(0x1f, 0, 11));
827: tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(TCG_REG_R20));
828: tcg_out32(s, VEXTRS | INSN_R1(args[0]) | INSN_R2(args[1]) |
829: INSN_DEP_LEN(32));
830: break;
831:
832: case INDEX_op_mul_i32:
833: fprintf(stderr, "unimplemented mul\n");
834: tcg_abort();
835: break;
836: case INDEX_op_mulu2_i32:
837: fprintf(stderr, "unimplemented mulu2\n");
838: tcg_abort();
839: break;
840: case INDEX_op_div2_i32:
841: fprintf(stderr, "unimplemented div2\n");
842: tcg_abort();
843: break;
844: case INDEX_op_divu2_i32:
845: fprintf(stderr, "unimplemented divu2\n");
846: tcg_abort();
847: break;
848:
849: case INDEX_op_brcond_i32:
850: fprintf(stderr, "unimplemented brcond\n");
851: tcg_abort();
852: break;
853:
854: case INDEX_op_qemu_ld8u:
855: tcg_out_qemu_ld(s, args, 0);
856: break;
857: case INDEX_op_qemu_ld8s:
858: tcg_out_qemu_ld(s, args, 0 | 4);
859: break;
860: case INDEX_op_qemu_ld16u:
861: tcg_out_qemu_ld(s, args, 1);
862: break;
863: case INDEX_op_qemu_ld16s:
864: tcg_out_qemu_ld(s, args, 1 | 4);
865: break;
866: case INDEX_op_qemu_ld32u:
867: tcg_out_qemu_ld(s, args, 2);
868: break;
869:
870: case INDEX_op_qemu_st8:
871: tcg_out_qemu_st(s, args, 0);
872: break;
873: case INDEX_op_qemu_st16:
874: tcg_out_qemu_st(s, args, 1);
875: break;
876: case INDEX_op_qemu_st32:
877: tcg_out_qemu_st(s, args, 2);
878: break;
879:
880: default:
881: fprintf(stderr, "unknown opcode 0x%x\n", opc);
882: tcg_abort();
883: }
884: return;
885:
886: gen_arith:
887: tcg_out_arith(s, args[0], args[1], args[2], c);
888: }
889:
890: static const TCGTargetOpDef hppa_op_defs[] = {
891: { INDEX_op_exit_tb, { } },
892: { INDEX_op_goto_tb, { } },
893:
894: { INDEX_op_call, { "r" } },
895: { INDEX_op_jmp, { "r" } },
896: { INDEX_op_br, { } },
897:
898: { INDEX_op_mov_i32, { "r", "r" } },
899: { INDEX_op_movi_i32, { "r" } },
900: { INDEX_op_ld8u_i32, { "r", "r" } },
901: { INDEX_op_ld8s_i32, { "r", "r" } },
902: { INDEX_op_ld16u_i32, { "r", "r" } },
903: { INDEX_op_ld16s_i32, { "r", "r" } },
904: { INDEX_op_ld_i32, { "r", "r" } },
905: { INDEX_op_st8_i32, { "r", "r" } },
906: { INDEX_op_st16_i32, { "r", "r" } },
907: { INDEX_op_st_i32, { "r", "r" } },
908:
909: { INDEX_op_add_i32, { "r", "r", "r" } },
910: { INDEX_op_sub_i32, { "r", "r", "r" } },
911: { INDEX_op_and_i32, { "r", "r", "r" } },
912: { INDEX_op_or_i32, { "r", "r", "r" } },
913: { INDEX_op_xor_i32, { "r", "r", "r" } },
914:
915: { INDEX_op_shl_i32, { "r", "r", "r" } },
916: { INDEX_op_shr_i32, { "r", "r", "r" } },
917: { INDEX_op_sar_i32, { "r", "r", "r" } },
918:
919: { INDEX_op_brcond_i32, { "r", "r" } },
920:
921: #if TARGET_LONG_BITS == 32
922: { INDEX_op_qemu_ld8u, { "r", "L" } },
923: { INDEX_op_qemu_ld8s, { "r", "L" } },
924: { INDEX_op_qemu_ld16u, { "r", "L" } },
925: { INDEX_op_qemu_ld16s, { "r", "L" } },
926: { INDEX_op_qemu_ld32u, { "r", "L" } },
927: { INDEX_op_qemu_ld64, { "r", "r", "L" } },
928:
929: { INDEX_op_qemu_st8, { "L", "L" } },
930: { INDEX_op_qemu_st16, { "L", "L" } },
931: { INDEX_op_qemu_st32, { "L", "L" } },
932: { INDEX_op_qemu_st64, { "L", "L", "L" } },
933: #else
934: { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
935: { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
936: { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
937: { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
938: { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
939: { INDEX_op_qemu_ld32s, { "r", "L", "L" } },
940: { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
941:
942: { INDEX_op_qemu_st8, { "L", "L", "L" } },
943: { INDEX_op_qemu_st16, { "L", "L", "L" } },
944: { INDEX_op_qemu_st32, { "L", "L", "L" } },
945: { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
946: #endif
947: { -1 },
948: };
949:
950: void tcg_target_init(TCGContext *s)
951: {
952: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
953: tcg_regset_set32(tcg_target_call_clobber_regs, 0,
954: (1 << TCG_REG_R20) |
955: (1 << TCG_REG_R21) |
956: (1 << TCG_REG_R22) |
957: (1 << TCG_REG_R23) |
958: (1 << TCG_REG_R24) |
959: (1 << TCG_REG_R25) |
960: (1 << TCG_REG_R26));
961:
962: tcg_regset_clear(s->reserved_regs);
963: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* hardwired to zero */
964: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* addil target */
965: tcg_regset_set_reg(s->reserved_regs, TCG_REG_RP); /* link register */
966: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R3); /* frame pointer */
967: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R18); /* return pointer */
968: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R19); /* clobbered w/o pic */
969: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R20); /* reserved */
970: tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP); /* data pointer */
971: tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
972: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
973:
974: tcg_add_target_add_op_defs(hppa_op_defs);
975: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.