about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-11-16 11:17:10 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-11-16 11:17:10 +0100
commit90b606584da7f20f1b8c34c1a8a5cfe78ae5545c (patch)
treee4a32182f44f8749000b4a9a8bc16178c68f23a9 /src
parent19a24c2171cd943e7b1398c5636c666e07efe6d4 (diff)
downloadbox64-90b606584da7f20f1b8c34c1a8a5cfe78ae5545c.tar.gz
box64-90b606584da7f20f1b8c34c1a8a5cfe78ae5545c.zip
[ARM64_DYNAREC] Optimized 66 AD opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_660f.c18
-rw-r--r--src/dynarec/arm64/dynarec_arm64_emit_shift.c50
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h2
3 files changed, 62 insertions, 8 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c
index 47586faf..7b4a35a2 100644
--- a/src/dynarec/arm64/dynarec_arm64_660f.c
+++ b/src/dynarec/arm64/dynarec_arm64_660f.c
@@ -2218,13 +2218,19 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
         case 0xAD:

             nextop = F8;

             INST_NAME("SHRD Ew, Gw, CL");

-            UXTBw(x3, xRCX);

-            MESSAGE(LOG_DUMP, "Need Optimization\n");

-            SETFLAGS(X_ALL, SF_SET);

-            GETEWW(x4, x1, (opcode==0xAC)?1:0);

+            SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+            if(box64_dynarec_safeflags>1)

+                MAYSETFLAGS();

             GETGW(x2);

-            CALL_(shrd16, x1, wback);

-            EWBACKW(x1);

+            GETEW(x1, 0);

+            UFLAG_IF {

+                ANDSw_mask(x3, xRCX, 0, 0b00100);  //mask=0x00000001f

+                B_NEXT(cEQ);

+            } else {

+                ANDw_mask(x3, xRCX, 0, 0b00100);  //mask=0x00000001f

+            }

+            emit_shrd16(dyn, ninst, ed, gd, x3, x5, x4);

+            EWBACK;

             break;

 

         case 0xAF:

diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
index bab869b7..19343416 100644
--- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c
+++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
@@ -1170,6 +1170,7 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
         }
         return;
     }
+    ORRw_REG_LSL(s1, s1, s2, 16);   // create concat first
     IFX(X_CF) {
         BFXILw(xFlags, s1, c-1, 1);    // set CF
     }
@@ -1179,8 +1180,7 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
             BFIw(xFlags, s4, F_OF, 1);  // store sign for later use
         }
     }
-    ORRw_REG_LSL(s1, s1, s2, 16);
-    LSRw_IMM(s1, s1, c);
+    RORw(s1, s1, c);
     IFX(X_PEND) {
         STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
@@ -1204,3 +1204,49 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
         emit_pf(dyn, ninst, s1, s3, s4);
     }
 }
+
+// emit SHRD16 instruction, from s1, fill s2 , shift s5, store result in s1 using s3 and s4 as scratch
+void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, int s4)
+{
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s5, xEmu, offsetof(x64emu_t, op2));
+        // same flags computation as with shl64/shl32
+        SET_DF(s4, d_shrd16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    ORRw_REG_LSL(s1, s1, s2, 16);   // create concat first
+    IFX(X_CF) {
+        SUBw_U12(s3, s5, 1);
+        LSRw_REG(s3, s1, s3);
+        BFIw(xFlags, s3, F_CF, 1);
+    }
+    IFX(X_OF) {
+        LSRw(s4, s1, 15);
+        BFIw(xFlags, s4, F_OF, 1);  // store sign fr now
+    }
+    RORw_REG(s1, s1, s5);
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        TSTw_mask(s1, 0, 15);   // 0xffff
+        CSETw(s4, cEQ);
+        BFIw(xFlags, s4, F_ZF, 1);
+    }
+    IFX(X_SF) {
+        LSRw(s4, s1, 15);
+        BFIw(xFlags, s4, F_SF, 1);
+    }
+    IFX(X_OF) {
+        CMPSw_U12(s5, 1);
+        Bcond(cNE, 4+3*4);
+            LSRw(s4, s1, 15);
+            EORw_REG_LSR(s4, s4, xFlags, F_OF); // Set if sign changed
+            BFIw(xFlags, s4, F_OF, 1);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
\ No newline at end of file
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 6102c9bc..a853e8f0 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1045,6 +1045,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 #define emit_shld32c    STEPNAME(emit_shld32c)
 #define emit_shrd32     STEPNAME(emit_shrd32)
 #define emit_shrd16c    STEPNAME(emit_shrd16c)
+#define emit_shrd16     STEPNAME(emit_shrd16)
 
 #define emit_pf         STEPNAME(emit_pf)
 
@@ -1192,6 +1193,7 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
 void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
 void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4);
 void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int s3, int s4);
+void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, int s4);
 
 void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);