diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/asm/vm_x86_64.asm | 18 | ||||
| -rw-r--r-- | src/qcommon/vm_x86.c | 91 | 
2 files changed, 40 insertions, 69 deletions
diff --git a/src/asm/vm_x86_64.asm b/src/asm/vm_x86_64.asm index 030b6987..87e04f4d 100644 --- a/src/asm/vm_x86_64.asm +++ b/src/asm/vm_x86_64.asm @@ -23,26 +23,8 @@  ;  ; assumes __fastcall calling convention -DoSyscall PROTO -  .code -; Call to static void DoSyscall(int syscallNum, int programStack, int *opStackBase, uint8_t opStackOfs, intptr_t arg) - -qsyscall64 PROC -  sub rsp, 28h						; after this esp will be aligned to 16 byte boundary -  mov qword ptr [rsp + 20h], rcx	; 5th parameter "arg" is passed on stack -  mov r9b, bl						; opStackOfs -  mov r8, rdi						; opStackBase -  mov edx, esi						; programStack -  mov ecx, eax						; syscallNum -  mov rax, DoSyscall				; store call address of DoSyscall in rax -  call rax -  add rsp, 28h -  ret -qsyscall64 ENDP - -  ; Call to compiled code after setting up the register environment for the VM  ; prototype:  ; uint8_t qvmcall64(int *programStack, int *opStack, intptr_t *instructionPointers, byte *dataBase); 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  | 
