about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-11-07 15:06:55 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-11-07 15:06:55 +0100
commitf5c9439f9110fcb4fde3c7db9f68be7c107b17f6 (patch)
treef0094dbbd242c7bc4526d61c2a1d48717f00324e /src
parentf73e4193f032713529e26c4537e5fac44147c040 (diff)
downloadbox64-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-xsrc/dynarec/dynarec_arm64_f20f.c30
-rwxr-xr-xsrc/dynarec/dynarec_arm64_f30f.c28
-rw-r--r--src/emu/x64runf20f.c6
-rw-r--r--src/emu/x64runf30f.c6
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;