about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-07-06 14:23:57 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-07-06 14:23:57 +0200
commitcb73eaf7768cd765cb242bb4526c9ce998e4d82d (patch)
tree2c2ed253027ad78ead5271bba67f7558d8062e3a
parentbb38d8d1ca3289422b52b2eb3a89a305afd88436 (diff)
downloadbox64-cb73eaf7768cd765cb242bb4526c9ce998e4d82d.tar.gz
box64-cb73eaf7768cd765cb242bb4526c9ce998e4d82d.zip
Work on CMPSS and CMPSD ([DYNAREC] too)
-rwxr-xr-xsrc/dynarec/dynarec_arm64_f20f.c11
-rwxr-xr-xsrc/dynarec/dynarec_arm64_f30f.c11
-rw-r--r--src/emu/x64runf20f.c2
-rw-r--r--tests/ref16.txt99
-rwxr-xr-xtests/test16bin16648 -> 30344 bytes
-rw-r--r--tests/test16.c154
6 files changed, 262 insertions, 15 deletions
diff --git a/src/dynarec/dynarec_arm64_f20f.c b/src/dynarec/dynarec_arm64_f20f.c
index ef709d02..4064b004 100755
--- a/src/dynarec/dynarec_arm64_f20f.c
+++ b/src/dynarec/dynarec_arm64_f20f.c
@@ -288,14 +288,13 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                 FCMPD(v0, v1);

             }

             switch(u8&7) {

-                case 0: CSETMx(x2, cEQ); break;   // Equal

-                case 1: CSETMx(x2, cMI); break;   // Less than

-                case 2: //CSETMx(x2, cLE); break;   // Less or equal (or unordered on ARM64, not on x86...)

-                        CSETMx(x2, cPL); CSINVx(x2, xZR, x2, cEQ); break;   // so use a 2 step here, but 1st test inverted because 2nd step invert again

+                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 3: CSETMx(x2, cVS); break;   // NaN

-                case 4: CSETMx(x2, cNE); break;   // Not Equal (or unordered on ARM, not on X86...)

+                case 4: CSETMx(x2, cNE); break;   // Not Equal

                 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 unordereded or less than (inverted)

+                case 6: CSETMx(x2, cLT); 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 2df33bcf..b8479d5c 100755
--- a/src/dynarec/dynarec_arm64_f30f.c
+++ b/src/dynarec/dynarec_arm64_f30f.c
@@ -376,14 +376,13 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                 FCMPS(v0, v1);

             }

             switch(u8&7) {

-                case 0: CSETMw(x2, cEQ); break;   // Equal

-                case 1: CSETMw(x2, cMI); break;   // Less than

-                case 2: //CSETMw(x2, cLE); break;   // Less or equal (or unordered on ARM64, not on x86...)

-                        CSETMw(x2, cPL); CSINVw(x2, xZR, x2, cEQ); break;   // so use a 2 step here, but 1st test inverted because 2nd step invert again

+                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 3: CSETMw(x2, cVS); break;   // NaN

-                case 4: CSETMw(x2, cNE); break;   // Not Equal (or unordered on ARM, not on X86...)

+                case 4: CSETMw(x2, cNE); break;   // Not Equal

                 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 unordereded or less than (inverted)

+                case 6: CSETMw(x2, cLT); 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 766a69f8..7bf3c99e 100644
--- a/src/emu/x64runf20f.c
+++ b/src/emu/x64runf20f.c
@@ -212,7 +212,7 @@ int RunF20F(x64emu_t *emu, rex_t rex)
         

     case 0xC2:  /* CMPSD Gx, Ex, Ib */

         nextop = F8;

-        GETEX(0);

+        GETEX(1);

         GETGX;

         tmp8u = F8;

         tmp8s = 0;

diff --git a/tests/ref16.txt b/tests/ref16.txt
index 4f5916e0..75b0fa8d 100644
--- a/tests/ref16.txt
+++ b/tests/ref16.txt
@@ -9,3 +9,102 @@ ucomiss nan, 1.000000 => 0x247
 ucomiss 1.000000, 1.000000 => 0x242
 ucomiss inf, inf => 0x242
 ucomiss nan, nan => 0x247
+ucomisd 1.000000, 2.000000 => 0x202
+ucomisd 2.000000, 1.000000 => 0x203
+ucomisd 1.000000, inf => 0x202
+ucomisd inf, 1.000000 => 0x203
+ucomisd 1.000000, -inf => 0x203
+ucomisd -inf, 1.000000 => 0x202
+ucomisd 1.000000, nan => 0x247
+ucomisd nan, 1.000000 => 0x247
+ucomisd 1.000000, 1.000000 => 0x242
+ucomisd inf, inf => 0x242
+ucomisd nan, nan => 0x247
+cmpsd 1.000000, 2.000000, 0 => 0x0
+cmpsd 2.000000, 1.000000, 0 => 0x0
+cmpsd 1.000000, inf, 0 => 0x0
+cmpsd inf, 1.000000, 0 => 0x0
+cmpsd 1.000000, -inf, 0 => 0x0
+cmpsd -inf, 1.000000, 0 => 0x0
+cmpsd 1.000000, nan, 0 => 0x0
+cmpsd nan, 1.000000, 0 => 0x0
+cmpsd 1.000000, 1.000000, 0 => 0xffffffffffffffff
+cmpsd inf, inf, 0 => 0xffffffffffffffff
+cmpsd nan, nan, 0 => 0x0
+cmpsd 1.000000, 2.000000, 1 => 0xffffffffffffffff
+cmpsd 2.000000, 1.000000, 1 => 0x0
+cmpsd 1.000000, inf, 1 => 0xffffffffffffffff
+cmpsd inf, 1.000000, 1 => 0x0
+cmpsd 1.000000, -inf, 1 => 0x0
+cmpsd -inf, 1.000000, 1 => 0xffffffffffffffff
+cmpsd 1.000000, nan, 1 => 0x0
+cmpsd nan, 1.000000, 1 => 0x0
+cmpsd 1.000000, 1.000000, 1 => 0x0
+cmpsd inf, inf, 1 => 0x0
+cmpsd nan, nan, 1 => 0x0
+cmpsd 1.000000, 2.000000, 2 => 0xffffffffffffffff
+cmpsd 2.000000, 1.000000, 2 => 0x0
+cmpsd 1.000000, inf, 2 => 0xffffffffffffffff
+cmpsd inf, 1.000000, 2 => 0x0
+cmpsd 1.000000, -inf, 2 => 0x0
+cmpsd -inf, 1.000000, 2 => 0xffffffffffffffff
+cmpsd 1.000000, nan, 2 => 0x0
+cmpsd nan, 1.000000, 2 => 0x0
+cmpsd 1.000000, 1.000000, 2 => 0xffffffffffffffff
+cmpsd inf, inf, 2 => 0xffffffffffffffff
+cmpsd nan, nan, 2 => 0x0
+cmpsd 1.000000, 2.000000, 3 => 0x0
+cmpsd 2.000000, 1.000000, 3 => 0x0
+cmpsd 1.000000, inf, 3 => 0x0
+cmpsd inf, 1.000000, 3 => 0x0
+cmpsd 1.000000, -inf, 3 => 0x0
+cmpsd -inf, 1.000000, 3 => 0x0
+cmpsd 1.000000, nan, 3 => 0xffffffffffffffff
+cmpsd nan, 1.000000, 3 => 0xffffffffffffffff
+cmpsd 1.000000, 1.000000, 3 => 0x0
+cmpsd inf, inf, 3 => 0x0
+cmpsd nan, nan, 3 => 0xffffffffffffffff
+cmpsd 1.000000, 2.000000, 4 => 0xffffffffffffffff
+cmpsd 2.000000, 1.000000, 4 => 0xffffffffffffffff
+cmpsd 1.000000, inf, 4 => 0xffffffffffffffff
+cmpsd inf, 1.000000, 4 => 0xffffffffffffffff
+cmpsd 1.000000, -inf, 4 => 0xffffffffffffffff
+cmpsd -inf, 1.000000, 4 => 0xffffffffffffffff
+cmpsd 1.000000, nan, 4 => 0xffffffffffffffff
+cmpsd nan, 1.000000, 4 => 0xffffffffffffffff
+cmpsd 1.000000, 1.000000, 4 => 0x0
+cmpsd inf, inf, 4 => 0x0
+cmpsd nan, nan, 4 => 0xffffffffffffffff
+cmpsd 1.000000, 2.000000, 5 => 0x0
+cmpsd 2.000000, 1.000000, 5 => 0xffffffffffffffff
+cmpsd 1.000000, inf, 5 => 0x0
+cmpsd inf, 1.000000, 5 => 0xffffffffffffffff
+cmpsd 1.000000, -inf, 5 => 0xffffffffffffffff
+cmpsd -inf, 1.000000, 5 => 0x0
+cmpsd 1.000000, nan, 5 => 0xffffffffffffffff
+cmpsd nan, 1.000000, 5 => 0xffffffffffffffff
+cmpsd 1.000000, 1.000000, 5 => 0xffffffffffffffff
+cmpsd inf, inf, 5 => 0xffffffffffffffff
+cmpsd nan, nan, 5 => 0xffffffffffffffff
+cmpsd 1.000000, 2.000000, 6 => 0x0
+cmpsd 2.000000, 1.000000, 6 => 0xffffffffffffffff
+cmpsd 1.000000, inf, 6 => 0x0
+cmpsd inf, 1.000000, 6 => 0xffffffffffffffff
+cmpsd 1.000000, -inf, 6 => 0xffffffffffffffff
+cmpsd -inf, 1.000000, 6 => 0x0
+cmpsd 1.000000, nan, 6 => 0xffffffffffffffff
+cmpsd nan, 1.000000, 6 => 0xffffffffffffffff
+cmpsd 1.000000, 1.000000, 6 => 0x0
+cmpsd inf, inf, 6 => 0x0
+cmpsd nan, nan, 6 => 0xffffffffffffffff
+cmpsd 1.000000, 2.000000, 7 => 0xffffffffffffffff
+cmpsd 2.000000, 1.000000, 7 => 0xffffffffffffffff
+cmpsd 1.000000, inf, 7 => 0xffffffffffffffff
+cmpsd inf, 1.000000, 7 => 0xffffffffffffffff
+cmpsd 1.000000, -inf, 7 => 0xffffffffffffffff
+cmpsd -inf, 1.000000, 7 => 0xffffffffffffffff
+cmpsd 1.000000, nan, 7 => 0x0
+cmpsd nan, 1.000000, 7 => 0x0
+cmpsd 1.000000, 1.000000, 7 => 0xffffffffffffffff
+cmpsd inf, inf, 7 => 0xffffffffffffffff
+cmpsd nan, nan, 7 => 0x0
diff --git a/tests/test16 b/tests/test16
index af645769..6f9a4b30 100755
--- a/tests/test16
+++ b/tests/test16
Binary files differdiff --git a/tests/test16.c b/tests/test16.c
index 2b312834..4096de18 100644
--- a/tests/test16.c
+++ b/tests/test16.c
@@ -5,6 +5,7 @@
 #include <stdint.h>
 #include <math.h>
 
+#if defined(__x86_64__)
 uint64_t _ucomiss_(float a, float b)
 {
     uint64_t ret;
@@ -13,11 +14,65 @@ uint64_t _ucomiss_(float a, float b)
     "pushf\n"
     "pop %%rax"
     :"=a" (ret)::"xmm0","xmm1","cc");
-
     return ret;
 }
+uint64_t _ucomisd_(double a, double b)
+{
+    uint64_t ret;
+    asm volatile (
+    "ucomisd %%xmm0, %%xmm1\n"
+    "pushf\n"
+    "pop %%rax"
+    :"=a" (ret)::"xmm0","xmm1","cc");
+    return ret;
+}
+#define GO(n) \
+uint64_t _cmpsd_##n##_(double a, double b) \
+{ \
+    uint64_t ret; \
+    asm volatile ( \
+    "cmpsd $" #n ", %%xmm1, %%xmm0\n" \
+    "movq %%xmm0, %%rax" \
+    :"=a" (ret)::"xmm0","xmm1","cc"); \
+    return ret; \
+}
+GO(0)
+GO(1)
+GO(2)
+GO(3)
+GO(4)
+GO(5)
+GO(6)
+GO(7)
+#undef GO
+#else
+uint64_t _ucomiss_(float a, float b)
+{
+    uint32_t ret;
+    asm volatile (
+    "movss %1, %%xmm0\n"
+    "movss %2, %%xmm1\n"
+    "ucomiss %%xmm0, %%xmm1\n"
+    "pushf\n"
+    "pop %%eax"
+    :"=a" (ret):"m"(a), "m"(b):"xmm0", "xmm1", "cc");
+    return ret;
+}
+uint64_t _ucomisd_(double a, double b)
+{
+    uint32_t ret;
+    asm volatile (
+    "movsd %1, %%xmm0\n"
+    "movsd %2, %%xmm1\n"
+    "ucomisd %%xmm0, %%xmm1\n"
+    "pushf\n"
+    "pop %%eax"
+    :"=a" (ret):"m"(a), "m"(b):"xmm0", "xmm1", "cc");
+    return ret;
+}
+#endif
 
-int main(int argc, const char** argv)
+void test_ucomiss()
 {
  float a, b;
  uint64_t flags;
@@ -50,6 +105,101 @@ int main(int argc, const char** argv)
  a = b = NAN;
  flags = _ucomiss_(a, b);
  printf("ucomiss %f, %f => 0x%lx\n", a, b, flags);
+}
+
+void test_ucomisd()
+{
+ double a, b;
+ uint64_t flags;
+ a = 1.0; b = 2.0;
+ flags = _ucomisd_(a, b);
+ printf("ucomisd %f, %f => 0x%lx\n", a, b, flags);
+ flags = _ucomisd_(b, a);
+ printf("ucomisd %f, %f => 0x%lx\n", b, a, flags);
+ b = INFINITY;
+ flags = _ucomisd_(a, b);
+ printf("ucomisd %f, %f => 0x%lx\n", a, b, flags);
+ flags = _ucomisd_(b, a);
+ printf("ucomisd %f, %f => 0x%lx\n", b, a, flags);
+ b = -INFINITY;
+ flags = _ucomisd_(a, b);
+ printf("ucomisd %f, %f => 0x%lx\n", a, b, flags);
+ flags = _ucomisd_(b, a);
+ printf("ucomisd %f, %f => 0x%lx\n", b, a, flags);
+ b = NAN;
+ flags = _ucomisd_(a, b);
+ printf("ucomisd %f, %f => 0x%lx\n", a, b, flags);
+ flags = _ucomisd_(b, a);
+ printf("ucomisd %f, %f => 0x%lx\n", b, a, flags);
+ b = a;
+ flags = _ucomisd_(a, b);
+ printf("ucomisd %f, %f => 0x%lx\n", a, b, flags);
+ a = b = INFINITY;
+ flags = _ucomisd_(a, b);
+ printf("ucomisd %f, %f => 0x%lx\n", a, b, flags);
+ a = b = NAN;
+ flags = _ucomisd_(a, b);
+ printf("ucomisd %f, %f => 0x%lx\n", a, b, flags);
+}
+#if defined(__x86_64__)
+#define GO(n) \
+void test_cmpsd_##n() \
+{ \
+ double a, b; \
+ uint64_t flags; \
+ a = 1.0; b = 2.0; \
+ flags = _cmpsd_##n##_(a, b); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", a, b, flags); \
+ flags = _cmpsd_##n##_(b, a); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", b, a, flags); \
+ b = INFINITY; \
+ flags = _cmpsd_##n##_(a, b); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", a, b, flags); \
+ flags = _cmpsd_##n##_(b, a); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", b, a, flags); \
+ b = -INFINITY; \
+ flags = _cmpsd_##n##_(a, b); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", a, b, flags); \
+ flags = _cmpsd_##n##_(b, a); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", b, a, flags); \
+ b = NAN; \
+ flags = _cmpsd_##n##_(a, b); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", a, b, flags); \
+ flags = _cmpsd_##n##_(b, a); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", b, a, flags); \
+ b = a; \
+ flags = _cmpsd_##n##_(a, b); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", a, b, flags); \
+ a = b = INFINITY; \
+ flags = _cmpsd_##n##_(a, b); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", a, b, flags); \
+ a = b = NAN; \
+ flags = _cmpsd_##n##_(a, b); \
+ printf("cmpsd %f, %f, " #n " => 0x%lx\n", a, b, flags); \
+}
+GO(0)
+GO(1)
+GO(2)
+GO(3)
+GO(4)
+GO(5)
+GO(6)
+GO(7)
+#endif
+int main(int argc, const char** argv)
+{
+ test_ucomiss();
+ test_ucomisd();
+ #if defined(__x86_64__)
+ test_cmpsd_0();
+ test_cmpsd_1();
+ test_cmpsd_2();
+ test_cmpsd_3();
+ test_cmpsd_4();
+ test_cmpsd_5();
+ test_cmpsd_6();
+ test_cmpsd_7();
+ #endif
 
  return 0;
 }