about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_emitter.h8
-rwxr-xr-xsrc/dynarec/arm64_printer.c11
-rwxr-xr-xsrc/dynarec/dynarec_arm64_660f.c13
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h40
4 files changed, 55 insertions, 17 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index 8dd42699..8078169a 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -365,6 +365,7 @@
 #define MOV_toSP(Rm)                    ADDx_U12(xSP, Rm, 0)
 #define BICx(Rd, Rn, Rm)                EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
 #define BICw(Rd, Rn, Rm)                EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
+#define BICw_LSL(Rd, Rn, Rm, lsl)       EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
 #define BICSx(Rd, Rn, Rm)               EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
 #define BICSw(Rd, Rn, Rm)               EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
 #define BICxw(Rd, Rn, Rm)               EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
@@ -644,5 +645,12 @@
 #define FSQRTS(Sd, Sn)              EMIT(FSQRT_scalar(0b00, Sn, Sd))
 #define FSQRTD(Dd, Dn)              EMIT(FSQRT_scalar(0b01, Dn, Dd))
 
+// CMP
+#define FCMP_scalar(type, Rn, Rm, opc)  (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | 0b1000<<10 | (Rn)<<5 | (opc)<<3)
+#define FCMPS(Sn, Sm)               EMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
+#define FCMPD(Dn, Dm)               EMIT(FCMP_scalar(0b01, Dn, Dm, 0b00))
+#define FCMPS_0(Sn)                 EMIT(FCMP_scalar(0b00, 0, Sn, 0b01))
+#define FCMPD_0(Dn)                 EMIT(FCMP_scalar(0b01, 0, Dn, 0b01))
+
 
 #endif  //__ARM64_EMITTER_H__
diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c
index a8f44fde..90d6ac2c 100755
--- a/src/dynarec/arm64_printer.c
+++ b/src/dynarec/arm64_printer.c
@@ -856,6 +856,17 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         return buff;

     }

 

+    //CMP

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

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

+        if(opc==1)

+            snprintf(buff, sizeof(buff), "FCMP %c%d, #0.0", s, Rn);

+        else

+            snprintf(buff, sizeof(buff), "FCMP %c%d, %c%d", s, Rn, s, Rm);

+        return buff;

+    }

+

+

     snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));

     return buff;

 }
\ No newline at end of file
diff --git a/src/dynarec/dynarec_arm64_660f.c b/src/dynarec/dynarec_arm64_660f.c
index 19f432ea..4ecb8f1c 100755
--- a/src/dynarec/dynarec_arm64_660f.c
+++ b/src/dynarec/dynarec_arm64_660f.c
@@ -98,6 +98,19 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             }

             break;

 

+        case 0x2E:

+            // no special check...

+        case 0x2F:

+            if(opcode==0x2F) {INST_NAME("COMISD Gx, Ex");} else {INST_NAME("UCOMISD Gx, Ex");}

+            SETFLAGS(X_ALL, SF_SET);

+            nextop = F8;

+            gd = ((nextop&0x38)>>3) + (rex.r<<3);

+            v0 = sse_get_reg(dyn, ninst, x1, gd);

+            GETEX(q0, 0);

+            FCMPD(v0, q0);

+            FCOMI(x1, x2);

+            break;

+

         #define GO(GETFLAGS, NO, YES, F)            \

             READFLAGS(F);                           \

             GETFLAGS;                               \

diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index c814d89f..e629c9f9 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -296,35 +296,41 @@
 #define IFXN(A, B)  if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
 
 // Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
-#define FCOM(s1, s2)    \
-    VMRS_APSR();    /* 0b0100011100000000 */                                    \
-    LDRH_IMM8(s1, xEmu, offsetof(x64emu_t, sw));   /*offset is 8bits right?*/   \
-    BIC_IMM8(s1, s1, 0b01000111, 12);                                           \
-    ORR_IMM8_COND(cVS, s1, s1, 0b01000101, 12); /* unordered */                 \
-    ORR_IMM8_COND(cEQ, s1, s1, 0b01000000, 12); /* equal */                     \
-    ORR_IMM8_COND(cMI, s1, s1, 0b00000001, 12); /* less than */                 \
-    /* greater than leave 0 */                                                  \
-    STRH_IMM8(s1, xEmu, offsetof(x64emu_t, sw))
+#define FCOM(s1, s2, s3)                                                    \
+    LDRH_U12(s3, xEmu, offsetof(x64emu_t, sw));   /*offset is 8bits right?*/\
+    MOV32w(s1, 0b01000111);                                                 \
+    BICw_REG_LSL(s3, s3, s1, 8);                                            \
+    CSETw(s1, cMI); /* 1 if less than, 0 else */                            \
+    MOV32w(s2, 0b01000101); /* unordered */                                 \
+    CSELw(s1, s2, s1, cVS);                                                 \
+    MOV32w(s2, 0b01000000); /* zero */                                      \
+    CSELw(s1, s2, s1, cEQ);                                                 \
+    /* greater than leave 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)    \
     IFX(X_CF|X_PF|X_ZF|X_PEND) {                                            \
-        VMRS_APSR();    /* 0b111 */                                         \
-        BIC_IMM8(xFlags, xFlags, 0b1000101, 0);                             \
-        ORR_IMM8_COND(cVS, xFlags, xFlags, 0b01000101, 0); /* unordered */  \
-        ORR_IMM8_COND(cEQ, xFlags, xFlags, 0b01000000, 0); /* zero */       \
-        ORR_IMM8_COND(cMI, xFlags, xFlags, 0b00000001, 0); /* less than */  \
+        MOV32w(s1, 0b01000101);                                             \
+        BICw_REG(xFlags, xFlags, s1);                                       \
+        CSETw(s1, cMI); /* 1 if less than, 0 else */                        \
+        MOV32w(s2, 0b01000101); /* unordered */                             \
+        CSELw(s1, s2, s1, cVS);                                             \
+        MOV32w(s2, 0b01000000); /* zero */                                  \
+        CSELw(s1, s2, s1, cEQ);                                             \
         /* greater than leave 0 */                                          \
+        ORRw_REG(xFlags, xFlags, s1);                                       \
     }                                                                       \
     SET_DFNONE(s1);                                                         \
     IFX(X_OF|X_PEND) {                                                      \
-        BFC(xFlags, F_OF, 1);                                               \
+        BFCw(xFlags, F_OF, 1);                                              \
     }                                                                       \
     IFX(X_AF|X_PEND) {                                                      \
-        BFC(xFlags, F_AF, 1);                                               \
+        BFCw(xFlags, F_AF, 1);                                              \
     }                                                                       \
     IFX(X_SF|X_PEND) {                                                      \
-        BFC(xFlags, F_SF, 1);                                               \
+        BFCw(xFlags, F_SF, 1);                                              \
     }                                                                       \