mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-target-arm-20250211' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue: * target/alpha: Don't corrupt error_code with unknown softfloat flags * target/arm: Implement FEAT_AFP and FEAT_RPRES # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmereaQZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3gyLEACglOM4E0j1hRl/JZlWD384 # nZL01Hayp9xwSNn28hkXaajCxkErTWLuCZax1g1fBvt/Yqn+E3oFan8gIybMEVgK # 9ei6/m45fuICSQQhifvYTtYhAMd5uclr0anjRp9gN7FH6aaNPan/ZQYcKYxFq6cp # RDTF5qiHIgTeXAlU+WiioxravL3A/D+jcQMYLEI5L+Vt5nYNM589PSNFWNLQ6W9e # Gtmvp0uzrRSZgWxR3nOvhsn1NS/xXK90Zil+GPBo4jf82QVumqKYMsAcireOlxfk # zTlHXH3PuonGj/ZPLxmiVKYhLb1RglQ9kIs/FHVel18QTz4dJ3DaJp8QXCNHbrKz # 3aUwSiIh5Y/s3Q/X2Qy3jUHQ5tSjayhIhGFbn6zPdZ+2JZbIEu1Czeparddu/Zlq # OR0CMVo2Lj/C6OakEU1/YRTKBKiNBaN1eVHi7gjzTDBdbMMC7ZlNuimpFAbthmSC # szHzkgX8LXHzJqe4vip27yOMFBRPxvst/CXcEoPnjsLEQhLlKjOeFiHuEI+DUvaI # 24AJ5b0FDdSOEcaFkxFD6gxW8E77MiNtBncfxDxTMKHs/4yFGiDihSPnOCANn3Kk # zpQIwl0KJAPTA6Cldck9lY7MsKgGPTUNhEThadZlInbp4Uc6T1bvNDtB9b7osDfy # FeposcM1+GBeuSde0yD6oQ== # =P3wv # -----END PGP SIGNATURE----- # gpg: Signature made Tue 11 Feb 2025 11:24:04 EST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20250211' of https://git.linaro.org/people/pmaydell/qemu-arm: (68 commits) target/arm: Sink fp_status and fpcr access into do_fmlal* target/arm: Read fz16 from env->vfp.fpcr target/arm: Simplify DO_VFP_cmp in vfp_helper.c target/arm: Simplify fp_status indexing in mve_helper.c target/arm: Remove fp_status_a32 target/arm: Remove fp_status_a64 target/arm: Remove fp_status_f16_a32 target/arm: Remove fp_status_f16_a64 target/arm: Remove ah_fp_status target/arm: Remove ah_fp_status_f16 target/arm: Remove standard_fp_status target/arm: Remove standard_fp_status_f16 target/arm: Introduce CPUARMState.vfp.fp_status[] target/arm: Enable FEAT_RPRES for -cpu max target/arm: Implement increased precision FRSQRTE target/arm: Implement increased precision FRECPE target/arm: Plumb FEAT_RPRES frecpe and frsqrte through to new helper target/arm: Enable FEAT_AFP for '-cpu max' target/arm: Handle FPCR.AH in SVE FMLSLB, FMLSLT (vectors) target/arm: Handle FPCR.AH in SVE FMLSL (indexed) ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -20,6 +20,7 @@ the following architecture extensions:
|
||||
- FEAT_AA64EL3 (Support for AArch64 at EL3)
|
||||
- FEAT_AdvSIMD (Advanced SIMD Extension)
|
||||
- FEAT_AES (AESD and AESE instructions)
|
||||
- FEAT_AFP (Alternate floating-point behavior)
|
||||
- FEAT_Armv9_Crypto (Armv9 Cryptographic Extension)
|
||||
- FEAT_ASID16 (16 bit ASID)
|
||||
- FEAT_BBM at level 2 (Translation table break-before-make levels)
|
||||
@@ -117,6 +118,7 @@ the following architecture extensions:
|
||||
- FEAT_RDM (Advanced SIMD rounding double multiply accumulate instructions)
|
||||
- FEAT_RME (Realm Management Extension) (NB: support status in QEMU is experimental)
|
||||
- FEAT_RNG (Random number generator)
|
||||
- FEAT_RPRES (Increased precision of FRECPE and FRSQRTE)
|
||||
- FEAT_S2FWB (Stage 2 forced Write-Back)
|
||||
- FEAT_SB (Speculation Barrier)
|
||||
- FEAT_SEL2 (Secure EL2)
|
||||
|
||||
+106
-21
@@ -204,7 +204,7 @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
|
||||
frac_clear(p);
|
||||
} else {
|
||||
int shift = frac_normalize(p);
|
||||
p->cls = float_class_normal;
|
||||
p->cls = float_class_denormal;
|
||||
p->exp = fmt->frac_shift - fmt->exp_bias
|
||||
- shift + !fmt->m68k_denormal;
|
||||
}
|
||||
@@ -334,7 +334,8 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
|
||||
p->frac_lo &= ~round_mask;
|
||||
}
|
||||
frac_shr(p, frac_shift);
|
||||
} else if (s->flush_to_zero) {
|
||||
} else if (s->flush_to_zero &&
|
||||
s->ftz_detection == float_ftz_before_rounding) {
|
||||
flags |= float_flag_output_denormal_flushed;
|
||||
p->cls = float_class_zero;
|
||||
exp = 0;
|
||||
@@ -381,11 +382,19 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
|
||||
exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) && !fmt->m68k_denormal;
|
||||
frac_shr(p, frac_shift);
|
||||
|
||||
if (is_tiny && (flags & float_flag_inexact)) {
|
||||
flags |= float_flag_underflow;
|
||||
}
|
||||
if (exp == 0 && frac_eqz(p)) {
|
||||
p->cls = float_class_zero;
|
||||
if (is_tiny) {
|
||||
if (s->flush_to_zero) {
|
||||
assert(s->ftz_detection == float_ftz_after_rounding);
|
||||
flags |= float_flag_output_denormal_flushed;
|
||||
p->cls = float_class_zero;
|
||||
exp = 0;
|
||||
frac_clear(p);
|
||||
} else if (flags & float_flag_inexact) {
|
||||
flags |= float_flag_underflow;
|
||||
}
|
||||
if (exp == 0 && frac_eqz(p)) {
|
||||
p->cls = float_class_zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
p->exp = exp;
|
||||
@@ -395,7 +404,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
|
||||
static void partsN(uncanon)(FloatPartsN *p, float_status *s,
|
||||
const FloatFmt *fmt)
|
||||
{
|
||||
if (likely(p->cls == float_class_normal)) {
|
||||
if (likely(is_anynorm(p->cls))) {
|
||||
parts_uncanon_normal(p, s, fmt);
|
||||
} else {
|
||||
switch (p->cls) {
|
||||
@@ -433,9 +442,18 @@ static FloatPartsN *partsN(addsub)(FloatPartsN *a, FloatPartsN *b,
|
||||
bool b_sign = b->sign ^ subtract;
|
||||
int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
|
||||
|
||||
/*
|
||||
* For addition and subtraction, we will consume an
|
||||
* input denormal unless the other input is a NaN.
|
||||
*/
|
||||
if ((ab_mask & (float_cmask_denormal | float_cmask_anynan)) ==
|
||||
float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
|
||||
if (a->sign != b_sign) {
|
||||
/* Subtraction */
|
||||
if (likely(ab_mask == float_cmask_normal)) {
|
||||
if (likely(cmask_is_only_normals(ab_mask))) {
|
||||
if (parts_sub_normal(a, b)) {
|
||||
return a;
|
||||
}
|
||||
@@ -468,7 +486,7 @@ static FloatPartsN *partsN(addsub)(FloatPartsN *a, FloatPartsN *b,
|
||||
}
|
||||
} else {
|
||||
/* Addition */
|
||||
if (likely(ab_mask == float_cmask_normal)) {
|
||||
if (likely(cmask_is_only_normals(ab_mask))) {
|
||||
parts_add_normal(a, b);
|
||||
return a;
|
||||
}
|
||||
@@ -488,12 +506,12 @@ static FloatPartsN *partsN(addsub)(FloatPartsN *a, FloatPartsN *b,
|
||||
}
|
||||
|
||||
if (b->cls == float_class_zero) {
|
||||
g_assert(a->cls == float_class_normal);
|
||||
g_assert(is_anynorm(a->cls));
|
||||
return a;
|
||||
}
|
||||
|
||||
g_assert(a->cls == float_class_zero);
|
||||
g_assert(b->cls == float_class_normal);
|
||||
g_assert(is_anynorm(b->cls));
|
||||
return_b:
|
||||
b->sign = b_sign;
|
||||
return b;
|
||||
@@ -513,9 +531,13 @@ static FloatPartsN *partsN(mul)(FloatPartsN *a, FloatPartsN *b,
|
||||
int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
|
||||
bool sign = a->sign ^ b->sign;
|
||||
|
||||
if (likely(ab_mask == float_cmask_normal)) {
|
||||
if (likely(cmask_is_only_normals(ab_mask))) {
|
||||
FloatPartsW tmp;
|
||||
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
|
||||
frac_mulw(&tmp, a, b);
|
||||
frac_truncjam(a, &tmp);
|
||||
|
||||
@@ -541,6 +563,10 @@ static FloatPartsN *partsN(mul)(FloatPartsN *a, FloatPartsN *b,
|
||||
}
|
||||
|
||||
/* Multiply by 0 or Inf */
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
|
||||
if (ab_mask & float_cmask_inf) {
|
||||
a->cls = float_class_inf;
|
||||
a->sign = sign;
|
||||
@@ -596,7 +622,7 @@ static FloatPartsN *partsN(muladd_scalbn)(FloatPartsN *a, FloatPartsN *b,
|
||||
a->sign ^= 1;
|
||||
}
|
||||
|
||||
if (unlikely(ab_mask != float_cmask_normal)) {
|
||||
if (unlikely(!cmask_is_only_normals(ab_mask))) {
|
||||
if (unlikely(ab_mask == float_cmask_infzero)) {
|
||||
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
|
||||
goto d_nan;
|
||||
@@ -611,7 +637,7 @@ static FloatPartsN *partsN(muladd_scalbn)(FloatPartsN *a, FloatPartsN *b,
|
||||
}
|
||||
|
||||
g_assert(ab_mask & float_cmask_zero);
|
||||
if (c->cls == float_class_normal) {
|
||||
if (is_anynorm(c->cls)) {
|
||||
*a = *c;
|
||||
goto return_normal;
|
||||
}
|
||||
@@ -664,6 +690,16 @@ static FloatPartsN *partsN(muladd_scalbn)(FloatPartsN *a, FloatPartsN *b,
|
||||
if (flags & float_muladd_negate_result) {
|
||||
a->sign ^= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* All result types except for "return the default NaN
|
||||
* because this is an Invalid Operation" go through here;
|
||||
* this matches the set of cases where we consumed a
|
||||
* denormal input.
|
||||
*/
|
||||
if (abc_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
return a;
|
||||
|
||||
return_sub_zero:
|
||||
@@ -692,7 +728,10 @@ static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b,
|
||||
int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
|
||||
bool sign = a->sign ^ b->sign;
|
||||
|
||||
if (likely(ab_mask == float_cmask_normal)) {
|
||||
if (likely(cmask_is_only_normals(ab_mask))) {
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
a->sign = sign;
|
||||
a->exp -= b->exp + frac_div(a, b);
|
||||
return a;
|
||||
@@ -713,6 +752,10 @@ static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b,
|
||||
return parts_pick_nan(a, b, s);
|
||||
}
|
||||
|
||||
if ((ab_mask & float_cmask_denormal) && b->cls != float_class_zero) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
|
||||
a->sign = sign;
|
||||
|
||||
/* Inf / X */
|
||||
@@ -750,7 +793,10 @@ static FloatPartsN *partsN(modrem)(FloatPartsN *a, FloatPartsN *b,
|
||||
{
|
||||
int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
|
||||
|
||||
if (likely(ab_mask == float_cmask_normal)) {
|
||||
if (likely(cmask_is_only_normals(ab_mask))) {
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
frac_modrem(a, b, mod_quot);
|
||||
return a;
|
||||
}
|
||||
@@ -771,6 +817,10 @@ static FloatPartsN *partsN(modrem)(FloatPartsN *a, FloatPartsN *b,
|
||||
return a;
|
||||
}
|
||||
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
|
||||
/* N % Inf; 0 % N */
|
||||
g_assert(b->cls == float_class_inf || a->cls == float_class_zero);
|
||||
return a;
|
||||
@@ -800,6 +850,12 @@ static void partsN(sqrt)(FloatPartsN *a, float_status *status,
|
||||
|
||||
if (unlikely(a->cls != float_class_normal)) {
|
||||
switch (a->cls) {
|
||||
case float_class_denormal:
|
||||
if (!a->sign) {
|
||||
/* -ve denormal will be InvalidOperation */
|
||||
float_raise(float_flag_input_denormal_used, status);
|
||||
}
|
||||
break;
|
||||
case float_class_snan:
|
||||
case float_class_qnan:
|
||||
parts_return_nan(a, status);
|
||||
@@ -1130,6 +1186,7 @@ static void partsN(round_to_int)(FloatPartsN *a, FloatRoundMode rmode,
|
||||
case float_class_inf:
|
||||
break;
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
if (parts_round_to_int_normal(a, rmode, scale, fmt->frac_size)) {
|
||||
float_raise(float_flag_inexact, s);
|
||||
}
|
||||
@@ -1174,6 +1231,7 @@ static int64_t partsN(float_to_sint)(FloatPartsN *p, FloatRoundMode rmode,
|
||||
return 0;
|
||||
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
/* TODO: N - 2 is frac_size for rounding; could use input fmt. */
|
||||
if (parts_round_to_int_normal(p, rmode, scale, N - 2)) {
|
||||
flags = float_flag_inexact;
|
||||
@@ -1241,6 +1299,7 @@ static uint64_t partsN(float_to_uint)(FloatPartsN *p, FloatRoundMode rmode,
|
||||
return 0;
|
||||
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
/* TODO: N - 2 is frac_size for rounding; could use input fmt. */
|
||||
if (parts_round_to_int_normal(p, rmode, scale, N - 2)) {
|
||||
flags = float_flag_inexact;
|
||||
@@ -1304,6 +1363,7 @@ static int64_t partsN(float_to_sint_modulo)(FloatPartsN *p,
|
||||
return 0;
|
||||
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
/* TODO: N - 2 is frac_size for rounding; could use input fmt. */
|
||||
if (parts_round_to_int_normal(p, rmode, 0, N - 2)) {
|
||||
flags = float_flag_inexact;
|
||||
@@ -1425,6 +1485,9 @@ static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
|
||||
if ((flags & (minmax_isnum | minmax_isnumber))
|
||||
&& !(ab_mask & float_cmask_snan)
|
||||
&& (ab_mask & ~float_cmask_qnan)) {
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
return is_nan(a->cls) ? b : a;
|
||||
}
|
||||
|
||||
@@ -1449,12 +1512,17 @@ static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
|
||||
return parts_pick_nan(a, b, s);
|
||||
}
|
||||
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
|
||||
a_exp = a->exp;
|
||||
b_exp = b->exp;
|
||||
|
||||
if (unlikely(ab_mask != float_cmask_normal)) {
|
||||
if (unlikely(!cmask_is_only_normals(ab_mask))) {
|
||||
switch (a->cls) {
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
break;
|
||||
case float_class_inf:
|
||||
a_exp = INT16_MAX;
|
||||
@@ -1467,6 +1535,7 @@ static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
|
||||
}
|
||||
switch (b->cls) {
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
break;
|
||||
case float_class_inf:
|
||||
b_exp = INT16_MAX;
|
||||
@@ -1513,9 +1582,13 @@ static FloatRelation partsN(compare)(FloatPartsN *a, FloatPartsN *b,
|
||||
{
|
||||
int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
|
||||
|
||||
if (likely(ab_mask == float_cmask_normal)) {
|
||||
if (likely(cmask_is_only_normals(ab_mask))) {
|
||||
FloatRelation cmp;
|
||||
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
|
||||
if (a->sign != b->sign) {
|
||||
goto a_sign;
|
||||
}
|
||||
@@ -1541,6 +1614,10 @@ static FloatRelation partsN(compare)(FloatPartsN *a, FloatPartsN *b,
|
||||
return float_relation_unordered;
|
||||
}
|
||||
|
||||
if (ab_mask & float_cmask_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
|
||||
if (ab_mask & float_cmask_zero) {
|
||||
if (ab_mask == float_cmask_zero) {
|
||||
return float_relation_equal;
|
||||
@@ -1580,6 +1657,9 @@ static void partsN(scalbn)(FloatPartsN *a, int n, float_status *s)
|
||||
case float_class_zero:
|
||||
case float_class_inf:
|
||||
break;
|
||||
case float_class_denormal:
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
/* fall through */
|
||||
case float_class_normal:
|
||||
a->exp += MIN(MAX(n, -0x10000), 0x10000);
|
||||
break;
|
||||
@@ -1599,6 +1679,12 @@ static void partsN(log2)(FloatPartsN *a, float_status *s, const FloatFmt *fmt)
|
||||
|
||||
if (unlikely(a->cls != float_class_normal)) {
|
||||
switch (a->cls) {
|
||||
case float_class_denormal:
|
||||
if (!a->sign) {
|
||||
/* -ve denormal will be InvalidOperation */
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
break;
|
||||
case float_class_snan:
|
||||
case float_class_qnan:
|
||||
parts_return_nan(a, s);
|
||||
@@ -1615,9 +1701,8 @@ static void partsN(log2)(FloatPartsN *a, float_status *s, const FloatFmt *fmt)
|
||||
}
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
g_assert_not_reached();
|
||||
}
|
||||
g_assert_not_reached();
|
||||
}
|
||||
if (unlikely(a->sign)) {
|
||||
goto d_nan;
|
||||
|
||||
+60
-6
@@ -404,12 +404,16 @@ float64_gen2(float64 xa, float64 xb, float_status *s,
|
||||
/*
|
||||
* Classify a floating point number. Everything above float_class_qnan
|
||||
* is a NaN so cls >= float_class_qnan is any NaN.
|
||||
*
|
||||
* Note that we canonicalize denormals, so most code should treat
|
||||
* class_normal and class_denormal identically.
|
||||
*/
|
||||
|
||||
typedef enum __attribute__ ((__packed__)) {
|
||||
float_class_unclassified,
|
||||
float_class_zero,
|
||||
float_class_normal,
|
||||
float_class_denormal, /* input was a non-squashed denormal */
|
||||
float_class_inf,
|
||||
float_class_qnan, /* all NaNs from here */
|
||||
float_class_snan,
|
||||
@@ -420,12 +424,14 @@ typedef enum __attribute__ ((__packed__)) {
|
||||
enum {
|
||||
float_cmask_zero = float_cmask(float_class_zero),
|
||||
float_cmask_normal = float_cmask(float_class_normal),
|
||||
float_cmask_denormal = float_cmask(float_class_denormal),
|
||||
float_cmask_inf = float_cmask(float_class_inf),
|
||||
float_cmask_qnan = float_cmask(float_class_qnan),
|
||||
float_cmask_snan = float_cmask(float_class_snan),
|
||||
|
||||
float_cmask_infzero = float_cmask_zero | float_cmask_inf,
|
||||
float_cmask_anynan = float_cmask_qnan | float_cmask_snan,
|
||||
float_cmask_anynorm = float_cmask_normal | float_cmask_denormal,
|
||||
};
|
||||
|
||||
/* Flags for parts_minmax. */
|
||||
@@ -459,6 +465,20 @@ static inline __attribute__((unused)) bool is_qnan(FloatClass c)
|
||||
return c == float_class_qnan;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the float_cmask has only normals in it
|
||||
* (including input denormals that were canonicalized)
|
||||
*/
|
||||
static inline bool cmask_is_only_normals(int cmask)
|
||||
{
|
||||
return !(cmask & ~float_cmask_anynorm);
|
||||
}
|
||||
|
||||
static inline bool is_anynorm(FloatClass c)
|
||||
{
|
||||
return float_cmask(c) & float_cmask_anynorm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure holding all of the decomposed parts of a float.
|
||||
* The exponent is unbiased and the fraction is normalized.
|
||||
@@ -1729,6 +1749,7 @@ static float64 float64r32_round_pack_canonical(FloatParts64 *p,
|
||||
*/
|
||||
switch (p->cls) {
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
if (unlikely(p->exp == 0)) {
|
||||
/*
|
||||
* The result is denormal for float32, but can be represented
|
||||
@@ -1817,6 +1838,7 @@ static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
|
||||
|
||||
switch (p->cls) {
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
if (s->floatx80_rounding_precision == floatx80_precision_x) {
|
||||
parts_uncanon_normal(p, s, fmt);
|
||||
frac = p->frac_hi;
|
||||
@@ -2696,6 +2718,9 @@ static void parts_float_to_ahp(FloatParts64 *a, float_status *s)
|
||||
float16_params_ahp.frac_size + 1);
|
||||
break;
|
||||
|
||||
case float_class_denormal:
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
break;
|
||||
case float_class_normal:
|
||||
case float_class_zero:
|
||||
break;
|
||||
@@ -2710,6 +2735,9 @@ static void parts64_float_to_float(FloatParts64 *a, float_status *s)
|
||||
if (is_nan(a->cls)) {
|
||||
parts_return_nan(a, s);
|
||||
}
|
||||
if (a->cls == float_class_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
}
|
||||
|
||||
static void parts128_float_to_float(FloatParts128 *a, float_status *s)
|
||||
@@ -2717,6 +2745,9 @@ static void parts128_float_to_float(FloatParts128 *a, float_status *s)
|
||||
if (is_nan(a->cls)) {
|
||||
parts_return_nan(a, s);
|
||||
}
|
||||
if (a->cls == float_class_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
}
|
||||
|
||||
#define parts_float_to_float(P, S) \
|
||||
@@ -2729,12 +2760,21 @@ static void parts_float_to_float_narrow(FloatParts64 *a, FloatParts128 *b,
|
||||
a->sign = b->sign;
|
||||
a->exp = b->exp;
|
||||
|
||||
if (a->cls == float_class_normal) {
|
||||
switch (a->cls) {
|
||||
case float_class_denormal:
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
/* fall through */
|
||||
case float_class_normal:
|
||||
frac_truncjam(a, b);
|
||||
} else if (is_nan(a->cls)) {
|
||||
break;
|
||||
case float_class_snan:
|
||||
case float_class_qnan:
|
||||
/* Discard the low bits of the NaN. */
|
||||
a->frac = b->frac_hi;
|
||||
parts_return_nan(a, s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2749,6 +2789,9 @@ static void parts_float_to_float_widen(FloatParts128 *a, FloatParts64 *b,
|
||||
if (is_nan(a->cls)) {
|
||||
parts_return_nan(a, s);
|
||||
}
|
||||
if (a->cls == float_class_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
}
|
||||
|
||||
float32 float16_to_float32(float16 a, bool ieee, float_status *s)
|
||||
@@ -3218,6 +3261,7 @@ static Int128 float128_to_int128_scalbn(float128 a, FloatRoundMode rmode,
|
||||
return int128_zero();
|
||||
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
if (parts_round_to_int_normal(&p, rmode, scale, 128 - 2)) {
|
||||
flags = float_flag_inexact;
|
||||
}
|
||||
@@ -3645,6 +3689,7 @@ static Int128 float128_to_uint128_scalbn(float128 a, FloatRoundMode rmode,
|
||||
return int128_zero();
|
||||
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
if (parts_round_to_int_normal(&p, rmode, scale, 128 - 2)) {
|
||||
flags = float_flag_inexact;
|
||||
if (p.cls == float_class_zero) {
|
||||
@@ -4386,7 +4431,11 @@ float32_hs_compare(float32 xa, float32 xb, float_status *s, bool is_quiet)
|
||||
goto soft;
|
||||
}
|
||||
|
||||
float32_input_flush2(&ua.s, &ub.s, s);
|
||||
if (unlikely(float32_is_denormal(ua.s) || float32_is_denormal(ub.s))) {
|
||||
/* We may need to set the input_denormal_used flag */
|
||||
goto soft;
|
||||
}
|
||||
|
||||
if (isgreaterequal(ua.h, ub.h)) {
|
||||
if (isgreater(ua.h, ub.h)) {
|
||||
return float_relation_greater;
|
||||
@@ -4436,7 +4485,11 @@ float64_hs_compare(float64 xa, float64 xb, float_status *s, bool is_quiet)
|
||||
goto soft;
|
||||
}
|
||||
|
||||
float64_input_flush2(&ua.s, &ub.s, s);
|
||||
if (unlikely(float64_is_denormal(ua.s) || float64_is_denormal(ub.s))) {
|
||||
/* We may need to set the input_denormal_used flag */
|
||||
goto soft;
|
||||
}
|
||||
|
||||
if (isgreaterequal(ua.h, ub.h)) {
|
||||
if (isgreater(ua.h, ub.h)) {
|
||||
return float_relation_greater;
|
||||
@@ -5231,6 +5284,8 @@ float32 float32_exp2(float32 a, float_status *status)
|
||||
float32_unpack_canonical(&xp, a, status);
|
||||
if (unlikely(xp.cls != float_class_normal)) {
|
||||
switch (xp.cls) {
|
||||
case float_class_denormal:
|
||||
break;
|
||||
case float_class_snan:
|
||||
case float_class_qnan:
|
||||
parts_return_nan(&xp, status);
|
||||
@@ -5240,9 +5295,8 @@ float32 float32_exp2(float32 a, float_status *status)
|
||||
case float_class_zero:
|
||||
return float32_one;
|
||||
default:
|
||||
break;
|
||||
g_assert_not_reached();
|
||||
}
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
float_raise(float_flag_inexact, status);
|
||||
|
||||
@@ -109,6 +109,12 @@ static inline void set_flush_inputs_to_zero(bool val, float_status *status)
|
||||
status->flush_inputs_to_zero = val;
|
||||
}
|
||||
|
||||
static inline void set_float_ftz_detection(FloatFTZDetection d,
|
||||
float_status *status)
|
||||
{
|
||||
status->ftz_detection = d;
|
||||
}
|
||||
|
||||
static inline void set_default_nan_mode(bool val, float_status *status)
|
||||
{
|
||||
status->default_nan_mode = val;
|
||||
@@ -183,4 +189,9 @@ static inline bool get_default_nan_mode(const float_status *status)
|
||||
return status->default_nan_mode;
|
||||
}
|
||||
|
||||
static inline FloatFTZDetection get_float_ftz_detection(const float_status *status)
|
||||
{
|
||||
return status->ftz_detection;
|
||||
}
|
||||
|
||||
#endif /* SOFTFLOAT_HELPERS_H */
|
||||
|
||||
@@ -165,6 +165,13 @@ enum {
|
||||
float_flag_invalid_sqrt = 0x0800, /* sqrt(-x) */
|
||||
float_flag_invalid_cvti = 0x1000, /* non-nan to integer */
|
||||
float_flag_invalid_snan = 0x2000, /* any operand was snan */
|
||||
/*
|
||||
* An input was denormal and we used it (without flushing it to zero).
|
||||
* Not set if we do not actually use the denormal input (e.g.
|
||||
* because some other input was a NaN, or because the operation
|
||||
* wasn't actually carried out (divide-by-zero; invalid))
|
||||
*/
|
||||
float_flag_input_denormal_used = 0x4000,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -297,6 +304,22 @@ typedef enum __attribute__((__packed__)) {
|
||||
float_infzeronan_suppress_invalid = (1 << 7),
|
||||
} FloatInfZeroNaNRule;
|
||||
|
||||
/*
|
||||
* When flush_to_zero is set, should we detect denormal results to
|
||||
* be flushed before or after rounding? For most architectures this
|
||||
* should be set to match the tininess_before_rounding setting,
|
||||
* but a few architectures, e.g. MIPS MSA, detect FTZ before
|
||||
* rounding but tininess after rounding.
|
||||
*
|
||||
* This enum is arranged so that the default if the target doesn't
|
||||
* configure it matches the default for tininess_before_rounding
|
||||
* (i.e. "after rounding").
|
||||
*/
|
||||
typedef enum __attribute__((__packed__)) {
|
||||
float_ftz_after_rounding = 0,
|
||||
float_ftz_before_rounding = 1,
|
||||
} FloatFTZDetection;
|
||||
|
||||
/*
|
||||
* Floating Point Status. Individual architectures may maintain
|
||||
* several versions of float_status for different functions. The
|
||||
@@ -314,6 +337,8 @@ typedef struct float_status {
|
||||
bool tininess_before_rounding;
|
||||
/* should denormalised results go to zero and set output_denormal_flushed? */
|
||||
bool flush_to_zero;
|
||||
/* do we detect and flush denormal results before or after rounding? */
|
||||
FloatFTZDetection ftz_detection;
|
||||
/* should denormalised inputs go to zero and set input_denormal_flushed? */
|
||||
bool flush_inputs_to_zero;
|
||||
bool default_nan_mode;
|
||||
|
||||
@@ -202,6 +202,13 @@ static void alpha_cpu_initfn(Object *obj)
|
||||
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
|
||||
/* Default NaN: sign bit clear, msb frac bit set */
|
||||
set_float_default_nan_pattern(0b01000000, &env->fp_status);
|
||||
/*
|
||||
* TODO: this is incorrect. The Alpha Architecture Handbook version 4
|
||||
* section 4.7.7.11 says that we flush to zero for underflow cases, so
|
||||
* this should be float_ftz_after_rounding to match the
|
||||
* tininess_after_rounding (which is specified in section 4.7.5).
|
||||
*/
|
||||
set_float_ftz_detection(float_ftz_before_rounding, &env->fp_status);
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
|
||||
cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
|
||||
|
||||
@@ -476,6 +476,8 @@ static uint64_t do_cvttq(CPUAlphaState *env, uint64_t a, int roundmode)
|
||||
exc = FPCR_INV;
|
||||
} else if (exc & float_flag_inexact) {
|
||||
exc = FPCR_INE;
|
||||
} else {
|
||||
exc = 0;
|
||||
}
|
||||
}
|
||||
env->error_code = exc;
|
||||
|
||||
@@ -597,6 +597,11 @@ static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS);
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_rpres(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, RPRES);
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
|
||||
{
|
||||
/* We always set the AdvSIMD and FP fields identically. */
|
||||
@@ -802,6 +807,11 @@ static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_afp(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, AFP) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0;
|
||||
|
||||
+14
-32
@@ -169,28 +169,6 @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
|
||||
QLIST_INSERT_HEAD(&cpu->el_change_hooks, entry, node);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the float_status behaviour to match the Arm defaults:
|
||||
* * tininess-before-rounding
|
||||
* * 2-input NaN propagation prefers SNaN over QNaN, and then
|
||||
* operand A over operand B (see FPProcessNaNs() pseudocode)
|
||||
* * 3-input NaN propagation prefers SNaN over QNaN, and then
|
||||
* operand C over A over B (see FPProcessNaNs3() pseudocode,
|
||||
* but note that for QEMU muladd is a * b + c, whereas for
|
||||
* the pseudocode function the arguments are in the order c, a, b.
|
||||
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
|
||||
* and the input NaN if it is signalling
|
||||
* * Default NaN has sign bit clear, msb frac bit set
|
||||
*/
|
||||
static void arm_set_default_fp_behaviours(float_status *s)
|
||||
{
|
||||
set_float_detect_tininess(float_tininess_before_rounding, s);
|
||||
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
|
||||
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
|
||||
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
|
||||
set_float_default_nan_pattern(0b01000000, s);
|
||||
}
|
||||
|
||||
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
|
||||
{
|
||||
/* Reset a single ARMCPRegInfo register */
|
||||
@@ -568,16 +546,20 @@ static void arm_cpu_reset_hold(Object *obj, ResetType type)
|
||||
env->sau.ctrl = 0;
|
||||
}
|
||||
|
||||
set_flush_to_zero(1, &env->vfp.standard_fp_status);
|
||||
set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
|
||||
set_default_nan_mode(1, &env->vfp.standard_fp_status);
|
||||
set_default_nan_mode(1, &env->vfp.standard_fp_status_f16);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status_a32);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status_a64);
|
||||
arm_set_default_fp_behaviours(&env->vfp.standard_fp_status);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status_f16_a32);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status_f16_a64);
|
||||
arm_set_default_fp_behaviours(&env->vfp.standard_fp_status_f16);
|
||||
set_flush_to_zero(1, &env->vfp.fp_status[FPST_STD]);
|
||||
set_flush_inputs_to_zero(1, &env->vfp.fp_status[FPST_STD]);
|
||||
set_default_nan_mode(1, &env->vfp.fp_status[FPST_STD]);
|
||||
set_default_nan_mode(1, &env->vfp.fp_status[FPST_STD_F16]);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A32]);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_STD]);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A32_F16]);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
|
||||
arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_STD_F16]);
|
||||
arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_AH]);
|
||||
set_flush_to_zero(1, &env->vfp.fp_status[FPST_AH]);
|
||||
set_flush_inputs_to_zero(1, &env->vfp.fp_status[FPST_AH]);
|
||||
arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_AH_F16]);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (kvm_enabled()) {
|
||||
|
||||
+62
-35
@@ -202,6 +202,61 @@ typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
|
||||
|
||||
typedef struct NVICState NVICState;
|
||||
|
||||
/*
|
||||
* Enum for indexing vfp.fp_status[].
|
||||
*
|
||||
* FPST_A32: is the "normal" fp status for AArch32 insns
|
||||
* FPST_A64: is the "normal" fp status for AArch64 insns
|
||||
* FPST_A32_F16: used for AArch32 half-precision calculations
|
||||
* FPST_A64_F16: used for AArch64 half-precision calculations
|
||||
* FPST_STD: the ARM "Standard FPSCR Value"
|
||||
* FPST_STD_F16: used for half-precision
|
||||
* calculations with the ARM "Standard FPSCR Value"
|
||||
* FPST_AH: used for the A64 insns which change behaviour
|
||||
* when FPCR.AH == 1 (bfloat16 conversions and multiplies,
|
||||
* and the reciprocal and square root estimate/step insns)
|
||||
* FPST_AH_F16: used for the A64 insns which change behaviour
|
||||
* when FPCR.AH == 1 (bfloat16 conversions and multiplies,
|
||||
* and the reciprocal and square root estimate/step insns);
|
||||
* for half-precision
|
||||
*
|
||||
* Half-precision operations are governed by a separate
|
||||
* flush-to-zero control bit in FPSCR:FZ16. We pass a separate
|
||||
* status structure to control this.
|
||||
*
|
||||
* The "Standard FPSCR", ie default-NaN, flush-to-zero,
|
||||
* round-to-nearest and is used by any operations (generally
|
||||
* Neon) which the architecture defines as controlled by the
|
||||
* standard FPSCR value rather than the FPSCR.
|
||||
*
|
||||
* The "standard FPSCR but for fp16 ops" is needed because
|
||||
* the "standard FPSCR" tracks the FPSCR.FZ16 bit rather than
|
||||
* using a fixed value for it.
|
||||
*
|
||||
* FPST_AH is needed because some insns have different
|
||||
* behaviour when FPCR.AH == 1: they don't update cumulative
|
||||
* exception flags, they act like FPCR.{FZ,FIZ} = {1,1} and
|
||||
* they ignore FPCR.RMode. But they don't ignore FPCR.FZ16,
|
||||
* which means we need an FPST_AH_F16 as well.
|
||||
*
|
||||
* To avoid having to transfer exception bits around, we simply
|
||||
* say that the FPSCR cumulative exception flags are the logical
|
||||
* OR of the flags in the four fp statuses. This relies on the
|
||||
* only thing which needs to read the exception flags being
|
||||
* an explicit FPSCR read.
|
||||
*/
|
||||
typedef enum ARMFPStatusFlavour {
|
||||
FPST_A32,
|
||||
FPST_A64,
|
||||
FPST_A32_F16,
|
||||
FPST_A64_F16,
|
||||
FPST_AH,
|
||||
FPST_AH_F16,
|
||||
FPST_STD,
|
||||
FPST_STD_F16,
|
||||
} ARMFPStatusFlavour;
|
||||
#define FPST_COUNT 8
|
||||
|
||||
typedef struct CPUArchState {
|
||||
/* Regs for current mode. */
|
||||
uint32_t regs[16];
|
||||
@@ -631,41 +686,8 @@ typedef struct CPUArchState {
|
||||
/* Scratch space for aa32 neon expansion. */
|
||||
uint32_t scratch[8];
|
||||
|
||||
/* There are a number of distinct float control structures:
|
||||
*
|
||||
* fp_status_a32: is the "normal" fp status for AArch32 insns
|
||||
* fp_status_a64: is the "normal" fp status for AArch64 insns
|
||||
* fp_status_fp16_a32: used for AArch32 half-precision calculations
|
||||
* fp_status_fp16_a64: used for AArch64 half-precision calculations
|
||||
* standard_fp_status : the ARM "Standard FPSCR Value"
|
||||
* standard_fp_status_fp16 : used for half-precision
|
||||
* calculations with the ARM "Standard FPSCR Value"
|
||||
*
|
||||
* Half-precision operations are governed by a separate
|
||||
* flush-to-zero control bit in FPSCR:FZ16. We pass a separate
|
||||
* status structure to control this.
|
||||
*
|
||||
* The "Standard FPSCR", ie default-NaN, flush-to-zero,
|
||||
* round-to-nearest and is used by any operations (generally
|
||||
* Neon) which the architecture defines as controlled by the
|
||||
* standard FPSCR value rather than the FPSCR.
|
||||
*
|
||||
* The "standard FPSCR but for fp16 ops" is needed because
|
||||
* the "standard FPSCR" tracks the FPSCR.FZ16 bit rather than
|
||||
* using a fixed value for it.
|
||||
*
|
||||
* To avoid having to transfer exception bits around, we simply
|
||||
* say that the FPSCR cumulative exception flags are the logical
|
||||
* OR of the flags in the four fp statuses. This relies on the
|
||||
* only thing which needs to read the exception flags being
|
||||
* an explicit FPSCR read.
|
||||
*/
|
||||
float_status fp_status_a32;
|
||||
float_status fp_status_a64;
|
||||
float_status fp_status_f16_a32;
|
||||
float_status fp_status_f16_a64;
|
||||
float_status standard_fp_status;
|
||||
float_status standard_fp_status_f16;
|
||||
/* There are a number of distinct float control structures. */
|
||||
float_status fp_status[FPST_COUNT];
|
||||
|
||||
uint64_t zcr_el[4]; /* ZCR_EL[1-3] */
|
||||
uint64_t smcr_el[4]; /* SMCR_EL[1-3] */
|
||||
@@ -1714,6 +1736,9 @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
|
||||
*/
|
||||
|
||||
/* FPCR bits */
|
||||
#define FPCR_FIZ (1 << 0) /* Flush Inputs to Zero (FEAT_AFP) */
|
||||
#define FPCR_AH (1 << 1) /* Alternate Handling (FEAT_AFP) */
|
||||
#define FPCR_NEP (1 << 2) /* SIMD scalar ops preserve elts (FEAT_AFP) */
|
||||
#define FPCR_IOE (1 << 8) /* Invalid Operation exception trap enable */
|
||||
#define FPCR_DZE (1 << 9) /* Divide by Zero exception trap enable */
|
||||
#define FPCR_OFE (1 << 10) /* Overflow exception trap enable */
|
||||
@@ -3195,6 +3220,8 @@ FIELD(TBFLAG_A64, NV2, 34, 1)
|
||||
FIELD(TBFLAG_A64, NV2_MEM_E20, 35, 1)
|
||||
/* Set if FEAT_NV2 RAM accesses are big-endian */
|
||||
FIELD(TBFLAG_A64, NV2_MEM_BE, 36, 1)
|
||||
FIELD(TBFLAG_A64, AH, 37, 1) /* FPCR.AH */
|
||||
FIELD(TBFLAG_A64, NEP, 38, 1) /* FPCR.NEP */
|
||||
|
||||
/*
|
||||
* Helpers for using the above. Note that only the A64 accessors use
|
||||
|
||||
+1
-1
@@ -4848,7 +4848,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
|
||||
.writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore },
|
||||
{ .name = "FPCR", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
|
||||
.access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END,
|
||||
.access = PL0_RW, .type = ARM_CP_FPU,
|
||||
.readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
|
||||
{ .name = "FPSR", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
|
||||
|
||||
@@ -245,9 +245,11 @@ DEF_HELPER_4(vfp_muladdh, f16, f16, f16, f16, fpst)
|
||||
|
||||
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, fpst)
|
||||
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_2(recpe_rpres_f32, TCG_CALL_NO_RWG, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, fpst)
|
||||
DEF_HELPER_FLAGS_2(rsqrte_f16, TCG_CALL_NO_RWG, f16, f16, fpst)
|
||||
DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_2(rsqrte_rpres_f32, TCG_CALL_NO_RWG, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, fpst)
|
||||
DEF_HELPER_FLAGS_1(recpe_u32, TCG_CALL_NO_RWG, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32)
|
||||
@@ -680,10 +682,12 @@ DEF_HELPER_FLAGS_4(gvec_vrintx_s, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_frecpe_rpres_s, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_frsqrte_h, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_frsqrte_s, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_frsqrte_rpres_s, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_frsqrte_d, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_fcgt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, fpst, i32)
|
||||
@@ -722,6 +726,10 @@ DEF_HELPER_FLAGS_5(gvec_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_fabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_fceq_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_fceq_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_fceq_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
@@ -778,6 +786,10 @@ DEF_HELPER_FLAGS_5(gvec_vfms_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_vfms_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_vfms_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_vfms_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_vfms_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_vfms_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
|
||||
@@ -809,6 +821,20 @@ DEF_HELPER_FLAGS_6(gvec_fmla_idx_s, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_6(gvec_fmla_idx_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(gvec_fmls_idx_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_fmls_idx_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_fmls_idx_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(gvec_ah_fmls_idx_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_ah_fmls_idx_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_ah_fmls_idx_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_uqadd_b, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_uqadd_h, TCG_CALL_NO_RWG,
|
||||
|
||||
@@ -1828,4 +1828,10 @@ uint64_t gt_virt_cnt_offset(CPUARMState *env);
|
||||
* all EL1" scope; this covers stage 1 and stage 2.
|
||||
*/
|
||||
int alle1_tlbmask(CPUARMState *env);
|
||||
|
||||
/* Set the float_status behaviour to match the Arm defaults */
|
||||
void arm_set_default_fp_behaviours(float_status *s);
|
||||
/* Set the float_status behaviour to match Arm FPCR.AH=1 behaviour */
|
||||
void arm_set_ah_fp_behaviours(float_status *s);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1167,6 +1167,7 @@ void aarch64_max_tcg_initfn(Object *obj)
|
||||
cpu->isar.id_aa64isar1 = t;
|
||||
|
||||
t = cpu->isar.id_aa64isar2;
|
||||
t = FIELD_DP64(t, ID_AA64ISAR2, RPRES, 1); /* FEAT_RPRES */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1); /* FEAT_MOPS */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR2, WFXT, 2); /* FEAT_WFxT */
|
||||
@@ -1218,6 +1219,7 @@ void aarch64_max_tcg_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 2); /* FEAT_ETS2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, AFP, 1); /* FEAT_AFP */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1); /* FEAT_TIDCP1 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, CMOW, 1); /* FEAT_CMOW */
|
||||
cpu->isar.id_aa64mmfr1 = t;
|
||||
|
||||
+76
-75
@@ -38,6 +38,7 @@
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#include "user/page-protection.h"
|
||||
#endif
|
||||
#include "vec_internal.h"
|
||||
|
||||
/* C2.4.7 Multiply and divide */
|
||||
/* special cases for 0 and LLONG_MIN are mandated by the standard */
|
||||
@@ -208,88 +209,52 @@ uint64_t HELPER(neon_cgt_f64)(float64 a, float64 b, float_status *fpst)
|
||||
return -float64_lt(b, a, fpst);
|
||||
}
|
||||
|
||||
/* Reciprocal step and sqrt step. Note that unlike the A32/T32
|
||||
/*
|
||||
* Reciprocal step and sqrt step. Note that unlike the A32/T32
|
||||
* versions, these do a fully fused multiply-add or
|
||||
* multiply-add-and-halve.
|
||||
* The FPCR.AH == 1 versions need to avoid flipping the sign of NaN.
|
||||
*/
|
||||
|
||||
uint32_t HELPER(recpsf_f16)(uint32_t a, uint32_t b, float_status *fpst)
|
||||
{
|
||||
a = float16_squash_input_denormal(a, fpst);
|
||||
b = float16_squash_input_denormal(b, fpst);
|
||||
|
||||
a = float16_chs(a);
|
||||
if ((float16_is_infinity(a) && float16_is_zero(b)) ||
|
||||
(float16_is_infinity(b) && float16_is_zero(a))) {
|
||||
return float16_two;
|
||||
#define DO_RECPS(NAME, CTYPE, FLOATTYPE, CHSFN) \
|
||||
CTYPE HELPER(NAME)(CTYPE a, CTYPE b, float_status *fpst) \
|
||||
{ \
|
||||
a = FLOATTYPE ## _squash_input_denormal(a, fpst); \
|
||||
b = FLOATTYPE ## _squash_input_denormal(b, fpst); \
|
||||
a = FLOATTYPE ## _ ## CHSFN(a); \
|
||||
if ((FLOATTYPE ## _is_infinity(a) && FLOATTYPE ## _is_zero(b)) || \
|
||||
(FLOATTYPE ## _is_infinity(b) && FLOATTYPE ## _is_zero(a))) { \
|
||||
return FLOATTYPE ## _two; \
|
||||
} \
|
||||
return FLOATTYPE ## _muladd(a, b, FLOATTYPE ## _two, 0, fpst); \
|
||||
}
|
||||
return float16_muladd(a, b, float16_two, 0, fpst);
|
||||
}
|
||||
|
||||
float32 HELPER(recpsf_f32)(float32 a, float32 b, float_status *fpst)
|
||||
{
|
||||
a = float32_squash_input_denormal(a, fpst);
|
||||
b = float32_squash_input_denormal(b, fpst);
|
||||
DO_RECPS(recpsf_f16, uint32_t, float16, chs)
|
||||
DO_RECPS(recpsf_f32, float32, float32, chs)
|
||||
DO_RECPS(recpsf_f64, float64, float64, chs)
|
||||
DO_RECPS(recpsf_ah_f16, uint32_t, float16, ah_chs)
|
||||
DO_RECPS(recpsf_ah_f32, float32, float32, ah_chs)
|
||||
DO_RECPS(recpsf_ah_f64, float64, float64, ah_chs)
|
||||
|
||||
a = float32_chs(a);
|
||||
if ((float32_is_infinity(a) && float32_is_zero(b)) ||
|
||||
(float32_is_infinity(b) && float32_is_zero(a))) {
|
||||
return float32_two;
|
||||
}
|
||||
return float32_muladd(a, b, float32_two, 0, fpst);
|
||||
}
|
||||
#define DO_RSQRTSF(NAME, CTYPE, FLOATTYPE, CHSFN) \
|
||||
CTYPE HELPER(NAME)(CTYPE a, CTYPE b, float_status *fpst) \
|
||||
{ \
|
||||
a = FLOATTYPE ## _squash_input_denormal(a, fpst); \
|
||||
b = FLOATTYPE ## _squash_input_denormal(b, fpst); \
|
||||
a = FLOATTYPE ## _ ## CHSFN(a); \
|
||||
if ((FLOATTYPE ## _is_infinity(a) && FLOATTYPE ## _is_zero(b)) || \
|
||||
(FLOATTYPE ## _is_infinity(b) && FLOATTYPE ## _is_zero(a))) { \
|
||||
return FLOATTYPE ## _one_point_five; \
|
||||
} \
|
||||
return FLOATTYPE ## _muladd_scalbn(a, b, FLOATTYPE ## _three, \
|
||||
-1, 0, fpst); \
|
||||
} \
|
||||
|
||||
float64 HELPER(recpsf_f64)(float64 a, float64 b, float_status *fpst)
|
||||
{
|
||||
a = float64_squash_input_denormal(a, fpst);
|
||||
b = float64_squash_input_denormal(b, fpst);
|
||||
|
||||
a = float64_chs(a);
|
||||
if ((float64_is_infinity(a) && float64_is_zero(b)) ||
|
||||
(float64_is_infinity(b) && float64_is_zero(a))) {
|
||||
return float64_two;
|
||||
}
|
||||
return float64_muladd(a, b, float64_two, 0, fpst);
|
||||
}
|
||||
|
||||
uint32_t HELPER(rsqrtsf_f16)(uint32_t a, uint32_t b, float_status *fpst)
|
||||
{
|
||||
a = float16_squash_input_denormal(a, fpst);
|
||||
b = float16_squash_input_denormal(b, fpst);
|
||||
|
||||
a = float16_chs(a);
|
||||
if ((float16_is_infinity(a) && float16_is_zero(b)) ||
|
||||
(float16_is_infinity(b) && float16_is_zero(a))) {
|
||||
return float16_one_point_five;
|
||||
}
|
||||
return float16_muladd_scalbn(a, b, float16_three, -1, 0, fpst);
|
||||
}
|
||||
|
||||
float32 HELPER(rsqrtsf_f32)(float32 a, float32 b, float_status *fpst)
|
||||
{
|
||||
a = float32_squash_input_denormal(a, fpst);
|
||||
b = float32_squash_input_denormal(b, fpst);
|
||||
|
||||
a = float32_chs(a);
|
||||
if ((float32_is_infinity(a) && float32_is_zero(b)) ||
|
||||
(float32_is_infinity(b) && float32_is_zero(a))) {
|
||||
return float32_one_point_five;
|
||||
}
|
||||
return float32_muladd_scalbn(a, b, float32_three, -1, 0, fpst);
|
||||
}
|
||||
|
||||
float64 HELPER(rsqrtsf_f64)(float64 a, float64 b, float_status *fpst)
|
||||
{
|
||||
a = float64_squash_input_denormal(a, fpst);
|
||||
b = float64_squash_input_denormal(b, fpst);
|
||||
|
||||
a = float64_chs(a);
|
||||
if ((float64_is_infinity(a) && float64_is_zero(b)) ||
|
||||
(float64_is_infinity(b) && float64_is_zero(a))) {
|
||||
return float64_one_point_five;
|
||||
}
|
||||
return float64_muladd_scalbn(a, b, float64_three, -1, 0, fpst);
|
||||
}
|
||||
DO_RSQRTSF(rsqrtsf_f16, uint32_t, float16, chs)
|
||||
DO_RSQRTSF(rsqrtsf_f32, float32, float32, chs)
|
||||
DO_RSQRTSF(rsqrtsf_f64, float64, float64, chs)
|
||||
DO_RSQRTSF(rsqrtsf_ah_f16, uint32_t, float16, ah_chs)
|
||||
DO_RSQRTSF(rsqrtsf_ah_f32, float32, float32, ah_chs)
|
||||
DO_RSQRTSF(rsqrtsf_ah_f64, float64, float64, ah_chs)
|
||||
|
||||
/* Floating-point reciprocal exponent - see FPRecpX in ARM ARM */
|
||||
uint32_t HELPER(frecpx_f16)(uint32_t a, float_status *fpst)
|
||||
@@ -399,6 +364,42 @@ float32 HELPER(fcvtx_f64_to_f32)(float64 a, float_status *fpst)
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* AH=1 min/max have some odd special cases:
|
||||
* comparing two zeroes (regardless of sign), (NaN, anything),
|
||||
* or (anything, NaN) should return the second argument (possibly
|
||||
* squashed to zero).
|
||||
* Also, denormal outputs are not squashed to zero regardless of FZ or FZ16.
|
||||
*/
|
||||
#define AH_MINMAX_HELPER(NAME, CTYPE, FLOATTYPE, MINMAX) \
|
||||
CTYPE HELPER(NAME)(CTYPE a, CTYPE b, float_status *fpst) \
|
||||
{ \
|
||||
bool save; \
|
||||
CTYPE r; \
|
||||
a = FLOATTYPE ## _squash_input_denormal(a, fpst); \
|
||||
b = FLOATTYPE ## _squash_input_denormal(b, fpst); \
|
||||
if (FLOATTYPE ## _is_zero(a) && FLOATTYPE ## _is_zero(b)) { \
|
||||
return b; \
|
||||
} \
|
||||
if (FLOATTYPE ## _is_any_nan(a) || \
|
||||
FLOATTYPE ## _is_any_nan(b)) { \
|
||||
float_raise(float_flag_invalid, fpst); \
|
||||
return b; \
|
||||
} \
|
||||
save = get_flush_to_zero(fpst); \
|
||||
set_flush_to_zero(false, fpst); \
|
||||
r = FLOATTYPE ## _ ## MINMAX(a, b, fpst); \
|
||||
set_flush_to_zero(save, fpst); \
|
||||
return r; \
|
||||
}
|
||||
|
||||
AH_MINMAX_HELPER(vfp_ah_minh, dh_ctype_f16, float16, min)
|
||||
AH_MINMAX_HELPER(vfp_ah_mins, float32, float32, min)
|
||||
AH_MINMAX_HELPER(vfp_ah_mind, float64, float64, min)
|
||||
AH_MINMAX_HELPER(vfp_ah_maxh, dh_ctype_f16, float16, max)
|
||||
AH_MINMAX_HELPER(vfp_ah_maxs, float32, float32, max)
|
||||
AH_MINMAX_HELPER(vfp_ah_maxd, float64, float64, max)
|
||||
|
||||
/* 64-bit versions of the CRC helpers. Note that although the operation
|
||||
* (and the prototypes of crc32c() and crc32() mean that only the bottom
|
||||
* 32 bits of the accumulator and result are used, we pass and return
|
||||
|
||||
@@ -38,9 +38,15 @@ DEF_HELPER_FLAGS_3(neon_cgt_f64, TCG_CALL_NO_RWG, i64, i64, i64, fpst)
|
||||
DEF_HELPER_FLAGS_3(recpsf_f16, TCG_CALL_NO_RWG, f16, f16, f16, fpst)
|
||||
DEF_HELPER_FLAGS_3(recpsf_f32, TCG_CALL_NO_RWG, f32, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_3(recpsf_f64, TCG_CALL_NO_RWG, f64, f64, f64, fpst)
|
||||
DEF_HELPER_FLAGS_3(recpsf_ah_f16, TCG_CALL_NO_RWG, f16, f16, f16, fpst)
|
||||
DEF_HELPER_FLAGS_3(recpsf_ah_f32, TCG_CALL_NO_RWG, f32, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_3(recpsf_ah_f64, TCG_CALL_NO_RWG, f64, f64, f64, fpst)
|
||||
DEF_HELPER_FLAGS_3(rsqrtsf_f16, TCG_CALL_NO_RWG, f16, f16, f16, fpst)
|
||||
DEF_HELPER_FLAGS_3(rsqrtsf_f32, TCG_CALL_NO_RWG, f32, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_3(rsqrtsf_f64, TCG_CALL_NO_RWG, f64, f64, f64, fpst)
|
||||
DEF_HELPER_FLAGS_3(rsqrtsf_ah_f16, TCG_CALL_NO_RWG, f16, f16, f16, fpst)
|
||||
DEF_HELPER_FLAGS_3(rsqrtsf_ah_f32, TCG_CALL_NO_RWG, f32, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_3(rsqrtsf_ah_f64, TCG_CALL_NO_RWG, f64, f64, f64, fpst)
|
||||
DEF_HELPER_FLAGS_2(frecpx_f64, TCG_CALL_NO_RWG, f64, f64, fpst)
|
||||
DEF_HELPER_FLAGS_2(frecpx_f32, TCG_CALL_NO_RWG, f32, f32, fpst)
|
||||
DEF_HELPER_FLAGS_2(frecpx_f16, TCG_CALL_NO_RWG, f16, f16, fpst)
|
||||
@@ -67,6 +73,13 @@ DEF_HELPER_4(advsimd_muladd2h, i32, i32, i32, i32, fpst)
|
||||
DEF_HELPER_2(advsimd_rinth_exact, f16, f16, fpst)
|
||||
DEF_HELPER_2(advsimd_rinth, f16, f16, fpst)
|
||||
|
||||
DEF_HELPER_3(vfp_ah_minh, f16, f16, f16, fpst)
|
||||
DEF_HELPER_3(vfp_ah_mins, f32, f32, f32, fpst)
|
||||
DEF_HELPER_3(vfp_ah_mind, f64, f64, f64, fpst)
|
||||
DEF_HELPER_3(vfp_ah_maxh, f16, f16, f16, fpst)
|
||||
DEF_HELPER_3(vfp_ah_maxs, f32, f32, f32, fpst)
|
||||
DEF_HELPER_3(vfp_ah_maxd, f64, f64, f64, fpst)
|
||||
|
||||
DEF_HELPER_2(exception_return, void, env, i64)
|
||||
DEF_HELPER_FLAGS_2(dc_zva, TCG_CALL_NO_WG, void, env, i64)
|
||||
|
||||
|
||||
@@ -541,10 +541,18 @@ DEF_HELPER_FLAGS_4(sve_fabs_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_fabs_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_fabs_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fabs_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fabs_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fabs_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_fneg_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_fneg_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_fneg_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fneg_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fneg_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fneg_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_not_zpz_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_not_zpz_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_not_zpz_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
@@ -972,6 +980,48 @@ DEF_HELPER_FLAGS_5(gvec_rsqrts_s, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_5(gvec_rsqrts_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_recps_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_recps_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_recps_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_rsqrts_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_rsqrts_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_rsqrts_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmax_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmax_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmax_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmin_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmin_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmin_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmaxp_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmaxp_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fmaxp_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fminp_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fminp_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_ah_fminp_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_faddv_h, TCG_CALL_NO_RWG,
|
||||
i64, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_faddv_s, TCG_CALL_NO_RWG,
|
||||
@@ -1007,6 +1057,20 @@ DEF_HELPER_FLAGS_4(sve_fminv_s, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_4(sve_fminv_d, TCG_CALL_NO_RWG,
|
||||
i64, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fmaxv_h, TCG_CALL_NO_RWG,
|
||||
i64, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fmaxv_s, TCG_CALL_NO_RWG,
|
||||
i64, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fmaxv_d, TCG_CALL_NO_RWG,
|
||||
i64, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fminv_h, TCG_CALL_NO_RWG,
|
||||
i64, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fminv_s, TCG_CALL_NO_RWG,
|
||||
i64, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_ah_fminv_d, TCG_CALL_NO_RWG,
|
||||
i64, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(sve_fadda_h, TCG_CALL_NO_RWG,
|
||||
i64, i64, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(sve_fadda_s, TCG_CALL_NO_RWG,
|
||||
@@ -1098,6 +1162,20 @@ DEF_HELPER_FLAGS_6(sve_fmax_s, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_6(sve_fmax_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmin_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmin_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmin_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmax_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmax_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmax_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_fminnum_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_fminnum_s, TCG_CALL_NO_RWG,
|
||||
@@ -1119,6 +1197,13 @@ DEF_HELPER_FLAGS_6(sve_fabd_s, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_6(sve_fabd_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fabd_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fabd_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fabd_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_fscalbn_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_fscalbn_s, TCG_CALL_NO_RWG,
|
||||
@@ -1189,6 +1274,20 @@ DEF_HELPER_FLAGS_6(sve_fmins_s, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_6(sve_fmins_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, i64, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmaxs_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, i64, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmaxs_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, i64, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmaxs_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, i64, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmins_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, i64, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmins_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, i64, fpst, i32)
|
||||
DEF_HELPER_FLAGS_6(sve_ah_fmins_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, i64, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(sve_fcvt_sh, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_5(sve_fcvt_dh, TCG_CALL_NO_RWG,
|
||||
@@ -1376,6 +1475,27 @@ DEF_HELPER_FLAGS_7(sve_fnmls_zpzzz_s, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_7(sve_fnmls_zpzzz_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fmls_zpzzz_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fmls_zpzzz_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fmls_zpzzz_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fnmla_zpzzz_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fnmla_zpzzz_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fnmla_zpzzz_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fnmls_zpzzz_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fnmls_zpzzz_s, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_7(sve_ah_fnmls_zpzzz_d, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_7(sve_fcmla_zpzzz_h, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, fpst, i32)
|
||||
DEF_HELPER_FLAGS_7(sve_fcmla_zpzzz_s, TCG_CALL_NO_RWG,
|
||||
|
||||
@@ -404,6 +404,19 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
|
||||
DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx));
|
||||
}
|
||||
|
||||
if (env->vfp.fpcr & FPCR_AH) {
|
||||
DP_TBFLAG_A64(flags, AH, 1);
|
||||
}
|
||||
if (env->vfp.fpcr & FPCR_NEP) {
|
||||
/*
|
||||
* In streaming-SVE without FA64, NEP behaves as if zero;
|
||||
* compare pseudocode IsMerging()
|
||||
*/
|
||||
if (!(EX_TBFLAG_A64(flags, PSTATE_SM) && !sme_fa64(env, el))) {
|
||||
DP_TBFLAG_A64(flags, NEP, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
|
||||
}
|
||||
|
||||
|
||||
+16
-28
@@ -2814,8 +2814,7 @@ DO_VMAXMINA(vminaw, 4, int32_t, uint32_t, DO_MIN)
|
||||
if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(mask & 1)) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
@@ -2888,8 +2887,7 @@ DO_2OP_FP_ALL(vminnma, minnuma)
|
||||
r[e] = 0; \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(tm & 1)) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
@@ -2926,8 +2924,7 @@ DO_VCADD_FP(vfcadd270s, 4, float32, float32_add, float32_sub)
|
||||
if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(mask & 1)) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
@@ -2964,8 +2961,7 @@ DO_VFMA(vfmss, 4, float32, true)
|
||||
if ((mask & MAKE_64BIT_MASK(0, ESIZE * 2)) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst0 = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst0 = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
fpst1 = fpst0; \
|
||||
if (!(mask & 1)) { \
|
||||
scratch_fpst = *fpst0; \
|
||||
@@ -3049,8 +3045,7 @@ DO_VCMLA(vcmla270s, 4, float32, 3, DO_VCMLAS)
|
||||
if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(mask & 1)) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
@@ -3084,8 +3079,7 @@ DO_2OP_FP_SCALAR_ALL(vfmul_scalar, mul)
|
||||
if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(mask & 1)) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
@@ -3116,9 +3110,8 @@ DO_2OP_FP_ACC_SCALAR(vfmas_scalars, 4, float32, DO_VFMAS_SCALARS)
|
||||
unsigned e; \
|
||||
TYPE *m = vm; \
|
||||
TYPE ra = (TYPE)ra_in; \
|
||||
float_status *fpst = (ESIZE == 2) ? \
|
||||
&env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
float_status *fpst = \
|
||||
&env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
|
||||
if (mask & 1) { \
|
||||
TYPE v = m[H##ESIZE(e)]; \
|
||||
@@ -3168,8 +3161,7 @@ DO_FP_VMAXMINV(vminnmavs, 4, float32, true, float32_minnum)
|
||||
if ((mask & emask) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(mask & (1 << (e * ESIZE)))) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
@@ -3202,8 +3194,7 @@ DO_FP_VMAXMINV(vminnmavs, 4, float32, true, float32_minnum)
|
||||
if ((mask & emask) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(mask & (1 << (e * ESIZE)))) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
@@ -3267,8 +3258,7 @@ DO_VCMP_FP_BOTH(vfcmples, vfcmple_scalars, 4, float32, !DO_GT32)
|
||||
if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(mask & 1)) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
@@ -3300,9 +3290,8 @@ DO_VCVT_FIXED(vcvt_fu, 4, uint32_t, helper_vfp_touls_round_to_zero)
|
||||
unsigned e; \
|
||||
float_status *fpst; \
|
||||
float_status scratch_fpst; \
|
||||
float_status *base_fpst = (ESIZE == 2) ? \
|
||||
&env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
float_status *base_fpst = \
|
||||
&env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
uint32_t prev_rmode = get_float_rounding_mode(base_fpst); \
|
||||
set_float_rounding_mode(rmode, base_fpst); \
|
||||
for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
|
||||
@@ -3347,7 +3336,7 @@ static void do_vcvt_sh(CPUARMState *env, void *vd, void *vm, int top)
|
||||
unsigned e;
|
||||
float_status *fpst;
|
||||
float_status scratch_fpst;
|
||||
float_status *base_fpst = &env->vfp.standard_fp_status;
|
||||
float_status *base_fpst = &env->vfp.fp_status[FPST_STD];
|
||||
bool old_fz = get_flush_to_zero(base_fpst);
|
||||
set_flush_to_zero(false, base_fpst);
|
||||
for (e = 0; e < 16 / 4; e++, mask >>= 4) {
|
||||
@@ -3377,7 +3366,7 @@ static void do_vcvt_hs(CPUARMState *env, void *vd, void *vm, int top)
|
||||
unsigned e;
|
||||
float_status *fpst;
|
||||
float_status scratch_fpst;
|
||||
float_status *base_fpst = &env->vfp.standard_fp_status;
|
||||
float_status *base_fpst = &env->vfp.fp_status[FPST_STD];
|
||||
bool old_fiz = get_flush_inputs_to_zero(base_fpst);
|
||||
set_flush_inputs_to_zero(false, base_fpst);
|
||||
for (e = 0; e < 16 / 4; e++, mask >>= 4) {
|
||||
@@ -3427,8 +3416,7 @@ void HELPER(mve_vcvtt_hs)(CPUARMState *env, void *vd, void *vm)
|
||||
if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
|
||||
continue; \
|
||||
} \
|
||||
fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
|
||||
&env->vfp.standard_fp_status; \
|
||||
fpst = &env->vfp.fp_status[ESIZE == 2 ? FPST_STD_F16 : FPST_STD]; \
|
||||
if (!(mask & 1)) { \
|
||||
/* We need the result but without updating flags */ \
|
||||
scratch_fpst = *fpst; \
|
||||
|
||||
@@ -1043,8 +1043,8 @@ void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn,
|
||||
* produces default NaNs. We also need a second copy of fp_status with
|
||||
* round-to-odd -- see above.
|
||||
*/
|
||||
fpst_f16 = env->vfp.fp_status_f16_a64;
|
||||
fpst_std = env->vfp.fp_status_a64;
|
||||
fpst_f16 = env->vfp.fp_status[FPST_A64_F16];
|
||||
fpst_std = env->vfp.fp_status[FPST_A64];
|
||||
set_default_nan_mode(true, &fpst_std);
|
||||
set_default_nan_mode(true, &fpst_f16);
|
||||
fpst_odd = fpst_std;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user