@@ -901,53 +901,6 @@ static void gen_fp_move(TCGv_ptr dest, TCGv_ptr src)
tcg_gen_st_i64(t64, dest, offsetof(FPReg, l.lower));
}
-static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
- int index)
-{
- TCGv tmp;
- TCGv_i64 t64;
-
- t64 = tcg_temp_new_i64();
- tmp = tcg_temp_new();
- switch (opsize) {
- case OS_BYTE:
- case OS_WORD:
- case OS_LONG:
- gen_helper_reds32(tmp, tcg_env, fp);
- tcg_gen_qemu_st_tl(tmp, addr, index, opsize | MO_TE);
- break;
- case OS_SINGLE:
- gen_helper_redf32(tmp, tcg_env, fp);
- tcg_gen_qemu_st_tl(tmp, addr, index, MO_TEUL);
- break;
- case OS_DOUBLE:
- gen_helper_redf64(t64, tcg_env, fp);
- tcg_gen_qemu_st_i64(t64, addr, index, MO_TEUQ);
- break;
- case OS_EXTENDED:
- if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
- gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
- break;
- }
- tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper));
- tcg_gen_shli_i32(tmp, tmp, 16);
- tcg_gen_qemu_st_i32(tmp, addr, index, MO_TEUL);
- tcg_gen_addi_i32(tmp, addr, 4);
- tcg_gen_ld_i64(t64, fp, offsetof(FPReg, l.lower));
- tcg_gen_qemu_st_i64(t64, tmp, index, MO_TEUQ);
- break;
- case OS_PACKED:
- /*
- * unimplemented data type on 68040/ColdFire
- * FIXME if needed for another FPU
- */
- gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
- break;
- default:
- g_assert_not_reached();
- }
-}
-
static bool gen_load_fp(DisasContext *s, uint16_t insn, int opsize,
TCGv_ptr fp, int index)
{
@@ -1087,12 +1040,13 @@ static bool gen_load_fp(DisasContext *s, uint16_t insn, int opsize,
return true;
}
-static bool gen_store_mode_fp(DisasContext *s, uint16_t insn, int opsize,
- TCGv_ptr fp, int index)
+static bool gen_store_fp(DisasContext *s, uint16_t insn, int opsize,
+ TCGv_ptr fp, int index)
{
int mode = extract32(insn, 3, 3);
int reg0 = REG(insn, 0);
- TCGv reg, addr;
+ TCGv reg, addr, tmp;
+ TCGv_i64 t64;
switch (mode) {
case 0: /* Data register direct. */
@@ -1126,10 +1080,55 @@ static bool gen_store_mode_fp(DisasContext *s, uint16_t insn, int opsize,
gen_addr_fault(s);
return false;
}
- gen_store_fp(s, opsize, addr, fp, index);
- return true;
+ break;
+
+ default:
+ g_assert_not_reached();
}
- g_assert_not_reached();
+
+ switch (opsize) {
+ case OS_BYTE:
+ case OS_WORD:
+ case OS_LONG:
+ tmp = tcg_temp_new();
+ gen_helper_reds32(tmp, tcg_env, fp);
+ tcg_gen_qemu_st_tl(tmp, addr, index, opsize | MO_TE);
+ break;
+ case OS_SINGLE:
+ tmp = tcg_temp_new();
+ gen_helper_redf32(tmp, tcg_env, fp);
+ tcg_gen_qemu_st_tl(tmp, addr, index, MO_TEUL);
+ break;
+ case OS_DOUBLE:
+ t64 = tcg_temp_new_i64();
+ gen_helper_redf64(t64, tcg_env, fp);
+ tcg_gen_qemu_st_i64(t64, addr, index, MO_TEUQ);
+ break;
+ case OS_EXTENDED:
+ if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
+ gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
+ return false;
+ }
+ tmp = tcg_temp_new();
+ t64 = tcg_temp_new_i64();
+ tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper));
+ tcg_gen_shli_i32(tmp, tmp, 16);
+ tcg_gen_qemu_st_i32(tmp, addr, index, MO_TEUL);
+ tcg_gen_addi_i32(addr, addr, 4);
+ tcg_gen_ld_i64(t64, fp, offsetof(FPReg, l.lower));
+ tcg_gen_qemu_st_i64(t64, addr, index, MO_TEUQ);
+ break;
+ case OS_PACKED:
+ /*
+ * unimplemented data type on 68040/ColdFire
+ * FIXME if needed for another FPU
+ */
+ gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
+ return false;
+ default:
+ g_assert_not_reached();
+ }
+ return true;
}
typedef struct {
@@ -4889,7 +4888,7 @@ DISAS_INSN(fpu)
case 3: /* fmove out */
cpu_src = gen_fp_ptr(REG(ext, 7));
opsize = ext_opsize(ext, 10);
- if (gen_store_mode_fp(s, insn, opsize, cpu_src, IS_USER(s))) {
+ if (gen_store_fp(s, insn, opsize, cpu_src, IS_USER(s))) {
gen_helper_update_fpsr(tcg_env, cpu_src);
}
return;
This enables the exceptions raised by the actual store to be reflected as a failure. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/m68k/translate.c | 107 ++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 54 deletions(-)