about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-06-14 17:07:19 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-06-14 17:07:19 +0200
commit00b5944271dd7063af9f4d6ecb42ec2e4dcd679e (patch)
tree9220e740dbe31759dd312dd015daf03dd650270c /src
parent196076f952f88c91c154f0abdd13acf79e044028 (diff)
downloadbox64-00b5944271dd7063af9f4d6ecb42ec2e4dcd679e.tar.gz
box64-00b5944271dd7063af9f4d6ecb42ec2e4dcd679e.zip
[DYNAREC] Added shld32c emiter and 0F A4 opcode
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_emitter.h2
-rwxr-xr-xsrc/dynarec/dynarec_arm64_0f.c11
-rwxr-xr-xsrc/dynarec/dynarec_arm64_emit_shift.c120
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h2
4 files changed, 69 insertions, 66 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index 7de69a59..b64413ef 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -433,6 +433,8 @@
 #define ORRx_REG(Rd, Rn, Rm)            EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
 #define ORRx_REG_LSL(Rd, Rn, Rm, lsl)   EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
 #define ORRw_REG_LSL(Rd, Rn, Rm, lsl)   EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
+#define ORRxw_REG_LSL(Rd, Rn, Rm, lsl)  EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
+#define ORRxw_REG_LSR(Rd, Rn, Rm, lsr)  EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
 #define ORRxw_REG(Rd, Rn, Rm)           EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
 #define ORRw_REG(Rd, Rn, Rm)            EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
 #define ORNx_REG(Rd, Rn, Rm)            EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c
index 5c8c9741..bb0ea063 100755
--- a/src/dynarec/dynarec_arm64_0f.c
+++ b/src/dynarec/dynarec_arm64_0f.c
@@ -1026,7 +1026,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             LSRxw_REG(x4, ed, x2);

             BFIw(xFlags, x4, F_CF, 1);

             break;

-

+        case 0xA4:

+            nextop = F8;

+            INST_NAME("SHLD Ed, Gd, Ib");

+            SETFLAGS(X_ALL, SF_SET_PENDING);

+            GETED(1);

+            GETGD;

+            u8 = F8;

+            emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);

+            WBACK;

+            break;

         case 0xA5:

             nextop = F8;

             INST_NAME("SHLD Ed, Gd, CL");

diff --git a/src/dynarec/dynarec_arm64_emit_shift.c b/src/dynarec/dynarec_arm64_emit_shift.c
index aaf049bb..1e0c89a3 100755
--- a/src/dynarec/dynarec_arm64_emit_shift.c
+++ b/src/dynarec/dynarec_arm64_emit_shift.c
@@ -72,9 +72,8 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
     IFX(X_OF) {
         CMPSxw_U12(s2, 1);   // if s2==1
             IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
-            Bcond(cNE, 4+3*4);
-            BFCw(xFlags, F_OF, 1);
             EORxw_REG(s4, s4, xFlags);  // CF is set if OF is asked
+            CSELw(s4, s4, wZR, cEQ);
             BFIw(xFlags, s4, F_OF, 1);
     }
     IFX(X_PF) {
@@ -102,7 +101,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
         }
         return;
     }
-    IFX(X_CF) {
+    IFX(X_CF|X_OF) {
         LSRxw(s3, s1, (rex.w?64:32)-c);
         BFIxw(xFlags, s3, F_CF, 1);
     }
@@ -124,7 +123,6 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
     IFX(X_OF) {
         if(c==1) {
             IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
-            Bcond(cNE, +12);
             EORxw_REG(s4, s4, xFlags);  // CF is set if OF is asked
             BFIw(xFlags, s4, F_OF, 1);
         } else {
@@ -403,63 +401,57 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
 //    }
 //}
 
-//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
-//{
-//    c&=0x1f;
-//    IFX(X_PEND) {
-//        MOVW(s3, c);
-//        STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
-//        STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
-//        // same flags computation as with shl32
-//        SET_DF(s4, d_shl32);
-//    } else IFX(X_ALL) {
-//        SET_DFNONE(s4);
-//    }
-//    if(c==0) {
-//        IFX(F_OF) {
-//            BFC(xFlags, F_OF, 1);
-//        }
-//        IFX(X_PEND) {
-//            STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
-//        }
-//        return;
-//    }
-//    IFX(X_CF) {
-//        MOV_REG_LSR_IMM5(s3, s1, 32-c);
-//        BFI(xFlags, s3, F_CF, 1);
-//    }
-//    IFX(X_OF) {
-//        MOVS_REG_LSL_IMM5(s1, s1, c);
-//    } else {
-//        MOV_REG_LSL_IMM5(s1, s1, c);
-//    }
-//    IFX(X_OF) {
-//        if(c==1) {
-//            UBFX(s3, s2, 0, 1);
-//            XOR_IMM8_COND(cCS, s3, s3, 1);
-//            BFI(xFlags, s3, F_OF, 1);
-//        } else {
-//            BFC(xFlags, F_OF, 1);
-//        }
-//    }
-//    IFX(X_ZF) {
-//        ORRS_REG_LSR_IMM5(s1, s1, s2, 32-c);
-//    } else {
-//        ORR_REG_LSR_IMM5(s1, s1, s2, 32-c);
-//    }
-//
-//    IFX(X_PEND) {
-//        STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
-//    }
-//    IFX(X_ZF) {
-//        ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
-//        BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
-//    }
-//    IFX(X_SF) {
-//        MOV_REG_LSR_IMM5(s3, s1, 31);
-//        BFI(xFlags, s3, F_SF, 1);
-//    }
-//    IFX(X_PF) {
-//        emit_pf(dyn, ninst, s1, s3, s4);
-//    }
-//}
+void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
+{
+    c&=(rex.w?0x3f:0x1f);
+    IFX(X_PEND) {
+        MOV32w(s3, c);
+        STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
+        // same flags computation as with shl64/shl32
+        SET_DF(s4, rex.w?d_shl64:d_shl32);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    if(c==0) {
+        IFX(F_OF) {
+            BFCx(xFlags, F_OF, 1);
+        }
+        IFX(X_PEND) {
+            STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
+        }
+        return;
+    }
+    IFX(X_CF|X_OF) {
+        LSRxw(s3, s1, (rex.w?64:32)-c);
+        BFIxw(xFlags, s3, F_CF, 1);
+    }
+    LSLxw(s1, s1, c);
+    ORRxw_REG_LSR(s1, s1, s2, (rex.w?64:32)-c);
+
+    IFX(X_PEND) {
+        STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        TSTxw_REG(s1, s1);
+        BFCx(xFlags, F_ZF, 1);
+        Bcond(cNE, +8);
+        ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
+    }
+    IFX(X_SF) {
+        LSRxw(s4, s1, (rex.w)?63:31);
+        BFIx(xFlags, s4, F_SF, 1);
+    }
+    IFX(X_OF) {
+        if(c==1) {
+            UBFXxw(s3, s1, rex.w?63:31, 1);
+            EORxw_REG(s3, s3, xFlags);  // CF is set if OF is asked
+            BFIw(xFlags, s3, F_OF, 1);
+        } else {
+            BFCw(xFlags, F_OF, 1);
+        }
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index 617524b4..fc6c427f 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -812,7 +812,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
 void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
 void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
 //void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
-//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
+void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
 
 void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);