diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-02-05 20:35:31 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-02-05 20:35:31 +0100 |
| commit | 399478d635c352a986aaa891ac824d840ae19e56 (patch) | |
| tree | d254f8f669bee5132e03de0e3d2572d2bfc40302 /src | |
| parent | 608c13ebbac542a0b9a70c0c1e86192208715176 (diff) | |
| download | box64-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.c | 82 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_64.c | 60 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 20 | ||||
| -rw-r--r-- | src/include/debug.h | 1 | ||||
| -rw-r--r-- | src/main.c | 11 | ||||
| -rw-r--r-- | src/tools/rcfile.c | 3 |
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 |