x64: updated system call signatures to accepts and return values of type intptr_t.

This commit is contained in:
Artem Kharytoniuk 2016-06-25 21:48:48 +03:00
parent d4f7c1b467
commit c6836b54b2
11 changed files with 48 additions and 82 deletions

View File

@ -28,10 +28,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
static int (QDECL *syscall)( int arg, ... ) = (int (QDECL *)( int, ...))-1;
static intptr_t (QDECL *syscall)( intptr_t arg, ... ) = (intptr_t (QDECL *)( intptr_t, ...))-1;
void dllEntry( int (QDECL *syscallptr)( int arg,... ) ) {
void dllEntry( intptr_t (QDECL *syscallptr)( intptr_t arg,... ) ) {
syscall = syscallptr;
}

View File

@ -413,8 +413,9 @@ The cgame module is making a system call
====================
*/
#define VMA(x) VM_ArgPtr(args[x])
#define VMF(x) ((float *)args)[x]
int CL_CgameSystemCalls( int *args ) {
#define VMF(x) (*(float*)&args[x])
intptr_t CL_CgameSystemCalls( intptr_t *args ) {
switch( args[0] ) {
case CG_PRINT:
Com_Printf( "%s", VMA(1) );

View File

@ -757,9 +757,9 @@ static int FloatAsInt( float f ) {
return temp;
}
void *VM_ArgPtr( int intValue );
void *VM_ArgPtr( intptr_t intValue );
#define VMA(x) VM_ArgPtr(args[x])
#define VMF(x) ((float *)args)[x]
#define VMF(x) (*(float*)&args[x])
/*
====================
@ -768,7 +768,7 @@ CL_UISystemCalls
The ui module is making a system call
====================
*/
int CL_UISystemCalls( int *args ) {
intptr_t CL_UISystemCalls( intptr_t *args ) {
switch( args[0] ) {
case UI_ERROR:
Com_Error( ERR_DROP, "%s", VMA(1) );

View File

@ -28,10 +28,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#error "Do not use in VM build"
#endif
static int (QDECL *syscall)( int arg, ... ) = (int (QDECL *)( int, ...))-1;
static intptr_t (QDECL *syscall)( intptr_t arg, ... ) = (intptr_t (QDECL *)( intptr_t, ...))-1;
void dllEntry( int (QDECL *syscallptr)( int arg,... ) ) {
void dllEntry( intptr_t (QDECL *syscallptr)( intptr_t arg,... ) ) {
syscall = syscallptr;
}

View File

@ -28,9 +28,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#error "Do not use in VM build"
#endif
static int (QDECL *syscall)( int arg, ... ) = (int (QDECL *)( int, ...))-1;
static intptr_t (QDECL *syscall)( intptr_t arg, ... ) = (intptr_t (QDECL *)( intptr_t, ...))-1;
void dllEntry( int (QDECL *syscallptr)( int arg,... ) ) {
void dllEntry( intptr_t (QDECL *syscallptr)( intptr_t arg,... ) ) {
syscall = syscallptr;
}

View File

@ -310,7 +310,7 @@ typedef enum {
} sharedTraps_t;
void VM_Init( void );
vm_t *VM_Create( const char *module, int (*systemCalls)(int *),
vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
vmInterpret_t interpret );
// module should be bare: "cgame", not "cgame.dll" or "vm/cgame.qvm"
@ -322,8 +322,9 @@ intptr_t QDECL VM_Call( vm_t *vm, int callNum, ... );
void VM_Debug( int level );
void *VM_ArgPtr( int intValue );
void *VM_ExplicitArgPtr( vm_t *vm, int intValue );
void *VM_ArgPtr( intptr_t intValue );
void *VM_ExplicitArgPtr( vm_t *vm, intptr_t intValue );
/*
==============================================================
@ -928,7 +929,7 @@ void Sys_Init (void);
// general development dll loading for virtual machine testing
// fqpath param added 7/20/02 by T.Ray - Sys_LoadDll is only called in vm.c at this time
void * QDECL Sys_LoadDll( const char *name, char *fqpath , intptr_t (QDECL **entryPoint)(int, ...),
int (QDECL *systemcalls)(int, ...) );
intptr_t (QDECL *systemcalls)(intptr_t, ...) );
void Sys_UnloadDll( void *dllHandle );
void Sys_UnloadGame( void );

View File

@ -249,62 +249,19 @@ void VM_LoadSymbols( vm_t *vm ) {
FS_FreeFile( mapfile );
}
/*
============
VM_DllSyscall
Dlls will call this directly
rcg010206 The horror; the horror.
The syscall mechanism relies on stack manipulation to get it's args.
This is likely due to C's inability to pass "..." parameters to
a function in one clean chunk. On PowerPC Linux, these parameters
are not necessarily passed on the stack, so while (&arg[0] == arg)
is true, (&arg[1] == 2nd function parameter) is not necessarily
accurate, as arg's value might have been stored to the stack or
other piece of scratch memory to give it a valid address, but the
next parameter might still be sitting in a register.
Quake's syscall system also assumes that the stack grows downward,
and that any needed types can be squeezed, safely, into a signed int.
This hack below copies all needed values for an argument to a
array in memory, so that Quake can get the correct values. This can
also be used on systems where the stack grows upwards, as the
presumably standard and safe stdargs.h macros are used.
As for having enough space in a signed int for your datatypes, well,
it might be better to wait for DOOM 3 before you start porting. :)
The original code, while probably still inherently dangerous, seems
to work well enough for the platforms it already works on. Rather
than add the performance hit for those platforms, the original code
is still in use there.
For speed, we just grab 15 arguments, and don't worry about exactly
how many the syscall actually needs; the extra is thrown away.
============
*/
int QDECL VM_DllSyscall( int arg, ... ) {
#ifdef _WIN64
// rcg010206 - see commentary above
int args[16];
intptr_t QDECL VM_DllSyscall( intptr_t arg, ... ) {
intptr_t args[MAX_VMSYSCALL_ARGS];
int i;
va_list ap;
args[0] = arg;
va_start(ap, arg);
for (i = 1; i < sizeof (args) / sizeof (args[i]); i++)
args[i] = va_arg(ap, int);
for (i = 1; i < ARRAY_LEN(args); i++)
args[i] = va_arg(ap, intptr_t);
va_end(ap);
return currentVM->systemCall( args );
#else // original id code
return currentVM->systemCall( &arg );
#endif
}
/*
@ -325,7 +282,7 @@ vm_t *VM_Restart( vm_t *vm ) {
// DLL's can't be restarted in place
if ( vm->dllHandle ) {
char name[MAX_QPATH];
int (*systemCall)( int *parms );
intptr_t (*systemCall)( intptr_t *parms );
systemCall = vm->systemCall;
Q_strncpyz( name, vm->name, sizeof( name ) );
@ -395,7 +352,7 @@ it will attempt to load as a system dll
#define STACK_SIZE 0x20000
vm_t *VM_Create( const char *module, int (*systemCalls)(int *),
vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
vmInterpret_t interpret ) {
vm_t *vm;
vmHeader_t *header;
@ -572,7 +529,7 @@ void VM_Clear(void) {
lastVM = NULL;
}
void *VM_ArgPtr( int intValue ) {
void *VM_ArgPtr( intptr_t intValue ) {
if ( !intValue ) {
return NULL;
}
@ -588,7 +545,7 @@ void *VM_ArgPtr( int intValue ) {
}
}
void *VM_ExplicitArgPtr( vm_t *vm, int intValue ) {
void *VM_ExplicitArgPtr( vm_t *vm, intptr_t intValue ) {
if ( !intValue ) {
return NULL;
}
@ -805,7 +762,7 @@ void VM_LogSyscalls( int *args ) {
f = fopen("syscalls.log", "w" );
}
callnum++;
fprintf(f, "%i: %i (%i) = %i %i %i %i\n", callnum, args - (int *)currentVM->dataBase,
fprintf(f, "%i: %i (%i) = %i %i %i %i\n", callnum, (int)(intptr_t)( args - (int *)currentVM->dataBase ),
args[0], args[1], args[2], args[3], args[4] );
}

View File

@ -479,7 +479,7 @@ nextInstruction2:
src = (int *)&image[ r0&dataMask ];
dest = (int *)&image[ r1&dataMask ];
if ( ( (int)src | (int)dest | count ) & 3 ) {
if ( ( (intptr_t)src | (intptr_t)dest | count ) & 3 ) {
Com_Error( ERR_DROP, "OP_BLOCK_COPY not dword aligned" );
}
count >>= 2;
@ -518,7 +518,16 @@ nextInstruction2:
*(int *)&image[ programStack + 4 ] = -1 - programCounter;
//VM_LogSyscalls( (int *)&image[ programStack + 4 ] );
r = vm->systemCall( (int *)&image[ programStack + 4 ] );
{
intptr_t argarr[MAX_VMSYSCALL_ARGS];
int *imagePtr = (int *)&image[ programStack + 4 ];
int i;
for (i = 0; i < ARRAY_LEN(argarr); i++) {
argarr[i] = *imagePtr;
imagePtr++;
}
r = vm->systemCall( argarr );
}
#ifdef DEBUG_VM
// this is just our stack frame pointer, only needed

View File

@ -22,6 +22,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../game/q_shared.h"
#include "qcommon.h"
// Max number of arguments to pass from a vm to engine's syscall handler function for the vm.
// syscall number + 15 arguments
#define MAX_VMSYSCALL_ARGS 16
typedef enum {
OP_UNDEF,
@ -127,7 +131,7 @@ struct vm_s {
// DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES
// USED BY THE ASM CODE
int programStack; // the vm may be recursively entered
int (*systemCall)( int *parms );
intptr_t (*systemCall)( intptr_t *parms );
//------------------------------------

View File

@ -305,16 +305,10 @@ SV_GameSystemCalls
The module is making a system call
====================
*/
//rcg010207 - see my comments in VM_DllSyscall(), in qcommon/vm.c ...
#if ((defined __linux__) && (defined __powerpc__))
#define VMA(x) ((void *) args[x])
#else
#define VMA(x) VM_ArgPtr(args[x])
#endif
#define VMF(x) (*(float*)&args[x])
#define VMF(x) ((float *)args)[x]
int SV_GameSystemCalls( int *args ) {
intptr_t SV_GameSystemCalls( intptr_t *args ) {
switch( args[0] ) {
case G_PRINT:
Com_Printf( "%s", VMA(1) );

View File

@ -527,10 +527,10 @@ extern char *FS_BuildOSPath( const char *base, const char *game, const char *qp
// fqpath will be empty if dll not loaded, otherwise will hold fully qualified path of dll module loaded
// fqpath buffersize must be at least MAX_QPATH+1 bytes long
void * QDECL Sys_LoadDll( const char *name, char *fqpath , intptr_t (QDECL **entryPoint)(int, ...),
int (QDECL *systemcalls)(int, ...) ) {
intptr_t (QDECL *systemcalls)(intptr_t, ...) ) {
static int lastWarning = 0;
HINSTANCE libHandle;
void (QDECL *dllEntry)( int (QDECL *syscallptr)(int, ...) );
void (QDECL *dllEntry)( intptr_t (QDECL *syscallptr)(intptr_t, ...) );
char *basepath;
char *cdpath;
char *gamedir;
@ -606,7 +606,7 @@ void * QDECL Sys_LoadDll( const char *name, char *fqpath , intptr_t (QDECL **ent
}
#endif
dllEntry = ( void (QDECL *)( int (QDECL *)( int, ... ) ) )GetProcAddress( libHandle, "dllEntry" );
dllEntry = ( void (QDECL *)( intptr_t (QDECL *)( intptr_t, ... ) ) )GetProcAddress( libHandle, "dllEntry" );
*entryPoint = (intptr_t (QDECL *)(int,...))GetProcAddress( libHandle, "vmMain" );
if ( !*entryPoint || !dllEntry ) {
FreeLibrary( libHandle );