mirror of
https://github.com/ptitSeb/box64.git
synced 2025-05-09 00:21:32 +08:00
[DYNAREC] Added BOX64_DYNAREC_TEST to run interpeter and dynarec at the same time and compare states
This commit is contained in:
parent
feb4a39457
commit
9f75f28e7a
@ -266,30 +266,6 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/emu/x64int3.c"
|
||||
"${BOX64_ROOT}/src/emu/x87emu_private.c"
|
||||
"${BOX64_ROOT}/src/emu/x64primop.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run0f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run64.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run660f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6664.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66d9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66dd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66f0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run670f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6766.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67660f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rund8.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rund9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runda.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundb.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundc.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runde.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundf.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runf0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runf20f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runf30f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run_private.c"
|
||||
"${BOX64_ROOT}/src/emu/x64syscall.c"
|
||||
"${BOX64_ROOT}/src/emu/x64tls.c"
|
||||
@ -319,6 +295,33 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/wrapped/generated/wrapper.c"
|
||||
)
|
||||
|
||||
set(INTERPRETER
|
||||
"${BOX64_ROOT}/src/emu/x64run.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run0f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run64.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run660f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6664.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66d9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66dd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66f0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run670f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6766.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67660f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rund8.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rund9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runda.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundb.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundc.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runde.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundf.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runf0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runf20f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runf30f.c"
|
||||
)
|
||||
|
||||
set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
|
||||
@ -548,6 +551,7 @@ if(DYNAREC)
|
||||
"${BOX64_ROOT}/src/dynarec/dynablock.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_native.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_native_functions.c"
|
||||
"${BOX64_ROOT}/src/emu/x64test.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -654,6 +658,8 @@ if(DYNAREC)
|
||||
set_target_properties(native_pass2 PROPERTIES COMPILE_FLAGS "-DSTEP=2")
|
||||
add_library(native_pass3 OBJECT ${DYNAREC_PASS})
|
||||
set_target_properties(native_pass3 PROPERTIES COMPILE_FLAGS "-DSTEP=3")
|
||||
add_library(test_interpreter OBJECT ${INTERPRETER})
|
||||
set_target_properties(test_interpreter PROPERTIES COMPILE_FLAGS "-DTEST_INTERPRETER")
|
||||
add_dependencies(native_pass0 WRAPPERS)
|
||||
add_dependencies(native_pass1 WRAPPERS)
|
||||
add_dependencies(native_pass2 WRAPPERS)
|
||||
@ -665,6 +671,7 @@ if(DYNAREC)
|
||||
$<TARGET_OBJECTS:native_pass1>
|
||||
$<TARGET_OBJECTS:native_pass2>
|
||||
$<TARGET_OBJECTS:native_pass3>
|
||||
$<TARGET_OBJECTS:test_interpreter>
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -673,16 +680,18 @@ if(DYNAREC)
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX64_ROOT}/src/git_head.h"
|
||||
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
|
||||
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX64_ROOT}/src/git_head.h"
|
||||
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
|
||||
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
add_library(interpreter OBJECT ${INTERPRETER})
|
||||
|
||||
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head.h")
|
||||
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
|
||||
add_dependencies(${BOX64} WRAPPERS)
|
||||
@ -696,6 +705,7 @@ endif()
|
||||
if(DYNAREC)
|
||||
target_link_libraries(${BOX64} dynarec)
|
||||
endif()
|
||||
target_link_libraries(${BOX64} interpreter)
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
if(NOT NOLOADADDR)
|
||||
|
@ -133,6 +133,11 @@ Enables/Disables trace for generated code.
|
||||
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpreter)
|
||||
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
|
||||
|
||||
#### BOX64_DYNAREC_TEST *
|
||||
Dynarec will compare it's execution with the interpreter (super slow, only for testing)
|
||||
* 0 : No comparison
|
||||
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different
|
||||
|
||||
#### BOX64_DYNAREC_BIGBLOCK *
|
||||
Enables/Disables Box64's Dynarec building BigBlock.
|
||||
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
|
||||
|
@ -261,6 +261,14 @@ down the program a lot and generate huge logs.
|
||||
Forbid dynablock creation in the interval specified (helpfull for debugging
|
||||
behaviour difference between Dynarec and Interpretor)
|
||||
|
||||
=item B<BOX64_DYNAREC_TEST>=I<0|1>
|
||||
|
||||
Enables/Disables test for generated code. This will run interpreter along the Dynacrec, so this will slow
|
||||
down the program a lot.
|
||||
|
||||
* 0 : No test for generated code. (Default.)
|
||||
* 1 : Enable Tests for generated code
|
||||
|
||||
=item B<BOX64_DYNAREC_BIGBLOCK>=I<0|1|2|3>
|
||||
|
||||
Enables/Disables Box64's Dynarec building BigBlock.
|
||||
|
@ -143,6 +143,7 @@ static void init_mutexes(box64context_t* context)
|
||||
native_lock_store(&context->mutex_thread, 0);
|
||||
native_lock_store(&context->mutex_bridge, 0);
|
||||
native_lock_store(&context->mutex_dyndump, 0);
|
||||
pthread_mutex_init(&context->mutex_lock, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -325,7 +326,9 @@ void FreeBox64Context(box64context_t** context)
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
#ifndef DYNAREC
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
|
@ -499,9 +499,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x56:
|
||||
case 0x57:
|
||||
INST_NAME("PUSH reg");
|
||||
if(dyn->doublepush)
|
||||
if(dyn->doublepush) {
|
||||
dyn->test = 0;
|
||||
dyn->doublepush = 0;
|
||||
else {
|
||||
} else {
|
||||
gd = xRAX+(opcode&0x07)+(rex.b<<3);
|
||||
if(gd==xRSP) {
|
||||
MOVx_REG(x1, gd);
|
||||
@ -524,6 +525,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
PUSH2(gd, u32);
|
||||
dyn->doublepush = 1;
|
||||
dyn->test = 0; // disable test for this OP
|
||||
} else {
|
||||
PUSH1(gd);
|
||||
}
|
||||
@ -538,9 +540,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x5E:
|
||||
case 0x5F:
|
||||
INST_NAME("POP reg");
|
||||
if(dyn->doublepop)
|
||||
if(dyn->doublepop) {
|
||||
dyn->test = 0;
|
||||
dyn->doublepop = 0;
|
||||
else {
|
||||
} else {
|
||||
gd = xRAX+(opcode&0x07)+(rex.b<<3);
|
||||
u32 = 0;
|
||||
i32 = 0;
|
||||
@ -563,6 +566,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
}
|
||||
dyn->doublepop = 1;
|
||||
dyn->test = 0; // disable test for this OP
|
||||
} else {
|
||||
if(gd == xRSP) {
|
||||
POP1(x1);
|
||||
@ -1745,6 +1749,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...)
|
||||
dyn->test = 0;
|
||||
if(PK(0)=='S' && PK(1)=='C') {
|
||||
addr+=2;
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
@ -2211,6 +2216,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
PUSH1(x2);
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
|
||||
dyn->test=0; // disable test as this hack dos 2 instructions for 1
|
||||
// calling a native function
|
||||
sse_purge07cache(dyn, ninst, x3);
|
||||
if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall)
|
||||
|
@ -106,6 +106,7 @@ typedef struct dynarec_arm_s {
|
||||
size_t insts_size; // size of the instruction size array (calculated)
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smwrite; // for strongmem model emulation
|
||||
int8_t test; // test the opcode?
|
||||
uintptr_t forward; // address of the last end of code while testing forward
|
||||
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
|
||||
int32_t forward_size; // size at the forward point
|
||||
@ -123,12 +124,12 @@ int Table64(dynarec_arm_t *dyn, uint64_t val); // add a value to etable64 (if n
|
||||
|
||||
void CreateJmpNext(void* addr, void* next);
|
||||
|
||||
#define GO_TRACE() \
|
||||
GETIP_(ip); \
|
||||
#define GO_TRACE(A, B) \
|
||||
GETIP_(addr); \
|
||||
MOVx_REG(x1, xRIP); \
|
||||
STORE_XEMU_CALL(xRIP); \
|
||||
MOV32w(x2, 1); \
|
||||
CALL(PrintTrace, -1); \
|
||||
MOV32w(x2, B); \
|
||||
CALL(A, -1); \
|
||||
LOAD_XEMU_CALL(xRIP)
|
||||
|
||||
#endif //__DYNAREC_ARM_PRIVATE_H_
|
||||
|
@ -83,13 +83,20 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
|
||||
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
|
||||
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND);
|
||||
}
|
||||
if(box64_dynarec_test) {
|
||||
MESSAGE(LOG_DUMP, "TEST INIT ----\n");
|
||||
fpu_reflectcache(dyn, ninst, x1, x2, x3);
|
||||
GO_TRACE(x64test_init, dyn->test);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
dyn->test = 1;
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
if(my_context->dec && box64_dynarec_trace) {
|
||||
else if(my_context->dec && box64_dynarec_trace) {
|
||||
if((trace_end == 0)
|
||||
|| ((ip >= trace_start) && (ip < trace_end))) {
|
||||
MESSAGE(LOG_DUMP, "TRACE ----\n");
|
||||
fpu_reflectcache(dyn, ninst, x1, x2, x3);
|
||||
GO_TRACE();
|
||||
GO_TRACE(PrintTrace, 1);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
}
|
||||
@ -115,6 +122,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
|
||||
|
||||
addr = dynarec64_00(dyn, addr, ip, ninst, rex, rep, &ok, &need_epilog);
|
||||
|
||||
if(dyn->test) {
|
||||
MESSAGE(LOG_DUMP, "TEST CHECK ----\n");
|
||||
fpu_reflectcache(dyn, ninst, x1, x2, x3);
|
||||
GO_TRACE(x64test_check, 1);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
|
||||
INST_EPILOG;
|
||||
|
||||
int next = ninst+1;
|
||||
|
@ -1270,6 +1270,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
|
||||
case 0xCC:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
dyn->test=0;
|
||||
if(PK(0)=='S' && PK(1)=='C') {
|
||||
addr+=2;
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
@ -1463,6 +1464,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
switch(tmp) {
|
||||
case 3:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
dyn->test = 0;
|
||||
BARRIER(BARRIER_FULL);
|
||||
//BARRIER_NEXT(BARRIER_FULL);
|
||||
if(dyn->last_ip && (addr-dyn->last_ip<0x1000)) {
|
||||
|
@ -107,6 +107,7 @@ typedef struct dynarec_rv64_s {
|
||||
size_t insts_size; // size of the instruction size array (calculated)
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smwrite; // for strongmem model emulation
|
||||
int8_t test; // test the opcode?
|
||||
uintptr_t forward; // address of the last end of code while testing forward
|
||||
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
|
||||
int32_t forward_size; // size at the forward point
|
||||
@ -127,12 +128,12 @@ int Table64(dynarec_rv64_t *dyn, uint64_t val); // add a value to etable64 (if
|
||||
|
||||
void CreateJmpNext(void* addr, void* next);
|
||||
|
||||
#define GO_TRACE() \
|
||||
#define GO_TRACE(A, B) \
|
||||
GETIP_(ip); \
|
||||
MV(A1, xRIP); \
|
||||
STORE_XEMU_CALL(); \
|
||||
MOV64x(A2, 1); \
|
||||
CALL(PrintTrace, -1); \
|
||||
MOV64x(A2, B); \
|
||||
CALL(A, -1); \
|
||||
LOAD_XEMU_CALL()
|
||||
|
||||
#endif //__DYNAREC_RV64_PRIVATE_H_
|
@ -18,6 +18,27 @@
|
||||
#define STEP3
|
||||
#endif
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
#define GETED(D) oped=TestEd(test, &addr, rex, nextop, D)
|
||||
#define GETED32(D) oped=TestEd32O(test, &addr, rex, nextop, D, 0)
|
||||
#define GETED_OFFS(D, O) oped=TestEdO(test, &addr, rex, nextop, D, O)
|
||||
#define GETGD opgd=GetGd(test->emu, &addr, rex, nextop)
|
||||
#define GETEB(D) oped=TestEb(test, &addr, rex, nextop, D)
|
||||
#define GETEB32(D) oped=TestEb32O(test, &addr, rex, nextop, D, 0)
|
||||
#define GETEB_OFFS(D, O) oped=TestEbO(test, &addr, rex, nextop, D, O)
|
||||
#define GETGB opgd=GetGb(test->emu, &addr, rex, nextop)
|
||||
#define GETEW(D) oped=TestEw(test, &addr, rex, nextop, D)
|
||||
#define GETEW32(D) oped=TestEw32O(test, &addr, rex, nextop, D, 0)
|
||||
#define GETEW_OFFS(D, O) oped=TestEdO(test, &addr, rex, nextop, D, O)
|
||||
#define GETGW opgd=GetGw(test->emu, &addr, rex, nextop)
|
||||
#define GETEX(D) opex=TestEx(test, &addr, rex, nextop, D)
|
||||
#define GETEX32(D) opex=TestEx32O(test, &addr, rex, nextop, D, 0)
|
||||
#define GETEX_OFFS(D, O) opex=TestExO(test, &addr, rex, nextop, D, O)
|
||||
#define GETGX opgx=GetGx(test->emu, &addr, rex, nextop)
|
||||
#define GETEM(D) opem=TestEm(test, &addr, rex, nextop, D)
|
||||
#define GETEM32(D) opem=TestEm32O(test, &addr, rex, nextop, D, 0)
|
||||
#define GETGM opgm=GetGm(test->emu, &addr, rex, nextop)
|
||||
#else
|
||||
#define GETED(D) oped=GetEd(emu, &addr, rex, nextop, D)
|
||||
#define GETED32(D) oped=GetEd32O(emu, &addr, rex, nextop, D, 0)
|
||||
#define GETED_OFFS(D, O) oped=GetEdO(emu, &addr, rex, nextop, D, O)
|
||||
@ -37,6 +58,7 @@
|
||||
#define GETEM(D) opem=GetEm(emu, &addr, rex, nextop, D)
|
||||
#define GETEM32(D) opem=GetEm32O(emu, &addr, rex, nextop, D, 0)
|
||||
#define GETGM opgm=GetGm(emu, &addr, rex, nextop)
|
||||
#endif
|
||||
#define ED oped
|
||||
#define GD opgd
|
||||
#define EB oped
|
||||
@ -47,6 +69,8 @@
|
||||
#define GX opgx
|
||||
#define EM opem
|
||||
#define GM opgm
|
||||
#define FAKEED(D) GetEd(emu, &addr, rex, nextop, D)
|
||||
#define FAKEED32(D) GetEd32O(emu, &addr, rex, nextop, D, 0)
|
||||
|
||||
#define MODREG ((nextop&0xC0)==0xC0)
|
||||
|
||||
|
@ -205,6 +205,11 @@ void FreeX64Emu(x64emu_t **emu)
|
||||
return;
|
||||
printf_log(LOG_DEBUG, "%04d|Free a X86_64 Emu (%p)\n", GetTID(), *emu);
|
||||
|
||||
if((*emu)->test.emu) {
|
||||
internalFreeX64((*emu)->test.emu);
|
||||
box_free((*emu)->test.emu);
|
||||
(*emu)->test.emu = NULL;
|
||||
}
|
||||
internalFreeX64(*emu);
|
||||
|
||||
box_free(*emu);
|
||||
@ -238,6 +243,13 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
|
||||
newemu->top = emu->top;
|
||||
newemu->fpu_stack = emu->fpu_stack;
|
||||
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
|
||||
newemu->df = emu->df;
|
||||
newemu->df_sav = emu->df_sav;
|
||||
newemu->op1 = emu->op1;
|
||||
newemu->op2 = emu->op2;
|
||||
newemu->res = emu->res;
|
||||
newemu->op1_sav = emu->op1_sav;
|
||||
newemu->res_sav = emu->res_sav;
|
||||
newemu->mxcsr = emu->mxcsr;
|
||||
newemu->quit = emu->quit;
|
||||
newemu->error = emu->error;
|
||||
@ -247,6 +259,37 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
|
||||
newemu->regs[_SP].q[0] = emu->regs[_SP].q[0] + (intptr_t)(newst - oldst);
|
||||
}
|
||||
|
||||
void CopyEmu(x64emu_t *newemu, const x64emu_t* emu)
|
||||
{
|
||||
memcpy(newemu->regs, emu->regs, sizeof(emu->regs));
|
||||
memcpy(&newemu->ip, &emu->ip, sizeof(emu->ip));
|
||||
memcpy(&newemu->eflags, &emu->eflags, sizeof(emu->eflags));
|
||||
newemu->old_ip = emu->old_ip;
|
||||
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
|
||||
memcpy(newemu->segs_serial, emu->segs_serial, sizeof(emu->segs_serial));
|
||||
memcpy(newemu->segs_offs, emu->segs_offs, sizeof(emu->segs_offs));
|
||||
memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
|
||||
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
|
||||
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
|
||||
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
|
||||
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
|
||||
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
|
||||
newemu->cw = emu->cw;
|
||||
newemu->sw = emu->sw;
|
||||
newemu->top = emu->top;
|
||||
newemu->fpu_stack = emu->fpu_stack;
|
||||
newemu->df = emu->df;
|
||||
newemu->df_sav = emu->df_sav;
|
||||
newemu->op1 = emu->op1;
|
||||
newemu->op2 = emu->op2;
|
||||
newemu->res = emu->res;
|
||||
newemu->op1_sav = emu->op1_sav;
|
||||
newemu->res_sav = emu->res_sav;
|
||||
newemu->mxcsr = emu->mxcsr;
|
||||
newemu->quit = emu->quit;
|
||||
newemu->error = emu->error;
|
||||
}
|
||||
|
||||
box64context_t* GetEmuContext(x64emu_t* emu)
|
||||
{
|
||||
return emu->context;
|
||||
@ -355,8 +398,8 @@ void ResetFlags(x64emu_t *emu)
|
||||
const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
|
||||
{
|
||||
static char buff[1000];
|
||||
char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
|
||||
" R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"};
|
||||
static const char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
|
||||
" R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"};
|
||||
char tmp[160];
|
||||
buff[0] = '\0';
|
||||
#ifdef HAVE_TRACE
|
||||
|
@ -25,6 +25,15 @@ typedef union multiuint_s {
|
||||
uint64_t u64;
|
||||
} multiuint_t;
|
||||
|
||||
typedef struct x64emu_s x64emu_t;
|
||||
|
||||
typedef struct x64test_s {
|
||||
x64emu_t* emu;
|
||||
uintptr_t memaddr;
|
||||
int memsize;
|
||||
uint8_t mem[16];
|
||||
} x64test_t;
|
||||
|
||||
typedef struct x64emu_s {
|
||||
// cpu
|
||||
reg64_t regs[16];
|
||||
@ -87,7 +96,7 @@ typedef struct x64emu_s {
|
||||
x64_ucontext_t *uc_link; // to handle setcontext
|
||||
|
||||
int type; // EMUTYPE_xxx define
|
||||
|
||||
x64test_t test;
|
||||
} x64emu_t;
|
||||
|
||||
#define EMUTYPE_NONE 0
|
||||
|
143
src/emu/x64run.c
143
src/emu/x64run.c
@ -28,7 +28,11 @@
|
||||
|
||||
int my_setcontext(x64emu_t* emu, void* ucp);
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
int RunTest(x64test_t *test)
|
||||
#else
|
||||
int Run(x64emu_t *emu, int step)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -40,6 +44,10 @@ int Run(x64emu_t *emu, int step)
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2, tmp64u3;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
int step = 0;
|
||||
#endif
|
||||
uintptr_t addr = R_RIP;
|
||||
rex_t rex;
|
||||
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
|
||||
@ -57,9 +65,11 @@ int Run(x64emu_t *emu, int step)
|
||||
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)addr, (void*)R_RSP);
|
||||
|
||||
x64emurun:
|
||||
|
||||
while(1) {
|
||||
#ifdef HAVE_TRACE
|
||||
#ifndef TEST_INTERPRETER
|
||||
while(1)
|
||||
#endif
|
||||
{
|
||||
#if defined(HAVE_TRACE)
|
||||
__builtin_prefetch((void*)addr, 0, 0);
|
||||
emu->prev2_ip = emu->old_ip;
|
||||
if(my_context->dec && (
|
||||
@ -136,24 +146,39 @@ x64emurun:
|
||||
case 0x0F: /* More instructions */
|
||||
switch(rep) {
|
||||
case 1:
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestF20F(test, rex, addr, &step)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunF20F(emu, rex, addr, &step))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(step==2) STEP2;
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestF30F(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunF30F(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = Test0F(test, rex, addr, &step)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = Run0F(emu, rex, addr, &step))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(step==2) STEP2;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if(emu->quit) {
|
||||
@ -255,6 +280,10 @@ x64emurun:
|
||||
GD->sdword[0] = ED->sdword[0]; // meh?
|
||||
break;
|
||||
case 0x64: /* FS: prefix */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = Test64(test, rex, _FS, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = Run64(emu, rex, _FS, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -263,8 +292,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x65: /* GS: prefix */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = Test64(test, rex, _GS, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = Run64(emu, rex, _GS, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -273,8 +307,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x66: /* 16bits prefix */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = Test66(test, rex, rep, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = Run66(emu, rex, rep, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -283,8 +322,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x67: /* reduce EASize prefix */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = Test67(test, rex, rep, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = Run67(emu, rex, rep, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -293,6 +337,7 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x68: /* Push Id */
|
||||
Push(emu, F32S64);
|
||||
@ -326,8 +371,10 @@ x64emurun:
|
||||
case 0x6E: /* OUTSB DX */
|
||||
case 0x6F: /* OUTSL DX */
|
||||
// this is a privilege opcode...
|
||||
#ifndef TEST_INTERPRETOR
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
|
||||
GOCOND(0x70
|
||||
@ -416,7 +463,7 @@ x64emurun:
|
||||
break;
|
||||
case 0x86: /* XCHG Eb,Gb */
|
||||
nextop = F8;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
if(MODREG) { // reg / reg: no lock
|
||||
@ -441,7 +488,7 @@ x64emurun:
|
||||
break;
|
||||
case 0x87: /* XCHG Ed,Gd */
|
||||
nextop = F8;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@ -527,8 +574,12 @@ x64emurun:
|
||||
break;
|
||||
case 0x8D: /* LEA Gd,M */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
#ifdef TEST_INTERPRETER
|
||||
oped=GetEd(emu, &addr, rex, nextop, 0);
|
||||
#else
|
||||
GETED(0);
|
||||
#endif
|
||||
if(rex.w)
|
||||
GD->q[0] = (uint64_t)ED;
|
||||
else
|
||||
@ -630,7 +681,9 @@ x64emurun:
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
tmp64u = (rep)?R_RCX:1L;
|
||||
while(tmp64u) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint8_t*)R_RDI = *(uint8_t*)R_RSI;
|
||||
#endif
|
||||
R_RDI += tmp8s;
|
||||
R_RSI += tmp8s;
|
||||
--tmp64u;
|
||||
@ -645,7 +698,9 @@ x64emurun:
|
||||
tmp8s *= 8;
|
||||
while(tmp64u) {
|
||||
--tmp64u;
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint64_t*)R_RDI = *(uint64_t*)R_RSI;
|
||||
#endif
|
||||
R_RDI += tmp8s;
|
||||
R_RSI += tmp8s;
|
||||
}
|
||||
@ -653,7 +708,9 @@ x64emurun:
|
||||
tmp8s *= 4;
|
||||
while(tmp64u) {
|
||||
--tmp64u;
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint32_t*)R_RDI = *(uint32_t*)R_RSI;
|
||||
#endif
|
||||
R_RDI += tmp8s;
|
||||
R_RSI += tmp8s;
|
||||
}
|
||||
@ -793,7 +850,9 @@ x64emurun:
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
tmp64u = (rep)?R_RCX:1L;
|
||||
while(tmp64u) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint8_t*)R_RDI = R_AL;
|
||||
#endif
|
||||
R_RDI += tmp8s;
|
||||
--tmp64u;
|
||||
}
|
||||
@ -808,7 +867,9 @@ x64emurun:
|
||||
tmp64u = (rep)?R_RCX:1L;
|
||||
if((rex.w))
|
||||
while(tmp64u) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint64_t*)R_RDI = R_RAX;
|
||||
#endif
|
||||
R_RDI += tmp8s;
|
||||
--tmp64u;
|
||||
}
|
||||
@ -1079,14 +1140,18 @@ x64emurun:
|
||||
break;
|
||||
|
||||
case 0xCC: /* INT 3 */
|
||||
#ifndef TEST_INTERPRETER
|
||||
x64Int3(emu, &addr);
|
||||
if(emu->quit) goto fini; // R_RIP is up to date when returning from x64Int3
|
||||
addr = R_RIP;
|
||||
#endif
|
||||
break;
|
||||
case 0xCD: /* INT n */
|
||||
// this is a privilege opcode...
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
@ -1165,6 +1230,10 @@ x64emurun:
|
||||
R_AL = *(uint8_t*)(R_RBX + R_AL);
|
||||
break;
|
||||
case 0xD8: /* x87 opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestD8(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunD8(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1173,8 +1242,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0xD9: /* x87 opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestD9(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunD9(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1183,8 +1257,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0xDA: /* x87 opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestDA(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunDA(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1193,8 +1272,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0xDB: /* x87 opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestDB(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunDB(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1203,8 +1287,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0xDC: /* x87 opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestDC(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunDC(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1213,8 +1302,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0xDD: /* x87 opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestDD(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunDD(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1223,8 +1317,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0xDE: /* x87 opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestDE(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunDE(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1233,8 +1332,13 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0xDF: /* x87 opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestDF(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunDF(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1243,6 +1347,7 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0xE0: /* LOOPNZ */
|
||||
CHECK_FLAGS(emu);
|
||||
@ -1278,8 +1383,10 @@ x64emurun:
|
||||
case 0xE6: /* OUT XX, AL */
|
||||
case 0xE7: /* OUT XX, EAX */
|
||||
// this is a privilege opcode...
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
@ -1303,10 +1410,16 @@ x64emurun:
|
||||
case 0xEE: /* OUT DX, AL */
|
||||
case 0xEF: /* OUT DX, EAX */
|
||||
// this is a privilege opcode...
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
case 0xF0: /* LOCK prefix */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = TestF0(test, rex, addr)))
|
||||
unimp = 1;
|
||||
#else
|
||||
if(!(addr = RunF0(emu, rex, addr))) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
@ -1315,12 +1428,15 @@ x64emurun:
|
||||
R_RIP = addr;
|
||||
goto fini;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xF4: /* HLT */
|
||||
// this is a privilege opcode...
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
case 0xF5: /* CMC */
|
||||
CHECK_FLAGS(emu);
|
||||
@ -1529,7 +1645,15 @@ x64emurun:
|
||||
break;
|
||||
case 6: /* Push Ed */
|
||||
tmp64u = ED->q[0]; // rex.w ignored
|
||||
#ifdef TEST_INTERPRETER
|
||||
R_RSP -=8;
|
||||
if(test->memsize!=8)
|
||||
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
|
||||
test->memsize = 8;
|
||||
test->memaddr = R_RSP;
|
||||
#else
|
||||
Push(emu, tmp64u); // avoid potential issue with push [esp+...]
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
|
||||
@ -1547,6 +1671,7 @@ x64emurun:
|
||||
|
||||
|
||||
fini:
|
||||
#ifndef TEST_INTERPRETER
|
||||
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit);
|
||||
if(unimp) {
|
||||
emu->quit = 1;
|
||||
@ -1570,5 +1695,11 @@ fini:
|
||||
addr = R_RIP;
|
||||
goto x64emurun;
|
||||
}
|
||||
#else
|
||||
if(unimp) {
|
||||
printf_log(LOG_INFO, "Warning, inimplemented opcode in Test Interpreter\n");
|
||||
} else
|
||||
addr = R_RIP;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,7 +28,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test0F(x64test_t *test, rex_t rex, uintptr_t addr, int *step)
|
||||
#else
|
||||
uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -42,27 +46,38 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opem, *opgm, eam1;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t *emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x05: /* SYSCALL */
|
||||
#ifndef TEST_INTERPRETER
|
||||
R_RIP = addr;
|
||||
x64Syscall(emu);
|
||||
#endif
|
||||
break;
|
||||
case 0x06: /* CLTS */
|
||||
// this is a privilege opcode...
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x08: /* INVD */
|
||||
case 0x09: /* WBINVD */
|
||||
// this is a privilege opcode...
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x0B: /* UD2 */
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x0D:
|
||||
@ -152,14 +167,16 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
|
||||
case 0x1F: /* NOP (multi-byte) */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
FAKEED(0);
|
||||
break;
|
||||
case 0x20: /* MOV REG, crX */
|
||||
case 0x21: /* MOV REG, drX */
|
||||
case 0x22: /* MOV cxR, REG */
|
||||
case 0x23: /* MOV drX, REG */
|
||||
// this is a privilege opcode...
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x28: /* MOVAPS Gx,Ex */
|
||||
@ -800,7 +817,15 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
|
||||
else
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
#endif
|
||||
}
|
||||
if(rex.w) {
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@ -843,7 +868,15 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
|
||||
else
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
#endif
|
||||
}
|
||||
if(rex.w) {
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@ -892,27 +925,33 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FXSAVE Ed */
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(rex.w)
|
||||
fpu_fxsave64(emu, ED);
|
||||
else
|
||||
fpu_fxsave32(emu, ED);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* FXRSTOR Ed */
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(rex.w)
|
||||
fpu_fxrstor64(emu, ED);
|
||||
else
|
||||
fpu_fxrstor32(emu, ED);
|
||||
#endif
|
||||
break;
|
||||
case 2: /* LDMXCSR Md */
|
||||
emu->mxcsr.x32 = ED->dword[0];
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(box64_sse_flushto0)
|
||||
applyFlushTo0(emu);
|
||||
#endif
|
||||
break;
|
||||
case 3: /* STMXCSR Md */
|
||||
ED->dword[0] = emu->mxcsr.x32;
|
||||
break;
|
||||
case 7: /* CLFLUSH Ed */
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(box64_dynarec)
|
||||
cleanDBFromAddressRange((uintptr_t)ED, 8, 0);
|
||||
#endif
|
||||
@ -975,7 +1014,15 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
|
||||
else
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
#endif
|
||||
}
|
||||
if(rex.w) {
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
@ -1105,7 +1152,15 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
|
||||
else
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
#endif
|
||||
}
|
||||
if(rex.w) {
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@ -1289,6 +1344,10 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memsize = 16;
|
||||
((uint64_t*)test->mem)[1] = ((uint64_t*)test->memaddr)[1];
|
||||
#endif
|
||||
switch((nextop>>3)&7) {
|
||||
case 1:
|
||||
if(rex.w) {
|
||||
|
@ -22,7 +22,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test64(x64test_t *test, rex_t rex, int seg, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -35,6 +39,9 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
int rep;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);
|
||||
|
||||
opcode = F8;
|
||||
|
@ -25,7 +25,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test66(x64test_t *test, rex_t rex, int rep, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -37,6 +41,9 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2, tmp64u3;
|
||||
reg64_t *oped, *opgd;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
|
||||
opcode = F8;
|
||||
|
||||
@ -105,7 +112,11 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
GO(0x30, xor) /* XOR 0x31 ~> 0x35 */
|
||||
|
||||
case 0x0F: /* more opcdes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test660F(test, rex, addr);
|
||||
#else
|
||||
return Run660F(emu, rex, addr);
|
||||
#endif
|
||||
|
||||
case 0x39:
|
||||
nextop = F8;
|
||||
@ -133,9 +144,17 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x64: /* FS: */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6664(test, rex, _FS, addr);
|
||||
#else
|
||||
return Run6664(emu, rex, _FS, addr);
|
||||
#endif
|
||||
case 0x65: /* GS: */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6664(test, rex, _GS, addr);
|
||||
#else
|
||||
return Run6664(emu, rex, _GS, addr);
|
||||
#endif
|
||||
|
||||
case 0x69: /* IMUL Gw,Ew,Iw */
|
||||
nextop = F8;
|
||||
@ -257,8 +276,12 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
break;
|
||||
case 0x8D: /* LEA Gw,M */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
#ifdef TEST_INTERPRETER
|
||||
oped=GetEd(emu, &addr, rex, nextop, 0);
|
||||
#else
|
||||
GETED(0);
|
||||
#endif
|
||||
if(rex.w)
|
||||
GD->q[0] = (uint64_t)ED;
|
||||
else
|
||||
@ -427,13 +450,17 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
tmp64u = (rep)?R_RCX:1L;
|
||||
if((rex.w))
|
||||
while(tmp64u) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint64_t*)R_RDI = R_RAX;
|
||||
#endif
|
||||
R_RDI += tmp8s;
|
||||
--tmp64u;
|
||||
}
|
||||
else
|
||||
while(tmp64u) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint16_t*)R_RDI = R_AX;
|
||||
#endif
|
||||
R_RDI += tmp8s;
|
||||
--tmp64u;
|
||||
}
|
||||
@ -609,10 +636,18 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0xD9: /* x87 opcdes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test66D9(test, rex, addr);
|
||||
#else
|
||||
return Run66D9(emu, rex, addr);
|
||||
#endif
|
||||
|
||||
case 0xDD: /* x87 opcdes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test66DD(test, rex, addr);
|
||||
#else
|
||||
return Run66DD(emu, rex, addr);
|
||||
#endif
|
||||
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
@ -621,7 +656,11 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0xF0: /* LOCK: */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test66F0(test, rex, addr);
|
||||
#else
|
||||
return Run66F0(emu, rex, addr);
|
||||
#endif
|
||||
|
||||
case 0xF7: /* GRP3 Ew(,Iw) */
|
||||
nextop = F8;
|
||||
|
@ -43,7 +43,11 @@ static uint8_t ff_mult(uint8_t a, uint8_t b)
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test660F(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -106,6 +110,9 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
@ -162,7 +169,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
|
||||
case 0x1F: /* NOP (multi-byte) */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
FAKEED(0);
|
||||
break;
|
||||
|
||||
case 0x28: /* MOVAPD Gx, Ex */
|
||||
@ -1564,7 +1571,15 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:1)));
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
|
||||
else
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
#endif
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<tmp8u)) {
|
||||
|
@ -22,12 +22,19 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test6664(x64test_t *test, rex_t rex, int seg, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run6664(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);
|
||||
|
||||
opcode = F8;
|
||||
|
@ -22,10 +22,17 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test66D9(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run66D9(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
@ -84,7 +91,9 @@ uintptr_t Run66D9(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 6: /* FNSTENV m */
|
||||
// warning, incomplete
|
||||
GETEW(0);
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 1);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -22,10 +22,17 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test66DD(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
@ -92,6 +99,7 @@ uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 6: /* FNSAVE m94byte */
|
||||
GETEW(0);
|
||||
// ENV first...
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 1);
|
||||
// save the STx
|
||||
{
|
||||
@ -102,6 +110,7 @@ uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
reset_fpu(emu);
|
||||
break;
|
||||
default:
|
||||
|
@ -25,7 +25,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test66F0(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -37,7 +41,9 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#ifdef USE_CAS
|
||||
uint64_t tmpcas;
|
||||
#endif
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
rex.rex = 0;
|
||||
@ -58,7 +64,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp16u = native_lock_read_h(EW);
|
||||
cmp16(emu, R_AX, tmp16u);
|
||||
@ -85,7 +91,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w) {
|
||||
do {
|
||||
tmp64u = native_lock_read_dd(ED);
|
||||
@ -128,7 +134,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
#define GO(B, OP) \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
@ -209,7 +215,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETED((opcode==0x83)?1:2);
|
||||
tmp64s = (opcode==0x83)?(F8S):(F16S);
|
||||
tmp64u = (uint64_t)tmp64s;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(MODREG)
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
|
||||
@ -253,7 +259,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w)
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned
|
||||
@ -295,7 +301,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w)
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned
|
||||
|
@ -22,7 +22,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test67(x64test_t *test, rex_t rex, int rep, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -32,7 +36,9 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
int32_t tmp32s;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
while(opcode==0x67)
|
||||
@ -146,7 +152,11 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6766(test, rex, rep, addr);
|
||||
#else
|
||||
return Run6766(emu, rex, rep, addr);
|
||||
#endif
|
||||
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
|
@ -26,7 +26,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test670F(x64test_t *test, rex_t rex, int rep, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
(void)rep;
|
||||
uint8_t opcode;
|
||||
@ -40,6 +44,9 @@ uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
sse_regs_t *opex, *opgx, eax1; (void)eax1;
|
||||
mmx87_regs_t *opem, *opgm, eam1; (void)opem; (void)opgm; (void)eam1;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
@ -99,8 +106,10 @@ uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
switch(rep) {
|
||||
case 0: /* UD1 Ed */
|
||||
nextop = F8;
|
||||
GETED32(0);
|
||||
FAKEED32(0);
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -25,7 +25,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test6766(x64test_t *test, rex_t rex, int rep, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run6766(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
// Hmmmm....
|
||||
(void)rep;
|
||||
@ -39,7 +43,9 @@ uintptr_t Run6766(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
int64_t tmp64s; (void)tmp64s;
|
||||
uint64_t tmp64u, tmp64u2, tmp64u3; (void)tmp64u; (void)tmp64u2; (void)tmp64u3;
|
||||
reg64_t *oped, *opgd; (void)oped; (void)opgd;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
|
||||
@ -59,7 +65,11 @@ uintptr_t Run6766(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F: /* more opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test67660F(test, rex, addr);
|
||||
#else
|
||||
return Run67660F(emu, rex, addr);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
@ -22,7 +22,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test67660F(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run67660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -36,7 +40,9 @@ uintptr_t Run67660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
uint64_t tmp64u; (void)tmp64u;
|
||||
reg64_t *oped, *opgd; (void)oped; (void)opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
@ -1225,6 +1225,26 @@ reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t del
|
||||
} else return GetECommon(emu, addr, rex, m, delta);
|
||||
}
|
||||
|
||||
reg64_t* TestEb(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
// rex ignored here
|
||||
uint8_t m = v&0xC7; // filter Eb
|
||||
if(m>=0xC0) {
|
||||
if(rex.rex) {
|
||||
return &test->emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
int lowhigh = (m&4)>>2;
|
||||
return (reg64_t *)(((char*)(&test->emu->regs[(m&0x03)]))+lowhigh); //?
|
||||
}
|
||||
} else {
|
||||
reg64_t* ret = GetECommon(test->emu, addr, rex, m, delta);
|
||||
test->memsize = 1;
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
test->mem[0] = ret->byte[0];
|
||||
return (reg64_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
// rex ignored here
|
||||
@ -1239,6 +1259,26 @@ reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t de
|
||||
} else return GetECommonO(emu, addr, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
reg64_t* TestEbO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
// rex ignored here
|
||||
uint8_t m = v&0xC7; // filter Eb
|
||||
if(m>=0xC0) {
|
||||
if(rex.rex) {
|
||||
return &test->emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
int lowhigh = (m&4)>>2;
|
||||
return (reg64_t *)(((char*)(&test->emu->regs[(m&0x03)]))+lowhigh); //?
|
||||
}
|
||||
} else {
|
||||
reg64_t* ret = GetECommonO(test->emu, addr, rex, m, delta, offset);
|
||||
test->memsize = 1;
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
test->mem[0] = ret->byte[0];
|
||||
return (reg64_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1247,6 +1287,23 @@ reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t del
|
||||
} else return GetECommon(emu, addr, rex, m, delta);
|
||||
}
|
||||
|
||||
reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &test->emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
reg64_t* ret = GetECommon(test->emu, addr, rex, m, delta);
|
||||
test->memsize = 4<<rex.w;
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = ret->q[0];
|
||||
else
|
||||
*(uint32_t*)test->mem = ret->dword[0];
|
||||
return (reg64_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1255,6 +1312,23 @@ reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t de
|
||||
} else return GetECommonO(emu, addr, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
reg64_t* TestEdO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &test->emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
reg64_t* ret = GetECommonO(test->emu, addr, rex, m, delta, offset);
|
||||
test->memsize = 4<<rex.w;
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = ret->q[0];
|
||||
else
|
||||
*(uint32_t*)test->mem = ret->dword[0];
|
||||
return (reg64_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1263,6 +1337,23 @@ reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t
|
||||
} else return GetECommon32O(emu, addr, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
reg64_t* TestEd32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &test->emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
reg64_t* ret = GetECommon32O(test->emu, addr, rex, m, delta, offset);
|
||||
test->memsize = 4<<rex.w;
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = ret->q[0];
|
||||
else
|
||||
*(uint32_t*)test->mem = ret->dword[0];
|
||||
return (reg64_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetEb32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Eb
|
||||
@ -1276,7 +1367,27 @@ reg64_t* GetEb32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t
|
||||
} else return GetECommon32O(emu, addr, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
reg64_t* TestEb32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Eb
|
||||
if(m>=0xC0) {
|
||||
if(rex.rex) {
|
||||
return &test->emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
int lowhigh = (m&4)>>2;
|
||||
return (reg64_t *)(((char*)(&test->emu->regs[(m&0x03)]))+lowhigh); //?
|
||||
}
|
||||
} else {
|
||||
reg64_t* ret = GetECommon32O(test->emu, addr, rex, m, delta, offset);
|
||||
test->memsize = 1;
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
test->mem[0] = ret->byte[0];
|
||||
return (reg64_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
#define GetEw GetEd
|
||||
#define TestEw TestEd
|
||||
|
||||
reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
|
||||
{
|
||||
@ -1307,6 +1418,39 @@ reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* TestEw16(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v)
|
||||
{
|
||||
(void)rex;
|
||||
x64emu_t* emu = test->emu;
|
||||
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->regs[(m&0x07)];
|
||||
} else {
|
||||
uintptr_t base = 0;
|
||||
switch(m&7) {
|
||||
case 0: base = R_BX+R_SI; break;
|
||||
case 1: base = R_BX+R_DI; break;
|
||||
case 2: base = R_BP+R_SI; break;
|
||||
case 3: base = R_BP+R_DI; break;
|
||||
case 4: base = R_SI; break;
|
||||
case 5: base = R_DI; break;
|
||||
case 6: base = R_BP; break;
|
||||
case 7: base = R_BX; break;
|
||||
}
|
||||
switch((m>>6)&3) {
|
||||
case 0: if(m==6) base = F16(addr); break;
|
||||
case 1: base += F8S(addr); break;
|
||||
case 2: base += F16S(addr); break;
|
||||
// case 3 is C0..C7, already dealt with
|
||||
}
|
||||
test->memsize = 2;
|
||||
*(uint16_t*)test->mem = *(uint16_t*)base;
|
||||
test->memaddr = (uintptr_t)base;
|
||||
return (reg64_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset)
|
||||
{
|
||||
(void)rex;
|
||||
@ -1336,6 +1480,39 @@ reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintpt
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* TestEw16off(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset)
|
||||
{
|
||||
(void)rex;
|
||||
x64emu_t* emu = test->emu;
|
||||
|
||||
uint32_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->regs[(m&0x07)];
|
||||
} else {
|
||||
uint32_t base = 0;
|
||||
switch(m&7) {
|
||||
case 0: base = R_BX+R_SI; break;
|
||||
case 1: base = R_BX+R_DI; break;
|
||||
case 2: base = R_BP+R_SI; break;
|
||||
case 3: base = R_BP+R_DI; break;
|
||||
case 4: base = R_SI; break;
|
||||
case 5: base = R_DI; break;
|
||||
case 6: base = R_BP; break;
|
||||
case 7: base = R_BX; break;
|
||||
}
|
||||
switch((m>>6)&3) {
|
||||
case 0: if(m==6) base = F16(addr); break;
|
||||
case 1: base += F8S(addr); break;
|
||||
case 2: base += F16S(addr); break;
|
||||
// case 3 is C0..C7, already dealt with
|
||||
}
|
||||
test->memsize = 2;
|
||||
*(uint16_t*)test->mem = *(uint16_t*)(base+offset);
|
||||
test->memaddr = (uintptr_t)(base+offset);
|
||||
return (reg64_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
mmx87_regs_t* GetEm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1344,6 +1521,20 @@ mmx87_regs_t* GetEm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_
|
||||
} else return (mmx87_regs_t*)GetECommon(emu, addr, rex, m, delta);
|
||||
}
|
||||
|
||||
mmx87_regs_t* TestEm(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &test->emu->mmx[m&0x07];
|
||||
} else {
|
||||
mmx87_regs_t* ret = (mmx87_regs_t*)GetECommon(test->emu, addr, rex, m, delta);
|
||||
test->memsize = 8;
|
||||
*(uint64_t*)test->mem = ret->q;
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
return (mmx87_regs_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
sse_regs_t* GetEx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1352,6 +1543,22 @@ sse_regs_t* GetEx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t
|
||||
} else return (sse_regs_t*)GetECommon(emu, addr, rex, m, delta);
|
||||
}
|
||||
|
||||
sse_regs_t* TestEx(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
test->memsize=0;
|
||||
return &test->emu->xmm[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
sse_regs_t* ret = (sse_regs_t*)GetECommon(test->emu, addr, rex, m, delta);
|
||||
test->memsize = 16;
|
||||
((uint64_t*)test->mem)[0] = ret->q[0];
|
||||
((uint64_t*)test->mem)[1] = ret->q[1];
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
return (sse_regs_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
sse_regs_t* GetExO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1360,6 +1567,21 @@ sse_regs_t* GetExO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t
|
||||
} else return (sse_regs_t*)GetECommonO(emu, addr, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
sse_regs_t* TestExO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &test->emu->xmm[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
sse_regs_t* ret = (sse_regs_t*)GetECommonO(test->emu, addr, rex, m, delta, offset);
|
||||
test->memsize = 16;
|
||||
((uint64_t*)test->mem)[0] = ret->q[0];
|
||||
((uint64_t*)test->mem)[1] = ret->q[1];
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
return (sse_regs_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
sse_regs_t* GetEx32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1368,6 +1590,21 @@ sse_regs_t* GetEx32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8
|
||||
} else return (sse_regs_t*)GetECommon32O(emu, addr, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
sse_regs_t* TestEx32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &test->emu->xmm[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
sse_regs_t* ret = (sse_regs_t*)GetECommon32O(test->emu, addr, rex, m, delta, offset);
|
||||
test->memsize = 16;
|
||||
((uint64_t*)test->mem)[0] = ret->q[0];
|
||||
((uint64_t*)test->mem)[1] = ret->q[1];
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
return (sse_regs_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
@ -1376,6 +1613,19 @@ mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uin
|
||||
} else return (mmx87_regs_t*)GetECommon32O(emu, addr, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
mmx87_regs_t* TestEm32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &test->emu->mmx[(m&0x07)];
|
||||
} else {
|
||||
mmx87_regs_t* ret = (mmx87_regs_t*)GetECommon32O(test->emu, addr, rex, m, delta, offset);
|
||||
test->memsize = 8;
|
||||
*(uint64_t*)test->mem = ret->q;
|
||||
test->memaddr = (uintptr_t)ret;
|
||||
return (mmx87_regs_t*)test->mem;
|
||||
}
|
||||
}
|
||||
|
||||
reg64_t* GetGd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
|
||||
{
|
||||
|
@ -26,12 +26,16 @@ static inline uint64_t Pop(x64emu_t *emu)
|
||||
return *st;
|
||||
}
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
#define Push(E, V) do{R_RSP -=8; test->memsize = 8; *(uint64_t*)test->mem = (V); test->memaddr = R_RSP;}while(0)
|
||||
#define Push16(E, V) do{R_RSP -=2; test->memsize = 2; *(uint16_t*)test->mem = (V); test->memaddr = R_RSP;}while(0)
|
||||
#else
|
||||
static inline void Push(x64emu_t *emu, uint64_t v)
|
||||
{
|
||||
R_RSP -= 8;
|
||||
*((uint64_t*)R_RSP) = v;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
|
||||
|
||||
@ -39,24 +43,39 @@ reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_
|
||||
reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetECommon32O(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
|
||||
reg64_t* TestEb(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
|
||||
reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* TestEbO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
|
||||
reg64_t* TestEd(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
|
||||
reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* TestEdO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* TestEd32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetEb32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* TestEb32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
#define GetEw GetEd
|
||||
#define TestEw TestEd
|
||||
#define GetEw32O GetEd32O
|
||||
#define TestEw32O TestEd32O
|
||||
reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
|
||||
reg64_t* TestEw16(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v);
|
||||
reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset);
|
||||
reg64_t* TestEw16off(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset);
|
||||
mmx87_regs_t* GetEm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
|
||||
mmx87_regs_t* TestEm(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
|
||||
sse_regs_t* GetEx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
|
||||
sse_regs_t* TestEx(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
|
||||
sse_regs_t* GetExO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
sse_regs_t* TestExO(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
sse_regs_t* GetEx32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
sse_regs_t* TestEx32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetGd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
|
||||
#define GetGw GetGd
|
||||
reg64_t* GetGb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
|
||||
mmx87_regs_t* GetGm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
|
||||
mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
mmx87_regs_t* TestEm32O(x64test_t *test, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
sse_regs_t* GetGx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
|
||||
|
||||
void UpdateFlags(x64emu_t *emu);
|
||||
@ -88,6 +107,31 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr);
|
||||
uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step);
|
||||
uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr);
|
||||
|
||||
uintptr_t Test0F(x64test_t *test, rex_t rex, uintptr_t addr, int *step);
|
||||
uintptr_t Test64(x64test_t *test, rex_t rex, int seg, uintptr_t addr);
|
||||
uintptr_t Test66(x64test_t *test, rex_t rex, int rep, uintptr_t addr);
|
||||
uintptr_t Test660F(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t Test6664(x64test_t *test, rex_t rex, int seg, uintptr_t addr);
|
||||
uintptr_t Test66D9(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t Test66DD(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t Test66F0(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t Test67(x64test_t *test, rex_t rex, int rep, uintptr_t addr);
|
||||
uintptr_t Test670F(x64test_t *test, rex_t rex, int rep, uintptr_t addr);
|
||||
uintptr_t Test6766(x64test_t *test, rex_t rex, int rep, uintptr_t addr);
|
||||
uintptr_t Test67660F(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestD8(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestD9(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestDA(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestDB(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestDC(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestDD(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestDE(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestDF(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestF0(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
uintptr_t TestF20F(x64test_t *test, rex_t rex, uintptr_t addr, int *step);
|
||||
uintptr_t TestF30F(x64test_t *test, rex_t rex, uintptr_t addr);
|
||||
|
||||
|
||||
void x64Syscall(x64emu_t *emu);
|
||||
void x64Int3(x64emu_t* emu, uintptr_t* addr);
|
||||
x64emu_t* x64emu_fork(x64emu_t* e, int forktype);
|
||||
|
@ -22,11 +22,18 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestD8(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
float f;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
|
@ -22,13 +22,20 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestD9(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
uint64_t ll;
|
||||
float f;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
@ -228,6 +235,9 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 0xEF:
|
||||
return 0;
|
||||
default:
|
||||
#ifdef TEST_INTERPRETER
|
||||
rex.w = 0; // hack, 32bit access only here
|
||||
#endif
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FLD ST0, Ed float */
|
||||
GETED(0);
|
||||
@ -256,7 +266,9 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 6: /* FNSTENV m */
|
||||
// warning, incomplete
|
||||
GETED(0);
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 0);
|
||||
#endif
|
||||
// intruction pointer: 48bits
|
||||
// data (operand) pointer: 48bits
|
||||
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
|
||||
|
@ -22,10 +22,17 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDA(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
@ -96,6 +103,9 @@ uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 0xFD:
|
||||
return 0;
|
||||
default:
|
||||
#ifdef TEST_INTERPRETER
|
||||
rex.w = 0; // hack, 32bit access only here
|
||||
#endif
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FIADD ST0, Ed int */
|
||||
GETED(0);
|
||||
|
@ -22,11 +22,18 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDB(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
@ -125,6 +132,9 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 0xE7:
|
||||
return 0;
|
||||
default:
|
||||
#ifdef TEST_INTERPRETER
|
||||
rex.w = 0; // hack, 32bit access only here
|
||||
#endif
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FILD ST0, Ed */
|
||||
GETED(0);
|
||||
@ -160,6 +170,10 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 5: /* FLD ST0, Et */
|
||||
GETED(0);
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memsize = 10;
|
||||
memcpy(ED, (void*)test->memaddr, 10);
|
||||
#endif
|
||||
fpu_do_push(emu);
|
||||
memcpy(&STld(0).ld, ED, 10);
|
||||
LD2D(&STld(0), &ST(0).d);
|
||||
@ -167,6 +181,9 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 7: /* FSTP tbyte */
|
||||
GETED(0);
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memsize = 10;
|
||||
#endif
|
||||
if(ST0.q!=STld(0).uref)
|
||||
D2LD(&ST0.d, ED);
|
||||
else
|
||||
|
@ -22,10 +22,17 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDC(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
@ -111,6 +118,9 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
ST(nextop&7).d /= ST0.d;
|
||||
break;
|
||||
default:
|
||||
#ifdef TEST_INTERPRETER
|
||||
rex.w = 1; // hack, 64bit access only here
|
||||
#endif
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FADD ST0, double */
|
||||
|
@ -22,10 +22,17 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDD(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
@ -110,6 +117,9 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
return 0;
|
||||
|
||||
default:
|
||||
#ifdef TEST_INTERPRETER
|
||||
rex.w = 1; // hack, mostly 64bit access only here
|
||||
#endif
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FLD double */
|
||||
GETED(0);
|
||||
@ -147,6 +157,7 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETED(0);
|
||||
// ENV first...
|
||||
// warning, incomplete
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 0);
|
||||
// save the STx
|
||||
{
|
||||
@ -157,10 +168,14 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
reset_fpu(emu);
|
||||
break;
|
||||
case 7: /* FNSTSW m2byte */
|
||||
GETED(0);
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memsize = 2;
|
||||
#endif
|
||||
emu->sw.f.F87_TOP = emu->top&7;
|
||||
*(uint16_t*)ED = emu->sw.x16;
|
||||
break;
|
||||
|
@ -22,10 +22,17 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDE(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
@ -127,6 +134,9 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
return 0;
|
||||
|
||||
default:
|
||||
#ifdef TEST_INTERPRETER
|
||||
rex.w = 0; // hack, 32bit access only here
|
||||
#endif
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FIADD ST0, Ew int */
|
||||
GETEW(0);
|
||||
|
@ -22,12 +22,19 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDF(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int16_t tmp16s;
|
||||
int64_t tmp64s;
|
||||
reg64_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
@ -144,10 +151,17 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 4: /* FBLD ST0, tbytes */
|
||||
GETED(0);
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memsize = 10;
|
||||
memcpy(ED, (void*)test->memaddr, 10);
|
||||
#endif
|
||||
fpu_do_push(emu);
|
||||
fpu_fbld(emu, (uint8_t*)ED);
|
||||
break;
|
||||
case 5: /* FILD ST0, Gq */
|
||||
#ifdef TEST_INTERPRETER
|
||||
rex.w = 1; // hack, 64bit access
|
||||
#endif
|
||||
GETED(0);
|
||||
tmp64s = ED->sq[0];
|
||||
fpu_do_push(emu);
|
||||
@ -157,10 +171,16 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 6: /* FBSTP tbytes, ST0 */
|
||||
GETED(0);
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memsize = 10;
|
||||
#endif
|
||||
fpu_fbst(emu, (uint8_t*)ED);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 7: /* FISTP i64 */
|
||||
#ifdef TEST_INTERPRETER
|
||||
rex.w = 1; // hack, 64bits access
|
||||
#endif
|
||||
GETED(0);
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
ED->sq[0] = STll(0).sq;
|
||||
|
@ -26,7 +26,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestF0(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -39,6 +43,9 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#ifdef USE_CAS
|
||||
uint64_t tmpcas;
|
||||
#endif
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
@ -49,7 +56,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
@ -181,9 +188,17 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
|
||||
else
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
#endif
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(MODREG) {
|
||||
@ -258,7 +273,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETGB;
|
||||
GETEB(0);
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u = native_lock_read_b(EB);
|
||||
cmp8(emu, R_AL, tmp8u);
|
||||
@ -284,7 +299,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w)
|
||||
if(((uintptr_t)ED)&7) {
|
||||
do {
|
||||
@ -360,10 +375,18 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:2)));
|
||||
if(rex.w)
|
||||
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
|
||||
else
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=rex.w?63:31;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w)
|
||||
do {
|
||||
tmp64u = native_lock_read_dd(ED);
|
||||
@ -437,7 +460,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
do {
|
||||
@ -491,7 +514,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w) {
|
||||
do {
|
||||
tmp8u&=63;
|
||||
@ -543,7 +566,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
do {
|
||||
@ -597,7 +620,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u = native_lock_read_b(EB);
|
||||
tmp8u2 = add8(emu, tmp8u, GB);
|
||||
@ -615,7 +638,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w) {
|
||||
do {
|
||||
tmp64u = native_lock_read_dd(ED);
|
||||
@ -665,7 +688,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 1:
|
||||
CHECK_FLAGS(emu);
|
||||
GETGD;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w)
|
||||
do {
|
||||
native_lock_read_dq(&tmp64u, &tmp64u2, ED);
|
||||
@ -695,6 +718,9 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memsize = 16;
|
||||
#endif
|
||||
tmp64u = ED->q[0];
|
||||
tmp64u2= ED->q[1];
|
||||
if(R_RAX == tmp64u && R_RDX == tmp64u2) {
|
||||
@ -707,6 +733,9 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
R_RDX = tmp64u2;
|
||||
}
|
||||
} else {
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memsize = 8;
|
||||
#endif
|
||||
tmp32u = ED->dword[0];
|
||||
tmp32u2= ED->dword[1];
|
||||
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
|
||||
@ -733,13 +762,17 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test66F0(test, rex, addr);
|
||||
#else
|
||||
return Run66F0(emu, rex, addr); // more opcode F0 66 and 66 F0 is the same
|
||||
#endif
|
||||
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
GETEB(1);
|
||||
tmp8u = F8;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp8u2 = native_lock_read_b(EB); tmp8u2 = add8(emu, tmp8u2, tmp8u);} while(native_lock_write_b(EB, tmp8u2)); break;
|
||||
case 1: do { tmp8u2 = native_lock_read_b(EB); tmp8u2 = or8(emu, tmp8u2, tmp8u);} while(native_lock_write_b(EB, tmp8u2)); break;
|
||||
@ -774,7 +807,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
tmp64u = (uint64_t)tmp64s;
|
||||
} else
|
||||
tmp64u = F32S64;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w) {
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp64u2 = native_lock_read_dd(ED); tmp64u2 = add64(emu, tmp64u2, tmp64u);} while(native_lock_write_dd(ED, tmp64u2)); break;
|
||||
@ -853,7 +886,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
|
||||
case 0x86: /* XCHG Eb,Gb */
|
||||
nextop = F8;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
if(MODREG) { // reg / reg: no lock
|
||||
@ -880,7 +913,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 0x87: /* XCHG Ed,Gd */
|
||||
nextop = F8;
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@ -926,7 +959,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETEB((tmp8u<2)?1:0);
|
||||
switch(tmp8u) {
|
||||
case 2: /* NOT Eb */
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u2 = native_lock_read_b(EB);
|
||||
tmp8u2 = not8(emu, tmp8u2);
|
||||
@ -947,7 +980,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Eb */
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u = native_lock_read_b(ED);
|
||||
} while(native_lock_write_b(ED, inc8(emu, tmp8u)));
|
||||
@ -958,7 +991,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u = native_lock_read_b(ED);
|
||||
} while(native_lock_write_b(ED, dec8(emu, tmp8u)));
|
||||
@ -980,7 +1013,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w)
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned
|
||||
@ -1026,7 +1059,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
#ifdef DYNAREC
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(rex.w)
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned
|
||||
|
@ -22,7 +22,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestF20F(x64test_t *test, rex_t rex, uintptr_t addr, int *step)
|
||||
#else
|
||||
uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -35,6 +39,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
#ifndef NOALIGN
|
||||
int is_nan;
|
||||
#endif
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
opcode = F8;
|
||||
|
||||
|
@ -22,7 +22,11 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestF30F(x64test_t *test, rex_t rex, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
@ -33,6 +37,9 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opem;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
opcode = F8;
|
||||
|
||||
|
142
src/emu/x64test.c
Normal file
142
src/emu/x64test.c
Normal file
@ -0,0 +1,142 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64stack.h"
|
||||
#include "x64emu.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu_private.h"
|
||||
#include "x64run_private.h"
|
||||
#include "x64primop.h"
|
||||
#include "x64trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box64context.h"
|
||||
#include "bridge.h"
|
||||
#include "signals.h"
|
||||
|
||||
void x64test_init(x64emu_t* ref, uintptr_t ip, int ok)
|
||||
{
|
||||
x64test_t* test = &ref->test;
|
||||
// check if test as a valid emu struct
|
||||
if(!test->emu) {
|
||||
test->emu = NewX64Emu(my_context, ip, (uintptr_t)ref->init_stack, ref->size_stack, 0);
|
||||
CopyEmu(test->emu, ref);
|
||||
}
|
||||
// check if IP is same, else, sync
|
||||
if(ip != test->emu->ip.q[0] || !ok) {
|
||||
CopyEmu(test->emu, ref);
|
||||
}
|
||||
// Do a Dry single Step
|
||||
test->memsize = 0;
|
||||
RunTest(test);
|
||||
}
|
||||
|
||||
void print_banner(x64emu_t* ref)
|
||||
{
|
||||
printf_log(LOG_NONE, "Warning, difference between Interpreter and Dynarec in %p\n=======================================\n", (void*)ref->ip.q[0]);
|
||||
printf_log(LOG_NONE, "DIF: Dynarec | Intepreter\n----------------------\n");
|
||||
}
|
||||
#define BANNER if(!banner) {banner=1; print_banner(ref);}
|
||||
void x64test_check(x64emu_t* ref, uintptr_t ip)
|
||||
{
|
||||
int banner = 0;
|
||||
x64test_t* test = &ref->test;
|
||||
x64emu_t* emu = test->emu;
|
||||
if(memcmp(ref->regs, emu->regs, sizeof(emu->regs))) {
|
||||
static const char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
|
||||
" R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"};
|
||||
BANNER;
|
||||
for(int i=0; i<16; ++i) {
|
||||
if(ref->regs[i].q[0]!=emu->regs[i].q[0]) {
|
||||
printf_log(LOG_NONE, "%s: %016zx | %016zx\n", regname[i], ref->regs[i].q[0], emu->regs[i].q[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ip!=emu->ip.q[0]) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "RIP: %016zx | %016zx\n", ip, emu->ip.q[0]);
|
||||
}
|
||||
// flags are volatile, so don't test them
|
||||
//memcpy(&ref->eflags, &emu->eflags, sizeof(emu->eflags));
|
||||
if(memcmp(ref->segs, emu->segs, sizeof(emu->segs))) {
|
||||
static const char* segname[] = {"CS", "DS", "ES", "SS", "FS", "GS"};
|
||||
BANNER;
|
||||
for(int i=0; i<6; ++i) {
|
||||
if(ref->segs[i]!=emu->segs[i]) {
|
||||
printf_log(LOG_NONE, "%s: %04x | %04x\n", segname[i], ref->segs[i], emu->segs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ref->top != emu->top) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 TOP: %d | %d\n", ref->top, emu->top);
|
||||
}
|
||||
if(ref->fpu_stack != emu->fpu_stack) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 STACK: %d | %d\n", ref->fpu_stack, emu->fpu_stack);
|
||||
}
|
||||
if(ref->fpu_stack && memcmp(ref->x87, emu->x87, sizeof(emu->x87))) {
|
||||
// need to check each regs, unused one might have different left over value
|
||||
for(int i=0; i<ref->fpu_stack; ++i) {
|
||||
if(ref->x87[(ref->top+i)&7].d != emu->x87[(emu->top+i)&7].d) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "ST%d: %g | %g\n", i, ref->x87[(ref->top+i)&7].d, emu->x87[(emu->top+i)&7].d);
|
||||
}
|
||||
}
|
||||
}
|
||||
//memcpy(ref->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
|
||||
//memcpy(ref->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
|
||||
/*if(ref->p_regs != emu->p_regs) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 PREG: %x | %x\n", ref->p_regs, emu->p_regs);
|
||||
}*/
|
||||
if(ref->cw.x16 != emu->cw.x16) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 CW: %x | %x\n", ref->cw.x16, emu->cw.x16);
|
||||
}
|
||||
if(ref->sw.x16 != emu->sw.x16) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 SW: %x | %x\n", ref->sw.x16, emu->sw.x16);
|
||||
}
|
||||
if(memcmp(ref->mmx, emu->mmx, sizeof(emu->mmx))) {
|
||||
BANNER;
|
||||
for(int i=0; i<8; ++i) {
|
||||
if(ref->mmx[i].q!=emu->mmx[i].q) {
|
||||
printf_log(LOG_NONE, "EMM[%d]: %016x | %016x\n", i, ref->mmx[i].q, emu->mmx[i].q);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ref->mxcsr.x32 != emu->mxcsr.x32) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "MXCSR: %x | %x\n", ref->mxcsr.x32, emu->mxcsr.x32);
|
||||
}
|
||||
if(memcmp(ref->xmm, emu->xmm, sizeof(emu->xmm))) {
|
||||
BANNER;
|
||||
for(int i=0; i<16; ++i) {
|
||||
if(ref->xmm[i].q[0]!=emu->xmm[i].q[0] || ref->xmm[i].q[1]!=emu->xmm[i].q[1] ) {
|
||||
printf_log(LOG_NONE, "XMM[%02d]: %016zx-%016zx | %016zx-%016zx\n", i, ref->xmm[i].q[0], ref->xmm[i].q[1], emu->xmm[i].q[0], emu->xmm[i].q[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(test->memsize) {
|
||||
if(memcmp(test->mem, (void*)test->memaddr, test->memsize)) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "MEM: @%p :", (void*)test->memaddr);
|
||||
for(int i=0; i<test->memsize; ++i)
|
||||
printf_log(LOG_NONE, " %02x", test->mem[i]);
|
||||
printf_log(LOG_NONE, " |");
|
||||
for(int i=0; i<test->memsize; ++i)
|
||||
printf_log(LOG_NONE, " %02x", ((uint8_t*)test->memaddr)[i]);
|
||||
}
|
||||
}
|
||||
if(banner) // there was an error, re-sync!
|
||||
CopyEmu(emu, ref);
|
||||
}
|
||||
#undef BANNER
|
@ -136,6 +136,7 @@ typedef struct box64context_s {
|
||||
uint32_t mutex_bridge;
|
||||
uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock
|
||||
int trace_dynarec;
|
||||
pthread_mutex_t mutex_lock; // this is for the Test interpreter
|
||||
#endif
|
||||
|
||||
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
|
||||
|
@ -26,6 +26,7 @@ extern int box64_dynarec_bleeding_edge;
|
||||
extern int box64_dynarec_hotpage;
|
||||
extern int box64_dynarec_fastpage;
|
||||
extern int box64_dynarec_wait;
|
||||
extern int box64_dynarec_test;
|
||||
#ifdef ARM64
|
||||
extern int arm64_asimd;
|
||||
extern int arm64_aes;
|
||||
|
@ -5,4 +5,7 @@ typedef struct x64emu_s x64emu_t;
|
||||
|
||||
void DynaCall(x64emu_t* emu, uintptr_t addr); // try to use DynaRec... Fallback to EmuCall if no dynarec available
|
||||
|
||||
void x64test_init(x64emu_t* ref);
|
||||
void x64test_check(x64emu_t* ref);
|
||||
|
||||
#endif // __DYNAREC_H_
|
@ -10,6 +10,7 @@ void SetupX64Emu(x64emu_t *emu);
|
||||
void FreeX64Emu(x64emu_t **x64emu);
|
||||
void FreeX64EmuFromStack(x64emu_t **emu);
|
||||
void CloneEmu(x64emu_t *newemu, const x64emu_t* emu);
|
||||
void CopyEmu(x64emu_t *newemu, const x64emu_t* emu);
|
||||
void SetTraceEmu(uintptr_t trace_start, uintptr_t trace_end);
|
||||
|
||||
box64context_t* GetEmuContext(x64emu_t* emu);
|
||||
|
@ -3,7 +3,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct x64emu_s x64emu_t;
|
||||
typedef struct x64test_s x64test_t;
|
||||
int Run(x64emu_t *emu, int step); // 0 if run was successfull, 1 if error in x86 world
|
||||
int RunTest(x64test_t *test);
|
||||
int DynaRun(x64emu_t *emu);
|
||||
|
||||
uint32_t LibSyscall(x64emu_t *emu);
|
||||
|
13
src/main.c
13
src/main.c
@ -62,6 +62,7 @@ int box64_dynarec_hotpage = 4;
|
||||
int box64_dynarec_fastpage = 0;
|
||||
int box64_dynarec_bleeding_edge = 1;
|
||||
int box64_dynarec_wait = 1;
|
||||
int box64_dynarec_test = 0;
|
||||
uintptr_t box64_nodynarec_start = 0;
|
||||
uintptr_t box64_nodynarec_end = 0;
|
||||
#ifdef ARM64
|
||||
@ -600,6 +601,18 @@ void LoadLogEnv()
|
||||
printf_log(LOG_INFO, "No dynablock creation that start in the range %p - %p\n", (void*)box64_nodynarec_start, (void*)box64_nodynarec_end);
|
||||
}
|
||||
}
|
||||
p = getenv("BOX64_DYNAREC_TEST");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box64_dynarec_test = p[0]-'0';
|
||||
}
|
||||
if(box64_dynarec_test) {
|
||||
box64_dynarec_fastnan = 0;
|
||||
box64_dynarec_fastround = 0;
|
||||
printf_log(LOG_INFO, "Dynarec will compare it's execution with the interpreter (super slow, only for testing)\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef HAVE_TRACE
|
||||
|
@ -127,6 +127,7 @@ ENTRYINT(BOX64_DYNAREC_HOTPAGE, box64_dynarec_hotpage, 0, 255, 8) \
|
||||
ENTRYBOOL(BOX64_DYNAREC_FASTPAGE, box64_dynarec_fastpage) \
|
||||
ENTRYBOOL(BOX64_DYNAREC_WAIT, box64_dynarec_wait) \
|
||||
ENTRYSTRING_(BOX64_NODYNAREC, box64_nodynarec) \
|
||||
ENTRYBOOL(BOX64_DYNAREC_TEST, box64_dynarec_test) \
|
||||
|
||||
#else
|
||||
#define SUPER3() \
|
||||
@ -146,6 +147,7 @@ IGNORE(BOX64_DYNAREC_HOTPAGE) \
|
||||
IGNORE(BOX64_DYNAREC_FASTPAGE) \
|
||||
IGNORE(BOX64_DYNAREC_WAIT) \
|
||||
IGNORE(BOX64_NODYNAREC) \
|
||||
IGNORE(BOX64_DYNAREC_TEST) \
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user