about summary refs log tree commit diff stats
path: root/src/dynarec/arm64/dynarec_arm64_helper.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec/arm64/dynarec_arm64_helper.h')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h48
1 files changed, 46 insertions, 2 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 267d873b..77cedbf1 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -880,7 +880,7 @@
 #endif
 
 // Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
-#define FCOM(s1, s2, s3)                                                    \
+#define FCOM(s1, s2, s3, s4, v1, v2, is_f)                                  \
     LDRH_U12(s3, xEmu, offsetof(x64emu_t, sw));   /*offset is 8bits right?*/\
     MOV32w(s1, 0b0100011100000000);                                         \
     BICw_REG(s3, s3, s1);                                                   \
@@ -890,11 +890,33 @@
     CSELw(s1, s2, s1, cEQ);                                                 \
     MOV32w(s2, 0b01000101); /* unordered */                                 \
     CSELw(s1, s2, s1, cVS);                                                 \
+    if(v1||v2) {                                                            \
+        Bcond(cVS, 10*4);                                                   \
+        if(is_f) {                                                          \
+            ORRw_mask(s4, xZR, 12, 10); /*+inf*/                            \
+            FMOVwS(s2, v1);                                                 \
+            CMPSw_REG(s2, s4);                                              \
+            Bcond(cEQ, 5*4); /* same */                                     \
+            FMOVwS(s2, v2);                                                 \
+            ORRw_mask(s4, s4, 1, 0); /*-inf*/                               \
+            CMPSw_REG(s2, s4);                                              \
+        } else {                                                            \
+            ORRx_mask(s4, xZR, 1, 12, 10); /*+inf*/                         \
+            FMOVxD(s2, v1);                                                 \
+            CMPSx_REG(s2, s4);                                              \
+            Bcond(cEQ, 5*4); /* same */                                     \
+            FMOVxD(s2, v2);                                                 \
+            ORRx_mask(s4, s4, 1, 1, 0); /*-inf*/                            \
+            CMPSx_REG(s2, s4);                                              \
+        }                                                                   \
+        Bcond(cNE, 4+4); /* same */                                         \
+        MOVZw(s2, 0);                                                       \
+    }                                                                       \
     ORRw_REG_LSL(s3, s3, s1, 8);                                            \
     STRH_U12(s3, xEmu, offsetof(x64emu_t, sw))
 
 // Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
-#define FCOMI(s1, s2)    \
+#define FCOMI(s1, s2, s4, v1, v2, is_f)                                     \
     IFX(X_OF|X_AF|X_SF|X_PEND) {                                            \
         MOV32w(s2, 0b100011010101);                                         \
         BICw_REG(xFlags, xFlags, s2);                                       \
@@ -914,6 +936,28 @@
         MOV32w(s2, 0b01000000); /* zero */                                  \
         CSELw(s1, s2, s1, cEQ);                                             \
         /* greater than leave 0 */                                          \
+        if(s4) {                                                            \
+            Bcond(cVS, 10*4);                                               \
+            if(is_f) {                                                      \
+                ORRw_mask(s4, xZR, 12, 10); /*+inf*/                        \
+                FMOVwS(s2, v1);                                             \
+                CMPSw_REG(s2, s4);                                          \
+                Bcond(cEQ, 5*4); /* same */                                 \
+                FMOVwS(s2, v2);                                             \
+                ORRw_mask(s4, s4, 1, 0); /*-inf*/                           \
+                CMPSw_REG(s2, s4);                                          \
+            } else {                                                        \
+                ORRx_mask(s4, xZR, 1, 12, 10); /*+inf*/                     \
+                FMOVxD(s2, v1);                                             \
+                CMPSx_REG(s2, s4);                                          \
+                Bcond(cEQ, 5*4); /* same */                                 \
+                FMOVxD(s2, v2);                                             \
+                ORRx_mask(s4, s4, 1, 1, 0); /*-inf*/                        \
+                CMPSx_REG(s2, s4);                                          \
+            }                                                               \
+            Bcond(cNE, 4+4); /* same */                                     \
+            MOVZw(s1, 0);                                                   \
+        }                                                                   \
         ORRw_REG(xFlags, xFlags, s1);                                       \
     }                                                                       \
     SET_DFNONE(s1);                                                         \