get rid of gas remains

This commit is contained in:
Ludwig Nussel 2009-10-26 21:59:03 +00:00
parent 0adae90465
commit 2fecf6d6bc
2 changed files with 10 additions and 245 deletions

View file

@ -281,7 +281,6 @@ ifeq ($(PLATFORM),linux)
OPTIMIZE = -O3 -fomit-frame-pointer -ffast-math -funroll-loops \ OPTIMIZE = -O3 -fomit-frame-pointer -ffast-math -funroll-loops \
-falign-loops=2 -falign-jumps=2 -falign-functions=2 \ -falign-loops=2 -falign-jumps=2 -falign-functions=2 \
-fstrength-reduce -fstrength-reduce
# experimental x86_64 jit compiler! you need GNU as
HAVE_VM_COMPILED = true HAVE_VM_COMPILED = true
else else
ifeq ($(ARCH),i386) ifeq ($(ARCH),i386)

View file

@ -35,7 +35,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
//#define USE_GAS
//#define DEBUG_VM //#define DEBUG_VM
#ifdef DEBUG_VM #ifdef DEBUG_VM
@ -47,16 +46,10 @@ static FILE* qdasmout;
#define VM_X86_64_MMAP #define VM_X86_64_MMAP
#ifndef USE_GAS
void assembler_set_output(char* buf); void assembler_set_output(char* buf);
size_t assembler_get_code_size(void); size_t assembler_get_code_size(void);
void assembler_init(int pass); void assembler_init(int pass);
void assemble_line(const char* input, size_t len); void assemble_line(const char* input, size_t len);
#ifdef Dfprintf
#undef Dfprintf
#define Dfprintf(args...)
#endif
#endif // USE_GAS
static void VM_Destroy_Compiled(vm_t* self); static void VM_Destroy_Compiled(vm_t* self);
@ -225,10 +218,6 @@ static unsigned char op_argsize[256] =
[OP_BLOCK_COPY] = 4, [OP_BLOCK_COPY] = 4,
}; };
#ifdef USE_GAS
#define emit(x...) \
do { fprintf(fh_s, ##x); fputc('\n', fh_s); } while(0)
#else
void emit(const char* fmt, ...) void emit(const char* fmt, ...)
{ {
va_list ap; va_list ap;
@ -238,16 +227,10 @@ void emit(const char* fmt, ...)
va_end(ap); va_end(ap);
assemble_line(line, strlen(line)); assemble_line(line, strlen(line));
} }
#endif // USE_GAS
#ifdef USE_GAS
#define JMPIARG \
emit("jmp i_%08x", iarg);
#else
#define JMPIARG \ #define JMPIARG \
emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \ emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \
emit("jmpq *%%rax"); emit("jmpq *%%rax");
#endif
// integer compare and jump // integer compare and jump
#define IJ(op) \ #define IJ(op) \
@ -335,103 +318,9 @@ void emit(const char* fmt, ...)
static void* getentrypoint(vm_t* vm) static void* getentrypoint(vm_t* vm)
{ {
#ifdef USE_GAS
return vm->codeBase+64; // skip ELF header
#else
return vm->codeBase; return vm->codeBase;
#endif // USE_GAS
} }
#ifdef USE_GAS
char* mmapfile(const char* fn, size_t* size)
{
int fd = -1;
char* mem = NULL;
struct stat stb;
fd = open(fn, O_RDONLY);
if(fd == -1)
goto out;
if(fstat(fd, &stb) == -1)
goto out;
*size = stb.st_size;
mem = mmap(NULL, stb.st_size, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
if(mem == (void*)-1)
mem = NULL;
out:
if(fd != -1)
close(fd);
return mem;
}
static int doas(char* in, char* out, unsigned char** compiledcode)
{
unsigned char* mem;
size_t size = -1;
pid_t pid;
Com_Printf("running assembler < %s > %s\n", in, out);
pid = fork();
if(pid == -1)
{
Com_Printf(S_COLOR_RED "can't fork\n");
return -1;
}
if(!pid)
{
char* const argv[] = {
"as",
"-o",
out,
in,
NULL
};
execvp(argv[0], argv);
_exit(-1);
}
else
{
int status;
if(waitpid(pid, &status, 0) == -1)
{
Com_Printf(S_COLOR_RED "can't wait for as: %s\n", strerror(errno));
return -1;
}
if(!WIFEXITED(status))
{
Com_Printf(S_COLOR_RED "as died\n");
return -1;
}
if(WEXITSTATUS(status))
{
Com_Printf(S_COLOR_RED "as failed with status %d\n", WEXITSTATUS(status));
return -1;
}
}
Com_Printf("done\n");
mem = (unsigned char*)mmapfile(out, &size);
if(!mem)
{
Com_Printf(S_COLOR_RED "can't mmap object file %s: %s\n", out, strerror(errno));
return -1;
}
*compiledcode = mem;
return size;
}
#endif // USE_GAS
static void block_copy_vm(unsigned dest, unsigned src, unsigned count) static void block_copy_vm(unsigned dest, unsigned src, unsigned count)
{ {
unsigned dataMask = currentVM->dataMask; unsigned dataMask = currentVM->dataMask;
@ -461,68 +350,10 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
unsigned char barg = 0; unsigned char barg = 0;
int neednilabel = 0; int neednilabel = 0;
struct timeval tvstart = {0, 0}; struct timeval tvstart = {0, 0};
#ifdef USE_GAS
byte* compiledcode;
int compiledsize;
void* entryPoint;
char fn_s[2*MAX_QPATH]; // output file for assembler code
char fn_o[2*MAX_QPATH]; // file written by as
#ifdef DEBUG_VM #ifdef DEBUG_VM
char fn_d[MAX_QPATH]; // disassembled char fn_d[MAX_QPATH]; // disassembled
#endif #endif
FILE* fh_s;
int fd_s, fd_o;
gettimeofday(&tvstart, NULL);
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|O_TRUNC, 0644);
fd_o = open(fn_o, O_CREAT|O_WRONLY|O_TRUNC, 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);
if(fd_o != -1) close(fd_o);
unlink(fn_s);
unlink(fn_o);
Com_Printf(S_COLOR_RED "can't create temporary file %s for vm\n", fn_s);
vm->compiled = qfalse;
return;
}
#ifdef DEBUG_VM
strcpy(fn_d,vm->name);
strcat(fn_d, ".qdasm");
qdasmout = fopen(fn_d, "w");
#endif
fh_s = fdopen(fd_s, "wb");
if(!fh_s)
{
Com_Printf(S_COLOR_RED "can't write %s\n", fn_s);
vm->compiled = qfalse;
return;
}
emit("start:");
emit("or %%r8, %%r8"); // check whether to set up instruction pointers
emit("jnz main");
emit("jmp setupinstructionpointers");
emit("main:");
#else // USE_GAS
int pass; int pass;
size_t compiledOfs = 0; size_t compiledOfs = 0;
@ -543,7 +374,12 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
assembler_init(pass); assembler_init(pass);
#endif // USE_GAS #ifdef DEBUG_VM
strcpy(fn_d,vm->name);
strcat(fn_d, ".qdasm");
qdasmout = fopen(fn_d, "w");
#endif
// translate all instructions // translate all instructions
pc = 0; pc = 0;
@ -554,12 +390,10 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
op = code[ pc ]; op = code[ pc ];
++pc; ++pc;
#ifndef USE_GAS
vm->instructionPointers[instruction] = assembler_get_code_size(); vm->instructionPointers[instruction] = assembler_get_code_size();
#endif
/* store current instruction number in r15 for debugging */ /* store current instruction number in r15 for debugging */
#if 1 #if DEBUG_VM
emit("nop"); emit("nop");
emit("movq $%d, %%r15", instruction); emit("movq $%d, %%r15", instruction);
emit("nop"); emit("nop");
@ -581,15 +415,11 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
Dfprintf(qdasmout, "%s\n", opnames[op]); Dfprintf(qdasmout, "%s\n", opnames[op]);
} }
#ifdef USE_GAS
emit("i_%08x:", instruction);
#else
if(neednilabel) if(neednilabel)
{ {
emit("i_%08x:", instruction); emit("i_%08x:", instruction);
neednilabel = 0; neednilabel = 0;
} }
#endif
switch ( op ) switch ( op )
{ {
@ -946,82 +776,20 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
} }
} }
#ifdef USE_GAS } // pass loop
emit("setupinstructionpointers:");
emit("movq $%lu, %%rax", (unsigned long)vm->instructionPointers);
for ( instruction = 0; instruction < header->instructionCount; ++instruction )
{
emit("movl $i_%08x-start, %d(%%rax)", instruction, instruction*4);
}
emit("ret");
emit("debugger:");
if(1);
{
int i = 6;
while(i--)
{
emit("nop");
emit("int3");
}
}
fflush(fh_s);
fclose(fh_s);
compiledsize = doas(fn_s, fn_o, &compiledcode);
if(compiledsize == -1)
{
vm->compiled = qfalse;
goto out;
}
vm->codeBase = compiledcode; // remember to skip ELF header!
vm->codeLength = compiledsize;
#else // USE_GAS
}
assembler_init(0); assembler_init(0);
if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC)) if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC))
Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed"); Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed");
#endif // USE_GAS
vm->destroy = VM_Destroy_Compiled; vm->destroy = VM_Destroy_Compiled;
#ifdef USE_GAS
entryPoint = getentrypoint(vm);
// __asm__ __volatile__ ("int3");
Com_Printf("computing jump table\n");
// call code with r8 set to zero to set up instruction pointers
__asm__ __volatile__ (
" xorq %%r8,%%r8 \r\n" \
" movq %0,%%r10 \r\n" \
" callq *%%r10 \r\n" \
:
: "m" (entryPoint)
: "%r8", "%r10", "%rax"
);
#ifdef DEBUG_VM #ifdef DEBUG_VM
fflush(qdasmout); fflush(qdasmout);
fclose(qdasmout); fclose(qdasmout);
#endif #endif
out:
close(fd_o);
#ifndef DEBUG_VM
if(!com_developer->integer)
{
unlink(fn_o);
unlink(fn_s);
}
#endif
#endif // USE_GAS
if(vm->compiled) if(vm->compiled)
{ {
struct timeval tvdone = {0, 0}; struct timeval tvdone = {0, 0};
@ -1037,9 +805,7 @@ out:
void VM_Destroy_Compiled(vm_t* self) void VM_Destroy_Compiled(vm_t* self)
{ {
#ifdef USE_GAS #ifdef _WIN32
munmap(self->codeBase, self->codeLength);
#elif _WIN32
VirtualFree(self->codeBase, 0, MEM_RELEASE); VirtualFree(self->codeBase, 0, MEM_RELEASE);
#else #else
munmap(self->codeBase, self->codeLength); munmap(self->codeBase, self->codeLength);