x64: updated system call signatures to accepts and return values of type intptr_t.
This commit is contained in:
parent
d4f7c1b467
commit
c6836b54b2
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) );
|
||||||
|
|
|
||||||
|
|
@ -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) );
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 );
|
||||||
|
|
|
||||||
|
|
@ -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] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 );
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) );
|
||||||
|
|
|
||||||
|
|
@ -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 );
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user