diff --git a/quake3-fastcall.patch b/quake3-fastcall.patch new file mode 100644 index 0000000..3c550e8 --- /dev/null +++ b/quake3-fastcall.patch @@ -0,0 +1,202 @@ +From ffac0e67574891072f74db3769b5ca7e252853b1 Mon Sep 17 00:00:00 2001 +From: Thilo Schulz +Date: Wed, 8 Aug 2012 09:34:03 +0000 +Subject: [PATCH] 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 + +[jlayton: a little wiggling to merge into r2102] + +--- + code/asm/vm_x86_64.asm | 18 ---------- + code/qcommon/vm_x86.c | 91 ++++++++++++++++++++++---------------------------- + 2 files changed, 40 insertions(+), 69 deletions(-) + +diff --git a/code/asm/vm_x86_64.asm b/code/asm/vm_x86_64.asm +index 030b6987db94..87e04f4dbbd3 100644 +--- a/code/asm/vm_x86_64.asm ++++ b/code/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/code/qcommon/vm_x86.c b/code/qcommon/vm_x86.c +index aa63d048471e..080fe54ec15d 100644 +--- a/code/qcommon/vm_x86.c ++++ b/code/qcommon/vm_x86.c +@@ -389,55 +389,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 +@@ -445,34 +418,34 @@ static void DoSyscall(void) + intptr_t args[11]; + #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(data); ++ data[0] = ~vm_syscallNum; ++ vm_opStackBase[vm_opStackOfs + 1] = savedVM->systemCall(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; + } + } +@@ -503,13 +476,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. +@@ -521,6 +489,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 diff --git a/quake3.spec b/quake3.spec index f6e7a5c..ba73ccb 100644 --- a/quake3.spec +++ b/quake3.spec @@ -1,6 +1,6 @@ Name: quake3 Version: 1.36 -Release: 20.svn2102%{?dist} +Release: 21.svn2102%{?dist} Summary: Quake 3 Arena engine (ioquake3 version) Group: Amusements/Games License: GPLv2+ @@ -37,6 +37,7 @@ Patch2: 0011-Double-the-maximum-number-of-cvars.patch Patch3: 0012-Increase-the-command-buffer-from-16K-to-128K-followi.patch # big-endian build fix Patch4: quake3-1.36-build.patch +Patch5: quake3-fastcall.patch BuildRequires: SDL-devel libXt-devel openal-soft-devel libjpeg-devel BuildRequires: speex-devel libvorbis-devel curl-devel desktop-file-utils BuildRequires: zlib-devel @@ -141,6 +142,7 @@ Padman menu entry, which will automatically download the necessary datafiles %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 # Add jpeg_memsrc cp -p %{SOURCE15} %{SOURCE16} ./code/renderer/ @@ -273,6 +275,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %changelog +* Thu Feb 26 2015 Jon Ciesla - 1.36.21.svn2102 +- Move argument passing from VM to engine to global variables (rhbz#1018398) +- per Jeff Layton + * Sun Aug 17 2014 Fedora Release Engineering - 1.36-20.svn2102 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild