@@ -5226,8 +5226,6 @@ void HELPER(sve_fcadd_h)(void *vd, void *vn, void *vm, void *vg,
uint64_t *g = vg;
bool rot = extract32(desc, SIMD_DATA_SHIFT, 1);
bool fpcr_ah = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
- float16 neg_imag = float16_set_sign(0, rot);
- float16 neg_real = float16_chs(neg_imag);
do {
uint64_t pg = g[(i - 1) >> 6];
@@ -5243,11 +5241,10 @@ void HELPER(sve_fcadd_h)(void *vd, void *vn, void *vm, void *vg,
e2 = *(float16 *)(vn + H1_2(j));
e3 = *(float16 *)(vm + H1_2(i));
- if (neg_real && !(fpcr_ah && float16_is_any_nan(e1))) {
- e1 ^= neg_real;
- }
- if (neg_imag && !(fpcr_ah && float16_is_any_nan(e3))) {
- e3 ^= neg_imag;
+ if (rot) {
+ e3 = float16_maybe_ah_chs(e3, fpcr_ah);
+ } else {
+ e1 = float16_maybe_ah_chs(e1, fpcr_ah);
}
if (likely((pg >> (i & 63)) & 1)) {
@@ -5267,8 +5264,6 @@ void HELPER(sve_fcadd_s)(void *vd, void *vn, void *vm, void *vg,
uint64_t *g = vg;
bool rot = extract32(desc, SIMD_DATA_SHIFT, 1);
bool fpcr_ah = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
- float32 neg_imag = float32_set_sign(0, rot);
- float32 neg_real = float32_chs(neg_imag);
do {
uint64_t pg = g[(i - 1) >> 6];
@@ -5284,11 +5279,10 @@ void HELPER(sve_fcadd_s)(void *vd, void *vn, void *vm, void *vg,
e2 = *(float32 *)(vn + H1_2(j));
e3 = *(float32 *)(vm + H1_2(i));
- if (neg_real && !(fpcr_ah && float32_is_any_nan(e1))) {
- e1 ^= neg_real;
- }
- if (neg_imag && !(fpcr_ah && float32_is_any_nan(e3))) {
- e3 ^= neg_imag;
+ if (rot) {
+ e3 = float32_maybe_ah_chs(e3, fpcr_ah);
+ } else {
+ e1 = float32_maybe_ah_chs(e1, fpcr_ah);
}
if (likely((pg >> (i & 63)) & 1)) {
@@ -5308,8 +5302,6 @@ void HELPER(sve_fcadd_d)(void *vd, void *vn, void *vm, void *vg,
uint64_t *g = vg;
bool rot = extract32(desc, SIMD_DATA_SHIFT, 1);
bool fpcr_ah = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
- float64 neg_imag = float64_set_sign(0, rot);
- float64 neg_real = float64_chs(neg_imag);
do {
uint64_t pg = g[(i - 1) >> 6];
@@ -5325,11 +5317,10 @@ void HELPER(sve_fcadd_d)(void *vd, void *vn, void *vm, void *vg,
e2 = *(float64 *)(vn + H1_2(j));
e3 = *(float64 *)(vm + H1_2(i));
- if (neg_real && !(fpcr_ah && float64_is_any_nan(e1))) {
- e1 ^= neg_real;
- }
- if (neg_imag && !(fpcr_ah && float64_is_any_nan(e3))) {
- e3 ^= neg_imag;
+ if (rot) {
+ e3 = float64_maybe_ah_chs(e3, fpcr_ah);
+ } else {
+ e1 = float64_maybe_ah_chs(e1, fpcr_ah);
}
if (likely((pg >> (i & 63)) & 1)) {
The construction of neg_imag and neg_real were done to make it easy to apply both in parallel with two simple logical operations. This changed with FPCR.AH, which is more complex than that. Note that there was a naming issue with neg_imag and neg_real. They were named backward, with neg_imag being non-zero for rot=1, and vice versa. This was combined with reversed usage within the loop, so that the negation in the end turned out correct. Using the rot variable introduced with fpcr_ah, it's easier to match the pseudocode for the instruction. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/arm/tcg/sve_helper.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-)