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