diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 30fd5f6be8..7785b84eca 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -821,13 +821,36 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 0x62: - if(rex.is32bits) { - // BOUND here - DEFAULT; + INST_NAME("BOUND Gd, Ed"); + nextop = F8; + if(rex.is32bits && MODREG) { + addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0); + LDRxw_U12(x2, wback, 0); + LDRxw_U12(x3, wback, 4+(rex.w*4)); + GETGD; + GETIP(ip); + CMPSxw_REG(gd, x2); + B_MARK(cLT); + CMPSxw_REG(gd, x3); + B_MARK(cGT); + B_NEXT_nocond; + MARK; + STORE_XEMU_CALL(xRIP); + CALL(native_br, -1); + LOAD_XEMU_CALL(xRIP); } else { - INST_NAME("BOUND Gd, Ed"); - nextop = F8; - FAKEED; + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_PEND); + } else { + SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state + } + GETIP(ip); + STORE_XEMU_CALL(xRIP); + CALL(native_ud, -1); + LOAD_XEMU_CALL(xRIP); + jump_to_epilog(dyn, 0, xRIP, ninst); + *need_epilog = 0; + *ok = 0; } break; case 0x63: diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index bcf06e6a7c..c9a116e6b1 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -189,6 +189,13 @@ void native_ud(x64emu_t* emu) emit_signal(emu, SIGILL, (void*)R_RIP, 0); } +void native_br(x64emu_t* emu) +{ + if(BOX64ENV(dynarec_test)) + emu->test.test = 0; + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xb09d); +} + void native_priv(x64emu_t* emu) { emu->test.test = 0; diff --git a/src/dynarec/dynarec_native_functions.h b/src/dynarec/dynarec_native_functions.h index 1fad8ef14b..ad8226e6be 100644 --- a/src/dynarec/dynarec_native_functions.h +++ b/src/dynarec/dynarec_native_functions.h @@ -53,6 +53,7 @@ void native_pclmul_y(x64emu_t* emu, int gy, int vy, void* p, uint32_t u8); void native_clflush(x64emu_t* emu, void* p); void native_ud(x64emu_t* emu); +void native_br(x64emu_t* emu); void native_priv(x64emu_t* emu); void native_singlestep(x64emu_t* emu); void native_int3(x64emu_t* emu); diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 4960088982..0fd35d2dc8 100644 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -432,9 +432,12 @@ int Run(x64emu_t *emu, int step) } break; case 0x62: /* BOUND Gd, Ed */ - if(rex.is32bits) { - nextop = F8; - FAKEED(0); + nextop = F8; + if(rex.is32bits && MODREG) { + GETGD; + int* bounds = (int*)GETEA(0); + if(bounds[0]dword[0] || bounds[1]>GD->dword[0]) + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xb09d); } else { unimp = 1; goto fini; diff --git a/src/libtools/signals.c b/src/libtools/signals.c index e87b1c342f..b424cee0b5 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -1241,6 +1241,10 @@ void my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigi sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 14; if(!mmapped) info2->si_code = 1; info2->si_errno = 0; + } else if (info->si_errno==0xb09d) { + sigcontext->uc_mcontext.gregs[X64_ERR] = 0; + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 5; + info2->si_errno = 0; }else { sigcontext->uc_mcontext.gregs[X64_ERR] = 0x14|((sysmapped && !(real_prot&PROT_READ))?0:1); sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 14; @@ -2088,6 +2092,9 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code) } else if(sig==SIGSEGV && code==0xecec) { info.si_errno = 0xecec; info.si_code = SEGV_ACCERR; + } else if (sig==SIGSEGV && code==0xb09d) { + info.si_errno = 0xb09d; + info.si_code = 0; } info.si_addr = addr; const char* x64name = NULL;