提交 5763190f 编写于 作者: R Richard Henderson 提交者: Peter Maydell

target/arm: Convert v8.2-fp16 from feature bit to aa64pfr0 test

Reviewed-by: NPhilippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: NRichard Henderson <richard.henderson@linaro.org>
Message-id: 20181016223115.24100-9-richard.henderson@linaro.org
Reviewed-by: NPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
上级 cd208a1c
...@@ -573,8 +573,6 @@ static uint32_t get_elf_hwcap(void) ...@@ -573,8 +573,6 @@ static uint32_t get_elf_hwcap(void)
hwcaps |= ARM_HWCAP_A64_ASIMD; hwcaps |= ARM_HWCAP_A64_ASIMD;
/* probe for the extra features */ /* probe for the extra features */
#define GET_FEATURE(feat, hwcap) \
do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
#define GET_FEATURE_ID(feat, hwcap) \ #define GET_FEATURE_ID(feat, hwcap) \
do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
...@@ -587,15 +585,13 @@ static uint32_t get_elf_hwcap(void) ...@@ -587,15 +585,13 @@ static uint32_t get_elf_hwcap(void)
GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3); GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3);
GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3); GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3);
GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4); GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4);
GET_FEATURE(ARM_FEATURE_V8_FP16, GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS); GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS);
GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM); GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM);
GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP); GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA); GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE); GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
#undef GET_FEATURE
#undef GET_FEATURE_ID #undef GET_FEATURE_ID
return hwcaps; return hwcaps;
......
...@@ -1603,7 +1603,6 @@ enum arm_features { ...@@ -1603,7 +1603,6 @@ enum arm_features {
ARM_FEATURE_PMU, /* has PMU support */ ARM_FEATURE_PMU, /* has PMU support */
ARM_FEATURE_VBAR, /* has cp15 VBAR */ ARM_FEATURE_VBAR, /* has cp15 VBAR */
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */ ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
ARM_FEATURE_M_MAIN, /* M profile Main Extension */ ARM_FEATURE_M_MAIN, /* M profile Main Extension */
}; };
...@@ -3213,6 +3212,16 @@ static inline bool isar_feature_aa32_dp(const ARMISARegisters *id) ...@@ -3213,6 +3212,16 @@ static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0; return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
} }
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
{
/*
* This is a placeholder for use by VCMA until the rest of
* the ARMv8.2-FP16 extension is implemented for aa32 mode.
* At which point we can properly set and check MVFR1.FPHP.
*/
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
}
/* /*
* 64-bit feature tests via id registers. * 64-bit feature tests via id registers.
*/ */
...@@ -3281,6 +3290,12 @@ static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) ...@@ -3281,6 +3290,12 @@ static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
} }
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
{
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
}
static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
{ {
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
......
...@@ -320,6 +320,8 @@ static void aarch64_max_initfn(Object *obj) ...@@ -320,6 +320,8 @@ static void aarch64_max_initfn(Object *obj)
t = cpu->isar.id_aa64pfr0; t = cpu->isar.id_aa64pfr0;
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
t = FIELD_DP64(t, ID_AA64PFR0, FP, 1);
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);
cpu->isar.id_aa64pfr0 = t; cpu->isar.id_aa64pfr0 = t;
/* Replicate the same data to the 32-bit id registers. */ /* Replicate the same data to the 32-bit id registers. */
...@@ -336,14 +338,14 @@ static void aarch64_max_initfn(Object *obj) ...@@ -336,14 +338,14 @@ static void aarch64_max_initfn(Object *obj)
u = FIELD_DP32(u, ID_ISAR6, DP, 1); u = FIELD_DP32(u, ID_ISAR6, DP, 1);
cpu->isar.id_isar6 = u; cpu->isar.id_isar6 = u;
#ifdef CONFIG_USER_ONLY /*
/* We don't set these in system emulation mode for the moment, * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
* since we don't correctly set the ID registers to advertise them, * so do not set MVFR1.FPHP. Strictly speaking this is not legal,
* and in some cases they're only available in AArch64 and not AArch32, * but it is also not legal to enable SVE without support for FP16,
* whereas the architecture requires them to be present in both if * and enabling SVE in system mode is more useful in the short term.
* present in either.
*/ */
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
#ifdef CONFIG_USER_ONLY
/* For usermode -cpu max we can use a larger and more efficient DCZ /* For usermode -cpu max we can use a larger and more efficient DCZ
* blocksize since we don't have to follow what the hardware does. * blocksize since we don't have to follow what the hardware does.
*/ */
......
...@@ -11612,7 +11612,7 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val) ...@@ -11612,7 +11612,7 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
uint32_t changed; uint32_t changed;
/* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */ /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
if (!arm_feature(env, ARM_FEATURE_V8_FP16)) { if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
val &= ~FPCR_FZ16; val &= ~FPCR_FZ16;
} }
......
...@@ -4811,7 +4811,7 @@ static void disas_fp_compare(DisasContext *s, uint32_t insn) ...@@ -4811,7 +4811,7 @@ static void disas_fp_compare(DisasContext *s, uint32_t insn)
break; break;
case 3: case 3:
size = MO_16; size = MO_16;
if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (dc_isar_feature(aa64_fp16, s)) {
break; break;
} }
/* fallthru */ /* fallthru */
...@@ -4862,7 +4862,7 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn) ...@@ -4862,7 +4862,7 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
break; break;
case 3: case 3:
size = MO_16; size = MO_16;
if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (dc_isar_feature(aa64_fp16, s)) {
break; break;
} }
/* fallthru */ /* fallthru */
...@@ -4928,7 +4928,7 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn) ...@@ -4928,7 +4928,7 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn)
break; break;
case 3: case 3:
sz = MO_16; sz = MO_16;
if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (dc_isar_feature(aa64_fp16, s)) {
break; break;
} }
/* fallthru */ /* fallthru */
...@@ -5261,7 +5261,7 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn) ...@@ -5261,7 +5261,7 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
handle_fp_1src_double(s, opcode, rd, rn); handle_fp_1src_double(s, opcode, rd, rn);
break; break;
case 3: case 3:
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
...@@ -5476,7 +5476,7 @@ static void disas_fp_2src(DisasContext *s, uint32_t insn) ...@@ -5476,7 +5476,7 @@ static void disas_fp_2src(DisasContext *s, uint32_t insn)
handle_fp_2src_double(s, opcode, rd, rn, rm); handle_fp_2src_double(s, opcode, rd, rn, rm);
break; break;
case 3: case 3:
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
...@@ -5634,7 +5634,7 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn) ...@@ -5634,7 +5634,7 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra); handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
break; break;
case 3: case 3:
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
...@@ -5704,7 +5704,7 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn) ...@@ -5704,7 +5704,7 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
break; break;
case 3: case 3:
sz = MO_16; sz = MO_16;
if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (dc_isar_feature(aa64_fp16, s)) {
break; break;
} }
/* fallthru */ /* fallthru */
...@@ -5929,7 +5929,7 @@ static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn) ...@@ -5929,7 +5929,7 @@ static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
case 1: /* float64 */ case 1: /* float64 */
break; break;
case 3: /* float16 */ case 3: /* float16 */
if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (dc_isar_feature(aa64_fp16, s)) {
break; break;
} }
/* fallthru */ /* fallthru */
...@@ -6059,7 +6059,7 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn) ...@@ -6059,7 +6059,7 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
break; break;
case 0x6: /* 16-bit float, 32-bit int */ case 0x6: /* 16-bit float, 32-bit int */
case 0xe: /* 16-bit float, 64-bit int */ case 0xe: /* 16-bit float, 64-bit int */
if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (dc_isar_feature(aa64_fp16, s)) {
break; break;
} }
/* fallthru */ /* fallthru */
...@@ -6086,7 +6086,7 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn) ...@@ -6086,7 +6086,7 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
case 1: /* float64 */ case 1: /* float64 */
break; break;
case 3: /* float16 */ case 3: /* float16 */
if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (dc_isar_feature(aa64_fp16, s)) {
break; break;
} }
/* fallthru */ /* fallthru */
...@@ -6523,7 +6523,7 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn) ...@@ -6523,7 +6523,7 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
*/ */
is_min = extract32(size, 1, 1); is_min = extract32(size, 1, 1);
is_fp = true; is_fp = true;
if (!is_u && arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!is_u && dc_isar_feature(aa64_fp16, s)) {
size = 1; size = 1;
} else if (!is_u || !is_q || extract32(size, 0, 1)) { } else if (!is_u || !is_q || extract32(size, 0, 1)) {
unallocated_encoding(s); unallocated_encoding(s);
...@@ -6919,7 +6919,7 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn) ...@@ -6919,7 +6919,7 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) { if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
/* Check for FMOV (vector, immediate) - half-precision */ /* Check for FMOV (vector, immediate) - half-precision */
if (!(arm_dc_feature(s, ARM_FEATURE_V8_FP16) && o2 && cmode == 0xf)) { if (!(dc_isar_feature(aa64_fp16, s) && o2 && cmode == 0xf)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
...@@ -7086,7 +7086,7 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn) ...@@ -7086,7 +7086,7 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
case 0x2f: /* FMINP */ case 0x2f: /* FMINP */
/* FP op, size[0] is 32 or 64 bit*/ /* FP op, size[0] is 32 or 64 bit*/
if (!u) { if (!u) {
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} else { } else {
...@@ -7731,7 +7731,7 @@ static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar, ...@@ -7731,7 +7731,7 @@ static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
size = MO_32; size = MO_32;
} else if (immh & 2) { } else if (immh & 2) {
size = MO_16; size = MO_16;
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
...@@ -7776,7 +7776,7 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar, ...@@ -7776,7 +7776,7 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
size = MO_32; size = MO_32;
} else if (immh & 0x2) { } else if (immh & 0x2) {
size = MO_16; size = MO_16;
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
...@@ -8540,7 +8540,7 @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s, ...@@ -8540,7 +8540,7 @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
return; return;
} }
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
} }
...@@ -11221,7 +11221,7 @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn) ...@@ -11221,7 +11221,7 @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
TCGv_ptr fpst; TCGv_ptr fpst;
bool pairwise = false; bool pairwise = false;
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
...@@ -11436,7 +11436,7 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn) ...@@ -11436,7 +11436,7 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
case 0x1c: /* FCADD, #90 */ case 0x1c: /* FCADD, #90 */
case 0x1e: /* FCADD, #270 */ case 0x1e: /* FCADD, #270 */
if (size == 0 if (size == 0
|| (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) || (size == 1 && !dc_isar_feature(aa64_fp16, s))
|| (size == 3 && !is_q)) { || (size == 3 && !is_q)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
...@@ -12316,7 +12316,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn) ...@@ -12316,7 +12316,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
bool need_fpst = true; bool need_fpst = true;
int rmode; int rmode;
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
...@@ -12733,7 +12733,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) ...@@ -12733,7 +12733,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
} }
break; break;
} }
if (is_fp16 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (is_fp16 && !dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s); unallocated_encoding(s);
return; return;
} }
......
...@@ -7812,7 +7812,7 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn) ...@@ -7812,7 +7812,7 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
int size = extract32(insn, 20, 1); int size = extract32(insn, 20, 1);
data = extract32(insn, 23, 2); /* rot */ data = extract32(insn, 23, 2); /* rot */
if (!dc_isar_feature(aa32_vcma, s) if (!dc_isar_feature(aa32_vcma, s)
|| (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) { || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
return 1; return 1;
} }
fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah; fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
...@@ -7821,7 +7821,7 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn) ...@@ -7821,7 +7821,7 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
int size = extract32(insn, 20, 1); int size = extract32(insn, 20, 1);
data = extract32(insn, 24, 1); /* rot */ data = extract32(insn, 24, 1); /* rot */
if (!dc_isar_feature(aa32_vcma, s) if (!dc_isar_feature(aa32_vcma, s)
|| (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) { || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
return 1; return 1;
} }
fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh; fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
...@@ -7894,7 +7894,7 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn) ...@@ -7894,7 +7894,7 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
return 1; return 1;
} }
if (size == 0) { if (size == 0) {
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { if (!dc_isar_feature(aa32_fp16_arith, s)) {
return 1; return 1;
} }
/* For fp16, rm is just Vm, and index is M. */ /* For fp16, rm is just Vm, and index is M. */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册