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:31:01 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-06-14 17:31:01 +0200
commit126119b1fbfd77d5c872130b76bb093d1bf1dbee (patch)
tree83c75d2790383e3b84810c8c9b60efbc6a63ddea /src
parent701bf913e87913420d1ef66413759a2d03fa532b (diff)
downloadbox64-126119b1fbfd77d5c872130b76bb093d1bf1dbee.tar.gz
box64-126119b1fbfd77d5c872130b76bb093d1bf1dbee.zip
[DYNAREC] Added shrd32c emiter and 0F AC opcode
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/dynarec_arm64_0f.c11
-rwxr-xr-xsrc/dynarec/dynarec_arm64_emit_shift.c103
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h2
3 files changed, 59 insertions, 57 deletions
diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c
index 56d61471..56e3529b 100755
--- a/src/dynarec/dynarec_arm64_0f.c
+++ b/src/dynarec/dynarec_arm64_0f.c
@@ -1086,7 +1086,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 STRxw_U12(ed, wback, fixedaddress);

             }

             break;

-

+        case 0xAC:

+            nextop = F8;

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

+            SETFLAGS(X_ALL, SF_SET_PENDING);

+            GETED(1);

+            GETGD;

+            u8 = F8;

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

+            WBACK;

+            break;

         case 0xAD:

             nextop = F8;

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

diff --git a/src/dynarec/dynarec_arm64_emit_shift.c b/src/dynarec/dynarec_arm64_emit_shift.c
index 1e0c89a3..db76657d 100755
--- a/src/dynarec/dynarec_arm64_emit_shift.c
+++ b/src/dynarec/dynarec_arm64_emit_shift.c
@@ -345,61 +345,54 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
 }
 
 // emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
-//void emit_shrd32c(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 calc as shr32
-//        SET_DF(s4, d_shr32);
-//    } else IFX(X_ALL) {
-//        SET_DFNONE(s4);
-//    }
-//    if(!c) {
-//        IFX(X_PEND) {
-//            STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
-//        }
-//        return;
-//    }
-//    IFX(X_CF) {
-//        MOVS_REG_LSR_IMM5(s1, s1, c);
-//    } else {
-//        MOV_REG_LSR_IMM5(s1, s1, c);
-//    }
-//    IFX(X_ZF|X_CF) {
-//        BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
-//    }
-//    IFX(X_CF) {
-//        ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
-//    }
-//    IFX(X_ZF) {
-//        ORRS_REG_LSL_IMM5(s1, s1, s2, 32-c);
-//    } else {
-//        ORR_REG_LSL_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);
-//    }
-//    IFX(X_SF) {
-//        MOV_REG_LSR_IMM5(s3, s1, 31);
-//        BFI(xFlags, s3, F_SF, 1);
-//    }
-//    IFX(X_OF) {
-//        if(c==1) {
-//            MOV_REG_LSR_IMM5(s4, s1, 30);
-//            XOR_REG_LSR_IMM8(s4, s4, s4, 1);
-//            BFI(xFlags, s4, F_OF, 1);
-//        }
-//    }
-//    IFX(X_PF) {
-//        emit_pf(dyn, ninst, s1, s3, s4);
-//    }
-//}
+void emit_shrd32c(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) {
+        IFX(X_PEND) {
+            STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
+        }
+        return;
+    }
+    IFX(X_CF) {
+        LSRxw_REG(s3, s1, c-1);
+        BFIw(xFlags, s3, 0, 1);
+    }
+    LSRxw(s1, s1, c);
+    ORRxw_REG_LSL(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) {
+            LSRxw(s4, s1, rex.w?62:30);
+            EORw_REG_LSR(s4, s4, s4, 1);
+            BFIw(xFlags, s4, F_OF, 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)
 {
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index fc6c427f..cf778874 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -811,7 +811,7 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
 void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
 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_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, 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);