e2k: add fxcmp{op}{type}b instructions

This commit is contained in:
Alibek Omarov 2020-12-21 19:10:14 +03:00 committed by Denis Drakhnia
parent 5bef8e4450
commit cee5be3c9c
3 changed files with 157 additions and 31 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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 */