about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-04-05 14:26:57 +0800
committerGitHub <noreply@github.com>2023-04-05 08:26:57 +0200
commit77cc2a6b8e98a2782bd9b0ea7e2b08f43e59a258 (patch)
tree46da02e31b4d531ccc153c933587958f72bd5d45 /src
parente58ff89044215e24ab74f7dbdfef57ce7e2c8ee9 (diff)
downloadbox64-77cc2a6b8e98a2782bd9b0ea7e2b08f43e59a258.tar.gz
box64-77cc2a6b8e98a2782bd9b0ea7e2b08f43e59a258.zip
[INTERP] Added 66 0F 2B MOVNTPD opcode & fixed some edge cases (#668)
* [INTERP] Fixed shift amount issues

* [INTERP] Added 66 0F 2B MOVNTPD opcode

* [INTERP] Fixed float to int convert issues
Diffstat (limited to 'src')
-rw-r--r--src/emu/x64run660f.c53
-rw-r--r--src/emu/x64runf20f.c30
-rw-r--r--src/emu/x64runf30f.c13
3 files changed, 61 insertions, 35 deletions
diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c
index 3e164c04..f67b7738 100644
--- a/src/emu/x64run660f.c
+++ b/src/emu/x64run660f.c
@@ -193,7 +193,13 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         GX->d[0] = EM->sd[0];

         GX->d[1] = EM->sd[1];

         break;

-

+    case 0x2B:                      /* MOVNTPD Ex, Gx */

+        nextop = F8;

+        GETEX(0);

+        GETGX;

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

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

+        break;

     case 0x2C:                      /* CVTTPD2PI Gm, Ex */

         nextop = F8;

         GETEX(0);

@@ -1063,24 +1069,27 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         nextop = F8;

         GETEX(0);

         GETGX;

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

-            if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>(int32_t)0x7fffffff || EX->f[i]<(int32_t)0x80000000)

-                GX->sd[i] = 0x80000000;

-            else

-                switch(emu->mxcsr.f.MXCSR_RC) {

-                    case ROUND_Nearest:

-                        GX->sd[i] = nearbyintf(EX->f[i]);

-                        break;

-                    case ROUND_Down:

-                        GX->sd[i] = floorf(EX->f[i]);

-                        break;

-                    case ROUND_Up:

-                        GX->sd[i] = ceilf(EX->f[i]);

-                        break;

-                    case ROUND_Chop:

-                        GX->sd[i] = EX->f[i];

-                        break;

-                }

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

+            switch(emu->mxcsr.f.MXCSR_RC) {

+                case ROUND_Nearest:

+                    tmp64s = nearbyintf(EX->f[i]);

+                    break;

+                case ROUND_Down:

+                    tmp64s = floorf(EX->f[i]);

+                    break;

+                case ROUND_Up:

+                    tmp64s = ceilf(EX->f[i]);

+                    break;

+                case ROUND_Chop:

+                    tmp64s = EX->f[i];

+                    break;

+            }

+            if (tmp64s==(int32_t)tmp64s) {

+                GX->sd[i] = (int32_t)tmp64s;

+            } else {

+                GX->sd[i] = INT32_MIN;

+            }

+        }

         break;

     case 0x5C:                      /* SUBPD Gx, Ex */

         nextop = F8;

@@ -1374,7 +1383,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 tmp8u = F8;

                 if(tmp8u>15)

                     {EX->q[0] = EX->q[1] = 0;}

-                else {

+                else if (tmp8u!=0) {

                     tmp8u*=8;

                     if (tmp8u < 64) {

                         EX->q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));

@@ -1396,7 +1405,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
                 tmp8u = F8;

                 if(tmp8u>15)

                     {EX->q[0] = EX->q[1] = 0;}

-                else {

+                else if (tmp8u!=0) {

                     tmp8u*=8;

                     if (tmp8u < 64) {

                         EX->q[1] = (EX->q[1] << tmp8u) | (EX->q[0] >> (64 - tmp8u));

@@ -2317,4 +2326,4 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         return 0;

     }

     return addr;

-}
\ No newline at end of file
+}

diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c
index d7ce1eee..eb94958d 100644
--- a/src/emu/x64runf20f.c
+++ b/src/emu/x64runf20f.c
@@ -33,6 +33,7 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
     int8_t tmp8s;

     uint8_t tmp8u;

     int32_t tmp32s;

+    int64_t tmp64s0, tmp64s1;

     reg64_t *oped, *opgd;

     sse_regs_t *opex, *opgx, eax1;

     mmx87_regs_t *opgm;

@@ -321,22 +322,33 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         GETGX;

         switch(emu->mxcsr.f.MXCSR_RC) {

             case ROUND_Nearest:

-                GX->sd[0] = nearbyint(EX->d[0]);

-                GX->sd[1] = nearbyint(EX->d[1]);

+                tmp64s0 = nearbyint(EX->d[0]);

+                tmp64s1 = nearbyint(EX->d[1]);

                 break;

             case ROUND_Down:

-                GX->sd[0] = floor(EX->d[0]);

-                GX->sd[1] = floor(EX->d[1]);

+                tmp64s0 = floor(EX->d[0]);

+                tmp64s1 = floor(EX->d[1]);

                 break;

             case ROUND_Up:

-                GX->sd[0] = ceil(EX->d[0]);

-                GX->sd[1] = ceil(EX->d[1]);

+                tmp64s0 = ceil(EX->d[0]);

+                tmp64s1 = ceil(EX->d[1]);

                 break;

             case ROUND_Chop:

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

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

+                tmp64s0 = EX->d[0];

+                tmp64s1 = EX->d[1];

                 break;

         }

+        if (tmp64s0==(int32_t)tmp64s0) {

+            GX->sd[0] = (int32_t)tmp64s0;

+        } else {

+            GX->sd[0] = INT32_MIN;

+        }

+        if (tmp64s1==(int32_t)tmp64s1) {

+            GX->sd[1] = (int32_t)tmp64s1;

+        } else {

+            GX->sd[1] = INT32_MIN;

+        }

+

         GX->q[1] = 0;

         break;

 

@@ -351,4 +363,4 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         return 0;

     }

     return addr;

-}
\ No newline at end of file
+}

diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c
index 4149c94e..e2830c4a 100644
--- a/src/emu/x64runf30f.c
+++ b/src/emu/x64runf30f.c
@@ -33,6 +33,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
     int8_t tmp8s;

     uint8_t tmp8u;

     uint32_t tmp32u;

+    int64_t tmp64s;

     uint64_t tmp64u;

     reg64_t *oped, *opgd;

     sse_regs_t *opex, *opgx, eax1;

@@ -194,10 +195,14 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
         nextop = F8;

         GETEX(0);

         GETGX;

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

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

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

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

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

+            tmp64s = EX->f[i];

+            if (tmp64s==(int32_t)tmp64s) {

+                GX->sd[i] = (int32_t)tmp64s;

+            } else {

+                GX->sd[i] = INT32_MIN;

+            }

+        }

         break;

     case 0x5C:  /* SUBSS Gx, Ex */

         nextop = F8;