target/arm: Implement ARMv8.5-FRINT

Backports 6bea25631af92531027d3bf3ef972a4d51d62e7c from qemu.
This commit is contained in:
Richard Henderson 2019-03-05 23:17:29 -05:00 committed by Lioncash
parent f855ac073d
commit f116560d2c
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
19 changed files with 228 additions and 3 deletions

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_aarch64
#define helper_exit_atomic helper_exit_atomic_aarch64
#define helper_fcos helper_fcos_aarch64
#define helper_frint32_d helper_frint32_d_aarch64
#define helper_frint32_s helper_frint32_s_aarch64
#define helper_frint64_d helper_frint64_d_aarch64
#define helper_frint64_s helper_frint64_s_aarch64
#define helper_fscale helper_fscale_aarch64
#define helper_fsincos helper_fsincos_aarch64
#define helper_fsin helper_fsin_aarch64

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_aarch64eb
#define helper_exit_atomic helper_exit_atomic_aarch64eb
#define helper_fcos helper_fcos_aarch64eb
#define helper_frint32_d helper_frint32_d_aarch64eb
#define helper_frint32_s helper_frint32_s_aarch64eb
#define helper_frint64_d helper_frint64_d_aarch64eb
#define helper_frint64_s helper_frint64_s_aarch64eb
#define helper_fscale helper_fscale_aarch64eb
#define helper_fsincos helper_fsincos_aarch64eb
#define helper_fsin helper_fsin_aarch64eb

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_arm
#define helper_exit_atomic helper_exit_atomic_arm
#define helper_fcos helper_fcos_arm
#define helper_frint32_d helper_frint32_d_arm
#define helper_frint32_s helper_frint32_s_arm
#define helper_frint64_d helper_frint64_d_arm
#define helper_frint64_s helper_frint64_s_arm
#define helper_fscale helper_fscale_arm
#define helper_fsincos helper_fsincos_arm
#define helper_fsin helper_fsin_arm

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_armeb
#define helper_exit_atomic helper_exit_atomic_armeb
#define helper_fcos helper_fcos_armeb
#define helper_frint32_d helper_frint32_d_armeb
#define helper_frint32_s helper_frint32_s_armeb
#define helper_frint64_d helper_frint64_d_armeb
#define helper_frint64_s helper_frint64_s_armeb
#define helper_fscale helper_fscale_armeb
#define helper_fsincos helper_fsincos_armeb
#define helper_fsin helper_fsin_armeb

View file

@ -1113,6 +1113,10 @@ symbols = (
'helper_exception_with_syndrome',
'helper_exit_atomic',
'helper_fcos',
'helper_frint32_d',
'helper_frint32_s',
'helper_frint64_d',
'helper_frint64_s',
'helper_fscale',
'helper_fsincos',
'helper_fsin',

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_m68k
#define helper_exit_atomic helper_exit_atomic_m68k
#define helper_fcos helper_fcos_m68k
#define helper_frint32_d helper_frint32_d_m68k
#define helper_frint32_s helper_frint32_s_m68k
#define helper_frint64_d helper_frint64_d_m68k
#define helper_frint64_s helper_frint64_s_m68k
#define helper_fscale helper_fscale_m68k
#define helper_fsincos helper_fsincos_m68k
#define helper_fsin helper_fsin_m68k

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_mips
#define helper_exit_atomic helper_exit_atomic_mips
#define helper_fcos helper_fcos_mips
#define helper_frint32_d helper_frint32_d_mips
#define helper_frint32_s helper_frint32_s_mips
#define helper_frint64_d helper_frint64_d_mips
#define helper_frint64_s helper_frint64_s_mips
#define helper_fscale helper_fscale_mips
#define helper_fsincos helper_fsincos_mips
#define helper_fsin helper_fsin_mips

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_mips64
#define helper_exit_atomic helper_exit_atomic_mips64
#define helper_fcos helper_fcos_mips64
#define helper_frint32_d helper_frint32_d_mips64
#define helper_frint32_s helper_frint32_s_mips64
#define helper_frint64_d helper_frint64_d_mips64
#define helper_frint64_s helper_frint64_s_mips64
#define helper_fscale helper_fscale_mips64
#define helper_fsincos helper_fsincos_mips64
#define helper_fsin helper_fsin_mips64

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_mips64el
#define helper_exit_atomic helper_exit_atomic_mips64el
#define helper_fcos helper_fcos_mips64el
#define helper_frint32_d helper_frint32_d_mips64el
#define helper_frint32_s helper_frint32_s_mips64el
#define helper_frint64_d helper_frint64_d_mips64el
#define helper_frint64_s helper_frint64_s_mips64el
#define helper_fscale helper_fscale_mips64el
#define helper_fsincos helper_fsincos_mips64el
#define helper_fsin helper_fsin_mips64el

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_mipsel
#define helper_exit_atomic helper_exit_atomic_mipsel
#define helper_fcos helper_fcos_mipsel
#define helper_frint32_d helper_frint32_d_mipsel
#define helper_frint32_s helper_frint32_s_mipsel
#define helper_frint64_d helper_frint64_d_mipsel
#define helper_frint64_s helper_frint64_s_mipsel
#define helper_fscale helper_fscale_mipsel
#define helper_fsincos helper_fsincos_mipsel
#define helper_fsin helper_fsin_mipsel

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_powerpc
#define helper_exit_atomic helper_exit_atomic_powerpc
#define helper_fcos helper_fcos_powerpc
#define helper_frint32_d helper_frint32_d_powerpc
#define helper_frint32_s helper_frint32_s_powerpc
#define helper_frint64_d helper_frint64_d_powerpc
#define helper_frint64_s helper_frint64_s_powerpc
#define helper_fscale helper_fscale_powerpc
#define helper_fsincos helper_fsincos_powerpc
#define helper_fsin helper_fsin_powerpc

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_sparc
#define helper_exit_atomic helper_exit_atomic_sparc
#define helper_fcos helper_fcos_sparc
#define helper_frint32_d helper_frint32_d_sparc
#define helper_frint32_s helper_frint32_s_sparc
#define helper_frint64_d helper_frint64_d_sparc
#define helper_frint64_s helper_frint64_s_sparc
#define helper_fscale helper_fscale_sparc
#define helper_fsincos helper_fsincos_sparc
#define helper_fsin helper_fsin_sparc

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_sparc64
#define helper_exit_atomic helper_exit_atomic_sparc64
#define helper_fcos helper_fcos_sparc64
#define helper_frint32_d helper_frint32_d_sparc64
#define helper_frint32_s helper_frint32_s_sparc64
#define helper_frint64_d helper_frint64_d_sparc64
#define helper_frint64_s helper_frint64_s_sparc64
#define helper_fscale helper_fscale_sparc64
#define helper_fsincos helper_fsincos_sparc64
#define helper_fsin helper_fsin_sparc64

View file

@ -3456,6 +3456,11 @@ static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0;
}
static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
}
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
{
/* We always set the AdvSIMD and FP fields identically wrt FP16. */

View file

@ -266,6 +266,7 @@ static void aarch64_max_initfn(struct uc_struct *uc, Object *obj, void *opaque)
t = FIELD_DP64(t, ID_AA64ISAR1, GPI, 0);
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
cpu->isar.id_aa64isar1 = t;
t = cpu->isar.id_aa64pfr0;

View file

@ -685,6 +685,11 @@ DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a32, TCG_CALL_NO_RWG,
DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a64, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_2(frint32_s, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(frint64_s, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(frint32_d, TCG_CALL_NO_RWG, f64, f64, ptr)
DEF_HELPER_FLAGS_2(frint64_d, TCG_CALL_NO_RWG, f64, f64, ptr)
#ifdef TARGET_ARM
#define helper_clz helper_clz_arm
#define gen_helper_clz gen_helper_clz_arm

View file

@ -5839,6 +5839,20 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
case 0xf: /* FRINTI */
gen_fpst = gen_helper_rints;
break;
case 0x10: /* FRINT32Z */
rmode = float_round_to_zero;
gen_fpst = gen_helper_frint32_s;
break;
case 0x11: /* FRINT32X */
gen_fpst = gen_helper_frint32_s;
break;
case 0x12: /* FRINT64Z */
rmode = float_round_to_zero;
gen_fpst = gen_helper_frint64_s;
break;
case 0x13: /* FRINT64X */
gen_fpst = gen_helper_frint64_s;
break;
default:
g_assert_not_reached();
}
@ -5903,6 +5917,20 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
case 0xf: /* FRINTI */
gen_fpst = gen_helper_rintd;
break;
case 0x10: /* FRINT32Z */
rmode = float_round_to_zero;
gen_fpst = gen_helper_frint32_d;
break;
case 0x11: /* FRINT32X */
gen_fpst = gen_helper_frint32_d;
break;
case 0x12: /* FRINT64Z */
rmode = float_round_to_zero;
gen_fpst = gen_helper_frint64_d;
break;
case 0x13: /* FRINT64X */
gen_fpst = gen_helper_frint64_d;
break;
default:
g_assert_not_reached();
}
@ -6041,6 +6069,13 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
break;
}
case 0x10: case 0x11: case 0x12: case 0x13: /* FRINT{32,64}{X,Z} */
if (type > 1 || !dc_isar_feature(aa64_frint, s)) {
unallocated_encoding(s);
return;
}
/* fall through */
case 0x0: case 0x1: case 0x2: case 0x3:
case 0x8: case 0x9: case 0xa: case 0xb: case 0xc:
case 0xe: case 0xf:
@ -6050,14 +6085,12 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
if (!fp_access_check(s)) {
return;
}
handle_fp_1src_single(s, opcode, rd, rn);
break;
case 1:
if (!fp_access_check(s)) {
return;
}
handle_fp_1src_double(s, opcode, rd, rn);
break;
case 3:
@ -6069,13 +6102,13 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
if (!fp_access_check(s)) {
return;
}
handle_fp_1src_half(s, opcode, rd, rn);
break;
default:
unallocated_encoding(s);
}
break;
default:
unallocated_encoding(s);
break;
@ -9643,6 +9676,14 @@ static void handle_2misc_64(DisasContext *s, int opcode, bool u,
case 0x59: /* FRINTX */
gen_helper_rintd_exact(tcg_ctx, tcg_rd, tcg_rn, tcg_fpstatus);
break;
case 0x1e: /* FRINT32Z */
case 0x5e: /* FRINT32X */
gen_helper_frint32_d(tcg_ctx, tcg_rd, tcg_rn, tcg_fpstatus);
break;
case 0x1f: /* FRINT64Z */
case 0x5f: /* FRINT64X */
gen_helper_frint64_d(tcg_ctx, tcg_rd, tcg_rn, tcg_fpstatus);
break;
default:
g_assert_not_reached();
}
@ -12462,6 +12503,19 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
}
need_fpstatus = true;
break;
case 0x1e: /* FRINT32Z */
case 0x1f: /* FRINT64Z */
need_rmode = true;
rmode = FPROUNDING_ZERO;
/* fall through */
case 0x5e: /* FRINT32X */
case 0x5f: /* FRINT64X */
need_fpstatus = true;
if ((size == 3 && !is_q) || !dc_isar_feature(aa64_frint, s)) {
unallocated_encoding(s);
return;
}
break;
default:
unallocated_encoding(s);
return;
@ -12627,6 +12681,14 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
case 0x7c: /* URSQRTE */
gen_helper_rsqrte_u32(tcg_ctx, tcg_res, tcg_op, tcg_fpstatus);
break;
case 0x1e: /* FRINT32Z */
case 0x5e: /* FRINT32X */
gen_helper_frint32_s(tcg_ctx, tcg_res, tcg_op, tcg_fpstatus);
break;
case 0x1f: /* FRINT64Z */
case 0x5f: /* FRINT64X */
gen_helper_frint64_s(tcg_ctx, tcg_res, tcg_op, tcg_fpstatus);
break;
default:
g_assert_not_reached();
}

View file

@ -1176,3 +1176,99 @@ uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
return result;
}
/* Round a float32 to an integer that fits in int32_t or int64_t. */
static float32 frint_s(float32 f, float_status *fpst, int intsize)
{
int old_flags = get_float_exception_flags(fpst);
uint32_t exp = extract32(f, 23, 8);
if (unlikely(exp == 0xff)) {
/* NaN or Inf. */
goto overflow;
}
/* Round and re-extract the exponent. */
f = float32_round_to_int(f, fpst);
exp = extract32(f, 23, 8);
/* Validate the range of the result. */
if (exp < 126 + intsize) {
/* abs(F) <= INT{N}_MAX */
return f;
}
if (exp == 126 + intsize) {
uint32_t sign = extract32(f, 31, 1);
uint32_t frac = extract32(f, 0, 23);
if (sign && frac == 0) {
/* F == INT{N}_MIN */
return f;
}
}
overflow:
/*
* Raise Invalid and return INT{N}_MIN as a float. Revert any
* inexact exception float32_round_to_int may have raised.
*/
set_float_exception_flags(old_flags | float_flag_invalid, fpst);
return (0x100u + 126u + intsize) << 23;
}
float32 HELPER(frint32_s)(float32 f, void *fpst)
{
return frint_s(f, fpst, 32);
}
float32 HELPER(frint64_s)(float32 f, void *fpst)
{
return frint_s(f, fpst, 64);
}
/* Round a float64 to an integer that fits in int32_t or int64_t. */
static float64 frint_d(float64 f, float_status *fpst, int intsize)
{
int old_flags = get_float_exception_flags(fpst);
uint32_t exp = extract64(f, 52, 11);
if (unlikely(exp == 0x7ff)) {
/* NaN or Inf. */
goto overflow;
}
/* Round and re-extract the exponent. */
f = float64_round_to_int(f, fpst);
exp = extract64(f, 52, 11);
/* Validate the range of the result. */
if (exp < 1022 + intsize) {
/* abs(F) <= INT{N}_MAX */
return f;
}
if (exp == 1022 + intsize) {
uint64_t sign = extract64(f, 63, 1);
uint64_t frac = extract64(f, 0, 52);
if (sign && frac == 0) {
/* F == INT{N}_MIN */
return f;
}
}
overflow:
/*
* Raise Invalid and return INT{N}_MIN as a float. Revert any
* inexact exception float64_round_to_int may have raised.
*/
set_float_exception_flags(old_flags | float_flag_invalid, fpst);
return (uint64_t)(0x800 + 1022 + intsize) << 52;
}
float64 HELPER(frint32_d)(float64 f, void *fpst)
{
return frint_d(f, fpst, 32);
}
float64 HELPER(frint64_d)(float64 f, void *fpst)
{
return frint_d(f, fpst, 64);
}

View file

@ -1107,6 +1107,10 @@
#define helper_exception_with_syndrome helper_exception_with_syndrome_x86_64
#define helper_exit_atomic helper_exit_atomic_x86_64
#define helper_fcos helper_fcos_x86_64
#define helper_frint32_d helper_frint32_d_x86_64
#define helper_frint32_s helper_frint32_s_x86_64
#define helper_frint64_d helper_frint64_d_x86_64
#define helper_frint64_s helper_frint64_s_x86_64
#define helper_fscale helper_fscale_x86_64
#define helper_fsincos helper_fsincos_x86_64
#define helper_fsin helper_fsin_x86_64