diff options
Diffstat (limited to 'src/tools/callback.c')
| -rw-r--r-- | src/tools/callback.c | 104 |
1 files changed, 95 insertions, 9 deletions
diff --git a/src/tools/callback.c b/src/tools/callback.c index 9aafa6d8..f3a6bbbf 100644 --- a/src/tools/callback.c +++ b/src/tools/callback.c @@ -14,10 +14,8 @@ #include "dynarec.h" EXPORTDYN -uint64_t RunFunction(box64context_t *context, uintptr_t fnc, int nargs, ...) +uint64_t RunFunction(uintptr_t fnc, int nargs, ...) { - (void)context; - x64emu_t *emu = thread_get_emu(); int align = (nargs>6)?(((nargs-6)&1)):0; int stackn = align + ((nargs>6)?(nargs-6):0); @@ -56,11 +54,101 @@ uint64_t RunFunction(box64context_t *context, uintptr_t fnc, int nargs, ...) } EXPORTDYN -uint64_t RunSafeFunction(box64context_t *context, uintptr_t fnc, int nargs, ...) +uint64_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...) { - (void)context; - x64emu_t *emu = thread_get_emu(); + int nargs = 0; + int ni = 0; + int ndf = 0; + for (int i=0; fmt[i]; ++i) { + switch(fmt[i]) { + case 'f': + case 'd': if(ndf<8) ++ndf; else ++nargs; break; + case 'p': + case 'i': + case 'u': + case 'I': + case 'U': + case 'L': + case 'l': + case 'w': + case 'W': + case 'c': + case 'C': if(ni<6) ++ni; else ++nargs; break; + default: + if(ni<6) ++ni; else ++nargs; break; + } + } + ni = 0; + ndf = 0; + int align = nargs&1; + int stackn = align + nargs; + + Push64(emu, R_RBP); // push rbp + R_RBP = R_RSP; // mov rbp, rsp + + R_RSP -= stackn*sizeof(void*); // need to push in reverse order + + uint64_t *p = (uint64_t*)R_RSP; + + static const int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9}; + #define GO(c, A, B, B2, C) case c: if(ni<6) emu->regs[nn[ni++]].A[0] = C va_arg(va, B2); else {*p = 0; *((B*)p) = va_arg(va, B2); ++p;}; break; + va_list va; + va_start (va, fmt); + for (int i=0; fmt[i]; ++i) { + switch(fmt[i]) { + case 'f': if(ndf<8) + emu->xmm[ndf++].f[0] = va_arg(va, double); // float are promoted to double in ... + else { + *p = 0; + *((float*)p) = va_arg(va, double); + ++p; + } + break; + case 'd': if(ndf<8) + emu->xmm[ndf++].d[0] = va_arg(va, double); + else { + *((double*)p) = va_arg(va, double); + ++p; + } + break; + GO('p', q, void*, void*, (uintptr_t)) + GO('i', sdword, int, int, ) + GO('u', dword, uint32_t, uint32_t, ) + GO('I', sq, int64_t, int64_t, ) + GO('U', q, uint64_t, uint64_t, ) + GO('L', q, uint64_t, uint64_t, ) + GO('l', sq, int64_t, int64_t, ) + GO('w', sword, int16_t, int, ) + GO('W', word, uint16_t, int, ) + GO('c', sbyte, int8_t, int, ) + GO('C', byte, uint8_t, int, ) + default: + printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]); + if(ni<6) emu->regs[nn[ni++]].q[0] = va_arg(va, uint64_t); else {*p = va_arg(va, uint64_t); ++p;}; + break; + } + } + va_end (va); + + uintptr_t oldip = R_RIP; + DynaCall(emu, fnc); + + if(oldip==R_RIP) { + R_RSP = R_RBP; // mov rsp, rbp + R_RBP = Pop64(emu); // pop rbp + } + + uint64_t ret = R_RAX; + + return ret; +} + +EXPORTDYN +uint64_t RunSafeFunction(uintptr_t fnc, int nargs, ...) +{ + x64emu_t * emu = thread_get_emu(); + int align = (nargs>6)?(((nargs-6)&1)):0; int stackn = align + ((nargs>6)?(nargs-6):0); @@ -165,10 +253,8 @@ uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in } EXPORTDYN -uint64_t RunFunctionWindows(box64context_t *context, uintptr_t fnc, int nargs, ...) +uint64_t RunFunctionWindows(uintptr_t fnc, int nargs, ...) { - (void)context; - x64emu_t *emu = thread_get_emu(); int align = (nargs>4)?(((nargs-4)&1)):0; int stackn = align + ((nargs>4)?(nargs-4):0); |