mirror of
https://github.com/ptitSeb/box86.git
synced 2024-11-27 03:44:40 +08:00
[DYNAREC] Backported DYNAREC_TEST to compare dynarec vs interpreter state
This commit is contained in:
parent
bf53a76223
commit
1411d44b51
@ -297,6 +297,30 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/librarian/symbols.c"
|
||||
"${BOX86_ROOT}/src/librarian/globalsymbols.c"
|
||||
"${BOX86_ROOT}/src/emu/x86emu.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run_private.c"
|
||||
"${BOX86_ROOT}/src/emu/x86syscall.c"
|
||||
"${BOX86_ROOT}/src/emu/x86primop.c"
|
||||
"${BOX86_ROOT}/src/emu/x86trace.c"
|
||||
"${BOX86_ROOT}/src/emu/x86int3.c"
|
||||
"${BOX86_ROOT}/src/emu/x86tls.c"
|
||||
"${BOX86_ROOT}/src/emu/x87emu_private.c"
|
||||
"${BOX86_ROOT}/src/libtools/auxval.c"
|
||||
"${BOX86_ROOT}/src/libtools/myalign.c"
|
||||
"${BOX86_ROOT}/src/libtools/myalign64.c"
|
||||
"${BOX86_ROOT}/src/libtools/myfts.c"
|
||||
"${BOX86_ROOT}/src/libtools/sdl1rwops.c"
|
||||
"${BOX86_ROOT}/src/libtools/sdl2rwops.c"
|
||||
"${BOX86_ROOT}/src/libtools/signals.c"
|
||||
"${BOX86_ROOT}/src/libtools/threads.c"
|
||||
"${BOX86_ROOT}/src/libtools/vkalign.c"
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec.c"
|
||||
"${BOX86_ROOT}/src/wrapped/generated/wrapper.c"
|
||||
)
|
||||
if(NOT ANDROID)
|
||||
list(APPEND ELFLOADER_SRC "${BOX86_ROOT}/src/libtools/obstack.c")
|
||||
endif()
|
||||
|
||||
set(INTERPRETER
|
||||
"${BOX86_ROOT}/src/emu/x86run.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run0f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run64.c"
|
||||
@ -321,28 +345,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/emu/x86runf066.c"
|
||||
"${BOX86_ROOT}/src/emu/x86runf20f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86runf30f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run_private.c"
|
||||
"${BOX86_ROOT}/src/emu/x86syscall.c"
|
||||
"${BOX86_ROOT}/src/emu/x86primop.c"
|
||||
"${BOX86_ROOT}/src/emu/x86trace.c"
|
||||
"${BOX86_ROOT}/src/emu/x86int3.c"
|
||||
"${BOX86_ROOT}/src/emu/x86tls.c"
|
||||
"${BOX86_ROOT}/src/emu/x87emu_private.c"
|
||||
"${BOX86_ROOT}/src/libtools/auxval.c"
|
||||
"${BOX86_ROOT}/src/libtools/myalign.c"
|
||||
"${BOX86_ROOT}/src/libtools/myalign64.c"
|
||||
"${BOX86_ROOT}/src/libtools/myfts.c"
|
||||
"${BOX86_ROOT}/src/libtools/sdl1rwops.c"
|
||||
"${BOX86_ROOT}/src/libtools/sdl2rwops.c"
|
||||
"${BOX86_ROOT}/src/libtools/signals.c"
|
||||
"${BOX86_ROOT}/src/libtools/threads.c"
|
||||
"${BOX86_ROOT}/src/libtools/vkalign.c"
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec.c"
|
||||
"${BOX86_ROOT}/src/wrapped/generated/wrapper.c"
|
||||
)
|
||||
if(NOT ANDROID)
|
||||
list(APPEND ELFLOADER_SRC "${BOX86_ROOT}/src/libtools/obstack.c")
|
||||
endif()
|
||||
|
||||
set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibc.c"
|
||||
@ -567,6 +570,7 @@ if(ARM_DYNAREC)
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec_arm.c"
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec_arm_functions.c"
|
||||
"${BOX86_ROOT}/src/dynarec/arm_printer.c"
|
||||
"${BOX86_ROOT}/src/emu/x86test.c"
|
||||
|
||||
"${BOX86_ROOT}/src/dynarec/arm_prolog.S"
|
||||
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
|
||||
@ -614,6 +618,8 @@ if(ARM_DYNAREC)
|
||||
set_target_properties(arm_pass2 PROPERTIES COMPILE_FLAGS "-DSTEP=2")
|
||||
add_library(arm_pass3 OBJECT ${DYNAREC_PASS})
|
||||
set_target_properties(arm_pass3 PROPERTIES COMPILE_FLAGS "-DSTEP=3")
|
||||
add_library(test_interpreter OBJECT ${INTERPRETER})
|
||||
set_target_properties(test_interpreter PROPERTIES COMPILE_FLAGS "-DTEST_INTERPRETER")
|
||||
add_dependencies(arm_pass0 WRAPPERS)
|
||||
add_dependencies(arm_pass1 WRAPPERS)
|
||||
add_dependencies(arm_pass2 WRAPPERS)
|
||||
@ -625,6 +631,7 @@ if(ARM_DYNAREC)
|
||||
$<TARGET_OBJECTS:arm_pass1>
|
||||
$<TARGET_OBJECTS:arm_pass2>
|
||||
$<TARGET_OBJECTS:arm_pass3>
|
||||
$<TARGET_OBJECTS:test_interpreter>
|
||||
)
|
||||
|
||||
endif()
|
||||
@ -634,16 +641,18 @@ if(ARM_DYNAREC)
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
|
||||
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
|
||||
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
add_library(interpreter OBJECT ${INTERPRETER})
|
||||
|
||||
if(BOX86LIB)
|
||||
#build a static or dynamic lib...
|
||||
if(BOX86DYNAMIC)
|
||||
@ -653,9 +662,9 @@ else()
|
||||
endif()
|
||||
if(ARM_DYNAREC)
|
||||
if(ANDROID)
|
||||
target_link_libraries(${BOX86} dynarec m dl)
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl)
|
||||
else()
|
||||
target_link_libraries(${BOX86} dynarec m dl rt pthread resolv)
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl rt pthread resolv)
|
||||
endif()
|
||||
endif()
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
@ -681,7 +690,9 @@ else()
|
||||
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
|
||||
endif()
|
||||
if(ARM_DYNAREC)
|
||||
target_link_libraries(${BOX86} dynarec)
|
||||
target_link_libraries(${BOX86} dynarec interpreter)
|
||||
else()
|
||||
target_link_libraries(${BOX86} interpreter)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
|
@ -127,6 +127,11 @@ Enables/Disables trace for generated code.
|
||||
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
|
||||
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
|
||||
|
||||
#### BOX86_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
|
||||
|
||||
#### BOX86_DYNAREC_BIGBLOCK *
|
||||
Enables/Disables Box86'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)
|
||||
|
@ -147,6 +147,7 @@ static void init_mutexes(box86context_t* context)
|
||||
arm_lock_stored(&context->mutex_tls, 0);
|
||||
arm_lock_stored(&context->mutex_thread, 0);
|
||||
arm_lock_stored(&context->mutex_bridge, 0);
|
||||
pthread_mutex_init(&context->mutex_lock, NULL);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
@ -360,7 +361,9 @@ void FreeBox86Context(box86context_t** context)
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
#ifndef DYNAREC
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
|
@ -398,6 +398,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(AreaInHotPage((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr + db->x86_size - 1)) {
|
||||
emu->test.test = 0;
|
||||
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
@ -424,6 +425,8 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
||||
}
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
if(!db || !db->block || !db->done)
|
||||
emu->test.test = 0;
|
||||
return db;
|
||||
}
|
||||
|
||||
@ -433,8 +436,10 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
int create = 1;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(mutex_trylock(&my_context->mutex_dyndump))
|
||||
if(mutex_trylock(&my_context->mutex_dyndump)) {
|
||||
emu->test.test = 0;
|
||||
return NULL;
|
||||
}
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
if(hash!=father->hash) {
|
||||
@ -453,5 +458,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
}
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
if(!db || !db->block || !db->done)
|
||||
emu->test.test = 0;
|
||||
return db;
|
||||
}
|
||||
|
@ -1663,6 +1663,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((PK(0)==0) && (PK(1)==0) && (PK(2)==0) && (PK(3)==0))
|
||||
{
|
||||
addr+=4;
|
||||
SKIPTEST(x14);
|
||||
MESSAGE(LOG_DEBUG, "Exit x86 Emu\n");
|
||||
MOV32(x14, ip+1+2);
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
|
||||
@ -1672,6 +1673,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
*need_epilog = 1;
|
||||
} else {
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
|
||||
SKIPTEST(x14);
|
||||
x87_forget(dyn, ninst, x3, x14, 0);
|
||||
if((box86_log<2) && !cycle_log) { // call the wrapper directly
|
||||
uintptr_t ncall[2]; // to avoid BUSERROR!!!
|
||||
@ -1715,6 +1717,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xCD:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
SKIPTEST(x14);
|
||||
SMEND();
|
||||
if(PK(0)==0x80) {
|
||||
INST_NAME("Syscall");
|
||||
@ -2169,12 +2172,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 1:
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
MESSAGE(LOG_DUMP, "Hack for Call 0\n");
|
||||
SKIPTEST(x14);
|
||||
MOV32(xEIP, addr);
|
||||
PUSH1(xEIP);
|
||||
break;
|
||||
case 2:
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
|
||||
SKIPTEST(x14);
|
||||
u8 = PK(i32+1);
|
||||
gd = xEAX+((u8&0x38)>>3);
|
||||
MOV32(gd, addr);
|
||||
|
@ -90,6 +90,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("UD2");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
//CALL(arm_ud, -1, 0);
|
||||
SKIPTEST(x14);
|
||||
UDF(0);
|
||||
break;
|
||||
|
||||
@ -656,6 +657,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x51:
|
||||
INST_NAME("SQRTPS Gx, Ex");
|
||||
SKIPTEST(x1);
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
@ -695,6 +697,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTPS Gx, Ex");
|
||||
SKIPTEST(x1);
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
@ -703,6 +706,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x53:
|
||||
INST_NAME("RCPPS Gx, Ex");
|
||||
SKIPTEST(x1);
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
|
@ -110,7 +110,7 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
|
||||
memcpy(ed, &STll(0).sq, sizeof(int64_t));
|
||||
} else {
|
||||
int64_t tmp;
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = fpu_round(emu, ST0.d);
|
||||
@ -121,7 +121,7 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
|
||||
int64_t arm_fist64_0(double d)
|
||||
{
|
||||
int64_t tmp;
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = nearbyint(d);
|
||||
@ -130,7 +130,7 @@ int64_t arm_fist64_0(double d)
|
||||
int64_t arm_fist64_1(double d)
|
||||
{
|
||||
int64_t tmp;
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = floor(d);
|
||||
@ -139,7 +139,7 @@ int64_t arm_fist64_1(double d)
|
||||
int64_t arm_fist64_2(double d)
|
||||
{
|
||||
int64_t tmp;
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = ceil(d);
|
||||
@ -148,7 +148,7 @@ int64_t arm_fist64_2(double d)
|
||||
int64_t arm_fist64_3(double d)
|
||||
{
|
||||
int64_t tmp;
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = trunc(d);
|
||||
@ -171,6 +171,7 @@ void arm_fld(x86emu_t* emu, uint8_t* ed)
|
||||
|
||||
void arm_ud(x86emu_t* emu)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
|
||||
}
|
||||
|
||||
|
@ -861,10 +861,29 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
|
||||
MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
// Synch top & stack counter
|
||||
int a = dyn->n.x87stack;
|
||||
if(a) {
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
ADD_IMM8(s1, s1, a);
|
||||
} else {
|
||||
SUB_IMM8(s1, s1, -a);
|
||||
}
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
|
||||
if(a>0) {
|
||||
SUB_IMM8(s1, s1, a);
|
||||
} else {
|
||||
ADD_IMM8(s1, s1, -a);
|
||||
}
|
||||
AND_IMM8(s1, s1, 7);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
|
||||
}
|
||||
int ret = 0;
|
||||
for (int i=0; (i<8) && (!ret); ++i)
|
||||
if(dyn->n.x87cache[i] != -1)
|
||||
@ -887,7 +906,31 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
// go back with the top & stack counter
|
||||
int a = dyn->n.x87stack;
|
||||
if(a) {
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
SUB_IMM8(s1, s1, a);
|
||||
} else {
|
||||
ADD_IMM8(s1, s1, -a);
|
||||
}
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
|
||||
if(a>0) {
|
||||
ADD_IMM8(s1, s1, a);
|
||||
} else {
|
||||
SUB_IMM8(s1, s1, -a);
|
||||
}
|
||||
AND_IMM8(s1, s1, 7);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
|
||||
}
|
||||
}
|
||||
|
||||
int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
|
||||
{
|
||||
@ -1223,7 +1266,6 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
int old = -1;
|
||||
@ -1241,7 +1283,6 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
VST1_32_W(dyn->n.mmxcache[i], s1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// SSE / SSE2 helpers
|
||||
@ -1321,7 +1362,6 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
int old = -1;
|
||||
@ -1345,7 +1385,6 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
VST1Q_32_W(dyn->n.ssecache[i].reg, s1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
@ -1843,16 +1882,17 @@ void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2,
|
||||
flagsCacheTransform(dyn, ninst, s1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
x87_reflectcache(dyn, ninst, s1, s2, s3);
|
||||
if(trace_emm)
|
||||
mmx_reflectcache(dyn, ninst, s1);
|
||||
if(trace_xmm)
|
||||
sse_reflectcache(dyn, ninst, s1);
|
||||
mmx_reflectcache(dyn, ninst, s1);
|
||||
sse_reflectcache(dyn, ninst, s1);
|
||||
}
|
||||
|
||||
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
x87_unreflectcache(dyn, ninst, s1, s2, s3);
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_reset(dynarec_arm_t* dyn)
|
||||
{
|
||||
|
@ -550,9 +550,8 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define fpu_purgecache STEPNAME(fpu_purgecache)
|
||||
#define x87_purgecache STEPNAME(x87_purgecache)
|
||||
#define mmx_purgecache STEPNAME(mmx_purgecache)
|
||||
#ifdef HAVE_TRACE
|
||||
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
|
||||
#endif
|
||||
#define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
|
||||
|
||||
// get the single reg that from the double "reg" (so Dx[idx])
|
||||
#define fpu_get_single_reg STEPNAME(fpu_get_single_reg)
|
||||
@ -745,9 +744,8 @@ void fpu_reset(dynarec_arm_t* dyn);
|
||||
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
|
||||
#ifdef HAVE_TRACE
|
||||
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
#endif
|
||||
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
|
||||
@ -794,4 +792,21 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
#define MAYUSE(A)
|
||||
#endif
|
||||
|
||||
#define NOTEST(s1) \
|
||||
if(box86_dynarec_test) { \
|
||||
MOVW(s1, 0); \
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.test)); \
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.clean)); \
|
||||
}
|
||||
#define SKIPTEST(s1) \
|
||||
if(box86_dynarec_test) { \
|
||||
MOVW(s1, 0); \
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.clean)); \
|
||||
}
|
||||
#define GOTEST(s1, s2) \
|
||||
if(box86_dynarec_test) { \
|
||||
MOVW(s2, 1); \
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, test.test)); \
|
||||
}
|
||||
|
||||
#endif //__DYNAREC_ARM_HELPER_H__
|
@ -124,13 +124,27 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->n.stack_push = 0;
|
||||
dyn->n.swapped = 0;
|
||||
NEW_INST;
|
||||
if(!ninst || isInstClean(dyn, ninst)) {
|
||||
GOTEST(x1, x2);
|
||||
}
|
||||
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
|
||||
fpu_reset_scratch(dyn);
|
||||
if((dyn->insts[ninst].x86.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
|
||||
READFLAGS(dyn->insts[ninst].x86.need_before&~X_PEND);
|
||||
}
|
||||
if(box86_dynarec_test) {
|
||||
MESSAGE(LOG_DUMP, "TEST INIT ----\n");
|
||||
fpu_reflectcache(dyn, ninst, x1, x2, x3);
|
||||
MOV32(x1, ip);
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
|
||||
MOVW(x2, 1);
|
||||
CALL(x86test_init, -1, 0);
|
||||
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
if(my_context->dec && box86_dynarec_trace) {
|
||||
else if(my_context->dec && box86_dynarec_trace) {
|
||||
if((trace_end == 0)
|
||||
|| ((ip >= trace_start) && (ip < trace_end))) {
|
||||
MESSAGE(LOG_DUMP, "TRACE ----\n");
|
||||
@ -140,6 +154,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
|
||||
MOVW(x2, 1);
|
||||
CALL(PrintTrace, -1, 0);
|
||||
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
}
|
||||
@ -252,12 +267,14 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->insts[ninst].x86.need_after |= X_PEND;
|
||||
#endif
|
||||
++ninst;
|
||||
NOTEST(x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
jump_to_next(dyn, addr, 0, ninst);
|
||||
ok=0; need_epilog=0;
|
||||
}
|
||||
}
|
||||
if(need_epilog) {
|
||||
NOTEST(x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include <string.h>
|
||||
|
||||
#define F8 *(uint8_t*)(addr++)
|
||||
#define F8S *(int8_t*)(addr++)
|
||||
#define F16 *(uint16_t*)(addr+=2, addr-2)
|
||||
@ -117,6 +119,17 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
} else getecommon(A, reg32_t)
|
||||
#define testeb(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
} else { \
|
||||
reg32_t* ret; \
|
||||
getecommono(ret, reg32_t, O);\
|
||||
test->memsize = 1; \
|
||||
test->memaddr = (uintptr_t)ret;\
|
||||
test->mem[0] = ret->byte[0];\
|
||||
A = (reg32_t*)test->mem;\
|
||||
}
|
||||
#define getebo(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
@ -129,14 +142,47 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommono(A, reg32_t, O)
|
||||
#define tested(A, SZ, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else {\
|
||||
reg32_t* ret; \
|
||||
getecommono(ret, reg32_t, O);\
|
||||
test->memsize = SZ; \
|
||||
test->memaddr = (uintptr_t)ret;\
|
||||
memcpy(test->mem, ret->dword, SZ);\
|
||||
A = (reg32_t*)test->mem;\
|
||||
}
|
||||
#define getem(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->mmx[(nextop&7)]; \
|
||||
} else getecommon(A, mmx87_regs_t)
|
||||
#define testem(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->mmx[(nextop&7)]; \
|
||||
} else {\
|
||||
mmx87_regs_t* ret; \
|
||||
getecommon(ret, mmx87_regs_t) \
|
||||
test->memsize = 8; \
|
||||
test->memaddr = (uintptr_t)ret;\
|
||||
memcpy(test->mem, ret->ub, 8);\
|
||||
A = (mmx87_regs_t*)test->mem;\
|
||||
}
|
||||
#define getex(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->xmm[(nextop&7)]; \
|
||||
} else getecommon(A, sse_regs_t)
|
||||
#define testex(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->xmm[(nextop&7)]; \
|
||||
} else {\
|
||||
sse_regs_t* ret; \
|
||||
getecommon(ret, sse_regs_t);\
|
||||
test->memsize = 16; \
|
||||
test->memaddr = (uintptr_t)ret;\
|
||||
memcpy(test->mem, ret->ub, 16);\
|
||||
A = (sse_regs_t*)test->mem;\
|
||||
}
|
||||
#define getew16(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
@ -145,21 +191,35 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommon16o(A, reg32_t, O)
|
||||
#define testtew16(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else { \
|
||||
reg32_t* ret; \
|
||||
getecommon16o(A, reg32_t, O); \
|
||||
test->memsize = 2; \
|
||||
test->memaddr = (uintptr_t)ret; \
|
||||
*(uint16_t*)test->mem = ret->word[0];\
|
||||
A = (reg32_t*)test->mem; \
|
||||
}
|
||||
|
||||
// Macros for ModR/M gets
|
||||
#ifdef TEST_INTERPRETER
|
||||
#warning TODO
|
||||
#define GET_EB geteb(oped)
|
||||
#define GET_ED geted(oped)
|
||||
#define GET_ED_OFFS(o) getedo(oped, o)
|
||||
#define GET_EB_OFFS(o) getebo(oped, o)
|
||||
#define GET_EM getem(opem)
|
||||
#define GET_EX getex(opex)
|
||||
#define GET_EW16 getew16(oped)
|
||||
#define GET_EW16_OFFS(o) getew16o(oped, o)
|
||||
#define GET_EB testeb(oped, 0)
|
||||
#define GET_ED tested(oped, 4, 0)
|
||||
#define GET_ED8 tested(oped, 8, 0)
|
||||
#define GET_EDT tested(oped, 10, 0)
|
||||
#define GET_ED_OFFS(o) tested(oped, 4, o)
|
||||
#define GET_EB_OFFS(o) testeb(oped, o)
|
||||
#define GET_EM testem(opem)
|
||||
#define GET_EX testex(opex)
|
||||
#define GET_EW16 testew16(oped, 0)
|
||||
#define GET_EW16_OFFS(o) testtew16(oped, o)
|
||||
#else
|
||||
#define GET_EB geteb(oped)
|
||||
#define GET_ED geted(oped)
|
||||
#define GET_ED8 geted(oped)
|
||||
#define GET_EDT geted(oped)
|
||||
#define GET_ED_OFFS(o) getedo(oped, o)
|
||||
#define GET_EB_OFFS(o) getebo(oped, o)
|
||||
#define GET_EM getem(opem)
|
||||
@ -167,6 +227,8 @@
|
||||
#define GET_EW16 getew16(oped)
|
||||
#define GET_EW16_OFFS(o) getew16o(oped, o)
|
||||
#endif
|
||||
#define GET_ED_ geted(oped)
|
||||
#define GET_EW16_ getew16(oped)
|
||||
#define EB oped
|
||||
#define ED oped
|
||||
#define EM opem
|
||||
|
@ -198,6 +198,11 @@ void FreeX86Emu(x86emu_t **emu)
|
||||
return;
|
||||
printf_log(LOG_DEBUG, "%04d|Free a X86 Emu (%p)\n", GetTID(), *emu);
|
||||
|
||||
if((*emu)->test.emu) {
|
||||
internalFreeX86((*emu)->test.emu);
|
||||
box_free((*emu)->test.emu);
|
||||
(*emu)->test.emu = NULL;
|
||||
}
|
||||
internalFreeX86(*emu);
|
||||
|
||||
box_free(*emu);
|
||||
@ -231,6 +236,10 @@ void CloneEmu(x86emu_t *newemu, const x86emu_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->op1 = emu->op1;
|
||||
newemu->op2 = emu->op2;
|
||||
newemu->res = emu->res;
|
||||
newemu->mxcsr = emu->mxcsr;
|
||||
newemu->quit = emu->quit;
|
||||
newemu->error = emu->error;
|
||||
@ -240,6 +249,34 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
|
||||
newemu->regs[_SP].dword[0] = emu->regs[_SP].dword[0] + (intptr_t)(newst - oldst);
|
||||
}
|
||||
|
||||
void CopyEmu(x86emu_t *newemu, const x86emu_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->op1 = emu->op1;
|
||||
newemu->op2 = emu->op2;
|
||||
newemu->res = emu->res;
|
||||
newemu->mxcsr = emu->mxcsr;
|
||||
newemu->quit = emu->quit;
|
||||
newemu->error = emu->error;
|
||||
}
|
||||
|
||||
box86context_t* GetEmuContext(x86emu_t* emu)
|
||||
{
|
||||
return emu->context;
|
||||
@ -311,7 +348,7 @@ void ResetFlags(x86emu_t *emu)
|
||||
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
|
||||
{
|
||||
static char buff[800];
|
||||
char* regname[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
|
||||
static const char* regname[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
|
||||
char tmp[80];
|
||||
buff[0] = '\0';
|
||||
if(trace_emm) {
|
||||
|
@ -23,6 +23,17 @@ typedef struct forkpty_s {
|
||||
void* f; // forkpty function
|
||||
} forkpty_t;
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
typedef struct x86test_s {
|
||||
x86emu_t* emu;
|
||||
uintptr_t memaddr;
|
||||
int memsize;
|
||||
int test;
|
||||
int clean;
|
||||
uint8_t mem[16];
|
||||
} x86test_t;
|
||||
|
||||
typedef struct x86emu_s {
|
||||
// cpu
|
||||
reg32_t regs[8];
|
||||
@ -63,6 +74,7 @@ typedef struct x86emu_s {
|
||||
int exit;
|
||||
int quitonlongjmp; // quit if longjmp is called
|
||||
int longjmp; // if quit because of longjmp
|
||||
x86test_t test; // used for dynarec testing
|
||||
// parent context
|
||||
box86context_t *context;
|
||||
// cpu helpers
|
||||
|
@ -30,7 +30,7 @@
|
||||
int my_setcontext(x86emu_t* emu, void* ucp);
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
int RunTest(x64test_t *test)
|
||||
int RunTest(x86test_t *test)
|
||||
#else
|
||||
int Run(x86emu_t *emu, int step)
|
||||
#endif
|
||||
@ -52,7 +52,7 @@ int Run(x86emu_t *emu, int step)
|
||||
sse_regs_t *opex, eax1;
|
||||
mmx87_regs_t *opem, eam1;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
x86emu_t* emu = test->emu;
|
||||
int step = 0;
|
||||
#endif
|
||||
#ifndef NOALIGN
|
||||
@ -371,7 +371,6 @@ x86emurun:
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x66: /* Prefix to change width of intructions, so here, down to 16bits */
|
||||
#ifdef TEST_INTERPRETER
|
||||
if(!(addr = Test66(test, rep, addr)))
|
||||
@ -682,7 +681,7 @@ x86emurun:
|
||||
break;
|
||||
case 0x8D: /* LEA Gd,M */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED_;
|
||||
GD.dword[0] = (uint32_t)ED;
|
||||
break;
|
||||
case 0x8E: /* MOV Seg,Ew */
|
||||
@ -757,16 +756,30 @@ x86emurun:
|
||||
R_EAX = *(uint32_t*)F32;
|
||||
break;
|
||||
case 0xA2: /* MOV Ob,AL */
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr = F32;
|
||||
test->memsize = 1;
|
||||
*(uint8_t*)(test->mem) = R_AL;
|
||||
#else
|
||||
*(uint8_t*)F32 = R_AL;
|
||||
#endif
|
||||
break;
|
||||
case 0xA3: /* MOV Od,EAX */
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr = F32;
|
||||
test->memsize = 4;
|
||||
*(uint32_t*)(test->mem) = R_EAX;
|
||||
#else
|
||||
*(uint32_t*)F32 = R_EAX;
|
||||
#endif
|
||||
break;
|
||||
case 0xA4: /* MOVSB */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
tmp32u = rep?R_ECX:1;
|
||||
while(tmp32u--) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint8_t*)R_EDI = *(uint8_t*)R_ESI;
|
||||
#endif
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
@ -776,7 +789,9 @@ x86emurun:
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
|
||||
tmp32u = rep?R_ECX:1;
|
||||
while(tmp32u--) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint32_t*)R_EDI = *(uint32_t*)R_ESI;
|
||||
#endif
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
@ -876,26 +891,30 @@ x86emurun:
|
||||
break;
|
||||
case 0xAA: /* STOSB */
|
||||
tmp32u = rep?R_ECX:1;
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
while(tmp32u--) {
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint8_t*)R_EDI = R_AL;
|
||||
#endif
|
||||
R_EDI += tmp8s;
|
||||
}
|
||||
if(rep) R_ECX = 0;
|
||||
break;
|
||||
case 0xAB: /* STOSD */
|
||||
tmp32u = rep?R_ECX:1;
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
|
||||
while(tmp32u--) {
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint32_t*)R_EDI = R_EAX;
|
||||
#endif
|
||||
R_EDI += tmp8s;
|
||||
}
|
||||
if(rep) R_ECX = 0;
|
||||
break;
|
||||
case 0xAC: /* LODSB */
|
||||
tmp32u = rep?R_ECX:1;
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
while(tmp32u--) {
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
R_AL = *(uint8_t*)R_ESI;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
@ -903,8 +922,8 @@ x86emurun:
|
||||
break;
|
||||
case 0xAD: /* LODSD */
|
||||
tmp32u = rep?R_ECX:1;
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
|
||||
while(tmp32u--) {
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
|
||||
R_EAX = *(uint32_t*)R_ESI;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
@ -1096,7 +1115,9 @@ x86emurun:
|
||||
case 0xCC: /* INT 3 */
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = addr;
|
||||
#ifndef TEST_INTERPRETER
|
||||
x86Int3(emu);
|
||||
#endif
|
||||
addr = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
break;
|
||||
@ -1105,7 +1126,9 @@ x86emurun:
|
||||
if(nextop == 0x80) {
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = addr;
|
||||
#ifndef TEST_INTERPRETER
|
||||
x86Syscall(emu);
|
||||
#endif
|
||||
addr = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
} else {
|
||||
@ -1120,11 +1143,13 @@ x86emurun:
|
||||
break;
|
||||
case 0xCE: /* INTO */
|
||||
emu->old_ip = R_EIP;
|
||||
#ifndef TEST_INTERPRETER
|
||||
R_EIP = addr;
|
||||
emit_signal(emu, SIGFPE, (void*)R_EIP, FPE_INTOVF);
|
||||
addr = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
case 0xCF: /* IRET */
|
||||
addr = Pop(emu);
|
||||
@ -1392,8 +1417,10 @@ x86emurun:
|
||||
|
||||
case 0xF4: /* HLT */
|
||||
// this is a privilege opcode... should an error be called instead?
|
||||
#ifndef TEST_INTERPRETER
|
||||
sched_yield();
|
||||
STEP2;
|
||||
#endif
|
||||
break;
|
||||
case 0xF5: /* CMC */
|
||||
CHECK_FLAGS(emu);
|
||||
@ -1547,7 +1574,15 @@ x86emurun:
|
||||
break;
|
||||
case 6: /* Push Ed */
|
||||
tmp32u = ED->dword[0];
|
||||
#ifdef TEST_INTERPRETER
|
||||
R_ESP -=4;
|
||||
if(test->memsize!=4)
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
test->memsize = 4;
|
||||
test->memaddr = R_ESP;
|
||||
#else
|
||||
Push(emu, tmp32u); // avoid potential issue with push [esp+...]
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
emu->old_ip = R_EIP;
|
||||
|
@ -965,7 +965,12 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
tmp32s >>= 5;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s);
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
|
||||
#endif
|
||||
}
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@ -998,7 +1003,12 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
tmp32s >>= 5;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s);
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
|
||||
#endif
|
||||
}
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@ -1029,18 +1039,24 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
GET_ED;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FXSAVE m512byte */
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_fxsave(emu, ED);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* FXRSTOR m512byte */
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_fxrstor(emu, ED);
|
||||
#endif
|
||||
break;
|
||||
case 2: /* LDMXCSR Md */
|
||||
emu->mxcsr.x32 = ED->dword[0];
|
||||
break;
|
||||
case 3: /* STMXCSR Md */
|
||||
ED->dword[0] = emu->mxcsr.x32;
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(box86_sse_flushto0)
|
||||
applyFlushTo0(emu);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
@ -1081,7 +1097,12 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
tmp32s >>= 5;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s);
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
|
||||
#endif
|
||||
}
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
@ -1162,7 +1183,12 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
tmp32s >>= 5;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s);
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
|
||||
#endif
|
||||
}
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@ -1274,7 +1300,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
break;
|
||||
case 0xC7: /* CMPXCHG8B Gq */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 1:
|
||||
CHECK_FLAGS(emu);
|
||||
|
@ -20,18 +20,20 @@
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test64(x86test_t *test, uintptr_t addr, int *step)
|
||||
uintptr_t Test64(x86test_t *test, int seg, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uintptr_t ip = R_EIP+1;
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uintptr_t tlsdata = (seg==_FS)?GetFSBaseEmu(emu):GetGSBaseEmu(emu);
|
||||
switch(opcode) {
|
||||
case 0x01: /* ADD GS:Ed, Gd */
|
||||
@ -55,7 +57,11 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test640F(test, tlsdata, addr);
|
||||
#else
|
||||
return Run640F(emu, tlsdata, addr);
|
||||
#endif
|
||||
|
||||
case 0x11: /* ADC GS:Ed, Gd */
|
||||
nextop = F8;
|
||||
@ -160,12 +166,24 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
|
||||
case 0x64: /* FS: */
|
||||
// so just ignore that GS: prefix then
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test64(test, _FS, addr-1); // put FS back
|
||||
#else
|
||||
return Run64(emu, _FS, addr-1); // put FS back
|
||||
#endif
|
||||
|
||||
case 0x66:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6466(test, tlsdata, addr);
|
||||
#else
|
||||
return Run6466(emu, tlsdata, addr);
|
||||
#endif
|
||||
case 0x67:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6467(test, tlsdata, addr);
|
||||
#else
|
||||
return Run6467(emu, tlsdata, addr);
|
||||
#endif
|
||||
|
||||
case 0x69: /* IMUL Gd,Ed,Id */
|
||||
nextop = F8;
|
||||
@ -294,8 +312,7 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
|
||||
case 0x9C: /* PUSHFD */
|
||||
// Segment override if for memory loc, no stack segment
|
||||
--ip; // so ignore prefix and continue
|
||||
break;
|
||||
return addr-1; // so ignore prefix and continue
|
||||
|
||||
case 0xA0: /* MOV AL,Ob */
|
||||
tmp32s = F32S;
|
||||
@ -395,8 +412,8 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
break;
|
||||
case 2: /* CALL NEAR Ed */
|
||||
R_EIP = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
Push(emu, ip);
|
||||
ip = R_EIP;
|
||||
Push(emu, addr);
|
||||
addr = R_EIP;
|
||||
break;
|
||||
case 3: /* CALL FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
@ -406,13 +423,13 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
return 0;
|
||||
} else {
|
||||
Push16(emu, R_CS);
|
||||
Push(emu, ip);
|
||||
ip = ED->dword[0];
|
||||
Push(emu, addr);
|
||||
addr = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
case 4: /* JMP NEAR Ed */
|
||||
ip = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
break;
|
||||
case 5: /* JMP FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
@ -421,7 +438,7 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
} else {
|
||||
ip = ED->dword[0];
|
||||
addr = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
|
@ -25,12 +25,15 @@ uintptr_t Test640F(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
|
||||
uintptr_t Run640F(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xAF: /* IMUL Gd,Ed */
|
||||
|
@ -25,12 +25,15 @@ uintptr_t Test6466(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
|
||||
uintptr_t Run6466(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x03: /* ADD Gw, FS:Ew */
|
||||
|
@ -25,12 +25,15 @@ uintptr_t Test6467(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
|
||||
uintptr_t Run6467(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x3B: /* CMP GD, FS:Ed16 */
|
||||
@ -63,7 +66,13 @@ uintptr_t Run6467(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
|
||||
break;
|
||||
case 0xA3: /* MOV Ov16,EAX */
|
||||
tmp32u = F16;
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr = tlsdata + tmp32u;
|
||||
test->memsize = 4;
|
||||
*(uint32_t*)(test->mem) = R_EAX;
|
||||
#else
|
||||
*(uint32_t*)(tlsdata + tmp32u) = R_EAX;
|
||||
#endif
|
||||
break;
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
|
@ -99,7 +99,11 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x0F: /* 66 0f prefix */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test660F(test, addr);
|
||||
#else
|
||||
return Run660F(emu, addr);
|
||||
#endif
|
||||
|
||||
case 0x1E: /* PUSH DS */
|
||||
Push16(emu, emu->segs[_DS]);
|
||||
@ -191,7 +195,11 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
|
||||
case 0x64:
|
||||
tlsdata = GetFSBaseEmu(emu);
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6466(test, tlsdata, addr);
|
||||
#else
|
||||
return Run6466(emu, tlsdata, addr);
|
||||
#endif
|
||||
|
||||
case 0x68: /* PUSH u16 */
|
||||
tmp16u = F16;
|
||||
@ -320,7 +328,9 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
tmp32u = rep?R_ECX:1;
|
||||
while(tmp32u--) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint8_t*)R_EDI = *(uint8_t*)R_ESI;
|
||||
#endif
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
@ -330,7 +340,9 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
|
||||
tmp32u = rep?R_ECX:1;
|
||||
while(tmp32u--) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint16_t*)R_EDI = *(uint16_t*)R_ESI;
|
||||
#endif
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
@ -375,7 +387,9 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
|
||||
tmp32u = rep?R_ECX:1;
|
||||
while(tmp32u--) {
|
||||
#ifndef TEST_INTERPRETER
|
||||
*(uint16_t*)R_EDI = R_AX;
|
||||
#endif
|
||||
R_EDI += tmp8s;
|
||||
}
|
||||
if(rep) R_ECX = 0;
|
||||
@ -453,8 +467,10 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
// need to check status of CS register!
|
||||
break;
|
||||
case 0xCC: /* INT3 */
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(my_context->signals[SIGTRAP])
|
||||
raise(SIGTRAP);
|
||||
#endif
|
||||
break;
|
||||
case 0xD1: /* GRP2 Ew,1 */
|
||||
case 0xD3: /* GRP2 Ew,CL */
|
||||
@ -474,13 +490,25 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0xD9:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test66D9(test, addr);
|
||||
#else
|
||||
return Run66D9(emu, addr);
|
||||
#endif
|
||||
|
||||
case 0xDD:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test66DD(test, addr);
|
||||
#else
|
||||
return Run66DD(emu, addr);
|
||||
#endif
|
||||
|
||||
case 0xF0: /* LOCK prefix */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return TestF066(test, addr);
|
||||
#else
|
||||
return RunF066(emu, addr);
|
||||
#endif
|
||||
|
||||
case 0xF5: /* CMC */
|
||||
CHECK_FLAGS(emu);
|
||||
|
@ -39,7 +39,7 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x64emu_t* emu = test->emu;
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
@ -157,7 +157,7 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
break;
|
||||
case 0x12: /* MOVLPD Gx, Eq */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if((uintptr_t)ED & 7)
|
||||
memcpy(&GX.q[0], ED, 8);
|
||||
else
|
||||
@ -165,7 +165,7 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
break;
|
||||
case 0x13: /* MOVLPD Eq, Gx */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if((uintptr_t)ED & 7)
|
||||
memcpy(ED, &GX.q[0], 8);
|
||||
else
|
||||
@ -184,12 +184,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
break;
|
||||
case 0x16: /* MOVHPD Gx, Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
GX.q[1] = *(uint64_t*)ED;
|
||||
break;
|
||||
case 0x17: /* MOVHPD Ed, Gx */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
*(uint64_t*)ED = GX.q[1];
|
||||
break;
|
||||
|
||||
@ -1214,7 +1214,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GET_EW;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s*2);
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
#endif
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@ -1241,7 +1246,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GET_EW;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s*2);
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
#endif
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@ -1287,7 +1297,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GET_EW;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s*2);
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
#endif
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
@ -1368,7 +1383,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GET_EW;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s*2);
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
#endif
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
|
@ -83,12 +83,16 @@ uintptr_t Run66D9(x86emu_t *emu, uintptr_t addr)
|
||||
case 4: /* FLDENV m */
|
||||
// warning, incomplete
|
||||
GET_EW;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_loadenv(emu, (char*)ED, 1);
|
||||
#endif
|
||||
break;
|
||||
case 6: /* FNSTENV m */
|
||||
// warning, incomplete
|
||||
GET_EW;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 1);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -83,6 +83,7 @@ uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr)
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* FRSTOR m94byte */
|
||||
GET_EW;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_loadenv(emu, (char*)ED, 1);
|
||||
// get the STx
|
||||
{
|
||||
@ -93,10 +94,12 @@ uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr)
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 6: /* FNSAVE m94byte */
|
||||
GET_EW;
|
||||
// ENV first...
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 1);
|
||||
// save the STx
|
||||
{
|
||||
@ -107,6 +110,7 @@ uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr)
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
reset_fpu(emu);
|
||||
break;
|
||||
default:
|
||||
|
@ -68,15 +68,25 @@ uintptr_t Run67(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
|
||||
case 0x64:
|
||||
tlsdata = GetFSBaseEmu(emu);
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6467(test, tlsdata, addr);
|
||||
#else
|
||||
return Run6467(emu, tlsdata, addr);
|
||||
#endif
|
||||
|
||||
case 0x66: /* MoooRE opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6766(test, rep, addr);
|
||||
#else
|
||||
return Run6766(emu, rep, addr);
|
||||
#endif
|
||||
|
||||
case 0x6C: /* INSB */
|
||||
tmp32u = rep?R_CX:1;
|
||||
while(tmp32u--) {
|
||||
#ifdef TEST_INTERPRETER
|
||||
*(int8_t*)(R_DI+GetESBaseEmu(emu)) = 0; // faking port read, using actual segment ES, just in case
|
||||
#endif
|
||||
if(ACCESS_FLAG(F_DF))
|
||||
R_DI-=1;
|
||||
else
|
||||
|
@ -30,6 +30,9 @@ uintptr_t Run6766(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uint8_t opcode = F8;
|
||||
|
||||
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
|
||||
@ -44,7 +47,7 @@ uintptr_t Run6766(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
|
||||
case 0x8D: /* LEA Gw,Ew */
|
||||
nextop = F8;
|
||||
GET_EW16;
|
||||
GET_EW16_;
|
||||
GW.word[0] = (uint16_t)(uintptr_t)ED;
|
||||
break;
|
||||
|
||||
|
@ -41,15 +41,19 @@ static inline uint32_t Pop(x86emu_t *emu)
|
||||
return *st;
|
||||
}
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
#define Push(E, V) do{E->regs[_SP].dword[0] -=4; test->memsize = 4; *(uint64_t*)test->mem = (V); test->memaddr = E->regs[_SP].dword[0];}while(0)
|
||||
#define Push16(E, V) do{E->regs[_SP].dword[0] -=2; test->memsize = 2; *(uint16_t*)test->mem = (V); test->memaddr = E->regs[_SP].dword[0];}while(0)
|
||||
#else
|
||||
static inline void Push(x86emu_t *emu, uint32_t v)
|
||||
{
|
||||
R_ESP -= 4;
|
||||
*((uint32_t*)R_ESP) = v;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
|
||||
|
||||
static inline reg32_t* GetECommon(x86emu_t* emu, uint32_t m)
|
||||
{
|
||||
if (m<=7) {
|
||||
@ -188,7 +192,7 @@ static inline sse_regs_t* GetGx(x86emu_t *emu, uint32_t v)
|
||||
uint8_t m = (v&0x38)>>3;
|
||||
return &emu->xmm[m&7];
|
||||
}
|
||||
|
||||
#endif
|
||||
void UpdateFlags(x86emu_t *emu);
|
||||
|
||||
#define CHECK_FLAGS(emu) if(emu->df) UpdateFlags(emu)
|
||||
@ -222,17 +226,35 @@ uintptr_t RunF066(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunF20F(x86emu_t *emu, uintptr_t addr, int *step);
|
||||
uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr);
|
||||
|
||||
//void Run67(x86emu_t *emu);
|
||||
//void Run0F(x86emu_t *emu);
|
||||
//void Run660F(x86emu_t *emu);
|
||||
//void Run66D9(x86emu_t *emu); // x87
|
||||
//void Run6766(x86emu_t *emu);
|
||||
//void RunGS(x86emu_t *emu);
|
||||
//void RunGS0F(x86emu_t *emu, uintptr_t tlsdata);
|
||||
//void RunFS(x86emu_t *emu);
|
||||
//void RunFS66(x86emu_t *emu, uintptr_t tlsdata);
|
||||
//void RunLock(x86emu_t *emu);
|
||||
//void RunLock66(x86emu_t *emu);
|
||||
#ifdef DYNAREC
|
||||
uintptr_t Test0F(x86test_t *test, uintptr_t addr, int *step);
|
||||
uintptr_t Test64(x86test_t *test, int seg, uintptr_t addr);
|
||||
uintptr_t Test640F(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Test6466(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Test6467(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Test66(x86test_t *test, int rep, uintptr_t addr);
|
||||
uintptr_t Test660F(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t Test6664(x86test_t *test, int seg, uintptr_t addr);
|
||||
uintptr_t Test66D9(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t Test66DD(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t Test66F0(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t Test67(x86test_t *test, int rep, uintptr_t addr);
|
||||
uintptr_t Test670F(x86test_t *test, int rep, uintptr_t addr);
|
||||
uintptr_t Test6766(x86test_t *test, int rep, uintptr_t addr);
|
||||
uintptr_t Test67660F(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestD8(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestD9(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDA(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDB(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDC(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDD(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDE(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDF(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestF0(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestF066(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestF20F(x86test_t *test, uintptr_t addr, int *step);
|
||||
uintptr_t TestF30F(x86test_t *test, uintptr_t addr);
|
||||
#endif
|
||||
|
||||
void x86Syscall(x86emu_t *emu);
|
||||
void x86Int3(x86emu_t* emu);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -275,7 +276,9 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
case 4: /* FLDENV m */
|
||||
// warning, incomplete
|
||||
GET_ED;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_loadenv(emu, (char*)ED, 0);
|
||||
#endif
|
||||
break;
|
||||
case 5: /* FLDCW Ew */
|
||||
GET_EW;
|
||||
@ -285,7 +288,9 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
case 6: /* FNSTENV m */
|
||||
// warning, incomplete
|
||||
GET_ED;
|
||||
#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)
|
||||
|
@ -100,8 +100,7 @@ uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFD:
|
||||
UnimpOpcode(emu);
|
||||
break;
|
||||
return 0;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FIADD ST0, Ed int */
|
||||
|
@ -164,14 +164,14 @@ uintptr_t RunDB(x86emu_t *emu, uintptr_t addr)
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 5: /* FLD ST0, Et */
|
||||
GET_ED;
|
||||
GET_EDT;
|
||||
fpu_do_push(emu);
|
||||
memcpy(&STld(0).ld, ED, 10);
|
||||
LD2D(&STld(0).ld, &ST(0).d);
|
||||
STld(0).uref = ST0.q;
|
||||
break;
|
||||
case 7: /* FSTP tbyte */
|
||||
GET_ED;
|
||||
GET_EDT;
|
||||
if(ST0.q!=STld(0).uref)
|
||||
D2LD(&ST0.d, ED);
|
||||
else
|
||||
|
@ -116,7 +116,7 @@ uintptr_t RunDC(x86emu_t *emu, uintptr_t addr)
|
||||
ST(nextop&7).d /= ST0.d;
|
||||
break;
|
||||
default:
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FADD ST0, double */
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
|
@ -118,7 +118,7 @@ uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FLD double */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
fpu_do_push(emu);
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d = *(double*)ED;
|
||||
@ -127,7 +127,7 @@ uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
case 1: /* FISTTP ED qword */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if(!(((uintptr_t)ED)&7)) {
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
*(int64_t*)ED = STll(0).sq;
|
||||
@ -152,7 +152,7 @@ uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 2: /* FST double */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(double*)ED = ST0.d;
|
||||
else {
|
||||
@ -160,7 +160,7 @@ uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
case 3: /* FSTP double */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(double*)ED = ST0.d;
|
||||
else {
|
||||
@ -169,8 +169,10 @@ uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FRSTOR m108byte */
|
||||
GET_ED;
|
||||
GET_ED_;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_loadenv(emu, (char*)ED, 0);
|
||||
#endif
|
||||
// get the STx
|
||||
{
|
||||
char* p =(char*)ED;
|
||||
@ -182,9 +184,10 @@ uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
case 6: /* FNSAVE m108byte */
|
||||
GET_ED;
|
||||
GET_ED_;
|
||||
// ENV first...
|
||||
// warning, incomplete
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 0);
|
||||
// save the STx
|
||||
{
|
||||
@ -195,6 +198,7 @@ uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
reset_fpu(emu);
|
||||
break;
|
||||
case 7: /* FNSTSW m2byte */
|
||||
|
@ -153,12 +153,12 @@ uintptr_t RunDF(x86emu_t *emu, uintptr_t addr)
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FBLD ST0, tbytes */
|
||||
GET_ED;
|
||||
GET_EDT;
|
||||
fpu_do_push(emu);
|
||||
fpu_fbld(emu, (uint8_t*)ED);
|
||||
break;
|
||||
case 5: /* FILD ST0, Gq */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
tmp64s = *(int64_t*)ED;
|
||||
fpu_do_push(emu);
|
||||
ST0.d = tmp64s;
|
||||
@ -166,12 +166,12 @@ uintptr_t RunDF(x86emu_t *emu, uintptr_t addr)
|
||||
STll(0).sref = ST0.sq;
|
||||
break;
|
||||
case 6: /* FBSTP tbytes, ST0 */
|
||||
GET_ED;
|
||||
GET_EDT;
|
||||
fpu_fbst(emu, (uint8_t*)ED);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 7: /* FISTP i64 */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if((uintptr_t)ED & 0x7) {
|
||||
// un-aligned!
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
|
@ -218,7 +218,12 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
tmp8u = GD.byte[0];
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
@ -252,7 +257,12 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
@ -275,7 +285,12 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
@ -307,7 +322,12 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
@ -344,7 +364,12 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
tmp8u = GD.byte[0];
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
@ -412,7 +437,7 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
break;
|
||||
case 0xC7: /* CMPXCHG8B Gq */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 1:
|
||||
CHECK_FLAGS(emu);
|
||||
@ -485,7 +510,11 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return TestF066(test, addr);
|
||||
#else
|
||||
return RunF066(emu, addr);
|
||||
#endif
|
||||
|
||||
case 0x81: /* GRP Ed,Id */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
|
159
src/emu/x86test.c
Normal file
159
src/emu/x86test.c
Normal file
@ -0,0 +1,159 @@
|
||||
#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 <stddef.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
#include "signals.h"
|
||||
|
||||
void print_banner(x86emu_t* ref)
|
||||
{
|
||||
printf_log(LOG_NONE, "Warning, difference between Interpreter and Dynarec in %p (%02x %02x %02x %02x %02x %02x %02x %02x)\n"\
|
||||
"=======================================\n",
|
||||
(void*)ref->old_ip,
|
||||
((uint8_t*)ref->old_ip)[0], ((uint8_t*)ref->old_ip)[1], ((uint8_t*)ref->old_ip)[2], ((uint8_t*)ref->old_ip)[3],
|
||||
((uint8_t*)ref->old_ip)[4], ((uint8_t*)ref->old_ip)[5], ((uint8_t*)ref->old_ip)[6], ((uint8_t*)ref->old_ip)[7]
|
||||
);
|
||||
printf_log(LOG_NONE, "DIFF: Dynarec | Interpreter\n----------------------\n");
|
||||
}
|
||||
#define BANNER if(!banner) {banner=1; print_banner(ref);}
|
||||
void x86test_check(x86emu_t* ref, uintptr_t ip)
|
||||
{
|
||||
int banner = 0;
|
||||
x86test_t* test = &ref->test;
|
||||
x86emu_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"};
|
||||
BANNER;
|
||||
for(int i=0; i<8; ++i) {
|
||||
if(ref->regs[i].dword[0]!=emu->regs[i].dword[0]) {
|
||||
printf_log(LOG_NONE, "%s: %08x | %08x\n", regname[i], ref->regs[i].dword[0], emu->regs[i].dword[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ip!=emu->ip.dword[0]) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "RIP: %08x | %08x\n", ip, emu->ip.dword[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]: %016llx | %016llx\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<8; ++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]: %016llx-%016llx | %016llx-%016llx\n", i, ref->xmm[i].q[1], ref->xmm[i].q[0], emu->xmm[i].q[1], emu->xmm[i].q[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
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]);
|
||||
printf_log(LOG_NONE, "\n");
|
||||
}
|
||||
}
|
||||
if(banner) // there was an error, re-sync!
|
||||
CopyEmu(emu, ref);
|
||||
}
|
||||
#undef BANNER
|
||||
|
||||
void x86test_init(x86emu_t* ref, uintptr_t ip)
|
||||
{
|
||||
x86test_t* test = &ref->test;
|
||||
if(!test->test) {
|
||||
test->clean = 0;
|
||||
return;
|
||||
}
|
||||
// check if test as a valid emu struct
|
||||
if(!test->emu) {
|
||||
test->emu = NewX86Emu(my_context, ip, (uintptr_t)ref->init_stack, ref->size_stack, 0);
|
||||
CopyEmu(test->emu, ref);
|
||||
} else {
|
||||
// check if IP is same, else, sync
|
||||
uintptr_t prev_ip = test->emu->ip.dword[0];
|
||||
if(test->clean)
|
||||
x86test_check(ref, ip);
|
||||
if(ip != prev_ip || !test->test) {
|
||||
CopyEmu(test->emu, ref);
|
||||
}
|
||||
}
|
||||
// Do a Dry single Step
|
||||
test->memsize = 0;
|
||||
test->clean = 1;
|
||||
ref->old_ip = ip;
|
||||
RunTest(test);
|
||||
// this will be anakyzed next step
|
||||
}
|
@ -140,6 +140,7 @@ typedef struct box86context_s {
|
||||
uint32_t mutex_bridge;
|
||||
uint32_t mutex_dyndump;
|
||||
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)
|
||||
|
@ -25,6 +25,7 @@ extern int box86_dynarec_fastnan;
|
||||
extern int box86_dynarec_fastround;
|
||||
extern int box86_dynarec_hotpage;
|
||||
extern int box86_dynarec_bleeding_edge;
|
||||
extern int box86_dynarec_test;
|
||||
#ifdef ARM
|
||||
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
extern int arm_swap;
|
||||
|
@ -4,5 +4,6 @@
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
void DynaCall(x86emu_t* emu, uintptr_t addr); // try to use DynaRec... Fallback to EmuCall if no dynarec available
|
||||
void x86test_init(x86emu_t* ref, uintptr_t ip);
|
||||
|
||||
#endif // __DYNAREC_H_
|
@ -10,6 +10,7 @@ void SetupX86Emu(x86emu_t *emu);
|
||||
void FreeX86Emu(x86emu_t **x86emu);
|
||||
void FreeX86EmuFromStack(x86emu_t **emu);
|
||||
void CloneEmu(x86emu_t *newemu, const x86emu_t* emu);
|
||||
void CopyEmu(x86emu_t *newemu, const x86emu_t* emu);
|
||||
void SetTraceEmu(uintptr_t trace_start, uintptr_t trace_end);
|
||||
|
||||
box86context_t* GetEmuContext(x86emu_t* emu);
|
||||
|
@ -3,7 +3,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct x86test_s x86test_t;
|
||||
int Run(x86emu_t *emu, int step); // 0 if run was successfull, 1 if error in x86 world
|
||||
int RunTest(x86test_t *test);
|
||||
int DynaRun(x86emu_t *emu);
|
||||
|
||||
uint32_t LibSyscall(x86emu_t *emu);
|
||||
|
@ -277,6 +277,10 @@ uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext,
|
||||
//trace_start = 0; trace_end = 1; // disabling trace, globably for now...
|
||||
|
||||
x86emu_t *emu = thread_get_emu();
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec_test)
|
||||
emu->test.test = 0;
|
||||
#endif
|
||||
|
||||
printf_log(LOG_DEBUG, "%04d|signal function handler %p called, ESP=%p\n", GetTID(), (void*)fnc, (void*)R_ESP);
|
||||
|
||||
@ -308,6 +312,12 @@ uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext,
|
||||
uint32_t ret = R_EAX;
|
||||
emu->quitonlongjmp = oldquitonlongjmp;
|
||||
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec_test)
|
||||
emu->test.test = 0;
|
||||
emu->test.clean = 0;
|
||||
#endif
|
||||
|
||||
if(emu->longjmp) {
|
||||
// longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
|
||||
emu->longjmp = 0;
|
||||
|
13
src/main.c
13
src/main.c
@ -67,6 +67,7 @@ int box86_dynarec_hotpage = 16;
|
||||
int box86_dynarec_bleeding_edge = 1;
|
||||
uintptr_t box86_nodynarec_start = 0;
|
||||
uintptr_t box86_nodynarec_end = 0;
|
||||
int box86_dynarec_test = 0;
|
||||
#ifdef ARM
|
||||
int arm_vfp = 0; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
int arm_swap = 0;
|
||||
@ -446,6 +447,18 @@ void LoadLogEnv()
|
||||
printf_log(LOG_INFO, "No Dynablock creation that start in %p - %p range\n", (void*)box86_nodynarec_start, (void*)box86_nodynarec_end);
|
||||
}
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_TEST");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_dynarec_test = p[0]-'0';
|
||||
}
|
||||
if(box86_dynarec_test) {
|
||||
box86_dynarec_fastnan = 0;
|
||||
box86_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
|
||||
|
@ -83,6 +83,7 @@ ENTRYINT(BOX86_DYNAREC_SAFEFLAGS, box86_dynarec_safeflags, 0, 2, 2) \
|
||||
ENTRYINT(BOX86_DYNAREC_HOTPAGE, box86_dynarec_hotpage, 0, 255, 8) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_BLEEDING_EDGE, box86_dynarec_bleeding_edge) \
|
||||
ENTRYSTRING_(BOX86_NODYNAREC, box86_nodynarec) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_TEST, box86_dynarec_test) \
|
||||
|
||||
#else
|
||||
#define SUPER3() \
|
||||
@ -99,6 +100,7 @@ IGNORE(BOX86_DYNAREC_SAFEFLAGS) \
|
||||
IGNORE(BOX86_DYNAREC_HOTPAGE) \
|
||||
IGNORE(BOX86_DYNAREC_BLEEDING_EDGE) \
|
||||
IGNORE(BOX86_NODYNAREC) \
|
||||
IGNORE(BOX86_DYNAREC_TEST) \
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user