diff options
| author | Thilo Schulz <arny@ats.s.bawue.de> | 2011-05-16 17:55:07 +0000 | 
|---|---|---|
| committer | Tim Angus <tim@ngus.net> | 2013-01-09 22:29:01 +0000 | 
| commit | 24d967c48660c3e98ef6d49b757c5ffb3e22f50c (patch) | |
| tree | 5d6bc2a9967264588b60ab4f4bf31f81894b56f4 /src | |
| parent | a794d38bda1b44bf4232cf6196919eab1321ff60 (diff) | |
- Fix SEGV in while loop getop() after t = b = 0 - Fix iss8, iss16 and iss32 which would not correctly detect 32-bit signed integer range - Add support for "addb", "subb" etc. assembler mnemonic - Change opStack protection for x86_64 VM: No overflow checks necessary anymore as offset register is 1 byte long only
Diffstat (limited to 'src')
| -rw-r--r-- | src/qcommon/vm_x86_64.c | 267 | ||||
| -rw-r--r-- | src/qcommon/vm_x86_64_assembler.c | 118 | 
2 files changed, 189 insertions, 196 deletions
diff --git a/src/qcommon/vm_x86_64.c b/src/qcommon/vm_x86_64.c index e7bb72ac..fcdd4657 100644 --- a/src/qcommon/vm_x86_64.c +++ b/src/qcommon/vm_x86_64.c @@ -72,13 +72,13 @@ static void VM_Destroy_Compiled(vm_t* self);    +- r8    eax	scratch -  ebx	scratch +  bl	opStack offset    ecx	scratch (required for shifts)    edx	scratch (required for divisions) -  rsi	opStack offset +  rsi	scratch    rdi	program frame pointer (programStack)    r8    pointer data (vm->dataBase) -  r9    opStack data base (opStack) +  r9    opStack data base (vm->opStack + OPSTACK_SIZE / 2)    r10   start of generated code  */ @@ -249,33 +249,19 @@ void emit(const char* fmt, ...)  	emit("movq $%"PRIu64", %%rax", (intptr_t) memviolation); \  	emit("callq *%%rax"); \  	emit("rc_ok_i_%08x:", instruction) - -#define OPSTACKCHECK() \ -	emit("movl %%esi, %%ecx"); \ -	emit("andl $0x%x, %%ecx", OPSTACK_MASK & ~0x03); \ -	emit("cmpl %%esi, %%ecx"); \ -	emit("jz oc_ok_i_%08x", instruction); \ -	emit("movq $%"PRIu64", %%rax", (intptr_t) opstackviolation); \ -	emit("callq *%%rax"); \ -	emit("oc_ok_i_%08x:", instruction)  #elif 1  // check is too expensive, so just confine memory access  #define RANGECHECK(reg, bytes) \  	emit("andl $0x%x, %%" #reg, vm->dataMask &~(bytes-1)) - -#define OPSTACKCHECK() \ -	emit("andl $0x%x, %%esi", OPSTACK_MASK & ~0x03)  #else  #define RANGECHECK(reg, bytes)  #endif  #define STACK_PUSH(bytes) \ -	emit("addl $0x%x, %%esi", bytes); \ -	OPSTACKCHECK() +	emit("addb $0x%x, %%bl", bytes); \  #define STACK_POP(bytes) \ -	emit("subl $0x%x, %%esi", bytes); \ -	OPSTACKCHECK() +	emit("subb $0x%x, %%bl", bytes); \  #define CHECK_INSTR_REG(reg) \  	emit("cmpl $%u, %%"#reg, header->instructionCount); \ @@ -286,8 +272,8 @@ void emit(const char* fmt, ...)  #define PREPARE_JMP(reg) \  	CHECK_INSTR_REG(reg); \ -	emit("movq $%"PRIu64", %%rbx", (intptr_t)vm->instructionPointers); \ -	emit("movl (%%rbx, %%rax, 4), %%eax"); \ +	emit("movq $%"PRIu64", %%rsi", (intptr_t)vm->instructionPointers); \ +	emit("movl (%%rsi, %%rax, 4), %%eax"); \  	emit("addq %%r10, %%rax")  #define CHECK_INSTR(nr) \ @@ -310,7 +296,7 @@ void emit(const char* fmt, ...)  		got_const = 0; \  		vm->instructionPointers[instruction-1] = assembler_get_code_size(); \  		STACK_PUSH(4); \ -		emit("movl $%d, 0(%%r9, %%rsi, 1)", const_value); \ +		emit("movl $%d, (%%r9, %%rbx, 1)", const_value); \  	}  #else  #define MAYBE_EMIT_CONST() @@ -320,8 +306,8 @@ void emit(const char* fmt, ...)  #define IJ(op) \  	MAYBE_EMIT_CONST(); \  	STACK_POP(8); \ -	emit("movl 4(%%r9, %%rsi, 1), %%eax"); \ -	emit("cmpl 8(%%r9, %%rsi, 1), %%eax"); \ +	emit("movl 4(%%r9, %%rbx, 1), %%eax"); \ +	emit("cmpl 8(%%r9, %%rbx, 1), %%eax"); \  	emit(op " i_%08x", instruction+1); \  	JMPIARG(); \  	neednilabel = 1 @@ -330,8 +316,8 @@ void emit(const char* fmt, ...)  #define FJ(bits, op) \  	MAYBE_EMIT_CONST(); \  	STACK_POP(8); \ -	emit("flds 4(%%r9, %%rsi, 1)");\ -	emit("fcomps 8(%%r9, %%rsi, 1)");\ +	emit("flds 4(%%r9, %%rbx, 1)");\ +	emit("fcomps 8(%%r9, %%rbx, 1)");\  	emit("fnstsw %%ax");\  	emit("testb $" #bits ", %%ah");\  	emit(op " i_%08x", instruction+1);\ @@ -343,8 +329,8 @@ void emit(const char* fmt, ...)  #define XJ(op) \  	MAYBE_EMIT_CONST(); \  	STACK_POP(8); \ -	emit("movss 4(%%r9, %%rsi, 1), %%xmm0");\ -	emit("ucomiss 8(%%r9, %%rsi, 1), %%xmm0");\ +	emit("movss 4(%%r9, %%rbx, 1), %%xmm0");\ +	emit("ucomiss 8(%%r9, %%rbx, 1), %%xmm0");\  	emit("jp i_%08x", instruction+1);\  	emit(op " i_%08x", instruction+1);\  	JMPIARG(); \ @@ -353,35 +339,35 @@ void emit(const char* fmt, ...)  #define SIMPLE(op) \  	MAYBE_EMIT_CONST(); \ -	emit("movl 0(%%r9, %%rsi, 1), %%eax"); \ +	emit("movl (%%r9, %%rbx, 1), %%eax"); \  	STACK_POP(4); \ -	emit(op " %%eax, 0(%%r9, %%rsi, 1)") +	emit(op " %%eax, (%%r9, %%rbx, 1)")  #ifdef USE_X87  #define FSIMPLE(op) \  	MAYBE_EMIT_CONST(); \  	STACK_POP(4); \ -	emit("flds 0(%%r9, %%rsi, 1)"); \ -	emit(op " 4(%%r9, %%rsi, 1)"); \ -	emit("fstps 0(%%r9, %%rsi, 1)") +	emit("flds (%%r9, %%rbx, 1)"); \ +	emit(op " 4(%%r9, %%rbx, 1)"); \ +	emit("fstps (%%r9, %%rbx, 1)")  #define XSIMPLE(op)  #else  #define FSIMPLE(op)  #define XSIMPLE(op) \  	MAYBE_EMIT_CONST(); \  	STACK_POP(4); \ -	emit("movss 0(%%r9, %%rsi, 1), %%xmm0"); \ -	emit(op " 4(%%r9, %%rsi, 1), %%xmm0"); \ -	emit("movss %%xmm0, 0(%%r9, %%rsi, 1)") +	emit("movss (%%r9, %%rbx, 1), %%xmm0"); \ +	emit(op " 4(%%r9, %%rbx, 1), %%xmm0"); \ +	emit("movss %%xmm0, (%%r9, %%rbx, 1)")  #endif  #define SHIFT(op) \  	MAYBE_EMIT_CONST(); \  	STACK_POP(4); \ -	emit("movl 4(%%r9, %%rsi, 1), %%ecx"); \ -	emit("movl 0(%%r9, %%rsi, 1), %%eax"); \ +	emit("movl 4(%%r9, %%rbx, 1), %%ecx"); \ +	emit("movl (%%r9, %%rbx, 1), %%eax"); \  	emit(op " %%cl, %%eax"); \ -	emit("movl %%eax, 0(%%r9, %%rsi, 1)") +	emit("movl %%eax, (%%r9, %%rbx, 1)")  #ifdef DEBUG_VM  #define NOTIMPL(x) \ @@ -563,7 +549,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  				break;  			case OP_CALL:  				RANGECHECK(edi, 4); -				emit("movl $%d, 0(%%r8, %%rdi, 1)", instruction+1);  // save next instruction +				emit("movl $%d, (%%r8, %%rdi, 1)", instruction+1);  // save next instruction  				if(got_const)  				{ @@ -579,7 +565,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  				else  				{  					MAYBE_EMIT_CONST(); -					emit("movl 0(%%r9, %%rsi, 1), %%eax");  // get instr from stack +					emit("movl (%%r9, %%rbx, 1), %%eax");  // get instr from stack  					STACK_POP(4);  					emit("orl %%eax, %%eax"); @@ -593,16 +579,15 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  				}  //				emit("fnsave 4(%%r9, %%rsi, 1)"); -				emit("push %%rsi");  				emit("push %%rdi");  				emit("push %%r8");  				emit("push %%r9");  				emit("push %%r10"); -				emit("movq %%rsp, %%rbx"); // we need to align the stack pointer -				emit("subq $8, %%rbx");    //   | -				emit("andq $127, %%rbx");  //   | -				emit("subq %%rbx, %%rsp"); // <-+ -				emit("push %%rbx"); +				emit("movq %%rsp, %%rsi"); // we need to align the stack pointer +				emit("subq $8, %%rsi");    //   | +				emit("andq $127, %%rsi");  //   | +				emit("subq %%rsi, %%rsp"); // <-+ +				emit("push %%rsi");  				if(got_const) {  					got_const = 0;  					emit("movq $%u, %%rsi", -1-const_value); // second argument in rsi @@ -613,16 +598,15 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  				}  				emit("movq $%"PRIu64", %%rax", (intptr_t) callAsmCall);  				emit("callq *%%rax"); -				emit("pop %%rbx"); -				emit("addq %%rbx, %%rsp"); +				emit("pop %%rsi"); +				emit("addq %%rsi, %%rsp");  				emit("pop %%r10");  				emit("pop %%r9");  				emit("pop %%r8");  				emit("pop %%rdi"); -				emit("pop %%rsi");  //				emit("frstor 4(%%r9, %%rsi, 1)");  				STACK_PUSH(4); -				emit("movl %%eax, (%%r9, %%rsi, 1)"); // store return value +				emit("movl %%eax, (%%r9, %%rbx, 1)"); // store return value  				neednilabel = 1;  				break;  			case OP_PUSH: @@ -640,15 +624,15 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  				const_value = iarg;  #else  				STACK_PUSH(4); -				emit("movl $%d, 0(%%r9, %%rsi, 1)", iarg); +				emit("movl $%d, (%%r9, %%rbx, 1)", iarg);  #endif  				break;  			case OP_LOCAL:  				MAYBE_EMIT_CONST(); -				emit("movl %%edi, %%ebx"); -				emit("addl $%d,%%ebx", iarg); +				emit("movl %%edi, %%esi"); +				emit("addl $%d,%%esi", iarg);  				STACK_PUSH(4); -				emit("movl %%ebx, 0(%%r9, %%rsi, 1)"); +				emit("movl %%esi, (%%r9, %%rbx, 1)");  				break;  			case OP_JUMP:  				if(got_const) { @@ -656,7 +640,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  					got_const = 0;  					JMPIARG();  				} else { -					emit("movl 0(%%r9, %%rsi, 1), %%eax"); // get instr from stack +					emit("movl (%%r9, %%rbx, 1), %%eax"); // get instr from stack  					STACK_POP(4);  					PREPARE_JMP(eax); @@ -702,8 +686,8 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  #ifndef USE_X87  				MAYBE_EMIT_CONST();  				STACK_POP(8); -				emit("movss 4(%%r9, %%rsi, 1), %%xmm0"); -				emit("ucomiss 8(%%r9, %%rsi, 1), %%xmm0"); +				emit("movss 4(%%r9, %%rbx, 1), %%xmm0"); +				emit("ucomiss 8(%%r9, %%rbx, 1), %%xmm0");  				emit("jp dojump_i_%08x", instruction);  				emit("jz i_%08x", instruction+1);  				emit("dojump_i_%08x:", instruction); @@ -729,105 +713,103 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  				break;  			case OP_LOAD1:  				MAYBE_EMIT_CONST(); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); // get value from stack +				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack  				RANGECHECK(eax, 1); -				emit("movb 0(%%r8, %%rax, 1), %%al"); // deref into eax +				emit("movb (%%r8, %%rax, 1), %%al"); // deref into eax  				emit("andq $255, %%rax"); -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); // store on stack +				emit("movl %%eax, (%%r9, %%rbx, 1)"); // store on stack  				break;  			case OP_LOAD2:  				MAYBE_EMIT_CONST(); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); // get value from stack +				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack  				RANGECHECK(eax, 2); -				emit("movw 0(%%r8, %%rax, 1), %%ax"); // deref into eax -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); // store on stack +				emit("movw (%%r8, %%rax, 1), %%ax"); // deref into eax +				emit("movl %%eax, (%%r9, %%rbx, 1)"); // store on stack  				break;  			case OP_LOAD4:  				MAYBE_EMIT_CONST(); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); // get value from stack +				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack  				RANGECHECK(eax, 4); // not a pointer!? -				emit("movl 0(%%r8, %%rax, 1), %%eax"); // deref into eax -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); // store on stack +				emit("movl (%%r8, %%rax, 1), %%eax"); // deref into eax +				emit("movl %%eax, (%%r9, %%rbx, 1)"); // store on stack  				break;  			case OP_STORE1:  				MAYBE_EMIT_CONST(); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); // get value from stack +				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack  				STACK_POP(8);  				emit("andq $255, %%rax"); -				emit("movl 4(%%r9, %%rsi, 1), %%ebx"); // get pointer from stack -				RANGECHECK(ebx, 1); -				emit("movb %%al, 0(%%r8, %%rbx, 1)"); // store in memory +				emit("movl 4(%%r9, %%rbx, 1), %%esi"); // get pointer from stack +				RANGECHECK(esi, 1); +				emit("movb %%al, (%%r8, %%rsi, 1)"); // store in memory  				break;  			case OP_STORE2:  				MAYBE_EMIT_CONST(); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); // get value from stack +				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack  				STACK_POP(8); -				emit("movl 4(%%r9, %%rsi, 1), %%ebx"); // get pointer from stack -				RANGECHECK(ebx, 2); -				emit("movw %%ax, 0(%%r8, %%rbx, 1)"); // store in memory +				emit("movl 4(%%r9, %%rbx, 1), %%esi"); // get pointer from stack +				RANGECHECK(esi, 2); +				emit("movw %%ax, (%%r8, %%rsi, 1)"); // store in memory  				break;  			case OP_STORE4:  				MAYBE_EMIT_CONST(); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); // get value from stack +				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack  				STACK_POP(8); -				emit("movl 4(%%r9, %%rsi, 1), %%ebx"); // get pointer from stack -				RANGECHECK(ebx, 4); -				emit("movl %%eax, 0(%%r8, %%rbx, 1)"); // store in memory +				emit("movl 4(%%r9, %%rbx, 1), %%esi"); // get pointer from stack +				RANGECHECK(esi, 4); +				emit("movl %%eax, (%%r8, %%rsi, 1)"); // store in memory  				break;  			case OP_ARG:  				MAYBE_EMIT_CONST(); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); // get value from stack +				emit("movl (%%r9, %%rbx, 1), %%eax"); // get value from stack  				STACK_POP(4); -				emit("movl $0x%hx, %%ebx", barg); -				emit("addl %%edi, %%ebx"); -				RANGECHECK(ebx, 4); -				emit("movl %%eax, 0(%%r8,%%rbx, 1)"); // store in args space +				emit("movl $0x%hx, %%esi", barg); +				emit("addl %%edi, %%esi"); +				RANGECHECK(esi, 4); +				emit("movl %%eax, (%%r8,%%rsi, 1)"); // store in args space  				break;  			case OP_BLOCK_COPY:  				MAYBE_EMIT_CONST();  				STACK_POP(8); -				emit("push %%rsi");  				emit("push %%rdi");  				emit("push %%r8");  				emit("push %%r9");  				emit("push %%r10"); -				emit("movq %%rsp, %%rbx"); // we need to align the stack pointer -				emit("subq $8, %%rbx");    //   | -				emit("andq $127, %%rbx");  //   | -				emit("subq %%rbx, %%rsp"); // <-+ -				emit("push %%rbx"); -				emit("movl 4(%%r9, %%rsi, 1), %%edi");  // 1st argument dest -				emit("movl 8(%%r9, %%rsi, 1), %%esi");  // 2nd argument src +				emit("movq %%rsp, %%rsi"); // we need to align the stack pointer +				emit("subq $8, %%rsi");    //   | +				emit("andq $127, %%rsi");  //   | +				emit("subq %%rsi, %%rsp"); // <-+ +				emit("push %%rsi"); +				emit("movl 4(%%r9, %%rbx, 1), %%edi");  // 1st argument dest +				emit("movl 8(%%r9, %%rbx, 1), %%rsi");  // 2nd argument src  				emit("movl $%d, %%edx", iarg); // 3rd argument count  				emit("movq $%"PRIu64", %%rax", (intptr_t) block_copy_vm);  				emit("callq *%%rax"); -				emit("pop %%rbx"); -				emit("addq %%rbx, %%rsp"); +				emit("pop %%rsi"); +				emit("addq %%rsi, %%rsp");  				emit("pop %%r10");  				emit("pop %%r9");  				emit("pop %%r8");  				emit("pop %%rdi"); -				emit("pop %%rsi");  				break;  			case OP_SEX8:  				MAYBE_EMIT_CONST(); -				emit("movw 0(%%r9, %%rsi, 1), %%ax"); +				emit("movw (%%r9, %%rbx, 1), %%ax");  				emit("andq $255, %%rax");  				emit("cbw");  				emit("cwde"); -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); +				emit("movl %%eax, (%%r9, %%rbx, 1)");  				break;  			case OP_SEX16:  				MAYBE_EMIT_CONST(); -				emit("movw 0(%%r9, %%rsi, 1), %%ax"); +				emit("movw (%%r9, %%rbx, 1), %%ax");  				emit("cwde"); -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); +				emit("movl %%eax, (%%r9, %%rbx, 1)");  				break;  			case OP_NEGI:  				MAYBE_EMIT_CONST(); -				emit("negl 0(%%r9, %%rsi, 1)"); +				emit("negl (%%r9, %%rbx, 1)");  				break;  			case OP_ADD:  				SIMPLE("addl"); @@ -838,49 +820,49 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  			case OP_DIVI:  				MAYBE_EMIT_CONST();  				STACK_POP(4); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); +				emit("movl (%%r9, %%rbx, 1), %%eax");  				emit("cdq"); -				emit("idivl 4(%%r9, %%rsi, 1)"); -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); +				emit("idivl 4(%%r9, %%rbx, 1)"); +				emit("movl %%eax, (%%r9, %%rbx, 1)");  				break;  			case OP_DIVU:  				MAYBE_EMIT_CONST();  				STACK_POP(4); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); +				emit("movl (%%r9, %%rbx, 1), %%eax");  				emit("xorq %%rdx, %%rdx"); -				emit("divl 4(%%r9, %%rsi, 1)"); -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); +				emit("divl 4(%%r9, %%rbx, 1)"); +				emit("movl %%eax, (%%r9, %%rbx, 1)");  				break;  			case OP_MODI:  				MAYBE_EMIT_CONST();  				STACK_POP(4); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); +				emit("movl (%%r9, %%rbx, 1), %%eax");  				emit("xorl %%edx, %%edx");  				emit("cdq"); -				emit("idivl 4(%%r9, %%rsi, 1)"); -				emit("movl %%edx, 0(%%r9, %%rsi, 1)"); +				emit("idivl 4(%%r9, %%rbx, 1)"); +				emit("movl %%edx, (%%r9, %%rbx, 1)");  				break;  			case OP_MODU:  				MAYBE_EMIT_CONST();  				STACK_POP(4); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); +				emit("movl (%%r9, %%rbx, 1), %%eax");  				emit("xorl %%edx, %%edx"); -				emit("divl 4(%%r9, %%rsi, 1)"); -				emit("movl %%edx, 0(%%r9, %%rsi, 1)"); +				emit("divl 4(%%r9, %%rbx, 1)"); +				emit("movl %%edx, (%%r9, %%rbx, 1)");  				break;  			case OP_MULI:  				MAYBE_EMIT_CONST();  				STACK_POP(4); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); -				emit("imull 4(%%r9, %%rsi, 1)"); -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); +				emit("movl (%%r9, %%rbx, 1), %%eax"); +				emit("imull 4(%%r9, %%rbx, 1)"); +				emit("movl %%eax, (%%r9, %%rbx, 1)");  				break;  			case OP_MULU:  				MAYBE_EMIT_CONST();  				STACK_POP(4); -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); -				emit("mull 4(%%r9, %%rsi, 1)"); -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); +				emit("movl (%%r9, %%rbx, 1), %%eax"); +				emit("mull 4(%%r9, %%rbx, 1)"); +				emit("movl %%eax, (%%r9, %%rbx, 1)");  				break;  			case OP_BAND:  				SIMPLE("andl"); @@ -893,7 +875,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  				break;  			case OP_BCOM:  				MAYBE_EMIT_CONST(); -				emit("notl 0(%%r9, %%rsi, 1)"); +				emit("notl (%%r9, %%rbx, 1)");  				break;  			case OP_LSH:  				SHIFT("shl"); @@ -907,12 +889,12 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  			case OP_NEGF:  				MAYBE_EMIT_CONST();  #ifdef USE_X87 -				emit("flds 0(%%r9, %%rsi, 1)"); +				emit("flds (%%r9, %%rbx, 1)");  				emit("fchs"); -				emit("fstps 0(%%r9, %%rsi, 1)"); +				emit("fstps (%%r9, %%rbx, 1)");  #else  				emit("movl $0x80000000, %%eax"); -				emit("xorl %%eax, 0(%%r9, %%rsi, 1)"); +				emit("xorl %%eax, (%%r9, %%rbx, 1)");  #endif  				break;  			case OP_ADDF: @@ -934,27 +916,27 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {  			case OP_CVIF:  				MAYBE_EMIT_CONST();  #ifdef USE_X87 -				emit("filds 0(%%r9, %%rsi, 1)"); -				emit("fstps 0(%%r9, %%rsi, 1)"); +				emit("filds (%%r9, %%rbx, 1)"); +				emit("fstps (%%r9, %%rbx, 1)");  #else -				emit("movl 0(%%r9, %%rsi, 1), %%eax"); +				emit("movl (%%r9, %%rbx, 1), %%eax");  				emit("cvtsi2ss %%eax, %%xmm0"); -				emit("movss %%xmm0, 0(%%r9, %%rsi, 1)"); +				emit("movss %%xmm0, (%%r9, %%rbx, 1)");  #endif  				break;  			case OP_CVFI:  				MAYBE_EMIT_CONST();  #ifdef USE_X87 -				emit("flds 0(%%r9, %%rsi, 1)"); -				emit("fnstcw 4(%%r9, %%rsi, 1)"); -				emit("movw $0x0F7F, 8(%%r9, %%rsi, 1)"); // round toward zero -				emit("fldcw 8(%%r9, %%rsi, 1)"); -				emit("fistpl 0(%%r9, %%rsi, 1)"); -				emit("fldcw 4(%%r9, %%rsi, 1)"); +				emit("flds (%%r9, %%rbx, 1)"); +				emit("fnstcw 4(%%r9, %%rbx, 1)"); +				emit("movw $0x0F7F, 8(%%r9, %%rbx, 1)"); // round toward zero +				emit("fldcw 8(%%r9, %%rbx, 1)"); +				emit("fistpl (%%r9, %%rbx, 1)"); +				emit("fldcw 4(%%r9, %%rbx, 1)");  #else -				emit("movss 0(%%r9, %%rsi, 1), %%xmm0"); +				emit("movss (%%r9, %%rbx, 1), %%xmm0");  				emit("cvttss2si %%xmm0, %%eax"); -				emit("movl %%eax, 0(%%r9, %%rsi, 1)"); +				emit("movl %%eax, (%%r9, %%rbx, 1)");  #endif  				break;  			default: @@ -1052,10 +1034,10 @@ int	VM_CallCompiled( vm_t *vm, int *args ) {  	int		programCounter;  	int		programStack;  	int		stackOnEntry; -	int		opStackRet; +	long		opStackRet;  	byte	*image;  	void	*entryPoint; -	void	*opStack; +	int	*opStack;  	int stack[OPSTACK_SIZE + 3] = { 0xDEADBEEF };  	currentVM = vm; @@ -1099,7 +1081,7 @@ int	VM_CallCompiled( vm_t *vm, int *args ) {  	opStack = PADP(stack, 4);  	__asm__ __volatile__ ( -		"	movl $0,%%esi		\r\n" \ +		"	movq $-0x80,%%rbx	\r\n" \  		"	movl %5,%%edi		\r\n" \  		"	movq %4,%%r8		\r\n" \  		"	movq %3,%%r9		\r\n" \ @@ -1108,14 +1090,13 @@ int	VM_CallCompiled( vm_t *vm, int *args ) {  		"	callq *%%r10		\r\n" \  		"       addq $24, %%rsp         \r\n" \  		"	movl %%edi, %0		\r\n" \ -		"	movl %%esi, %1		\r\n" \ -		: "=m" (programStack), "=m" (opStackRet) -		: "m" (entryPoint), "m" (opStack), "m" (vm->dataBase), "m" (programStack) +		"	movq %%rbx, %1		\r\n" \ +		: "=g" (programStack), "=g" (opStackRet) +		: "g" (entryPoint), "g" (((intptr_t ) opStack) + OPSTACK_SIZE / 2), "g" (vm->dataBase), "g" (programStack)  		: "%rsi", "%rdi", "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r15", "%xmm0"  	); - -	if(opStackRet != 4) -		Com_Error(ERR_DROP, "opStack corrupted in compiled code (offset %d)", opStackRet); +	if(opStackRet != -(OPSTACK_SIZE / 2) + 4 || *opStack != 0xDEADBEEF) +		Com_Error(ERR_DROP, "opStack corrupted in compiled code (offset %ld)", opStackRet);  	if ( programStack != stackOnEntry - 48 ) {  		Com_Error( ERR_DROP, "programStack corrupted in compiled code" ); diff --git a/src/qcommon/vm_x86_64_assembler.c b/src/qcommon/vm_x86_64_assembler.c index 10280be2..5047977a 100644 --- a/src/qcommon/vm_x86_64_assembler.c +++ b/src/qcommon/vm_x86_64_assembler.c @@ -160,6 +160,7 @@ typedef enum {  	R_R15 =  0x0F  | R_64,  	R_AL  =  R_EAX | R_8,  	R_AX  =  R_EAX | R_16, +	R_BL  =  R_EBX | R_8,  	R_CL  =  R_ECX | R_8,  	R_XMM0 = 0x00  | R_XMM,  	R_MGP =  0x0F, // mask for general purpose registers @@ -215,6 +216,32 @@ typedef struct {  	u8 rcode;  // opcode for reg/mem  } opparam_t; +static opparam_t params_add = { subcode: 0, rmcode: 0x01, }; +static opparam_t params_or = { subcode: 1, rmcode: 0x09, }; +static opparam_t params_and = { subcode: 4, rmcode: 0x21, }; +static opparam_t params_sub = { subcode: 5, rmcode: 0x29, }; +static opparam_t params_xor = { subcode: 6, rmcode: 0x31, }; +static opparam_t params_cmp = { subcode: 7, rmcode: 0x39, mrcode: 0x3b, }; +static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, }; +static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, }; +static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, }; +static opparam_t params_shr = { subcode: 5, rcode: 0xd3, rcode8: 0xd2, }; +static opparam_t params_idiv = { subcode: 7, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_div = { subcode: 6, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_imul = { subcode: 5, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_mul = { subcode: 4, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_neg = { subcode: 3, rcode: 0xf7, rcode8: 0xf6, }; +static opparam_t params_not = { subcode: 2, rcode: 0xf7, rcode8: 0xf6, }; + +static opparam_t params_cvtsi2ss = { xmmprefix: 0xf3, rmcode: 0x2a }; +static opparam_t params_cvttss2si = { xmmprefix: 0xf3, rmcode: 0x2c }; +static opparam_t params_addss = { xmmprefix: 0xf3, mrcode: 0x58 }; +static opparam_t params_divss = { xmmprefix: 0xf3, mrcode: 0x5e }; +static opparam_t params_movss = { xmmprefix: 0xf3, mrcode: 0x10, rmcode: 0x11 }; +static opparam_t params_mulss = { xmmprefix: 0xf3, mrcode: 0x59 }; +static opparam_t params_subss = { xmmprefix: 0xf3, mrcode: 0x5c }; +static opparam_t params_ucomiss = { mrcode: 0x2e }; +  /* ************************* */  static unsigned hashkey(const char *string, unsigned len) { @@ -316,9 +343,9 @@ static const char* argtype2str(argtype_t t)  /* ************************* */ -static inline int iss8(u64 v) +static inline int iss8(int64_t v)  { -	return (llabs(v) <= 0x80); //llabs instead of labs required for __WIN64 +	return (v >= -0x80 && v <= 0x7f);  }  static inline int isu8(u64 v) @@ -326,9 +353,9 @@ static inline int isu8(u64 v)  	return (v <= 0xff);  } -static inline int iss16(u64 v) +static inline int iss16(int64_t v)  { -	return (llabs(v) <= 0x8000); +	return (v >= -0x8000 && v <= 0x7fff);  }  static inline int isu16(u64 v) @@ -336,9 +363,9 @@ static inline int isu16(u64 v)  	return (v <= 0xffff);  } -static inline int iss32(u64 v) +static inline int iss32(int64_t v)  { -	return (llabs(v) <= 0x80000000); +	return (v >= -0x80000000L && v <= 0x7fffffff);  }  static inline int isu32(u64 v) @@ -597,7 +624,7 @@ static void emit_mov(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)  		if(arg2.v.reg & R_8)  		{ -			if(!isu8(arg1.v.imm)) +			if(!iss8(arg1.v.imm))  				crap("value too large for 8bit register");  			op = 0xb0; @@ -713,19 +740,23 @@ static void emit_subaddand(const char* mnemonic, arg_t arg1, arg_t arg2, void* d  		}  		compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2); -  		modrm |= params->subcode << 3;  		if(rex) emit1(rex); -#if 0 -		if(isu8(arg1.v.imm)) + +		if(arg2.v.reg & R_8) +		{ +			emit1(0x80); // sub reg8/mem8, imm8 +			emit1(modrm); +			emit1(arg1.v.imm & 0xFF); +		} +		else if(iss8(arg1.v.imm))  		{  			emit1(0x83); // sub reg/mem, imm8  			emit1(modrm); -			emit1(arg1.v.imm&0xFF); +			emit1(arg1.v.imm & 0xFF);  		}  		else -#endif  		{  			emit1(0x81); // sub reg/mem, imm32  			emit1(modrm); @@ -895,42 +926,19 @@ static void emit_twobyte(const char* mnemonic, arg_t arg1, arg_t arg2, void* dat  		CRAP_INVALID_ARGS;  } -static opparam_t params_add = { subcode: 0, rmcode: 0x01, }; -static opparam_t params_or = { subcode: 1, rmcode: 0x09, }; -static opparam_t params_and = { subcode: 4, rmcode: 0x21, }; -static opparam_t params_sub = { subcode: 5, rmcode: 0x29, }; -static opparam_t params_xor = { subcode: 6, rmcode: 0x31, }; -static opparam_t params_cmp = { subcode: 7, rmcode: 0x39, mrcode: 0x3b, }; -static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, }; -static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, }; -static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, }; -static opparam_t params_shr = { subcode: 5, rcode: 0xd3, rcode8: 0xd2, }; -static opparam_t params_idiv = { subcode: 7, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_div = { subcode: 6, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_imul = { subcode: 5, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_mul = { subcode: 4, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_neg = { subcode: 3, rcode: 0xf7, rcode8: 0xf6, }; -static opparam_t params_not = { subcode: 2, rcode: 0xf7, rcode8: 0xf6, }; - -static opparam_t params_cvtsi2ss = { xmmprefix: 0xf3, rmcode: 0x2a }; -static opparam_t params_cvttss2si = { xmmprefix: 0xf3, rmcode: 0x2c }; -static opparam_t params_addss = { xmmprefix: 0xf3, mrcode: 0x58 }; -static opparam_t params_divss = { xmmprefix: 0xf3, mrcode: 0x5e }; -static opparam_t params_movss = { xmmprefix: 0xf3, mrcode: 0x10, rmcode: 0x11 }; -static opparam_t params_mulss = { xmmprefix: 0xf3, mrcode: 0x59 }; -static opparam_t params_subss = { xmmprefix: 0xf3, mrcode: 0x5c }; -static opparam_t params_ucomiss = { mrcode: 0x2e }; -  static int ops_sorted = 0;  static op_t ops[] = { +	{ "addb", emit_subaddand, ¶ms_add },  	{ "addl", emit_subaddand, ¶ms_add },  	{ "addq", emit_subaddand, ¶ms_add },  	{ "addss", emit_twobyte, ¶ms_addss }, +	{ "andb", emit_subaddand, ¶ms_and },  	{ "andl", emit_subaddand, ¶ms_and },  	{ "andq", emit_subaddand, ¶ms_and },  	{ "callq", emit_call, NULL },  	{ "cbw", emit_opsingle16, (void*)0x98 },  	{ "cdq", emit_opsingle, (void*)0x99 }, +	{ "cmpb", emit_subaddand, ¶ms_cmp },  	{ "cmpl", emit_subaddand, ¶ms_cmp },  	{ "cmpq", emit_subaddand, ¶ms_cmp },  	{ "cvtsi2ss", emit_twobyte, ¶ms_cvtsi2ss }, @@ -976,18 +984,21 @@ static op_t ops[] = {  	{ "nop", emit_opsingle, (void*)0x90 },  	{ "notl", emit_op_rm, ¶ms_not },  	{ "notq", emit_op_rm, ¶ms_not }, -	{ "or",   emit_subaddand, ¶ms_or }, +	{ "orb",   emit_subaddand, ¶ms_or },  	{ "orl",  emit_subaddand, ¶ms_or }, +	{ "orq",  emit_subaddand, ¶ms_or },  	{ "pop", emit_opreg, (void*)0x58 },  	{ "push", emit_opreg, (void*)0x50 },  	{ "ret", emit_opsingle, (void*)0xc3 },  	{ "sarl", emit_op_rm_cl, ¶ms_sar },  	{ "shl", emit_op_rm_cl, ¶ms_shl },  	{ "shrl", emit_op_rm_cl, ¶ms_shr }, +	{ "subb", emit_subaddand, ¶ms_sub },  	{ "subl", emit_subaddand, ¶ms_sub },  	{ "subq", emit_subaddand, ¶ms_sub },  	{ "subss", emit_twobyte, ¶ms_subss },  	{ "ucomiss", emit_twobyte, ¶ms_ucomiss }, +	{ "xorb",  emit_subaddand, ¶ms_xor },  	{ "xorl",  emit_subaddand, ¶ms_xor },  	{ "xorq",  emit_subaddand, ¶ms_xor },  	{ NULL, NULL, NULL } @@ -1012,27 +1023,24 @@ static op_t* getop(const char* n)  	}  #else -	unsigned m, t, b; +	unsigned int m, t, b;  	int r;  	t = ARRAY_LEN(ops)-1; -	b = 0; -	while(b <= t) +	r = m = -1; + +	do  	{ -		m = ((t-b)>>1) + b; -		if((r = strcmp(ops[m].mnemonic, n)) == 0) -		{ -			return &ops[m]; -		} -		else if(r < 0) -		{ +		if(r < 0)  			b = m + 1; -		}  		else -		{  			t = m - 1; -		} -	} + +		m = ((t - b) >> 1) + b; + +		if((r = strcmp(ops[m].mnemonic, n)) == 0) +			return &ops[m]; +	} while(b <= t && t);  #endif  	return NULL; @@ -1049,6 +1057,10 @@ static reg_t parsereg(const char* str)  	{  		return R_AX;  	} +	if(*s == 'b' && s[1] == 'l' && !s[2]) +	{ +		return R_BL; +	}  	if(*s == 'c' && s[1] == 'l' && !s[2])  	{  		return R_CL;  | 
