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);
/*
|=====================|
^ 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] ) {