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,7 +71,6 @@ static const int tcg_target_reg_alloc_order[TCG_TARGET_NB_REGS] = { | ||
| 71 | TCG_REG_I2, | 71 | TCG_REG_I2, |
| 72 | TCG_REG_I3, | 72 | TCG_REG_I3, |
| 73 | TCG_REG_I4, | 73 | TCG_REG_I4, |
| 74 | - TCG_REG_I5, | ||
| 75 | }; | 74 | }; |
| 76 | 75 | ||
| 77 | static const int tcg_target_call_iarg_regs[6] = { | 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,8 +160,11 @@ static inline int tcg_target_const_match(tcg_target_long val, | ||
| 161 | #define INSN_RS2(x) (x) | 160 | #define INSN_RS2(x) (x) |
| 162 | 161 | ||
| 163 | #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) | 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 | #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) | 169 | #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) |
| 168 | #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) | 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,6 +215,10 @@ static inline void tcg_out_mov(TCGContext *s, int ret, int arg) | ||
| 213 | static inline void tcg_out_movi(TCGContext *s, TCGType type, | 215 | static inline void tcg_out_movi(TCGContext *s, TCGType type, |
| 214 | int ret, tcg_target_long arg) | 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 | if (arg == (arg & 0xfff)) | 222 | if (arg == (arg & 0xfff)) |
| 217 | tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(TCG_REG_G0) | | 223 | tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(TCG_REG_G0) | |
| 218 | INSN_IMM13(arg)); | 224 | INSN_IMM13(arg)); |
| @@ -232,6 +238,21 @@ static inline void tcg_out_ld_raw(TCGContext *s, int ret, | @@ -232,6 +238,21 @@ static inline void tcg_out_ld_raw(TCGContext *s, int ret, | ||
| 232 | INSN_IMM13(arg & 0x3ff)); | 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 | static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op) | 256 | static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op) |
| 236 | { | 257 | { |
| 237 | if (offset == (offset & 0xfff)) | 258 | if (offset == (offset & 0xfff)) |
| @@ -290,6 +311,12 @@ static inline void tcg_out_nop(TCGContext *s) | @@ -290,6 +311,12 @@ static inline void tcg_out_nop(TCGContext *s) | ||
| 290 | tcg_out32(s, SETHI | INSN_RD(TCG_REG_G0) | 0); | 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 | static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | 320 | static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
| 294 | const int *const_args) | 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,22 +324,31 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 297 | 324 | ||
| 298 | switch (opc) { | 325 | switch (opc) { |
| 299 | case INDEX_op_exit_tb: | 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 | INSN_IMM13(8)); | 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 | break; | 332 | break; |
| 305 | case INDEX_op_goto_tb: | 333 | case INDEX_op_goto_tb: |
| 306 | if (s->tb_jmp_offset) { | 334 | if (s->tb_jmp_offset) { |
| 307 | /* direct jump method */ | 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 | s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; | 345 | s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; |
| 310 | } else { | 346 | } else { |
| 311 | /* indirect jump method */ | 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 | tcg_out_nop(s); | 352 | tcg_out_nop(s); |
| 317 | s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; | 353 | s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; |
| 318 | break; | 354 | break; |
| @@ -323,7 +359,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -323,7 +359,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 323 | & 0x3fffffff)); | 359 | & 0x3fffffff)); |
| 324 | tcg_out_nop(s); | 360 | tcg_out_nop(s); |
| 325 | } else { | 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 | tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_O7) | | 363 | tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_O7) | |
| 328 | INSN_RS2(TCG_REG_G0)); | 364 | INSN_RS2(TCG_REG_G0)); |
| 329 | tcg_out_nop(s); | 365 | tcg_out_nop(s); |
| @@ -514,7 +550,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -514,7 +550,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 514 | 550 | ||
| 515 | static const TCGTargetOpDef sparc_op_defs[] = { | 551 | static const TCGTargetOpDef sparc_op_defs[] = { |
| 516 | { INDEX_op_exit_tb, { } }, | 552 | { INDEX_op_exit_tb, { } }, |
| 517 | - { INDEX_op_goto_tb, { "r" } }, | 553 | + { INDEX_op_goto_tb, { } }, |
| 518 | { INDEX_op_call, { "ri" } }, | 554 | { INDEX_op_call, { "ri" } }, |
| 519 | { INDEX_op_jmp, { "ri" } }, | 555 | { INDEX_op_jmp, { "ri" } }, |
| 520 | { INDEX_op_br, { } }, | 556 | { INDEX_op_br, { } }, |
| @@ -596,13 +632,19 @@ void tcg_target_init(TCGContext *s) | @@ -596,13 +632,19 @@ void tcg_target_init(TCGContext *s) | ||
| 596 | tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); | 632 | tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); |
| 597 | #endif | 633 | #endif |
| 598 | tcg_regset_set32(tcg_target_call_clobber_regs, 0, | 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 | (1 << TCG_REG_O0) | | 642 | (1 << TCG_REG_O0) | |
| 600 | (1 << TCG_REG_O1) | | 643 | (1 << TCG_REG_O1) | |
| 601 | (1 << TCG_REG_O2) | | 644 | (1 << TCG_REG_O2) | |
| 602 | (1 << TCG_REG_O3) | | 645 | (1 << TCG_REG_O3) | |
| 603 | (1 << TCG_REG_O4) | | 646 | (1 << TCG_REG_O4) | |
| 604 | (1 << TCG_REG_O5) | | 647 | (1 << TCG_REG_O5) | |
| 605 | - (1 << TCG_REG_O6) | | ||
| 606 | (1 << TCG_REG_O7)); | 648 | (1 << TCG_REG_O7)); |
| 607 | 649 | ||
| 608 | tcg_regset_clear(s->reserved_regs); | 650 | tcg_regset_clear(s->reserved_regs); |
tcg/sparc/tcg-target.h
| @@ -75,10 +75,18 @@ enum { | @@ -75,10 +75,18 @@ enum { | ||
| 75 | #define TCG_REG_CALL_STACK TCG_REG_O6 | 75 | #define TCG_REG_CALL_STACK TCG_REG_O6 |
| 76 | #define TCG_TARGET_STACK_ALIGN 16 | 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 | /* optional instructions */ | 84 | /* optional instructions */ |
| 79 | //#define TCG_TARGET_HAS_bswap_i32 | 85 | //#define TCG_TARGET_HAS_bswap_i32 |
| 80 | //#define TCG_TARGET_HAS_bswap_i64 | 86 | //#define TCG_TARGET_HAS_bswap_i64 |
| 81 | 87 | ||
| 88 | +#define TCG_TARGET_NEEDS_PROLOGUE 1 | ||
| 89 | + | ||
| 82 | /* Note: must be synced with dyngen-exec.h */ | 90 | /* Note: must be synced with dyngen-exec.h */ |
| 83 | #ifdef HOST_SOLARIS | 91 | #ifdef HOST_SOLARIS |
| 84 | #define TCG_AREG0 TCG_REG_G2 | 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,6 +1685,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, | ||
| 1685 | macro_op_index = -1; | 1685 | macro_op_index = -1; |
| 1686 | args = gen_opparam_buf; | 1686 | args = gen_opparam_buf; |
| 1687 | op_index = 0; | 1687 | op_index = 0; |
| 1688 | + | ||
| 1689 | +#ifdef TCG_TARGET_NEEDS_PROLOGUE | ||
| 1690 | + tcg_target_prologue(s); | ||
| 1691 | +#endif | ||
| 1692 | + | ||
| 1688 | for(;;) { | 1693 | for(;;) { |
| 1689 | opc = gen_opc_buf[op_index]; | 1694 | opc = gen_opc_buf[op_index]; |
| 1690 | #ifdef CONFIG_PROFILER | 1695 | #ifdef CONFIG_PROFILER |