diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-04-03 13:54:07 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-04-03 13:54:07 +0200 |
| commit | cd3163a78585c35d41a18f248cb9575c46ffab38 (patch) | |
| tree | f783852464152315088550f795640f4381b8f4df /src | |
| parent | b472459a22169c1bf1932f5e69577ac149c1b2d7 (diff) | |
| download | box64-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.h | 12 | ||||
| -rw-r--r-- | src/emu/x64run0f.c | 6 | ||||
| -rw-r--r-- | src/emu/x64run64.c | 3 | ||||
| -rw-r--r-- | src/emu/x64run660f.c | 53 | ||||
| -rw-r--r-- | src/emu/x64runavx0f.c | 21 | ||||
| -rw-r--r-- | src/emu/x64runavx660f.c | 93 | ||||
| -rw-r--r-- | src/emu/x64runavxf20f.c | 76 | ||||
| -rw-r--r-- | src/emu/x64runavxf30f.c | 2 | ||||
| -rw-r--r-- | src/emu/x64runf20f.c | 84 | ||||
| -rw-r--r-- | src/emu/x64runf30f.c | 5 |
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; |