mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-24 13:15:40 +00:00
target/arm: Convert v8.2-fp16 from feature bit to aa64pfr0 test
Backports commit 5763190fa8705863b4b725aa1657661a97113eb4 from qemu
This commit is contained in:
parent
0286f9525d
commit
03ec90f39b
|
@ -1547,7 +1547,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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3151,6 +3150,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.
|
||||||
*/
|
*/
|
||||||
|
@ -3219,6 +3228,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;
|
||||||
|
|
|
@ -265,6 +265,8 @@ static void aarch64_max_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
||||||
|
|
||||||
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. */
|
||||||
|
@ -282,13 +284,12 @@ static void aarch64_max_initfn(struct uc_struct *uc, Object *obj, void *opaque)
|
||||||
cpu->isar.id_isar6 = u;
|
cpu->isar.id_isar6 = u;
|
||||||
|
|
||||||
// Unicorn: we lie and enable them anyway
|
// Unicorn: we lie and enable them anyway
|
||||||
/* We don't set these in system emulation mode for the moment,
|
/*
|
||||||
* since we don't correctly set the ID registers to advertise them,
|
* FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
|
||||||
* and in some cases they're only available in AArch64 and not AArch32,
|
* so do not set MVFR1.FPHP. Strictly speaking this is not legal,
|
||||||
* whereas the architecture requires them to be present in both if
|
* but it is also not legal to enable SVE without support for FP16,
|
||||||
* present in either.
|
* and enabling SVE in system mode is more useful in the short term.
|
||||||
*/
|
*/
|
||||||
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
|
|
||||||
/* 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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10835,7 +10835,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4905,7 +4905,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 */
|
||||||
|
@ -4957,7 +4957,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 */
|
||||||
|
@ -5024,7 +5024,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 */
|
||||||
|
@ -5361,7 +5361,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;
|
||||||
}
|
}
|
||||||
|
@ -5580,7 +5580,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;
|
||||||
}
|
}
|
||||||
|
@ -5742,7 +5742,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;
|
||||||
}
|
}
|
||||||
|
@ -5813,7 +5813,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 */
|
||||||
|
@ -6039,7 +6039,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 */
|
||||||
|
@ -6170,7 +6170,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 */
|
||||||
|
@ -6197,7 +6197,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 */
|
||||||
|
@ -6641,7 +6641,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);
|
||||||
|
@ -7043,7 +7043,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;
|
||||||
}
|
}
|
||||||
|
@ -7211,7 +7211,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 {
|
||||||
|
@ -7862,7 +7862,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;
|
||||||
}
|
}
|
||||||
|
@ -7908,7 +7908,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;
|
||||||
}
|
}
|
||||||
|
@ -8677,7 +8677,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11379,7 +11379,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;
|
||||||
}
|
}
|
||||||
|
@ -11593,7 +11593,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;
|
||||||
|
@ -12479,7 +12479,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;
|
||||||
}
|
}
|
||||||
|
@ -12897,7 +12897,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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7979,7 +7979,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;
|
||||||
|
@ -7988,7 +7988,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;
|
||||||
|
@ -8062,7 +8062,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. */
|
||||||
|
|
Loading…
Reference in a new issue