diff options
author | Thilo Schulz <arny@ats.s.bawue.de> | 2012-08-08 09:34:03 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-12 20:46:32 +0000 |
commit | b66b793567754f4256f41795297305c25b5bb94f (patch) | |
tree | 653e11fc520596a58a1248927e2108e2d89c3222 /src/qcommon | |
parent | b59190cd51d190f7b5111a2f4f85da86f0a0aa44 (diff) |
Move argument passing from VM to engine to global variables which allows to get rid of lots of OS specific stuff and also fixes errors that happens when compilers add lots of boilerplate to the DoSyscall() function
Diffstat (limited to 'src/qcommon')
-rw-r--r-- | src/qcommon/vm_x86.c | 91 |
1 files changed, 40 insertions, 51 deletions
diff --git a/src/qcommon/vm_x86.c b/src/qcommon/vm_x86.c index ef912729..2ef49752 100644 --- a/src/qcommon/vm_x86.c +++ b/src/qcommon/vm_x86.c @@ -391,55 +391,28 @@ static void ErrJump(void) /* ================= DoSyscall -Uses asm to retrieve arguments from registers to work around different calling conventions + +Assembler helper routines will write its arguments directly to global variables so as to +work around different calling conventions ================= */ -#if defined(_MSC_VER) && idx64 - -extern void qsyscall64(void); -extern uint8_t qvmcall64(int *programStack, int *opStack, intptr_t *instructionPointers, byte *dataBase); +int vm_syscallNum; +int vm_programStack; +int *vm_opStackBase; +uint8_t vm_opStackOfs; +intptr_t vm_arg; -// Microsoft does not support inline assembler on x64 platforms. Meh. -void DoSyscall(int syscallNum, int programStack, int *opStackBase, uint8_t opStackOfs, intptr_t arg) -{ -#else static void DoSyscall(void) { - int syscallNum; - int programStack; - int *opStackBase; - uint8_t opStackOfs; - intptr_t arg; -#endif - vm_t *savedVM; -#if defined(_MSC_VER) - #if !idx64 - __asm - { - mov dword ptr syscallNum, eax - mov dword ptr programStack, esi - mov byte ptr opStackOfs, bl - mov dword ptr opStackBase, edi - mov dword ptr arg, ecx - } - #endif -#else - __asm__ volatile( - "" - : "=a" (syscallNum), "=S" (programStack), "=D" (opStackBase), "=b" (opStackOfs), - "=c" (arg) - ); -#endif - // save currentVM so as to allow for recursive VM entry savedVM = currentVM; // modify VM stack pointer for recursive VM entry - currentVM->programStack = programStack - 4; + currentVM->programStack = vm_programStack - 4; - if(syscallNum < 0) + if(vm_syscallNum < 0) { int *data; #if idx64 @@ -447,34 +420,34 @@ static void DoSyscall(void) intptr_t args[16]; #endif - data = (int *) (savedVM->dataBase + programStack + 4); + data = (int *) (savedVM->dataBase + vm_programStack + 4); #if idx64 - args[0] = ~syscallNum; + args[0] = ~vm_syscallNum; for(index = 1; index < ARRAY_LEN(args); index++) args[index] = data[index]; - opStackBase[opStackOfs + 1] = savedVM->systemCall(args); + vm_opStackBase[vm_opStackOfs + 1] = savedVM->systemCall(args); #else - data[0] = ~syscallNum; - opStackBase[opStackOfs + 1] = savedVM->systemCall((intptr_t *) data); + data[0] = ~vm_syscallNum; + vm_opStackBase[vm_opStackOfs + 1] = savedVM->systemCall((intptr_t *) data); #endif } else { - switch(syscallNum) + switch(vm_syscallNum) { case VM_JMP_VIOLATION: ErrJump(); break; case VM_BLOCK_COPY: - if(opStackOfs < 1) + if(vm_opStackOfs < 1) Com_Error(ERR_DROP, "VM_BLOCK_COPY failed due to corrupted opStack"); - VM_BlockCopy(opStackBase[(opStackOfs - 1)], opStackBase[opStackOfs], arg); + VM_BlockCopy(vm_opStackBase[(vm_opStackOfs - 1)], vm_opStackBase[vm_opStackOfs], vm_arg); break; default: - Com_Error(ERR_DROP, "Unknown VM operation %d", syscallNum); + Com_Error(ERR_DROP, "Unknown VM operation %d", vm_syscallNum); break; } } @@ -505,13 +478,8 @@ Call to DoSyscall() int EmitCallDoSyscall(vm_t *vm) { // use edx register to store DoSyscall address -#if defined(_MSC_VER) && idx64 - EmitRexString(0x48, "BA"); // mov edx, qsyscall64 - EmitPtr(qsyscall64); -#else EmitRexString(0x48, "BA"); // mov edx, DoSyscall EmitPtr(DoSyscall); -#endif // Push important registers to stack as we can't really make // any assumptions about calling conventions. @@ -523,6 +491,27 @@ int EmitCallDoSyscall(vm_t *vm) EmitRexString(0x41, "51"); // push r9 #endif + // write arguments to global vars + // syscall number + EmitString("A3"); // mov [0x12345678], eax + EmitPtr(&vm_syscallNum); + // vm_programStack value + EmitString("89 F0"); // mov eax, esi + EmitString("A3"); // mov [0x12345678], eax + EmitPtr(&vm_programStack); + // vm_opStackOfs + EmitString("88 D8"); // mov al, bl + EmitString("A2"); // mov [0x12345678], al + EmitPtr(&vm_opStackOfs); + // vm_opStackBase + EmitRexString(0x48, "89 F8"); // mov eax, edi + EmitRexString(0x48, "A3"); // mov [0x12345678], eax + EmitPtr(&vm_opStackBase); + // vm_arg + EmitString("89 C8"); // mov eax, ecx + EmitString("A3"); // mov [0x12345678], eax + EmitPtr(&vm_arg); + // align the stack pointer to a 16-byte-boundary EmitString("55"); // push ebp EmitRexString(0x48, "89 E5"); // mov ebp, esp |