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.hender...@linaro.org>
---
 target/arm/tcg/sve_helper.c | 33 ++++++++++++---------------------
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c
index a2ff3b7f11..a1f7743221 100644
--- a/target/arm/tcg/sve_helper.c
+++ b/target/arm/tcg/sve_helper.c
@@ -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)) {
-- 
2.43.0


Reply via email to