diff --git a/code/qcommon/vm_x86_64.c b/code/qcommon/vm_x86_64.c index 1db478f7..128ddfa0 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] ) {