about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-11-11 17:12:40 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-11-11 17:12:40 +0100
commitda3373ae42fe9e9cc3ed078562c7db7eee098622 (patch)
tree331411ad05a41a0595a16178ef2ddfa798fa0669
parentcd0173dae40050c52e1f0ae5b38d943f44b980ca (diff)
downloadbox64-da3373ae42fe9e9cc3ed078562c7db7eee098622.tar.gz
box64-da3373ae42fe9e9cc3ed078562c7db7eee098622.zip
[ARM64_DYNAREC] improved D2 /4/6 opcodes
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c16
-rw-r--r--src/dynarec/arm64/dynarec_arm64_emit_shift.c47
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h2
3 files changed, 58 insertions, 7 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 73e086f1..06d10a4e 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -2294,14 +2294,18 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 4:
                 case 6:
                     INST_NAME("SHL Eb, CL");
-                    ANDSw_mask(x2, xRCX, 0, 0b00100);
-                    SETFLAGS(X_ALL, SF_PENDING);
+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
+                    UFLAG_IF {
+                        ANDSw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
+                    } else {
+                        ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
+                    }
                     GETEB(x1, 0);
-                    UFLAG_OP12(ed, x2)
-                    LSLw_REG(ed, ed, x2);
+                    UFLAG_IF {
+                        B_NEXT(cEQ);
+                    }
+                    emit_shl8(dyn, ninst, x1, x2, x5, x4);
                     EBBACK;
-                    UFLAG_RES(ed);
-                    UFLAG_DF(x3, d_shl8);
                     break;
                 case 5:
                     INST_NAME("SHR Eb, CL");
diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
index 266576f7..526364ee 100644
--- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c
+++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
@@ -270,6 +270,51 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
     }
 }
 
+// emit SHL8 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
+void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
+{
+    MAYUSE(s2);
+    int64_t j64;
+    MAYUSE(j64);
+
+    IFX(X_PEND) {
+        STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_shl8);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    IFX(X_CF | X_OF) {
+        MOV32w(s4, 8);
+        SUBw_REG(s4, s4, s2);
+        LSRw_REG(s4, s1, s4);
+        BFIw(xFlags, s4, F_CF, 1);
+    }
+    LSLw_REG(s1, s1, s2);
+    IFX(X_PEND) {
+        STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        TSTw_mask(s1, 0, 7);
+        CSETw(s4, cEQ);
+        BFIw(xFlags, s4, F_ZF, 1);
+    }
+    IFX(X_SF) {
+        LSRw(s4, s1, 7);
+        BFIw(xFlags, s4, F_SF, 1);
+    }
+    IFX(X_OF) {
+        CMPSw_U12(s2, 1);   // if s2==1
+            IFX(X_SF) {} else {LSRw(s4, s1, 7);}
+            EORw_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) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
 // emit SHL8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
 void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
 {
@@ -300,7 +345,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
         STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
     IFX(X_ZF) {
-        TSTw_REG(s1, s1);
+        TSTw_mask(s1, 0, 7);
         CSETw(s4, cEQ);
         BFIw(xFlags, s4, F_ZF, 1);
     }
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 1bb519f3..c141ea8b 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1023,6 +1023,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 #define emit_shr32      STEPNAME(emit_shr32)
 #define emit_shr32c     STEPNAME(emit_shr32c)
 #define emit_sar32c     STEPNAME(emit_sar32c)
+#define emit_shl8       STEPNAME(emit_shl8)
 #define emit_shl8c      STEPNAME(emit_shl8c)
 #define emit_rol32c     STEPNAME(emit_rol32c)
 #define emit_ror32c     STEPNAME(emit_ror32c)
@@ -1157,6 +1158,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
 void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
 void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
+void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
 void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);