use native stack for vm stack as well, frees one register

This commit is contained in:
Ludwig Nussel 2007-06-25 10:01:40 +00:00
parent 6a5908d444
commit da2f4341c2

View file

@ -42,15 +42,19 @@ static FILE* qdasmout;
static void VM_Destroy_Compiled(vm_t* self); static void VM_Destroy_Compiled(vm_t* self);
/* /*
|=====================|
^ dataMask ^- programStack rdi
|
+- r8
eax scratch eax scratch
ebx scratch ebx scratch
ecx scratch (required for shifts) ecx scratch (required for shifts)
edx scratch (required for divisions) edx scratch (required for divisions)
rsi stack pointer rsi stack pointer (opStack)
rdi program frame pointer rdi program frame pointer (programStack)
r8 pointer to begin of real stack memory r8 pointer data (vm->dataBase)
r9 return address to real program
r10 start of generated code r10 start of generated code
*/ */
@ -265,6 +269,15 @@ static unsigned char op_argsize[256] =
#if 1 #if 1
#define RANGECHECK(reg) \ #define RANGECHECK(reg) \
emit("andl $0x%x, %%" #reg, vm->dataMask); 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 #else
#define RANGECHECK(reg) #define RANGECHECK(reg)
#endif #endif
@ -411,10 +424,17 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
Com_Printf("compiling %s\n", vm->name); 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_s, sizeof(fn_s), "/tmp/%.63s.s_XXXXXX", vm->name);
snprintf(fn_o, sizeof(fn_o), "/tmp/%.63s.o_XXXXXX", vm->name); snprintf(fn_o, sizeof(fn_o), "/tmp/%.63s.o_XXXXXX", vm->name);
fd_s = mkstemp(fn_s); fd_s = mkstemp(fn_s);
fd_o = mkstemp(fn_o); fd_o = mkstemp(fn_o);
#endif
if(fd_s == -1 || fd_o == -1) if(fd_s == -1 || fd_o == -1)
{ {
if(fd_s != -1) close(fd_s); 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("or %%r8, %%r8"); // check whether to set up instruction pointers
emit("jnz main"); emit("jnz main");
emit("jmp setupinstructionpointers"); emit("jmp setupinstructionpointers");
emit("exit:");
emit("jmp *%%r9");
emit("main:"); emit("main:");
@ -501,16 +519,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
break; break;
case OP_LEAVE: case OP_LEAVE:
emit("addl $%d, %%edi", iarg); // get rid of stack frame emit("addl $%d, %%edi", iarg); // get rid of stack frame
RANGECHECK(edi); emit("ret");
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");
break; break;
case OP_CALL: case OP_CALL:
emit("movl 0(%%rsi), %%eax"); // get instr from stack 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("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
emit("addq %%r10, %%rax"); emit("addq %%r10, %%rax");
emit("jmp *%%rax"); emit("callq *%%rax");
emit("jmp i_%08x", instruction+1);
emit("callSyscall%d:", instruction); emit("callSyscall%d:", instruction);
// emit("fnsave 4(%%rsi)"); // emit("fnsave 4(%%rsi)");
emit("push %%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("movl $i_%08x-start, %d(%%rax)", instruction, instruction*4);
} }
emit("jmp exit"); emit("ret");
emit("debugger:"); emit("debugger:");
if(1); 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 // call code with r8 set to zero to set up instruction pointers
__asm__ __volatile__ ( __asm__ __volatile__ (
" xorq %%r8,%%r8 \r\n" \ " xorq %%r8,%%r8 \r\n" \
" movq $doneinit,%%r9 \r\n" \
" movq %0,%%r10 \r\n" \ " movq %0,%%r10 \r\n" \
" jmp *%%r10 \r\n" \ " callq *%%r10 \r\n" \
"doneinit: \r\n" \
: :
: "m" (entryPoint) : "m" (entryPoint)
: "%r8", "%r9", "%r10", "%rax" : "%r8", "%r10", "%rax"
); );
#ifdef DEBUG_VM #ifdef DEBUG_VM
fflush(qdasmout); fflush(qdasmout);
fclose(qdasmout);
#endif #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 ); 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: out:
close(fd_o); close(fd_o);
#ifndef DEBUG_VM
if(!com_developer->integer) if(!com_developer->integer)
{ {
unlink(fn_o); unlink(fn_o);
unlink(fn_s); unlink(fn_s);
} }
#endif
} }
@ -977,16 +989,14 @@ int VM_CallCompiled( vm_t *vm, int *args ) {
__asm__ __volatile__ ( __asm__ __volatile__ (
" movq %5,%%rsi \r\n" \ " movq %5,%%rsi \r\n" \
" movl %4,%%edi \r\n" \ " movl %4,%%edi \r\n" \
" movq $done,%%r9 \r\n" \
" movq %2,%%r10 \r\n" \ " movq %2,%%r10 \r\n" \
" movq %3,%%r8 \r\n" \ " movq %3,%%r8 \r\n" \
" jmp *%%r10 \r\n" \ " callq *%%r10 \r\n" \
"done: \r\n" \
" movl %%edi, %0 \r\n" \ " movl %%edi, %0 \r\n" \
" movq %%rsi, %1 \r\n" \ " movq %%rsi, %1 \r\n" \
: "=m" (programStack), "=m" (opStack) : "=m" (programStack), "=m" (opStack)
: "m" (entryPoint), "m" (vm->dataBase), "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] ) { if ( opStack != &stack[1] ) {