aboutsummaryrefslogtreecommitdiffstats
path: root/code
diff options
context:
space:
mode:
Diffstat (limited to 'code')
-rw-r--r--code/qcommon/vm_x86_64.c62
1 files changed, 36 insertions, 26 deletions
diff --git a/code/qcommon/vm_x86_64.c b/code/qcommon/vm_x86_64.c
index 1db478f..128ddfa 100644
--- a/code/qcommon/vm_x86_64.c
+++ b/code/qcommon/vm_x86_64.c
@@ -42,15 +42,19 @@ static FILE* qdasmout;
static void VM_Destroy_Compiled(vm_t* self);
/*
+
+ |=====================|
+ ^ dataMask ^- programStack rdi
+ |
+ +- r8
eax scratch
ebx scratch
ecx scratch (required for shifts)
edx scratch (required for divisions)
- rsi stack pointer
- rdi program frame pointer
- r8 pointer to begin of real stack memory
- r9 return address to real program
+ rsi stack pointer (opStack)
+ rdi program frame pointer (programStack)
+ r8 pointer data (vm->dataBase)
r10 start of generated code
*/
@@ -265,6 +269,15 @@ static unsigned char op_argsize[256] =
#if 1
#define RANGECHECK(reg) \
emit("andl $0x%x, %%" #reg, vm->dataMask);
+#elif 0
+#define RANGECHECK(reg) \
+ emit("pushl %%" #reg); \
+ emit("andl $0x%x, %%" #reg, ~vm->dataMask); \
+ emit("jz rangecheck_ok_i_%08x", instruction); \
+ emit("int3"); \
+ emit("rangecheck_ok_i_%08x:", instruction); \
+ emit("popl %%" #reg); \
+ emit("andl $0x%x, %%" #reg, vm->dataMask);
#else
#define RANGECHECK(reg)
#endif
@@ -411,10 +424,17 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
Com_Printf("compiling %s\n", vm->name);
+#ifdef DEBUG_VM
+ snprintf(fn_s, sizeof(fn_s), "%.63s.s", vm->name);
+ snprintf(fn_o, sizeof(fn_o), "%.63s.o", vm->name);
+ fd_s = open(fn_s, O_CREAT|O_WRONLY, 0644);
+ fd_o = open(fn_o, O_CREAT|O_WRONLY, 0644);
+#else
snprintf(fn_s, sizeof(fn_s), "/tmp/%.63s.s_XXXXXX", vm->name);
snprintf(fn_o, sizeof(fn_o), "/tmp/%.63s.o_XXXXXX", vm->name);
fd_s = mkstemp(fn_s);
fd_o = mkstemp(fn_o);
+#endif
if(fd_s == -1 || fd_o == -1)
{
if(fd_s != -1) close(fd_s);
@@ -450,8 +470,6 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("or %%r8, %%r8"); // check whether to set up instruction pointers
emit("jnz main");
emit("jmp setupinstructionpointers");
- emit("exit:");
- emit("jmp *%%r9");
emit("main:");
@@ -501,16 +519,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
break;
case OP_LEAVE:
emit("addl $%d, %%edi", iarg); // get rid of stack frame
- RANGECHECK(edi);
- emit("movl 0(%%r8, %%rdi, 1), %%eax"); // get return address
- emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
- emit("cmp $-1, %%eax");
- emit("je jumptoexit%d", instruction);
- emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
- emit("addq %%r10, %%rax");
- emit("jmp *%%rax");
- emit("jumptoexit%d:", instruction);
- emit("jmp exit");
+ emit("ret");
break;
case OP_CALL:
emit("movl 0(%%rsi), %%eax"); // get instr from stack
@@ -521,7 +530,8 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
emit("addq %%r10, %%rax");
- emit("jmp *%%rax");
+ emit("callq *%%rax");
+ emit("jmp i_%08x", instruction+1);
emit("callSyscall%d:", instruction);
// emit("fnsave 4(%%rsi)");
emit("push %%rsi");
@@ -846,7 +856,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
{
emit("movl $i_%08x-start, %d(%%rax)", instruction, instruction*4);
}
- emit("jmp exit");
+ emit("ret");
emit("debugger:");
if(1);
@@ -882,28 +892,30 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
// call code with r8 set to zero to set up instruction pointers
__asm__ __volatile__ (
" xorq %%r8,%%r8 \r\n" \
- " movq $doneinit,%%r9 \r\n" \
" movq %0,%%r10 \r\n" \
- " jmp *%%r10 \r\n" \
- "doneinit: \r\n" \
+ " callq *%%r10 \r\n" \
:
: "m" (entryPoint)
- : "%r8", "%r9", "%r10", "%rax"
+ : "%r8", "%r10", "%rax"
);
#ifdef DEBUG_VM
fflush(qdasmout);
+ fclose(qdasmout);
#endif
Com_Printf( "VM file %s compiled to %i bytes of code (%p - %p)\n", vm->name, vm->codeLength, vm->codeBase, vm->codeBase+vm->codeLength );
out:
close(fd_o);
+
+#ifndef DEBUG_VM
if(!com_developer->integer)
{
unlink(fn_o);
unlink(fn_s);
}
+#endif
}
@@ -977,16 +989,14 @@ int VM_CallCompiled( vm_t *vm, int *args ) {
__asm__ __volatile__ (
" movq %5,%%rsi \r\n" \
" movl %4,%%edi \r\n" \
- " movq $done,%%r9 \r\n" \
" movq %2,%%r10 \r\n" \
" movq %3,%%r8 \r\n" \
- " jmp *%%r10 \r\n" \
- "done: \r\n" \
+ " callq *%%r10 \r\n" \
" movl %%edi, %0 \r\n" \
" movq %%rsi, %1 \r\n" \
: "=m" (programStack), "=m" (opStack)
: "m" (entryPoint), "m" (vm->dataBase), "m" (programStack), "m" (opStack)
- : "%rsi", "%rdi", "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r15", "%xmm0"
+ : "%rsi", "%rdi", "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r10", "%r15", "%xmm0"
);
if ( opStack != &stack[1] ) {