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" #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; syscall = syscallptr;
} }

View File

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

View File

@ -757,9 +757,9 @@ static int FloatAsInt( float f ) {
return temp; return temp;
} }
void *VM_ArgPtr( int intValue ); void *VM_ArgPtr( intptr_t intValue );
#define VMA(x) VM_ArgPtr(args[x]) #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 The ui module is making a system call
==================== ====================
*/ */
int CL_UISystemCalls( int *args ) { intptr_t CL_UISystemCalls( intptr_t *args ) {
switch( args[0] ) { switch( args[0] ) {
case UI_ERROR: case UI_ERROR:
Com_Error( ERR_DROP, "%s", VMA(1) ); 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" #error "Do not use in VM build"
#endif #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; 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" #error "Do not use in VM build"
#endif #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; syscall = syscallptr;
} }

View File

@ -310,7 +310,7 @@ typedef enum {
} sharedTraps_t; } sharedTraps_t;
void VM_Init( void ); 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 ); vmInterpret_t interpret );
// module should be bare: "cgame", not "cgame.dll" or "vm/cgame.qvm" // 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_Debug( int level );
void *VM_ArgPtr( int intValue ); void *VM_ArgPtr( intptr_t intValue );
void *VM_ExplicitArgPtr( vm_t *vm, int 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 // 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 // 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, ...), 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_UnloadDll( void *dllHandle );
void Sys_UnloadGame( void ); void Sys_UnloadGame( void );

View File

@ -249,62 +249,19 @@ void VM_LoadSymbols( vm_t *vm ) {
FS_FreeFile( mapfile ); FS_FreeFile( mapfile );
} }
/* intptr_t QDECL VM_DllSyscall( intptr_t arg, ... ) {
============ intptr_t args[MAX_VMSYSCALL_ARGS];
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];
int i; int i;
va_list ap; va_list ap;
args[0] = arg; args[0] = arg;
va_start(ap, arg); va_start(ap, arg);
for (i = 1; i < sizeof (args) / sizeof (args[i]); i++) for (i = 1; i < ARRAY_LEN(args); i++)
args[i] = va_arg(ap, int); args[i] = va_arg(ap, intptr_t);
va_end(ap); va_end(ap);
return currentVM->systemCall( args ); 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 // DLL's can't be restarted in place
if ( vm->dllHandle ) { if ( vm->dllHandle ) {
char name[MAX_QPATH]; char name[MAX_QPATH];
int (*systemCall)( int *parms ); intptr_t (*systemCall)( intptr_t *parms );
systemCall = vm->systemCall; systemCall = vm->systemCall;
Q_strncpyz( name, vm->name, sizeof( name ) ); Q_strncpyz( name, vm->name, sizeof( name ) );
@ -395,7 +352,7 @@ it will attempt to load as a system dll
#define STACK_SIZE 0x20000 #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 ) { vmInterpret_t interpret ) {
vm_t *vm; vm_t *vm;
vmHeader_t *header; vmHeader_t *header;
@ -572,7 +529,7 @@ void VM_Clear(void) {
lastVM = NULL; lastVM = NULL;
} }
void *VM_ArgPtr( int intValue ) { void *VM_ArgPtr( intptr_t intValue ) {
if ( !intValue ) { if ( !intValue ) {
return NULL; 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 ) { if ( !intValue ) {
return NULL; return NULL;
} }
@ -805,7 +762,7 @@ void VM_LogSyscalls( int *args ) {
f = fopen("syscalls.log", "w" ); f = fopen("syscalls.log", "w" );
} }
callnum++; 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] ); args[0], args[1], args[2], args[3], args[4] );
} }

View File

@ -479,7 +479,7 @@ nextInstruction2:
src = (int *)&image[ r0&dataMask ]; src = (int *)&image[ r0&dataMask ];
dest = (int *)&image[ r1&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" ); Com_Error( ERR_DROP, "OP_BLOCK_COPY not dword aligned" );
} }
count >>= 2; count >>= 2;
@ -518,7 +518,16 @@ nextInstruction2:
*(int *)&image[ programStack + 4 ] = -1 - programCounter; *(int *)&image[ programStack + 4 ] = -1 - programCounter;
//VM_LogSyscalls( (int *)&image[ programStack + 4 ] ); //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 #ifdef DEBUG_VM
// this is just our stack frame pointer, only needed // 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 "../game/q_shared.h"
#include "qcommon.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 { typedef enum {
OP_UNDEF, OP_UNDEF,
@ -127,7 +131,7 @@ struct vm_s {
// DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES // DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES
// USED BY THE ASM CODE // USED BY THE ASM CODE
int programStack; // the vm may be recursively entered 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 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]) #define VMA(x) VM_ArgPtr(args[x])
#endif #define VMF(x) (*(float*)&args[x])
#define VMF(x) ((float *)args)[x] intptr_t SV_GameSystemCalls( intptr_t *args ) {
int SV_GameSystemCalls( int *args ) {
switch( args[0] ) { switch( args[0] ) {
case G_PRINT: case G_PRINT:
Com_Printf( "%s", VMA(1) ); 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 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 // 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, ...), 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; static int lastWarning = 0;
HINSTANCE libHandle; HINSTANCE libHandle;
void (QDECL *dllEntry)( int (QDECL *syscallptr)(int, ...) ); void (QDECL *dllEntry)( intptr_t (QDECL *syscallptr)(intptr_t, ...) );
char *basepath; char *basepath;
char *cdpath; char *cdpath;
char *gamedir; char *gamedir;
@ -606,7 +606,7 @@ void * QDECL Sys_LoadDll( const char *name, char *fqpath , intptr_t (QDECL **ent
} }
#endif #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" ); *entryPoint = (intptr_t (QDECL *)(int,...))GetProcAddress( libHandle, "vmMain" );
if ( !*entryPoint || !dllEntry ) { if ( !*entryPoint || !dllEntry ) {
FreeLibrary( libHandle ); FreeLibrary( libHandle );