Skip to content

Commit

Permalink
64bit Windows support (patch by Michael Menegakis)
Browse files Browse the repository at this point in the history
  • Loading branch information
lnussel committed Feb 28, 2010
1 parent 34d616d commit 760f4a1
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 63 deletions.
36 changes: 27 additions & 9 deletions Makefile
Expand Up @@ -460,8 +460,6 @@ ifeq ($(PLATFORM),mingw32)
WINDRES=windres
endif

ARCH=x86

BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \
-DUSE_ICON
CLIENT_CFLAGS =
Expand All @@ -486,12 +484,20 @@ ifeq ($(PLATFORM),mingw32)
CLIENT_CFLAGS += -DUSE_CODEC_VORBIS
endif

OPTIMIZEVM = -O3 -march=i586 -fno-omit-frame-pointer \
-falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \
-fstrength-reduce
OPTIMIZE = $(OPTIMIZEVM) -ffast-math

HAVE_VM_COMPILED = true
ifeq ($(ARCH),x86_64)
OPTIMIZEVM = -O3 -fno-omit-frame-pointer \
-falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \
-fstrength-reduce
OPTIMIZE = $(OPTIMIZEVM) --fast-math
HAVE_VM_COMPILED = true
endif
ifeq ($(ARCH),x86)
OPTIMIZEVM = -O3 -march=i586 -fno-omit-frame-pointer \
-falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \
-fstrength-reduce
OPTIMIZE = $(OPTIMIZEVM) -ffast-math
HAVE_VM_COMPILED = true
endif

SHLIBEXT=dll
SHLIBCFLAGS=
Expand All @@ -509,7 +515,11 @@ ifeq ($(PLATFORM),mingw32)
ifneq ($(USE_CURL_DLOPEN),1)
ifeq ($(USE_LOCAL_HEADERS),1)
CLIENT_CFLAGS += -DCURL_STATICLIB
CLIENT_LIBS += $(LIBSDIR)/win32/libcurl.a
ifeq ($(ARCH),x86_64)
CLIENT_LIBS += $(LIBSDIR)/win64/libcurl.a
else
CLIENT_LIBS += $(LIBSDIR)/win32/libcurl.a
endif
else
CLIENT_LIBS += $(CURL_LIBS)
endif
Expand All @@ -523,14 +533,22 @@ ifeq ($(PLATFORM),mingw32)
ifeq ($(ARCH),x86)
# build 32bit
BASE_CFLAGS += -m32
else
BASE_CFLAGS += -m64
endif

# libmingw32 must be linked before libSDLmain
CLIENT_LIBS += -lmingw32
ifeq ($(USE_LOCAL_HEADERS),1)
CLIENT_CFLAGS += -I$(SDLHDIR)/include
ifeq ($(ARCH), x86)
CLIENT_LIBS += $(LIBSDIR)/win32/libSDLmain.a \
$(LIBSDIR)/win32/libSDL.dll.a
else
CLIENT_LIBS += $(LIBSDIR)/win64/libSDLmain.a \
$(LIBSDIR)/win64/libSDL.dll.a \
$(LIBSDIR)/win64/libSDL.a
endif
else
CLIENT_CFLAGS += $(SDL_CFLAGS)
CLIENT_LIBS += $(SDL_LIBS)
Expand Down
3 changes: 3 additions & 0 deletions code/jpeg-6b/jinclude.h
Expand Up @@ -14,6 +14,9 @@
* JPEG library. Most applications need only include jpeglib.h.
*/

#ifdef __WIN64__
#include "basetsd.h"
#endif

#ifdef _MSC_VER

Expand Down
2 changes: 2 additions & 0 deletions code/jpeg-6b/jmorecfg.h
Expand Up @@ -158,9 +158,11 @@ typedef short INT16;
/* INT32 must hold at least signed 32-bit values. */

/* MinGW basetsd.h defines INT32 - don't redefine it */
#ifndef __WIN64
#if !(defined __MINGW32__ && defined _BASETSD_H)
typedef long INT32;
#endif
#endif

/* Datatype used for image dimensions. The JPEG standard only supports
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
Expand Down
28 changes: 26 additions & 2 deletions code/qcommon/q_platform.h
Expand Up @@ -72,9 +72,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// for windows fastcall option
#define QDECL

//================================================================= WIN32 ===
//================================================================= WIN64/32 ===

#ifdef _WIN32
#ifdef __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 __WIN32__

#undef QDECL
#define QDECL __cdecl
Expand Down
106 changes: 68 additions & 38 deletions code/qcommon/vm_x86_64.c
Expand Up @@ -23,18 +23,28 @@ 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>
#include <errno.h>
#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
Expand All @@ -44,8 +54,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);
Expand All @@ -71,11 +79,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;

Expand Down Expand Up @@ -231,13 +239,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");

Expand All @@ -249,7 +257,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
Expand Down Expand Up @@ -339,7 +347,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
Expand All @@ -363,7 +371,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;

Expand All @@ -378,20 +386,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);
Expand Down Expand Up @@ -430,9 +438,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);
}
Expand Down Expand Up @@ -473,7 +491,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
{
Expand Down Expand Up @@ -517,7 +535,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;
Expand Down Expand Up @@ -558,7 +576,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
// 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");
Expand Down Expand Up @@ -725,7 +743,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
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
Expand All @@ -742,7 +760,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
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 %%r10");
emit("pop %%r9");
Expand Down Expand Up @@ -909,15 +927,25 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
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;

Expand All @@ -934,17 +962,19 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
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
}


Expand Down Expand Up @@ -1034,7 +1064,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" );
Expand Down

0 comments on commit 760f4a1

Please sign in to comment.