- 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
This commit is contained in:
Thilo Schulz 2011-05-16 17:55:07 +00:00
parent 558ed62771
commit 5aa3da2f84
2 changed files with 189 additions and 196 deletions

View file

@ -71,13 +71,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
*/
@ -248,33 +248,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); \
@ -285,8 +271,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) \
@ -309,7 +295,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()
@ -319,8 +305,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
@ -329,8 +315,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);\
@ -342,8 +328,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(); \
@ -352,35 +338,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) \
@ -562,7 +548,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)
{
@ -578,7 +564,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");
@ -592,16 +578,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
@ -612,16 +597,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:
@ -639,15 +623,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) {
@ -655,7 +639,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);
@ -701,8 +685,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);
@ -728,105 +712,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");
@ -837,49 +819,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");
@ -892,7 +874,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");
@ -906,12 +888,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:
@ -933,27 +915,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:
@ -1051,10 +1033,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;
@ -1098,7 +1080,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" \
@ -1107,14 +1089,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" );

View file

@ -158,6 +158,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
@ -213,6 +214,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) {
@ -314,9 +341,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)
@ -324,9 +351,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)
@ -334,9 +361,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)
@ -595,7 +622,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;
@ -711,19 +738,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);
@ -893,42 +924,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, &params_add },
{ "addl", emit_subaddand, &params_add },
{ "addq", emit_subaddand, &params_add },
{ "addss", emit_twobyte, &params_addss },
{ "andb", emit_subaddand, &params_and },
{ "andl", emit_subaddand, &params_and },
{ "andq", emit_subaddand, &params_and },
{ "callq", emit_call, NULL },
{ "cbw", emit_opsingle16, (void*)0x98 },
{ "cdq", emit_opsingle, (void*)0x99 },
{ "cmpb", emit_subaddand, &params_cmp },
{ "cmpl", emit_subaddand, &params_cmp },
{ "cmpq", emit_subaddand, &params_cmp },
{ "cvtsi2ss", emit_twobyte, &params_cvtsi2ss },
@ -974,18 +982,21 @@ static op_t ops[] = {
{ "nop", emit_opsingle, (void*)0x90 },
{ "notl", emit_op_rm, &params_not },
{ "notq", emit_op_rm, &params_not },
{ "or", emit_subaddand, &params_or },
{ "orb", emit_subaddand, &params_or },
{ "orl", emit_subaddand, &params_or },
{ "orq", emit_subaddand, &params_or },
{ "pop", emit_opreg, (void*)0x58 },
{ "push", emit_opreg, (void*)0x50 },
{ "ret", emit_opsingle, (void*)0xc3 },
{ "sarl", emit_op_rm_cl, &params_sar },
{ "shl", emit_op_rm_cl, &params_shl },
{ "shrl", emit_op_rm_cl, &params_shr },
{ "subb", emit_subaddand, &params_sub },
{ "subl", emit_subaddand, &params_sub },
{ "subq", emit_subaddand, &params_sub },
{ "subss", emit_twobyte, &params_subss },
{ "ucomiss", emit_twobyte, &params_ucomiss },
{ "xorb", emit_subaddand, &params_xor },
{ "xorl", emit_subaddand, &params_xor },
{ "xorq", emit_subaddand, &params_xor },
{ NULL, NULL, NULL }
@ -1010,27 +1021,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;
@ -1047,6 +1055,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;