about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-06-06 13:47:14 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-06-06 13:47:14 +0200
commit1612687acfd6200515fc38fd46180f09f5a41661 (patch)
tree6aee8c56bf64a97f80d6cc5deb94da277e6ed0a7 /src
parent67d587cd9bfd5d8594df7ec1ba78ebe002b7dbee (diff)
downloadbox64-1612687acfd6200515fc38fd46180f09f5a41661.tar.gz
box64-1612687acfd6200515fc38fd46180f09f5a41661.zip
[ARM64_DYNAREC] Fixed VCMPSS opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
index 3391a293..816b695c 100644
--- a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
@@ -348,6 +348,56 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
             YMM0(gd);
             break;
 
+        case 0xE6:
+            INST_NAME("VCVTPD2DQ Gx, Ex");
+            nextop = F8;
+            u8 = sse_setround(dyn, ninst, x1, x2, x6);
+            for(int l=0; l<1+vex.l; ++l) {
+                if(!l) {
+                    GETEX_Y(v1, 0, 0);
+                    GETGX_empty(v0);
+                } else {
+                    if(box64_dynarec_fastround)
+                        d0 = fpu_get_scratch(dyn, ninst);
+                    GETEY(v1);
+                }
+                if(box64_dynarec_fastround) {
+                    VFRINTIDQ(v0, v1);
+                    VFCVTNSQD(v0, v0);  // convert double -> int64
+                    if(!l)
+                        SQXTN_32(v0, v0);   // convert int64 -> int32 with saturation in lower part, RaZ high part
+                    else
+                        SQXTN2_32(v0, d0);   // convert int64 -> int32 with saturation in higher part
+                } else {
+                    if(!l) {
+                        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, ninst);
+                    }
+                    for(int i=0; i<2; ++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
+                        TSTw_mask(x5, 0, 0);    // mask = 1 = FPSR_IOC
+                        CSELx(x1, x1, x4, cEQ);
+                        VMOVQSfrom(v0, i+l*2, x1);
+                    }
+                    if(!vex.l && !l) VMOVQDfrom(v0, 1, xZR);
+                }
+            }
+            x87_restoreround(dyn, ninst, u8);
+            YMM0(gd);
+            break;
+
         default:
             DEFAULT;
     }