about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-04-03 13:54:07 +0200
committerptitSeb <sebastien.chev@gmail.com>2025-04-03 13:54:07 +0200
commitcd3163a78585c35d41a18f248cb9575c46ffab38 (patch)
treef783852464152315088550f795640f4381b8f4df /src
parentb472459a22169c1bf1932f5e69577ac149c1b2d7 (diff)
downloadbox64-cd3163a78585c35d41a18f248cb9575c46ffab38.tar.gz
box64-cd3163a78585c35d41a18f248cb9575c46ffab38.zip
[INTERP] Better handling of default NAN for a few opcodes, more to come
Diffstat (limited to 'src')
-rw-r--r--src/emu/modrm.h12
-rw-r--r--src/emu/x64run0f.c6
-rw-r--r--src/emu/x64run64.c3
-rw-r--r--src/emu/x64run660f.c53
-rw-r--r--src/emu/x64runavx0f.c21
-rw-r--r--src/emu/x64runavx660f.c93
-rw-r--r--src/emu/x64runavxf20f.c76
-rw-r--r--src/emu/x64runavxf30f.c2
-rw-r--r--src/emu/x64runf20f.c84
-rw-r--r--src/emu/x64runf30f.c5
10 files changed, 126 insertions, 229 deletions
diff --git a/src/emu/modrm.h b/src/emu/modrm.h
index edb391d5..4a1abd3e 100644
--- a/src/emu/modrm.h
+++ b/src/emu/modrm.h
@@ -131,6 +131,18 @@
 #define NAN_PROPAGATION(dest, src, break_or_continue)

 #endif

 

+#define MARK_NAN_VF_2(A, B) for(int idx=0; idx<4; ++idx) mask_nan[idx] = isnanf(A->f[idx]) || isnanf(B->f[idx])

+#define CHECK_NAN_VF(A) for(int idx=0; idx<4; ++idx) if(!mask_nan[idx] && isnanf(A->f[idx])) A->f[idx] = -NAN

+

+#define MARK_NAN_VD_2(A, B) for(int idx=0; idx<2; ++idx) mask_nan[idx] = isnan(A->d[idx]) || isnan(B->d[idx])

+#define CHECK_NAN_VD(A) for(int idx=0; idx<2; ++idx) if(!mask_nan[idx] && isnan(A->d[idx])) A->d[idx] = -NAN

+

+#define MARK_NAN_F_2(A, B) is_nan = isnanf(A->f[0]) || isnanf(B->f[0])

+#define CHECK_NAN_F(A) if(!is_nan && isnanf(A->f[0])) A->f[0] = -NAN

+

+#define MARK_NAN_D_2(A, B) is_nan = isnan(A->d[0]) || isnan(B->d[0])

+#define CHECK_NAN_D(A) if(!is_nan && isnan(A->d[0])) A->d[0] = -NAN

+

 #define GOCOND(BASE, PREFIX, COND, NOTCOND, POST)\

     case BASE+0x0:                              \

         PREFIX                                  \

diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c
index 45fb53ef..4a52bec3 100644
--- a/src/emu/x64run0f.c
+++ b/src/emu/x64run0f.c
@@ -752,15 +752,13 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
             nextop = F8;

             GETEX(0);

             GETGX;

-            for(int i=0; i<4; ++i)

-                GX->ud[i] &= EX->ud[i];

+            GX->u128 &= EX->u128;

             break;

         case 0x55:                      /* ANDNPS Gx, Ex */

             nextop = F8;

             GETEX(0);

             GETGX;

-            for(int i=0; i<4; ++i)

-                GX->ud[i] = (~GX->ud[i]) & EX->ud[i];

+            GX->u128 = (~GX->u128) & EX->u128;

             break;

         case 0x56:                      /* ORPS Gx, Ex */

             nextop = F8;

diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c
index 3fa47326..d70d7c75 100644
--- a/src/emu/x64run64.c
+++ b/src/emu/x64run64.c
@@ -43,6 +43,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
     #ifdef TEST_INTERPRETER

     x64emu_t* emu = test->emu;

     #endif

+    int is_nan;

     uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);

 

     opcode = F8;

@@ -217,8 +218,10 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
                             nextop = F8;

                             GETEX_OFFS(0, tlsdata);

                             GETGX;

+                            is_nan = isnanf(GX->f[0]) || isnanf(EX->f[0]);

                             NAN_PROPAGATION(GX->f[0], EX->f[0], break);

                             GX->f[0] += EX->f[0];

+                            if(!is_nan && isnanf(GX->f[0])) GX->f[0] = -NAN;

                             break;

 

                         default:

diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c
index eef57099..51a7b35c 100644
--- a/src/emu/x64run660f.c
+++ b/src/emu/x64run660f.c
@@ -67,9 +67,8 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
     int64_t tmp64s, i64[4];

     float tmpf;

     double tmpd;

-    #ifndef NOALIGN

     int is_nan;

-    #endif

+    int mask_nan[4];

     reg64_t *oped, *opgd;

     sse_regs_t *opex, *opgx, eax1, *opex2, eax2;

     mmx87_regs_t *opem, *opgm;

@@ -1276,12 +1275,10 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         GETEX(0);

         GETGX;

         for (int i=0; i<2; ++i) {

-            #ifndef NOALIGN

             if(EX->d[i]<0.0)        // on x86, default nan are negative

                 GX->d[i] = -NAN;    // but input NAN are not touched (so sqrt(+nan) -> +nan)

             else

-            #endif

-            GX->d[i] = sqrt(EX->d[i]);

+                GX->d[i] = sqrt(EX->d[i]);

         }

         break;

 

@@ -1317,29 +1314,21 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         nextop = F8;

         GETEX(0);

         GETGX;

+        MARK_NAN_VD_2(GX, EX);

         for(int i=0; i<2; ++i) {

-            #ifndef NOALIGN

-                // add generate a -NAN only if doing inf + -inf

-                if((isinf(GX->d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)!=(GX->q[i]&0x8000000000000000LL)))

-                    GX->d[i] = -NAN;

-                else

-            #endif

             GX->d[i] += EX->d[i];

         }

+        CHECK_NAN_VD(GX);

         break;

     case 0x59:                      /* MULPD Gx, Ex */

         nextop = F8;

         GETEX(0);

         GETGX;

+        MARK_NAN_VD_2(GX, EX);

         for(int i=0; i<2; ++i) {

-            #ifndef NOALIGN

-                // mul generate a -NAN only if doing (+/-)inf * (+/-)0

-                if((isinf(GX->d[i]) && EX->d[i]==0.0) || (isinf(EX->d[i]) && GX->d[i]==0.0))

-                    GX->d[i] = -NAN;

-                else

-            #endif

             GX->d[i] *= EX->d[i];

         }

+        CHECK_NAN_VD(GX);

         break;

     case 0x5A:                      /* CVTPD2PS Gx, Ex */

         nextop = F8;

@@ -1386,15 +1375,11 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         nextop = F8;

         GETEX(0);

         GETGX;

+        MARK_NAN_VD_2(GX, EX);

         for(int i=0; i<2; ++i) {

-            #ifndef NOALIGN

-                // sub generate a -NAN only if doing inf - inf

-                if((isinf(GX->d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)==(GX->q[i]&0x8000000000000000LL)))

-                    GX->d[i] = -NAN;

-                else

-            #endif

             GX->d[i] -= EX->d[i];

         }

+        CHECK_NAN_VD(GX);

         break;

     case 0x5D:                      /* MINPD Gx, Ex */

         nextop = F8;

@@ -1410,14 +1395,10 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         GETEX(0);

         GETGX;

         for (int i=0; i<2; ++i) {

-            #ifndef NOALIGN

             is_nan = isnan(GX->d[i]) || isnan(EX->d[i]);

-            #endif

             GX->d[i] /= EX->d[i];

-            #ifndef NOALIGN

             if(!is_nan && isnan(GX->d[i]))

                 GX->d[i] = -NAN;

-            #endif

         }

         break;

     case 0x5F:                      /* MAXPD Gx, Ex */

@@ -1752,50 +1733,34 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         nextop = F8;

         GETEX(0);

         GETGX;

-        #ifndef NOALIGN

         is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);

-        #endif

         GX->d[0] += GX->d[1];

-        #ifndef NOALIGN

         if(!is_nan && isnan(GX->d[0]))

             GX->d[0] = -NAN;

-        #endif

         if(EX==GX) {

             GX->d[1] = GX->d[0];

         } else {

-            #ifndef NOALIGN

             is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);

-            #endif

             GX->d[1] = EX->d[0] + EX->d[1];

-            #ifndef NOALIGN

             if(!is_nan && isnan(GX->d[1]))

                 GX->d[1] = -NAN;

-            #endif

         }

         break;

     case 0x7D:  /* HSUBPD Gx, Ex */

         nextop = F8;

         GETEX(0);

         GETGX;

-        #ifndef NOALIGN

         is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);

-        #endif

         GX->d[0] -= GX->d[1];

-        #ifndef NOALIGN

         if(!is_nan && isnan(GX->d[0]))

             GX->d[0] = -NAN;

-        #endif

         if(EX==GX) {

             GX->d[1] = GX->d[0];

         } else {

-            #ifndef NOALIGN

             is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);

-            #endif

             GX->d[1] = EX->d[0] - EX->d[1];

-            #ifndef NOALIGN

             if(!is_nan && isnan(GX->d[1]))

                 GX->d[1] = -NAN;

-            #endif

         }

         break;

     case 0x7E:                      /* MOVD Ed, Gx */

@@ -2283,8 +2248,10 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         nextop = F8;

         GETEX(0);

         GETGX;

+        MARK_NAN_VD_2(GX, EX);

         GX->d[0] -= EX->d[0];

         GX->d[1] += EX->d[1];

+        CHECK_NAN_VD(GX);

         break;

     case 0xD1:  /* PSRLW Gx, Ex */

         nextop = F8;

diff --git a/src/emu/x64runavx0f.c b/src/emu/x64runavx0f.c
index 2e514e32..dbc24f81 100644
--- a/src/emu/x64runavx0f.c
+++ b/src/emu/x64runavx0f.c
@@ -53,6 +53,7 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
     sse_regs_t *opex, *opgx, *opvx, eax1;
     sse_regs_t *opey, *opgy, *opvy, eay1;
     uint8_t maskps[4];
+    uint8_t nanmask[4];
 
 #ifdef TEST_INTERPRETER
     x64emu_t *emu = test->emu;
@@ -384,29 +385,17 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETVX;
             GETGY;
             for(int i=0; i<4; ++i) {
-                if (isnan(VX->f[i]) || isnan(EX->f[i])) {
-                    if (isnan(VX->f[i]))
-                        GX->f[i] = VX->f[i];
-                    else
-                        GX->f[i] = EX->f[i];
-                    continue;
-                }
+                nanmask[i] = isnan(VX->f[i]) || isnan(EX->f[i]);
                 GX->f[i] = VX->f[i] + EX->f[i];
-                if (isnan(GX->f[i])) GX->ud[i] |= 0x80000000;
+                if(!nanmask[i] && isnan(GX->f[i])) GX->f[i] = -NAN;
             }
             if(vex.l) {
                 GETEY;
                 GETVY;
                 for(int i=0; i<4; ++i) {
-                    if (isnan(VY->f[i]) || isnan(EY->f[i])) {
-                        if (isnan(VY->f[i]))
-                            GY->f[i] = VY->f[i];
-                        else
-                            GY->f[i] = EY->f[i];
-                        continue;
-                    }
+                    nanmask[i] = isnan(VY->f[i]) || isnan(EY->f[i]);
                     GY->f[i] = VY->f[i] + EY->f[i];
-                    if (isnan(GY->f[i])) GY->ud[i] |= 0x80000000;
+                    if(!nanmask[i] && isnan(GY->f[i])) GY->f[i] = -NAN;
                 }
             } else
                 GY->u128 = 0;
diff --git a/src/emu/x64runavx660f.c b/src/emu/x64runavx660f.c
index 8f9790f7..6ee3ae52 100644
--- a/src/emu/x64runavx660f.c
+++ b/src/emu/x64runavx660f.c
@@ -49,6 +49,7 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
     sse_regs_t *opex, *opgx, *opvx, eax1;
     sse_regs_t *opey, *opgy, *opvy, eay1;
     int is_nan;
+    int mask_nan[4];
 
 
 #ifdef TEST_INTERPRETER
@@ -220,22 +221,18 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETEX(0);
             GETGX; GETGY;
             for (int i=0; i<2; ++i) {
-                #ifndef NOALIGN
                 if(EX->d[i]<0.0)        // on x86, default nan are negative
                     GX->d[i] = -NAN;    // but input NAN are not touched (so sqrt(+nan) -> +nan)
                 else
-                #endif
-                GX->d[i] = sqrt(EX->d[i]);
+                    GX->d[i] = sqrt(EX->d[i]);
             }
             if(vex.l) {
                 GETEY;
                 for (int i=0; i<2; ++i) {
-                    #ifndef NOALIGN
                     if(EY->d[i]<0.0)
                         GY->d[i] = -NAN;
                     else
-                    #endif
-                    GY->d[i] = sqrt(EY->d[i]);
+                        GY->d[i] = sqrt(EY->d[i]);
                 }
             } else
                 GY->u128 = 0;
@@ -306,14 +303,20 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETEX(0);
             GETGX;
             GETVX;
-            GX->d[0] = VX->d[0] + EX->d[0];
-            GX->d[1] = VX->d[1] + EX->d[1];
+            MARK_NAN_VD_2(VX, EX);
+            for(int i=0; i<2; ++i) {
+                GX->d[i] = VX->d[i] + EX->d[i];
+            }
+            CHECK_NAN_VD(GX);
             GETGY;
             if(vex.l) {
                 GETEY;
                 GETVY;
-                GY->d[0] = VY->d[0] + EY->d[0];
-                GY->d[1] = VY->d[1] + EY->d[1];
+                MARK_NAN_VD_2(VY, EY);
+                for(int i=0; i<2; ++i) {
+                    GY->d[i] = VY->d[i] + EY->d[i];
+                }
+                CHECK_NAN_VD(GY);
             } else {
                 GY->u128 = 0;
             }
@@ -324,27 +327,19 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETGX;
             GETVX;
             GETGY;
+            MARK_NAN_VD_2(VX, EX);
             for(int i=0; i<2; ++i) {
-                #ifndef NOALIGN
-                    // mul generate a -NAN only if doing (+/-)inf * (+/-)0
-                    if((isinf(VX->d[i]) && EX->d[i]==0.0) || (isinf(EX->d[i]) && VX->d[i]==0.0))
-                        GX->d[i] = -NAN;
-                    else
-                #endif
                 GX->d[i] = VX->d[i] * EX->d[i];
             }
+            CHECK_NAN_VD(GX);
             if(vex.l) {
                 GETEY;
                 GETVY;
+                MARK_NAN_VD_2(VY, EY);
                 for(int i=0; i<2; ++i) {
-                    #ifndef NOALIGN
-                        // mul generate a -NAN only if doing (+/-)inf * (+/-)0
-                        if((isinf(VY->d[i]) && EY->d[i]==0.0) || (isinf(EY->d[i]) && VY->d[i]==0.0))
-                            GY->d[i] = -NAN;
-                        else
-                    #endif
                     GY->d[i] = VY->d[i] * EY->d[i];
                 }
+                CHECK_NAN_VD(GY);
             } else
                 GY->u128 = 0;
             break;
@@ -474,29 +469,19 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETGX;
             GETVX;
             GETGY;
+            MARK_NAN_VD_2(VX, EX);
             for (int i=0; i<2; ++i) {
-                #ifndef NOALIGN
-                is_nan = isnan(VX->d[i]) || isnan(EX->d[i]);
-                #endif
                 GX->d[i] = VX->d[i] / EX->d[i];
-                #ifndef NOALIGN
-                if(!is_nan && isnan(GX->d[i]))
-                    GX->d[i] = -NAN;
-                #endif
             }
+            CHECK_NAN_VD(GX);
             if(vex.l) {
                 GETEY;
                 GETVY;
+                MARK_NAN_VD_2(VY, EY);
                 for (int i=0; i<2; ++i) {
-                    #ifndef NOALIGN
-                    is_nan = isnan(VY->d[i]) || isnan(EY->d[i]);
-                    #endif
                     GY->d[i] = VY->d[i] / EY->d[i];
-                    #ifndef NOALIGN
-                    if(!is_nan && isnan(GY->d[i]))
-                        GY->d[i] = -NAN;
-                    #endif
                 }
+                CHECK_NAN_VD(GY);
             } else
                 GY->u128 = 0;
             break;
@@ -1107,25 +1092,17 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
                 eax1 = *EX;
                 EX = &eax1;
             }
-            #ifndef NOALIGN
             is_nan = isnan(VX->d[0]) || isnan(VX->d[1]);
-            #endif
             GX->d[0] = VX->d[0] + VX->d[1];
-            #ifndef NOALIGN
             if(!is_nan && isnan(GX->d[0]))
                 GX->d[0] = -NAN;
-            #endif
             if(EX==VX) {
                 GX->d[1] = GX->d[0];
             } else {
-                #ifndef NOALIGN
                 is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
-                #endif
                 GX->d[1] = EX->d[0] + EX->d[1];
-                #ifndef NOALIGN
                 if(!is_nan && isnan(GX->d[1]))
                     GX->d[1] = -NAN;
-                #endif
             }
             if(vex.l) {
                 if(GY==EY) {
@@ -1133,25 +1110,17 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
                     EY = &eay1;
                 }
                 GETVY;
-                #ifndef NOALIGN
                 is_nan = isnan(VY->d[0]) || isnan(VY->d[1]);
-                #endif
                 GY->d[0] = VY->d[0] + VY->d[1];
-                #ifndef NOALIGN
                 if(!is_nan && isnan(GY->d[0]))
                     GY->d[0] = -NAN;
-                #endif
                 if(EY==VY) {
                     GY->d[1] = GY->d[0];
                 } else {
-                    #ifndef NOALIGN
                     is_nan = isnan(EY->d[0]) || isnan(EY->d[1]);
-                    #endif
                     GY->d[1] = EY->d[0] + EY->d[1];
-                    #ifndef NOALIGN
                     if(!is_nan && isnan(GY->d[1]))
                         GY->d[1] = -NAN;
-                    #endif
                 }
             } else
                 GY->u128 = 0;
@@ -1167,25 +1136,17 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
                 eax1 = *EX;
                 EX = &eax1;
             }
-            #ifndef NOALIGN
             is_nan = isnan(VX->d[0]) || isnan(VX->d[1]);
-            #endif
             GX->d[0] = VX->d[0] - VX->d[1];
-            #ifndef NOALIGN
             if(!is_nan && isnan(GX->d[0]))
                 GX->d[0] = -NAN;
-            #endif
             if(EX==VX) {
                 GX->d[1] = GX->d[0];
             } else {
-                #ifndef NOALIGN
                 is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
-                #endif
                 GX->d[1] = EX->d[0] - EX->d[1];
-                #ifndef NOALIGN
                 if(!is_nan && isnan(GX->d[1]))
                     GX->d[1] = -NAN;
-                #endif
             }
             if(vex.l) {
                 if(GY==EY) {
@@ -1193,25 +1154,17 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
                     EY = &eay1;
                 }
                 GETVY;
-                #ifndef NOALIGN
                 is_nan = isnan(VY->d[0]) || isnan(VY->d[1]);
-                #endif
                 GY->d[0] = VY->d[0] - VY->d[1];
-                #ifndef NOALIGN
                 if(!is_nan && isnan(GY->d[0]))
                     GY->d[0] = -NAN;
-                #endif
                 if(EY==VY) {
                     GY->d[1] = GY->d[0];
                 } else {
-                    #ifndef NOALIGN
                     is_nan = isnan(EY->d[0]) || isnan(EY->d[1]);
-                    #endif
                     GY->d[1] = EY->d[0] - EY->d[1];
-                    #ifndef NOALIGN
                     if(!is_nan && isnan(GY->d[1]))
                         GY->d[1] = -NAN;
-                    #endif
                 }
             } else
                 GY->u128 = 0;
@@ -1347,13 +1300,17 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETGX;
             GETVX;
             GETGY;
+            MARK_NAN_VD_2(VX, EX);
             GX->d[0] = VX->d[0] - EX->d[0];
             GX->d[1] = VX->d[1] + EX->d[1];
+            CHECK_NAN_VD(GX);
             if(vex.l) {
                 GETEY;
                 GETVY;
+                MARK_NAN_VD_2(VY, EY);
                 GY->d[0] = VY->d[0] - EY->d[0];
                 GY->d[1] = VY->d[1] + EY->d[1];
+                CHECK_NAN_VD(GY);
             } else
                 GY->u128 = 0;
             break;
diff --git a/src/emu/x64runavxf20f.c b/src/emu/x64runavxf20f.c
index 4cbd1af5..a2c68a24 100644
--- a/src/emu/x64runavxf20f.c
+++ b/src/emu/x64runavxf20f.c
@@ -48,7 +48,7 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
     sse_regs_t *opex, *opgx, *opvx, eax1;
     sse_regs_t *opey, *opgy, *opvy, eay1;
     int is_nan;
-    int nan_mask[4];
+    int mask_nan[4];
 
 
 #ifdef TEST_INTERPRETER
@@ -201,7 +201,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETGX;
             GETVX;
             GETGY;
+            MARK_NAN_D_2(VX, EX);
             GX->d[0] = VX->d[0] + EX->d[0];
+            CHECK_NAN_D(GX);
             GX->q[1] = VX->q[1];
             GY->u128 = 0;
             break;
@@ -211,13 +213,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETGX;
             GETVX;
             GETGY;
-            #ifndef NOALIGN
-                // mul generate a -NAN only if doing (+/-)inf * (+/-)0
-                if((isinf(GX->d[0]) && EX->d[0]==0.0) || (isinf(EX->d[0]) && GX->d[0]==0.0))
-                    GX->d[0] = -NAN;
-                else
-            #endif
+            MARK_NAN_D_2(VX, EX);
             GX->d[0] = VX->d[0] * EX->d[0];
+            CHECK_NAN_D(GX);
             if(GX!=VX) {
                 GX->q[1] = VX->q[1];
             }
@@ -333,46 +331,44 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
                 eax1 = *EX;
                 EX = &eax1;
             }
-            nan_mask[0] = isnanf(VX->f[0]) || isnanf(VX->f[1]);
-            nan_mask[1] = isnanf(VX->f[2]) || isnanf(VX->f[3]);
+            mask_nan[0] = isnanf(VX->f[0]) || isnanf(VX->f[1]);
+            mask_nan[1] = isnanf(VX->f[2]) || isnanf(VX->f[3]);
             GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(VX->f[1]) ? VX->f[1] : (VX->f[0] + VX->f[1]));
             GX->f[1] = isnan(VX->f[2]) ? VX->f[2] : (isnan(VX->f[3]) ? VX->f[3] : (VX->f[2] + VX->f[3]));
             if(EX==VX) {
                 GX->f[2] = GX->f[0];
                 GX->f[3] = GX->f[1];
-                nan_mask[2] = nan_mask[0];
-                nan_mask[3] = nan_mask[1];
+                mask_nan[2] = mask_nan[0];
+                mask_nan[3] = mask_nan[1];
             } else {
-                nan_mask[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
-                nan_mask[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
+                mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
+                mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
                 GX->f[2] = isnan(EX->f[0]) ? EX->f[0] : (isnan(EX->f[1]) ? EX->f[1] : (EX->f[0] + EX->f[1]));
                 GX->f[3] = isnan(EX->f[2]) ? EX->f[2] : (isnan(EX->f[3]) ? EX->f[3] : (EX->f[2] + EX->f[3]));
             }
-            for(int i=0; i<4; ++i)
-                if (!nan_mask[i] && isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
+            CHECK_NAN_VF(GX);
             if(vex.l) {
                 if(GY==EY) {
                     eay1 = *EY;
                     EY = &eay1;
                 }
                 GETVY;
-                nan_mask[0] = isnanf(VY->f[0]) || isnanf(VY->f[1]);
-                nan_mask[1] = isnanf(VY->f[2]) || isnanf(VY->f[3]);
+                mask_nan[0] = isnanf(VY->f[0]) || isnanf(VY->f[1]);
+                mask_nan[1] = isnanf(VY->f[2]) || isnanf(VY->f[3]);
                 GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(VY->f[1]) ? VY->f[1] : (VY->f[0] + VY->f[1]));
                 GY->f[1] = isnan(VY->f[2]) ? VY->f[2] : (isnan(VY->f[3]) ? VY->f[3] : (VY->f[2] + VY->f[3]));
                 if(EY==VY) {
                     GY->f[2] = GY->f[0];
                     GY->f[3] = GY->f[1];
-                    nan_mask[2] = nan_mask[0];
-                    nan_mask[3] = nan_mask[1];
+                    mask_nan[2] = mask_nan[0];
+                    mask_nan[3] = mask_nan[1];
                 } else {
-                    nan_mask[2] = isnanf(EY->f[0]) || isnanf(EY->f[1]);
-                    nan_mask[3] = isnanf(EY->f[2]) || isnanf(EY->f[3]);
+                    mask_nan[2] = isnanf(EY->f[0]) || isnanf(EY->f[1]);
+                    mask_nan[3] = isnanf(EY->f[2]) || isnanf(EY->f[3]);
                     GY->f[2] = isnan(EY->f[0]) ? EY->f[0] : (isnan(EY->f[1]) ? EY->f[1] : (EY->f[0] + EY->f[1]));
                     GY->f[3] = isnan(EY->f[2]) ? EY->f[2] : (isnan(EY->f[3]) ? EY->f[3] : (EY->f[2] + EY->f[3]));
                 }
-                for(int i=0; i<4; ++i)
-                    if (!nan_mask[i] && isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
+                CHECK_NAN_VF(GY);
             } else
                 GY->u128 = 0;
             break;
@@ -387,46 +383,44 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
                 eax1 = *EX;
                 EX = &eax1;
             }
-            nan_mask[0] = isnanf(VX->f[0]) || isnanf(VX->f[1]);
-            nan_mask[1] = isnanf(VX->f[2]) || isnanf(VX->f[3]);
+            mask_nan[0] = isnanf(VX->f[0]) || isnanf(VX->f[1]);
+            mask_nan[1] = isnanf(VX->f[2]) || isnanf(VX->f[3]);
             GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(VX->f[1]) ? VX->f[1] : (VX->f[0] - VX->f[1]));
             GX->f[1] = isnan(VX->f[2]) ? VX->f[2] : (isnan(VX->f[3]) ? VX->f[3] : (VX->f[2] - VX->f[3]));
             if (EX == VX) {
                 GX->f[2] = GX->f[0];
                 GX->f[3] = GX->f[1];
-                nan_mask[2] = nan_mask[0];
-                nan_mask[3] = nan_mask[1];
+                mask_nan[2] = mask_nan[0];
+                mask_nan[3] = mask_nan[1];
             } else {
-                nan_mask[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
-                nan_mask[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
+                mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
+                mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
                 GX->f[2] = isnan(EX->f[0]) ? EX->f[0] : (isnan(EX->f[1]) ? EX->f[1] : (EX->f[0] - EX->f[1]));
                 GX->f[3] = isnan(EX->f[2]) ? EX->f[2] : (isnan(EX->f[3]) ? EX->f[3] : (EX->f[2] - EX->f[3]));
             }
-            for (int i = 0; i < 4; ++i)
-                if (!nan_mask[i] && isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
+            CHECK_NAN_VF(GX);
             if (vex.l) {
                 if (GY == EY) {
                     eay1 = *EY;
                     EY = &eay1;
                 }
                 GETVY;
-                nan_mask[0] = isnanf(VY->f[0]) || isnanf(VY->f[1]);
-                nan_mask[1] = isnanf(VY->f[2]) || isnanf(VY->f[3]);
+                mask_nan[0] = isnanf(VY->f[0]) || isnanf(VY->f[1]);
+                mask_nan[1] = isnanf(VY->f[2]) || isnanf(VY->f[3]);
                 GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(VY->f[1]) ? VY->f[1] : (VY->f[0] - VY->f[1]));
                 GY->f[1] = isnan(VY->f[2]) ? VY->f[2] : (isnan(VY->f[3]) ? VY->f[3] : (VY->f[2] - VY->f[3]));
                 if (EY == VY) {
                     GY->f[2] = GY->f[0];
                     GY->f[3] = GY->f[1];
-                    nan_mask[2] = nan_mask[0];
-                    nan_mask[3] = nan_mask[1];
+                    mask_nan[2] = mask_nan[0];
+                    mask_nan[3] = mask_nan[1];
                 } else {
-                    nan_mask[2] = isnanf(EY->f[0]) || isnanf(EY->f[1]);
-                    nan_mask[3] = isnanf(EY->f[2]) || isnanf(EY->f[3]);
+                    mask_nan[2] = isnanf(EY->f[0]) || isnanf(EY->f[1]);
+                    mask_nan[3] = isnanf(EY->f[2]) || isnanf(EY->f[3]);
                     GY->f[2] = isnan(EY->f[0]) ? EY->f[0] : (isnan(EY->f[1]) ? EY->f[1] : (EY->f[0] - EY->f[1]));
                     GY->f[3] = isnan(EY->f[2]) ? EY->f[2] : (isnan(EY->f[3]) ? EY->f[3] : (EY->f[2] - EY->f[3]));
                 }
-                for (int i = 0; i < 4; ++i)
-                    if (!nan_mask[i] && isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
+                CHECK_NAN_VF(GY);
             } else
                 GY->u128 = 0;
             break;
@@ -469,17 +463,21 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETGX;
             GETVX;
             GETGY;
+            MARK_NAN_VF_2(VX, EX);
             GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(EX->f[0]) ? EX->f[0] : (VX->f[0] - EX->f[0]));
             GX->f[1] = isnan(VX->f[1]) ? VX->f[1] : (isnan(EX->f[1]) ? EX->f[1] : (VX->f[1] + EX->f[1]));
             GX->f[2] = isnan(VX->f[2]) ? VX->f[2] : (isnan(EX->f[2]) ? EX->f[2] : (VX->f[2] - EX->f[2]));
             GX->f[3] = isnan(VX->f[3]) ? VX->f[3] : (isnan(EX->f[3]) ? EX->f[3] : (VX->f[3] + EX->f[3]));
+            CHECK_NAN_VF(GX);
             if(vex.l) {
                 GETEY;
                 GETVY;
+                MARK_NAN_VF_2(VY, EY);
                 GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(EY->f[0]) ? EY->f[0] : (VY->f[0] - EY->f[0]));
                 GY->f[1] = isnan(VY->f[1]) ? VY->f[1] : (isnan(EY->f[1]) ? EY->f[1] : (VY->f[1] + EY->f[1]));
                 GY->f[2] = isnan(VY->f[2]) ? VY->f[2] : (isnan(EY->f[2]) ? EY->f[2] : (VY->f[2] - EY->f[2]));
                 GY->f[3] = isnan(VY->f[3]) ? VY->f[3] : (isnan(EY->f[3]) ? EY->f[3] : (VY->f[3] + EY->f[3]));
+                CHECK_NAN_VF(GY);
             } else
                 GY->u128 = 0;
             break;
diff --git a/src/emu/x64runavxf30f.c b/src/emu/x64runavxf30f.c
index 08d746cf..9b2ab7a7 100644
--- a/src/emu/x64runavxf30f.c
+++ b/src/emu/x64runavxf30f.c
@@ -252,7 +252,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
             GETGX;
             GETVX;
             GETGY;
+            MARK_NAN_F_2(VX, EX);
             GX->f[0] = VX->f[0] + EX->f[0];
+            CHECK_NAN_F(GX);
             if(GX!=VX) {
                 GX->ud[1] = VX->ud[1];
                 GX->q[1] = VX->q[1];
diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c
index 9fe4c319..dc86c70f 100644
--- a/src/emu/x64runf20f.c
+++ b/src/emu/x64runf20f.c
@@ -40,10 +40,8 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
     reg64_t *oped, *opgd;

     sse_regs_t *opex, *opgx, eax1;

     mmx87_regs_t *opgm;

-    #ifndef NOALIGN

-    int nan_mask[4];

+    int mask_nan[4];

     int is_nan;

-    #endif

     #ifdef TEST_INTERPRETER

     x64emu_t*emu = test->emu;

     #endif

@@ -217,31 +215,24 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         nextop = F8;

         _GETEX(0);

         GETGX;

-        #ifndef NOALIGN

-        // add generate a -NAN only if doing inf + -inf

-        if((isinf(GX->d[0]) && isinf(EX->d[0]) && (EX->q[0]&0x8000000000000000LL)!=(GX->q[0]&0x8000000000000000LL)))

-            GX->d[0] = -NAN;

-        else

-#endif

+        MARK_NAN_D_2(GX, EX);

         {

             NAN_PROPAGATION(GX->d[0], EX->d[0], break);

             GX->d[0] += EX->d[0];

         }

+        CHECK_NAN_D(GX);

         break;

     case 0x59:  /* MULSD Gx, Ex */

         nextop = F8;

         _GETEX(0);

         GETGX;

-        #ifndef NOALIGN

         // mul generate a -NAN only if doing (+/-)inf * (+/-)0

-        if ((isinf(GX->d[0]) && EX->d[0] == 0.0) || (isinf(EX->d[0]) && GX->d[0] == 0.0))

-            GX->d[0] = -NAN;

-        else

-#endif

+        MARK_NAN_D_2(GX, EX);

         {

             NAN_PROPAGATION(GX->d[0], EX->d[0], break);

             GX->d[0] *= EX->d[0];

         }

+        CHECK_NAN_D(GX);

         break;

     case 0x5A:  /* CVTSD2SS Gx, Ex */

         nextop = F8;

@@ -254,16 +245,12 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         nextop = F8;

         _GETEX(0);

         GETGX;

-        #ifndef NOALIGN

-        // sub generate a -NAN only if doing inf - inf

-        if ((isinf(GX->d[0]) && isinf(EX->d[0]) && (EX->q[0] & 0x8000000000000000LL) == (GX->q[0] & 0x8000000000000000LL)))

-            GX->d[0] = -NAN;

-        else

-#endif

+        MARK_NAN_D_2(GX, EX);

         {

             NAN_PROPAGATION(GX->d[0], EX->d[0], break);

             GX->d[0] -= EX->d[0];

         }

+        CHECK_NAN_D(GX);

         break;

     case 0x5D:  /* MINSD Gx, Ex */

         nextop = F8;

@@ -278,14 +265,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         nextop = F8;

         _GETEX(0);

         GETGX;

-        #ifndef NOALIGN

-        is_nan = isnan(GX->d[0]) || isnan(EX->d[0]);

-        #endif

+        MARK_NAN_D_2(GX, EX);

         GX->d[0] /= EX->d[0];

-        #ifndef NOALIGN

-        if(!is_nan && isnan(GX->d[0]))

-            GX->d[0] = -NAN;

-        #endif

+        CHECK_NAN_D(GX);

         break;

     case 0x5F:  /* MAXSD Gx, Ex */

         nextop = F8;

@@ -352,59 +334,41 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         nextop = F8;

         _GETEX(0);

         GETGX;

-        #ifndef NOALIGN

-        nan_mask[0] = isnanf(GX->f[0]) || isnanf(GX->f[1]);

-        nan_mask[1] = isnanf(GX->f[2]) || isnanf(GX->f[3]);

-        #endif

+        mask_nan[0] = isnanf(GX->f[0]) || isnanf(GX->f[1]);

+        mask_nan[1] = isnanf(GX->f[2]) || isnanf(GX->f[3]);

         GX->f[0] += GX->f[1];

         GX->f[1] = GX->f[2] + GX->f[3];

         if(EX==GX) {

             GX->q[1] = GX->q[0];

-            #ifndef NOALIGN

-            nan_mask[2] = nan_mask[0];

-            nan_mask[3] = nan_mask[1];

-            #endif

+            mask_nan[2] = mask_nan[0];

+            mask_nan[3] = mask_nan[1];

         } else {

-            #ifndef NOALIGN

-            nan_mask[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);

-            nan_mask[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);

-            #endif

+            mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);

+            mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);

             GX->f[2] = EX->f[0] + EX->f[1];

             GX->f[3] = EX->f[2] + EX->f[3];

         }

-        #ifndef NOALIGN

-        for(int i=0; i<4; ++i)

-            if(!nan_mask[i] && isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;

-        #endif

+        CHECK_NAN_VF(GX);

         break;

     case 0x7D:  /* HSUBPS Gx, Ex */

         nextop = F8;

         _GETEX(0);

         GETGX;

-        #ifndef NOALIGN

-        nan_mask[0] = isnanf(GX->f[0]) || isnanf(GX->f[1]);

-        nan_mask[1] = isnanf(GX->f[2]) || isnanf(GX->f[3]);

-        #endif

+        mask_nan[0] = isnanf(GX->f[0]) || isnanf(GX->f[1]);

+        mask_nan[1] = isnanf(GX->f[2]) || isnanf(GX->f[3]);

         GX->f[0] -= GX->f[1];

         GX->f[1] = GX->f[2] - GX->f[3];

         if(EX==GX) {

             GX->q[1] = GX->q[0];

-            #ifndef NOALIGN

-            nan_mask[2] = nan_mask[0];

-            nan_mask[3] = nan_mask[1];

-            #endif

+            mask_nan[2] = mask_nan[0];

+            mask_nan[3] = mask_nan[1];

         } else {

-            #ifndef NOALIGN

-            nan_mask[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);

-            nan_mask[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);

-            #endif

+            mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);

+            mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);

             GX->f[2] = EX->f[0] - EX->f[1];

             GX->f[3] = EX->f[2] - EX->f[3];

         }

-        #ifndef NOALIGN

-        for(int i=0; i<4; ++i)

-            if(!nan_mask[i] && isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;

-        #endif

+        CHECK_NAN_VF(GX);

         break;

 

     GOCOND(0x80

@@ -444,10 +408,12 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         nextop = F8;

         _GETEX(0);

         GETGX;

+        MARK_NAN_VF_2(GX, EX);

         GX->f[0] -= EX->f[0];

         GX->f[1] += EX->f[1];

         GX->f[2] -= EX->f[2];

         GX->f[3] += EX->f[3];

+        CHECK_NAN_VF(GX);

         break;

 

     case 0xD6:  /* MOVDQ2Q Gm, Ex */

diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c
index 7332032f..09267166 100644
--- a/src/emu/x64runf30f.c
+++ b/src/emu/x64runf30f.c
@@ -41,6 +41,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
     #ifdef TEST_INTERPRETER

     x64emu_t*emu = test->emu;

     #endif

+    int is_nan;

 

     #ifdef __clang__

     extern int isinff(float);

@@ -237,15 +238,19 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         nextop = F8;

         GETEX(0);

         GETGX;

+        MARK_NAN_F_2(GX, EX);

         NAN_PROPAGATION(GX->f[0], EX->f[0], break);

         GX->f[0] += EX->f[0];

+        CHECK_NAN_F(GX);

         break;

     case 0x59:  /* MULSS Gx, Ex */

         nextop = F8;

         GETEX(0);

         GETGX;

+        MARK_NAN_F_2(GX, EX);

         NAN_PROPAGATION(GX->f[0], EX->f[0], break);

         GX->f[0] *= EX->f[0];

+        CHECK_NAN_F(GX);

         break;

     case 0x5A:  /* CVTSS2SD Gx, Ex */

         nextop = F8;