about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-05-02 15:44:14 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-05-02 15:44:14 +0200
commit85458d1f2045324c669cf4a283d21ac46c5f2e48 (patch)
treec7e71eaae1dd1f62e1cdd56423b959b43a064076 /src
parent5b5723c5a50a607331787a14081c47ba8e7d9400 (diff)
downloadbox64-85458d1f2045324c669cf4a283d21ac46c5f2e48.tar.gz
box64-85458d1f2045324c669cf4a283d21ac46c5f2e48.zip
[ARM64_DYNAREC] Added rcr16 / rcl16 emitter, plus some tiny fixes to other rotate operations
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c8
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c32
-rw-r--r--src/dynarec/arm64/dynarec_arm64_emit_shift.c99
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h4
4 files changed, 114 insertions, 29 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 7f0aff2f..54f59b0d 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -2420,14 +2420,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             switch((nextop>>3)&7) {
                 case 0:
                     INST_NAME("ROL Eb, 1");
-                    SETFLAGS(X_OF|X_CF, SF_SUBSET);
+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
                     GETEB(x1, 0);
                     emit_rol8c(dyn, ninst, ed, 1, x4, x5);
                     EBBACK;
                     break;
                 case 1:
                     INST_NAME("ROR Eb, 1");
-                    SETFLAGS(X_OF|X_CF, SF_SUBSET);
+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
                     GETEB(x1, 0);
                     emit_ror8c(dyn, ninst, ed, 1, x4, x5);
                     EBBACK;
@@ -2435,7 +2435,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 2:
                     INST_NAME("RCL Eb, 1");
                     READFLAGS(X_CF);
-                    SETFLAGS(X_OF|X_CF, SF_SUBSET);
+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
                     GETEB(x1, 0);
                     emit_rcl8c(dyn, ninst, ed, 1, x4, x5);
                     EBBACK;
@@ -2443,7 +2443,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 3:
                     INST_NAME("RCR Eb, 1");
                     READFLAGS(X_CF);
-                    SETFLAGS(X_OF|X_CF, SF_SUBSET);
+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
                     GETEB(x1, 0);
                     emit_rcr8c(dyn, ninst, ed, 1, x4, x5);
                     EBBACK;
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index e6761c63..709605f1 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -974,27 +974,21 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     }

                     break;

                 case 2:

-                    INST_NAME("RCL Ew, Ib");

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

+                    INST_NAME("RCL Ew, 1");

                     READFLAGS(X_CF);

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

-                    SETFLAGS(X_OF | X_CF, SF_SET_DF);

+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

                     GETEW(x1, 1);

                     u8 = F8;

-                    MOV32w(x2, u8);

-                    CALL_(rcl16, x1, x3);

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

                     EWBACK;

                     break;

                 case 3:

-                    INST_NAME("RCR Ew, Ib");

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

+                    INST_NAME("RCR Ew, 1");

                     READFLAGS(X_CF);

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

-                    SETFLAGS(X_OF | X_CF, SF_SET_DF);

+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

                     GETEW(x1, 1);

                     u8 = F8;

-                    MOV32w(x2, u8);

-                    CALL_(rcr16, x1, x3);

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

                     EWBACK;

                     break;

                 case 4:

@@ -1076,22 +1070,16 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

                 case 2:

                     INST_NAME("RCL Ew, 1");

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

-                    READFLAGS(X_CF);

-                    SETFLAGS(X_OF|X_CF, SF_SET_DF);

-                    MOV32w(x2, 1);

+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

                     GETEW(x1, 0);

-                    CALL_(rcl16, x1, x3);

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

                     EWBACK;

                     break;

                 case 3:

                     INST_NAME("RCR Ew, 1");

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

-                    READFLAGS(X_CF);

-                    SETFLAGS(X_OF|X_CF, SF_SET_DF);

-                    MOV32w(x2, 1);

+                    SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);

                     GETEW(x1, 0);

-                    CALL_(rcr16, x1, x3);

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

                     EWBACK;

                     break;

                 case 4:

diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
index a05eee0e..486555f1 100644
--- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c
+++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
@@ -1013,10 +1013,14 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
     }
     BFIw(s1, xFlags, 8, 1); // insert cf
     IFX(X_OF|X_CF) {
-        if(c%9!=8) {
-            LSRw_IMM(s3, s1, 8-(c%9));
+        if(c%9) {
+            if(c%9!=8) {
+                LSRw_IMM(s3, s1, 8-(c%9));
+            } else {
+                MOVw_REG(s3, s1);
+            }
         } else {
-            MOVw_REG(s3, s1);
+            MOVw_REG(s3, xFlags);
         }
     }
     ORRw_REG_LSL(s1, s1, s1, 9);    // insert s1 again
@@ -1082,6 +1086,95 @@ void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
     }
 }
 
+// emit RCL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
+{
+    MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
+
+    if (!c) return;
+
+    IFX(X_PEND) {
+        MOV32w(s3, c);
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_rcl16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    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);
+            }
+        } else {
+            MOVw_REG(s3, xFlags);
+        }
+    }
+    ORRw_REG_LSL(s1, s1, s1, 17);    // insert s1 again
+    if(c%17) {
+        LSRw_IMM(s1, s1, 17-(c%17)); // 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_OF) {
+            if(c==1) {
+                EORw_REG_LSR(s3, s3, s1, 15);
+                BFIw(xFlags, s3, F_OF, 1);
+            }
+        }
+    }
+}
+
+// emit RCR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
+{
+    MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
+
+    if (!c) return;
+
+    IFX(X_PEND) {
+        MOV32w(s3, c);
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_rcr16);
+    } 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);
+        }
+    }
+    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_PEND) {
+        STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    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);
+            }
+        }
+    }
+}
 // 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/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index e4a7c94d..f19db163 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1100,6 +1100,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 #define emit_ror16c     STEPNAME(emit_ror16c)
 #define emit_rcl8c      STEPNAME(emit_rcl8c)
 #define emit_rcr8c      STEPNAME(emit_rcr8c)
+#define emit_rcl16c     STEPNAME(emit_rcl16c)
+#define emit_rcr16c     STEPNAME(emit_rcr16c)
 #define emit_shrd32c    STEPNAME(emit_shrd32c)
 #define emit_shrd32     STEPNAME(emit_shrd32)
 #define emit_shld32c    STEPNAME(emit_shld32c)
@@ -1255,6 +1257,8 @@ void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
 void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
 void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
 void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
+void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
+void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
 void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
 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);