diff options
Diffstat (limited to 'code')
| -rw-r--r-- | code/qcommon/vm_x86_64.c | 62 | 
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] ) { | 
