Skip to content

Commit

Permalink
[ARM64_DYNAREC] Added BOX64_DYNAREC_DIV0 option to check/trigger Divi…
Browse files Browse the repository at this point in the history
…de by 0 when needed
  • Loading branch information
ptitSeb committed Feb 5, 2024
1 parent 608c13e commit 399478d
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 1 deletion.
82 changes: 81 additions & 1 deletion src/dynarec/arm64/dynarec_arm64_00.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
60 changes: 60 additions & 0 deletions src/dynarec/arm64/dynarec_arm64_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions src/dynarec/arm64/dynarec_arm64_66.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/include/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 11 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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");
}
Expand Down
3 changes: 3 additions & 0 deletions src/tools/rcfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand All @@ -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) \
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 399478d

Please sign in to comment.