diff --git a/configure b/configure index 94a1cdbf45..bbef4c6389 100755 --- a/configure +++ b/configure @@ -1291,24 +1291,30 @@ case "$target_cpu" in ;; sparc) echo "TARGET_ARCH=sparc" >> $config_mak + echo "CONFIG_NO_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"sparc\"" >> $config_h echo "#define TARGET_SPARC 1" >> $config_h + echo "#define CONFIG_NO_DYNGEN_OP 1" >> $config_h ;; sparc64) echo "TARGET_ARCH=sparc64" >> $config_mak + echo "CONFIG_NO_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"sparc64\"" >> $config_h echo "#define TARGET_SPARC 1" >> $config_h echo "#define TARGET_SPARC64 1" >> $config_h + echo "#define CONFIG_NO_DYNGEN_OP 1" >> $config_h elfload32="yes" ;; sparc32plus) echo "TARGET_ARCH=sparc64" >> $config_mak echo "TARGET_ABI_DIR=sparc" >> $config_mak echo "TARGET_ARCH2=sparc32plus" >> $config_mak + echo "CONFIG_NO_DYNGEN_OP=yes" >> $config_mak echo "#define TARGET_ARCH \"sparc64\"" >> $config_h echo "#define TARGET_SPARC 1" >> $config_h echo "#define TARGET_SPARC64 1" >> $config_h echo "#define TARGET_ABI32 1" >> $config_h + echo "#define CONFIG_NO_DYNGEN_OP 1" >> $config_h ;; *) echo "Unsupported target CPU" diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index fee26981e6..ee30bf54e2 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -250,7 +250,7 @@ typedef struct CPUSPARCState { float_status fp_status; #if defined(TARGET_SPARC64) #define MAXTL 4 - uint64_t t0, t1, t2; + uint64_t t0; trap_state *tsptr; trap_state ts[MAXTL]; uint32_t xcc; /* Extended integer condition codes */ @@ -271,9 +271,7 @@ typedef struct CPUSPARCState { uint64_t hpstate, htstate[MAXTL], hintp, htba, hver, hstick_cmpr, ssr; void *hstick; // UA 2005 #endif -#if !defined(TARGET_SPARC64) && !defined(reg_T2) - target_ulong t2; -#endif + target_ulong t1, t2; } CPUSPARCState; #if defined(TARGET_SPARC64) #define GET_FSR32(env) (env->fsr & 0xcfc1ffff) diff --git a/target-sparc/exec.h b/target-sparc/exec.h index d49812003c..8badf1a70c 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -7,12 +7,10 @@ register struct CPUSPARCState *env asm(AREG0); #ifdef TARGET_SPARC64 #define T0 (env->t0) -#define T1 (env->t1) #define T2 (env->t2) #define REGWPTR env->regwptr #else register uint32_t T0 asm(AREG1); -register uint32_t T1 asm(AREG2); #undef REG_REGWPTR // Broken #ifdef REG_REGWPTR diff --git a/target-sparc/helper.h b/target-sparc/helper.h index 39dac74676..4007ddfea0 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -45,6 +45,13 @@ void TCG_HELPER_PROTO helper_flush(target_ulong addr); target_ulong TCG_HELPER_PROTO helper_udiv(target_ulong a, target_ulong b); target_ulong TCG_HELPER_PROTO helper_sdiv(target_ulong a, target_ulong b); uint64_t TCG_HELPER_PROTO helper_pack64(target_ulong high, target_ulong low); +void TCG_HELPER_PROTO helper_std_i386(target_ulong addr, int mem_idx); +void TCG_HELPER_PROTO helper_stdf(target_ulong addr, int mem_idx); +void TCG_HELPER_PROTO helper_lddf(target_ulong addr, int mem_idx); +#if defined(CONFIG_USER_ONLY) +void TCG_HELPER_PROTO helper_ldqf(target_ulong addr); +void TCG_HELPER_PROTO helper_stqf(target_ulong addr); +#endif uint64_t TCG_HELPER_PROTO helper_ld_asi(target_ulong addr, int asi, int size, int sign); void TCG_HELPER_PROTO helper_st_asi(target_ulong addr, uint64_t val, int asi, diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index bc9bb179d6..70e72bb50c 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -2217,6 +2217,109 @@ uint64_t helper_pack64(target_ulong high, target_ulong low) return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff); } +#ifdef TARGET_ABI32 +#define ADDR(x) ((x) & 0xffffffff) +#else +#define ADDR(x) (x) +#endif + +#ifdef __i386__ +void helper_std_i386(target_ulong addr, int mem_idx) +{ + uint64_t tmp = ((uint64_t)env->t1 << 32) | (uint64_t)(env->t2 & 0xffffffff); + +#if !defined(CONFIG_USER_ONLY) + switch (mem_idx) { + case 0: + stq_user(ADDR(addr), tmp); + break; + case 1: + stq_kernel(ADDR(addr), tmp); + break; +#ifdef TARGET_SPARC64 + case 2: + stq_hypv(ADDR(addr), tmp); + break; +#endif + default: + break; + } +#else + stq_raw(ADDR(addr), tmp); +#endif +} +#endif /* __i386__ */ + +void helper_stdf(target_ulong addr, int mem_idx) +{ +#if !defined(CONFIG_USER_ONLY) + switch (mem_idx) { + case 0: + stfq_user(ADDR(addr), DT0); + break; + case 1: + stfq_kernel(ADDR(addr), DT0); + break; +#ifdef TARGET_SPARC64 + case 2: + stfq_hypv(ADDR(addr), DT0); + break; +#endif + default: + break; + } +#else + stfq_raw(ADDR(addr), DT0); +#endif +} + +void helper_lddf(target_ulong addr, int mem_idx) +{ +#if !defined(CONFIG_USER_ONLY) + switch (mem_idx) { + case 0: + DT0 = ldfq_user(ADDR(addr)); + break; + case 1: + DT0 = ldfq_kernel(ADDR(addr)); + break; +#ifdef TARGET_SPARC64 + case 2: + DT0 = ldfq_hypv(ADDR(addr)); + break; +#endif + default: + break; + } +#else + DT0 = ldfq_raw(ADDR(addr)); +#endif +} + +#if defined(CONFIG_USER_ONLY) +void helper_ldqf(target_ulong addr) +{ + // XXX add 128 bit load + CPU_QuadU u; + + u.ll.upper = ldq_raw(ADDR(addr)); + u.ll.lower = ldq_raw(ADDR(addr + 8)); + QT0 = u.q; +} + +void helper_stqf(target_ulong addr) +{ + // XXX add 128 bit store + CPU_QuadU u; + + u.q = QT0; + stq_raw(ADDR(addr), u.ll.upper); + stq_raw(ADDR(addr + 8), u.ll.lower); +} +#endif + +#undef ADDR + void helper_ldfsr(void) { int rnd_mode; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 93a517f484..0696db3fe6 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -184,33 +184,12 @@ static void gen_op_store_QT0_fpr(unsigned int dst) #ifdef TARGET_SPARC64 #define hypervisor(dc) 0 #endif -#define gen_op_ldst(name) gen_op_##name##_raw() #else #define supervisor(dc) (dc->mem_idx >= 1) #ifdef TARGET_SPARC64 #define hypervisor(dc) (dc->mem_idx == 2) -#define OP_LD_TABLE(width) \ - static GenOpFunc * const gen_op_##width[] = { \ - &gen_op_##width##_user, \ - &gen_op_##width##_kernel, \ - &gen_op_##width##_hypv, \ - }; #else -#define OP_LD_TABLE(width) \ - static GenOpFunc * const gen_op_##width[] = { \ - &gen_op_##width##_user, \ - &gen_op_##width##_kernel, \ - }; #endif -#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])() -#endif - -#ifndef CONFIG_USER_ONLY -#ifdef __i386__ -OP_LD_TABLE(std); -#endif /* __i386__ */ -OP_LD_TABLE(stdf); -OP_LD_TABLE(lddf); #endif #ifdef TARGET_ABI32 @@ -4209,16 +4188,19 @@ static void disas_sparc_insn(DisasContext * dc) break; case 0x22: /* load quad fpreg */ #if defined(CONFIG_USER_ONLY) - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); - gen_op_ldst(ldqf); + tcg_gen_helper_0_2(helper_check_align, cpu_addr, + tcg_const_i32(7)); + tcg_gen_helper_0_1(helper_ldqf, cpu_addr); gen_op_store_QT0_fpr(QFPREG(rd)); break; #else goto nfpu_insn; #endif case 0x23: /* load double fpreg */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); - gen_op_ldst(lddf); + tcg_gen_helper_0_2(helper_check_align, cpu_addr, + tcg_const_i32(7)); + tcg_gen_helper_0_2(helper_lddf, cpu_addr, + tcg_const_i32(dc->mem_idx)); gen_op_store_DT0_fpr(DFPREG(rd)); break; default: @@ -4245,23 +4227,23 @@ static void disas_sparc_insn(DisasContext * dc) case 0x7: /* store double word */ if (rd & 1) goto illegal_insn; -#ifndef __i386__ else { TCGv r_low; tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); r_low = tcg_temp_new(TCG_TYPE_I32); gen_movl_reg_TN(rd + 1, r_low); +#ifndef __i386__ tcg_gen_helper_1_2(helper_pack64, cpu_tmp64, cpu_val, r_low); tcg_gen_qemu_st64(cpu_tmp64, cpu_addr, dc->mem_idx); - } #else /* __i386__ */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); - flush_cond(dc, cpu_cond); - gen_movl_reg_TN(rd + 1, cpu_cond); - gen_op_ldst(std); + tcg_gen_st_tl(cpu_val, cpu_env, offsetof(CPUState, t1)); + tcg_gen_st_tl(r_low, cpu_env, offsetof(CPUState, t2)); + tcg_gen_helper_0_2(helper_std_i386, cpu_addr, + tcg_const_i32(dc->mem_idx)); #endif /* __i386__ */ + } break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) case 0x14: /* store word alternate */ @@ -4345,9 +4327,10 @@ static void disas_sparc_insn(DisasContext * dc) #ifdef TARGET_SPARC64 #if defined(CONFIG_USER_ONLY) /* V9 stqf, store quad fpreg */ - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + tcg_gen_helper_0_2(helper_check_align, cpu_addr, + tcg_const_i32(7)); gen_op_load_fpr_QT0(QFPREG(rd)); - gen_op_ldst(stqf); + tcg_gen_helper_0_1(helper_stqf, cpu_addr); break; #else goto nfpu_insn; @@ -4364,10 +4347,12 @@ static void disas_sparc_insn(DisasContext * dc) goto nfq_insn; #endif #endif - case 0x27: - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); + case 0x27: /* store double fpreg */ + tcg_gen_helper_0_2(helper_check_align, cpu_addr, + tcg_const_i32(7)); gen_op_load_fpr_DT0(DFPREG(rd)); - gen_op_ldst(stdf); + tcg_gen_helper_0_2(helper_stdf, cpu_addr, + tcg_const_i32(dc->mem_idx)); break; default: goto illegal_insn;