From cc4ba6a9826d94bb46f13856927f7883fd6b9d51 Mon Sep 17 00:00:00 2001 From: aurel32 Date: Mon, 1 Sep 2008 22:11:56 +0000 Subject: [PATCH] SH4: convert floating-point ops to TCG Signed-off-by: Aurelien Jarno git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5124 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-sh4/helper.h | 24 +++ target-sh4/op.c | 229 --------------------------- target-sh4/op_helper.c | 148 ++++++++++++++++++ target-sh4/op_mem.c | 38 ----- target-sh4/translate.c | 402 ++++++++++++++++++++++++++++++------------------ 5 files changed, 421 insertions(+), 420 deletions(-) delete mode 100644 target-sh4/op_mem.c diff --git a/target-sh4/helper.h b/target-sh4/helper.h index c9465a7..19f5981 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -19,3 +19,27 @@ DEF_HELPER(void, helper_macl, (uint32_t, uint32_t)) DEF_HELPER(void, helper_macw, (uint32_t, uint32_t)) DEF_HELPER(void, helper_ld_fpscr, (uint32_t)) + +DEF_HELPER(uint32_t, helper_fabs_FT, (uint32_t)) +DEF_HELPER(uint64_t, helper_fabs_DT, (uint64_t)) +DEF_HELPER(uint32_t, helper_fadd_FT, (uint32_t, uint32_t)) +DEF_HELPER(uint64_t, helper_fadd_DT, (uint64_t, uint64_t)) +DEF_HELPER(uint64_t, helper_fcnvsd_FT_DT, (uint32_t)) +DEF_HELPER(uint32_t, helper_fcnvds_DT_FT, (uint64_t)) + +DEF_HELPER(void, helper_fcmp_eq_FT, (uint32_t, uint32_t)) +DEF_HELPER(void, helper_fcmp_eq_DT, (uint64_t, uint64_t)) +DEF_HELPER(void, helper_fcmp_gt_FT, (uint32_t, uint32_t)) +DEF_HELPER(void, helper_fcmp_gt_DT, (uint64_t, uint64_t)) +DEF_HELPER(uint32_t, helper_fdiv_FT, (uint32_t, uint32_t)) +DEF_HELPER(uint64_t, helper_fdiv_DT, (uint64_t, uint64_t)) +DEF_HELPER(uint32_t, helper_float_FT, (uint32_t)) +DEF_HELPER(uint64_t, helper_float_DT, (uint32_t)) +DEF_HELPER(uint32_t, helper_fmul_FT, (uint32_t, uint32_t)) +DEF_HELPER(uint64_t, helper_fmul_DT, (uint64_t, uint64_t)) +DEF_HELPER(uint32_t, helper_fsub_FT, (uint32_t, uint32_t)) +DEF_HELPER(uint64_t, helper_fsub_DT, (uint64_t, uint64_t)) +DEF_HELPER(uint32_t, helper_fsqrt_FT, (uint32_t)) +DEF_HELPER(uint64_t, helper_fsqrt_DT, (uint64_t)) +DEF_HELPER(uint32_t, helper_ftrc_FT, (uint32_t)) +DEF_HELPER(uint32_t, helper_ftrc_DT, (uint64_t)) diff --git a/target-sh4/op.c b/target-sh4/op.c index 3b25b4a..02d86fe 100644 --- a/target-sh4/op.c +++ b/target-sh4/op.c @@ -19,238 +19,9 @@ */ #include "exec.h" -static inline void set_t(void) -{ - env->sr |= SR_T; -} - -static inline void clr_t(void) -{ - env->sr &= ~SR_T; -} - -static inline void cond_t(int cond) -{ - if (cond) - set_t(); - else - clr_t(); -} - -void OPPROTO op_fmov_frN_FT0(void) -{ - FT0 = env->fregs[PARAM1]; - RETURN(); -} - -void OPPROTO op_fmov_drN_DT0(void) -{ - CPU_DoubleU d; - - d.l.upper = *(uint32_t *)&env->fregs[PARAM1]; - d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1]; - DT0 = d.d; - RETURN(); -} - -void OPPROTO op_fmov_frN_FT1(void) -{ - FT1 = env->fregs[PARAM1]; - RETURN(); -} - -void OPPROTO op_fmov_drN_DT1(void) -{ - CPU_DoubleU d; - - d.l.upper = *(uint32_t *)&env->fregs[PARAM1]; - d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1]; - DT1 = d.d; - RETURN(); -} - -void OPPROTO op_fmov_FT0_frN(void) -{ - env->fregs[PARAM1] = FT0; - RETURN(); -} - -void OPPROTO op_fmov_DT0_drN(void) -{ - CPU_DoubleU d; - - d.d = DT0; - *(uint32_t *)&env->fregs[PARAM1] = d.l.upper; - *(uint32_t *)&env->fregs[PARAM1 + 1] = d.l.lower; - RETURN(); -} - -void OPPROTO op_fadd_FT(void) -{ - FT0 = float32_add(FT0, FT1, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fadd_DT(void) -{ - DT0 = float64_add(DT0, DT1, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fsub_FT(void) -{ - FT0 = float32_sub(FT0, FT1, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fsub_DT(void) -{ - DT0 = float64_sub(DT0, DT1, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fmul_FT(void) -{ - FT0 = float32_mul(FT0, FT1, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fmul_DT(void) -{ - DT0 = float64_mul(DT0, DT1, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fdiv_FT(void) -{ - FT0 = float32_div(FT0, FT1, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fdiv_DT(void) -{ - DT0 = float64_div(DT0, DT1, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fcmp_eq_FT(void) -{ - cond_t(float32_compare(FT0, FT1, &env->fp_status) == 0); - RETURN(); -} - -void OPPROTO op_fcmp_eq_DT(void) -{ - cond_t(float64_compare(DT0, DT1, &env->fp_status) == 0); - RETURN(); -} - -void OPPROTO op_fcmp_gt_FT(void) -{ - cond_t(float32_compare(FT0, FT1, &env->fp_status) == 1); - RETURN(); -} - -void OPPROTO op_fcmp_gt_DT(void) -{ - cond_t(float64_compare(DT0, DT1, &env->fp_status) == 1); - RETURN(); -} - -void OPPROTO op_float_FT(void) -{ - FT0 = int32_to_float32(env->fpul, &env->fp_status); - RETURN(); -} - -void OPPROTO op_float_DT(void) -{ - DT0 = int32_to_float64(env->fpul, &env->fp_status); - RETURN(); -} - -void OPPROTO op_ftrc_FT(void) -{ - env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status); - RETURN(); -} - -void OPPROTO op_ftrc_DT(void) -{ - env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status); - RETURN(); -} - void OPPROTO op_fneg_frN(void) { env->fregs[PARAM1] = float32_chs(env->fregs[PARAM1]); RETURN(); } -void OPPROTO op_fabs_FT(void) -{ - FT0 = float32_abs(FT0); - RETURN(); -} - -void OPPROTO op_fabs_DT(void) -{ - DT0 = float64_abs(DT0); - RETURN(); -} - -void OPPROTO op_fcnvsd_FT_DT(void) -{ - DT0 = float32_to_float64(FT0, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fcnvds_DT_FT(void) -{ - FT0 = float64_to_float32(DT0, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fsqrt_FT(void) -{ - FT0 = float32_sqrt(FT0, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fsqrt_DT(void) -{ - DT0 = float64_sqrt(DT0, &env->fp_status); - RETURN(); -} - -void OPPROTO op_fmov_T0_frN(void) -{ - *(uint32_t *)&env->fregs[PARAM1] = T0; - RETURN(); -} - -void OPPROTO op_movl_fpul_FT0(void) -{ - FT0 = *(float32 *)&env->fpul; - RETURN(); -} - -void OPPROTO op_movl_FT0_fpul(void) -{ - *(float32 *)&env->fpul = FT0; - RETURN(); -} - -/* Load and store */ -#define MEMSUFFIX _raw -#include "op_mem.c" -#undef MEMSUFFIX -#if !defined(CONFIG_USER_ONLY) -#define MEMSUFFIX _user -#include "op_mem.c" -#undef MEMSUFFIX - -#define MEMSUFFIX _kernel -#include "op_mem.c" -#undef MEMSUFFIX -#endif diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index d3bde5c..5d9c414 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -366,6 +366,16 @@ uint32_t helper_subv(uint32_t arg0, uint32_t arg1) return arg1; } +static inline void set_t(void) +{ + env->sr |= SR_T; +} + +static inline void clr_t(void) +{ + env->sr &= ~SR_T; +} + void helper_ld_fpscr(uint32_t val) { env->fpscr = val & 0x003fffff; @@ -374,3 +384,141 @@ void helper_ld_fpscr(uint32_t val) else set_float_rounding_mode(float_round_nearest_even, &env->fp_status); } + +uint32_t helper_fabs_FT(uint32_t t0) +{ + float32 ret = float32_abs(*(float32*)&t0); + return *(uint32_t*)(&ret); +} + +uint64_t helper_fabs_DT(uint64_t t0) +{ + float64 ret = float64_abs(*(float64*)&t0); + return *(uint64_t*)(&ret); +} + +uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1) +{ + float32 ret = float32_add(*(float32*)&t0, *(float32*)&t1, &env->fp_status); + return *(uint32_t*)(&ret); +} + +uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1) +{ + float64 ret = float64_add(*(float64*)&t0, *(float64*)&t1, &env->fp_status); + return *(uint64_t*)(&ret); +} + +void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1) +{ + if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 0) + set_t(); + else + clr_t(); +} + +void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1) +{ + if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 0) + set_t(); + else + clr_t(); +} + +void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1) +{ + if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 1) + set_t(); + else + clr_t(); +} + +void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1) +{ + if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 1) + set_t(); + else + clr_t(); +} + +uint64_t helper_fcnvsd_FT_DT(uint32_t t0) +{ + float64 ret = float32_to_float64(*(float32*)&t0, &env->fp_status); + return *(uint64_t*)(&ret); +} + +uint32_t helper_fcnvds_DT_FT(uint64_t t0) +{ + float32 ret = float64_to_float32(*(float64*)&t0, &env->fp_status); + return *(uint32_t*)(&ret); +} + +uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1) +{ + float32 ret = float32_div(*(float32*)&t0, *(float32*)&t1, &env->fp_status); + return *(uint32_t*)(&ret); +} + +uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1) +{ + float64 ret = float64_div(*(float64*)&t0, *(float64*)&t1, &env->fp_status); + return *(uint64_t*)(&ret); +} + +uint32_t helper_float_FT(uint32_t t0) +{ + float32 ret = int32_to_float32(t0, &env->fp_status); + return *(uint32_t*)(&ret); +} + +uint64_t helper_float_DT(uint32_t t0) +{ + float64 ret = int32_to_float64(t0, &env->fp_status); + return *(uint64_t*)(&ret); +} + +uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1) +{ + float32 ret = float32_mul(*(float32*)&t0, *(float32*)&t1, &env->fp_status); + return *(uint32_t*)(&ret); +} + +uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1) +{ + float64 ret = float64_mul(*(float64*)&t0, *(float64*)&t1, &env->fp_status); + return *(uint64_t*)(&ret); +} + +uint32_t helper_fsqrt_FT(uint32_t t0) +{ + float32 ret = float32_sqrt(*(float32*)&t0, &env->fp_status); + return *(uint32_t*)(&ret); +} + +uint64_t helper_fsqrt_DT(uint64_t t0) +{ + float64 ret = float64_sqrt(*(float64*)&t0, &env->fp_status); + return *(uint64_t*)(&ret); +} + +uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1) +{ + float32 ret = float32_sub(*(float32*)&t0, *(float32*)&t1, &env->fp_status); + return *(uint32_t*)(&ret); +} + +uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1) +{ + float64 ret = float64_sub(*(float64*)&t0, *(float64*)&t1, &env->fp_status); + return *(uint64_t*)(&ret); +} + +uint32_t helper_ftrc_FT(uint32_t t0) +{ + return float32_to_int32_round_to_zero(*(float32*)&t0, &env->fp_status); +} + +uint32_t helper_ftrc_DT(uint64_t t0) +{ + return float64_to_int32_round_to_zero(*(float64*)&t0, &env->fp_status); +} diff --git a/target-sh4/op_mem.c b/target-sh4/op_mem.c deleted file mode 100644 index d4c6874..0000000 --- a/target-sh4/op_mem.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SH4 emulation - * - * Copyright (c) 2005 Samuel Tardieu - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -void glue(op_ldfl_T0_FT0, MEMSUFFIX) (void) { - FT0 = glue(ldfl, MEMSUFFIX) (T0); - RETURN(); -} - -void glue(op_stfl_FT0_T1, MEMSUFFIX) (void) { - glue(stfl, MEMSUFFIX) (T1, FT0); - RETURN(); -} - -void glue(op_ldfq_T0_DT0, MEMSUFFIX) (void) { - DT0 = glue(ldfq, MEMSUFFIX) (T0); - RETURN(); -} - -void glue(op_stfq_DT0_T1, MEMSUFFIX) (void) { - glue(stfq, MEMSUFFIX) (T1, DT0); - RETURN(); -} diff --git a/target-sh4/translate.c b/target-sh4/translate.c index cea4aa2..30362a8 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -137,37 +137,6 @@ static void sh4_translate_init(void) done_init = 1; } -#ifdef CONFIG_USER_ONLY - -#define GEN_OP_LD(width, reg) \ - void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \ - gen_op_ld##width##_T0_##reg##_raw(); \ - } -#define GEN_OP_ST(width, reg) \ - void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \ - gen_op_st##width##_##reg##_T1_raw(); \ - } - -#else - -#define GEN_OP_LD(width, reg) \ - void gen_op_ld##width##_T0_##reg (DisasContext *ctx) { \ - if (ctx->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \ - else gen_op_ld##width##_T0_##reg##_user();\ - } -#define GEN_OP_ST(width, reg) \ - void gen_op_st##width##_##reg##_T1 (DisasContext *ctx) { \ - if (ctx->memidx) gen_op_st##width##_##reg##_T1_kernel(); \ - else gen_op_st##width##_##reg##_T1_user();\ - } - -#endif - -GEN_OP_LD(fl, FT0) -GEN_OP_ST(fl, FT0) -GEN_OP_LD(fq, DT0) -GEN_OP_ST(fq, DT0) - void cpu_dump_state(CPUState * env, FILE * f, int (*cpu_fprintf) (FILE * f, const char *fmt, ...), int flags) @@ -361,6 +330,44 @@ static inline void gen_copy_bit_i32(TCGv t0, int p0, TCGv t1, int p1) tcg_temp_free(tmp); } + +static inline void gen_load_fpr32(TCGv t, int reg) +{ + tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, fregs[reg])); +} + +static inline void gen_load_fpr64(TCGv t, int reg) +{ + TCGv tmp1 = tcg_temp_new(TCG_TYPE_I32); + TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_ld_i32(tmp1, cpu_env, offsetof(CPUState, fregs[reg])); + tcg_gen_extu_i32_i64(t, tmp1); + tcg_gen_shli_i64(t, t, 32); + tcg_gen_ld_i32(tmp1, cpu_env, offsetof(CPUState, fregs[reg + 1])); + tcg_gen_extu_i32_i64(tmp2, tmp1); + tcg_temp_free(tmp1); + tcg_gen_or_i64(t, t, tmp2); + tcg_temp_free(tmp2); +} + +static inline void gen_store_fpr32(TCGv t, int reg) +{ + tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, fregs[reg])); +} + +static inline void gen_store_fpr64 (TCGv t, int reg) +{ + TCGv tmp = tcg_temp_new(TCG_TYPE_I32); + + tcg_gen_trunc_i64_i32(tmp, t); + tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, fregs[reg + 1])); + tcg_gen_shri_i64(t, t, 32); + tcg_gen_trunc_i64_i32(tmp, t); + tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, fregs[reg])); + tcg_temp_free(tmp); +} + #define B3_0 (ctx->opcode & 0xf) #define B6_4 ((ctx->opcode >> 4) & 0x7) #define B7_4 ((ctx->opcode >> 4) & 0xf) @@ -913,88 +920,115 @@ void _decode_opc(DisasContext * ctx) return; case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */ if (ctx->fpscr & FPSCR_SZ) { - gen_op_fmov_drN_DT0(XREG(B7_4)); - gen_op_fmov_DT0_drN(XREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp, XREG(B7_4)); + gen_store_fpr64(fp, XREG(B11_8)); + tcg_temp_free(fp); } else { - gen_op_fmov_frN_FT0(FREG(B7_4)); - gen_op_fmov_FT0_frN(FREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp, FREG(B7_4)); + gen_store_fpr32(fp, FREG(B11_8)); + tcg_temp_free(fp); } return; case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */ if (ctx->fpscr & FPSCR_SZ) { - gen_op_fmov_drN_DT0(XREG(B7_4)); - tcg_gen_mov_i32(cpu_T[1], REG(B11_8)); - gen_op_stfq_DT0_T1(ctx); + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp, XREG(B7_4)); + tcg_gen_qemu_st64(fp, REG(B11_8), ctx->memidx); + tcg_temp_free(fp); } else { - gen_op_fmov_frN_FT0(FREG(B7_4)); - tcg_gen_mov_i32(cpu_T[1], REG(B11_8)); - gen_op_stfl_FT0_T1(ctx); + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp, FREG(B7_4)); + tcg_gen_qemu_st32(fp, REG(B11_8), ctx->memidx); + tcg_temp_free(fp); } return; case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */ if (ctx->fpscr & FPSCR_SZ) { - tcg_gen_mov_i32(cpu_T[0], REG(B7_4)); - gen_op_ldfq_T0_DT0(ctx); - gen_op_fmov_DT0_drN(XREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_qemu_ld64(fp, REG(B7_4), ctx->memidx); + gen_store_fpr64(fp, XREG(B11_8)); + tcg_temp_free(fp); } else { - tcg_gen_mov_i32(cpu_T[0], REG(B7_4)); - gen_op_ldfl_T0_FT0(ctx); - gen_op_fmov_FT0_frN(FREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_qemu_ld32u(fp, REG(B7_4), ctx->memidx); + gen_store_fpr32(fp, FREG(B11_8)); + tcg_temp_free(fp); } return; case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */ if (ctx->fpscr & FPSCR_SZ) { - tcg_gen_mov_i32(cpu_T[0], REG(B7_4)); - gen_op_ldfq_T0_DT0(ctx); - gen_op_fmov_DT0_drN(XREG(B11_8)); - tcg_gen_addi_i32(REG(B7_4), - REG(B7_4), 8); + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_qemu_ld64(fp, REG(B7_4), ctx->memidx); + gen_store_fpr64(fp, XREG(B11_8)); + tcg_temp_free(fp); + tcg_gen_addi_i32(REG(B7_4),REG(B7_4), 8); } else { - tcg_gen_mov_i32(cpu_T[0], REG(B7_4)); - gen_op_ldfl_T0_FT0(ctx); - gen_op_fmov_FT0_frN(FREG(B11_8)); - tcg_gen_addi_i32(REG(B7_4), - REG(B7_4), 4); + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_qemu_ld32u(fp, REG(B7_4), ctx->memidx); + gen_store_fpr32(fp, FREG(B11_8)); + tcg_temp_free(fp); + tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); } return; case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */ if (ctx->fpscr & FPSCR_SZ) { - tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 8); - gen_op_fmov_drN_DT0(XREG(B7_4)); - tcg_gen_mov_i32(cpu_T[1], REG(B11_8)); - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 8); - gen_op_stfq_DT0_T1(ctx); + TCGv addr, fp; + addr = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_subi_i32(addr, REG(B11_8), 8); + fp = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp, XREG(B7_4)); + tcg_gen_qemu_st64(fp, addr, ctx->memidx); + tcg_temp_free(fp); + tcg_temp_free(addr); tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 8); } else { - tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4); - gen_op_fmov_frN_FT0(FREG(B7_4)); - tcg_gen_mov_i32(cpu_T[1], REG(B11_8)); - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); - gen_op_stfl_FT0_T1(ctx); + TCGv addr, fp; + addr = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_subi_i32(addr, REG(B11_8), 4); + fp = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp, FREG(B7_4)); + tcg_gen_qemu_st32(fp, addr, ctx->memidx); + tcg_temp_free(fp); + tcg_temp_free(addr); tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 4); } return; case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */ - tcg_gen_add_i32(cpu_T[0], REG(B7_4), REG(0)); - if (ctx->fpscr & FPSCR_SZ) { - gen_op_ldfq_T0_DT0(ctx); - gen_op_fmov_DT0_drN(XREG(B11_8)); - } else { - gen_op_ldfl_T0_FT0(ctx); - gen_op_fmov_FT0_frN(FREG(B11_8)); + { + TCGv addr = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_add_i32(addr, REG(B7_4), REG(0)); + if (ctx->fpscr & FPSCR_SZ) { + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_qemu_ld64(fp, addr, ctx->memidx); + gen_store_fpr64(fp, XREG(B11_8)); + tcg_temp_free(fp); + } else { + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_qemu_ld32u(fp, addr, ctx->memidx); + gen_store_fpr32(fp, FREG(B11_8)); + tcg_temp_free(fp); + } + tcg_temp_free(addr); } return; case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */ - if (ctx->fpscr & FPSCR_SZ) { - gen_op_fmov_drN_DT0(XREG(B7_4)); - tcg_gen_mov_i32(cpu_T[1], REG(B11_8)); - tcg_gen_add_i32(cpu_T[1], cpu_T[1], REG(0)); - gen_op_stfq_DT0_T1(ctx); - } else { - gen_op_fmov_frN_FT0(FREG(B7_4)); - tcg_gen_mov_i32(cpu_T[1], REG(B11_8)); - tcg_gen_add_i32(cpu_T[1], cpu_T[1], REG(0)); - gen_op_stfl_FT0_T1(ctx); + { + TCGv addr = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_add_i32(addr, REG(B11_8), REG(0)); + if (ctx->fpscr & FPSCR_SZ) { + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp, XREG(B7_4)); + tcg_gen_qemu_st64(fp, addr, ctx->memidx); + tcg_temp_free(fp); + } else { + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp, FREG(B7_4)); + tcg_gen_qemu_st32(fp, addr, ctx->memidx); + tcg_temp_free(fp); + } + tcg_temp_free(addr); } return; case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ @@ -1003,43 +1037,71 @@ void _decode_opc(DisasContext * ctx) case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ - if (ctx->fpscr & FPSCR_PR) { - if (ctx->opcode & 0x0110) - break; /* illegal instruction */ - gen_op_fmov_drN_DT1(DREG(B7_4)); - gen_op_fmov_drN_DT0(DREG(B11_8)); - } - else { - gen_op_fmov_frN_FT1(FREG(B7_4)); - gen_op_fmov_frN_FT0(FREG(B11_8)); - } + { + TCGv fp0, fp1; + + if (ctx->fpscr & FPSCR_PR) { + if (ctx->opcode & 0x0110) + break; /* illegal instruction */ + fp0 = tcg_temp_new(TCG_TYPE_I64); + fp1 = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp0, DREG(B11_8)); + gen_load_fpr64(fp1, DREG(B7_4)); + } + else { + fp0 = tcg_temp_new(TCG_TYPE_I32); + fp1 = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp0, FREG(B11_8)); + gen_load_fpr32(fp1, FREG(B7_4)); + } - switch (ctx->opcode & 0xf00f) { - case 0xf000: /* fadd Rm,Rn */ - ctx->fpscr & FPSCR_PR ? gen_op_fadd_DT() : gen_op_fadd_FT(); - break; - case 0xf001: /* fsub Rm,Rn */ - ctx->fpscr & FPSCR_PR ? gen_op_fsub_DT() : gen_op_fsub_FT(); - break; - case 0xf002: /* fmul Rm,Rn */ - ctx->fpscr & FPSCR_PR ? gen_op_fmul_DT() : gen_op_fmul_FT(); - break; - case 0xf003: /* fdiv Rm,Rn */ - ctx->fpscr & FPSCR_PR ? gen_op_fdiv_DT() : gen_op_fdiv_FT(); - break; - case 0xf004: /* fcmp/eq Rm,Rn */ - ctx->fpscr & FPSCR_PR ? gen_op_fcmp_eq_DT() : gen_op_fcmp_eq_FT(); - return; - case 0xf005: /* fcmp/gt Rm,Rn */ - ctx->fpscr & FPSCR_PR ? gen_op_fcmp_gt_DT() : gen_op_fcmp_gt_FT(); - return; - } + switch (ctx->opcode & 0xf00f) { + case 0xf000: /* fadd Rm,Rn */ + if (ctx->fpscr & FPSCR_PR) + tcg_gen_helper_1_2(helper_fadd_DT, fp0, fp0, fp1); + else + tcg_gen_helper_1_2(helper_fadd_FT, fp0, fp0, fp1); + break; + case 0xf001: /* fsub Rm,Rn */ + if (ctx->fpscr & FPSCR_PR) + tcg_gen_helper_1_2(helper_fsub_DT, fp0, fp0, fp1); + else + tcg_gen_helper_1_2(helper_fsub_FT, fp0, fp0, fp1); + break; + case 0xf002: /* fmul Rm,Rn */ + if (ctx->fpscr & FPSCR_PR) + tcg_gen_helper_1_2(helper_fmul_DT, fp0, fp0, fp1); + else + tcg_gen_helper_1_2(helper_fmul_FT, fp0, fp0, fp1); + break; + case 0xf003: /* fdiv Rm,Rn */ + if (ctx->fpscr & FPSCR_PR) + tcg_gen_helper_1_2(helper_fdiv_DT, fp0, fp0, fp1); + else + tcg_gen_helper_1_2(helper_fdiv_FT, fp0, fp0, fp1); + break; + case 0xf004: /* fcmp/eq Rm,Rn */ + if (ctx->fpscr & FPSCR_PR) + tcg_gen_helper_0_2(helper_fcmp_eq_DT, fp0, fp1); + else + tcg_gen_helper_0_2(helper_fcmp_eq_FT, fp0, fp1); + return; + case 0xf005: /* fcmp/gt Rm,Rn */ + if (ctx->fpscr & FPSCR_PR) + tcg_gen_helper_0_2(helper_fcmp_gt_DT, fp0, fp1); + else + tcg_gen_helper_0_2(helper_fcmp_gt_FT, fp0, fp1); + return; + } - if (ctx->fpscr & FPSCR_PR) { - gen_op_fmov_DT0_drN(DREG(B11_8)); - } - else { - gen_op_fmov_FT0_frN(FREG(B11_8)); + if (ctx->fpscr & FPSCR_PR) { + gen_store_fpr64(fp0, DREG(B11_8)); + } + else { + gen_store_fpr32(fp0, FREG(B11_8)); + } + tcg_temp_free(fp1); + tcg_temp_free(fp0); } return; } @@ -1481,35 +1543,53 @@ void _decode_opc(DisasContext * ctx) } return; case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */ - gen_op_movl_fpul_FT0(); - gen_op_fmov_FT0_frN(FREG(B11_8)); + { + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_mov_i32(fp, cpu_fpul); + gen_store_fpr32(fp, FREG(B11_8)); + tcg_temp_free(fp); + } return; case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */ - gen_op_fmov_frN_FT0(FREG(B11_8)); - gen_op_movl_FT0_fpul(); + { + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp, FREG(B11_8)); + tcg_gen_mov_i32(cpu_fpul, fp); + tcg_temp_free(fp); + } return; case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */ if (ctx->fpscr & FPSCR_PR) { + TCGv fp; if (ctx->opcode & 0x0100) break; /* illegal instruction */ - gen_op_float_DT(); - gen_op_fmov_DT0_drN(DREG(B11_8)); + fp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_helper_1_1(helper_float_DT, fp, cpu_fpul); + gen_store_fpr64(fp, DREG(B11_8)); + tcg_temp_free(fp); } else { - gen_op_float_FT(); - gen_op_fmov_FT0_frN(FREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_helper_1_1(helper_float_FT, fp, cpu_fpul); + gen_store_fpr32(fp, FREG(B11_8)); + tcg_temp_free(fp); } return; case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ if (ctx->fpscr & FPSCR_PR) { + TCGv fp; if (ctx->opcode & 0x0100) break; /* illegal instruction */ - gen_op_fmov_drN_DT0(DREG(B11_8)); - gen_op_ftrc_DT(); + fp = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp, DREG(B11_8)); + tcg_gen_helper_1_1(helper_ftrc_DT, cpu_fpul, fp); + tcg_temp_free(fp); } else { - gen_op_fmov_frN_FT0(FREG(B11_8)); - gen_op_ftrc_FT(); + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp, FREG(B11_8)); + tcg_gen_helper_1_1(helper_ftrc_FT, cpu_fpul, fp); + tcg_temp_free(fp); } return; case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */ @@ -1519,53 +1599,69 @@ void _decode_opc(DisasContext * ctx) if (ctx->fpscr & FPSCR_PR) { if (ctx->opcode & 0x0100) break; /* illegal instruction */ - gen_op_fmov_drN_DT0(DREG(B11_8)); - gen_op_fabs_DT(); - gen_op_fmov_DT0_drN(DREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp, DREG(B11_8)); + tcg_gen_helper_1_1(helper_fabs_DT, fp, fp); + gen_store_fpr64(fp, DREG(B11_8)); + tcg_temp_free(fp); } else { - gen_op_fmov_frN_FT0(FREG(B11_8)); - gen_op_fabs_FT(); - gen_op_fmov_FT0_frN(FREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp, FREG(B11_8)); + tcg_gen_helper_1_1(helper_fabs_FT, fp, fp); + gen_store_fpr32(fp, FREG(B11_8)); + tcg_temp_free(fp); } return; case 0xf06d: /* fsqrt FRn */ if (ctx->fpscr & FPSCR_PR) { if (ctx->opcode & 0x0100) break; /* illegal instruction */ - gen_op_fmov_drN_DT0(FREG(B11_8)); - gen_op_fsqrt_DT(); - gen_op_fmov_DT0_drN(FREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp, DREG(B11_8)); + tcg_gen_helper_1_1(helper_fsqrt_DT, fp, fp); + gen_store_fpr64(fp, DREG(B11_8)); + tcg_temp_free(fp); } else { - gen_op_fmov_frN_FT0(FREG(B11_8)); - gen_op_fsqrt_FT(); - gen_op_fmov_FT0_frN(FREG(B11_8)); + TCGv fp = tcg_temp_new(TCG_TYPE_I32); + gen_load_fpr32(fp, FREG(B11_8)); + tcg_gen_helper_1_1(helper_fsqrt_FT, fp, fp); + gen_store_fpr32(fp, FREG(B11_8)); + tcg_temp_free(fp); } return; case 0xf07d: /* fsrra FRn */ break; case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */ if (!(ctx->fpscr & FPSCR_PR)) { - tcg_gen_movi_i32(cpu_T[0], 0); - gen_op_fmov_T0_frN(FREG(B11_8)); + TCGv val = tcg_const_i32(0); + gen_load_fpr32(val, FREG(B11_8)); + tcg_temp_free(val); return; } break; case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */ if (!(ctx->fpscr & FPSCR_PR)) { - tcg_gen_movi_i32(cpu_T[0], 0x3f800000); - gen_op_fmov_T0_frN(FREG(B11_8)); + TCGv val = tcg_const_i32(0x3f800000); + gen_load_fpr32(val, FREG(B11_8)); + tcg_temp_free(val); return; } break; case 0xf0ad: /* fcnvsd FPUL,DRn */ - gen_op_movl_fpul_FT0(); - gen_op_fcnvsd_FT_DT(); - gen_op_fmov_DT0_drN(DREG(B11_8)); + { + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_helper_1_1(helper_fcnvsd_FT_DT, fp, cpu_fpul); + gen_store_fpr64(fp, DREG(B11_8)); + tcg_temp_free(fp); + } return; case 0xf0bd: /* fcnvds DRn,FPUL */ - gen_op_fmov_drN_DT0(DREG(B11_8)); - gen_op_fcnvds_DT_FT(); - gen_op_movl_FT0_fpul(); + { + TCGv fp = tcg_temp_new(TCG_TYPE_I64); + gen_load_fpr64(fp, DREG(B11_8)); + tcg_gen_helper_1_1(helper_fcnvds_DT_FT, cpu_fpul, fp); + tcg_temp_free(fp); + } return; } -- 1.7.9.5