From a0e898c7da668bdaddaadd20e87e34a54a100946 Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Wed, 16 Dec 2020 21:19:01 +0200 Subject: [PATCH] target: e2k: Add basic FX instrs. --- target/e2k/helper.h | 18 ++ target/e2k/helper_fpu.c | 80 +++++-- target/e2k/translate.c | 4 +- target/e2k/translate/alc.c | 471 ++++++++++++++++++++++++++++++++++++- 4 files changed, 547 insertions(+), 26 deletions(-) diff --git a/target/e2k/helper.h b/target/e2k/helper.h index ca4b4f7676..6685f62b92 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -1,3 +1,10 @@ +#define dh_alias_Reg ptr +#define dh_alias_f80 ptr +#define dh_ctype_Reg E2KReg * +#define dh_ctype_f80 floatx80 * +#define dh_is_signed_Reg dh_is_signed_ptr +#define dh_is_signed_f80 dh_is_signed_ptr + DEF_HELPER_2(raise_exception, noreturn, env, int) DEF_HELPER_2(raise_exception_no_spill, noreturn, env, int) DEF_HELPER_1(debug, void, env) @@ -51,10 +58,12 @@ DEF_HELPER_3_32_64(fcmpod) DEF_HELPER_2(fstois, i32, env, i32) DEF_HELPER_2(istofs, i32, env, i32) DEF_HELPER_2(fstoistr, i32, env, i32) +DEF_HELPER_3(fstofx, void, f80, env, i32) DEF_HELPER_2(fdtoid, i64, env, i64) DEF_HELPER_2(idtofd, i64, env, i64) DEF_HELPER_2(fdtoidtr, i64, env, i64) +DEF_HELPER_3(fdtofx, void, f80, env, i64) DEF_HELPER_2(fstofd, i64, env, i32) DEF_HELPER_2(fstoid, i64, env, i32) @@ -65,3 +74,12 @@ DEF_HELPER_2(fdtofs, i32, env, i64) DEF_HELPER_2(fdtois, i32, env, i64) DEF_HELPER_2(idtofs, i32, env, i64) DEF_HELPER_2(fdtoistr, i32, env, i64) + +DEF_HELPER_2(fxtofs, i32, env, f80) +DEF_HELPER_2(fxtofd, i64, env, f80) + +DEF_HELPER_3(fxaddxx, void, env, f80, f80) +DEF_HELPER_3(fxsubxx, void, env, f80, f80) +DEF_HELPER_3(fxrsubxx, void, env, f80, f80) +DEF_HELPER_3(fxmulxx, void, env, f80, f80) +DEF_HELPER_3(fxdivxx, void, env, f80, f80) diff --git a/target/e2k/helper_fpu.c b/target/e2k/helper_fpu.c index b941a7e318..3e0a63138d 100644 --- a/target/e2k/helper_fpu.c +++ b/target/e2k/helper_fpu.c @@ -5,6 +5,9 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" +#define glue3(x, y, z) glue(glue(x, y), z) +#define deref(x) *(x) + static inline void fpu_set_exception(CPUE2KState *env, int mask) { env->fpsr.ef |= mask; @@ -93,21 +96,21 @@ void e2k_update_fp_status(CPUE2KState *env) #define no_cvt(x) (x) // when function already returns in correct type #define GENERATE_CVT_FLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \ - uint##size_to##_t HELPER(name)(CPUE2KState *env, uint##size_from##_t x) \ + size_to HELPER(name)(CPUE2KState *env, size_from x) \ {\ uint8_t old_flags = save_exception_flags(env); \ - uint##size_to##_t z = func_to( from_t##_to_##to_t (func_from(x), &env->fp_status) );\ + size_to z = func_to( glue3(from_t, _to_, to_t) (func_from(x), &env->fp_status) );\ merge_exception_flags(env, old_flags); \ return z; \ } #define GENERATE_SIMPLE_FLOAT2_OPS_32_64(name, function) \ - GENERATE_SIMPLE_FLOAT2_OP(name##s, function, 32) \ - GENERATE_SIMPLE_FLOAT2_OP(name##d, function, 64) + GENERATE_SIMPLE_FLOAT2_OP(glue(name, s), function, 32) \ + GENERATE_SIMPLE_FLOAT2_OP(glue(name, d), function, 64) #define GENERATE_CMP_FLOAT2_OPS_32_64(name, function, expr) \ - GENERATE_CMP_FLOAT2_OP(name##s, function, expr, 32) \ - GENERATE_CMP_FLOAT2_OP(name##d, function, expr, 64) + GENERATE_CMP_FLOAT2_OP(glue(name, s), function, expr, 32) \ + GENERATE_CMP_FLOAT2_OP(glue(name, d), function, expr, 64) GENERATE_SIMPLE_FLOAT2_OPS_32_64(fadd, add) GENERATE_SIMPLE_FLOAT2_OPS_32_64(fsub, sub) @@ -124,20 +127,57 @@ GENERATE_CMP_FLOAT2_OPS_32_64(fcmpnlt, lt, !) GENERATE_CMP_FLOAT2_OPS_32_64(fcmpuod, unordered, ) GENERATE_CMP_FLOAT2_OPS_32_64(fcmpod, unordered, !) -GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, 32, 32, make_float32, no_cvt) -GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, 32, 32, no_cvt, float32_val) -GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, 32, 32, make_float32, no_cvt) +GENERATE_CVT_FLOAT1_OP(fstois, float32, int32, uint32_t, uint32_t, make_float32, no_cvt) +GENERATE_CVT_FLOAT1_OP(istofs, int32, float32, uint32_t, uint32_t, no_cvt, float32_val) +GENERATE_CVT_FLOAT1_OP(fstoistr, float32, int32_round_to_zero, uint32_t, uint32_t, make_float32, no_cvt) -GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, 64, 64, make_float64, no_cvt) -GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, 64, 64, no_cvt, float64_val) -GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, 64, 64, make_float64, no_cvt) +GENERATE_CVT_FLOAT1_OP(fdtoid, float64, int64, uint64_t, uint64_t, make_float64, no_cvt) +GENERATE_CVT_FLOAT1_OP(idtofd, int64, float64, uint64_t, uint64_t, no_cvt, float64_val) +GENERATE_CVT_FLOAT1_OP(fdtoidtr, float64, int64_round_to_zero, uint64_t, uint64_t, make_float64, no_cvt) -GENERATE_CVT_FLOAT1_OP(fstofd, float32, float64, 32, 64, make_float32, float64_val) -GENERATE_CVT_FLOAT1_OP(fstoid, float32, int64, 32, 64, make_float32, no_cvt) -GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, 32, 64, no_cvt, float64_val) -GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, 32, 64, make_float32, no_cvt) +GENERATE_CVT_FLOAT1_OP(fstofd, float32, float64, uint32_t, uint64_t, make_float32, float64_val) +GENERATE_CVT_FLOAT1_OP(fstoid, float32, int64, uint32_t, uint64_t, make_float32, no_cvt) +GENERATE_CVT_FLOAT1_OP(istofd, int32, float64, uint32_t, uint64_t, no_cvt, float64_val) +GENERATE_CVT_FLOAT1_OP(fstoidtr, float32, int64_round_to_zero, uint32_t, uint64_t, make_float32, no_cvt) -GENERATE_CVT_FLOAT1_OP(fdtofs, float64, float32, 64, 32, make_float64, float32_val) -GENERATE_CVT_FLOAT1_OP(fdtois, float64, int32, 64, 32, make_float64, no_cvt) -GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, 64, 32, no_cvt, float32_val) -GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, 64, 32, make_float64, no_cvt) +GENERATE_CVT_FLOAT1_OP(fdtofs, float64, float32, uint64_t, uint32_t, make_float64, float32_val) +GENERATE_CVT_FLOAT1_OP(fdtois, float64, int32, uint64_t, uint32_t, make_float64, no_cvt) +GENERATE_CVT_FLOAT1_OP(idtofs, int64, float32, uint64_t, uint32_t, no_cvt, float32_val) +GENERATE_CVT_FLOAT1_OP(fdtoistr, float64, int32_round_to_zero, uint64_t, uint32_t, make_float64, no_cvt) + +GENERATE_CVT_FLOAT1_OP(fxtofs, floatx80, float32, floatx80*, uint32_t, deref, float32_val) +GENERATE_CVT_FLOAT1_OP(fxtofd, floatx80, float64, floatx80*, uint64_t, deref, float64_val) + +void HELPER(fstofx)(floatx80 *ret, CPUE2KState *env, uint32_t x) +{ + uint8_t old_flags = save_exception_flags(env); + *ret = float32_to_floatx80(make_float32(x), &env->fp_status); + merge_exception_flags(env, old_flags); +} + +void HELPER(fdtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x) +{ + uint8_t old_flags = save_exception_flags(env); + *ret = float64_to_floatx80(make_float64(x), &env->fp_status); + merge_exception_flags(env, old_flags); +} + +#define GEN_OP2_XX(name, op) \ + void HELPER(name)(CPUE2KState *env, floatx80 *x, floatx80 *y) \ + { \ + uint8_t old_flags = save_exception_flags(env); \ + *x = glue(floatx80_, op)(*x, *y, &env->fp_status); \ + merge_exception_flags(env, old_flags); \ + } + +GEN_OP2_XX(fxaddxx, add) +GEN_OP2_XX(fxsubxx, sub) +GEN_OP2_XX(fxmulxx, mul) +GEN_OP2_XX(fxdivxx, div) + +void HELPER(fxrsubxx)(CPUE2KState *env, floatx80 *x, floatx80 *y) +{ + uint8_t old_flags = save_exception_flags(env); + *x = floatx80_sub(*y, *x, &env->fp_status); + merge_exception_flags(env, old_flags); +} diff --git a/target/e2k/translate.c b/target/e2k/translate.c index f681e45a2b..95bb7b95b5 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -372,11 +372,11 @@ static inline void do_branch(DisasContext *ctx, target_ulong pc_next) static void e2k_tr_init_disas_context(DisasContextBase *db, CPUState *cs) { - DisasContext *dc = container_of(db, DisasContext, base); + DisasContext *ctx = container_of(db, DisasContext, base); E2KCPU *cpu = E2K_CPU(cs); CPUE2KState *env = &cpu->env; - dc->version = env->version; + ctx->version = env->version; } static bool e2k_tr_breakpoint_check(DisasContextBase *db, CPUState *cs, diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 0e920efc8a..246ac6fed7 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -19,6 +19,35 @@ typedef struct { TCGv_i32 value; } Src32; +static inline Src80 temp_new_src80(void) +{ + Src80 t = { 0 }; + + t.tag = tcg_temp_new_i32(); + t.lo = tcg_temp_new_i64(); + t.hi = tcg_temp_new_i32(); + + return t; +} + +static inline void temp_free_src80(Src80 *t) +{ + tcg_temp_free_i32(t->tag); + tcg_temp_free_i64(t->lo); + tcg_temp_free_i32(t->hi); +} + +static inline Src80 get_temp_src80(DisasContext *ctx) +{ + Src80 t = { 0 }; + + t.tag = e2k_get_temp_i32(ctx); + t.lo = e2k_get_temp_i64(ctx); + t.hi = e2k_get_temp_i32(ctx); + + return t; +} + typedef struct { int chan; union { @@ -131,6 +160,20 @@ static inline void gen_reg_i32(DisasContext *ctx, Src32 *ret, uint8_t arg) tcg_temp_free_i32(t0); } +static inline void gen_temp_reg_write_i64_i32(TCGv_i64 lo, TCGv_i32 hi, + TCGv_ptr ptr) +{ + tcg_gen_st_i64(lo, ptr, offsetof(E2KReg, f80.low)); + tcg_gen_st16_i32(hi, ptr, offsetof(E2KReg, f80.high)); +} + +static inline void gen_temp_reg_read_i64_i32(TCGv_ptr ptr, TCGv_i64 ret_lo, + TCGv_i32 ret_hi) +{ + tcg_gen_ld_i64(ret_lo, ptr, offsetof(E2KReg, f80.low)); + tcg_gen_ld16u_i32(ret_hi, ptr, offsetof(E2KReg, f80.high)); +} + static inline void gen_literal_i64(DisasContext *ctx, Src64 *ret, uint8_t arg) { int i = GET_LIT(arg); @@ -1650,6 +1693,46 @@ static inline void gen_movif(DisasContext *ctx, Instr *instr) gen_al_result_i80(ctx, instr, src1.value, src2.value, tag); } +static inline void gen_fstofx(Src80 *ret, TCGv_i32 src2) +{ + TCGv_ptr t0 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0.f80)); + gen_helper_fstofx(t0, cpu_env, src2); + gen_temp_reg_read_i64_i32(t0, ret->lo, ret->hi); + tcg_temp_free_ptr(t0); +} + +static inline void gen_fdtofx(Src80 *ret, TCGv_i64 src2) +{ + TCGv_ptr t0 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0)); + gen_helper_fdtofx(t0, cpu_env, src2); + gen_temp_reg_read_i64_i32(t0, ret->lo, ret->hi); + tcg_temp_free_ptr(t0); +} + +static inline void gen_fxtofs(TCGv_i32 ret, Src80 src2) +{ + TCGv_ptr t0 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0)); + gen_temp_reg_write_i64_i32(src2.lo, src2.hi, t0); + gen_helper_fxtofs(ret, cpu_env, t0); + tcg_temp_free_ptr(t0); +} + +static inline void gen_fxtofd(TCGv_i64 ret, Src80 src2) +{ + TCGv_ptr t0 = tcg_temp_new_ptr(); + + tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0)); + gen_temp_reg_write_i64_i32(src2.lo, src2.hi, t0); + gen_helper_fxtofd(ret, cpu_env, t0); + tcg_temp_free_ptr(t0); +} + static void gen_aad_tag(TCGv_i64 ret, TCGv_i32 tag) { TCGv_i32 t0 = tcg_temp_new_i32(); @@ -2186,6 +2269,191 @@ static void gen_alopf2_i32_i64_env(DisasContext *ctx, int chan, void (*op)(TCGv_ gen_al_result_i64(ctx, chan, dst, tag); } +static inline void gen_alopf1_f80(Src80 *ret, Src80 src1, Src80 src2, + void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr)) +{ + TCGv_ptr t0 = tcg_temp_new_ptr(); + TCGv_ptr t1 = tcg_temp_new_ptr(); + + gen_tag2_i64(ret->tag, src1.tag, src2.tag); + + tcg_gen_addi_ptr(t0, cpu_env, offsetof(CPUE2KState, t0.f80)); + tcg_gen_addi_ptr(t1, cpu_env, offsetof(CPUE2KState, t1.f80)); + + gen_temp_reg_write_i64_i32(src1.lo, src1.hi, t0); + gen_temp_reg_write_i64_i32(src2.lo, src2.hi, t1); + + (*op)(cpu_env, t0, t1); + + gen_temp_reg_read_i64_i32(t0, ret->lo, ret->hi); + + tcg_temp_free_ptr(t1); + tcg_temp_free_ptr(t0); +} + +static inline void gen_alopf1_xxx(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr)) +{ + Src80 src1 = get_src1_i80(ctx, instr->src1); + Src80 src2 = get_src2_i80(ctx, instr->src2); + Src80 res = get_temp_src80(ctx); + gen_alopf1_f80(&res, src1, src2, op); + gen_al_result_i80(ctx, instr, res.lo, res.hi, res.tag); +} + +static inline void gen_alopf1_xxs(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr)) +{ + Src80 src1 = get_src1_i80(ctx, instr->src1); + Src80 src2 = get_src2_i80(ctx, instr->chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + TCGv_i32 dst = e2k_get_temp_i32(ctx); + Src80 t0 = temp_new_src80(); + + gen_tag2_i32(tag, src1.tag, src2.tag); + gen_alopf1_f80(&t0, src1, src2, op); + gen_fxtofs(dst, t0); + gen_al_result_i32(ctx, instr->chan, dst, tag); + + temp_free_src80(&t0); +} + +static inline void gen_alopf1_xxd(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr)) +{ + Src80 src1 = get_src1_i80(ctx, instr->src1); + Src80 src2 = get_src2_i80(ctx, instr->chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + TCGv_i64 dst = e2k_get_temp_i64(ctx); + Src80 t0 = temp_new_src80(); + + gen_tag2_i64(tag, src1.tag, src2.tag); + gen_alopf1_f80(&t0, src1, src2, op); + gen_fxtofd(dst, t0); + gen_al_result_i64(ctx, instr->chan, dst, tag); + + temp_free_src80(&t0); +} + +static inline void gen_alopf1_xss(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr)) +{ + Src80 src1 = get_src1_i80(ctx, instr->src1); + Src32 src2 = get_src2_i32(ctx, instr->chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + TCGv_i32 dst = e2k_get_temp_i32(ctx); + Src80 t0 = temp_new_src80(); + Src80 t1 = temp_new_src80(); + + gen_tag2_i32(tag, src1.tag, src2.tag); + gen_fstofx(&t0, src2.value); + gen_alopf1_f80(&t1, src1, t0, op); + gen_fxtofs(dst, t1); + gen_al_result_i32(ctx, instr->chan, dst, tag); + + temp_free_src80(&t1); + temp_free_src80(&t0); +} + +static inline void gen_alopf1_xdd(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr)) +{ + Src80 src1 = get_src1_i80(ctx, instr->src1); + Src64 src2 = get_src2_i64(ctx, instr->chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + TCGv_i64 dst = e2k_get_temp_i64(ctx); + Src80 t0 = temp_new_src80(); + Src80 t1 = temp_new_src80(); + + gen_tag2_i64(tag, src1.tag, src2.tag); + gen_fdtofx(&t0, src2.value); + gen_alopf1_f80(&t1, src1, t0, op); + gen_fxtofd(dst, t1); + gen_al_result_i64(ctx, instr->chan, dst, tag); + + temp_free_src80(&t1); + temp_free_src80(&t0); +} + +static inline void gen_alopf1_xsx(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr)) +{ + Src80 src1 = get_src1_i80(ctx, instr->src1); + Src32 src2 = get_src2_i32(ctx, instr->chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + Src80 t0 = temp_new_src80(); + Src80 t1 = get_temp_src80(ctx); + + gen_tag2_i64(tag, src1.tag, src2.tag); + gen_fstofx(&t0, src2.value); + gen_alopf1_f80(&t1, src1, t0, op); + gen_al_result_i80(ctx, instr, t1.lo, t1.hi, tag); + + temp_free_src80(&t0); +} + +static inline void gen_alopf1_xdx(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_env, TCGv_ptr, TCGv_ptr)) +{ + Src80 src1 = get_src1_i80(ctx, instr->src1); + Src64 src2 = get_src2_i64(ctx, instr->chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + Src80 t0 = temp_new_src80(); + Src80 t1 = get_temp_src80(ctx); + + gen_tag2_i64(tag, src1.tag, src2.tag); + gen_fdtofx(&t0, src2.value); + gen_alopf1_f80(&t1, src1, t0, op); + gen_al_result_i80(ctx, instr, t1.lo, t1.hi, tag); + + temp_free_src80(&t0); +} + +static inline void gen_alopf2_xs(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_i32 ret, Src80 src2)) +{ + Src80 src2 = get_src2_i80(ctx, instr->chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + TCGv_i32 dst = e2k_get_temp_i32(ctx); + + gen_tag1_i32(tag, src2.tag); + (*op)(dst, src2); + gen_al_result_i32(ctx, instr->chan, dst, tag); +} + +static inline void gen_alopf2_xd(DisasContext *ctx, Instr *instr, + void (*op)(TCGv_i64 ret, Src80 src2)) +{ + Src80 src2 = get_src2_i80(ctx, instr->chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + TCGv_i64 dst = e2k_get_temp_i64(ctx); + + gen_tag1_i32(tag, src2.tag); + (*op)(dst, src2); + gen_al_result_i64(ctx, instr->chan, dst, tag); +} + +static inline void gen_alopf2_sx(DisasContext *ctx, Instr *instr, + void (*op)(Src80 *ret, TCGv_i32 src2)) +{ + Src32 src2 = get_src2_i32(ctx, instr->chan); + Src80 res = get_temp_src80(ctx); + + gen_tag1_i64(res.tag, src2.tag); + (*op)(&res, src2.value); + gen_al_result_i80(ctx, instr, res.lo, res.hi, res.tag); +} + +static inline void gen_alopf2_dx(DisasContext *ctx, Instr *instr, + void (*op)(Src80 *ret, TCGv_i64 src2)) +{ + Src64 src2 = get_src2_i64(ctx, instr->chan); + Src80 res = get_temp_src80(ctx); + + gen_tag1_i64(res.tag, src2.tag); + (*op)(&res, src2.value); + gen_al_result_i80(ctx, instr, res.lo, res.hi, res.tag); +} static void execute_ext_00(DisasContext *ctx, Instr *instr) { @@ -2401,6 +2669,8 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr) case 0xc0: func = gen_helper_fdtoid; break; case 0xc2: func = ctx->version >= 2 ? gen_helper_fdtoidtr : 0; break; case 0xc4: func = gen_helper_idtofd; break; + case 0xc6: gen_alopf2_xd(ctx, instr, gen_fxtofd); return; + case 0xc7: gen_alopf2_dx(ctx, instr, gen_fdtofx); return; } if (func) { @@ -2418,6 +2688,7 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr) case 0xc2: func = ctx->version >= 2 ? gen_helper_fstoidtr : 0; break; case 0xc4: func = gen_helper_istofd; break; case 0xc6: func = gen_helper_fstofd; break; + case 0xc7: gen_alopf2_sx(ctx, instr, gen_fstofx); return; } if (func) { @@ -2435,6 +2706,7 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr) case 0xc2: func = gen_helper_fdtoistr; break; case 0xc4: func = gen_helper_idtofs; break; case 0xc6: func = gen_helper_fdtofs; break; + case 0xc7: gen_alopf2_xs(ctx, instr, gen_fxtofs); return; } if (func) { @@ -2444,7 +2716,11 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr) } break; case 0x40: - if (chan == 5) { + if (is_chan_0134(chan)) { + /* fxaddss */ + gen_alopf1_xss(ctx, instr, gen_helper_fxaddxx); + return; + } else if (chan == 5) { // FIXME: temp hack if (instr->src2 == 0xc0) { e2k_tr_gen_exception_no_spill(ctx, 0); @@ -2457,26 +2733,213 @@ static void execute_ext_00(DisasContext *ctx, Instr *instr) } break; case 0x41: - if (chan == 5) { + if (is_chan_0134(chan)) { + /* fxadddd */ + gen_alopf1_xdd(ctx, instr, gen_helper_fxaddxx); + return; + } else if (chan == 5) { /* udivd */ gen_alopf1_tag_i64(ctx, chan, gen_udivd); return; } break; case 0x42: - if (chan == 5) { + if (is_chan_0134(chan)) { + /* fxaddsx */ + gen_alopf1_xsx(ctx, instr, gen_helper_fxaddxx); + return; + } else if (chan == 5) { /* sdivs */ gen_alopf1_tag_i32(ctx, chan, gen_sdivs); return; } break; case 0x43: - if (chan == 5) { + if (is_chan_0134(chan)) { + /* fxadddx */ + gen_alopf1_xdx(ctx, instr, gen_helper_fxaddxx); + return; + } else if (chan == 5) { /* sdivd */ gen_alopf1_tag_i64(ctx, chan, gen_sdivd); return; } break; + case 0x44: + if (is_chan_0134(chan)) { + /* fxaddxs */ + gen_alopf1_xxs(ctx, instr, gen_helper_fxaddxx); + return; + } + break; + case 0x45: + if (is_chan_0134(chan)) { + /* fxaddxd */ + gen_alopf1_xxd(ctx, instr, gen_helper_fxaddxx); + return; + } + break; + case 0x47: + if (is_chan_0134(chan)) { + /* fxaddxx */ + gen_alopf1_xxx(ctx, instr, gen_helper_fxaddxx); + return; + } + break; + case 0x48: + if (is_chan_0134(chan)) { + /* fxsubss */ + gen_alopf1_xss(ctx, instr, gen_helper_fxsubxx); + return; + } else if (chan == 5) { + /* fxdivss */ + gen_alopf1_xss(ctx, instr, gen_helper_fxdivxx); + return; + } + break; + case 0x49: + if (is_chan_0134(chan)) { + /* fxsubdd */ + gen_alopf1_xdd(ctx, instr, gen_helper_fxsubxx); + return; + } else if (chan == 5) { + /* fxdivdd */ + gen_alopf1_xdd(ctx, instr, gen_helper_fxdivxx); + return; + } + break; + case 0x4a: + if (is_chan_0134(chan)) { + /* fxsubsx */ + gen_alopf1_xsx(ctx, instr, gen_helper_fxsubxx); + return; + } else if (chan == 5) { + /* fxdivsx */ + gen_alopf1_xsx(ctx, instr, gen_helper_fxdivxx); + return; + } + break; + case 0x4b: + if (is_chan_0134(chan)) { + /* fxsubdx */ + gen_alopf1_xdx(ctx, instr, gen_helper_fxsubxx); + return; + } else if (chan == 5) { + /* fxdivdx */ + gen_alopf1_xdx(ctx, instr, gen_helper_fxdivxx); + return; + } + break; + case 0x4c: + if (is_chan_0134(chan)) { + /* fxsubxs */ + gen_alopf1_xxs(ctx, instr, gen_helper_fxsubxx); + return; + } else if (chan == 5) { + /* fxdivxs */ + gen_alopf1_xxs(ctx, instr, gen_helper_fxdivxx); + return; + } + break; + case 0x4d: + if (is_chan_0134(chan)) { + /* fxsubxd */ + gen_alopf1_xxd(ctx, instr, gen_helper_fxsubxx); + return; + } else if (chan == 5) { + /* fxdivxd */ + gen_alopf1_xxd(ctx, instr, gen_helper_fxdivxx); + return; + } + break; + case 0x4f: + if (is_chan_0134(chan)) { + /* fxsubxx */ + gen_alopf1_xxx(ctx, instr, gen_helper_fxsubxx); + return; + } else if (chan == 5) { + /* fxdivxx */ + gen_alopf1_xxx(ctx, instr, gen_helper_fxdivxx); + return; + } + break; + case 0x50: + if (is_chan_0134(chan)) { + /* fxmulss */ + gen_alopf1_xss(ctx, instr, gen_helper_fxmulxx); + return; + } + break; + case 0x51: + if (is_chan_0134(chan)) { + /* fxmuldd */ + gen_alopf1_xdd(ctx, instr, gen_helper_fxmulxx); + return; + } + break; + case 0x52: + if (is_chan_0134(chan)) { + /* fxmulsx */ + gen_alopf1_xsx(ctx, instr, gen_helper_fxmulxx); + return; + } + break; + case 0x53: + if (is_chan_0134(chan)) { + /* fxmuldx */ + gen_alopf1_xdx(ctx, instr, gen_helper_fxmulxx); + return; + } + break; + case 0x54: + if (is_chan_0134(chan)) { + /* fxmulxs */ + gen_alopf1_xxs(ctx, instr, gen_helper_fxmulxx); + return; + } + break; + case 0x55: + if (is_chan_0134(chan)) { + /* fxmulxd */ + gen_alopf1_xxd(ctx, instr, gen_helper_fxmulxx); + return; + } + break; + case 0x57: + if (is_chan_0134(chan)) { + /* fxmulxx */ + gen_alopf1_xxx(ctx, instr, gen_helper_fxmulxx); + return; + } + break; + case 0x58: + if (is_chan_0134(chan)) { + /* fxrsubss */ + gen_alopf1_xss(ctx, instr, gen_helper_fxrsubxx); + return; + } + break; + case 0x59: + if (is_chan_0134(chan)) { + /* fxrsubdd */ + gen_alopf1_xdd(ctx, instr, gen_helper_fxrsubxx); + return; + } + break; + case 0x5a: + if (is_chan_0134(chan)) { + /* fxrsubsx */ + gen_alopf1_xsx(ctx, instr, gen_helper_fxrsubxx); + return; + } + break; + case 0x5b: + if (is_chan_0134(chan)) { + /* fxrsubdx */ + gen_alopf1_xdx(ctx, instr, gen_helper_fxrsubxx); + return; + } + break; case 0x5c: if (is_chan_14(chan) || (ctx->version >= 2 && is_chan_03(chan))) { /* movfi */