summaryrefslogtreecommitdiff
path: root/src/qcommon
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2011-01-24 22:07:34 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:17:54 +0000
commitf96ae257eab6fae9b4b4f4409c58dbce6915ac35 (patch)
treec9828a3c3726d4b260493a710fd1f2f9f7bc6056 /src/qcommon
parenta0101a6294268ef392b3fa4ecad12706e6cf4cf3 (diff)
* Merge ioq3-r1813
Diffstat (limited to 'src/qcommon')
-rw-r--r--src/qcommon/common.c20
-rw-r--r--src/qcommon/msg.c8
-rw-r--r--src/qcommon/net_ip.c73
-rw-r--r--src/qcommon/q_platform.h33
-rw-r--r--src/qcommon/q_shared.h2
-rw-r--r--src/qcommon/qcommon.h26
-rw-r--r--src/qcommon/vm_interpreted.c24
-rw-r--r--src/qcommon/vm_x86.c2
-rw-r--r--src/qcommon/vm_x86_64.c113
-rw-r--r--src/qcommon/vm_x86_64_assembler.c30
10 files changed, 221 insertions, 110 deletions
diff --git a/src/qcommon/common.c b/src/qcommon/common.c
index d9fb4495..38902e92 100644
--- a/src/qcommon/common.c
+++ b/src/qcommon/common.c
@@ -82,6 +82,7 @@ cvar_t *com_unfocused;
cvar_t *com_maxfpsUnfocused;
cvar_t *com_minimized;
cvar_t *com_maxfpsMinimized;
+cvar_t *com_abnormalExit;
// com_speeds times
int time_game;
@@ -238,7 +239,7 @@ void QDECL Com_DPrintf( const char *fmt, ...) {
Com_Error
Both client and server can use this, and it will
-do the apropriate things.
+do the appropriate thing.
=============
*/
void QDECL Com_Error( int code, const char *fmt, ... ) {
@@ -323,7 +324,7 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
com_errorEntered = qfalse;
longjmp (abortframe, -1);
} else {
- CL_Shutdown ();
+ CL_Shutdown (va("Client fatal crashed: %s", com_errorMessage));
SV_Shutdown (va("Server fatal crashed: %s", com_errorMessage));
}
@@ -347,7 +348,7 @@ void Com_Quit_f( void ) {
char *p = Cmd_Args( );
if ( !com_errorEntered ) {
SV_Shutdown (p[0] ? p : "Server quit");
- CL_Shutdown ();
+ CL_Shutdown (p[0] ? p : "Client quit");
Com_Shutdown ();
FS_Shutdown(qtrue);
}
@@ -2616,12 +2617,25 @@ void Com_Init( char *commandLine ) {
com_maxfpsUnfocused = Cvar_Get( "com_maxfpsUnfocused", "0", CVAR_ARCHIVE );
com_minimized = Cvar_Get( "com_minimized", "0", CVAR_ROM );
com_maxfpsMinimized = Cvar_Get( "com_maxfpsMinimized", "0", CVAR_ARCHIVE );
+ com_abnormalExit = Cvar_Get( "com_abnormalExit", "0", CVAR_ROM );
s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ );
com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO );
Sys_Init();
+ if( Sys_WritePIDFile( ) ) {
+#ifndef DEDICATED
+ const char *message = "The last time " CLIENT_WINDOW_TITLE " ran, "
+ "it didn't exit properly. This may be due to inappropriate video "
+ "settings. Would you like to start with \"safe\" video settings?";
+
+ if( Sys_Dialog( DT_YES_NO, message, "Abnormal Exit" ) == DR_YES ) {
+ Cvar_Set( "com_abnormalExit", "1" );
+ }
+#endif
+ }
+
// Pick a random port value
Com_RandomBytes( (byte*)&qport, sizeof(int) );
Netchan_Init( qport & 0xffff );
diff --git a/src/qcommon/msg.c b/src/qcommon/msg.c
index c85360c4..ba956bc8 100644
--- a/src/qcommon/msg.c
+++ b/src/qcommon/msg.c
@@ -1033,6 +1033,10 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to,
numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);
lc = MSG_ReadByte(msg);
+ if ( lc > numFields || lc < 0 ) {
+ Com_Error( ERR_DROP, "invalid entityState field count" );
+ }
+
// shownet 2/3 will interleave with other printed info, -1 will
// just print the delta records`
if ( cl_shownet->integer >= 2 || cl_shownet->integer == -1 ) {
@@ -1352,6 +1356,10 @@ void MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *t
numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
lc = MSG_ReadByte(msg);
+ if ( lc > numFields || lc < 0 ) {
+ Com_Error( ERR_DROP, "invalid playerState field count" );
+ }
+
for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) {
fromF = (int *)( (byte *)from + field->offset );
toF = (int *)( (byte *)to + field->offset );
diff --git a/src/qcommon/net_ip.c b/src/qcommon/net_ip.c
index 2be40a86..c1e527c5 100644
--- a/src/qcommon/net_ip.c
+++ b/src/qcommon/net_ip.c
@@ -310,11 +310,11 @@ static qboolean Sys_StringToSockaddr(const char *s, struct sockaddr *sadr, int s
if(search)
{
- if(res->ai_addrlen > sadr_len)
- res->ai_addrlen = sadr_len;
+ if(search->ai_addrlen > sadr_len)
+ search->ai_addrlen = sadr_len;
- memcpy(sadr, res->ai_addr, res->ai_addrlen);
- freeaddrinfo(res);
+ memcpy(sadr, search->ai_addr, search->ai_addrlen);
+ freeaddrinfo(search);
return qtrue;
}
@@ -853,9 +853,6 @@ int NET_IPSocket( char *net_interface, int port, int *err ) {
// make it broadcast capable
if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof(i) ) == SOCKET_ERROR ) {
Com_Printf( "WARNING: NET_IPSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
-
- // it is not that bad if this one fails.
-// return newsocket;
}
if( !net_interface || !net_interface[0]) {
@@ -1035,28 +1032,28 @@ void NET_JoinMulticast6(void)
if(curgroup.ipv6mr_interface)
{
if (setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
- (char *) &curgroup.ipv6mr_interface, sizeof(curgroup.ipv6mr_interface)) < 0)
+ (char *) &curgroup.ipv6mr_interface, sizeof(curgroup.ipv6mr_interface)) < 0)
{
- Com_Printf("NET_JoinMulticast6: Couldn't set scope on multicast socket: %s\n", NET_ErrorString());
+ Com_Printf("NET_JoinMulticast6: Couldn't set scope on multicast socket: %s\n", NET_ErrorString());
- if(multicast6_socket != ip6_socket)
- {
- closesocket(multicast6_socket);
- multicast6_socket = INVALID_SOCKET;
- return;
+ if(multicast6_socket != ip6_socket)
+ {
+ closesocket(multicast6_socket);
+ multicast6_socket = INVALID_SOCKET;
+ return;
}
}
- }
-
- if (setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &curgroup, sizeof(curgroup)))
- {
- Com_Printf("NET_JoinMulticast6: Couldn't join multicast group: %s\n", NET_ErrorString());
-
- if(multicast6_socket != ip6_socket)
- {
- closesocket(multicast6_socket);
- multicast6_socket = INVALID_SOCKET;
- return;
+ }
+
+ if (setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &curgroup, sizeof(curgroup)))
+ {
+ Com_Printf("NET_JoinMulticast6: Couldn't join multicast group: %s\n", NET_ErrorString());
+
+ if(multicast6_socket != ip6_socket)
+ {
+ closesocket(multicast6_socket);
+ multicast6_socket = INVALID_SOCKET;
+ return;
}
}
}
@@ -1253,10 +1250,10 @@ void NET_OpenSocks( int port ) {
/*
=====================
-NET_GetLocalAddress
+NET_AddLocalAddress
=====================
*/
-void NET_AddLocalAddress(char *ifname, struct sockaddr *addr, struct sockaddr *netmask)
+static void NET_AddLocalAddress(char *ifname, struct sockaddr *addr, struct sockaddr *netmask)
{
int addrlen;
sa_family_t family;
@@ -1294,7 +1291,7 @@ void NET_AddLocalAddress(char *ifname, struct sockaddr *addr, struct sockaddr *n
}
#if defined(__linux__) || defined(MACOSX) || defined(__BSD__)
-void NET_GetLocalAddress(void)
+static void NET_GetLocalAddress(void)
{
struct ifaddrs *ifap, *search;
@@ -1315,10 +1312,10 @@ void NET_GetLocalAddress(void)
}
}
#else
-void NET_GetLocalAddress( void ) {
+static void NET_GetLocalAddress( void ) {
char hostname[256];
- struct addrinfo hint;
- struct addrinfo *res = NULL;
+ struct addrinfo hint;
+ struct addrinfo *res = NULL;
if(gethostname( hostname, 256 ) == SOCKET_ERROR)
return;
@@ -1334,7 +1331,7 @@ void NET_GetLocalAddress( void ) {
{
struct sockaddr_in mask4;
struct sockaddr_in6 mask6;
- struct addrinfo *search;
+ struct addrinfo *search;
/* On operating systems where it's more difficult to find out the configured interfaces, we'll just assume a
* netmask with all bits set. */
@@ -1476,27 +1473,27 @@ static qboolean NET_GetCvars( void ) {
#else
net_mcast6iface = Cvar_Get( "net_mcast6iface", "", CVAR_LATCH | CVAR_ARCHIVE );
#endif
- modified += net_mcast6iface->modified;
+ modified += net_mcast6iface->modified;
net_mcast6iface->modified = qfalse;
net_socksEnabled = Cvar_Get( "net_socksEnabled", "0", CVAR_LATCH | CVAR_ARCHIVE );
- modified += net_socksEnabled->modified;
+ modified += net_socksEnabled->modified;
net_socksEnabled->modified = qfalse;
net_socksServer = Cvar_Get( "net_socksServer", "", CVAR_LATCH | CVAR_ARCHIVE );
- modified += net_socksServer->modified;
+ modified += net_socksServer->modified;
net_socksServer->modified = qfalse;
net_socksPort = Cvar_Get( "net_socksPort", "1080", CVAR_LATCH | CVAR_ARCHIVE );
- modified += net_socksPort->modified;
+ modified += net_socksPort->modified;
net_socksPort->modified = qfalse;
net_socksUsername = Cvar_Get( "net_socksUsername", "", CVAR_LATCH | CVAR_ARCHIVE );
- modified += net_socksUsername->modified;
+ modified += net_socksUsername->modified;
net_socksUsername->modified = qfalse;
net_socksPassword = Cvar_Get( "net_socksPassword", "", CVAR_LATCH | CVAR_ARCHIVE );
- modified += net_socksPassword->modified;
+ modified += net_socksPassword->modified;
net_socksPassword->modified = qfalse;
return modified ? qtrue : qfalse;
diff --git a/src/qcommon/q_platform.h b/src/qcommon/q_platform.h
index 9405e749..4d4d2856 100644
--- a/src/qcommon/q_platform.h
+++ b/src/qcommon/q_platform.h
@@ -73,9 +73,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// for windows fastcall option
#define QDECL
-//================================================================= WIN32 ===
+//================================================================= WIN64/32 ===
-#ifdef _WIN32
+#if defined(_WIN64) || defined(__WIN64__)
+
+#undef QDECL
+#define QDECL __cdecl
+
+#if defined( _MSC_VER )
+#define OS_STRING "win_msvc64"
+#elif defined __MINGW64__
+#define OS_STRING "win_mingw64"
+#endif
+
+#define ID_INLINE inline
+#define PATH_SEP '\\'
+
+#if defined( __WIN64__ )
+#define ARCH_STRING "x86_64"
+#elif defined _M_ALPHA
+#define ARCH_STRING "AXP"
+#endif
+
+#define Q3_LITTLE_ENDIAN
+
+#define DLL_EXT ".dll"
+
+#elif defined(_WIN32) || defined(__WIN32__)
#undef QDECL
#define QDECL __cdecl
@@ -120,6 +144,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#elif defined __i386__
#define ARCH_STRING "x86"
#define Q3_LITTLE_ENDIAN
+#elif defined __x86_64__
+#define ARCH_STRING "x86_64"
+#define Q3_LITTLE_ENDIAN
#endif
#define DLL_EXT ".dylib"
@@ -201,7 +228,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifdef __i386__
#define ARCH_STRING "x86"
#elif defined __amd64__
-#define ARCH_STRING "x86_64"
+#define ARCH_STRING "amd64"
#elif defined __axp__
#define ARCH_STRING "alpha"
#endif
diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h
index 44685582..3f2cb9d5 100644
--- a/src/qcommon/q_shared.h
+++ b/src/qcommon/q_shared.h
@@ -184,6 +184,8 @@ typedef int clipHandle_t;
#define MAX_QINT 0x7fffffff
#define MIN_QINT (-MAX_QINT-1)
+#define ARRAY_LEN(x) (sizeof(x) / sizeof(*x))
+
// angle indexes
#define PITCH 0 // up / down
diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h
index 18f4c5e5..09132159 100644
--- a/src/qcommon/qcommon.h
+++ b/src/qcommon/qcommon.h
@@ -179,7 +179,7 @@ qboolean NET_CompareBaseAdrMask(netadr_t a, netadr_t b, int netmask);
qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b);
qboolean NET_IsLocalAddress (netadr_t adr);
const char *NET_AdrToString (netadr_t a);
-const char *NET_AdrToStringwPort (netadr_t a);
+const char *NET_AdrToStringwPort (netadr_t a);
int NET_StringToAdr ( const char *s, netadr_t *a, netadrtype_t family);
qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, msg_t *net_message);
void NET_JoinMulticast6(void);
@@ -923,7 +923,7 @@ void CL_InitKeyCommands( void );
void CL_Init( void );
void CL_Disconnect( qboolean showMainMenu );
-void CL_Shutdown( void );
+void CL_Shutdown( char *finalmsg );
void CL_Frame( int msec );
qboolean CL_GameCommand( void );
void CL_KeyEvent (int key, qboolean down, unsigned time);
@@ -1072,6 +1072,7 @@ char *Sys_DefaultAppPath(void);
void Sys_SetDefaultHomePath(const char *path);
char *Sys_DefaultHomePath(void);
+const char *Sys_TempPath(void);
const char *Sys_Dirname( char *path );
const char *Sys_Basename( char *path );
char *Sys_ConsoleInput(void);
@@ -1084,6 +1085,27 @@ qboolean Sys_LowPhysicalMemory( void );
void Sys_SetEnv(const char *name, const char *value);
+typedef enum
+{
+ DR_YES = 0,
+ DR_NO = 1,
+ DR_OK = 0,
+ DR_CANCEL = 1
+} dialogResult_t;
+
+typedef enum
+{
+ DT_INFO,
+ DT_WARNING,
+ DT_ERROR,
+ DT_YES_NO,
+ DT_OK_CANCEL
+} dialogType_t;
+
+dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title );
+
+qboolean Sys_WritePIDFile( void );
+
/* This is based on the Adaptive Huffman algorithm described in Sayood's Data
* Compression book. The ranks are not actually stored, but implicitly defined
* by the location of a node within a doubly-linked list */
diff --git a/src/qcommon/vm_interpreted.c b/src/qcommon/vm_interpreted.c
index 53357f5d..2b9ffea6 100644
--- a/src/qcommon/vm_interpreted.c
+++ b/src/qcommon/vm_interpreted.c
@@ -517,18 +517,20 @@ nextInstruction2:
//VM_LogSyscalls( (int *)&image[ programStack + 4 ] );
{
- intptr_t* argptr = (intptr_t *)&image[ programStack + 4 ];
- #if __WORDSIZE == 64
- // the vm has ints on the stack, we expect
- // longs so we have to convert it
- intptr_t argarr[16];
- int i;
- for (i = 0; i < 16; ++i) {
- argarr[i] = *(int*)&image[ programStack + 4 + 4*i ];
+ // the vm has ints on the stack, we expect
+ // pointers so we might have to convert it
+ if (sizeof(intptr_t) != sizeof(int)) {
+ intptr_t argarr[16];
+ int *imagePtr = (int *)&image[programStack];
+ int i;
+ for (i = 0; i < 16; ++i) {
+ argarr[i] = *(++imagePtr);
+ }
+ r = vm->systemCall( argarr );
+ } else {
+ intptr_t* argptr = (intptr_t *)&image[ programStack + 4 ];
+ r = vm->systemCall( argptr );
}
- argptr = argarr;
- #endif
- r = vm->systemCall( argptr );
}
#ifdef DEBUG_VM
diff --git a/src/qcommon/vm_x86.c b/src/qcommon/vm_x86.c
index dc7f5a67..41806f2a 100644
--- a/src/qcommon/vm_x86.c
+++ b/src/qcommon/vm_x86.c
@@ -37,7 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/* need this on NX enabled systems (i386 with PAE kernel or
* noexec32=on x86_64) */
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
#define VM_X86_MMAP
#endif
diff --git a/src/qcommon/vm_x86_64.c b/src/qcommon/vm_x86_64.c
index 93e25f6d..13c39172 100644
--- a/src/qcommon/vm_x86_64.c
+++ b/src/qcommon/vm_x86_64.c
@@ -24,11 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// vm_x86_64.c -- load time compiler and execution environment for x86-64
#include "vm_local.h"
-
-#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/wait.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
@@ -36,6 +33,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <unistd.h>
#include <stdarg.h>
+#include <inttypes.h>
+
+#ifdef __WIN64__
+ #include <windows.h>
+ #define CROSSCALL __attribute__ ((sysv_abi))//fool the vm we're SYSV ABI
+ //#define __USE_MINGW_ANSI_STDIO 1 //very slow - avoid if possible
+#else
+ #include <sys/mman.h>
+ #include <sys/wait.h>
+ #define VM_X86_64_MMAP
+ #define CROSSCALL
+#endif
+
//#define DEBUG_VM
#ifdef DEBUG_VM
@@ -45,8 +55,6 @@ static FILE* qdasmout;
#define Dfprintf(args...)
#endif
-#define VM_X86_64_MMAP
-
void assembler_set_output(char* buf);
size_t assembler_get_code_size(void);
void assembler_init(int pass);
@@ -72,11 +80,11 @@ static void VM_Destroy_Compiled(vm_t* self);
*/
-static long callAsmCall(long callProgramStack, long callSyscallNum)
+static int64_t CROSSCALL callAsmCall(int64_t callProgramStack, int64_t callSyscallNum)
{
vm_t *savedVM;
- long ret = 0x77;
- long args[11];
+ int64_t ret = 0x77;
+ int64_t args[11];
// int iargs[11];
int i;
@@ -232,13 +240,13 @@ void emit(const char* fmt, ...)
#define CHECK_INSTR_REG(reg) \
emit("cmpl $%u, %%"#reg, header->instructionCount); \
emit("jb jmp_ok_i_%08x", instruction); \
- emit("movq $%lu, %%rax", (unsigned long)jmpviolation); \
+ emit("movq $%"PRIu64", %%rax", (uint64_t)jmpviolation); \
emit("callq *%%rax"); \
emit("jmp_ok_i_%08x:", instruction);
#define PREPARE_JMP(reg) \
CHECK_INSTR_REG(reg) \
- emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers); \
+ emit("movq $%"PRIu64", %%rbx", (uint64_t)vm->instructionPointers); \
emit("movl (%%rbx, %%rax, 4), %%eax"); \
emit("addq %%r10, %%rax");
@@ -250,7 +258,7 @@ void emit(const char* fmt, ...)
#define JMPIARG \
CHECK_INSTR(iarg); \
- emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \
+ emit("movq $%"PRIu64", %%rax", vm->codeBase+vm->instructionPointers[iarg]); \
emit("jmpq *%%rax");
#define CONST_OPTIMIZE
@@ -340,7 +348,7 @@ void emit(const char* fmt, ...)
emit("andl $0x%x, %%ecx", vm->dataMask &~(bytes-1)); \
emit("cmpl %%" #reg ", %%ecx"); \
emit("jz rc_ok_i_%08x", instruction); \
- emit("movq $%lu, %%rax", (unsigned long)memviolation); \
+ emit("movq $%"PRIu64", %%rax", (uint64_t)memviolation); \
emit("callq *%%rax"); \
emit("rc_ok_i_%08x:", instruction);
#elif 1
@@ -364,7 +372,7 @@ static void* getentrypoint(vm_t* vm)
return vm->codeBase;
}
-static void block_copy_vm(unsigned dest, unsigned src, unsigned count)
+static void CROSSCALL block_copy_vm(unsigned dest, unsigned src, unsigned count)
{
unsigned dataMask = currentVM->dataMask;
@@ -379,20 +387,20 @@ static void block_copy_vm(unsigned dest, unsigned src, unsigned count)
memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count);
}
-static void eop(void)
+static void CROSSCALL eop(void)
{
Com_Error(ERR_DROP, "end of program reached without return!\n");
exit(1);
}
-static void jmpviolation(void)
+static void CROSSCALL jmpviolation(void)
{
Com_Error(ERR_DROP, "program tried to execute code outside VM\n");
exit(1);
}
#ifdef DEBUG_VM
-static void memviolation(void)
+static void CROSSCALL memviolation(void)
{
Com_Error(ERR_DROP, "program tried to access memory outside VM\n");
exit(1);
@@ -431,9 +439,19 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
{
compiledOfs = assembler_get_code_size();
vm->codeLength = compiledOfs;
- vm->codeBase = mmap(NULL, compiledOfs, PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
- if(vm->codeBase == (void*)-1)
- Com_Error(ERR_DROP, "VM_CompileX86: can't mmap memory");
+
+ #ifdef VM_X86_64_MMAP
+ vm->codeBase = mmap(NULL, compiledOfs, PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+ if(vm->codeBase == (void*)-1)
+ Com_Error(ERR_DROP, "VM_CompileX86: can't mmap memory");
+ #elif __WIN64__
+ // allocate memory with write permissions under windows.
+ vm->codeBase = VirtualAlloc(NULL, compiledOfs, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
+ if(!vm->codeBase)
+ Com_Error(ERR_DROP, "VM_CompileX86: VirtualAlloc failed");
+ #else
+ vm->codeBase = malloc(compiledOfs);
+ #endif
assembler_set_output((char*)vm->codeBase);
}
@@ -474,7 +492,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
else if(op_argsize[op] == 1)
{
barg = code[pc++];
- Dfprintf(qdasmout, "%s %8hhu\n", opnames[op], barg);
+ Dfprintf(qdasmout, "%s %8hu\n", opnames[op], barg);
}
else
{
@@ -518,7 +536,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
goto emit_do_syscall;
CHECK_INSTR(const_value);
- emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[const_value]);
+ emit("movq $%"PRIu64", %%rax", vm->codeBase+vm->instructionPointers[const_value]);
emit("callq *%%rax");
got_const = 0;
break;
@@ -559,7 +577,7 @@ emit_do_syscall:
// first argument already in rdi
emit("movq %%rax, %%rsi"); // second argument in rsi
}
- emit("movq $%lu, %%rax", (unsigned long)callAsmCall);
+ emit("movq $%"PRIu64", %%rax", (uint64_t)callAsmCall);
emit("callq *%%rax");
emit("pop %%rbx");
emit("addq %%rbx, %%rsp");
@@ -726,7 +744,7 @@ emit_do_syscall:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 4(%%rsi), %%eax"); // get value from stack
- emit("movl $0x%hhx, %%ebx", barg);
+ emit("movl $0x%hx, %%ebx", barg);
emit("addl %%edi, %%ebx");
RANGECHECK(ebx, 4);
emit("movl %%eax, 0(%%r8,%%rbx, 1)"); // store in args space
@@ -740,11 +758,18 @@ emit_do_syscall:
emit("push %%r8");
emit("push %%r9");
emit("push %%r10");
+ emit("movq %%rsp, %%rbx"); // we need to align the stack pointer
+ emit("subq $8, %%rbx"); // |
+ emit("andq $127, %%rbx"); // |
+ emit("subq %%rbx, %%rsp"); // <-+
+ emit("push %%rbx");
emit("movl 4(%%rsi), %%edi"); // 1st argument dest
emit("movl 8(%%rsi), %%esi"); // 2nd argument src
emit("movl $%d, %%edx", iarg); // 3rd argument count
- emit("movq $%lu, %%rax", (unsigned long)block_copy_vm);
+ emit("movq $%"PRIu64", %%rax", (uint64_t)block_copy_vm);
emit("callq *%%rax");
+ emit("pop %%rbx");
+ emit("addq %%rbx, %%rsp");
emit("pop %%r10");
emit("pop %%r9");
emit("pop %%r8");
@@ -910,15 +935,25 @@ emit_do_syscall:
Com_Error(ERR_DROP, "leftover const\n");
}
- emit("movq $%lu, %%rax", (unsigned long)eop);
+ emit("movq $%"PRIu64", %%rax", (uint64_t)eop);
emit("callq *%%rax");
} // pass loop
assembler_init(0);
- if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC))
- Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed");
+ #ifdef VM_X86_64_MMAP
+ if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC))
+ Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed");
+ #elif __WIN64__
+ {
+ DWORD oldProtect = 0;
+
+ // remove write permissions; give exec permision
+ if(!VirtualProtect(vm->codeBase, compiledOfs, PAGE_EXECUTE_READ, &oldProtect))
+ Com_Error(ERR_DROP, "VM_CompileX86: VirtualProtect failed");
+ }
+ #endif
vm->destroy = VM_Destroy_Compiled;
@@ -935,17 +970,19 @@ emit_do_syscall:
fclose(qdasmout);
#endif
#endif
-
- if(vm->compiled)
- {
- struct timeval tvdone = {0, 0};
- struct timeval dur = {0, 0};
- Com_Printf( "VM file %s compiled to %i bytes of code (%p - %p)\n", vm->name, vm->codeLength, vm->codeBase, vm->codeBase+vm->codeLength );
- gettimeofday(&tvdone, NULL);
- timersub(&tvdone, &tvstart, &dur);
- Com_Printf( "compilation took %lu.%06lu seconds\n", dur.tv_sec, dur.tv_usec );
- }
+ #ifndef __WIN64__ //timersub and gettimeofday
+ if(vm->compiled)
+ {
+ struct timeval tvdone = {0, 0};
+ struct timeval dur = {0, 0};
+ Com_Printf( "VM file %s compiled to %i bytes of code (%p - %p)\n", vm->name, vm->codeLength, vm->codeBase, vm->codeBase+vm->codeLength );
+
+ gettimeofday(&tvdone, NULL);
+ timersub(&tvdone, &tvstart, &dur);
+ Com_Printf( "compilation took %"PRIu64".%06"PRIu64" seconds\n", dur.tv_sec, dur.tv_usec );
+ }
+ #endif
}
@@ -1035,7 +1072,7 @@ int VM_CallCompiled( vm_t *vm, int *args ) {
);
if ( opStack != &stack[1] ) {
- Com_Error( ERR_DROP, "opStack corrupted in compiled code (offset %ld)\n", (long int) ((void *) &stack[1] - opStack));
+ Com_Error( ERR_DROP, "opStack corrupted in compiled code (offset %"PRId64")\n", (int64_t) ((void *) &stack[1] - opStack));
}
if ( programStack != stackOnEntry - 48 ) {
Com_Error( ERR_DROP, "programStack corrupted in compiled code\n" );
diff --git a/src/qcommon/vm_x86_64_assembler.c b/src/qcommon/vm_x86_64_assembler.c
index 46227e6d..99d2898e 100644
--- a/src/qcommon/vm_x86_64_assembler.c
+++ b/src/qcommon/vm_x86_64_assembler.c
@@ -27,10 +27,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <string.h>
#include <stdarg.h>
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-typedef unsigned long u64;
+#include <inttypes.h>
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
static char* out;
static unsigned compiledOfs;
@@ -79,7 +81,7 @@ static void emit1(unsigned char v)
if(fout)
writecnt = fwrite(&v, 1, 1, fout);
- debug("%02hhx ", v);
+ debug("%02hx ", v);
}
else
{
@@ -284,7 +286,7 @@ static void labelhash_free(void)
min = MIN(min, n);
max = MAX(max, n);
}
- printf("total %u, hsize %lu, zero %u, min %u, max %u\n", t, sizeof(labelhash)/sizeof(labelhash[0]), z, min, max);
+ printf("total %u, hsize %"PRIu64", zero %u, min %u, max %u\n", t, sizeof(labelhash)/sizeof(labelhash[0]), z, min, max);
memset(labelhash, 0, sizeof(labelhash));
}
@@ -310,7 +312,7 @@ static const char* argtype2str(argtype_t t)
static inline int iss8(u64 v)
{
- return (labs(v) <= 0x80);
+ return (llabs(v) <= 0x80); //llabs instead of labs required for __WIN64
}
static inline int isu8(u64 v)
@@ -320,7 +322,7 @@ static inline int isu8(u64 v)
static inline int iss16(u64 v)
{
- return (labs(v) <= 0x8000);
+ return (llabs(v) <= 0x8000);
}
static inline int isu16(u64 v)
@@ -330,7 +332,7 @@ static inline int isu16(u64 v)
static inline int iss32(u64 v)
{
- return (labs(v) <= 0x80000000);
+ return (llabs(v) <= 0x80000000);
}
static inline int isu32(u64 v)
@@ -340,7 +342,7 @@ static inline int isu32(u64 v)
static void emit_opsingle(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
{
- u8 op = (u8)((unsigned long) data);
+ u8 op = (u8)((uint64_t) data);
if(arg1.type != T_NONE || arg2.type != T_NONE)
CRAP_INVALID_ARGS;
@@ -503,7 +505,7 @@ static void maybe_emit_displacement(arg_t* arg)
/* one byte operator with register added to operator */
static void emit_opreg(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
{
- u8 op = (u8)((unsigned long) data);
+ u8 op = (u8)((uint64_t) data);
if(arg1.type != T_REGISTER || arg2.type != T_NONE)
CRAP_INVALID_ARGS;
@@ -756,7 +758,7 @@ static void emit_condjump(const char* mnemonic, arg_t arg1, arg_t arg2, void* da
{
unsigned off;
int disp;
- unsigned char opcode = (unsigned char)(((unsigned long)data)&0xFF);
+ unsigned char opcode = (unsigned char)(((uint64_t)data)&0xFF);
if(arg1.type != T_LABEL || arg2.type != T_NONE)
crap("%s: argument must be label", mnemonic);
@@ -1153,7 +1155,7 @@ static unsigned char nexttok(const char** str, char* label, u64* val)
else if(*s >= '0' && *s <= '9')
{
char* endptr = NULL;
- u64 v = strtol(s, &endptr, 0);
+ u64 v = strtoull(s, &endptr, 0);
if(endptr && (endptr-s == 0))
crap("invalid integer %s", s);
if(val) *val = v;
@@ -1274,7 +1276,7 @@ tok_memory:
}
break;
default:
- crap("invalid token %hhu in %s", *(unsigned char*)s, *str);
+ crap("invalid token %hu in %s", *(unsigned char*)s, *str);
break;
}