diff options
Diffstat (limited to 'src/dynarec/arm64/dynarec_arm64_00.c')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 81 |
1 files changed, 52 insertions, 29 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index aa5f4461..a0177a3a 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1802,8 +1802,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Eb, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&0x1f) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; + if(u8) { + SETFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF|((u8==1)?X_OF:0), (u8==1)?SF_SET_PENDING:SF_SUBSET_PENDING); GETEB(x1, 1); u8 = (F8)&0x1f; emit_shl8c(dyn, ninst, ed, u8, x4, x5); @@ -1815,8 +1816,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("SHR Eb, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&0x1f) { - SETFLAGS(X_ALL, SF_SET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; + if(u8) { + SETFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF|((u8==1)?X_OF:0), (u8==1)?SF_SET_PENDING:SF_SUBSET_PENDING); GETEB(x1, 1); u8 = (F8)&0x1f; emit_shr8c(dyn, ninst, ed, u8, x4, x5); @@ -1828,8 +1830,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 7: INST_NAME("SAR Eb, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&0x1f) { - SETFLAGS(X_ALL, SF_SET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; + if(u8) { + SETFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF|((u8==1)?X_OF:0), (u8==1)?SF_SET_PENDING:SF_SUBSET_PENDING); GETSEB(x1, 1); u8 = (F8)&0x1f; emit_sar8c(dyn, ninst, ed, u8, x4, x5); @@ -1846,8 +1849,9 @@ 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 Ed, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20))) { - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); + if(u8) { + SETFLAGS(X_CF|((u8==1)?X_OF:0), SF_SUBSET_PENDING); GETED(1); u8 = (F8)&(rex.w?0x3f:0x1f); emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4); @@ -1859,8 +1863,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 1: INST_NAME("ROR Ed, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20))) { - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); + if(u8) { + SETFLAGS(X_CF|((u8==1)?X_OF:0), SF_SUBSET_PENDING); GETED(1); u8 = (F8)&(rex.w?0x3f:0x1f); emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4); @@ -1895,8 +1900,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Ed, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20))) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); + if(u8) { + SETFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF|((u8==1)?X_OF:0), (u8==1)?SF_SET_PENDING:SF_SUBSET_PENDING); GETED(1); u8 = (F8)&(rex.w?0x3f:0x1f); emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4); @@ -1908,8 +1914,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("SHR Ed, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20))) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); + if(u8) { + SETFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF|((u8==1)?X_OF:0), (u8==1)?SF_SET_PENDING:SF_SUBSET_PENDING); GETED(1); u8 = (F8)&(rex.w?0x3f:0x1f); emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); @@ -1921,8 +1928,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 7: INST_NAME("SAR Ed, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20))) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); + if(u8) { + SETFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF|((u8==1)?X_OF:0), (u8==1)?SF_SET_PENDING:SF_SUBSET_PENDING); GETED(1); u8 = (F8)&(rex.w?0x3f:0x1f); emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); @@ -2063,13 +2071,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin #if 1 INST_NAME("INT 3"); // check if TRAP signal is handled - LDRx_U12(x1, xEmu, offsetof(x64emu_t, context)); + TABLE64(x1, (uintptr_t)my_context); MOV32w(x2, offsetof(box64context_t, signals[SIGTRAP])); LDRx_REG(x3, x1, x2); + //LDRx_U12(x3, x1, offsetof(box64context_t, signals[SIGTRAP])); CMPSx_U12(x3, 0); - B_NEXT(cNE); - MOV32w(x1, SIGTRAP); - CALL_(raise, -1, 0); + B_NEXT(cEQ); + GETIP(ip); + STORE_XEMU_CALL(xRIP); + CALL(native_int3, -1); + LOAD_XEMU_CALL(xRIP); break; #else DEFAULT; @@ -2957,16 +2968,28 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin if(!rex.w) { SET_DFNONE(x2); GETED(0); - MOVw_REG(x3, xRAX); - ORRx_REG_LSL(x3, x3, xRDX, 32); - if(MODREG) { - MOVw_REG(x4, ed); - ed = x4; + if(ninst && (nextop==0xF0) + && dyn->insts[ninst-1].x64.addr + && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0xB8 + && *(uint32_t*)(dyn->insts[ninst-1].x64.addr+1)==0) { + // hack for some protection that check a divide by zero actualy trigger a divide by zero exception + MESSAGE(LOG_INFO, "Divide by 0 hack\n"); + GETIP(ip); + STORE_XEMU_CALL(xRIP); + CALL(native_div0, -1); + LOAD_XEMU_CALL(xRIP); + } else { + MOVw_REG(x3, xRAX); + ORRx_REG_LSL(x3, x3, xRDX, 32); + if(MODREG) { + MOVw_REG(x4, ed); + ed = x4; + } + UDIVx(x2, x3, ed); + MSUBx(x4, x2, ed, xRAX); + MOVw_REG(xRAX, x2); + MOVw_REG(xRDX, x4); } - UDIVx(x2, x3, ed); - MSUBx(x4, x2, ed, xRAX); - MOVw_REG(xRAX, x2); - MOVw_REG(xRDX, x4); } else { if(ninst && dyn->insts[ninst-1].x64.addr |