e2k: add fxcmp{op}{type}b instructions
This commit is contained in:
parent
5bef8e4450
commit
cee5be3c9c
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue