about summary refs log tree commit diff stats
path: root/src/tools/callback.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/callback.c')
-rw-r--r--src/tools/callback.c104
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);