about summary refs log tree commit diff stats
path: root/src/dynarec/la64/dynarec_la64_helper.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec/la64/dynarec_la64_helper.h')
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h251
1 files changed, 146 insertions, 105 deletions
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index 630f3873..15f9bb15 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -416,10 +416,10 @@
 #define MARKF2       MARKFi(1)
 #define GETMARKF2    GETMARKFi(1)
 
-#define MARKSEG     dyn->insts[ninst].markseg = dyn->native_size
-#define GETMARKSEG  dyn->insts[ninst].markseg
-#define MARKLOCK    dyn->insts[ninst].marklock = dyn->native_size
-#define GETMARKLOCK dyn->insts[ninst].marklock
+#define MARKSEG      dyn->insts[ninst].markseg = dyn->native_size
+#define GETMARKSEG   dyn->insts[ninst].markseg
+#define MARKLOCK     dyn->insts[ninst].marklock = dyn->native_size
+#define GETMARKLOCK  dyn->insts[ninst].marklock
 #define MARKLOCK2    dyn->insts[ninst].marklock2 = dyn->native_size
 #define GETMARKLOCK2 dyn->insts[ninst].marklock2
 
@@ -553,7 +553,8 @@
 
 #define IFX(A)      if ((dyn->insts[ninst].x64.gen_flags & (A)))
 #define IFXA(A, B)  if ((dyn->insts[ninst].x64.gen_flags & (A)) && (B))
-#define IFX_PENDOR0 if ((dyn->insts[ninst].x64.gen_flags & (X_PEND) || !dyn->insts[ninst].x64.gen_flags))
+#define IFXORNAT(A) if ((dyn->insts[ninst].x64.gen_flags & (A)) || dyn->insts[ninst].nat_flags_fusion)
+#define IFX_PENDOR0 if ((dyn->insts[ninst].x64.gen_flags & (X_PEND) || (!dyn->insts[ninst].x64.gen_flags && !dyn->insts[ninst].nat_flags_fusion)))
 #define IFXX(A)     if ((dyn->insts[ninst].x64.gen_flags == (A)))
 #define IFX2X(A, B) if ((dyn->insts[ninst].x64.gen_flags == (A) || dyn->insts[ninst].x64.gen_flags == (B) || dyn->insts[ninst].x64.gen_flags == ((A) | (B))))
 #define IFXN(A, B)  if ((dyn->insts[ninst].x64.gen_flags & (A) && !(dyn->insts[ninst].x64.gen_flags & (B))))
@@ -639,7 +640,7 @@
             if ((width) == 8) {                                       \
                 ANDI(scratch1, scratch2, 0x80);                       \
             } else {                                                  \
-                SRLI_D(scratch1, scratch2, (width)-1);                \
+                SRLI_D(scratch1, scratch2, (width) - 1);              \
                 if ((width) != 64) ANDI(scratch1, scratch1, 1);       \
             }                                                         \
             BEQZ(scratch1, 8);                                        \
@@ -647,7 +648,7 @@
         }                                                             \
         IFX (X_OF) {                                                  \
             /* of = ((bc >> (width-2)) ^ (bc >> (width-1))) & 0x1; */ \
-            SRLI_D(scratch1, scratch2, (width)-2);                    \
+            SRLI_D(scratch1, scratch2, (width) - 2);                  \
             SRLI_D(scratch2, scratch1, 1);                            \
             XOR(scratch1, scratch1, scratch2);                        \
             ANDI(scratch1, scratch1, 1);                              \
@@ -678,8 +679,29 @@
     }
 #endif
 
+#ifndef READFLAGS_FUSION
+#define READFLAGS_FUSION(A, s1, s2, s3, s4, s5)                                \
+    if (dyn->insts[ninst].nat_flags_fusion)                                    \
+        get_free_scratch(dyn, ninst, &tmp1, &tmp2, &tmp3, s1, s2, s3, s4, s5); \
+    else {                                                                     \
+        tmp1 = s1;                                                             \
+        tmp2 = s2;                                                             \
+        tmp3 = s3;                                                             \
+    }                                                                          \
+    READFLAGS(A)
+#endif
+
+#define NAT_FLAGS_OPS(op1, op2)                    \
+    do {                                           \
+        dyn->insts[ninst + 1].nat_flags_op1 = op1; \
+        dyn->insts[ninst + 1].nat_flags_op2 = op2; \
+    } while (0)
+
+#define NAT_FLAGS_ENABLE_CARRY() dyn->insts[ninst].nat_flags_carry = 1
+#define NAT_FLAGS_ENABLE_SIGN()  dyn->insts[ninst].nat_flags_sign = 1
+
 #ifndef SETFLAGS
-#define SETFLAGS(A, B)                                                                                              \
+#define SETFLAGS(A, B, FUSION)                                                                                      \
     if (dyn->f.pending != SF_SET                                                                                    \
         && ((B) & SF_SUB)                                                                                           \
         && (dyn->insts[ninst].x64.gen_flags & (~(A))))                                                              \
@@ -687,6 +709,14 @@
     if (dyn->insts[ninst].x64.gen_flags) switch (B) {                                                               \
             case SF_SUBSET:                                                                                         \
             case SF_SET: dyn->f.pending = SF_SET; break;                                                            \
+            case SF_SET_DF:                                                                                         \
+                dyn->f.pending = SF_SET;                                                                            \
+                dyn->f.dfnone = 1;                                                                                  \
+                break;                                                                                              \
+            case SF_SET_NODF:                                                                                       \
+                dyn->f.pending = SF_SET;                                                                            \
+                dyn->f.dfnone = 0;                                                                                  \
+                break;                                                                                              \
             case SF_PENDING: dyn->f.pending = SF_PENDING; break;                                                    \
             case SF_SUBSET_PENDING:                                                                                 \
             case SF_SET_PENDING:                                                                                    \
@@ -694,7 +724,8 @@
                 break;                                                                                              \
         }                                                                                                           \
     else                                                                                                            \
-        dyn->f.pending = SF_SET
+        dyn->f.pending = SF_SET;                                                                                    \
+    dyn->insts[ninst].nat_flags_nofusion = (FUSION)
 #endif
 #ifndef JUMP
 #define JUMP(A, C)
@@ -738,23 +769,23 @@
 #define GETIP_(A) TABLE64(0, 0)
 #else
 // put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later...
-#define GETIP(A)                                     \
-    if (dyn->last_ip && ((A)-dyn->last_ip) < 2048) { \
-        uint64_t _delta_ip = (A)-dyn->last_ip;       \
-        dyn->last_ip += _delta_ip;                   \
-        if (_delta_ip) {                             \
-            ADDI_D(xRIP, xRIP, _delta_ip);           \
-        }                                            \
-    } else {                                         \
-        dyn->last_ip = (A);                          \
-        if (dyn->last_ip < 0xffffffff) {             \
-            MOV64x(xRIP, dyn->last_ip);              \
-        } else                                       \
-            TABLE64(xRIP, dyn->last_ip);             \
+#define GETIP(A)                                       \
+    if (dyn->last_ip && ((A) - dyn->last_ip) < 2048) { \
+        uint64_t _delta_ip = (A) - dyn->last_ip;       \
+        dyn->last_ip += _delta_ip;                     \
+        if (_delta_ip) {                               \
+            ADDI_D(xRIP, xRIP, _delta_ip);             \
+        }                                              \
+    } else {                                           \
+        dyn->last_ip = (A);                            \
+        if (dyn->last_ip < 0xffffffff) {               \
+            MOV64x(xRIP, dyn->last_ip);                \
+        } else                                         \
+            TABLE64(xRIP, dyn->last_ip);               \
     }
 #define GETIP_(A)                                         \
-    if (dyn->last_ip && ((A)-dyn->last_ip) < 2048) {      \
-        int64_t _delta_ip = (A)-dyn->last_ip;             \
+    if (dyn->last_ip && ((A) - dyn->last_ip) < 2048) {    \
+        int64_t _delta_ip = (A) - dyn->last_ip;           \
         if (_delta_ip) { ADDI_D(xRIP, xRIP, _delta_ip); } \
     } else {                                              \
         if ((A) < 0xffffffff) {                           \
@@ -862,16 +893,16 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
 #define emit_and32          STEPNAME(emit_and32)
 #define emit_and32c         STEPNAME(emit_and32c)
 #define emit_shl16          STEPNAME(emit_shl16)
-#define emit_shl16c          STEPNAME(emit_shl16c)
+#define emit_shl16c         STEPNAME(emit_shl16c)
 #define emit_shl32          STEPNAME(emit_shl32)
 #define emit_shl32c         STEPNAME(emit_shl32c)
 #define emit_shr8           STEPNAME(emit_shr8)
 #define emit_shr16          STEPNAME(emit_shr16)
-#define emit_shr16c          STEPNAME(emit_shr16c)
+#define emit_shr16c         STEPNAME(emit_shr16c)
 #define emit_shr32          STEPNAME(emit_shr32)
 #define emit_shr32c         STEPNAME(emit_shr32c)
 #define emit_sar16          STEPNAME(emit_sar16)
-#define emit_sar16c          STEPNAME(emit_sar16c)
+#define emit_sar16c         STEPNAME(emit_sar16c)
 #define emit_sar32c         STEPNAME(emit_sar32c)
 #define emit_shld32c        STEPNAME(emit_shld32c)
 #define emit_shrd32c        STEPNAME(emit_shrd32c)
@@ -1054,86 +1085,96 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
 #define MAYUSE(A)
 #endif
 
-#define GOCOND(B, T1, T2)                                                                        \
-    case B + 0x0:                                                                                \
-        INST_NAME(T1 "O " T2);                                                                   \
-        GO(ANDI(x1, xFlags, 1 << F_OF), EQZ, NEZ, X_OF, X64_JMP_JO);                             \
-        break;                                                                                   \
-    case B + 0x1:                                                                                \
-        INST_NAME(T1 "NO " T2);                                                                  \
-        GO(ANDI(x1, xFlags, 1 << F_OF), NEZ, EQZ, X_OF, X64_JMP_JNO);                            \
-        break;                                                                                   \
-    case B + 0x2:                                                                                \
-        INST_NAME(T1 "C " T2);                                                                   \
-        GO(ANDI(x1, xFlags, 1 << F_CF), EQZ, NEZ, X_CF, X64_JMP_JC);                             \
-        break;                                                                                   \
-    case B + 0x3:                                                                                \
-        INST_NAME(T1 "NC " T2);                                                                  \
-        GO(ANDI(x1, xFlags, 1 << F_CF), NEZ, EQZ, X_CF, X64_JMP_JNC);                            \
-        break;                                                                                   \
-    case B + 0x4:                                                                                \
-        INST_NAME(T1 "Z " T2);                                                                   \
-        GO(ANDI(x1, xFlags, 1 << F_ZF), EQZ, NEZ, X_ZF, X64_JMP_JZ);                             \
-        break;                                                                                   \
-    case B + 0x5:                                                                                \
-        INST_NAME(T1 "NZ " T2);                                                                  \
-        GO(ANDI(x1, xFlags, 1 << F_ZF), NEZ, EQZ, X_ZF, X64_JMP_JNZ);                            \
-        break;                                                                                   \
-    case B + 0x6:                                                                                \
-        INST_NAME(T1 "BE " T2);                                                                  \
-        GO(ANDI(x1, xFlags, (1 << F_CF) | (1 << F_ZF)), EQZ, NEZ, X_CF | X_ZF, X64_JMP_JBE);     \
-        break;                                                                                   \
-    case B + 0x7:                                                                                \
-        INST_NAME(T1 "NBE " T2);                                                                 \
-        GO(ANDI(x1, xFlags, (1 << F_CF) | (1 << F_ZF)), NEZ, EQZ, X_CF | X_ZF, X64_JMP_JNBE);    \
-        break;                                                                                   \
-    case B + 0x8:                                                                                \
-        INST_NAME(T1 "S " T2);                                                                   \
-        GO(ANDI(x1, xFlags, 1 << F_SF), EQZ, NEZ, X_SF, X64_JMP_JS);                             \
-        break;                                                                                   \
-    case B + 0x9:                                                                                \
-        INST_NAME(T1 "NS " T2);                                                                  \
-        GO(ANDI(x1, xFlags, 1 << F_SF), NEZ, EQZ, X_SF, X64_JMP_JNS);                            \
-        break;                                                                                   \
-    case B + 0xA:                                                                                \
-        INST_NAME(T1 "P " T2);                                                                   \
-        GO(ANDI(x1, xFlags, 1 << F_PF), EQZ, NEZ, X_PF, X64_JMP_JP);                             \
-        break;                                                                                   \
-    case B + 0xB:                                                                                \
-        INST_NAME(T1 "NP " T2);                                                                  \
-        GO(ANDI(x1, xFlags, 1 << F_PF), NEZ, EQZ, X_PF, X64_JMP_JNP);                            \
-        break;                                                                                   \
-    case B + 0xC:                                                                                \
-        INST_NAME(T1 "L " T2);                                                                   \
-        GO(SRLI_D(x1, xFlags, F_OF - F_SF);                                                      \
-            XOR(x1, x1, xFlags);                                                                 \
-            ANDI(x1, x1, 1 << F_SF), EQZ, NEZ, X_SF | X_OF, X64_JMP_JL);                         \
-        break;                                                                                   \
-    case B + 0xD:                                                                                \
-        INST_NAME(T1 "GE " T2);                                                                  \
-        GO(SRLI_D(x1, xFlags, F_OF - F_SF);                                                      \
-            XOR(x1, x1, xFlags);                                                                 \
-            ANDI(x1, x1, 1 << F_SF), NEZ, EQZ, X_SF | X_OF, X64_JMP_JGE);                        \
-        break;                                                                                   \
-    case B + 0xE:                                                                                \
-        INST_NAME(T1 "LE " T2);                                                                  \
-        GO(SRLI_D(x1, xFlags, F_OF - F_SF);                                                      \
-            XOR(x1, x1, xFlags);                                                                 \
-            ANDI(x1, x1, 1 << F_SF);                                                             \
-            ANDI(x3, xFlags, 1 << F_ZF);                                                         \
-            OR(x1, x1, x3);                                                                      \
-            ANDI(x1, x1, (1 << F_SF) | (1 << F_ZF)), EQZ, NEZ, X_SF | X_OF | X_ZF, X64_JMP_JLE); \
-        break;                                                                                   \
-    case B + 0xF:                                                                                \
-        INST_NAME(T1 "G " T2);                                                                   \
-        GO(SRLI_D(x1, xFlags, F_OF - F_SF);                                                      \
-            XOR(x1, x1, xFlags);                                                                 \
-            ANDI(x1, x1, 1 << F_SF);                                                             \
-            ANDI(x3, xFlags, 1 << F_ZF);                                                         \
-            OR(x1, x1, x3);                                                                      \
-            ANDI(x1, x1, (1 << F_SF) | (1 << F_ZF)), NEZ, EQZ, X_SF | X_OF | X_ZF, X64_JMP_JG);  \
+#define GOCOND(B, T1, T2)                                                                                    \
+    case B + 0x0:                                                                                            \
+        INST_NAME(T1 "O " T2);                                                                               \
+        GO(ANDI(tmp1, xFlags, 1 << F_OF), EQZ, NEZ, _, _, X_OF, X64_JMP_JO);                                 \
+        break;                                                                                               \
+    case B + 0x1:                                                                                            \
+        INST_NAME(T1 "NO " T2);                                                                              \
+        GO(ANDI(tmp1, xFlags, 1 << F_OF), NEZ, EQZ, _, _, X_OF, X64_JMP_JNO);                                \
+        break;                                                                                               \
+    case B + 0x2:                                                                                            \
+        INST_NAME(T1 "C " T2);                                                                               \
+        GO(ANDI(tmp1, xFlags, 1 << F_CF), EQZ, NEZ, GEU, LTU, X_CF, X64_JMP_JC);                             \
+        break;                                                                                               \
+    case B + 0x3:                                                                                            \
+        INST_NAME(T1 "NC " T2);                                                                              \
+        GO(ANDI(tmp1, xFlags, 1 << F_CF), NEZ, EQZ, LTU, GEU, X_CF, X64_JMP_JNC);                            \
+        break;                                                                                               \
+    case B + 0x4:                                                                                            \
+        INST_NAME(T1 "Z " T2);                                                                               \
+        GO(ANDI(tmp1, xFlags, 1 << F_ZF), EQZ, NEZ, NE, EQ, X_ZF, X64_JMP_JZ);                               \
+        break;                                                                                               \
+    case B + 0x5:                                                                                            \
+        INST_NAME(T1 "NZ " T2);                                                                              \
+        GO(ANDI(tmp1, xFlags, 1 << F_ZF), NEZ, EQZ, EQ, NE, X_ZF, X64_JMP_JNZ);                              \
+        break;                                                                                               \
+    case B + 0x6:                                                                                            \
+        INST_NAME(T1 "BE " T2);                                                                              \
+        GO(ANDI(tmp1, xFlags, (1 << F_CF) | (1 << F_ZF)), EQZ, NEZ, GTU, LEU, X_CF | X_ZF, X64_JMP_JBE);     \
+        break;                                                                                               \
+    case B + 0x7:                                                                                            \
+        INST_NAME(T1 "NBE " T2);                                                                             \
+        GO(ANDI(tmp1, xFlags, (1 << F_CF) | (1 << F_ZF)), NEZ, EQZ, LEU, GTU, X_CF | X_ZF, X64_JMP_JNBE);    \
+        break;                                                                                               \
+    case B + 0x8:                                                                                            \
+        INST_NAME(T1 "S " T2);                                                                               \
+        GO(ANDI(tmp1, xFlags, 1 << F_SF), EQZ, NEZ, _, _, X_SF, X64_JMP_JS);                                 \
+        break;                                                                                               \
+    case B + 0x9:                                                                                            \
+        INST_NAME(T1 "NS " T2);                                                                              \
+        GO(ANDI(tmp1, xFlags, 1 << F_SF), NEZ, EQZ, _, _, X_SF, X64_JMP_JNS);                                \
+        break;                                                                                               \
+    case B + 0xA:                                                                                            \
+        INST_NAME(T1 "P " T2);                                                                               \
+        GO(ANDI(tmp1, xFlags, 1 << F_PF), EQZ, NEZ, _, _, X_PF, X64_JMP_JP);                                 \
+        break;                                                                                               \
+    case B + 0xB:                                                                                            \
+        INST_NAME(T1 "NP " T2);                                                                              \
+        GO(ANDI(tmp1, xFlags, 1 << F_PF), NEZ, EQZ, _, _, X_PF, X64_JMP_JNP);                                \
+        break;                                                                                               \
+    case B + 0xC:                                                                                            \
+        INST_NAME(T1 "L " T2);                                                                               \
+        GO(SRLI_D(tmp1, xFlags, F_OF - F_SF);                                                                \
+            XOR(tmp1, tmp1, xFlags);                                                                         \
+            ANDI(tmp1, tmp1, 1 << F_SF), EQZ, NEZ, GE, LT, X_SF | X_OF, X64_JMP_JL);                         \
+        break;                                                                                               \
+    case B + 0xD:                                                                                            \
+        INST_NAME(T1 "GE " T2);                                                                              \
+        GO(SRLI_D(tmp1, xFlags, F_OF - F_SF);                                                                \
+            XOR(tmp1, tmp1, xFlags);                                                                         \
+            ANDI(tmp1, tmp1, 1 << F_SF), NEZ, EQZ, LT, GE, X_SF | X_OF, X64_JMP_JGE);                        \
+        break;                                                                                               \
+    case B + 0xE:                                                                                            \
+        INST_NAME(T1 "LE " T2);                                                                              \
+        GO(SRLI_D(tmp1, xFlags, F_OF - F_SF);                                                                \
+            XOR(tmp1, tmp1, xFlags);                                                                         \
+            ANDI(tmp1, tmp1, 1 << F_SF);                                                                     \
+            ANDI(tmp3, xFlags, 1 << F_ZF);                                                                   \
+            OR(tmp1, tmp1, tmp3);                                                                            \
+            ANDI(tmp1, tmp1, (1 << F_SF) | (1 << F_ZF)), EQZ, NEZ, GT, LE, X_SF | X_OF | X_ZF, X64_JMP_JLE); \
+        break;                                                                                               \
+    case B + 0xF:                                                                                            \
+        INST_NAME(T1 "G " T2);                                                                               \
+        GO(SRLI_D(tmp1, xFlags, F_OF - F_SF);                                                                \
+            XOR(tmp1, tmp1, xFlags);                                                                         \
+            ANDI(tmp1, tmp1, 1 << F_SF);                                                                     \
+            ANDI(tmp3, xFlags, 1 << F_ZF);                                                                   \
+            OR(tmp1, tmp1, tmp3);                                                                            \
+            ANDI(tmp1, tmp1, (1 << F_SF) | (1 << F_ZF)), NEZ, EQZ, LE, GT, X_SF | X_OF | X_ZF, X64_JMP_JG);  \
         break
 
+// Dummy macros
+#define B__safe(a, b, c) XOR(xZR, xZR, xZR)
+#define B_(a, b, c)      XOR(xZR, xZR, xZR)
+
+#define NATIVEJUMP_safe(COND, val) \
+    B##COND##_safe(dyn->insts[ninst].nat_flags_op1, dyn->insts[ninst].nat_flags_op2, val);
+
+#define NATIVEJUMP(COND, val) \
+    B##COND(dyn->insts[ninst].nat_flags_op1, dyn->insts[ninst].nat_flags_op2, val);
+
 #define NOTEST(s1)                                       \
     if (box64_dynarec_test) {                            \
         ST_W(xZR, xEmu, offsetof(x64emu_t, test.test));  \