|
|
3e9809c |
From ffac0e67574891072f74db3769b5ca7e252853b1 Mon Sep 17 00:00:00 2001
|
|
|
3e9809c |
From: Thilo Schulz <arny@ats.s.bawue.de>
|
|
|
3e9809c |
Date: Wed, 8 Aug 2012 09:34:03 +0000
|
|
|
3e9809c |
Subject: [PATCH] Move argument passing from VM to engine to global variables
|
|
|
3e9809c |
which allows to get rid of lots of OS specific stuff and also fixes errors
|
|
|
3e9809c |
that happens when compilers add lots of boilerplate to the DoSyscall()
|
|
|
3e9809c |
function
|
|
|
3e9809c |
|
|
|
3e9809c |
[jlayton: a little wiggling to merge into r2102]
|
|
|
3e9809c |
|
|
|
3e9809c |
---
|
|
|
3e9809c |
code/asm/vm_x86_64.asm | 18 ----------
|
|
|
3e9809c |
code/qcommon/vm_x86.c | 91 ++++++++++++++++++++++----------------------------
|
|
|
3e9809c |
2 files changed, 40 insertions(+), 69 deletions(-)
|
|
|
3e9809c |
|
|
|
3e9809c |
diff --git a/code/asm/vm_x86_64.asm b/code/asm/vm_x86_64.asm
|
|
|
3e9809c |
index 030b6987db94..87e04f4dbbd3 100644
|
|
|
3e9809c |
--- a/code/asm/vm_x86_64.asm
|
|
|
3e9809c |
+++ b/code/asm/vm_x86_64.asm
|
|
|
3e9809c |
@@ -23,26 +23,8 @@
|
|
|
3e9809c |
;
|
|
|
3e9809c |
; assumes __fastcall calling convention
|
|
|
3e9809c |
|
|
|
3e9809c |
-DoSyscall PROTO
|
|
|
3e9809c |
-
|
|
|
3e9809c |
.code
|
|
|
3e9809c |
|
|
|
3e9809c |
-; Call to static void DoSyscall(int syscallNum, int programStack, int *opStackBase, uint8_t opStackOfs, intptr_t arg)
|
|
|
3e9809c |
-
|
|
|
3e9809c |
-qsyscall64 PROC
|
|
|
3e9809c |
- sub rsp, 28h ; after this esp will be aligned to 16 byte boundary
|
|
|
3e9809c |
- mov qword ptr [rsp + 20h], rcx ; 5th parameter "arg" is passed on stack
|
|
|
3e9809c |
- mov r9b, bl ; opStackOfs
|
|
|
3e9809c |
- mov r8, rdi ; opStackBase
|
|
|
3e9809c |
- mov edx, esi ; programStack
|
|
|
3e9809c |
- mov ecx, eax ; syscallNum
|
|
|
3e9809c |
- mov rax, DoSyscall ; store call address of DoSyscall in rax
|
|
|
3e9809c |
- call rax
|
|
|
3e9809c |
- add rsp, 28h
|
|
|
3e9809c |
- ret
|
|
|
3e9809c |
-qsyscall64 ENDP
|
|
|
3e9809c |
-
|
|
|
3e9809c |
-
|
|
|
3e9809c |
; Call to compiled code after setting up the register environment for the VM
|
|
|
3e9809c |
; prototype:
|
|
|
3e9809c |
; uint8_t qvmcall64(int *programStack, int *opStack, intptr_t *instructionPointers, byte *dataBase);
|
|
|
3e9809c |
diff --git a/code/qcommon/vm_x86.c b/code/qcommon/vm_x86.c
|
|
|
3e9809c |
index aa63d048471e..080fe54ec15d 100644
|
|
|
3e9809c |
--- a/code/qcommon/vm_x86.c
|
|
|
3e9809c |
+++ b/code/qcommon/vm_x86.c
|
|
|
3e9809c |
@@ -389,55 +389,28 @@ static void ErrJump(void)
|
|
|
3e9809c |
/*
|
|
|
3e9809c |
=================
|
|
|
3e9809c |
DoSyscall
|
|
|
3e9809c |
-Uses asm to retrieve arguments from registers to work around different calling conventions
|
|
|
3e9809c |
+
|
|
|
3e9809c |
+Assembler helper routines will write its arguments directly to global variables so as to
|
|
|
3e9809c |
+work around different calling conventions
|
|
|
3e9809c |
=================
|
|
|
3e9809c |
*/
|
|
|
3e9809c |
|
|
|
3e9809c |
-#if defined(_MSC_VER) && idx64
|
|
|
3e9809c |
-
|
|
|
3e9809c |
-extern void qsyscall64(void);
|
|
|
3e9809c |
-extern uint8_t qvmcall64(int *programStack, int *opStack, intptr_t *instructionPointers, byte *dataBase);
|
|
|
3e9809c |
+int vm_syscallNum;
|
|
|
3e9809c |
+int vm_programStack;
|
|
|
3e9809c |
+int *vm_opStackBase;
|
|
|
3e9809c |
+uint8_t vm_opStackOfs;
|
|
|
3e9809c |
+intptr_t vm_arg;
|
|
|
3e9809c |
|
|
|
3e9809c |
-// Microsoft does not support inline assembler on x64 platforms. Meh.
|
|
|
3e9809c |
-void DoSyscall(int syscallNum, int programStack, int *opStackBase, uint8_t opStackOfs, intptr_t arg)
|
|
|
3e9809c |
-{
|
|
|
3e9809c |
-#else
|
|
|
3e9809c |
static void DoSyscall(void)
|
|
|
3e9809c |
{
|
|
|
3e9809c |
- int syscallNum;
|
|
|
3e9809c |
- int programStack;
|
|
|
3e9809c |
- int *opStackBase;
|
|
|
3e9809c |
- uint8_t opStackOfs;
|
|
|
3e9809c |
- intptr_t arg;
|
|
|
3e9809c |
-#endif
|
|
|
3e9809c |
-
|
|
|
3e9809c |
vm_t *savedVM;
|
|
|
3e9809c |
|
|
|
3e9809c |
-#if defined(_MSC_VER)
|
|
|
3e9809c |
- #if !idx64
|
|
|
3e9809c |
- __asm
|
|
|
3e9809c |
- {
|
|
|
3e9809c |
- mov dword ptr syscallNum, eax
|
|
|
3e9809c |
- mov dword ptr programStack, esi
|
|
|
3e9809c |
- mov byte ptr opStackOfs, bl
|
|
|
3e9809c |
- mov dword ptr opStackBase, edi
|
|
|
3e9809c |
- mov dword ptr arg, ecx
|
|
|
3e9809c |
- }
|
|
|
3e9809c |
- #endif
|
|
|
3e9809c |
-#else
|
|
|
3e9809c |
- __asm__ volatile(
|
|
|
3e9809c |
- ""
|
|
|
3e9809c |
- : "=a" (syscallNum), "=S" (programStack), "=D" (opStackBase), "=b" (opStackOfs),
|
|
|
3e9809c |
- "=c" (arg)
|
|
|
3e9809c |
- );
|
|
|
3e9809c |
-#endif
|
|
|
3e9809c |
-
|
|
|
3e9809c |
// save currentVM so as to allow for recursive VM entry
|
|
|
3e9809c |
savedVM = currentVM;
|
|
|
3e9809c |
// modify VM stack pointer for recursive VM entry
|
|
|
3e9809c |
- currentVM->programStack = programStack - 4;
|
|
|
3e9809c |
+ currentVM->programStack = vm_programStack - 4;
|
|
|
3e9809c |
|
|
|
3e9809c |
- if(syscallNum < 0)
|
|
|
3e9809c |
+ if(vm_syscallNum < 0)
|
|
|
3e9809c |
{
|
|
|
3e9809c |
int *data;
|
|
|
3e9809c |
#if idx64
|
|
|
3e9809c |
@@ -445,34 +418,34 @@ static void DoSyscall(void)
|
|
|
3e9809c |
intptr_t args[11];
|
|
|
3e9809c |
#endif
|
|
|
3e9809c |
|
|
|
3e9809c |
- data = (int *) (savedVM->dataBase + programStack + 4);
|
|
|
3e9809c |
+ data = (int *) (savedVM->dataBase + vm_programStack + 4);
|
|
|
3e9809c |
|
|
|
3e9809c |
#if idx64
|
|
|
3e9809c |
- args[0] = ~syscallNum;
|
|
|
3e9809c |
+ args[0] = ~vm_syscallNum;
|
|
|
3e9809c |
for(index = 1; index < ARRAY_LEN(args); index++)
|
|
|
3e9809c |
args[index] = data[index];
|
|
|
3e9809c |
|
|
|
3e9809c |
- opStackBase[opStackOfs + 1] = savedVM->systemCall(args);
|
|
|
3e9809c |
+ vm_opStackBase[vm_opStackOfs + 1] = savedVM->systemCall(args);
|
|
|
3e9809c |
#else
|
|
|
3e9809c |
- data[0] = ~syscallNum;
|
|
|
3e9809c |
- opStackBase[opStackOfs + 1] = savedVM->systemCall(data);
|
|
|
3e9809c |
+ data[0] = ~vm_syscallNum;
|
|
|
3e9809c |
+ vm_opStackBase[vm_opStackOfs + 1] = savedVM->systemCall(data);
|
|
|
3e9809c |
#endif
|
|
|
3e9809c |
}
|
|
|
3e9809c |
else
|
|
|
3e9809c |
{
|
|
|
3e9809c |
- switch(syscallNum)
|
|
|
3e9809c |
+ switch(vm_syscallNum)
|
|
|
3e9809c |
{
|
|
|
3e9809c |
case VM_JMP_VIOLATION:
|
|
|
3e9809c |
ErrJump();
|
|
|
3e9809c |
break;
|
|
|
3e9809c |
case VM_BLOCK_COPY:
|
|
|
3e9809c |
- if(opStackOfs < 1)
|
|
|
3e9809c |
+ if(vm_opStackOfs < 1)
|
|
|
3e9809c |
Com_Error(ERR_DROP, "VM_BLOCK_COPY failed due to corrupted opStack");
|
|
|
3e9809c |
|
|
|
3e9809c |
- VM_BlockCopy(opStackBase[(opStackOfs - 1)], opStackBase[opStackOfs], arg);
|
|
|
3e9809c |
+ VM_BlockCopy(vm_opStackBase[(vm_opStackOfs - 1)], vm_opStackBase[vm_opStackOfs], vm_arg);
|
|
|
3e9809c |
break;
|
|
|
3e9809c |
default:
|
|
|
3e9809c |
- Com_Error(ERR_DROP, "Unknown VM operation %d", syscallNum);
|
|
|
3e9809c |
+ Com_Error(ERR_DROP, "Unknown VM operation %d", vm_syscallNum);
|
|
|
3e9809c |
break;
|
|
|
3e9809c |
}
|
|
|
3e9809c |
}
|
|
|
3e9809c |
@@ -503,13 +476,8 @@ Call to DoSyscall()
|
|
|
3e9809c |
int EmitCallDoSyscall(vm_t *vm)
|
|
|
3e9809c |
{
|
|
|
3e9809c |
// use edx register to store DoSyscall address
|
|
|
3e9809c |
-#if defined(_MSC_VER) && idx64
|
|
|
3e9809c |
- EmitRexString(0x48, "BA"); // mov edx, qsyscall64
|
|
|
3e9809c |
- EmitPtr(qsyscall64);
|
|
|
3e9809c |
-#else
|
|
|
3e9809c |
EmitRexString(0x48, "BA"); // mov edx, DoSyscall
|
|
|
3e9809c |
EmitPtr(DoSyscall);
|
|
|
3e9809c |
-#endif
|
|
|
3e9809c |
|
|
|
3e9809c |
// Push important registers to stack as we can't really make
|
|
|
3e9809c |
// any assumptions about calling conventions.
|
|
|
3e9809c |
@@ -521,6 +489,27 @@ int EmitCallDoSyscall(vm_t *vm)
|
|
|
3e9809c |
EmitRexString(0x41, "51"); // push r9
|
|
|
3e9809c |
#endif
|
|
|
3e9809c |
|
|
|
3e9809c |
+ // write arguments to global vars
|
|
|
3e9809c |
+ // syscall number
|
|
|
3e9809c |
+ EmitString("A3"); // mov [0x12345678], eax
|
|
|
3e9809c |
+ EmitPtr(&vm_syscallNum);
|
|
|
3e9809c |
+ // vm_programStack value
|
|
|
3e9809c |
+ EmitString("89 F0"); // mov eax, esi
|
|
|
3e9809c |
+ EmitString("A3"); // mov [0x12345678], eax
|
|
|
3e9809c |
+ EmitPtr(&vm_programStack);
|
|
|
3e9809c |
+ // vm_opStackOfs
|
|
|
3e9809c |
+ EmitString("88 D8"); // mov al, bl
|
|
|
3e9809c |
+ EmitString("A2"); // mov [0x12345678], al
|
|
|
3e9809c |
+ EmitPtr(&vm_opStackOfs);
|
|
|
3e9809c |
+ // vm_opStackBase
|
|
|
3e9809c |
+ EmitRexString(0x48, "89 F8"); // mov eax, edi
|
|
|
3e9809c |
+ EmitRexString(0x48, "A3"); // mov [0x12345678], eax
|
|
|
3e9809c |
+ EmitPtr(&vm_opStackBase);
|
|
|
3e9809c |
+ // vm_arg
|
|
|
3e9809c |
+ EmitString("89 C8"); // mov eax, ecx
|
|
|
3e9809c |
+ EmitString("A3"); // mov [0x12345678], eax
|
|
|
3e9809c |
+ EmitPtr(&vm_arg);
|
|
|
3e9809c |
+
|
|
|
3e9809c |
// align the stack pointer to a 16-byte-boundary
|
|
|
3e9809c |
EmitString("55"); // push ebp
|
|
|
3e9809c |
EmitRexString(0x48, "89 E5"); // mov ebp, esp
|