about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-02-05 20:35:31 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-02-05 20:35:31 +0100
commit399478d635c352a986aaa891ac824d840ae19e56 (patch)
treed254f8f669bee5132e03de0e3d2572d2bfc40302 /src
parent608c13ebbac542a0b9a70c0c1e86192208715176 (diff)
downloadbox64-399478d635c352a986aaa891ac824d840ae19e56.tar.gz
box64-399478d635c352a986aaa891ac824d840ae19e56.zip
[ARM64_DYNAREC] Added BOX64_DYNAREC_DIV0 option to check/trigger Divide by 0 when needed
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c82
-rw-r--r--src/dynarec/arm64/dynarec_arm64_64.c60
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c20
-rw-r--r--src/include/debug.h1
-rw-r--r--src/main.c11
-rw-r--r--src/tools/rcfile.c3
6 files changed, 176 insertions, 1 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index bcfced0b..6a5c5b7e 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -2130,7 +2130,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
 
         case 0xCC:
             SETFLAGS(X_ALL, SF_SET);    // Hack, set all flags (to an unknown state...)
-            SKIPTEST(x1);
+            NOTEST(x1);
             if(PK(0)=='S' && PK(1)=='C') {
                 addr+=2;
                 //BARRIER(BARRIER_FLOAT);
@@ -3041,6 +3041,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     SETFLAGS(X_ALL, SF_SET);
                     GETEB(x1, 0);
                     UXTHw(x2, xRAX);
+                    if(box64_dynarec_div0) {
+                        CBNZw_MARK3(ed);
+                        GETIP_(ip);
+                        STORE_XEMU_CALL(xRIP);
+                        CALL(native_div0, -1);
+                        CLEARIP();
+                        LOAD_XEMU_CALL(xRIP);
+                        jump_to_epilog(dyn, 0, xRIP, ninst);
+                        MARK3;
+                    }
                     UDIVw(x3, x2, ed);
                     MSUBw(x4, x3, ed, x2);  // x4 = x2 mod ed (i.e. x2 - x3*ed)
                     BFIx(xRAX, x3, 0, 8);
@@ -3051,6 +3061,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     SKIPTEST(x1);
                     SETFLAGS(X_ALL, SF_SET);
                     GETSEB(x1, 0);
+                    if(box64_dynarec_div0) {
+                        CBNZw_MARK3(ed);
+                        GETIP_(ip);
+                        STORE_XEMU_CALL(xRIP);
+                        CALL(native_div0, -1);
+                        CLEARIP();
+                        LOAD_XEMU_CALL(xRIP);
+                        jump_to_epilog(dyn, 0, xRIP, ninst);
+                        MARK3;
+                    }
                     SXTHw(x2, xRAX);
                     SDIVw(x3, x2, ed);
                     MSUBw(x4, x3, ed, x2);  // x4 = x2 mod ed (i.e. x2 - x3*ed)
@@ -3137,6 +3157,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                             CALL(native_div0, -1);
                             LOAD_XEMU_CALL(xRIP);
                         } else {
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             MOVw_REG(x3, xRAX);
                             ORRx_REG_LSL(x3, x3, xRDX, 32);
                             if(MODREG) {
@@ -3155,11 +3185,31 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                            && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
                             SET_DFNONE(x2);
                             GETED(0);
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             UDIVx(x2, xRAX, ed);
                             MSUBx(xRDX, x2, ed, xRAX);
                             MOVx_REG(xRAX, x2);
                         } else {
                             GETEDH(x1, 0);  // get edd changed addr, so cannot be called 2 times for same op...
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             CBZxw_MARK(xRDX);
                             if(ed!=x1) {MOVx_REG(x1, ed);}
                             CALL(div64, -1);
@@ -3179,6 +3229,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     if(!rex.w) {
                         SET_DFNONE(x2)
                         GETSEDw(0);
+                        if(box64_dynarec_div0) {
+                            CBNZx_MARK3(wb);
+                            GETIP_(ip);
+                            STORE_XEMU_CALL(xRIP);
+                            CALL(native_div0, -1);
+                            CLEARIP();
+                            LOAD_XEMU_CALL(xRIP);
+                            jump_to_epilog(dyn, 0, xRIP, ninst);
+                            MARK3;
+                        }
                         MOVw_REG(x3, xRAX);
                         ORRx_REG_LSL(x3, x3, xRDX, 32);
                         SDIVx(x2, x3, wb);
@@ -3192,11 +3252,31 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                            && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
                             SET_DFNONE(x2)
                             GETED(0);
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             SDIVx(x2, xRAX, ed);
                             MSUBx(xRDX, x2, ed, xRAX);
                             MOVx_REG(xRAX, x2);
                         } else {
                             GETEDH(x1, 0);  // get edd changed addr, so cannot be called 2 times for same op...
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             //Need to see if RDX==0 and RAX not signed
                             // or RDX==-1 and RAX signed
                             CBNZx_MARK2(xRDX);
diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c
index 8d4f3bfa..068e4ed0 100644
--- a/src/dynarec/arm64/dynarec_arm64_64.c
+++ b/src/dynarec/arm64/dynarec_arm64_64.c
@@ -1024,6 +1024,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     if(!rex.w) {
                         SET_DFNONE(x2);
                         GETEDO(x6, 0);
+                        if(box64_dynarec_div0) {
+                            CBNZx_MARK3(ed);
+                            GETIP_(ip);
+                            STORE_XEMU_CALL(xRIP);
+                            CALL(native_div0, -1);
+                            CLEARIP();
+                            LOAD_XEMU_CALL(xRIP);
+                            jump_to_epilog(dyn, 0, xRIP, ninst);
+                            MARK3;
+                        }
                         MOVw_REG(x3, xRAX);
                         ORRx_REG_LSL(x3, x3, xRDX, 32);
                         if(MODREG) {
@@ -1041,6 +1051,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                            && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
                             SET_DFNONE(x2);
                             GETEDO(x6, 0);
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             UDIVx(x2, xRAX, ed);
                             MSUBx(xRDX, x2, ed, xRAX);
                             MOVx_REG(xRAX, x2);
@@ -1051,6 +1071,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                             CALL(div64, -1);
                             B_NEXT_nocond;
                             MARK;
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             UDIVx(x2, xRAX, ed);
                             MSUBx(xRDX, x2, ed, xRAX);
                             MOVx_REG(xRAX, x2);
@@ -1067,6 +1097,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         GETSEDOw(x6, 0);
                         MOVw_REG(x3, xRAX);
                         ORRx_REG_LSL(x3, x3, xRDX, 32);
+                        if(box64_dynarec_div0) {
+                            CBNZx_MARK3(wb);
+                            GETIP_(ip);
+                            STORE_XEMU_CALL(xRIP);
+                            CALL(native_div0, -1);
+                            CLEARIP();
+                            LOAD_XEMU_CALL(xRIP);
+                            jump_to_epilog(dyn, 0, xRIP, ninst);
+                            MARK3;
+                        }
                         SDIVx(x2, x3, wb);
                         MSUBx(x4, x2, wb, x3);
                         MOVw_REG(xRAX, x2);
@@ -1078,11 +1118,31 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                            && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
                             SET_DFNONE(x2)
                             GETEDO(x6, 0);
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             SDIVx(x2, xRAX, ed);
                             MSUBx(xRDX, x2, ed, xRAX);
                             MOVx_REG(xRAX, x2);
                         } else {
                             GETEDO(x6, 0);
+                            if(box64_dynarec_div0) {
+                                CBNZx_MARK3(ed);
+                                GETIP_(ip);
+                                STORE_XEMU_CALL(xRIP);
+                                CALL(native_div0, -1);
+                                CLEARIP();
+                                LOAD_XEMU_CALL(xRIP);
+                                jump_to_epilog(dyn, 0, xRIP, ninst);
+                                MARK3;
+                            }
                             CBZxw_MARK(xRDX);
                             MVNx_REG(x2, xRDX);
                             CBZxw_MARK(x2);
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index aa5384cd..cdbc9796 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -1306,6 +1306,16 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     GETEW(x1, 0);

                     UXTHw(x2, xRAX);

                     BFIw(x2, xRDX, 16, 16);

+                    if(box64_dynarec_div0) {

+                        CBNZw_MARK3(ed);

+                        GETIP_(ip);

+                        STORE_XEMU_CALL(xRIP);

+                        CALL(native_div0, -1);

+                        CLEARIP();

+                        LOAD_XEMU_CALL(xRIP);

+                        jump_to_epilog(dyn, 0, xRIP, ninst);

+                        MARK3;

+                    }

                     UDIVw(x3, x2, ed);

                     MSUBw(x4, x3, ed, x2);  // x4 = x2 mod ed (i.e. x2 - x3*ed)

                     BFIz(xRAX, x3, 0, 16);

@@ -1316,6 +1326,16 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     SKIPTEST(x1);

                     SETFLAGS(X_ALL, SF_SET);

                     GETSEW(x1, 0);

+                    if(box64_dynarec_div0) {

+                        CBNZw_MARK3(ed);

+                        GETIP_(ip);

+                        STORE_XEMU_CALL(xRIP);

+                        CALL(native_div0, -1);

+                        CLEARIP();

+                        LOAD_XEMU_CALL(xRIP);

+                        jump_to_epilog(dyn, 0, xRIP, ninst);

+                        MARK3;

+                    }

                     UXTHw(x2, xRAX);

                     BFIw(x2, xRDX, 16, 16);

                     SDIVw(x3, x2, ed);

diff --git a/src/include/debug.h b/src/include/debug.h
index 70502586..c3a08258 100644
--- a/src/include/debug.h
+++ b/src/include/debug.h
@@ -24,6 +24,7 @@ extern int box64_dynarec_strongmem;
 extern int box64_dynarec_fastnan;
 extern int box64_dynarec_fastround;
 extern int box64_dynarec_x87double;
+extern int box64_dynarec_div0;
 extern int box64_dynarec_safeflags;
 extern int box64_dynarec_callret;
 extern int box64_dynarec_bleeding_edge;
diff --git a/src/main.c b/src/main.c
index ed3a1525..cdc91fe0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -65,6 +65,7 @@ int box64_dynarec_bigblock = 1;
 int box64_dynarec_forward = 128;
 int box64_dynarec_strongmem = 0;
 int box64_dynarec_x87double = 0;
+int box64_dynarec_div0 = 0;
 int box64_dynarec_fastnan = 1;
 int box64_dynarec_fastround = 1;
 int box64_dynarec_safeflags = 1;
@@ -622,6 +623,15 @@ void LoadLogEnv()
         if(box64_dynarec_x87double)
             printf_log(LOG_INFO, "Dynarec will use only double for x87 emulation\n");
     }
+    p = getenv("BOX64_DYNAREC_DIV0");
+    if(p) {
+        if(strlen(p)==1) {
+            if(p[0]>='0' && p[0]<='1')
+                box64_dynarec_div0 = p[0]-'0';
+        }
+        if(box64_dynarec_div0)
+            printf_log(LOG_INFO, "Dynarec will check for divide by 0\n");
+    }
     p = getenv("BOX64_DYNAREC_FASTNAN");
     if(p) {
         if(strlen(p)==1) {
@@ -736,6 +746,7 @@ void LoadLogEnv()
             box64_dynarec_fastnan = 0;
             box64_dynarec_fastround = 0;
             box64_dynarec_x87double = 1;
+            box64_dynarec_div0 = 1;
             box64_dynarec_callret = 0;
             printf_log(LOG_INFO, "Dynarec will compare it's execution with the interpreter (super slow, only for testing)\n");
         }
diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c
index 1bd0da27..e7dcd939 100644
--- a/src/tools/rcfile.c
+++ b/src/tools/rcfile.c
@@ -147,6 +147,7 @@ ENTRYINT(BOX64_DYNAREC_BIGBLOCK, box64_dynarec_bigblock, 0, 3, 2)   \
 ENTRYSTRING_(BOX64_DYNAREC_FORWARD, box64_dynarec_forward)          \
 ENTRYINT(BOX64_DYNAREC_STRONGMEM, box64_dynarec_strongmem, 0, 3, 2) \
 ENTRYBOOL(BOX64_DYNAREC_X87DOUBLE, box64_dynarec_x87double)         \
+ENTRYBOOL(BOX64_DYNAREC_DIV0, box64_dynarec_div0)                   \
 ENTRYBOOL(BOX64_DYNAREC_FASTNAN, box64_dynarec_fastnan)             \
 ENTRYBOOL(BOX64_DYNAREC_FASTROUND, box64_dynarec_fastround)         \
 ENTRYINT(BOX64_DYNAREC_SAFEFLAGS, box64_dynarec_safeflags, 0, 2, 2) \
@@ -171,6 +172,7 @@ IGNORE(BOX64_DYNAREC_BIGBLOCK)                                      \
 IGNORE(BOX64_DYNAREC_FORWARD)                                       \
 IGNORE(BOX64_DYNAREC_STRONGMEM)                                     \
 IGNORE(BOX64_DYNAREC_X87DOUBLE)                                     \
+IGNORE(BOX64_DYNAREC_DIV0)                                          \
 IGNORE(BOX64_DYNAREC_FASTNAN)                                       \
 IGNORE(BOX64_DYNAREC_FASTROUND)                                     \
 IGNORE(BOX64_DYNAREC_SAFEFLAGS)                                     \
@@ -631,6 +633,7 @@ void ApplyParams(const char* name)
         box64_dynarec_fastnan = 0;
         box64_dynarec_fastround = 0;
         box64_dynarec_x87double = 1;
+        box64_dynarec_div0 = 1;
         box64_dynarec_callret = 0;
     }
     #endif