# HG changeset patch # User Michael Pavone # Date 1392798147 28800 # Node ID 96489fb27dbfde4145d071d578cb79e76f6a29cb # Parent 32da1e0d5e55fc40f63ac89a426051254bd17ae2 Apart from the Z80 core, BlastEm now supports 32-bit x86 diff -r 32da1e0d5e55 -r 96489fb27dbf Makefile --- a/Makefile Tue Feb 18 23:19:07 2014 -0800 +++ b/Makefile Wed Feb 19 00:22:27 2014 -0800 @@ -22,8 +22,18 @@ CPU:=$(shell uname -m) endif + + TRANSOBJS=gen_x86.o x86_backend.o mem.o -M68KOBJS=68kinst.o m68k_to_x86.o runtime.o +M68KOBJS=68kinst.o m68k_to_x86.o +ifeq ($(CPU),x86_64) +M68kOBJS+= runtime.o +else +ifeq ($(CPU),i686) +M68KOBJS+= runtime_32.o +endif +endif + Z80OBJS=z80inst.o z80_to_x86.o zruntime.o AUDIOOBJS=ym2612.o psg.o wave.o CONFIGOBJS=config.o tern.o util.o diff -r 32da1e0d5e55 -r 96489fb27dbf gen_x86.c --- a/gen_x86.c Tue Feb 18 23:19:07 2014 -0800 +++ b/gen_x86.c Wed Feb 19 00:22:27 2014 -0800 @@ -1756,7 +1756,7 @@ disp >>= 8; *(out++) = disp; } else { - printf("%p - %p = %lX\n", dest, out + 6, disp); + printf("%p - %p = %lX\n", dest, out + 6, (long)disp); return NULL; } } @@ -1781,7 +1781,7 @@ disp >>= 8; *(out++) = disp; } else { - printf("%p - %p = %lX\n", dest, out + 6, disp); + printf("%p - %p = %lX\n", dest, out + 6, (long)disp); return NULL; } } @@ -1813,7 +1813,7 @@ *(out++) = disp; } else { //TODO: Implement far call??? - printf("%p - %p = %lX\n", fun, out + 5, disp); + printf("%p - %p = %lX\n", fun, out + 5, (long)disp); return NULL; } return out; diff -r 32da1e0d5e55 -r 96489fb27dbf gen_x86.h --- a/gen_x86.h Tue Feb 18 23:19:07 2014 -0800 +++ b/gen_x86.h Wed Feb 19 00:22:27 2014 -0800 @@ -57,6 +57,12 @@ SZ_Q } x86_size; +#ifdef X86_64 +#define SZ_PTR SZ_Q +#else +#define SZ_PTR SZ_D +#endif + enum { MODE_REG_INDIRECT = 0, MODE_REG_INDEXED = 4, diff -r 32da1e0d5e55 -r 96489fb27dbf m68k_to_x86.c --- a/m68k_to_x86.c Tue Feb 18 23:19:07 2014 -0800 +++ b/m68k_to_x86.c Wed Feb 19 00:22:27 2014 -0800 @@ -3371,7 +3371,11 @@ break; case M68K_ILLEGAL: dst = call(dst, opts->save_context); - dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); +#ifdef X86_64 + dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); +#else + dst = push_r(dst, CONTEXT); +#endif dst = call(dst, (uint8_t *)print_regs_exit); break; case M68K_MOVE_FROM_SR: @@ -3606,7 +3610,11 @@ break; case M68K_RESET: dst = call(dst, opts->save_context); - dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); +#ifdef X86_64 + dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); +#else + dst = push_r(dst, CONTEXT); +#endif dst = call(dst, (uint8_t *)print_regs_exit); break; case M68K_ROL: @@ -4108,6 +4116,9 @@ } if (address >= 0x400000 && address < 0xE00000) { dst = xor_rr(dst, RDI, RDI, SZ_D); +#ifdef X86_32 + dst = push_r(dst, RDI); +#endif dst = call(dst, (uint8_t *)exit); break; } @@ -4237,9 +4248,16 @@ uint8_t * rdst = options->retrans_stub = options->cur_code; rdst = call(rdst, options->save_context); rdst = push_r(rdst, CONTEXT); +#ifdef X86_32 + rdst = push_r(rdst, CONTEXT); + rdst = push_r(rdst, SCRATCH2); +#endif rdst = call(rdst, (uint8_t *)m68k_retranslate_inst); +#ifdef X86_32 + rdst = add_ir(rdst, 8, RSP, SZ_D); +#endif rdst = pop_r(rdst, CONTEXT); - rdst = mov_rr(rdst, RAX, SCRATCH1, SZ_Q); + rdst = mov_rr(rdst, RAX, SCRATCH1, SZ_PTR); rdst = call(rdst, options->load_context); rdst = jmp_r(rdst, SCRATCH1); options->cur_code = rdst; @@ -4275,10 +4293,18 @@ //Save context and call breakpoint handler dst = call(dst, opts->save_context); dst = push_r(dst, SCRATCH1); - dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); +#ifdef X86_64 + dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); +#else + dst = push_r(dst, SCRATCH1); + dst = push_r(dst, CONTEXT); +#endif dst = call(dst, bp_handler); - dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); +#ifdef X86_32 + dst = add_ir(dst, 8, RSP, SZ_D); +#endif + dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); //Restore context dst = call(dst, opts->load_context); dst = pop_r(dst, SCRATCH1); @@ -4290,7 +4316,7 @@ *jmp_off = dst - (jmp_off+1); //jump back to body of translated instruction dst = pop_r(dst, SCRATCH1); - dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_Q); + dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_PTR); dst = jmp_r(dst, SCRATCH1); opts->cur_code = dst; } else { @@ -4375,10 +4401,11 @@ if(memmap[chunk].buffer && memmap[chunk].flags & access_flag) { if (memmap[chunk].flags & MMAP_PTR_IDX) { if (memmap[chunk].flags & MMAP_FUNC_NULL) { - dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, SZ_Q); + dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, SZ_PTR); uint8_t * not_null = dst+1; dst = jcc(dst, CC_NZ, dst+2); dst = call(dst, opts->save_context); +#ifdef X86_64 if (is_write) { if (SCRATCH2 != RDI) { dst = mov_rr(dst, SCRATCH2, RDI, SZ_D); @@ -4395,12 +4422,23 @@ uint8_t *no_adjust = dst+1; dst = jmp(dst, dst+2); *adjust_rsp = dst - (adjust_rsp + 1); - dst = sub_ir(dst, 8, RSP, SZ_Q); + dst = sub_ir(dst, 8, RSP, SZ_PTR); dst = call(dst, cfun); - dst = add_ir(dst, 8, RSP, SZ_Q); + dst = add_ir(dst, 8, RSP, SZ_PTR); *no_adjust = dst - (no_adjust + 1); +#else if (is_write) { - dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); + dst = push_r(dst, SCRATCH1); + } else { + dst = push_r(dst, CONTEXT);//save CONTEXT for later + } + dst = push_r(dst, CONTEXT); + dst = push_r(dst, is_write ? SCRATCH2 : SCRATCH1); + dst = call(dst, cfun); + dst = add_ir(dst, is_write ? 12 : 8, RSP, SZ_D); +#endif + if (is_write) { + dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); } else { dst = pop_r(dst, CONTEXT); dst = mov_rr(dst, RAX, SCRATCH1, size); @@ -4412,7 +4450,7 @@ if (size == SZ_B) { dst = xor_ir(dst, 1, adr_reg, SZ_D); } - dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_Q); + dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_PTR); if (is_write) { dst = mov_rrind(dst, SCRATCH1, SCRATCH2, size); @@ -4442,21 +4480,21 @@ dst = shr_ir(dst, 8, SCRATCH1, SZ_W); } } - if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) { + if ((intptr_t)memmap[chunk].buffer <= 0x7FFFFFFF && (intptr_t)memmap[chunk].buffer >= -2147483648) { if (is_write) { - dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (int64_t)memmap[chunk].buffer, tmp_size); + dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (intptr_t)memmap[chunk].buffer, tmp_size); } else { - dst = mov_rdisp32r(dst, SCRATCH1, (int64_t)memmap[chunk].buffer, SCRATCH1, tmp_size); + dst = mov_rdisp32r(dst, SCRATCH1, (intptr_t)memmap[chunk].buffer, SCRATCH1, tmp_size); } } else { if (is_write) { dst = push_r(dst, SCRATCH1); - dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_Q); - dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_Q); + dst = mov_ir(dst, (intptr_t)memmap[chunk].buffer, SCRATCH1, SZ_PTR); + dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_PTR); dst = pop_r(dst, SCRATCH1); dst = mov_rrind(dst, SCRATCH1, SCRATCH2, tmp_size); } else { - dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH2, SZ_Q); + dst = mov_ir(dst, (intptr_t)memmap[chunk].buffer, SCRATCH2, SZ_PTR); dst = mov_rindexr(dst, SCRATCH2, SCRATCH1, 1, SCRATCH1, tmp_size); } } @@ -4476,14 +4514,22 @@ uint8_t * not_code = dst+1; dst = jcc(dst, CC_NC, dst+2); dst = call(dst, opts->save_context); +#ifdef X86_32 + dst = push_r(dst, CONTEXT); + dst = push_r(dst, SCRATCH2); +#endif dst = call(dst, (uint8_t *)m68k_handle_code_write); - dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); +#ifdef X86_32 + dst = add_ir(dst, 8, RSP, SZ_D); +#endif + dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); dst = call(dst, opts->load_context); *not_code = dst - (not_code+1); } dst = retn(dst); } else if (cfun) { dst = call(dst, opts->save_context); +#ifdef X86_64 if (is_write) { if (SCRATCH2 != RDI) { dst = mov_rr(dst, SCRATCH2, RDI, SZ_D); @@ -4500,12 +4546,23 @@ uint8_t *no_adjust = dst+1; dst = jmp(dst, dst+2); *adjust_rsp = dst - (adjust_rsp + 1); - dst = sub_ir(dst, 8, RSP, SZ_Q); + dst = sub_ir(dst, 8, RSP, SZ_PTR); dst = call(dst, cfun); - dst = add_ir(dst, 8, RSP, SZ_Q); + dst = add_ir(dst, 8, RSP, SZ_PTR); *no_adjust = dst - (no_adjust+1); +#else if (is_write) { - dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); + dst = push_r(dst, SCRATCH1); + } else { + dst = push_r(dst, CONTEXT);//save CONTEXT for later + } + dst = push_r(dst, CONTEXT); + dst = push_r(dst, is_write ? SCRATCH2 : SCRATCH1); + dst = call(dst, cfun); + dst = add_ir(dst, is_write ? 12 : 8, RSP, SZ_D); +#endif + if (is_write) { + dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); } else { dst = pop_r(dst, CONTEXT); dst = mov_rr(dst, RAX, SCRATCH1, size); @@ -4611,8 +4668,9 @@ dst = retn(dst); opts->start_context = (start_fun)dst; +#ifdef X86_64 if (SCRATCH2 != RDI) { - dst = mov_rr(dst, RDI, SCRATCH2, SZ_Q); + dst = mov_rr(dst, RDI, SCRATCH2, SZ_PTR); } //save callee save registers dst = push_r(dst, RBP); @@ -4620,24 +4678,49 @@ dst = push_r(dst, R13); dst = push_r(dst, R14); dst = push_r(dst, R15); +#else + //save callee save registers + dst = push_r(dst, RBP); + dst = push_r(dst, RBX); + dst = push_r(dst, RSI); + dst = push_r(dst, RDI); + + dst = mov_rdisp8r(dst, RSP, 20, SCRATCH2, SZ_D); + dst = mov_rdisp8r(dst, RSP, 24, CONTEXT, SZ_D); +#endif dst = call(dst, opts->load_context); dst = call_r(dst, SCRATCH2); dst = call(dst, opts->save_context); +#ifdef X86_64 //restore callee save registers dst = pop_r(dst, R15); dst = pop_r(dst, R14); dst = pop_r(dst, R13); dst = pop_r(dst, R12); dst = pop_r(dst, RBP); +#else + dst = pop_r(dst, RDI); + dst = pop_r(dst, RSI); + dst = pop_r(dst, RBX); + dst = pop_r(dst, RBP); +#endif dst = retn(dst); opts->native_addr = dst; dst = call(dst, opts->save_context); dst = push_r(dst, CONTEXT); - dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); //move context to 1st arg reg +#ifdef X86_64 + dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); //move context to 1st arg reg dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); //move address to 2nd arg reg +#else + dst = push_r(dst, SCRATCH1); + dst = push_r(dst, CONTEXT); +#endif dst = call(dst, (uint8_t *)get_native_address_trans); - dst = mov_rr(dst, RAX, SCRATCH1, SZ_Q); //move result to scratch reg +#ifdef X86_32 + dst = add_ir(dst, 8, RSP, SZ_D); +#endif + dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg dst = pop_r(dst, CONTEXT); dst = call(dst, opts->load_context); dst = retn(dst); @@ -4645,24 +4728,40 @@ opts->native_addr_and_sync = dst; dst = call(dst, opts->save_context); dst = push_r(dst, SCRATCH1); - dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); +#ifdef X86_64 + dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); dst = xor_rr(dst, RSI, RSI, SZ_D); - dst = test_ir(dst, 8, RSP, SZ_Q); //check stack alignment + dst = test_ir(dst, 8, RSP, SZ_PTR); //check stack alignment uint8_t * do_adjust_rsp = dst+1; dst = jcc(dst, CC_NZ, dst+2); dst = call(dst, (uint8_t *)sync_components); uint8_t * no_adjust_rsp = dst+1; dst = jmp(dst, dst+2); *do_adjust_rsp = dst - (do_adjust_rsp+1); - dst = sub_ir(dst, 8, RSP, SZ_Q); + dst = sub_ir(dst, 8, RSP, SZ_PTR); dst = call(dst, (uint8_t *)sync_components); - dst = add_ir(dst, 8, RSP, SZ_Q); + dst = add_ir(dst, 8, RSP, SZ_PTR); *no_adjust_rsp = dst - (no_adjust_rsp+1); dst = pop_r(dst, RSI); dst = push_r(dst, RAX); - dst = mov_rr(dst, RAX, RDI, SZ_Q); + dst = mov_rr(dst, RAX, RDI, SZ_PTR); dst = call(dst, (uint8_t *)get_native_address_trans); - dst = mov_rr(dst, RAX, SCRATCH1, SZ_Q); //move result to scratch reg +#else + //TODO: Add support for pushing a constant in gen_x86 + dst = xor_rr(dst, RAX, RAX, SZ_D); + dst = push_r(dst, RAX); + dst = push_r(dst, CONTEXT); + dst = call(dst, (uint8_t *)sync_components); + dst = add_ir(dst, 8, RSP, SZ_D); + dst = pop_r(dst, RSI); //restore saved address from SCRATCH1 + dst = push_r(dst, RAX); //save context pointer for later + dst = push_r(dst, RSI); //2nd arg -- address + dst = push_r(dst, RAX); //1st arg -- context pointer + dst = call(dst, (uint8_t *)get_native_address_trans); + dst = add_ir(dst, 8, RSP, SZ_D); +#endif + + dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg dst = pop_r(dst, CONTEXT); dst = call(dst, opts->load_context); dst = retn(dst); @@ -4675,7 +4774,8 @@ dst = push_r(dst, SCRATCH1); dst = push_r(dst, SCRATCH2); dst = call(dst, opts->save_context); - dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); +#ifdef X86_64 + dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); dst = xor_rr(dst, RSI, RSI, SZ_D); dst = test_ir(dst, 8, RSP, SZ_D); uint8_t *adjust_rsp = dst+1; @@ -4684,11 +4784,19 @@ uint8_t *no_adjust = dst+1; dst = jmp(dst, dst+2); *adjust_rsp = dst - (adjust_rsp + 1); - dst = sub_ir(dst, 8, RSP, SZ_Q); + dst = sub_ir(dst, 8, RSP, SZ_PTR); dst = call(dst, (uint8_t *)sync_components); - dst = add_ir(dst, 8, RSP, SZ_Q); + dst = add_ir(dst, 8, RSP, SZ_PTR); *no_adjust = dst - (no_adjust+1); - dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); +#else + //TODO: Add support for pushing a constant in gen_x86 + dst = xor_rr(dst, RAX, RAX, SZ_D); + dst = push_r(dst, RAX); + dst = push_r(dst, CONTEXT); + dst = call(dst, (uint8_t *)sync_components); + dst = add_ir(dst, 8, RSP, SZ_D); +#endif + dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); dst = call(dst, opts->load_context); dst = pop_r(dst, SCRATCH2); dst = pop_r(dst, SCRATCH1); @@ -4806,7 +4914,8 @@ skip_sync = dst+1; dst = jcc(dst, CC_C, dst+2); dst = call(dst, opts->save_context); - dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); +#ifdef X86_64 + dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); dst = test_ir(dst, 8, RSP, SZ_D); adjust_rsp = dst+1; @@ -4815,11 +4924,17 @@ no_adjust = dst+1; dst = jmp(dst, dst+2); *adjust_rsp = dst - (adjust_rsp + 1); - dst = sub_ir(dst, 8, RSP, SZ_Q); + dst = sub_ir(dst, 8, RSP, SZ_PTR); dst = call(dst, (uint8_t *)sync_components); - dst = add_ir(dst, 8, RSP, SZ_Q); + dst = add_ir(dst, 8, RSP, SZ_PTR); *no_adjust = dst - (no_adjust+1); - dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); +#else + dst = push_r(dst, SCRATCH1); + dst = push_r(dst, CONTEXT); + dst = call(dst, (uint8_t *)sync_components); + dst = add_ir(dst, 8, RSP, SZ_D); +#endif + dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR); dst = jmp(dst, opts->load_context); *skip_sync = dst - (skip_sync+1); dst = retn(dst); diff -r 32da1e0d5e55 -r 96489fb27dbf runtime_32.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/runtime_32.S Wed Feb 19 00:22:27 2014 -0800 @@ -0,0 +1,74 @@ + + +invalid_msg: + .asciz "Invalid instruction at %X\n" + + .global m68k_invalid +m68k_invalid: + push %ecx + push invalid_msg + xor %eax, %eax + call printf + push $1 + call exit + + .global bcd_add +bcd_add: + xchg %eax, %edi + + mov %cl, %ch + mov %al, %ah + and $0xF, %ch + and $0xF, %ah + and $0xF0, %cl + and $0xF0, %al + add %ah, %ch + cmp $10, %ch + jb no_adjust + add $6, %ch +no_adjust: + add %ch, %al + add %al, %cl + mov $0, %ch + jc def_adjust + cmp $0xA0, %cl + jb no_adjust_h +def_adjust: + add $0x60, %cl + mov $1, %ch +no_adjust_h: + + mov %edi, %eax + ret + + .global bcd_sub +bcd_sub: + xchg %eax, %edi + + mov %cl, %ch + mov %al, %ah + and $0xF, %ch + and $0xF, %ah + and $0xF0, %cl + and $0xF0, %al + sub %ah, %ch + cmp $10, %ch + jb no_adjusts + sub $6, %ch +no_adjusts: + add %ch, %cl + sub %al, %cl + mov $0, %ch + jc def_adjusts + cmp $0xA0, %cl + jb no_adjust_hs +def_adjusts: + sub $0x60, %cl + mov $1, %ch +no_adjust_hs: + + mov %edi, %eax + ret + + +