e2k: add fcmp{op} instructions that write into normal register

This commit is contained in:
Alibek Omarov 2021-01-03 05:08:40 +03:00 committed by Denis Drakhnia
parent 1c16338c6d
commit 3607137905
2 changed files with 87 additions and 123 deletions

View File

@ -86,18 +86,18 @@ void e2k_update_fp_status(CPUE2KState *env)
merge_exception_flags(env, old_flags); \ merge_exception_flags(env, old_flags); \
return float##size##_val(z); \ return float##size##_val(z); \
} }
#define GENERATE_SIMPLE_FLOAT2_OPS_32_64(name, function) \ #define GENERATE_SIMPLE_FLOAT2_OPS_32_64(name, function) \
GENERATE_SIMPLE_FLOAT2_OP(glue(name, s), function, 32) \ GENERATE_SIMPLE_FLOAT2_OP(glue(name, s), function, 32) \
GENERATE_SIMPLE_FLOAT2_OP(glue(name, d), function, 64) GENERATE_SIMPLE_FLOAT2_OP(glue(name, d), function, 64)
#define GENERATE_CMP_FLOAT2_OP(ret_type, name, expr, op, in_type, cvt_macro) \ #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) \ ret_type HELPER(name)(CPUE2KState *env, in_type x, in_type y) \
{ \ { \
int old_flags = save_exception_flags(env); \ int old_flags = save_exception_flags(env); \
ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fp_status); \ ret_type z = expr op(cvt_macro(x), cvt_macro(y), &env->fp_status); \
merge_exception_flags(env, old_flags); \ merge_exception_flags(env, old_flags); \
return z; \ return z ? -1 : 0; \
} }
#define GENERATE_CMP_FLOAT2_OPS_32_64_80(name, expr, op) \ #define GENERATE_CMP_FLOAT2_OPS_32_64_80(name, expr, op) \

View File

@ -1138,40 +1138,66 @@ static inline void gen_cmpand_i32(TCGv_i32 ret, int opc, TCGv_i32 src1,
tcg_temp_free_i32(t0); tcg_temp_free_i32(t0);
} }
#define WRAP_FCMP_HELPER_(helper, type) \
static void glue(gen_, helper)(type ret, type src1, type src2) \
{ \
glue(gen_helper_, helper)(ret, cpu_env, src1, src2); \
}
#define WRAP_FCMP_HELPER(op) \
WRAP_FCMP_HELPER_(glue(op, s), TCGv_i32) \
WRAP_FCMP_HELPER_(glue(op, d), TCGv_i64)
WRAP_FCMP_HELPER(fcmpeq)
WRAP_FCMP_HELPER(fcmplt)
WRAP_FCMP_HELPER(fcmple)
WRAP_FCMP_HELPER(fcmpuod)
WRAP_FCMP_HELPER(fcmpneq)
WRAP_FCMP_HELPER(fcmpnlt)
WRAP_FCMP_HELPER(fcmpnle)
WRAP_FCMP_HELPER(fcmpod)
#undef WRAP_FCMP_HELPER
#undef WRAP_FCMP_HELPER_
#define glue4(a, b, c, d) glue(glue(a, b), glue(c, d))
#define GENERATE_FCMP_SWITCH_TABLE(f, opc, b, pre, suf, post) \
switch((opc)) { \
case b + 0: /* eq */ \
f = glue4(pre, suf, cmpeq, post); \
break; \
case b + 1: /* lt */ \
f = glue4(pre, suf, cmplt, post); \
break; \
case b + 2: /* le */ \
f = glue4(pre, suf, cmple, post); \
break; \
case b + 3: /* uod */ \
f = glue4(pre, suf, cmpuod, post); \
break; \
case b + 4: /* neq */ \
f = glue4(pre, suf, cmpneq, post); \
break; \
case b + 5: /* nlt */ \
f = glue4(pre, suf, cmpnlt, post); \
break; \
case b + 6: /* nle */ \
f = glue4(pre, suf, cmpnle, post); \
break; \
case b + 7: /* od */ \
f = glue4(pre, suf, cmpod, post); \
break; \
default: \
e2k_gen_exception(E2K_EXCP_ILLOPC); \
break; \
}
static void gen_fcmp_i32(TCGv_i32 ret, int opc, TCGv_i32 src1, TCGv_i32 src2) static void gen_fcmp_i32(TCGv_i32 ret, int opc, TCGv_i32 src1, TCGv_i32 src2)
{ {
void (*f)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32) = 0; void (*f)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32) = 0;
TCGv_i32 dst = tcg_temp_new_i32(); TCGv_i32 dst = tcg_temp_new_i32();
switch(opc) { GENERATE_FCMP_SWITCH_TABLE(f, opc, 0, gen_helper_, f, s)
case 0: /* eq */
f = gen_helper_fcmpeqs;
break;
case 1: /* lt */
f = gen_helper_fcmplts;
break;
case 2: /* le */
f = gen_helper_fcmples;
break;
case 3: /* uod */
f = gen_helper_fcmpuods;
break;
case 4: /* neq */
f = gen_helper_fcmpneqs;
break;
case 5: /* nlt */
f = gen_helper_fcmpnlts;
break;
case 6: /* nle */
f = gen_helper_fcmpnles;
break;
case 7: /* od */
f = gen_helper_fcmpods;
break;
default:
e2k_gen_exception(E2K_EXCP_ILLOPC);
break;
}
(*f)(dst, cpu_env, src1, src2); (*f)(dst, cpu_env, src1, src2);
tcg_gen_setcondi_i32(TCG_COND_NE, ret, dst, 0); tcg_gen_setcondi_i32(TCG_COND_NE, ret, dst, 0);
@ -1184,35 +1210,7 @@ static void gen_fcmp_i64(TCGv_i64 ret, int opc, TCGv_i64 src1, TCGv_i64 src2)
void (*f)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64) = 0; void (*f)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64) = 0;
TCGv_i64 dst = tcg_temp_new_i64(); TCGv_i64 dst = tcg_temp_new_i64();
switch(opc) { GENERATE_FCMP_SWITCH_TABLE(f, opc, 0, gen_helper_, f, d)
case 0: /* eq */
f = gen_helper_fcmpeqd;
break;
case 1: /* lt */
f = gen_helper_fcmpltd;
break;
case 2: /* le */
f = gen_helper_fcmpled;
break;
case 3: /* uod */
f = gen_helper_fcmpuodd;
break;
case 4: /* neq */
f = gen_helper_fcmpneqd;
break;
case 5: /* nlt */
f = gen_helper_fcmpnltd;
break;
case 6: /* nle */
f = gen_helper_fcmpnled;
break;
case 7: /* od */
f = gen_helper_fcmpodd;
break;
default:
e2k_gen_exception(E2K_EXCP_ILLOPC);
break;
}
(*f)(dst, cpu_env, src1, src2); (*f)(dst, cpu_env, src1, src2);
tcg_gen_setcondi_i64(TCG_COND_NE, ret, dst, 0); tcg_gen_setcondi_i64(TCG_COND_NE, ret, dst, 0);
@ -1233,38 +1231,10 @@ static void gen_fcmp_f80(TCGv_i64 ret, int opc, Src80 src1, Src80 src2)
gen_temp_reg_write_i64_i32(src1.lo, src1.hi, t0); gen_temp_reg_write_i64_i32(src1.lo, src1.hi, t0);
gen_temp_reg_write_i64_i32(src2.lo, src2.hi, t1); gen_temp_reg_write_i64_i32(src2.lo, src2.hi, t1);
switch(opc) { GENERATE_FCMP_SWITCH_TABLE(f, opc, 0, gen_helper_, fx, x)
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); (*f)(dst, cpu_env, t0, t1);
tcg_gen_setcondi_i64(TCG_COND_NE, ret, dst, 0); tcg_gen_setcondi_i64(TCG_COND_NE, ret, dst, 0);
tcg_temp_free_ptr(t1); tcg_temp_free_ptr(t1);
@ -2387,38 +2357,6 @@ static void gen_alopf21_i32(DisasContext *ctx, Instr *instr,
gen_al_result_i32(ctx, instr->chan, dst, tag); gen_al_result_i32(ctx, instr->chan, dst, tag);
} }
static void gen_alopf21_comb_i64_env(DisasContext *ctx, Instr *instr,
void (*op1)(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64),
void (*op2)(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64))
{
Src64 s1 = get_src1_i64(ctx, instr->chan);
Src64 s2 = get_src2_i64(ctx, instr->chan);
Src64 s3 = get_src3_i64(ctx, instr->chan);
TCGv_i32 tag = e2k_get_temp_i32(ctx);
TCGv_i64 dst = e2k_get_temp_i64(ctx);
gen_tag3_i64(tag, s1.tag, s2.tag, s3.tag);
(*op1)(dst, cpu_env, s1.value, s2.value);
(*op2)(dst, cpu_env, dst, s3.value);
gen_al_result_i64(ctx, instr->chan, dst, tag);
}
static void gen_alopf21_comb_i32_env(DisasContext *ctx, Instr *instr,
void (*op1)(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32),
void (*op2)(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32))
{
Src32 s1 = get_src1_i32(ctx, instr->chan);
Src32 s2 = get_src2_i32(ctx, instr->chan);
Src32 s3 = get_src3_i32(ctx, instr->chan);
TCGv_i32 tag = e2k_get_temp_i32(ctx);
TCGv_i32 dst = e2k_get_temp_i32(ctx);
gen_tag3_i32(tag, s1.tag, s2.tag, s3.tag);
(*op1)(dst, cpu_env, s1.value, s2.value);
(*op2)(dst, cpu_env, dst, s3.value);
gen_al_result_i32(ctx, instr->chan, dst, tag);
}
static void gen_alopf2_i32(DisasContext *ctx, int chan, void (*op)(TCGv_i32, TCGv_i32)) static void gen_alopf2_i32(DisasContext *ctx, int chan, void (*op)(TCGv_i32, TCGv_i32))
{ {
Src32 s2 = get_src2_i32(ctx, chan); Src32 s2 = get_src2_i32(ctx, chan);
@ -3399,6 +3337,32 @@ static void gen_ext(DisasContext *ctx, Instr *instr)
return; return;
} }
break; break;
case 0x2c:
if (is_chan_0134(chan)) {
/* fcmp{op}s */
void (*f)(TCGv_i32, TCGv_i32, TCGv_i32) = 0;
GENERATE_FCMP_SWITCH_TABLE(f, instr->opce3, 0xc0, gen_, f, s);
if(f) {
gen_alopf1_i32(ctx, chan, f);
return;
}
}
break;
case 0x2d:
if (is_chan_0134(chan)) {
/* fcmp{op}d */
void (*f)(TCGv_i64, TCGv_i64, TCGv_i64) = 0;
GENERATE_FCMP_SWITCH_TABLE(f, instr->opce3, 0xc0, gen_, f, d);
if(f) {
gen_alopf1_i64(ctx, chan, f);
return;
}
}
break;
case 0x3c: case 0x3c:
if (chan == 0) { if (chan == 0) {
/* rws */ /* rws */