[quake3-commits] r2003 - in trunk: . code/asm code/qcommon
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Wed Jun 1 11:17:19 EDT 2011
Author: thilo
Date: 2011-06-01 11:17:18 -0400 (Wed, 01 Jun 2011)
New Revision: 2003
Modified:
trunk/Makefile
trunk/README
trunk/code/asm/ftola.s
trunk/code/asm/qasm.h
trunk/code/qcommon/cm_polylib.c
trunk/code/qcommon/q_platform.h
trunk/code/qcommon/vm.c
trunk/code/qcommon/vm_local.h
trunk/code/qcommon/vm_x86.c
trunk/code/qcommon/vm_x86_64.c
Log:
- Add x86_64 support to vm_x86.c
- Fix warning on mingw64
Modified: trunk/Makefile
===================================================================
--- trunk/Makefile 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/Makefile 2011-06-01 15:17:18 UTC (rev 2003)
@@ -163,6 +163,10 @@
DEBUG_CFLAGS=-g -O0
endif
+ifndef USE_OLD_VM64
+USE_OLD_VM64=0
+endif
+
#############################################################################
BD=$(BUILD_DIR)/debug-$(PLATFORM)-$(ARCH)
@@ -1501,14 +1505,12 @@
Q3OBJ += \
$(B)/client/snd_mixa.o \
$(B)/client/matha.o \
- $(B)/client/ftola.o \
$(B)/client/snapvectora.o
endif
ifeq ($(ARCH),x86)
Q3OBJ += \
$(B)/client/snd_mixa.o \
$(B)/client/matha.o \
- $(B)/client/ftola.o \
$(B)/client/snapvectora.o
endif
@@ -1570,19 +1572,47 @@
ifeq ($(HAVE_VM_COMPILED),true)
ifeq ($(ARCH),i386)
- Q3OBJ += $(B)/client/vm_x86.o
+ Q3OBJ += \
+ $(B)/client/vm_x86.o \
+ $(B)/client/ftola.o
endif
ifeq ($(ARCH),x86)
- Q3OBJ += $(B)/client/vm_x86.o
+ Q3OBJ += \
+ $(B)/client/vm_x86.o \
+ $(B)/client/ftola.o
endif
ifeq ($(ARCH),x86_64)
- Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o
+ ifeq ($(USE_OLD_VM64),1)
+ Q3OBJ += \
+ $(B)/client/vm_x86_64.o \
+ $(B)/client/vm_x86_64_assembler.o
+ else
+ Q3OBJ += \
+ $(B)/client/vm_x86.o \
+ $(B)/client/ftola.o
+ endif
endif
ifeq ($(ARCH),amd64)
- Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o
+ ifeq ($(USE_OLD_VM64),1)
+ Q3OBJ += \
+ $(B)/client/vm_x86_64.o \
+ $(B)/client/vm_x86_64_assembler.o
+ else
+ Q3OBJ += \
+ $(B)/client/vm_x86.o \
+ $(B)/client/ftola.o
+ endif
endif
ifeq ($(ARCH),x64)
- Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o
+ ifeq ($(USE_OLD_VM64),1)
+ Q3OBJ += \
+ $(B)/client/vm_x86_64.o \
+ $(B)/client/vm_x86_64_assembler.o
+ else
+ Q3OBJ += \
+ $(B)/client/vm_x86.o \
+ $(B)/client/ftola.o
+ endif
endif
ifeq ($(ARCH),ppc)
Q3OBJ += $(B)/client/vm_powerpc.o $(B)/client/vm_powerpc_asm.o
@@ -1718,13 +1748,11 @@
ifeq ($(ARCH),i386)
Q3DOBJ += \
- $(B)/ded/ftola.o \
$(B)/ded/snapvectora.o \
$(B)/ded/matha.o
endif
ifeq ($(ARCH),x86)
Q3DOBJ += \
- $(B)/ded/ftola.o \
$(B)/ded/snapvectora.o \
$(B)/ded/matha.o
endif
@@ -1741,19 +1769,47 @@
ifeq ($(HAVE_VM_COMPILED),true)
ifeq ($(ARCH),i386)
- Q3DOBJ += $(B)/ded/vm_x86.o
+ Q3DOBJ += \
+ $(B)/ded/vm_x86.o \
+ $(B)/ded/ftola.o
endif
ifeq ($(ARCH),x86)
- Q3DOBJ += $(B)/ded/vm_x86.o
+ Q3DOBJ += \
+ $(B)/ded/vm_x86.o \
+ $(B)/ded/ftola.o
endif
ifeq ($(ARCH),x86_64)
- Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o
+ ifeq ($(USE_OLD_VM64),1)
+ Q3DOBJ += \
+ $(B)/ded/vm_x86_64.o \
+ $(B)/ded/vm_x86_64_assembler.o
+ else
+ Q3DOBJ += \
+ $(B)/ded/vm_x86.o \
+ $(B)/ded/ftola.o
+ endif
endif
ifeq ($(ARCH),amd64)
- Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o
+ ifeq ($(USE_OLD_VM64),1)
+ Q3DOBJ += \
+ $(B)/ded/vm_x86_64.o \
+ $(B)/ded/vm_x86_64_assembler.o
+ else
+ Q3DOBJ += \
+ $(B)/ded/vm_x86.o \
+ $(B)/ded/ftola.o
+ endif
endif
ifeq ($(ARCH),x64)
- Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o
+ ifeq ($(USE_OLD_VM64),1)
+ Q3DOBJ += \
+ $(B)/ded/vm_x86_64.o \
+ $(B)/ded/vm_x86_64_assembler.o
+ else
+ Q3DOBJ += \
+ $(B)/ded/vm_x86.o \
+ $(B)/ded/ftola.o
+ endif
endif
ifeq ($(ARCH),ppc)
Q3DOBJ += $(B)/ded/vm_powerpc.o $(B)/ded/vm_powerpc_asm.o
Modified: trunk/README
===================================================================
--- trunk/README 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/README 2011-06-01 15:17:18 UTC (rev 2003)
@@ -95,6 +95,8 @@
USE_VOIP - enable built-in VoIP support
USE_INTERNAL_SPEEX - build internal speex library instead of dynamically
linking against system libspeex
+ USE_OLD_VM64 - use Ludwig Nussel's old JIT compiler implementation
+ for x86_64
USE_INTERNAL_ZLIB - build and link against internal zlib
USE_INTERNAL_JPEG - build and link against internal JPEG library
USE_LOCAL_HEADERS - use headers local to ioq3 instead of system ones
Modified: trunk/code/asm/ftola.s
===================================================================
--- trunk/code/asm/ftola.s 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/code/asm/ftola.s 2011-06-01 15:17:18 UTC (rev 2003)
@@ -29,8 +29,6 @@
#include "qasm.h"
-#if id386
-
.data
temp: .single 0.0
@@ -157,4 +155,3 @@
fldcw fpucw
movl temp,%eax
ret
-#endif
Modified: trunk/code/asm/qasm.h
===================================================================
--- trunk/code/asm/qasm.h 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/code/asm/qasm.h 2011-06-01 15:17:18 UTC (rev 2003)
@@ -28,7 +28,7 @@
.section .note.GNU-stack,"", at progbits
#endif
-#ifdef __ELF__
+#if defined(__ELF__) || defined(__WIN64__)
#define C(label) label
#else
#define C(label) _##label
Modified: trunk/code/qcommon/cm_polylib.c
===================================================================
--- trunk/code/qcommon/cm_polylib.c 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/code/qcommon/cm_polylib.c 2011-06-01 15:17:18 UTC (rev 2003)
@@ -272,11 +272,11 @@
*/
winding_t *CopyWinding (winding_t *w)
{
- unsigned long size;
+ intptr_t size;
winding_t *c;
c = AllocWinding (w->numpoints);
- size = (long)((winding_t *)0)->p[w->numpoints];
+ size = (intptr_t) ((winding_t *)0)->p[w->numpoints];
Com_Memcpy (c, w, size);
return c;
}
Modified: trunk/code/qcommon/q_platform.h
===================================================================
--- trunk/code/qcommon/q_platform.h 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/code/qcommon/q_platform.h 2011-06-01 15:17:18 UTC (rev 2003)
@@ -76,6 +76,8 @@
#if defined(_WIN64) || defined(__WIN64__)
+#define idx64
+
#undef QDECL
#define QDECL __cdecl
@@ -144,6 +146,7 @@
#define ARCH_STRING "i386"
#define Q3_LITTLE_ENDIAN
#elif defined __x86_64__
+#define idx64
#define ARCH_STRING "x86_64"
#define Q3_LITTLE_ENDIAN
#endif
@@ -170,6 +173,7 @@
#if defined __i386__
#define ARCH_STRING "i386"
#elif defined __x86_64__
+#define idx64
#define ARCH_STRING "x86_64"
#elif defined __powerpc64__
#define ARCH_STRING "ppc64"
@@ -232,6 +236,7 @@
#ifdef __i386__
#define ARCH_STRING "i386"
#elif defined __amd64__
+#define idx64
#define ARCH_STRING "amd64"
#elif defined __axp__
#define ARCH_STRING "alpha"
Modified: trunk/code/qcommon/vm.c
===================================================================
--- trunk/code/qcommon/vm.c 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/code/qcommon/vm.c 2011-06-01 15:17:18 UTC (rev 2003)
@@ -575,7 +575,7 @@
// allocate space for the jump targets, which will be filled in by the compile/prep functions
vm->instructionCount = header->instructionCount;
- vm->instructionPointers = Hunk_Alloc( vm->instructionCount*4, h_high );
+ vm->instructionPointers = Hunk_Alloc(vm->instructionCount * sizeof(*vm->instructionPointers), h_high);
// copy or compile the instructions
vm->codeLength = header->codeLength;
Modified: trunk/code/qcommon/vm_local.h
===================================================================
--- trunk/code/qcommon/vm_local.h 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/code/qcommon/vm_local.h 2011-06-01 15:17:18 UTC (rev 2003)
@@ -156,7 +156,7 @@
int entryOfs;
int codeLength;
- int *instructionPointers;
+ intptr_t *instructionPointers;
int instructionCount;
byte *dataBase;
Modified: trunk/code/qcommon/vm_x86.c
===================================================================
--- trunk/code/qcommon/vm_x86.c 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/code/qcommon/vm_x86.c 2011-06-01 15:17:18 UTC (rev 2003)
@@ -22,6 +22,7 @@
// vm_x86.c -- load time compiler and execution environment for x86
#include "vm_local.h"
+
#ifdef _WIN32
#include <windows.h>
#endif
@@ -50,6 +51,9 @@
edx scratch (required for divisions)
esi program stack
edi opStack base
+x86_64:
+ r8 vm->instructionPointers
+ r9 vm->dataBase
*/
@@ -67,7 +71,7 @@
#if defined( FTOL_PTR )
int _ftol( float );
-static int ftolPtr = (int)_ftol;
+static void *ftolPtr = _ftol;
#endif
#else // _MSC_VER
@@ -81,7 +85,7 @@
int qftol0F7F( void );
-static int ftolPtr = (int)qftol0F7F;
+static void *ftolPtr = qftol0F7F;
#endif // FTOL_PTR
#endif
@@ -106,23 +110,14 @@
static ELastCommand LastCommand;
-static void ErrJump( void )
-{
- Com_Error(ERR_DROP, "program tried to execute code outside VM");
- exit(1);
-}
-
-static void (*const errJumpPtr)(void) = ErrJump;
-
-
static inline int iss8(int32_t v)
{
- return (v >= -0x80 && v <= 0x7f);
+ return (SCHAR_MIN <= v && v <= SCHAR_MAX);
}
static inline int isu8(uint32_t v)
{
- return (v <= 0xff);
+ return (v <= UCHAR_MAX);
}
static int NextConstant4(void)
@@ -160,13 +155,28 @@
Emit1((v >> 8) & 255);
}
-static void Emit4( int v ) {
- Emit1( v & 255 );
- Emit1( ( v >> 8 ) & 255 );
- Emit1( ( v >> 16 ) & 255 );
- Emit1( ( v >> 24 ) & 255 );
+
+static void Emit4(int v)
+{
+ Emit1(v & 0xFF);
+ Emit1((v >> 8) & 0xFF);
+ Emit1((v >> 16) & 0xFF);
+ Emit1((v >> 24) & 0xFF);
}
+static void EmitPtr(void *ptr)
+{
+ intptr_t v = (intptr_t) ptr;
+
+ Emit4(v);
+#ifdef idx64
+ Emit1((v >> 32) & 0xFF);
+ Emit1((v >> 40) & 0xFF);
+ Emit1((v >> 48) & 0xFF);
+ Emit1((v >> 56) & 0xFF);
+#endif
+}
+
static int Hex( int c ) {
if ( c >= 'a' && c <= 'f' ) {
return 10 + c - 'a';
@@ -200,7 +210,17 @@
string += 3;
}
}
+static void EmitRexString(byte rex, const char *string)
+{
+#ifdef idx64
+ if(rex)
+ Emit1(rex);
+#endif
+ EmitString(string);
+}
+
+
#define MASK_REG(modrm, mask) \
EmitString("81"); \
EmitString((modrm)); \
@@ -372,6 +392,17 @@
#define SET_JMPOFS(x) do { buf[(x)] = compiledOfs - ((x) + 1); } while(0)
+static void ErrJump(void)
+{
+ Com_Error(ERR_DROP, "program tried to execute code outside VM");
+ exit(1);
+}
+
+#define ERRJUMP() \
+ EmitRexString(0x48, "B8"); \
+ EmitPtr(ErrJump); \
+ EmitRexString(0x48, "FF D0")
+
/*
=================
DoBlockCopy
@@ -404,12 +435,11 @@
static void DoSyscall(void)
{
vm_t *savedVM;
- int *data;
- intptr_t syscallNum;
- intptr_t programStack;
- intptr_t *opStackBase;
- intptr_t opStackOfs;
+ int syscallNum;
+ int programStack;
+ int *opStackBase;
+ int opStackOfs;
intptr_t arg;
#ifdef _MSC_VER
@@ -426,21 +456,34 @@
""
: "=a" (syscallNum), "=S" (programStack), "=D" (opStackBase), "=b" (opStackOfs),
"=c" (arg)
- :
- : "memory"
);
#endif
if(syscallNum < 0)
{
+ int *data;
+#ifdef idx64
+ int index;
+ intptr_t args[11];
+#endif
+
// save currentVM so as to allow for recursive VM entry
savedVM = currentVM;
data = (int *) (savedVM->dataBase + programStack + 4);
// modify VM stack pointer for recursive VM entry
savedVM->programStack = programStack - 4;
- *data = ~syscallNum;
+
+#ifdef idx64
+ args[0] = ~syscallNum;
+ for(index = 1; index < ARRAY_LEN(args); index++)
+ args[index] = data[index];
+
+ opStackBase[opStackOfs + 1] = savedVM->systemCall(args);
+#else
+ data[0] = ~syscallNum;
opStackBase[opStackOfs + 1] = savedVM->systemCall(data);
+#endif
currentVM = savedVM;
}
@@ -471,22 +514,42 @@
int EmitCallDoSyscall(vm_t *vm)
{
// use edx register to store DoSyscall address
- EmitString("BA"); // mov edx, DoSyscall
- Emit4((intptr_t) DoSyscall);
+ EmitRexString(0x48, "BA"); // mov edx, DoSyscall
+ EmitPtr(DoSyscall);
+ // Push important registers to stack as we can't really make
+ // any assumptions about calling conventions.
+ EmitString("51"); // push ebx
+ EmitString("56"); // push esi
+ EmitString("57"); // push edi
+#ifdef idx64
+ EmitRexString(0x41, "50"); // push r8
+ EmitRexString(0x41, "51"); // push r9
+#endif
+
// align the stack pointer to a 16-byte-boundary
- EmitString("55"); // push ebp
- EmitString("89 E5"); // mov ebp, esp
- EmitString("83 E4 F0"); // and esp, 0xFFFFFFF0
+ EmitString("55"); // push ebp
+ EmitRexString(0x48, "89 E5"); // mov ebp, esp
+ EmitRexString(0x48, "83 E4 F0"); // and esp, 0xFFFFFFF0
// call the syscall wrapper function
- EmitString("FF D2"); // call edx
+ EmitString("FF D2"); // call edx
+
// reset the stack pointer to its previous value
- EmitString("89 EC"); // mov esp, ebp
- EmitString("5D"); // pop ebp
- EmitString("C3"); // ret
+ EmitRexString(0x48, "89 EC"); // mov esp, ebp
+ EmitString("5D"); // pop ebp
+#ifdef idx64
+ EmitRexString(0x41, "59"); // pop r9
+ EmitRexString(0x41, "58"); // pop r8
+#endif
+ EmitString("5F"); // pop edi
+ EmitString("5E"); // pop esi
+ EmitString("59"); // pop ebx
+
+ EmitString("C3"); // ret
+
return compiledOfs;
}
@@ -531,17 +594,19 @@
// Error jump if invalid jump target
EmitString("73"); // jae badAddr
jmpBadAddr = compiledOfs++;
-
- EmitString("FF 14 85"); // call dword ptr [vm->instructionPointers + eax * 4]
+
+#ifdef idx64
+ EmitRexString(0x49, "FF 14 C0"); // call qword ptr [r8 + eax * 8]
+#else
+ EmitString("FF 14 85"); // call dword ptr [vm->instructionPointers + eax * 4]
Emit4((intptr_t) vm->instructionPointers);
- EmitString("8B 04 9F"); // mov eax, dword ptr [edi + ebx * 4]
- EmitString("C3"); // ret
+#endif
+ EmitString("8B 04 9F"); // mov eax, dword ptr [edi + ebx * 4]
+ EmitString("C3"); // ret
// badAddr:
SET_JMPOFS(jmpBadAddr);
- EmitString("B8"); // mov eax, ErrJump
- Emit4((intptr_t) ErrJump);
- EmitString("FF D0"); // call eax
+ ERRJUMP();
/************ System Call ************/
@@ -686,9 +751,14 @@
case OP_LOAD4:
EmitPushStack(vm);
+#ifdef idx64
+ EmitRexString(0x41, "8B 81"); // mov eax, dword ptr [r9 + 0x12345678]
+ Emit4(Constant4() & vm->dataMask);
+#else
EmitString("B8"); // mov eax, 0x12345678
- Emit4((Constant4() & vm->dataMask) + (intptr_t) vm->dataBase);
+ EmitPtr(vm->dataBase + (Constant4() & vm->dataMask));
EmitString("8B 00"); // mov eax, dword ptr [eax]
+#endif
EmitCommand(LAST_COMMAND_MOV_STACK_EAX); // mov dword ptr [edi + ebx * 4], eax
pc++; // OP_LOAD4
@@ -697,9 +767,14 @@
case OP_LOAD2:
EmitPushStack(vm);
+#ifdef idx64
+ EmitRexString(0x41, "0F B7 81"); // movzx eax, word ptr [r9 + 0x12345678]
+ Emit4(Constant4() & vm->dataMask);
+#else
EmitString("B8"); // mov eax, 0x12345678
- Emit4((Constant4() & vm->dataMask) + (intptr_t) vm->dataBase);
+ EmitPtr(vm->dataBase + (Constant4() & vm->dataMask));
EmitString("0F B7 00"); // movzx eax, word ptr [eax]
+#endif
EmitCommand(LAST_COMMAND_MOV_STACK_EAX); // mov dword ptr [edi + ebx * 4], eax
pc++; // OP_LOAD2
@@ -708,9 +783,14 @@
case OP_LOAD1:
EmitPushStack(vm);
+#ifdef idx64
+ EmitRexString(0x41, "0F B6 81"); // movzx eax, byte ptr [r9 + 0x12345678]
+ Emit4(Constant4() & vm->dataMask);
+#else
EmitString("B8"); // mov eax, 0x12345678
- Emit4((Constant4() & vm->dataMask) + (intptr_t) vm->dataBase);
+ EmitPtr(vm->dataBase + (Constant4() & vm->dataMask));
EmitString("0F B6 00"); // movzx eax, byte ptr [eax]
+#endif
EmitCommand(LAST_COMMAND_MOV_STACK_EAX); // mov dword ptr [edi + ebx * 4], eax
pc++; // OP_LOAD1
@@ -719,9 +799,14 @@
case OP_STORE4:
EmitMovEAXStack(vm, (vm->dataMask & ~3));
+#ifdef idx64
+ EmitRexString(0x41, "C7 04 01"); // mov dword ptr [r9 + eax], 0x12345678
+ Emit4(Constant4());
+#else
EmitString("C7 80"); // mov dword ptr [eax + 0x12345678], 0x12345678
Emit4((intptr_t) vm->dataBase);
Emit4(Constant4());
+#endif
EmitCommand(LAST_COMMAND_SUB_BL_1); // sub bl, 1
pc++; // OP_STORE4
instruction += 1;
@@ -729,9 +814,15 @@
case OP_STORE2:
EmitMovEAXStack(vm, (vm->dataMask & ~1));
+#ifdef idx64
+ Emit1(0x66); // mov word ptr [r9 + eax], 0x1234
+ EmitRexString(0x41, "C7 04 01");
+ Emit2(Constant4());
+#else
EmitString("66 C7 80"); // mov word ptr [eax + 0x12345678], 0x1234
Emit4((intptr_t) vm->dataBase);
Emit2(Constant4());
+#endif
EmitCommand(LAST_COMMAND_SUB_BL_1); // sub bl, 1
pc++; // OP_STORE2
@@ -740,12 +831,17 @@
case OP_STORE1:
EmitMovEAXStack(vm, vm->dataMask);
+#ifdef idx64
+ EmitRexString(0x41, "C6 04 01"); // mov byte [r9 + eax], 0x12
+ Emit1(Constant4());
+#else
EmitString("C6 80"); // mov byte ptr [eax + 0x12345678], 0x12
Emit4((intptr_t) vm->dataBase);
Emit1(Constant4());
+#endif
EmitCommand(LAST_COMMAND_SUB_BL_1); // sub bl, 1
- pc++; // OP_STORE4
+ pc++; // OP_STORE1
instruction += 1;
return qtrue;
@@ -1092,8 +1188,12 @@
EmitString("81 C2"); // add edx, 0x12345678
Emit4((Constant1() & 0xFF));
MASK_REG("E2", vm->dataMask); // and edx, 0x12345678
+#ifdef idx64
+ EmitRexString(0x41, "89 04 11"); // mov dword ptr [r9 + edx], eax
+#else
EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
Emit4((intptr_t) vm->dataBase);
+#endif
EmitCommand(LAST_COMMAND_SUB_BL_1); // sub bl, 1
break;
case OP_CALL:
@@ -1126,28 +1226,44 @@
EmitMovEDXStack(vm, vm->dataMask);
if(v == 1 && oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
{
- EmitString("FF 82"); // inc dword ptr [edx + 0x12345678]
+#ifdef idx64
+ EmitRexString(0x41, "FF 04 11"); // inc dword ptr [r9 + edx]
+#else
+ EmitString("FF 82"); // inc dword ptr [edx + 0x12345678]
Emit4((intptr_t) vm->dataBase);
+#endif
}
else
{
- EmitString("8B 82"); // mov eax, dword ptr [edx + 0x12345678]
+#ifdef idx64
+ EmitRexString(0x41, "8B 04 11"); // mov eax, dword ptr [r9 + edx]
+#else
+ EmitString("8B 82"); // mov eax, dword ptr [edx + 0x12345678]
Emit4((intptr_t) vm->dataBase);
- EmitString("05"); // add eax, const
+#endif
+ EmitString("05"); // add eax, v
Emit4(v);
if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
{
- EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
+#ifdef idx64
+ EmitRexString(0x41, "89 04 11"); // mov dword ptr [r9 + edx], eax
+#else
+ EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
Emit4((intptr_t) vm->dataBase);
+#endif
}
else
{
EmitCommand(LAST_COMMAND_SUB_BL_1); // sub bl, 1
- EmitString("8B 14 9F"); // mov edx, dword ptr [edi + ebx * 4]
- MASK_REG("E2", vm->dataMask); // and edx, 0x12345678
- EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
+ EmitString("8B 14 9F"); // mov edx, dword ptr [edi + ebx * 4]
+ MASK_REG("E2", vm->dataMask); // and edx, 0x12345678
+#ifdef idx64
+ EmitRexString(0x41, "89 04 11"); // mov dword ptr [r9 + edx], eax
+#else
+ EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
Emit4((intptr_t) vm->dataBase);
+#endif
}
}
@@ -1172,28 +1288,44 @@
EmitMovEDXStack(vm, vm->dataMask);
if(v == 1 && oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
{
- EmitString("FF 8A"); // dec dword ptr [edx + 0x12345678]
+#ifdef idx64
+ EmitRexString(0x41, "FF 0C 11"); // dec dword ptr [r9 + edx]
+#else
+ EmitString("FF 8A"); // dec dword ptr [edx + 0x12345678]
Emit4((intptr_t) vm->dataBase);
+#endif
}
else
{
- EmitString("8B 82"); // mov eax, dword ptr [edx + 0x12345678]
+#ifdef idx64
+ EmitRexString(0x41, "8B 04 11"); // mov eax, dword ptr [r9 + edx]
+#else
+ EmitString("8B 82"); // mov eax, dword ptr [edx + 0x12345678]
Emit4((intptr_t) vm->dataBase);
- EmitString("2D"); // sub eax, const
+#endif
+ EmitString("2D"); // sub eax, v
Emit4(v);
if(oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL)
{
- EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
+#ifdef idx64
+ EmitRexString(0x41, "89 04 11"); // mov dword ptr [r9 + edx], eax
+#else
+ EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
Emit4((intptr_t) vm->dataBase);
+#endif
}
else
{
EmitCommand(LAST_COMMAND_SUB_BL_1); // sub bl, 1
- EmitString("8B 14 9F"); // mov edx, dword ptr [edi + ebx * 4]
- MASK_REG("E2", vm->dataMask); // and edx, 0x12345678
- EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
+ EmitString("8B 14 9F"); // mov edx, dword ptr [edi + ebx * 4]
+ MASK_REG("E2", vm->dataMask); // and edx, 0x12345678
+#ifdef idx64
+ EmitRexString(0x41, "89 04 11"); // mov dword ptr [r9 + edx], eax
+#else
+ EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
Emit4((intptr_t) vm->dataBase);
+#endif
}
}
EmitCommand(LAST_COMMAND_SUB_BL_1); // sub bl, 1
@@ -1207,52 +1339,81 @@
{
compiledOfs -= 3;
vm->instructionPointers[instruction - 1] = compiledOfs;
- MASK_REG("E0", vm->dataMask); // and eax, 0x12345678
- EmitString("8B 80"); // mov eax, dword ptr [eax + 0x1234567]
+ MASK_REG("E0", vm->dataMask); // and eax, 0x12345678
+#ifdef idx64
+ EmitRexString(0x41, "8B 04 01"); // mov eax, dword ptr [r9 + eax]
+#else
+ EmitString("8B 80"); // mov eax, dword ptr [eax + 0x1234567]
Emit4((intptr_t) vm->dataBase);
+#endif
EmitCommand(LAST_COMMAND_MOV_STACK_EAX); // mov dword ptr [edi + ebx * 4], eax
break;
}
EmitMovEAXStack(vm, vm->dataMask);
+#ifdef idx64
+ EmitRexString(0x41, "8B 04 01"); // mov eax, dword ptr [r9 + eax]
+#else
EmitString("8B 80"); // mov eax, dword ptr [eax + 0x12345678]
Emit4((intptr_t) vm->dataBase);
+#endif
EmitCommand(LAST_COMMAND_MOV_STACK_EAX); // mov dword ptr [edi + ebx * 4], eax
break;
case OP_LOAD2:
EmitMovEAXStack(vm, vm->dataMask);
+#ifdef idx64
+ EmitRexString(0x41, "0F B7 04 01"); // movzx eax, word ptr [r9 + eax]
+#else
EmitString("0F B7 80"); // movzx eax, word ptr [eax + 0x12345678]
Emit4((intptr_t) vm->dataBase);
+#endif
EmitCommand(LAST_COMMAND_MOV_STACK_EAX); // mov dword ptr [edi + ebx * 4], eax
break;
case OP_LOAD1:
EmitMovEAXStack(vm, vm->dataMask);
+#ifdef idx64
+ EmitRexString(0x41, "0F B6 04 01"); // movzx eax, byte ptr [r9 + eax]
+#else
EmitString("0F B6 80"); // movzx eax, byte ptr [eax + 0x12345678]
Emit4((intptr_t) vm->dataBase);
+#endif
EmitCommand(LAST_COMMAND_MOV_STACK_EAX); // mov dword ptr [edi + ebx * 4], eax
break;
case OP_STORE4:
EmitMovEAXStack(vm, 0);
EmitString("8B 54 9F FC"); // mov edx, dword ptr -4[edi + ebx * 4]
MASK_REG("E2", vm->dataMask & ~3); // and edx, 0x12345678
+#ifdef idx64
+ EmitRexString(0x41, "89 04 11"); // mov dword ptr [r9 + edx], eax
+#else
EmitString("89 82"); // mov dword ptr [edx + 0x12345678], eax
Emit4((intptr_t) vm->dataBase);
+#endif
EmitCommand(LAST_COMMAND_SUB_BL_2); // sub bl, 2
break;
case OP_STORE2:
EmitMovEAXStack(vm, 0);
EmitString("8B 54 9F FC"); // mov edx, dword ptr -4[edi + ebx * 4]
MASK_REG("E2", vm->dataMask & ~1); // and edx, 0x12345678
+#ifdef idx64
+ Emit1(0x66); // mov word ptr [r9 + edx], eax
+ EmitRexString(0x41, "89 04 11");
+#else
EmitString("66 89 82"); // mov word ptr [edx + 0x12345678], eax
Emit4((intptr_t) vm->dataBase);
+#endif
EmitCommand(LAST_COMMAND_SUB_BL_2); // sub bl, 2
break;
case OP_STORE1:
EmitMovEAXStack(vm, 0);
EmitString("8B 54 9F FC"); // mov edx, dword ptr -4[edi + ebx * 4]
MASK_REG("E2", vm->dataMask); // and edx, 0x12345678
+#ifdef idx64
+ EmitRexString(0x41, "88 04 11"); // mov byte ptr [r9 + edx], eax
+#else
EmitString("88 82"); // mov byte ptr [edx + 0x12345678], eax
Emit4((intptr_t) vm->dataBase);
+#endif
EmitCommand(LAST_COMMAND_SUB_BL_2); // sub bl, 2
break;
@@ -1440,8 +1601,9 @@
#else // FTOL_PTR
// call the library conversion function
EmitString("D9 04 9F"); // fld dword ptr [edi + ebx * 4]
- EmitString("FF 15"); // call ftolPtr
- Emit4( (int)&ftolPtr );
+ EmitRexString(0x48, "BA"); // mov edx, ftolPtr
+ EmitPtr(ftolPtr);
+ EmitRexString(0x48, "FF D2"); // call edx
EmitCommand(LAST_COMMAND_MOV_STACK_EAX); // mov dword ptr [edi + ebx * 4], eax
#endif
break;
@@ -1467,14 +1629,18 @@
case OP_JUMP:
EmitCommand(LAST_COMMAND_SUB_BL_1); // sub bl, 1
- EmitString("8B 44 9F 04"); // mov eax,dword ptr 4[edi + ebx * 4]
+ EmitString("8B 44 9F 04"); // mov eax, dword ptr 4[edi + ebx * 4]
EmitString("81 F8"); // cmp eax, vm->instructionCount
Emit4(vm->instructionCount);
+#ifdef idx64
+ EmitString("73 04"); // jae +4
+ EmitRexString(0x49, "FF 24 C0"); // jmp qword ptr [r8 + eax * 8]
+#else
EmitString("73 07"); // jae +7
EmitString("FF 24 85"); // jmp dword ptr [instructionPointers + eax * 4]
Emit4((intptr_t) vm->instructionPointers);
- EmitString("FF 15"); // call errJumpPtr
- Emit4((intptr_t) &errJumpPtr);
+#endif
+ ERRJUMP();
break;
default:
VMFREE_BUFFERS();
@@ -1526,7 +1692,7 @@
// offset all the instruction pointers for the new location
for ( i = 0 ; i < header->instructionCount ; i++ ) {
- vm->instructionPointers[i] += (int)vm->codeBase;
+ vm->instructionPointers[i] += (intptr_t) vm->codeBase;
}
}
@@ -1551,10 +1717,10 @@
int VM_CallCompiled(vm_t *vm, int *args)
{
- int stack[OPSTACK_SIZE + 3];
+ int stack[OPSTACK_SIZE + 7];
void *entryPoint;
int programCounter;
- int programStack, stackOnEntry;
+ intptr_t programStack, stackOnEntry;
byte *image;
int *opStack, *opStackOnEntry;
int opStackOfs;
@@ -1589,23 +1755,50 @@
// off we go into generated code...
entryPoint = vm->codeBase + vm->entryOfs;
- opStack = opStackOnEntry = PADP(stack, 4);
+ opStack = opStackOnEntry = PADP(stack, 8);
*opStack = 0xDEADBEEF;
opStackOfs = 0;
#ifdef _MSC_VER
__asm
{
+#ifndef idx64
pushad
+#endif
mov esi, programStack
mov edi, opStack
mov ebx, opStackOfs
+#ifdef idx64
+#warning look up calling conventions and push/pop if necessary
+ mov r8, vm->instructionPointers
+ mov r9, vm->dataBase
+#endif
call entryPoint
mov opStackOfs, ebx
mov opStack, edi
mov programStack, esi
+#ifndef idx64
popad
+#endif
}
+#elif defined(idx64)
+ __asm__ volatile(
+ "movq %5, %%rax\r\n"
+ "movq %3, %%r8\r\n"
+ "movq %4, %%r9\r\n"
+ "push %%r15\r\n"
+ "push %%r14\r\n"
+ "push %%r13\r\n"
+ "push %%r12\r\n"
+ "callq *%%rax\r\n"
+ "pop %%r12\r\n"
+ "pop %%r13\r\n"
+ "pop %%r14\r\n"
+ "pop %%r15\r\n"
+ : "+S" (programStack), "+D" (opStack), "+b" (opStackOfs)
+ : "g" (vm->instructionPointers), "g" (vm->dataBase), "g" (entryPoint)
+ : "cc", "memory", "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%xmm0"
+ );
#else
__asm__ volatile(
"calll *%3\r\n"
@@ -1616,7 +1809,9 @@
#endif
if(opStack != opStackOnEntry || opStackOfs != 1 || *opStack != 0xDEADBEEF)
+ {
Com_Error(ERR_DROP, "opStack corrupted in compiled code");
+ }
if(programStack != stackOnEntry - 48)
Com_Error(ERR_DROP, "programStack corrupted in compiled code");
Modified: trunk/code/qcommon/vm_x86_64.c
===================================================================
--- trunk/code/qcommon/vm_x86_64.c 2011-06-01 01:50:19 UTC (rev 2002)
+++ trunk/code/qcommon/vm_x86_64.c 2011-06-01 15:17:18 UTC (rev 2003)
@@ -272,7 +272,7 @@
#define PREPARE_JMP(reg) \
CHECK_INSTR_REG(reg); \
emit("movq $%"PRIu64", %%rsi", (intptr_t)vm->instructionPointers); \
- emit("movl (%%rsi, %%rax, 4), %%eax"); \
+ emit("movl (%%rsi, %%rax, 8), %%eax"); \
emit("addq %%r10, %%rax")
#define CHECK_INSTR(nr) \
More information about the quake3-commits
mailing list