From cee5be3c9c521000e7e1ec7bd425fb339f2d81c1 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Mon, 21 Dec 2020 19:10:14 +0300 Subject: [PATCH] e2k: add fxcmp{op}{type}b instructions --- target/e2k/helper.h | 21 ++++--- target/e2k/helper_fpu.c | 47 ++++++++------- target/e2k/translate/alc.c | 120 +++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 31 deletions(-) diff --git a/target/e2k/helper.h b/target/e2k/helper.h index fac935bc76..19e67b0de0 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -42,20 +42,25 @@ DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int) DEF_HELPER_3(name##s, i32, env, i32, i32) \ DEF_HELPER_3(name##d, i64, env, i64, i64) +#define DEF_HELPER_3_32_64_80(name) \ + DEF_HELPER_3_32_64(f##name) \ + DEF_HELPER_3(fx##name##x, i64, env, f80, f80) + DEF_HELPER_3_32_64(fadd) DEF_HELPER_3_32_64(fsub) DEF_HELPER_3_32_64(fmin) DEF_HELPER_3_32_64(fmax) DEF_HELPER_3_32_64(fmul) DEF_HELPER_3_32_64(fdiv) -DEF_HELPER_3_32_64(fcmpeq) -DEF_HELPER_3_32_64(fcmpneq) -DEF_HELPER_3_32_64(fcmple) -DEF_HELPER_3_32_64(fcmpnle) -DEF_HELPER_3_32_64(fcmplt) -DEF_HELPER_3_32_64(fcmpnlt) -DEF_HELPER_3_32_64(fcmpuod) -DEF_HELPER_3_32_64(fcmpod) +DEF_HELPER_3_32_64_80(cmpeq) +DEF_HELPER_3_32_64_80(cmpneq) +DEF_HELPER_3_32_64_80(cmple) +DEF_HELPER_3_32_64_80(cmpnle) +DEF_HELPER_3_32_64_80(cmplt) +DEF_HELPER_3_32_64_80(cmpnlt) +DEF_HELPER_3_32_64_80(cmpuod) +DEF_HELPER_3_32_64_80(cmpod) +#undef DEF_HELPER_3_32_64_80 #undef DEF_HELPER_3_32_64 DEF_HELPER_2(fstois, i32, env, i32) diff --git a/target/e2k/helper_fpu.c b/target/e2k/helper_fpu.c index 11e3266f02..89a7758426 100644 --- a/target/e2k/helper_fpu.c +++ b/target/e2k/helper_fpu.c @@ -6,7 +6,9 @@ #include "exec/helper-proto.h" #define glue3(x, y, z) glue(glue(x, y), z) +#define glue4(x, y, z, w) glue(glue3(x, y, z), w) #define deref(x) *(x) +#define no_cvt(x) (x) /* when in correct type */ static inline void fpu_set_exception(CPUE2KState *env, int mask) { @@ -84,16 +86,23 @@ void e2k_update_fp_status(CPUE2KState *env) return float##size##_val(z); \ } -#define GENERATE_CMP_FLOAT2_OP(name, function, expr, size) \ - uint##size##_t HELPER(name)(CPUE2KState *env, uint##size##_t x, uint##size##_t y) \ +#define GENERATE_SIMPLE_FLOAT2_OPS_32_64(name, function) \ + GENERATE_SIMPLE_FLOAT2_OP(glue(name, s), function, 32) \ + GENERATE_SIMPLE_FLOAT2_OP(glue(name, d), function, 64) + +#define GENERATE_CMP_FLOAT2_OP(ret_type, name, expr, op, in_type, cvt_macro) \ + ret_type HELPER(name)(CPUE2KState *env, in_type x, in_type y) \ { \ uint8_t old_flags = save_exception_flags(env); \ - uint##size##_t z = expr float##size##_##function (make_float##size (x), make_float##size (y), &env->fp_status); \ + ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fp_status); \ merge_exception_flags(env, old_flags); \ return z; \ } -#define no_cvt(x) (x) // when function already returns in correct type +#define GENERATE_CMP_FLOAT2_OPS_32_64_80(name, expr, op) \ + GENERATE_CMP_FLOAT2_OP(uint32_t, glue3(f, name, s), expr, glue(float32_, op), uint32_t, make_float32) \ + GENERATE_CMP_FLOAT2_OP(uint64_t, glue3(f, name, d), expr, glue(float64_, op), uint64_t, make_float32) \ + GENERATE_CMP_FLOAT2_OP(uint64_t, glue3(fx, name, x), expr, glue(floatx80_, op), floatx80*, deref) #define GENERATE_CVT_FLOAT1_OP(name, from_t, to_t, size_from, size_to, func_from, func_to) \ size_to HELPER(name)(CPUE2KState *env, size_from x) \ @@ -104,28 +113,20 @@ void e2k_update_fp_status(CPUE2KState *env) return z; \ } -#define GENERATE_SIMPLE_FLOAT2_OPS_32_64(name, function) \ - 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(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) GENERATE_SIMPLE_FLOAT2_OPS_32_64(fmin, min) GENERATE_SIMPLE_FLOAT2_OPS_32_64(fmax, max) GENERATE_SIMPLE_FLOAT2_OPS_32_64(fmul, mul) GENERATE_SIMPLE_FLOAT2_OPS_32_64(fdiv, div) -GENERATE_CMP_FLOAT2_OPS_32_64(fcmpeq, eq, ) -GENERATE_CMP_FLOAT2_OPS_32_64(fcmpneq, eq, !) -GENERATE_CMP_FLOAT2_OPS_32_64(fcmple, le, ) -GENERATE_CMP_FLOAT2_OPS_32_64(fcmpnle, le, !) -GENERATE_CMP_FLOAT2_OPS_32_64(fcmplt, lt, ) -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_CMP_FLOAT2_OPS_32_64_80(cmpeq, , eq) +GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpneq, !, eq) +GENERATE_CMP_FLOAT2_OPS_32_64_80(cmple, , le) +GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpnle, !, le) +GENERATE_CMP_FLOAT2_OPS_32_64_80(cmplt, , lt) +GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpnlt, !, lt) +GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpuod, , unordered) +GENERATE_CMP_FLOAT2_OPS_32_64_80(cmpod, !, unordered) 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) @@ -165,9 +166,9 @@ void HELPER(fdtofx)(floatx80 *ret, CPUE2KState *env, uint64_t x) #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); \ + 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) diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 07e7e8216a..82ad71574a 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -1220,6 +1220,58 @@ static void gen_fcmp_i64(TCGv_i64 ret, int opc, TCGv_i64 src1, TCGv_i64 src2) tcg_temp_free_i64(dst); } +static void gen_fcmp_f80(TCGv_i64 ret, int opc, Src80 src1, Src80 src2) +{ + void (*f)(TCGv_i64, TCGv_env, TCGv_ptr, TCGv_ptr) = 0; + TCGv_i64 dst = tcg_temp_new_i64(); + TCGv_ptr t0 = tcg_temp_new_ptr(); + TCGv_ptr t1 = tcg_temp_new_ptr(); + + 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); + + switch(opc) { + case 0: /* eq */ + f = gen_helper_fxcmpeqx; + break; + case 1: /* lt */ + f = gen_helper_fxcmpltx; + break; + case 2: /* le */ + f = gen_helper_fxcmplex; + break; + case 3: /* uod */ + f = gen_helper_fxcmpuodx; + break; + case 4: /* neq */ + f = gen_helper_fxcmpneqx; + break; + case 5: /* nlt */ + f = gen_helper_fxcmpnltx; + break; + case 6: /* nle */ + f = gen_helper_fxcmpnlex; + break; + case 7: /* od */ + f = gen_helper_fxcmpodx; + break; + default: + e2k_gen_exception(E2K_EXCP_ILLOPC); + break; + } + + (*f)(dst, cpu_env, t0, t1); + + tcg_gen_setcondi_i64(TCG_COND_NE, ret, dst, 0); + + tcg_temp_free_ptr(t1); + tcg_temp_free_ptr(t0); + tcg_temp_free_i64(dst); +} + /* * ret[31:0] = x[31:0] * ret[63:32] = y[63:32] @@ -2206,6 +2258,55 @@ static void gen_alopf1_cmp_i32(DisasContext *ctx, Instr *instr, tcg_temp_free_i32(t0); } +static void gen_alopf1_cmp_f80(DisasContext *ctx, Instr *instr, Src80 s2, TCGv_i32 s2tag) +{ + int chan = instr->chan; + TCGLabel *l0 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); + Src80 s1 = get_src1_i80(ctx, instr->src1); + TCGv_i64 dst = e2k_get_temp_i64(ctx); + TCGv_i32 t0 = tcg_temp_new_i32(); + + gen_tag2_i64(t0, s1.tag, s2tag); + gen_tag_check(ctx, instr->sm, t0); + tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l0); + gen_fcmp_f80(dst, instr->opc_cmp, s1, s2); + tcg_gen_br(l1); + gen_set_label(l0); + tcg_gen_movi_i64(dst, 2); + gen_set_label(l1); + set_al_result_preg(ctx, chan, instr->dst_preg, dst); + tcg_temp_free_i32(t0); +} + +static void gen_alopf1_cmp_xx(DisasContext *ctx, Instr *instr) +{ + Src80 s2 = get_src2_i80(ctx, instr->src2); + gen_alopf1_cmp_f80(ctx, instr, s2, s2.tag); +} + +static void gen_alopf1_cmp_xd(DisasContext *ctx, Instr *instr) +{ + Src64 s2 = get_src2_i64(ctx, instr->chan); + Src80 t2 = temp_new_src80(); + + gen_fdtofx(&t2, s2.value); + gen_alopf1_cmp_f80(ctx, instr, t2, s2.tag); + + temp_free_src80(&t2); +} + +static void gen_alopf1_cmp_xs(DisasContext *ctx, Instr *instr) +{ + Src32 s2 = get_src2_i32(ctx, instr->chan); + Src80 t2 = temp_new_src80(); + + gen_fstofx(&t2, s2.value); + gen_alopf1_cmp_f80(ctx, instr, t2, s2.tag); + + temp_free_src80(&t2); +} + static void gen_alopf1_mrgc_i32(DisasContext *ctx, Instr *instr) { Src32 s1 = get_src1_i32(ctx, instr->chan); @@ -2628,6 +2729,25 @@ static void gen_no_ext(DisasContext *ctx, Instr *instr) } break; } + case 0x28: + if (is_chan_0134(chan)) { + /* fxcmp{op}sb */ + gen_alopf1_cmp_xs(ctx, instr); + return; + } + case 0x29: + if (is_chan_0134(chan)) { + /* fxcmp{op}db */ + gen_alopf1_cmp_xd(ctx, instr); + return; + } + case 0x2b: { + if (is_chan_0134(chan)) { + /* fxcmp{op}xb */ + gen_alopf1_cmp_xx(ctx, instr); + return; + } + } case 0x2e: { if (is_chan_0134(chan)) { /* fcmp{op}sb */