[DYNAREC] Added BOX64_DYNAREC_TEST to run interpeter and dynarec at the same time and compare states

This commit is contained in:
ptitSeb 2023-03-27 23:21:36 +02:00
parent feb4a39457
commit 9f75f28e7a
46 changed files with 1138 additions and 88 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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.

View File

@ -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);

View File

@ -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)

View File

@ -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_

View File

@ -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;

View File

@ -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)) {

View File

@ -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_

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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)) {

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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)
{

View File

@ -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);

View File

@ -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) {

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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
View 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

View File

@ -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)

View File

@ -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;

View File

@ -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_

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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