target-arm: Implement ARMv8 FP VMAXNM and VMINNM instructions.

This adds support for the ARMv8 floating point VMAXNM and VMINNM
instructions.

Signed-off-by: Will Newton <will.newton@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1386158099-9239-6-git-send-email-will.newton@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Will Newton 2013-12-06 17:01:41 +00:00 committed by Peter Maydell
parent e17ab310e9
commit 40cfacdd80
3 changed files with 80 additions and 0 deletions

View File

@ -4085,3 +4085,28 @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
float_status *fpst = fpstp;
return float64_muladd(a, b, c, 0, fpst);
}
/* ARMv8 VMAXNM/VMINNM */
float32 VFP_HELPER(maxnm, s)(float32 a, float32 b, void *fpstp)
{
float_status *fpst = fpstp;
return float32_maxnum(a, b, fpst);
}
float64 VFP_HELPER(maxnm, d)(float64 a, float64 b, void *fpstp)
{
float_status *fpst = fpstp;
return float64_maxnum(a, b, fpst);
}
float32 VFP_HELPER(minnm, s)(float32 a, float32 b, void *fpstp)
{
float_status *fpst = fpstp;
return float32_minnum(a, b, fpst);
}
float64 VFP_HELPER(minnm, d)(float64 a, float64 b, void *fpstp)
{
float_status *fpst = fpstp;
return float64_minnum(a, b, fpst);
}

View File

@ -132,6 +132,11 @@ DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
DEF_HELPER_3(vfp_maxnmd, f64, f64, f64, ptr)
DEF_HELPER_3(vfp_maxnms, f32, f32, f32, ptr)
DEF_HELPER_3(vfp_minnmd, f64, f64, f64, ptr)
DEF_HELPER_3(vfp_minnms, f32, f32, f32, ptr)
DEF_HELPER_3(recps_f32, f32, f32, f32, env)
DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
DEF_HELPER_2(recpe_f32, f32, f32, env)

View File

@ -2723,6 +2723,54 @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
return 0;
}
static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
uint32_t rm, uint32_t dp)
{
uint32_t vmin = extract32(insn, 6, 1);
TCGv_ptr fpst = get_fpstatus_ptr(0);
if (dp) {
TCGv_i64 frn, frm, dest;
frn = tcg_temp_new_i64();
frm = tcg_temp_new_i64();
dest = tcg_temp_new_i64();
tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
if (vmin) {
gen_helper_vfp_minnmd(dest, frn, frm, fpst);
} else {
gen_helper_vfp_maxnmd(dest, frn, frm, fpst);
}
tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i64(frn);
tcg_temp_free_i64(frm);
tcg_temp_free_i64(dest);
} else {
TCGv_i32 frn, frm, dest;
frn = tcg_temp_new_i32();
frm = tcg_temp_new_i32();
dest = tcg_temp_new_i32();
tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
if (vmin) {
gen_helper_vfp_minnms(dest, frn, frm, fpst);
} else {
gen_helper_vfp_maxnms(dest, frn, frm, fpst);
}
tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i32(frn);
tcg_temp_free_i32(frm);
tcg_temp_free_i32(dest);
}
tcg_temp_free_ptr(fpst);
return 0;
}
static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
{
uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
@ -2743,6 +2791,8 @@ static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
if ((insn & 0x0f800e50) == 0x0e000a00) {
return handle_vsel(insn, rd, rn, rm, dp);
} else if ((insn & 0x0fb00e10) == 0x0e800a00) {
return handle_vminmaxnm(insn, rd, rn, rm, dp);
}
return 1;
}