diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-11-07 15:06:55 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-11-07 15:06:55 +0100 |
| commit | f5c9439f9110fcb4fde3c7db9f68be7c107b17f6 (patch) | |
| tree | f0094dbbd242c7bc4526d61c2a1d48717f00324e /src | |
| parent | f73e4193f032713529e26c4537e5fac44147c040 (diff) | |
| download | box64-f5c9439f9110fcb4fde3c7db9f68be7c107b17f6.tar.gz box64-f5c9439f9110fcb4fde3c7db9f68be7c107b17f6.zip | |
Improved CMPSS/CMPSD opcodes, improved test17 ([DYNAREC] too, and improved MINSS/MAXSS/MINSD/MAXSD too)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/dynarec_arm64_f20f.c | 30 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_f30f.c | 28 | ||||
| -rw-r--r-- | src/emu/x64runf20f.c | 6 | ||||
| -rw-r--r-- | src/emu/x64runf30f.c | 6 |
4 files changed, 43 insertions, 27 deletions
diff --git a/src/dynarec/dynarec_arm64_f20f.c b/src/dynarec/dynarec_arm64_f20f.c index e9a75a7d..e179b2ac 100755 --- a/src/dynarec/dynarec_arm64_f20f.c +++ b/src/dynarec/dynarec_arm64_f20f.c @@ -49,7 +49,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n uint8_t gd, ed; uint8_t wback; uint8_t u8; - uint64_t u64; + uint64_t u64, j64; int v0, v1; int q0; int d0, d1; @@ -214,9 +214,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n v0 = sse_get_reg(dyn, ninst, x1, gd); GETEX(v1, 0); // MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0] + #if 0 d0 = fpu_get_scratch(dyn); FMINNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem? VMOVeD(v0, 0, d0, 0); // to not erase uper part + #else + FCMPD(v0, v1); + B_NEXT(cLS); //Less than or equal + VMOVeD(v0, 0, v1, 0); // to not erase uper part + #endif break; case 0x5E: INST_NAME("DIVSD Gx, Ex"); @@ -234,9 +240,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n v0 = sse_get_reg(dyn, ninst, x1, gd); GETEX(v1, 0); // MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0] + #if 0 d0 = fpu_get_scratch(dyn); FMAXNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem? VMOVeD(v0, 0, d0, 0); // to not erase uper part + #else + FCMPD(v0, v1); + B_NEXT(cGE); //Greater than or equal + VMOVeD(v0, 0, v1, 0); // to not erase uper part + #endif break; case 0x70: @@ -282,19 +294,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GETGX(v0); GETEX(v1, 1); u8 = F8; - if((u8&7)==6){ - FCMPD(v1, v0); - } else { - FCMPD(v0, v1); - } + FCMPD(v0, v1); switch(u8&7) { - case 0: CSETMx(x2, cEQ); CSELx(x2, xZR, x2, cVS); break; // Equal - case 1: CSETMx(x2, cMI); CSELx(x2, xZR, x2, cVS); break; // Less than - case 2: CSETMx(x2, cLE); CSELx(x2, xZR, x2, cVS); break; // Less or equal + case 0: CSETMx(x2, cEQ); break; // Equal + case 1: CSETMx(x2, cCC); break; // Less than + case 2: CSETMx(x2, cLS); break; // Less or equal case 3: CSETMx(x2, cVS); break; // NaN - case 4: CSETMx(x2, cNE); break; // Not Equal + case 4: CSETMx(x2, cNE); break; // Not Equal or unordered case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered - case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted) + case 6: CSETMx(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted) case 7: CSETMx(x2, cVC); break; // not NaN } VMOVQDfrom(v0, 0, x2); diff --git a/src/dynarec/dynarec_arm64_f30f.c b/src/dynarec/dynarec_arm64_f30f.c index 8c87b790..d47a99c5 100755 --- a/src/dynarec/dynarec_arm64_f30f.c +++ b/src/dynarec/dynarec_arm64_f30f.c @@ -259,9 +259,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GETGX(v0); GETEX(v1, 0); // MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0] + #if 0 d0 = fpu_get_scratch(dyn); FMINNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem? VMOVeS(v0, 0, d0, 0); // to not erase uper part + #else + FCMPS(v0, v1); + B_NEXT(cLS); //Less than or equal + VMOVeS(v0, 0, v1, 0); // to not erase uper part + #endif break; case 0x5E: INST_NAME("DIVSS Gx, Ex"); @@ -278,9 +284,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GETGX(v0); GETEX(v1, 0); // MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0] + #if 0 d0 = fpu_get_scratch(dyn); FMAXNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem? VMOVeS(v0, 0, d0, 0); // to not erase uper part + #else + FCMPS(v0, v1); + B_NEXT(cGE); //Greater than or equal + VMOVeS(v0, 0, v1, 0); // to not erase uper part + #endif break; case 0x6F: @@ -384,19 +396,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GETGX(v0); GETEX(v1, 1); u8 = F8; - if((u8&7)==6){ - FCMPS(v1, v0); - } else { - FCMPS(v0, v1); - } + FCMPS(v0, v1); switch(u8&7) { - case 0: CSETMw(x2, cEQ); CSELw(x2, xZR, x2, cVS); break; // Equal - case 1: CSETMw(x2, cMI); CSELw(x2, xZR, x2, cVS); break; // Less than - case 2: CSETMw(x2, cLE); CSELw(x2, xZR, x2, cVS); break; // Less or equal + case 0: CSETMw(x2, cEQ); break; // Equal + case 1: CSETMw(x2, cCC); break; // Less than + case 2: CSETMw(x2, cLS); break; // Less or equal case 3: CSETMw(x2, cVS); break; // NaN - case 4: CSETMw(x2, cNE); break; // Not Equal + case 4: CSETMw(x2, cNE); break; // Not Equal or unordered case 5: CSETMw(x2, cCS); break; // Greater or equal or unordered - case 6: CSETMw(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted) + case 6: CSETMw(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted) case 7: CSETMw(x2, cVC); break; // not NaN } VMOVQSfrom(v0, 0, x2); diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index 7bf3c99e..eff4ca5f 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -218,10 +218,10 @@ int RunF20F(x64emu_t *emu, rex_t rex) tmp8s = 0; switch(tmp8u&7) { case 0: tmp8s=(GX->d[0] == EX->d[0]); break; - case 1: tmp8s=isless(GX->d[0], EX->d[0]); break; - case 2: tmp8s=islessequal(GX->d[0], EX->d[0]); break; + case 1: tmp8s=isless(GX->d[0], EX->d[0]) && !(isnan(GX->d[0]) || isnan(EX->d[0])); break; + case 2: tmp8s=islessequal(GX->d[0], EX->d[0]) && !(isnan(GX->d[0]) || isnan(EX->d[0])); break; case 3: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]); break; - case 4: tmp8s=(GX->d[0] != EX->d[0]); break; + case 4: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || (GX->d[0] != EX->d[0]); break; case 5: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreaterequal(GX->d[0], EX->d[0]); break; case 6: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreater(GX->d[0], EX->d[0]); break; case 7: tmp8s=!isnan(GX->d[0]) && !isnan(EX->d[0]); break; diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index 1960238e..7cc7add5 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -318,10 +318,10 @@ int RunF30F(x64emu_t *emu, rex_t rex) tmp8s = 0; switch(tmp8u&7) { case 0: tmp8s=(GX->f[0] == EX->f[0]); break; - case 1: tmp8s=isless(GX->f[0], EX->f[0]); break; - case 2: tmp8s=islessequal(GX->f[0], EX->f[0]); break; + case 1: tmp8s=isless(GX->f[0], EX->f[0]) && !(isnan(GX->f[0]) || isnan(EX->f[0])); break; + case 2: tmp8s=islessequal(GX->f[0], EX->f[0]) && !(isnan(GX->f[0]) || isnan(EX->f[0])); break; case 3: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]); break; - case 4: tmp8s=(GX->f[0] != EX->f[0]); break; + case 4: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || (GX->f[0] != EX->f[0]); break; case 5: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreaterequal(GX->f[0], EX->f[0]); break; case 6: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreater(GX->f[0], EX->f[0]); break; case 7: tmp8s=!isnan(GX->f[0]) && !isnan(EX->f[0]); break; |