Patchwork [v2,8/9] target-i386: cleanup helper_fxam_ST0()

login
register
mail settings
Submitter Aurelien Jarno
Date May 23, 2011, 9:42 p.m.
Message ID <1306186971-9528-9-git-send-email-aurelien@aurel32.net>
Download mbox | patch
Permalink /patch/97090/
State New
Headers show

Comments

Aurelien Jarno - May 23, 2011, 9:42 p.m.
Rewrite helper_fxam_ST0() using only softfloat functions.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
---
 target-i386/op_helper.c |   30 ++++++++++++------------------
 1 files changed, 12 insertions(+), 18 deletions(-)
Peter Maydell - May 23, 2011, 10:02 p.m.
On 23 May 2011 22:42, Aurelien Jarno <aurelien@aurel32.net> wrote:
> Rewrite helper_fxam_ST0() using only softfloat functions.
>
> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

(Sorry I didn't get round to this one earlier; I think I did
the easy patches and stalled on the ones I'd have to pull out
the x86 manuals for :-))

>     /* XXX: test fptags too */

You could fix this XXX while you were here; it's just adding

    if (env->fptags[env->fpstt]) {
       env->fpus |= 0x4100; /* (C3,C2,C0) <-- 101 */
    } else ...

to the top of the ladder, right?

(Catching the "Unsupported" case would be slightly more tedious,
we'd need to identify all the floatx80 weirdo bitpatterns
as per the table in the architecture manual. Could use a
FIXME/XXX comment on that account, maybe.)

> -    expdif = EXPD(temp);
> -    if (expdif == MAXEXPD) {
> -        if (MANTD(temp) == 0x8000000000000000ULL)
> -            env->fpus |=  0x500 /*Infinity*/;
> -        else
> -            env->fpus |=  0x100 /*NaN*/;
> -    } else if (expdif == 0) {
> -        if (MANTD(temp) == 0)
> -            env->fpus |=  0x4000 /*Zero*/;
> -        else
> -            env->fpus |= 0x4400 /*Denormal*/;
> +    if (floatx80_is_infinity(ST0)) {
> +        env->fpus |=  0x500; /* (C3,C2,C0) <-- 011 */
> +    } else if (floatx80_is_any_nan(ST0)) {
> +        env->fpus |=  0x100; /* (C3,C2,C0) <-- 001 */
> +    } else if (floatx80_is_zero(ST0)) {
> +        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
> +    } else if (floatx80_is_zero_or_denormal(ST0)) {
> +        env->fpus |= 0x4400; /* (C3,C2,C0) <-- 110 */
>     } else {
> -        env->fpus |= 0x400;
> +        env->fpus |=  0x400; /* (C3,C2,C0) <-- 010 */
>     }
>  }

This all looks right. The C0/C1/C2/C3 bits seem to get enough
use in this and other functions to merit FPUS_* constants,
although that should probably be a different patch.

There's also code in helper_fstenv() which is currently
doing manual identification of zero/NaN/inf/denorm.

-- PMM

Patch

diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index cec0c76..8ba2b5f 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -4241,29 +4241,23 @@  void helper_fcos(void)
 
 void helper_fxam_ST0(void)
 {
-    CPU_LDoubleU temp;
-    int expdif;
-
-    temp.d = ST0;
-
     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
-    if (SIGND(temp))
+
+    if (floatx80_is_neg(ST0)) {
         env->fpus |= 0x200; /* C1 <-- 1 */
+    }
 
     /* XXX: test fptags too */
-    expdif = EXPD(temp);
-    if (expdif == MAXEXPD) {
-        if (MANTD(temp) == 0x8000000000000000ULL)
-            env->fpus |=  0x500 /*Infinity*/;
-        else
-            env->fpus |=  0x100 /*NaN*/;
-    } else if (expdif == 0) {
-        if (MANTD(temp) == 0)
-            env->fpus |=  0x4000 /*Zero*/;
-        else
-            env->fpus |= 0x4400 /*Denormal*/;
+    if (floatx80_is_infinity(ST0)) {
+        env->fpus |=  0x500; /* (C3,C2,C0) <-- 011 */
+    } else if (floatx80_is_any_nan(ST0)) {
+        env->fpus |=  0x100; /* (C3,C2,C0) <-- 001 */
+    } else if (floatx80_is_zero(ST0)) {
+        env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
+    } else if (floatx80_is_zero_or_denormal(ST0)) {
+        env->fpus |= 0x4400; /* (C3,C2,C0) <-- 110 */
     } else {
-        env->fpus |= 0x400;
+        env->fpus |=  0x400; /* (C3,C2,C0) <-- 010 */
     }
 }