optimize const before jump

This commit is contained in:
Ludwig Nussel 2009-11-01 19:58:12 +00:00
parent a7dee44def
commit ed98f65d10

View file

@ -239,8 +239,23 @@ void emit(const char* fmt, ...)
emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \ emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \
emit("jmpq *%%rax"); emit("jmpq *%%rax");
#define CONST_OPTIMIZE
#ifdef CONST_OPTIMIZE
#define MAYBE_EMIT_CONST() \
if (got_const) \
{ \
got_const = 0; \
vm->instructionPointers[instruction-1] = assembler_get_code_size(); \
emit("addq $4, %%rsi"); \
emit("movl $%d, 0(%%rsi)", const_value); \
}
#else
#define MAYBE_EMIT_CONST()
#endif
// integer compare and jump // integer compare and jump
#define IJ(op) \ #define IJ(op) \
MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi"); \ emit("subq $8, %%rsi"); \
emit("movl 4(%%rsi), %%eax"); \ emit("movl 4(%%rsi), %%eax"); \
emit("cmpl 8(%%rsi), %%eax"); \ emit("cmpl 8(%%rsi), %%eax"); \
@ -250,6 +265,7 @@ void emit(const char* fmt, ...)
#ifdef USE_X87 #ifdef USE_X87
#define FJ(bits, op) \ #define FJ(bits, op) \
MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi");\ emit("subq $8, %%rsi");\
emit("flds 4(%%rsi)");\ emit("flds 4(%%rsi)");\
emit("fcomps 8(%%rsi)");\ emit("fcomps 8(%%rsi)");\
@ -262,6 +278,7 @@ void emit(const char* fmt, ...)
#else #else
#define FJ(x, y) #define FJ(x, y)
#define XJ(op) \ #define XJ(op) \
MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi");\ emit("subq $8, %%rsi");\
emit("movss 4(%%rsi), %%xmm0");\ emit("movss 4(%%rsi), %%xmm0");\
emit("ucomiss 8(%%rsi), %%xmm0");\ emit("ucomiss 8(%%rsi), %%xmm0");\
@ -272,12 +289,14 @@ void emit(const char* fmt, ...)
#endif #endif
#define SIMPLE(op) \ #define SIMPLE(op) \
MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \ emit("subq $4, %%rsi"); \
emit("movl 4(%%rsi), %%eax"); \ emit("movl 4(%%rsi), %%eax"); \
emit(op " %%eax, 0(%%rsi)"); emit(op " %%eax, 0(%%rsi)");
#ifdef USE_X87 #ifdef USE_X87
#define FSIMPLE(op) \ #define FSIMPLE(op) \
MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \ emit("subq $4, %%rsi"); \
emit("flds 0(%%rsi)"); \ emit("flds 0(%%rsi)"); \
emit(op " 4(%%rsi)"); \ emit(op " 4(%%rsi)"); \
@ -286,6 +305,7 @@ void emit(const char* fmt, ...)
#else #else
#define FSIMPLE(op) #define FSIMPLE(op)
#define XSIMPLE(op) \ #define XSIMPLE(op) \
MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \ emit("subq $4, %%rsi"); \
emit("movss 0(%%rsi), %%xmm0"); \ emit("movss 0(%%rsi), %%xmm0"); \
emit(op " 4(%%rsi), %%xmm0"); \ emit(op " 4(%%rsi), %%xmm0"); \
@ -293,6 +313,7 @@ void emit(const char* fmt, ...)
#endif #endif
#define SHIFT(op) \ #define SHIFT(op) \
MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \ emit("subq $4, %%rsi"); \
emit("movl 4(%%rsi), %%ecx"); \ emit("movl 4(%%rsi), %%ecx"); \
emit("movl 0(%%rsi), %%eax"); \ emit("movl 0(%%rsi), %%eax"); \
@ -343,6 +364,12 @@ static void block_copy_vm(unsigned dest, unsigned src, unsigned count)
memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count); memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count);
} }
static void eop(void)
{
Com_Error(ERR_DROP, "end of program reached without return!\n");
exit(1);
}
/* /*
================= =================
VM_Compile VM_Compile
@ -364,6 +391,9 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
int pass; int pass;
size_t compiledOfs = 0; size_t compiledOfs = 0;
// const optimization
unsigned got_const = 0, const_value = 0;
gettimeofday(&tvstart, NULL); gettimeofday(&tvstart, NULL);
for (pass = 0; pass < 2; ++pass) { for (pass = 0; pass < 2; ++pass) {
@ -400,7 +430,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
vm->instructionPointers[instruction] = assembler_get_code_size(); vm->instructionPointers[instruction] = assembler_get_code_size();
/* store current instruction number in r15 for debugging */ /* store current instruction number in r15 for debugging */
#if DEBUG_VM #if DEBUG_VM0
emit("nop"); emit("nop");
emit("movq $%d, %%r15", instruction); emit("movq $%d, %%r15", instruction);
emit("nop"); emit("nop");
@ -434,20 +464,25 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
NOTIMPL(op); NOTIMPL(op);
break; break;
case OP_IGNORE: case OP_IGNORE:
MAYBE_EMIT_CONST();
emit("nop"); emit("nop");
break; break;
case OP_BREAK: case OP_BREAK:
MAYBE_EMIT_CONST();
emit("int3"); emit("int3");
break; break;
case OP_ENTER: case OP_ENTER:
MAYBE_EMIT_CONST();
emit("subl $%d, %%edi", iarg); emit("subl $%d, %%edi", iarg);
RANGECHECK(edi); RANGECHECK(edi);
break; break;
case OP_LEAVE: case OP_LEAVE:
MAYBE_EMIT_CONST();
emit("addl $%d, %%edi", iarg); // get rid of stack frame emit("addl $%d, %%edi", iarg); // get rid of stack frame
emit("ret"); emit("ret");
break; break;
case OP_CALL: case OP_CALL:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get instr from stack emit("movl 0(%%rsi), %%eax"); // get instr from stack
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
emit("movl $%d, 0(%%r8, %%rdi, 1)", instruction+1); // save next instruction emit("movl $%d, 0(%%r8, %%rdi, 1)", instruction+1); // save next instruction
@ -489,31 +524,43 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
neednilabel = 1; neednilabel = 1;
break; break;
case OP_PUSH: case OP_PUSH:
MAYBE_EMIT_CONST();
emit("addq $4, %%rsi"); emit("addq $4, %%rsi");
break; break;
case OP_POP: case OP_POP:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
break; break;
case OP_CONST: case OP_CONST:
if(code[pc] == OP_JUMP) { MAYBE_EMIT_CONST();
CHECK_IARG; #ifdef CONST_OPTIMIZE
} got_const = 1;
const_value = iarg;
#else
emit("addq $4, %%rsi"); emit("addq $4, %%rsi");
emit("movl $%d, 0(%%rsi)", iarg); emit("movl $%d, 0(%%rsi)", iarg);
#endif
break; break;
case OP_LOCAL: case OP_LOCAL:
MAYBE_EMIT_CONST();
emit("movl %%edi, %%ebx"); emit("movl %%edi, %%ebx");
emit("addl $%d,%%ebx", iarg); emit("addl $%d,%%ebx", iarg);
emit("addq $4, %%rsi"); emit("addq $4, %%rsi");
emit("movl %%ebx, 0(%%rsi)"); emit("movl %%ebx, 0(%%rsi)");
break; break;
case OP_JUMP: case OP_JUMP:
emit("movl 0(%%rsi), %%eax"); // get instr from stack if(got_const) {
emit("subq $4, %%rsi"); iarg = const_value;
emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers); got_const = 0;
emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address JMPIARG;
emit("addq %%r10, %%rax"); } else {
emit("jmp *%%rax"); emit("movl 0(%%rsi), %%eax"); // get instr from stack
emit("subq $4, %%rsi");
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");
}
break; break;
case OP_EQ: case OP_EQ:
IJ("jne"); IJ("jne");
@ -552,6 +599,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
case OP_NEF: case OP_NEF:
FJ(0x40, "jnz"); FJ(0x40, "jnz");
#ifndef USE_X87 #ifndef USE_X87
MAYBE_EMIT_CONST();
emit("subq $8, %%rsi"); emit("subq $8, %%rsi");
emit("movss 4(%%rsi), %%xmm0"); emit("movss 4(%%rsi), %%xmm0");
emit("ucomiss 8(%%rsi), %%xmm0"); emit("ucomiss 8(%%rsi), %%xmm0");
@ -579,6 +627,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
XJ("jb"); XJ("jb");
break; break;
case OP_LOAD1: case OP_LOAD1:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack emit("movl 0(%%rsi), %%eax"); // get value from stack
RANGECHECK(eax); RANGECHECK(eax);
emit("movb 0(%%r8, %%rax, 1), %%al"); // deref into eax emit("movb 0(%%r8, %%rax, 1), %%al"); // deref into eax
@ -586,18 +635,21 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%eax, 0(%%rsi)"); // store on stack emit("movl %%eax, 0(%%rsi)"); // store on stack
break; break;
case OP_LOAD2: case OP_LOAD2:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack emit("movl 0(%%rsi), %%eax"); // get value from stack
RANGECHECK(eax); RANGECHECK(eax);
emit("movw 0(%%r8, %%rax, 1), %%ax"); // deref into eax emit("movw 0(%%r8, %%rax, 1), %%ax"); // deref into eax
emit("movl %%eax, 0(%%rsi)"); // store on stack emit("movl %%eax, 0(%%rsi)"); // store on stack
break; break;
case OP_LOAD4: case OP_LOAD4:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack emit("movl 0(%%rsi), %%eax"); // get value from stack
RANGECHECK(eax); // not a pointer!? RANGECHECK(eax); // not a pointer!?
emit("movl 0(%%r8, %%rax, 1), %%eax"); // deref into eax emit("movl 0(%%r8, %%rax, 1), %%eax"); // deref into eax
emit("movl %%eax, 0(%%rsi)"); // store on stack emit("movl %%eax, 0(%%rsi)"); // store on stack
break; break;
case OP_STORE1: case OP_STORE1:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("andq $255, %%rax"); emit("andq $255, %%rax");
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
@ -606,6 +658,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("subq $8, %%rsi"); emit("subq $8, %%rsi");
break; break;
case OP_STORE2: case OP_STORE2:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
RANGECHECK(ebx); RANGECHECK(ebx);
@ -613,6 +666,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("subq $8, %%rsi"); emit("subq $8, %%rsi");
break; break;
case OP_STORE4: case OP_STORE4:
MAYBE_EMIT_CONST();
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
RANGECHECK(ebx); RANGECHECK(ebx);
emit("movl 0(%%rsi), %%ecx"); // get value from stack emit("movl 0(%%rsi), %%ecx"); // get value from stack
@ -620,6 +674,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("subq $8, %%rsi"); emit("subq $8, %%rsi");
break; break;
case OP_ARG: case OP_ARG:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
emit("movl 4(%%rsi), %%eax"); // get value from stack emit("movl 4(%%rsi), %%eax"); // get value from stack
emit("movl $0x%hhx, %%ebx", barg); emit("movl $0x%hhx, %%ebx", barg);
@ -629,6 +684,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
break; break;
case OP_BLOCK_COPY: case OP_BLOCK_COPY:
MAYBE_EMIT_CONST();
emit("subq $8, %%rsi"); emit("subq $8, %%rsi");
emit("push %%rsi"); emit("push %%rsi");
emit("push %%rdi"); emit("push %%rdi");
@ -648,6 +704,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
break; break;
case OP_SEX8: case OP_SEX8:
MAYBE_EMIT_CONST();
emit("movw 0(%%rsi), %%ax"); emit("movw 0(%%rsi), %%ax");
emit("andq $255, %%rax"); emit("andq $255, %%rax");
emit("cbw"); emit("cbw");
@ -655,11 +712,13 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%eax, 0(%%rsi)"); emit("movl %%eax, 0(%%rsi)");
break; break;
case OP_SEX16: case OP_SEX16:
MAYBE_EMIT_CONST();
emit("movw 0(%%rsi), %%ax"); emit("movw 0(%%rsi), %%ax");
emit("cwde"); emit("cwde");
emit("movl %%eax, 0(%%rsi)"); emit("movl %%eax, 0(%%rsi)");
break; break;
case OP_NEGI: case OP_NEGI:
MAYBE_EMIT_CONST();
emit("negl 0(%%rsi)"); emit("negl 0(%%rsi)");
break; break;
case OP_ADD: case OP_ADD:
@ -669,6 +728,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
SIMPLE("subl"); SIMPLE("subl");
break; break;
case OP_DIVI: case OP_DIVI:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax"); emit("movl 0(%%rsi), %%eax");
emit("cdq"); emit("cdq");
@ -676,6 +736,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%eax, 0(%%rsi)"); emit("movl %%eax, 0(%%rsi)");
break; break;
case OP_DIVU: case OP_DIVU:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax"); emit("movl 0(%%rsi), %%eax");
emit("xorq %%rdx, %%rdx"); emit("xorq %%rdx, %%rdx");
@ -683,6 +744,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%eax, 0(%%rsi)"); emit("movl %%eax, 0(%%rsi)");
break; break;
case OP_MODI: case OP_MODI:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax"); emit("movl 0(%%rsi), %%eax");
emit("xorl %%edx, %%edx"); emit("xorl %%edx, %%edx");
@ -691,6 +753,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%edx, 0(%%rsi)"); emit("movl %%edx, 0(%%rsi)");
break; break;
case OP_MODU: case OP_MODU:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax"); emit("movl 0(%%rsi), %%eax");
emit("xorl %%edx, %%edx"); emit("xorl %%edx, %%edx");
@ -698,12 +761,14 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl %%edx, 0(%%rsi)"); emit("movl %%edx, 0(%%rsi)");
break; break;
case OP_MULI: case OP_MULI:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax"); emit("movl 0(%%rsi), %%eax");
emit("imull 4(%%rsi)"); emit("imull 4(%%rsi)");
emit("movl %%eax, 0(%%rsi)"); emit("movl %%eax, 0(%%rsi)");
break; break;
case OP_MULU: case OP_MULU:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi"); emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax"); emit("movl 0(%%rsi), %%eax");
emit("mull 4(%%rsi)"); emit("mull 4(%%rsi)");
@ -719,6 +784,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
SIMPLE("xorl"); SIMPLE("xorl");
break; break;
case OP_BCOM: case OP_BCOM:
MAYBE_EMIT_CONST();
emit("notl 0(%%rsi)"); emit("notl 0(%%rsi)");
break; break;
case OP_LSH: case OP_LSH:
@ -731,6 +797,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
SHIFT("shrl"); SHIFT("shrl");
break; break;
case OP_NEGF: case OP_NEGF:
MAYBE_EMIT_CONST();
#ifdef USE_X87 #ifdef USE_X87
emit("flds 0(%%rsi)"); emit("flds 0(%%rsi)");
emit("fchs"); emit("fchs");
@ -757,6 +824,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
XSIMPLE("mulss"); XSIMPLE("mulss");
break; break;
case OP_CVIF: case OP_CVIF:
MAYBE_EMIT_CONST();
#ifdef USE_X87 #ifdef USE_X87
emit("filds 0(%%rsi)"); emit("filds 0(%%rsi)");
emit("fstps 0(%%rsi)"); emit("fstps 0(%%rsi)");
@ -767,6 +835,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
#endif #endif
break; break;
case OP_CVFI: case OP_CVFI:
MAYBE_EMIT_CONST();
#ifdef USE_X87 #ifdef USE_X87
emit("flds 0(%%rsi)"); emit("flds 0(%%rsi)");
emit("fnstcw 4(%%rsi)"); emit("fnstcw 4(%%rsi)");
@ -784,8 +853,17 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
NOTIMPL(op); NOTIMPL(op);
break; break;
} }
} }
if(got_const) {
Com_Error(ERR_DROP, "leftover const\n");
}
emit("movq $%lu, %%rax", (unsigned long)eop);
emit("callq *%%rax");
} // pass loop } // pass loop
assembler_init(0); assembler_init(0);
@ -798,6 +876,15 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
#ifdef DEBUG_VM #ifdef DEBUG_VM
fflush(qdasmout); fflush(qdasmout);
fclose(qdasmout); fclose(qdasmout);
#if 0
strcpy(fn_d,vm->name);
strcat(fn_d, ".bin");
qdasmout = fopen(fn_d, "w");
fwrite(vm->codeBase, compiledOfs, 1, qdasmout);
fflush(qdasmout);
fclose(qdasmout);
#endif
#endif #endif
if(vm->compiled) if(vm->compiled)