mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2024-12-14 22:20:58 +00:00
get rid of gas remains
This commit is contained in:
parent
0adae90465
commit
2fecf6d6bc
2 changed files with 10 additions and 245 deletions
1
Makefile
1
Makefile
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue