about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-05-09 22:03:25 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-05-09 22:03:25 +0200
commitff755facc0c0ec502b4476d1144b61055abb3e7b (patch)
tree911d30c96c337df8fa401cb405eed1e24ecd6bf9 /src
parentd38f659f428544de524fe6f2a49355a104055555 (diff)
downloadbox64-ff755facc0c0ec502b4476d1144b61055abb3e7b.tar.gz
box64-ff755facc0c0ec502b4476d1144b61055abb3e7b.zip
[ARM64_DYNAREC] Fix and improvments on rcl/rcr helper
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c41
-rw-r--r--src/dynarec/arm64/dynarec_arm64_emit_shift.c146
-rw-r--r--src/emu/x64run_private.c15
3 files changed, 95 insertions, 107 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index 709605f1..d06665a2 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -961,7 +961,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

                 case 1:

                     INST_NAME("ROR Ew, Ib");

-                    u8 = geted_ib(dyn, addr, ninst, nextop) & 15;

                     if (geted_ib(dyn, addr, ninst, nextop) & 15) {

                         SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING);

                         GETEW(x1, 1);

@@ -974,22 +973,32 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     }

                     break;

                 case 2:

-                    INST_NAME("RCL Ew, 1");

-                    READFLAGS(X_CF);

-                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

-                    GETEW(x1, 1);

-                    u8 = F8;

-                    emit_rcl8c(dyn, ninst, ed, u8, x4, x5);

-                    EWBACK;

+                    INST_NAME("RCL Ew, Ib");

+                    if (geted_ib(dyn, addr, ninst, nextop) & 31) {

+                        READFLAGS(X_CF);

+                        SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

+                        GETEW(x1, 1);

+                        u8 = F8;

+                        emit_rcl16c(dyn, ninst, ed, u8, x4, x5);

+                        EWBACK;

+                    } else {

+                        FAKEED;

+                        F8;

+                    }

                     break;

                 case 3:

-                    INST_NAME("RCR Ew, 1");

-                    READFLAGS(X_CF);

-                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

-                    GETEW(x1, 1);

-                    u8 = F8;

-                    emit_rcr8c(dyn, ninst, ed, u8, x4, x5);

-                    EWBACK;

+                    INST_NAME("RCR Ew, Ib");

+                    if (geted_ib(dyn, addr, ninst, nextop) & 31) {

+                        READFLAGS(X_CF);

+                        SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

+                        GETEW(x1, 1);

+                        u8 = F8;

+                        emit_rcr16c(dyn, ninst, ed, u8, x4, x5);

+                        EWBACK;

+                    } else {

+                        FAKEED;

+                        F8;

+                    }

                     break;

                 case 4:

                 case 6:

@@ -1070,6 +1079,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

                 case 2:

                     INST_NAME("RCL Ew, 1");

+                    READFLAGS(X_CF);

                     SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

                     GETEW(x1, 0);

                     emit_rcl16c(dyn, ninst, x1, 1, x5, x4);

@@ -1077,6 +1087,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

                 case 3:

                     INST_NAME("RCR Ew, 1");

+                    READFLAGS(X_CF);

                     SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

                     GETEW(x1, 0);

                     emit_rcr16c(dyn, ninst, x1, 1, x5, x4);

diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
index 486555f1..4b614a94 100644
--- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c
+++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
@@ -197,12 +197,6 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
-    if(!c) {
-        IFX(X_PEND) {
-            STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
-        }
-        return;
-    }
     IFX(X_CF) {
         if(c==1) {
             BFIw(xFlags, s1, 0, 1);
@@ -252,12 +246,6 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
-    if(!c) {
-        IFX(X_PEND) {
-            STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
-        }
-        return;
-    }
     IFX(X_CF) {
         ASRxw(s3, s1, c-1);
         BFIw(xFlags, s3, 0, 1);
@@ -1001,7 +989,7 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
 {
     MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
 
-    if (!c) return;
+    if (!(c%9)) return;
 
     IFX(X_PEND) {
         MOV32w(s3, c);
@@ -1011,27 +999,24 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
+    c%=9;
     BFIw(s1, xFlags, 8, 1); // insert cf
     IFX(X_OF|X_CF) {
-        if(c%9) {
-            if(c%9!=8) {
-                LSRw_IMM(s3, s1, 8-(c%9));
-            } else {
-                MOVw_REG(s3, s1);
-            }
+        if(c!=8) {
+            LSRw_IMM(s3, s1, 8-c);
         } else {
-            MOVw_REG(s3, xFlags);
+            MOVw_REG(s3, s1);
         }
     }
     ORRw_REG_LSL(s1, s1, s1, 9);    // insert s1 again
-    if(c%9) {
-        LSRw_IMM(s1, s1, 9-(c%9)); // do the rcl
-    }
+    LSRw_IMM(s1, s1, 9-c); // do the rcl
     IFX(X_PEND) {
         STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
     IFX(X_OF|X_CF) {
-        BFIw(xFlags, s3, F_CF, 1);
+        IFX(X_CF) {
+            BFIw(xFlags, s3, F_CF, 1);
+        }
         IFX(X_OF) {
             if(c==1) {
                 EORw_REG_LSR(s3, s3, s1, 7);
@@ -1046,7 +1031,7 @@ void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
 {
     MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
 
-    if (!c) return;
+    if (!(c%9)) return;
 
     IFX(X_PEND) {
         MOV32w(s3, c);
@@ -1056,34 +1041,27 @@ void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
-    IFX(X_OF|X_CF) {
-        if(c%9) {
-            if((c%9)==1) {
-                MOVx_REG(s3, s1);
-            } else {
-                LSRw_IMM(s3, s1, (c%9)-1);
-            }
-        } else {
-            MOVw_REG(s3, xFlags);
-        }
+    c%=9;
+    IFX(X_OF) {
+        MOVw_REG(s3, wFlags);
     }
     BFIw(s1, xFlags, 8, 1); // insert cf
-    ORRw_REG_LSL(s1, s1, s1, 9);    // insert s1 again
-    if(c%9) {
-        LSRw_IMM(s1, s1, (c%9)); // do the rcr
+    IFX(X_CF) {
+        BFXILw(xFlags, s1, c-1, 1);
     }
-    IFX(X_PEND) {
-        STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
+    if(c>1) {
+        ORRw_REG_LSL(s1, s1, s1, 9);    // insert s1 again
     }
-    IFX(X_OF|X_CF) {
-        BFIw(xFlags, s3, F_CF, 1);
-        IFX(X_OF) {
-            if(c==1) {
-                EORw_REG_LSR(s3, s3, s1, 7);
-                BFIw(xFlags, s3, F_OF, 1);
-            }
+    LSRw_IMM(s1, s1, c); // do the rcr
+    IFX(X_OF) {
+        if(c==1) {
+            EORw_REG_LSR(s3, s3, s1, 7);
+            BFIw(xFlags, s3, F_OF, 1);
         }
     }
+    IFX(X_PEND) {
+        STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
 }
 
 // emit RCL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
@@ -1091,7 +1069,7 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
 {
     MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
 
-    if (!c) return;
+    if (!(c%17)) return;
 
     IFX(X_PEND) {
         MOV32w(s3, c);
@@ -1101,32 +1079,27 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
+    c%=17;
     BFIw(s1, xFlags, 16, 1); // insert cf
     IFX(X_OF|X_CF) {
-        if(c%17) {
-            if(c%17!=16) {
-                LSRw_IMM(s3, s1, 16-(c%17));
-            } else {
-                MOVw_REG(s3, s1);
-            }
+        if(c!=16) {
+            LSRw_IMM(s3, s1, 16-c);
         } else {
-            MOVw_REG(s3, xFlags);
+            MOVw_REG(s3, s1);
         }
     }
-    ORRw_REG_LSL(s1, s1, s1, 17);    // insert s1 again
-    if(c%17) {
-        LSRw_IMM(s1, s1, 17-(c%17)); // do the rcl
-    }
+    ORRx_REG_LSL(s1, s1, s1, 17);    // insert s1 again
+    LSRx_IMM(s1, s1, 17-c); // do the rcl
     IFX(X_PEND) {
-        STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
-    IFX(X_OF|X_CF) {
+    IFX(X_CF) {
         BFIw(xFlags, s3, F_CF, 1);
-        IFX(X_OF) {
-            if(c==1) {
-                EORw_REG_LSR(s3, s3, s1, 15);
-                BFIw(xFlags, s3, F_OF, 1);
-            }
+    }
+    IFX(X_OF) {
+        if(c==1) {
+            EORw_REG_LSR(s3, s3, s1, 15);
+            BFIw(xFlags, s3, F_OF, 1);
         }
     }
 }
@@ -1136,7 +1109,7 @@ void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
 {
     MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
 
-    if (!c) return;
+    if (!(c%17)) return;
 
     IFX(X_PEND) {
         MOV32w(s3, c);
@@ -1146,34 +1119,27 @@ void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
-    IFX(X_OF|X_CF) {
-        if(c%17) {
-            if((c%17)==1) {
-                MOVx_REG(s3, s1);
-            } else {
-                LSRw_IMM(s3, s1, (c%17)-1);
-            }
-        } else {
-            MOVw_REG(s3, xFlags);
-        }
+    c%=17;
+    BFIw(s1, xFlags, 16, 1); // insert cf
+    IFX(X_OF) {
+        MOVw_REG(s3, wFlags);
     }
-    BFIw(s1, xFlags, 17, 1); // insert cf
-    ORRw_REG_LSL(s1, s1, s1, 17);    // insert s1 again
-    if(c%17) {
-        LSRw_IMM(s1, s1, (c%17)); // do the rcr
+    IFX(X_CF) {
+        BFXILx(xFlags, s1, c-1, 1);
     }
-    IFX(X_PEND) {
-        STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
+    if(c>1) {
+        ORRx_REG_LSL(s1, s1, s1, 17);    // insert s1 again
     }
-    IFX(X_OF|X_CF) {
-        BFIw(xFlags, s3, F_CF, 1);
-        IFX(X_OF) {
-            if(c==1) {
-                EORw_REG_LSR(s3, s3, s1, 15);
-                BFIw(xFlags, s3, F_OF, 1);
-            }
+    LSRx_IMM(s1, s1, c); // do the rcr
+    IFX(X_OF) {
+        if(c==1) {
+            EORw_REG_LSR(s3, s3, s1, 15);
+            BFIw(xFlags, s3, F_OF, 1);
         }
     }
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
 }
 // 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, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index 2891b04c..016092b3 100644
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -1064,11 +1064,22 @@ void UpdateFlags(x64emu_t *emu)
             // new CF
             CONDITIONAL_SET_FLAG(((cnt==1)?emu->op1.u8:(emu->op1.u8>>(cnt-1))) & 1, F_CF);
             break;
-
         case d_rcl16:
+            cnt = emu->op2.u16%17;
+            CONDITIONAL_SET_FLAG(emu->op1.u16>>(17-cnt) & 1, F_CF);
+            // should for cnt==1
+            CONDITIONAL_SET_FLAG(((emu->res.u16>>15) ^ ACCESS_FLAG(F_CF)) & 1, F_OF);
+            break;
+        case d_rcr16:
+            cnt = emu->op2.u16%17;
+            // should for cnt==1, using "before" CF
+            CONDITIONAL_SET_FLAG(((emu->res.u16>>15) ^ ACCESS_FLAG(F_CF)) & 1, F_OF);
+            // new CF
+            CONDITIONAL_SET_FLAG(((cnt==1)?emu->op1.u16:(emu->op1.u16>>(cnt-1))) & 1, F_CF);
+            break;
+
         case d_rcl32:
         case d_rcl64:
-        case d_rcr16:
         case d_rcr32:
         case d_rcr64:
         case d_unknown: