# HG changeset patch # User Mike Pavone # Date 1366176540 25200 # Node ID 4d4559b04c59f3346930af4e041df7a706bcc7c9 # Parent e657a99b5abfd30e17e18ec2e6a0cab807746262 Make reset trigger debug exit to make it easier to test the same cases in blastem and musashi. Fix asl #1 overflow flag. diff -r e657a99b5abf -r 4d4559b04c59 m68k_to_x86.c --- a/m68k_to_x86.c Tue Apr 16 09:38:30 2013 -0700 +++ b/m68k_to_x86.c Tue Apr 16 22:29:00 2013 -0700 @@ -2640,6 +2640,7 @@ } else { dst = shift_irdisp8(dst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size); } + dst = setcc_r(dst, CC_O, FLAG_V); } } else { if (src_op->base != RCX) { @@ -3432,7 +3433,11 @@ } } break; - /*case M68K_RESET:*/ + case M68K_RESET: + dst = call(dst, (uint8_t *)m68k_save_context); + dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); + dst = call(dst, (uint8_t *)print_regs_exit); + break; case M68K_ROL: case M68K_ROR: dst = mov_ir(dst, 0, FLAG_V, SZ_B); diff -r e657a99b5abf -r 4d4559b04c59 z80_to_x86.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/z80_to_x86.c Tue Apr 16 22:29:00 2013 -0700 @@ -0,0 +1,369 @@ +#include "z80_to_x86.h" +#include "gen_x86.h" + +#define MODE_UNUSED (MODE_IMMED-1) + +#define ZCYCLES RBP +#define SCRATCH1 R13 +#define SCRATCH2 R14 + +void z80_read_byte(); +void z80_read_word(); + +uint8_t z80_size(z80_inst * inst) +{ + uint8_t reg = (inst->reg & 0x1F); + if (reg != Z80_UNUSED &&) { + return reg < Z80_BC ? SZ_B : SZ_W; + } + //TODO: Handle any necessary special cases + return SZ_B; +} + +uint8_t * zcylces(dst, uint32_t num_cycles) +{ + return add_ir(dst, num_cycles, ZCYCLES, SZ_D); +} + +uint8_t * translate_z80_reg(z80_inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_options * opts) +{ + if (inst->reg == Z80_USE_IMMED) { + ea->mode = MODE_IMMED; + ea->disp = inst->immed; + } else if ((inst->reg & 0x1F) == Z80_UNUSED) { + ea->mode = MODE_UNUSED; + } else { + ea->mode = MODE_REG; + if (inst->reg == Z80_IYH) { + ea->base = opts->regs[Z80_IYL]; + dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); + } else { + ea->base = opts->regs[inst->reg] + } + } + return dst; +} + +uint8_t * save_z80_reg(uint8_t * dst, z80_inst * inst, x86_z80_options * opts) +{ + if (inst->reg == Z80_IYH) { + dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); + } + return dst; +} + +uint8_t * translate_z80_ea(z80_inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_options * opts, uint8_t read, uint8_t modify) +{ + uint8_t size, reg, areg; + ea->mode = MODE_REG; + areg = read ? SCRATCH1 : SCRATCH2; + switch(inst->addr_mode & 0x1F) + { + case Z80_REG: + if (inst->ea_reg == Z80_IYH) { + ea->base = opts->regs[Z80_IYL]; + dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); + } else { + ea->base = opts->regs[inst->ea_reg]; + } + break; + case Z80_REG_INDIRECT: + dst = mov_rr(dst, opts->regs[inst->ea_reg], areg, SZ_W); + size = z80_size(inst); + if (read) { + if (modify) { + dst = push_r(dst, SCRATCH1); + } + if (size == SZ_B) { + dst = call(dst, (uint8_t *)z80_read_byte); + } else { + dst = call(dst, (uint8_t *)z80_read_word); + } + if (modify) { + dst = pop_r(dst, SCRATCH2); + } + } + ea->base = SCRATCH1; + break; + case Z80_IMMED: + ea->mode = MODE_IMMED; + ea->disp = inst->immed; + break; + case Z80_IMMED_INDIRECT: + dst = mov_ir(dst, inst->immed, areg, SZ_W); + size = z80_size(inst); + if (read) { + if (modify) { + dst = push_r(dst, SCRATCH1); + } + if (size == SZ_B) { + dst = call(dst, (uint8_t *)z80_read_byte); + } else { + dst = call(dst, (uint8_t *)z80_read_word); + } + if (modify) { + dst = pop_r(dst, SCRATCH2); + } + } + ea->base = SCRATCH1; + break; + case Z80_IX_INDEXED: + case Z80_IY_INDEXED: + reg = opts->regs[inst->addr_mode == Z80_IX_INDEXED ? Z80_IX : Z80_IY]; + dst = mov_rr(dst, reg, areg, SZ_W); + dst = add_ir(dst, inst->immed, areg, SZ_W); + size = z80_size(inst); + if (read) { + if (modify) { + dst = push_r(dst, SCRATCH1); + } + if (size == SZ_B) { + dst = call(dst, (uint8_t *)z80_read_byte); + } else { + dst = call(dst, (uint8_t *)z80_read_word); + } + if (modify) { + dst = pop_r(dst, SCRATCH2); + } + } + break; + case Z80_UNUSED: + ea->mode = MODE_UNUSED: + break; + default: + fprintf(stderr, "Unrecognized Z80 addressing mode %d\n", inst->addr_mode); + exit(1); + } + return dst; +} + +uint8_t * z80_save_ea(uint8_t * dst, z80_inst * inst, x86_z80_options * opts) +{ + if (inst->addr_mode == Z80_REG_DIRECT && inst->ea_reg == Z80_IYH) { + dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); + } + return dst; +} + +uint8_t * z80_save_result(uint8_t * dst, z80_inst * inst) +{ + if (z80_size(inst). == SZ_B) { + dst = call(dst, (uint8_t *)z80_write_byte); + } else { + dst = call(dst, (uint8_t *)z80_write_word); + } + return dst; +} + +enum { + DONT_READ=0, + READ +}; + +enum { + DONT_MODIFY=0, + MODIFY +}; + +uint8_t zf_off(uint8_t flag) +{ + return offsetof(z80_context, flags) + flag; +} + +uint8_t * translate_z80_inst(z80_inst * inst, uint8_t * dst, x86_z80_options * opts) +{ + uint32_t cycles; + x86_ea src_op, dst_op; + switch(inst->op) + { + case Z80_LD: + if (inst->addr_mode & Z80_DIR) { + dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); + dst = translate_z80_reg(inst, &dst_op, dst, opts); + } else { + dst = translate_z80_reg(inst, &src_op, dst, opts); + dst = translate_z80_ea(inst, &dst_op, dst, opts, DONT_READ, MODIFY); + } + if (ea_op.mode == MODE_REG_DIRECT) { + dst = mov_rr(dst, ea_op.base, reg_op.base, z80_size(inst)); + } else { + dst = mov_ir(dst, ea_op.disp, reg_op.base, z80_size(inst)); + } + dst = z80_save_reg(dst, inst, opts); + dst = z80_save_ea(dst, inst, opts); + if (!(inst->addr_mode & Z80_DIR)) { + dst = z80_save_result(dst, inst, opts); + } + break; + case Z80_PUSH: + dst = zcycles(dst, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5); + dst = sub_ir(dst, opts->regs[Z80_SP], SZ_W); + dst = translate_z80_reg(inst, &src_op, dst, opts); + dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_W); + dst = call(dst, z80_write_word); + break; + case Z80_POP: + dst = zcycles(dst, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4); + dst = sub_ir(dst, opts->regs[Z80_SP], SZ_W); + dst = translate_z80_reg(inst, &src_op, dst, opts); + dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_W); + dst = call(dst, z80_write_word); + break; + /*case Z80_EX: + case Z80_EXX: + case Z80_LDI: + case Z80_LDIR: + case Z80_LDD: + case Z80_LDDR: + case Z80_CPI: + case Z80_CPIR: + case Z80_CPD: + case Z80_CPDR: + break;*/ + case Z80_ADD: + cycles = 4; + if (inst->addr_mode == Z80_IX_INDIRECT || inst->addr_mdoe == Z80_IY_INDIRECT) { + cycles += 12; + } else if(inst->addr_mode == Z80_IMMED) { + cycles += 3; + } else if(z80_size(inst) == SZ_W) { + cycles += 4; + } + dst = zcycles(dst, cycles); + dst = translate_z80_reg(inst, &dst_op, dst, opts); + dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); + if (src_op.mode == MODE_REG_DIRECT) { + dst = add_rr(dst, src_op.base, dst_op.base, z80_size(inst)); + } else { + dst = add_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); + } + dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N)); + //TODO: Implement half-carry flag + if (z80_size(inst) == SZ_B) { + dst = setcc_rdisp8(dst, CC_O, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, zf_off(ZF_S)); + } + dst = z80_save_reg(dst, inst, opts); + dst = z80_save_ea(dst, inst, opts); + break; + /*case Z80_ADC: + break;*/ + case Z80_SUB: + cycles = 4; + if (inst->addr_mode == Z80_IX_INDIRECT || inst->addr_mdoe == Z80_IY_INDIRECT) { + cycles += 12; + } else if(inst->addr_mode == Z80_IMMED) { + cycles += 3; + } + dst = zcycles(dst, cycles); + dst = translate_z80_reg(inst, &dst_op, dst, opts); + dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); + if (src_op.mode == MODE_REG_DIRECT) { + dst = sub_rr(dst, src_op.base, dst_op.base, z80_size(inst)); + } else { + dst = sub_ir(dst, src_op.disp, dst_op.base, z80_size(inst)); + } + dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_N)); + dst = setcc_rdisp8(dst, CC_O, zf_off(ZF_PV)); + //TODO: Implement half-carry flag + dst = setcc_rdisp8(dst, CC_Z, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, zf_off(ZF_S) + dst = z80_save_reg(dst, inst, opts); + dst = z80_save_ea(dst, inst, opts); + break; + /*case Z80_SBC: + case Z80_AND: + case Z80_OR: + case Z80_XOR: + case Z80_CP:*/ + case Z80_INC: + cycles = 4; + if (inst->reg == Z80_IX || inst->reg == Z80_IY) { + cycles += 6; + } else if(z80_size(inst) == SZ_W) { + cycles += 2; + } else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + cycles += 4; + } + dst = translate_z80_reg(inst, &dst_op, dst, opts); + if (dst_op.mode == MODE_UNUSED) { + dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); + } + dst = add_ir(dst, 1, dst_op.base, z80_size(inst)); + if (z80_size(inst) == SZ_B) { + dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N)); + //TODO: Implement half-carry flag + dst = setcc_rdisp8(dst, CC_O, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, zf_off(ZF_S)); + } + dst = z80_save_reg(dst, inst, opts); + dst = z80_save_ea(dst, inst, opts); + break; + /*case Z80_DEC: + break; + case Z80_DAA: + case Z80_CPL: + case Z80_NEG: + case Z80_CCF: + case Z80_SCF:*/ + case Z80_NOP: + if (inst->immed == 42) { + dst = call(dst, (uint8_t *)z80_save_context); + dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); + dst = jmp(dst, (uint8_t *)z80_print_regs_exit); + } else { + dst = zcycles(dst, 4 * inst->immed); + } + break; + /*case Z80_HALT: + case Z80_DI: + case Z80_EI: + case Z80_IM: + case Z80_RLC: + case Z80_RL: + case Z80_RRC: + case Z80_RR: + case Z80_SLA: + case Z80_SRA: + case Z80_SLL: + case Z80_SRL: + case Z80_RLD: + case Z80_RRD: + case Z80_BIT: + case Z80_SET: + case Z80_RES: + case Z80_JP: + case Z80_JPCC: + case Z80_JR: + case Z80_JRCC: + case Z80_DJNZ: + case Z80_CALL: + case Z80_CALLCC: + case Z80_RET: + case Z80_RETCC: + case Z80_RETI: + case Z80_RETN: + case Z80_RST: + case Z80_IN: + case Z80_INI: + case Z80_INIR: + case Z80_IND: + case Z80_INDR: + case Z80_OUT: + case Z80_OUTI: + case Z80_OTIR: + case Z80_OUTD: + case Z80_OTDR:*/ + default: + fprintf(stderr, "unimplemented instruction: %d\n", inst->op); + exit(1); + } +} + +void translate_z80_stream(z80_context * context, uint16_t address) +{ +} diff -r e657a99b5abf -r 4d4559b04c59 z80_to_x86.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/z80_to_x86.h Tue Apr 16 22:29:00 2013 -0700 @@ -0,0 +1,39 @@ +#ifndef Z80_TO_X86_H_ +#define Z80_TO_X86_H_ +#include "z80inst.h" +#include "x86_backend.h" + +#define ZNUM_MEM_AREAS 4 + +enum { + ZF_C = 0, + ZF_N, + ZF_PV, + ZF_H, + ZF_Z, + ZF_S, + ZF_NUM +}; + +typedef struct { + uint32_t flags; + int8_t regs[Z80_UNUSED]; +} x86_z80_options; + +typedef struct { + void * native_pc; + uint16_t sp; + uint8_t flags[ZF_NUM]; + uint16_t bank_reg; + uint8_t regs[Z80_A+1]; + uint8_t alt_regs[Z80_A+1]; + uint8_t * mem_pointers[ZNUM_MEM_AREAS]; + native_map_slot * native_code_map; + void * options + void * next_context; +} z80_context; + +void translate_z80_stream(z80_context * context, uint16_t address); + +#endif //Z80_TO_X86_H_ + diff -r e657a99b5abf -r 4d4559b04c59 z80inst.c --- a/z80inst.c Tue Apr 16 09:38:30 2013 -0700 +++ b/z80inst.c Tue Apr 16 22:29:00 2013 -0700 @@ -1118,7 +1118,9 @@ NOP2, NOP2, NOP2, - NOP2 + //TODO: Enable this based on a define + {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 42} + //NOP2 }; #define SHIFT_BLOCK_IY(op) \ @@ -1342,14 +1344,13 @@ "e", "h", "l", - "", - "a", "ixh", "ixl", "iyh", "iyl", "i", "r", + "a", "bc", "de", "hl", diff -r e657a99b5abf -r 4d4559b04c59 z80inst.h --- a/z80inst.h Tue Apr 16 09:38:30 2013 -0700 +++ b/z80inst.h Tue Apr 16 22:29:00 2013 -0700 @@ -78,13 +78,13 @@ Z80_E, Z80_H, Z80_L, - Z80_A=7, Z80_IXH, Z80_IXL, Z80_IYH, Z80_IYL, Z80_I, Z80_R, + Z80_A, Z80_BC, Z80_DE, Z80_HL,