target/loongarch: Implement vfcmp
This patch includes: - VFCMP.cond.{S/D}. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Song Gao <gaosong@loongson.cn> Message-Id: <20230504122810.4094787-37-gaosong@loongson.cn>
This commit is contained in:
parent
f435e1e5af
commit
386c4e86d0
@ -1447,3 +1447,97 @@ INSN_LSX(vslti_bu, vv_i)
|
||||
INSN_LSX(vslti_hu, vv_i)
|
||||
INSN_LSX(vslti_wu, vv_i)
|
||||
INSN_LSX(vslti_du, vv_i)
|
||||
|
||||
#define output_vfcmp(C, PREFIX, SUFFIX) \
|
||||
{ \
|
||||
(C)->info->fprintf_func((C)->info->stream, "%08x %s%s\t%d, f%d, f%d", \
|
||||
(C)->insn, PREFIX, SUFFIX, a->vd, \
|
||||
a->vj, a->vk); \
|
||||
}
|
||||
|
||||
static bool output_vvv_fcond(DisasContext *ctx, arg_vvv_fcond * a,
|
||||
const char *suffix)
|
||||
{
|
||||
bool ret = true;
|
||||
switch (a->fcond) {
|
||||
case 0x0:
|
||||
output_vfcmp(ctx, "vfcmp_caf_", suffix);
|
||||
break;
|
||||
case 0x1:
|
||||
output_vfcmp(ctx, "vfcmp_saf_", suffix);
|
||||
break;
|
||||
case 0x2:
|
||||
output_vfcmp(ctx, "vfcmp_clt_", suffix);
|
||||
break;
|
||||
case 0x3:
|
||||
output_vfcmp(ctx, "vfcmp_slt_", suffix);
|
||||
break;
|
||||
case 0x4:
|
||||
output_vfcmp(ctx, "vfcmp_ceq_", suffix);
|
||||
break;
|
||||
case 0x5:
|
||||
output_vfcmp(ctx, "vfcmp_seq_", suffix);
|
||||
break;
|
||||
case 0x6:
|
||||
output_vfcmp(ctx, "vfcmp_cle_", suffix);
|
||||
break;
|
||||
case 0x7:
|
||||
output_vfcmp(ctx, "vfcmp_sle_", suffix);
|
||||
break;
|
||||
case 0x8:
|
||||
output_vfcmp(ctx, "vfcmp_cun_", suffix);
|
||||
break;
|
||||
case 0x9:
|
||||
output_vfcmp(ctx, "vfcmp_sun_", suffix);
|
||||
break;
|
||||
case 0xA:
|
||||
output_vfcmp(ctx, "vfcmp_cult_", suffix);
|
||||
break;
|
||||
case 0xB:
|
||||
output_vfcmp(ctx, "vfcmp_sult_", suffix);
|
||||
break;
|
||||
case 0xC:
|
||||
output_vfcmp(ctx, "vfcmp_cueq_", suffix);
|
||||
break;
|
||||
case 0xD:
|
||||
output_vfcmp(ctx, "vfcmp_sueq_", suffix);
|
||||
break;
|
||||
case 0xE:
|
||||
output_vfcmp(ctx, "vfcmp_cule_", suffix);
|
||||
break;
|
||||
case 0xF:
|
||||
output_vfcmp(ctx, "vfcmp_sule_", suffix);
|
||||
break;
|
||||
case 0x10:
|
||||
output_vfcmp(ctx, "vfcmp_cne_", suffix);
|
||||
break;
|
||||
case 0x11:
|
||||
output_vfcmp(ctx, "vfcmp_sne_", suffix);
|
||||
break;
|
||||
case 0x14:
|
||||
output_vfcmp(ctx, "vfcmp_cor_", suffix);
|
||||
break;
|
||||
case 0x15:
|
||||
output_vfcmp(ctx, "vfcmp_sor_", suffix);
|
||||
break;
|
||||
case 0x18:
|
||||
output_vfcmp(ctx, "vfcmp_cune_", suffix);
|
||||
break;
|
||||
case 0x19:
|
||||
output_vfcmp(ctx, "vfcmp_sune_", suffix);
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define LSX_FCMP_INSN(suffix) \
|
||||
static bool trans_vfcmp_cond_##suffix(DisasContext *ctx, \
|
||||
arg_vvv_fcond * a) \
|
||||
{ \
|
||||
return output_vvv_fcond(ctx, a, #suffix); \
|
||||
}
|
||||
|
||||
LSX_FCMP_INSN(s)
|
||||
LSX_FCMP_INSN(d)
|
||||
|
@ -637,3 +637,8 @@ DEF_HELPER_FLAGS_4(vslti_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(vslti_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(vslti_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(vslti_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
|
||||
DEF_HELPER_5(vfcmp_c_s, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(vfcmp_s_s, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(vfcmp_c_d, void, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_5(vfcmp_s_d, void, env, i32, i32, i32, i32)
|
||||
|
@ -3717,3 +3717,35 @@ TRANS(vslti_bu, do_vslti_u, MO_8)
|
||||
TRANS(vslti_hu, do_vslti_u, MO_16)
|
||||
TRANS(vslti_wu, do_vslti_u, MO_32)
|
||||
TRANS(vslti_du, do_vslti_u, MO_64)
|
||||
|
||||
static bool trans_vfcmp_cond_s(DisasContext *ctx, arg_vvv_fcond *a)
|
||||
{
|
||||
uint32_t flags;
|
||||
void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
|
||||
TCGv_i32 vd = tcg_constant_i32(a->vd);
|
||||
TCGv_i32 vj = tcg_constant_i32(a->vj);
|
||||
TCGv_i32 vk = tcg_constant_i32(a->vk);
|
||||
|
||||
CHECK_SXE;
|
||||
|
||||
fn = (a->fcond & 1 ? gen_helper_vfcmp_s_s : gen_helper_vfcmp_c_s);
|
||||
flags = get_fcmp_flags(a->fcond >> 1);
|
||||
fn(cpu_env, vd, vj, vk, tcg_constant_i32(flags));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_vfcmp_cond_d(DisasContext *ctx, arg_vvv_fcond *a)
|
||||
{
|
||||
uint32_t flags;
|
||||
void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
|
||||
TCGv_i32 vd = tcg_constant_i32(a->vd);
|
||||
TCGv_i32 vj = tcg_constant_i32(a->vj);
|
||||
TCGv_i32 vk = tcg_constant_i32(a->vk);
|
||||
|
||||
fn = (a->fcond & 1 ? gen_helper_vfcmp_s_d : gen_helper_vfcmp_c_d);
|
||||
flags = get_fcmp_flags(a->fcond >> 1);
|
||||
fn(cpu_env, vd, vj, vk, tcg_constant_i32(flags));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -494,6 +494,7 @@ dbcl 0000 00000010 10101 ............... @i15
|
||||
&vvv vd vj vk
|
||||
&vv_i vd vj imm
|
||||
&vvvv vd vj vk va
|
||||
&vvv_fcond vd vj vk fcond
|
||||
|
||||
#
|
||||
# LSX Formats
|
||||
@ -508,6 +509,7 @@ dbcl 0000 00000010 10101 ............... @i15
|
||||
@vv_ui8 .... ........ .. imm:8 vj:5 vd:5 &vv_i
|
||||
@vv_i5 .... ........ ..... imm:s5 vj:5 vd:5 &vv_i
|
||||
@vvvv .... ........ va:5 vk:5 vj:5 vd:5 &vvvv
|
||||
@vvv_fcond .... ........ fcond:5 vk:5 vj:5 vd:5 &vvv_fcond
|
||||
|
||||
vadd_b 0111 00000000 10100 ..... ..... ..... @vvv
|
||||
vadd_h 0111 00000000 10101 ..... ..... ..... @vvv
|
||||
@ -1145,3 +1147,6 @@ vslti_bu 0111 00101000 10000 ..... ..... ..... @vv_ui5
|
||||
vslti_hu 0111 00101000 10001 ..... ..... ..... @vv_ui5
|
||||
vslti_wu 0111 00101000 10010 ..... ..... ..... @vv_ui5
|
||||
vslti_du 0111 00101000 10011 ..... ..... ..... @vv_ui5
|
||||
|
||||
vfcmp_cond_s 0000 11000101 ..... ..... ..... ..... @vvv_fcond
|
||||
vfcmp_cond_d 0000 11000110 ..... ..... ..... ..... @vvv_fcond
|
||||
|
@ -2660,3 +2660,57 @@ VCMPI(vslti_bu, 8, UB, VSLT)
|
||||
VCMPI(vslti_hu, 16, UH, VSLT)
|
||||
VCMPI(vslti_wu, 32, UW, VSLT)
|
||||
VCMPI(vslti_du, 64, UD, VSLT)
|
||||
|
||||
static uint64_t vfcmp_common(CPULoongArchState *env,
|
||||
FloatRelation cmp, uint32_t flags)
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
|
||||
switch (cmp) {
|
||||
case float_relation_less:
|
||||
ret = (flags & FCMP_LT);
|
||||
break;
|
||||
case float_relation_equal:
|
||||
ret = (flags & FCMP_EQ);
|
||||
break;
|
||||
case float_relation_greater:
|
||||
ret = (flags & FCMP_GT);
|
||||
break;
|
||||
case float_relation_unordered:
|
||||
ret = (flags & FCMP_UN);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define VFCMP(NAME, BIT, E, FN) \
|
||||
void HELPER(NAME)(CPULoongArchState *env, \
|
||||
uint32_t vd, uint32_t vj, uint32_t vk, uint32_t flags) \
|
||||
{ \
|
||||
int i; \
|
||||
VReg t; \
|
||||
VReg *Vd = &(env->fpr[vd].vreg); \
|
||||
VReg *Vj = &(env->fpr[vj].vreg); \
|
||||
VReg *Vk = &(env->fpr[vk].vreg); \
|
||||
\
|
||||
vec_clear_cause(env); \
|
||||
for (i = 0; i < LSX_LEN/BIT ; i++) { \
|
||||
FloatRelation cmp; \
|
||||
cmp = FN(Vj->E(i), Vk->E(i), &env->fp_status); \
|
||||
t.E(i) = vfcmp_common(env, cmp, flags); \
|
||||
vec_update_fcsr0(env, GETPC()); \
|
||||
} \
|
||||
*Vd = t; \
|
||||
}
|
||||
|
||||
VFCMP(vfcmp_c_s, 32, UW, float32_compare_quiet)
|
||||
VFCMP(vfcmp_s_s, 32, UW, float32_compare)
|
||||
VFCMP(vfcmp_c_d, 64, UD, float64_compare_quiet)
|
||||
VFCMP(vfcmp_s_d, 64, UD, float64_compare)
|
||||
|
Loading…
Reference in New Issue
Block a user