e2k: implement f{,x}cmp{op}{s,d,x}f instructions

This commit is contained in:
Alibek Omarov 2021-01-08 04:45:48 +03:00 committed by Denis Drakhnia
parent 7f3dbf0c0d
commit 6f463100cc
3 changed files with 176 additions and 11 deletions

View File

@ -91,3 +91,10 @@ 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)
DEF_HELPER_3(fcmpodsf, i32, env, i32, i32)
DEF_HELPER_3(fcmpudsf, i32, env, i32, i32)
DEF_HELPER_3(fcmpoddf, i32, env, i64, i64)
DEF_HELPER_3(fcmpuddf, i32, env, i64, i64)
DEF_HELPER_3(fxcmpodxf, i32, env, f80, f80)
DEF_HELPER_3(fxcmpudxf, i32, env, f80, f80)

View File

@ -75,7 +75,6 @@ void e2k_update_fp_status(CPUE2KState *env)
}
set_floatx80_rounding_precision(x, &env->fp_status);
}
#define GENERATE_SIMPLE_FLOAT2_OP(name, function, size) \
@ -183,3 +182,84 @@ void HELPER(fxrsubxx)(CPUE2KState *env, floatx80 *x, floatx80 *y)
*x = floatx80_sub(*y, *x, &env->fp_status);
merge_exception_flags(env, old_flags);
}
#define GENERATE_FCMPODF(op, IN, F, cvt_macro) \
uint32_t HELPER(op)(CPUE2KState *env, IN _x, IN _y) \
{ \
int old_flags = save_exception_flags(env); \
uint32_t ret; \
F x = cvt_macro(_x); \
F y = cvt_macro(_y); \
if (glue(F, _is_any_nan)(x) || glue(F, _is_any_nan)(y)) { \
ret = 0x45; \
} else { \
FloatRelation relation = glue(F, _compare_quiet)(x, y, &env->fp_status); \
switch(relation) \
{ \
case float_relation_less: \
ret = 0x01; \
break; \
case float_relation_greater: \
ret = 0x00; \
break; \
case float_relation_equal: \
ret = 0x40; \
break; \
case float_relation_unordered: \
default: \
ret = 0x45; \
break; \
} \
} \
merge_exception_flags(env, old_flags); \
return ret; \
}
GENERATE_FCMPODF(fcmpodsf, uint32_t, float32, make_float32)
GENERATE_FCMPODF(fcmpoddf, uint64_t, float64, make_float64)
GENERATE_FCMPODF(fxcmpodxf, floatx80 *, floatx80, deref)
/* didn't found any difference between these instruction
so keep it that way for now */
uint32_t HELPER(fcmpudsf)(CPUE2KState *env, float32 x, float32 y)
{
return HELPER(fcmpodsf)(env, x, y);
}
uint32_t HELPER(fcmpuddf)(CPUE2KState *env, float64 x, float64 y)
{
return HELPER(fcmpoddf)(env, x, y);
}
uint32_t HELPER(fxcmpudxf)(CPUE2KState *env, floatx80 *x, floatx80 *y)
{
return HELPER(fxcmpodxf)(env, x, y);
}
/* TODO: test if valid, test exception flags */
#if 0
uint32_t HELPER(frcps)(CPUE2KState *env, uint32_t x)
{
int old_flags = save_exception_flags(env);
uint32_t y = float32_div(float32_one, make_float32(x), &env->fp_status);
merge_exception_flags(env, old_flags);
return float32_val(y);
}
uint32_t HELPER(fsqrts)(CPUE2KState *env, uint32_t x)
{
int old_flags = save_exception_flags(env);
uint32_t y = float32_sqrt(make_float32(x), &env->fp_status);
merge_exception_flags(env, old_flags);
return float32_val(y);
}
uint32_t HELPER(frsqrts)(CPUE2KState *env, uint32_t x)
{
int old_flags = save_exception_flags(env);
uint32_t y = float32_div(float32_one,
float32_sqrt(make_float32(x), &env->fp_status),
&env->fp_status);
merge_exception_flags(env, old_flags);
return float32_val(z);
}
#endif

View File

@ -2134,6 +2134,84 @@ static void gen_alopf1_sess(DisasContext *ctx, int chan,
gen_al_result_i32(ctx, chan, dst, tag);
}
static void gen_alopf1_sedd(DisasContext *ctx, int chan,
void (*op)(TCGv_i32, TCGv_env, TCGv_i64, TCGv_i64))
{
Src64 s1 = get_src1_i64(ctx, chan);
Src64 s2 = get_src2_i64(ctx, chan);
TCGv_i32 tag = e2k_get_temp_i32(ctx);
TCGv_i32 dst = e2k_get_temp_i32(ctx);
gen_tag2_i64(tag, s1.tag, s2.tag);
(*op)(dst, cpu_env, s1.value, s2.value);
gen_al_result_i32(ctx, chan, dst, tag);
}
static inline void gen_alopf1_sf80(TCGv_i32 dst, Src80 src1, Src80 src2,
void (*op)(TCGv_i32, TCGv_env, TCGv_ptr, TCGv_ptr))
{
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);
(*op)(dst, cpu_env, t0, t1);
tcg_temp_free_ptr(t1);
tcg_temp_free_ptr(t0);
}
static void gen_alopf1_sexs(DisasContext *ctx, int chan,
void (*op)(TCGv_i32, TCGv_env, TCGv_ptr, TCGv_ptr))
{
Src80 s1 = get_src1_i80(ctx, chan);
Src32 s2 = get_src2_i32(ctx, chan);
TCGv_i32 tag = e2k_get_temp_i32(ctx);
TCGv_i32 dst = e2k_get_temp_i32(ctx);
Src80 t0 = temp_new_src80();
gen_tag2_i64(tag, s1.tag, s2.tag);
gen_fstofx(&t0, s2.value);
gen_alopf1_sf80(dst, s1, t0, op);
gen_al_result_i32(ctx, chan, dst, tag);
temp_free_src80(&t0);
}
static void gen_alopf1_sexd(DisasContext *ctx, int chan,
void (*op)(TCGv_i32, TCGv_env, TCGv_ptr, TCGv_ptr))
{
Src80 s1 = get_src1_i80(ctx, chan);
Src64 s2 = get_src2_i64(ctx, chan);
TCGv_i32 tag = e2k_get_temp_i32(ctx);
TCGv_i32 dst = e2k_get_temp_i32(ctx);
Src80 t0 = temp_new_src80();
gen_tag2_i64(tag, s1.tag, s2.tag);
gen_fdtofx(&t0, s2.value);
gen_alopf1_sf80(dst, s1, t0, op);
gen_al_result_i32(ctx, chan, dst, tag);
temp_free_src80(&t0);
}
static void gen_alopf1_sexx(DisasContext *ctx, int chan,
void (*op)(TCGv_i32, TCGv_env, TCGv_ptr, TCGv_ptr))
{
Src80 s1 = get_src1_i80(ctx, chan);
Src80 s2 = get_src2_i80(ctx, chan);
TCGv_i32 tag = e2k_get_temp_i32(ctx);
TCGv_i32 dst = e2k_get_temp_i32(ctx);
gen_tag2_i64(tag, s1.tag, s2.tag);
gen_alopf1_sf80(dst, s1, s2, op);
gen_al_result_i32(ctx, chan, dst, tag);
}
static void gen_alopf1_dss(DisasContext *ctx, int chan,
void (*op)(TCGv_i64, TCGv_i32, TCGv_i32))
{
@ -3092,16 +3170,16 @@ static void gen_op(DisasContext *ctx, Instr *instr)
case OP_PFCMPNLTD:
case OP_PFCMPNLED:
case OP_PFCMPODD:
case OP_FCMPODSF:
case OP_FCMPUDSF:
case OP_FCMPODDF:
case OP_FCMPUDDF:
case OP_FXCMPODSF:
case OP_FXCMPUDSF:
case OP_FXCMPODDF:
case OP_FXCMPUDDF:
case OP_FXCMPODXF:
case OP_FXCMPUDXF:
case OP_FCMPODSF: gen_alopf1_sess(ctx, chan, gen_helper_fcmpodsf); break;
case OP_FCMPUDSF: gen_alopf1_sess(ctx, chan, gen_helper_fcmpudsf); break;
case OP_FCMPODDF: gen_alopf1_sedd(ctx, chan, gen_helper_fcmpoddf); break;
case OP_FCMPUDDF: gen_alopf1_sedd(ctx, chan, gen_helper_fcmpoddf); break;
case OP_FXCMPODSF: gen_alopf1_sexs(ctx, chan, gen_helper_fxcmpodxf); break;
case OP_FXCMPUDSF: gen_alopf1_sexs(ctx, chan, gen_helper_fxcmpudxf); break;
case OP_FXCMPODDF: gen_alopf1_sexd(ctx, chan, gen_helper_fxcmpodxf); break;
case OP_FXCMPUDDF: gen_alopf1_sexd(ctx, chan, gen_helper_fxcmpudxf); break;
case OP_FXCMPODXF: gen_alopf1_sexx(ctx, chan, gen_helper_fxcmpodxf); break;
case OP_FXCMPUDXF: gen_alopf1_sexx(ctx, chan, gen_helper_fxcmpudxf); break;
case OP_PCMPEQH:
case OP_PCMPEQW:
case OP_PCMPGTB: