about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-11-14 15:00:58 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-11-14 15:00:58 +0100
commitcd2638d11a1ce7d1db868e47953740ac540c40ee (patch)
tree5a740662a6f737700c8a6f965a34c31ab84d2576 /src
parentc87796e51cacf7758523fe1fb20ef2b2b5193b49 (diff)
downloadbox64-cd2638d11a1ce7d1db868e47953740ac540c40ee.tar.gz
box64-cd2638d11a1ce7d1db868e47953740ac540c40ee.zip
[ARM64_DYNAREC] Some refactor on 8/16/32/64bits SHL/SHR/SAR opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_64.c6
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67.c8
-rw-r--r--src/dynarec/arm64/dynarec_arm64_emit_shift.c132
3 files changed, 67 insertions, 79 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c
index 7e76fb20..9ad0be88 100644
--- a/src/dynarec/arm64/dynarec_arm64_64.c
+++ b/src/dynarec/arm64/dynarec_arm64_64.c
@@ -1244,6 +1244,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 6:
                     INST_NAME("SHL Ed, CL");
                     SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
+                    if(box64_dynarec_safeflags>1)
+                        MAYSETFLAGS();
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -1258,6 +1260,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 5:
                     INST_NAME("SHR Ed, CL");
                     SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
+                    if(box64_dynarec_safeflags>1)
+                        MAYSETFLAGS();
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -1272,6 +1276,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 7:
                     INST_NAME("SAR Ed, CL");
                     SETFLAGS(X_ALL, SF_SET_PENDING);
+                    if(box64_dynarec_safeflags>1)
+                        MAYSETFLAGS();
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c
index a109f95d..a77d88a5 100644
--- a/src/dynarec/arm64/dynarec_arm64_67.c
+++ b/src/dynarec/arm64/dynarec_arm64_67.c
@@ -1248,11 +1248,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 4:

                 case 6:

                     INST_NAME("SHL Ed, Ib");

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

                     GETED32(1);

                     u8 = (F8)&(rex.w?0x3f:0x1f);

-                    emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);

-                    WBACK;

+                    if(u8) {    //should create the geted32_ib utility function for that

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

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

+                        WBACK;

+                    }

                     break;

                 case 5:

                     INST_NAME("SHR Ed, Ib");

diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
index c2d74576..464fb7d7 100644
--- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c
+++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
@@ -21,7 +21,7 @@
 #include "dynarec_arm64_functions.h"
 #include "dynarec_arm64_helper.h"
 
-// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
+// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2. s2 must be non-0
 void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
 {
     MAYUSE(s2);
@@ -35,15 +35,6 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
-    IFX(X_OF) {
-        CMPSxw_U12(s2, 0);
-        Bcond(cNE, +8+((dyn->insts[ninst].x64.gen_flags&X_PEND)?4:0));
-        BFCw(xFlags, F_OF, 1);
-        IFX(X_PEND) {
-            STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
-        }
-        B_NEXT(cEQ);
-    }
     IFX(X_CF | X_OF) {
         MOV32w(s4, rex.w?64:32);
         SUBxw_REG(s4, s4, s2);
@@ -54,28 +45,28 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
     IFX(X_PEND) {
         STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
+    IFX(X_OF) {
+        CMPSxw_U12(s2, 1);   // if s2==1
+            LSRxw(s4, s1, (rex.w)?63:31);
+            EORxw_REG(s3, s4, xFlags);  // CF is set if OF is asked
+            CSELw(s3, s3, wZR, cEQ);
+            BFIw(xFlags, s3, F_OF, 1);
+    }
     int need_tst = 0;
     IFX(X_ZF) need_tst = 1;
     IFXNATIVE(X_SF, NF_SF) need_tst = 1;
     if(need_tst) TSTxw_REG(s1, s1);
-    IFX(X_ZF) {
-        IFNATIVE(NF_EQ) {} else {
-            CSETw(s4, cEQ);
-            BFIw(xFlags, s4, F_ZF, 1);
-        }
-    }
     IFX(X_SF) {
         IFNATIVE(NF_SF) {} else {
-            LSRxw(s4, s1, (rex.w)?63:31);
+            IFX(X_OF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
             BFIw(xFlags, s4, F_SF, 1);
         }
     }
-    IFX(X_OF) {
-        CMPSxw_U12(s2, 1);   // if s2==1
-            IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
-            EORxw_REG(s4, s4, xFlags);  // CF is set if OF is asked
-            CSELw(s4, s4, wZR, cEQ);
-            BFIw(xFlags, s4, F_OF, 1);
+    IFX(X_ZF) {
+        IFNATIVE(NF_EQ) {} else {
+            CSETw(s4, cEQ);
+            BFIw(xFlags, s4, F_ZF, 1);
+        }
     }
     if(box64_dynarec_test)
         IFX(X_AF) {
@@ -99,15 +90,6 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
     } else IFX(X_ALL) {
         SET_DFNONE(s4);
     }
-    if(c==0) {
-        IFX(X_OF) {
-            BFCw(xFlags, F_OF, 1);
-        }
-        IFX(X_PEND) {
-            STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
-        }
-        return;
-    }
     IFX(X_CF|X_OF) {
         LSRxw(s3, s1, (rex.w?64:32)-c);
         BFIxw(xFlags, s3, F_CF, 1);
@@ -391,14 +373,14 @@ void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
     IFX(X_PEND) {
         STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
-    COMP_ZFSF(s1, 8)
     IFX(X_OF) {
         CMPSw_U12(s2, 1);   // if s2==1
-            IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);}
+            LSRw(s3, s1, 7);
             EORw_REG(s4, s3, xFlags);  // CF is set if OF is asked
             CSELw(s4, s4, wZR, cEQ);
             BFIw(xFlags, s4, F_OF, 1);
     }
+    COMP_ZFSF(s1, 8)
     if(box64_dynarec_test)
         IFX(X_AF) {
             BFCw(xFlags, F_AF, 1);
@@ -433,7 +415,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
         COMP_ZFSF(s1, 8)
         IFX(X_OF) {
             if(c==1) {
-                IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);}
+                IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);}  //use COMP_ZFSF operation
                 EORw_REG(s4, s3, xFlags);  // CF is set if OF is asked
                 BFIw(xFlags, s4, F_OF, 1);
             } else {
@@ -447,11 +429,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
             emit_pf(dyn, ninst, s1, s4);
         }
     } else {
-        IFX(X_CF) {
-            LSLw(s3, s1, c-1);
-            BFXILw(xFlags, s3, 7, 1);   // insert F_CF from s3[7:1]
-        }
-        IFXNATIVE(X_ZF|X_SF, NF_EQ|NF_SF) {
+        IFXNATIVE(X_ZF|X_SF|X_CF, NF_EQ|NF_SF|NF_CF) {
             SUBSw_REG(s1, s1, s1);
         } else {
             MOVw_REG(s1, xZR);
@@ -459,6 +437,10 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
         IFX(X_PEND) {
             STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
         }
+        IFX(X_CF) {
+            // sub X, X will generate a carry flags
+            IFNATIVE(NF_CF) {GEN_INVERTED_CARRY();} else {BFCw(xFlags, F_CF, 1);}
+        }
         IFX(X_OF) {
             BFCw(xFlags, F_OF, 1);
         }
@@ -468,17 +450,14 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
         if(box64_dynarec_test) IFX(X_AF) {
             BFCw(xFlags, F_AF, 1);
         }
-        IFX(X_PF | X_ZF) {
-            IFNATIVE(NF_EQ) {IFX(X_PF) {MOV32w(s3, 1);}} else {
-                MOV32w(s3, 1);
-                IFX(X_ZF) {
-                    BFIw(xFlags, s3, F_ZF, 1);
-                }
-            }
-            IFX(X_PF) {
-                BFIw(xFlags, s3, F_PF, 1);
+        IFX(X_ZF) {
+            IFNATIVE(NF_EQ) {} else {
+                ORRw_mask(xFlags, xFlags, 26, 0);   //1<<F_ZF
             }
         }
+        IFX(X_PF) {
+            ORRw_mask(xFlags, xFlags, 30, 0);   //1<<F_PF
+        }
     }
 }
 
@@ -625,13 +604,18 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
             emit_pf(dyn, ninst, s1, s4);
         }
     } else {
-        LSRw(s3, s1, 7);
-        BFIw(xFlags, s3, F_CF, 1);
-        BFIw(wFlags, s3, F_SF, 1);
-        EORw_mask(s3, s3, 0, 0);    //1
-        BFIw(xFlags, s3, F_ZF, 1);
-        MOV32w(s3, 1);
-        BFIw(xFlags, s3, F_PF, 1);
+        IFX(X_CF|X_ZF|X_SF|X_PF) {
+            LSRw(s3, s1, 7);
+            IFX(X_CF){ BFIw(xFlags, s3, F_CF, 1); }
+            IFX(X_SF){ BFIw(wFlags, s3, F_SF, 1); }
+            IFX(X_ZF) {
+                EORw_mask(s3, s3, 0, 0);    //1
+                BFIw(xFlags, s3, F_ZF, 1);
+            }
+            IFX(X_PF) {
+                ORRw_mask(xFlags, xFlags, 30, 0);   //1<<F_PF
+            }
+        }
     }
     if(box64_dynarec_test)
         IFX(X_AF) {
@@ -659,14 +643,14 @@ void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
     IFX(X_PEND) {
         STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
-    COMP_ZFSF(s1, 16)
     IFX(X_OF) {
         CMPSw_U12(s2, 1);   // if s2==1
-            IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);}
+            LSRw(s3, s1, 15);
             EORw_REG(s4, s3, xFlags);  // CF is set if OF is asked
             CSELw(s4, s4, wZR, cEQ);
             BFIw(xFlags, s4, F_OF, 1);
     }
+    COMP_ZFSF(s1, 16)
     if(box64_dynarec_test)
         IFX(X_AF) {
             BFCw(xFlags, F_AF, 1);
@@ -701,7 +685,7 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
         COMP_ZFSF(s1, 16)
         IFX(X_OF) {
             if(c==1) {
-                IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);}
+                IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);} // use COMP_ZFSF operation
                 EORw_REG(s4, s3, xFlags);  // CF is set if OF is asked
                 BFIw(xFlags, s4, F_OF, 1);
             } else {
@@ -714,17 +698,12 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
         IFX(X_PF) {
             if(c>7) {
                 // the 0xff area will be 0, so PF is known
-                MOV32w(s3, 1);
-                BFIw(xFlags, s3, F_PF, 1);
+                ORRw_mask(xFlags, xFlags, 30, 0);   //1<<F_PF
             } else
                 emit_pf(dyn, ninst, s1, s4);
         }
     } else {
-        IFX(X_CF) {
-            LSLw(s3, s1, c-1);
-            BFXILw(xFlags, s3, 15, 1);   // insert F_CF from s3[15:1]
-        }
-        IFXNATIVE(X_ZF|X_SF, NF_EQ|NF_SF) {
+        IFXNATIVE(X_ZF|X_SF|X_CF, NF_EQ|NF_SF|NF_CF) {
             SUBSw_REG(s1, s1, s1);
         } else {
             MOVw_REG(s1, xZR);
@@ -735,23 +714,24 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
         IFX(X_OF) {
             BFCw(xFlags, F_OF, 1);
         }
+        IFX(X_CF) {
+            // sub X, X will generate a carry flags
+            IFNATIVE(NF_CF) {GEN_INVERTED_CARRY();} else {BFCw(xFlags, F_CF, 1);}
+        }
         IFX(X_SF) {
             IFNATIVE(NF_SF) {} else BFCw(xFlags, F_SF, 1);
         }
         if(box64_dynarec_test) IFX(X_AF) {
             BFCw(xFlags, F_AF, 1);
         }
-        IFX(X_PF | X_ZF) {
-            IFNATIVE(NF_EQ) {IFX(X_PF) {MOV32w(s3, 1);}} else {
-                MOV32w(s3, 1);
-                IFX(X_ZF) {
-                    BFIw(xFlags, s3, F_ZF, 1);
-                }
-            }
-            IFX(X_PF) {
-                BFIw(xFlags, s3, F_PF, 1);
+        IFX(X_ZF) {
+            IFNATIVE(NF_EQ) {} else {
+                ORRw_mask(xFlags, xFlags, 26, 0);   //1<<F_ZF
             }
         }
+        IFX(X_PF) {
+            ORRw_mask(xFlags, xFlags, 30, 0);   //1<<F_PF
+        }
     }
 }
 
@@ -850,12 +830,12 @@ void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
     IFX(X_PEND) {
         STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
     }
-    COMP_ZFSF(s1, 16)
     IFX(X_OF) {
         SUBw_U12(s4, s2, 1);
         CBNZw(s4, 4+4);
             BFCw(xFlags, F_OF, 1);
     }
+    COMP_ZFSF(s1, 16)
     if(box64_dynarec_test)
         IFX(X_AF) {
             BFCw(xFlags, F_AF, 1);