diff --git a/Makefile.target b/Makefile.target index 0c33f856ab..ff105c1fa5 100644 --- a/Makefile.target +++ b/Makefile.target @@ -121,10 +121,12 @@ ifeq ($(ARCH),sparc) endif ifeq ($(ARCH),sparc64) - CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 OP_CFLAGS+=-mcpu=ultrasparc -m64 -fno-delayed-branch -ffixed-i0 ifneq ($(CONFIG_SOLARIS),yes) - OP_CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 + CFLAGS+=-ffixed-g5 -ffixed-g6 -ffixed-g7 + OP_CFLAGS+=-ffixed-g5 -ffixed-g6 -ffixed-g7 + else + CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 endif endif diff --git a/dyngen-exec.h b/dyngen-exec.h index 2b616a941a..4caf9ffb57 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -146,10 +146,9 @@ extern int printf(const char *, ...); #define AREG4 "g6" #else #ifdef __sparc_v9__ -#define AREG0 "g1" -#define AREG1 "g4" -#define AREG2 "g5" -#define AREG3 "g7" +#define AREG0 "g5" +#define AREG1 "g6" +#define AREG2 "g7" #else #define AREG0 "g6" #define AREG1 "g1" diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 58f86d35a7..33fb9b4315 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -839,16 +839,34 @@ 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; break; case INDEX_op_call: - if (const_args[0]) { - tcg_out32(s, CALL | ((((tcg_target_ulong)args[0] - - (tcg_target_ulong)s->code_ptr) >> 2) - & 0x3fffffff)); - tcg_out_nop(s); - } 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)); - tcg_out_nop(s); + { + unsigned int st_op, ld_op; + +#ifdef __arch64__ + st_op = STX; + ld_op = LDX; +#else + st_op = STW; + ld_op = LDUW; +#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); } break; case INDEX_op_jmp: diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 4a0c831d2b..ea99c888c5 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -72,14 +72,15 @@ enum { #define TCG_CT_CONST_S13 0x200 /* used for function call generation */ -#define TCG_REG_CALL_STACK TCG_REG_O6 +#define TCG_REG_CALL_STACK TCG_REG_I6 #ifdef __arch64__ -#define TCG_TARGET_STACK_MINFRAME 176 -#define TCG_TARGET_CALL_STACK_OFFSET (2047 + 176) +// Reserve space for AREG0 +#define TCG_TARGET_STACK_MINFRAME (176 + 2 * sizeof(long)) +#define TCG_TARGET_CALL_STACK_OFFSET (2047 + TCG_TARGET_STACK_MINFRAME) #define TCG_TARGET_STACK_ALIGN 16 #else -#define TCG_TARGET_STACK_MINFRAME 92 -#define TCG_TARGET_CALL_STACK_OFFSET 92 +#define TCG_TARGET_STACK_MINFRAME (92 + 2 * sizeof(long)) +#define TCG_TARGET_CALL_STACK_OFFSET TCG_TARGET_STACK_MINFRAME #define TCG_TARGET_STACK_ALIGN 8 #endif @@ -90,7 +91,7 @@ enum { //#define TCG_TARGET_HAS_neg_i64 -/* Note: must be synced with dyngen-exec.h */ +/* Note: must be synced with dyngen-exec.h and Makefile.target */ #ifdef HOST_SOLARIS #define TCG_AREG0 TCG_REG_G2 #define TCG_AREG1 TCG_REG_G3 @@ -98,10 +99,9 @@ enum { #define TCG_AREG3 TCG_REG_G5 #define TCG_AREG4 TCG_REG_G6 #elif defined(__sparc_v9__) -#define TCG_AREG0 TCG_REG_G1 -#define TCG_AREG1 TCG_REG_G4 -#define TCG_AREG2 TCG_REG_G5 -#define TCG_AREG3 TCG_REG_G7 +#define TCG_AREG0 TCG_REG_G5 +#define TCG_AREG1 TCG_REG_G6 +#define TCG_AREG2 TCG_REG_G7 #else #define TCG_AREG0 TCG_REG_G6 #define TCG_AREG1 TCG_REG_G1