Restore AREG0 after calls

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5018 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
blueswir1 2008-08-17 14:34:27 +00:00
parent 2ae72bce02
commit bffe143153
1 changed files with 64 additions and 73 deletions

View File

@ -491,11 +491,28 @@ static const void * const qemu_st_helpers[4] = {
}; };
#endif #endif
#if TARGET_LONG_BITS == 32
#define TARGET_LD_OP LDUW
#else
#define TARGET_LD_OP LDX
#endif
#ifdef __arch64__
#define HOST_LD_OP LDX
#define HOST_ST_OP STX
#define HOST_SLL_OP SHIFT_SLLX
#define HOST_SRA_OP SHIFT_SRAX
#else
#define HOST_LD_OP LDUW
#define HOST_ST_OP STW
#define HOST_SLL_OP SHIFT_SLL
#define HOST_SRA_OP SHIFT_SRA
#endif
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int opc) int opc)
{ {
int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits; int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits;
int target_ld_op, host_ld_op, sll_op, sra_op;
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
uint32_t *label1_ptr, *label2_ptr; uint32_t *label1_ptr, *label2_ptr;
#endif #endif
@ -509,23 +526,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
arg1 = TCG_REG_O1; arg1 = TCG_REG_O1;
arg2 = TCG_REG_O2; arg2 = TCG_REG_O2;
#if TARGET_LONG_BITS == 32
target_ld_op = LDUW;
#else
target_ld_op = LDX;
#endif
#ifdef __arch64__
host_ld_op = LDX;
sll_op = SHIFT_SLLX;
sra_op = SHIFT_SRAX;
#else
host_ld_op = LDUW;
sll_op = SHIFT_SLL;
sra_op = SHIFT_SRA;
#endif
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
/* srl addr_reg, x, arg1 */ /* srl addr_reg, x, arg1 */
tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
@ -545,7 +545,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD); tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD);
/* ld [arg1], arg2 */ /* ld [arg1], arg2 */
tcg_out32(s, target_ld_op | INSN_RD(arg2) | INSN_RS1(arg1) | tcg_out32(s, TARGET_LD_OP | INSN_RD(arg2) | INSN_RS1(arg1) |
INSN_RS2(TCG_REG_G0)); INSN_RS2(TCG_REG_G0));
/* subcc arg0, arg2, %g0 */ /* subcc arg0, arg2, %g0 */
@ -559,37 +559,45 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* mov (delay slot) */ /* mov (delay slot) */
tcg_out_mov(s, arg0, addr_reg); tcg_out_mov(s, arg0, addr_reg);
/* mov */
tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
/* XXX: move that code at the end of the TB */ /* XXX: move that code at the end of the TB */
/* qemu_ld_helper[s_bits](arg0, arg1) */ /* qemu_ld_helper[s_bits](arg0, arg1) */
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits] tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits]
- (tcg_target_ulong)s->code_ptr) >> 2) - (tcg_target_ulong)s->code_ptr) >> 2)
& 0x3fffffff)); & 0x3fffffff));
/* mov (delay slot) */ /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); global registers */
// delay slot
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP);
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP);
/* data_reg = sign_extend(arg0) */ /* data_reg = sign_extend(arg0) */
switch(opc) { switch(opc) {
case 0 | 4: case 0 | 4:
/* sll arg0, 24/56, data_reg */ /* sll arg0, 24/56, data_reg */
tcg_out_arithi(s, data_reg, arg0, (int)sizeof(tcg_target_long) * 8 - 8, tcg_out_arithi(s, data_reg, arg0, (int)sizeof(tcg_target_long) * 8 - 8,
sll_op); HOST_SLL_OP);
/* sra data_reg, 24/56, data_reg */ /* sra data_reg, 24/56, data_reg */
tcg_out_arithi(s, data_reg, data_reg, tcg_out_arithi(s, data_reg, data_reg,
(int)sizeof(tcg_target_long) * 8 - 8, sra_op); (int)sizeof(tcg_target_long) * 8 - 8, HOST_SRA_OP);
break; break;
case 1 | 4: case 1 | 4:
/* sll arg0, 16/48, data_reg */ /* sll arg0, 16/48, data_reg */
tcg_out_arithi(s, data_reg, arg0, tcg_out_arithi(s, data_reg, arg0,
(int)sizeof(tcg_target_long) * 8 - 16, sll_op); (int)sizeof(tcg_target_long) * 8 - 16, HOST_SLL_OP);
/* sra data_reg, 16/48, data_reg */ /* sra data_reg, 16/48, data_reg */
tcg_out_arithi(s, data_reg, data_reg, tcg_out_arithi(s, data_reg, data_reg,
(int)sizeof(tcg_target_long) * 8 - 16, sra_op); (int)sizeof(tcg_target_long) * 8 - 16, HOST_SRA_OP);
break; break;
case 2 | 4: case 2 | 4:
/* sll arg0, 32, data_reg */ /* sll arg0, 32, data_reg */
tcg_out_arithi(s, data_reg, arg0, 32, sll_op); tcg_out_arithi(s, data_reg, arg0, 32, HOST_SLL_OP);
/* sra data_reg, 32, data_reg */ /* sra data_reg, 32, data_reg */
tcg_out_arithi(s, data_reg, data_reg, 32, sra_op); tcg_out_arithi(s, data_reg, data_reg, 32, HOST_SRA_OP);
break; break;
case 0: case 0:
case 1: case 1:
@ -616,7 +624,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* ld [arg1 + x], arg1 */ /* ld [arg1 + x], arg1 */
tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) - tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) -
offsetof(CPUTLBEntry, addr_read), host_ld_op); offsetof(CPUTLBEntry, addr_read), HOST_LD_OP);
/* add addr_reg, arg1, arg0 */ /* add addr_reg, arg1, arg0 */
tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD); tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD);
#else #else
@ -693,7 +701,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
int opc) int opc)
{ {
int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits; int addr_reg, data_reg, arg0, arg1, arg2, mem_index, s_bits;
int target_ld_op, host_ld_op;
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
uint32_t *label1_ptr, *label2_ptr; uint32_t *label1_ptr, *label2_ptr;
#endif #endif
@ -708,18 +715,6 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
arg1 = TCG_REG_O1; arg1 = TCG_REG_O1;
arg2 = TCG_REG_O2; arg2 = TCG_REG_O2;
#if TARGET_LONG_BITS == 32
target_ld_op = LDUW;
#else
target_ld_op = LDX;
#endif
#ifdef __arch64__
host_ld_op = LDX;
#else
host_ld_op = LDUW;
#endif
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
/* srl addr_reg, x, arg1 */ /* srl addr_reg, x, arg1 */
tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, tcg_out_arithi(s, arg1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
@ -740,7 +735,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD); tcg_out_arith(s, arg1, TCG_AREG0, arg1, ARITH_ADD);
/* ld [arg1], arg2 */ /* ld [arg1], arg2 */
tcg_out32(s, target_ld_op | INSN_RD(arg2) | INSN_RS1(arg1) | tcg_out32(s, TARGET_LD_OP | INSN_RD(arg2) | INSN_RS1(arg1) |
INSN_RS2(TCG_REG_G0)); INSN_RS2(TCG_REG_G0));
/* subcc arg0, arg2, %g0 */ /* subcc arg0, arg2, %g0 */
@ -757,13 +752,21 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* mov */ /* mov */
tcg_out_mov(s, arg1, data_reg); tcg_out_mov(s, arg1, data_reg);
/* mov */
tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index);
/* XXX: move that code at the end of the TB */ /* XXX: move that code at the end of the TB */
/* qemu_st_helper[s_bits](arg0, arg1, arg2) */ /* qemu_st_helper[s_bits](arg0, arg1, arg2) */
tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits] tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits]
- (tcg_target_ulong)s->code_ptr) >> 2) - (tcg_target_ulong)s->code_ptr) >> 2)
& 0x3fffffff)); & 0x3fffffff));
/* mov (delay slot) */ /* Store AREG0 in stack to avoid ugly glibc bugs that mangle
tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index); global registers */
// delay slot
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP);
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP);
/* will become: /* will become:
ba label2 */ ba label2 */
@ -780,7 +783,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* ld [arg1 + x], arg1 */ /* ld [arg1 + x], arg1 */
tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) - tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) -
offsetof(CPUTLBEntry, addr_write), host_ld_op); offsetof(CPUTLBEntry, addr_write), HOST_LD_OP);
/* add addr_reg, arg1, arg0 */ /* add addr_reg, arg1, arg0 */
tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD); tcg_out_arith(s, arg0, addr_reg, arg1, ARITH_ADD);
@ -862,35 +865,23 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
break; break;
case INDEX_op_call: case INDEX_op_call:
{ if (const_args[0])
unsigned int st_op, ld_op; tcg_out32(s, CALL | ((((tcg_target_ulong)args[0]
- (tcg_target_ulong)s->code_ptr) >> 2)
#ifdef __arch64__ & 0x3fffffff));
st_op = STX; else {
ld_op = LDX; tcg_out_ld_ptr(s, TCG_REG_I5,
#else (tcg_target_long)(s->tb_next + args[0]));
st_op = STW; tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) |
ld_op = LDUW; INSN_RS2(TCG_REG_G0));
#endif
if (const_args[0])
tcg_out32(s, CALL | ((((tcg_target_ulong)args[0]
- (tcg_target_ulong)s->code_ptr) >> 2)
& 0x3fffffff));
else {
tcg_out_ld_ptr(s, TCG_REG_I5,
(tcg_target_long)(s->tb_next + args[0]));
tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) |
INSN_RS2(TCG_REG_G0));
}
/* Store AREG0 in stack to avoid ugly glibc bugs that mangle
global registers */
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - sizeof(long),
st_op); // delay slot
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - sizeof(long),
ld_op);
} }
/* Store AREG0 in stack to avoid ugly glibc bugs that mangle
global registers */
// delay slot
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP);
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP);
break; break;
case INDEX_op_jmp: case INDEX_op_jmp:
case INDEX_op_br: case INDEX_op_br: