about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-04-07 10:29:52 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-04-07 10:29:52 +0200
commit14695faa43b34bc4d81a8fc0d3756a2f7f60b398 (patch)
tree122f6472baa1b6d44415cc26a6c2609e982fa27d /src
parent1159c0530bba39bd293c146b313bfd5968c9efa0 (diff)
downloadbox64-14695faa43b34bc4d81a8fc0d3756a2f7f60b398.tar.gz
box64-14695faa43b34bc4d81a8fc0d3756a2f7f60b398.zip
[ARM64_DYNAREC] Handling of FASTROUND=0 for F2 0F E6 opcode
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64/arm64_printer.c14
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_f20f.c38
2 files changed, 46 insertions, 6 deletions
diff --git a/src/dynarec/arm64/arm64_printer.c b/src/dynarec/arm64/arm64_printer.c
index 9fe7535d..55c06494 100755
--- a/src/dynarec/arm64/arm64_printer.c
+++ b/src/dynarec/arm64/arm64_printer.c
@@ -1108,6 +1108,20 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         return buff;

     }

 

+    // FRINTI

+    if(isMask(opcode, "0Q1011101f100001100110nnnnnddddd", &a)) {

+        char s = a.Q?'V':'D';

+        char d = sf?'D':'S';

+        int n = (a.Q && !sf)?4:2;

+        snprintf(buff, sizeof(buff), "VFRINTI %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d);

+        return buff;

+    }

+    if(isMask(opcode, "00011110ff100111110000nnnnnddddd", &a)) {

+        char s = (sf==0)?'S':((sf==1)?'D':'?');

+        snprintf(buff, sizeof(buff), "FRINTI %c%d, %c%d", s, Rd, s, Rn);

+        return buff;

+    }

+

     //CMP

     if(isMask(opcode, "00011110ff1mmmmm001000nnnnn0c000", &a)) {

         char s = (sf==0)?'S':((sf==1)?'D':'?');

diff --git a/src/dynarec/arm64/dynarec_arm64_f20f.c b/src/dynarec/arm64/dynarec_arm64_f20f.c
index 144ae8d3..31745377 100755
--- a/src/dynarec/arm64/dynarec_arm64_f20f.c
+++ b/src/dynarec/arm64/dynarec_arm64_f20f.c
@@ -422,13 +422,39 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
         case 0xE6:

             INST_NAME("CVTPD2DQ Gx, Ex");

             nextop = F8;

-            GETEXSD(v1, 0, 0);

+            GETEX(v1, 0, 0);

             GETGX_empty(v0);

-            u8 = sse_setround(dyn, ninst, x1, x2, x3);

-            VFRINTIDQ(v0, v1);

-            x87_restoreround(dyn, ninst, u8);

-            VFCVTNSQD(v0, v0);  // convert double -> int64

-            SQXTN_32(v0, v0);   // convert int64 -> int32 with saturation in lower part, RaZ high part

+            if(box64_dynarec_fastround) {

+                u8 = sse_setround(dyn, ninst, x1, x2, x3);

+                VFRINTIDQ(v0, v1);

+                x87_restoreround(dyn, ninst, u8);

+                VFCVTNSQD(v0, v0);  // convert double -> int64

+                SQXTN_32(v0, v0);   // convert int64 -> int32 with saturation in lower part, RaZ high part

+            } else {

+                u8 = sse_setround(dyn, ninst, x1, x2, x3);

+                MRS_fpsr(x5);

+                BFCw(x5, FPSR_IOC, 1);   // reset IOC bit

+                MSR_fpsr(x5);

+                ORRw_mask(x4, xZR, 1, 0);    //0x80000000

+                d0 = fpu_get_scratch(dyn);

+                for(int i=1; i>=0; --i) {

+                    BFCw(x5, FPSR_IOC, 1);   // reset IOC bit

+                    MSR_fpsr(x5);

+                    if(i) {

+                        VMOVeD(d0, 0, v1, i);

+                        FRINTID(d0, d0);

+                    } else {

+                        FRINTID(d0, v1);

+                    }

+                    FCVTZSwD(x1, d0);

+                    MRS_fpsr(x5);   // get back FPSR to check the IOC bit

+                    TBZ(x5, FPSR_IOC, 4+4);

+                    MOVw_REG(x1, x4);

+                    VMOVQSfrom(v0, i, x1);

+                }

+                x87_restoreround(dyn, ninst, u8);

+                VMOVQDfrom(v0, 1, xZR);

+            }

             break;

 

         case 0xF0: