aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure6
-rw-r--r--target-sparc/cpu.h6
-rw-r--r--target-sparc/exec.h2
-rw-r--r--target-sparc/helper.h7
-rw-r--r--target-sparc/op_helper.c103
-rw-r--r--target-sparc/translate.c57
6 files changed, 139 insertions, 42 deletions
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;