Commit b3db87581213138e8a90862816051ca5f885e6d5
1 parent
53cd9273
Add function prologue, fix pointer load on Sparc64 host
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4027 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
67 additions
and
12 deletions
tcg/sparc/tcg-target.c
... | ... | @@ -71,7 +71,6 @@ static const int tcg_target_reg_alloc_order[TCG_TARGET_NB_REGS] = { |
71 | 71 | TCG_REG_I2, |
72 | 72 | TCG_REG_I3, |
73 | 73 | TCG_REG_I4, |
74 | - TCG_REG_I5, | |
75 | 74 | }; |
76 | 75 | |
77 | 76 | static const int tcg_target_call_iarg_regs[6] = { |
... | ... | @@ -161,8 +160,11 @@ static inline int tcg_target_const_match(tcg_target_long val, |
161 | 160 | #define INSN_RS2(x) (x) |
162 | 161 | |
163 | 162 | #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) |
163 | +#define INSN_OFF22(x) (((x) >> 2) & 0x3fffff) | |
164 | 164 | |
165 | -#define INSN_COND(x, a) (((x) << 25) | ((a) << 29) | |
165 | +#define INSN_COND(x, a) (((x) << 25) | ((a) << 29)) | |
166 | +#define COND_A 0x8 | |
167 | +#define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2)) | |
166 | 168 | |
167 | 169 | #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) |
168 | 170 | #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) |
... | ... | @@ -213,6 +215,10 @@ static inline void tcg_out_mov(TCGContext *s, int ret, int arg) |
213 | 215 | static inline void tcg_out_movi(TCGContext *s, TCGType type, |
214 | 216 | int ret, tcg_target_long arg) |
215 | 217 | { |
218 | +#if defined(__sparc_v9__) && !defined(__sparc_v8plus__) | |
219 | + if (arg != (arg & 0xffffffff)) | |
220 | + fprintf(stderr, "unimplemented %s with constant %ld\n", __func__, arg); | |
221 | +#endif | |
216 | 222 | if (arg == (arg & 0xfff)) |
217 | 223 | tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(TCG_REG_G0) | |
218 | 224 | INSN_IMM13(arg)); |
... | ... | @@ -232,6 +238,21 @@ static inline void tcg_out_ld_raw(TCGContext *s, int ret, |
232 | 238 | INSN_IMM13(arg & 0x3ff)); |
233 | 239 | } |
234 | 240 | |
241 | +static inline void tcg_out_ld_ptr(TCGContext *s, int ret, | |
242 | + tcg_target_long arg) | |
243 | +{ | |
244 | +#if defined(__sparc_v9__) && !defined(__sparc_v8plus__) | |
245 | + if (arg != (arg & 0xffffffff)) | |
246 | + fprintf(stderr, "unimplemented %s with offset %ld\n", __func__, arg); | |
247 | + if (arg != (arg & 0xfff)) | |
248 | + tcg_out32(s, SETHI | INSN_RD(ret) | (((uint32_t)arg & 0xfffffc00) >> 10)); | |
249 | + tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) | | |
250 | + INSN_IMM13(arg & 0x3ff)); | |
251 | +#else | |
252 | + tcg_out_ld_raw(s, ret, arg); | |
253 | +#endif | |
254 | +} | |
255 | + | |
235 | 256 | static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op) |
236 | 257 | { |
237 | 258 | if (offset == (offset & 0xfff)) |
... | ... | @@ -290,6 +311,12 @@ static inline void tcg_out_nop(TCGContext *s) |
290 | 311 | tcg_out32(s, SETHI | INSN_RD(TCG_REG_G0) | 0); |
291 | 312 | } |
292 | 313 | |
314 | +static inline void tcg_target_prologue(TCGContext *s) | |
315 | +{ | |
316 | + tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) | | |
317 | + INSN_IMM13(-TCG_TARGET_STACK_MINFRAME)); | |
318 | +} | |
319 | + | |
293 | 320 | static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
294 | 321 | const int *const_args) |
295 | 322 | { |
... | ... | @@ -297,22 +324,31 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
297 | 324 | |
298 | 325 | switch (opc) { |
299 | 326 | case INDEX_op_exit_tb: |
300 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_O0, args[0]); | |
301 | - tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_O7) | | |
327 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]); | |
328 | + tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I7) | | |
302 | 329 | INSN_IMM13(8)); |
303 | - tcg_out_nop(s); | |
330 | + tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) | | |
331 | + INSN_RS2(TCG_REG_G0)); | |
304 | 332 | break; |
305 | 333 | case INDEX_op_goto_tb: |
306 | 334 | if (s->tb_jmp_offset) { |
307 | 335 | /* direct jump method */ |
308 | - tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_I5, args[0]); | |
336 | + if (ABS(args[0] - (unsigned long)s->code_ptr) == | |
337 | + (ABS(args[0] - (unsigned long)s->code_ptr) & 0x1fffff)) { | |
338 | + tcg_out32(s, BA | | |
339 | + INSN_OFF22(args[0] - (unsigned long)s->code_ptr)); | |
340 | + } else { | |
341 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, args[0]); | |
342 | + tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | | |
343 | + INSN_RS2(TCG_REG_G0)); | |
344 | + } | |
309 | 345 | s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; |
310 | 346 | } else { |
311 | 347 | /* indirect jump method */ |
312 | - tcg_out_ld_raw(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0])); | |
348 | + tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0])); | |
349 | + tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | | |
350 | + INSN_RS2(TCG_REG_G0)); | |
313 | 351 | } |
314 | - tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | | |
315 | - INSN_RS2(TCG_REG_G0)); | |
316 | 352 | tcg_out_nop(s); |
317 | 353 | s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; |
318 | 354 | break; |
... | ... | @@ -323,7 +359,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
323 | 359 | & 0x3fffffff)); |
324 | 360 | tcg_out_nop(s); |
325 | 361 | } else { |
326 | - tcg_out_ld_raw(s, TCG_REG_O7, (tcg_target_long)(s->tb_next + args[0])); | |
362 | + tcg_out_ld_ptr(s, TCG_REG_O7, (tcg_target_long)(s->tb_next + args[0])); | |
327 | 363 | tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_O7) | |
328 | 364 | INSN_RS2(TCG_REG_G0)); |
329 | 365 | tcg_out_nop(s); |
... | ... | @@ -514,7 +550,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
514 | 550 | |
515 | 551 | static const TCGTargetOpDef sparc_op_defs[] = { |
516 | 552 | { INDEX_op_exit_tb, { } }, |
517 | - { INDEX_op_goto_tb, { "r" } }, | |
553 | + { INDEX_op_goto_tb, { } }, | |
518 | 554 | { INDEX_op_call, { "ri" } }, |
519 | 555 | { INDEX_op_jmp, { "ri" } }, |
520 | 556 | { INDEX_op_br, { } }, |
... | ... | @@ -596,13 +632,19 @@ void tcg_target_init(TCGContext *s) |
596 | 632 | tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); |
597 | 633 | #endif |
598 | 634 | tcg_regset_set32(tcg_target_call_clobber_regs, 0, |
635 | + (1 << TCG_REG_G1) | | |
636 | + (1 << TCG_REG_G2) | | |
637 | + (1 << TCG_REG_G3) | | |
638 | + (1 << TCG_REG_G4) | | |
639 | + (1 << TCG_REG_G5) | | |
640 | + (1 << TCG_REG_G6) | | |
641 | + (1 << TCG_REG_G7) | | |
599 | 642 | (1 << TCG_REG_O0) | |
600 | 643 | (1 << TCG_REG_O1) | |
601 | 644 | (1 << TCG_REG_O2) | |
602 | 645 | (1 << TCG_REG_O3) | |
603 | 646 | (1 << TCG_REG_O4) | |
604 | 647 | (1 << TCG_REG_O5) | |
605 | - (1 << TCG_REG_O6) | | |
606 | 648 | (1 << TCG_REG_O7)); |
607 | 649 | |
608 | 650 | tcg_regset_clear(s->reserved_regs); | ... | ... |
tcg/sparc/tcg-target.h
... | ... | @@ -75,10 +75,18 @@ enum { |
75 | 75 | #define TCG_REG_CALL_STACK TCG_REG_O6 |
76 | 76 | #define TCG_TARGET_STACK_ALIGN 16 |
77 | 77 | |
78 | +#if defined(__sparc_v9__) && !defined(__sparc_v8plus__) | |
79 | +#define TCG_TARGET_STACK_MINFRAME 176 | |
80 | +#else | |
81 | +#define TCG_TARGET_STACK_MINFRAME 92 | |
82 | +#endif | |
83 | + | |
78 | 84 | /* optional instructions */ |
79 | 85 | //#define TCG_TARGET_HAS_bswap_i32 |
80 | 86 | //#define TCG_TARGET_HAS_bswap_i64 |
81 | 87 | |
88 | +#define TCG_TARGET_NEEDS_PROLOGUE 1 | |
89 | + | |
82 | 90 | /* Note: must be synced with dyngen-exec.h */ |
83 | 91 | #ifdef HOST_SOLARIS |
84 | 92 | #define TCG_AREG0 TCG_REG_G2 | ... | ... |
tcg/tcg.c
... | ... | @@ -1685,6 +1685,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, |
1685 | 1685 | macro_op_index = -1; |
1686 | 1686 | args = gen_opparam_buf; |
1687 | 1687 | op_index = 0; |
1688 | + | |
1689 | +#ifdef TCG_TARGET_NEEDS_PROLOGUE | |
1690 | + tcg_target_prologue(s); | |
1691 | +#endif | |
1692 | + | |
1688 | 1693 | for(;;) { |
1689 | 1694 | opc = gen_opc_buf[op_index]; |
1690 | 1695 | #ifdef CONFIG_PROFILER | ... | ... |