# HG changeset patch # User Mike Pavone # Date 1367556844 25200 # Node ID 6c2d7e003a55fb0ea213053ea03e52261ec2a230 # Parent 1788e3f29c2883b430e73c3065eddc550ef993cc Sync Z80 on writes to busreq/reset ports. NULL out extra_pc on z80 reset diff -r 1788e3f29c28 -r 6c2d7e003a55 blastem.c --- a/blastem.c Thu May 02 00:10:24 2013 -0700 +++ b/blastem.c Thu May 02 21:54:04 2013 -0700 @@ -134,12 +134,14 @@ uint32_t busack_cycle = CYCLE_NEVER; uint8_t new_busack = 0; -m68k_context * sync_components(m68k_context * context, uint32_t address) +#ifdef DO_DEBUG_PRINT +#define dprintf printf +#else +#define dprintf +#endif + +void sync_z80(z80_context * z_context, uint32_t mclks) { - //TODO: Handle sync targets smaller than a single frame - z80_context * z_context = context->next_cpu; - vdp_context * v_context = context->video_context; - uint32_t mclks = context->current_cycle * MCLKS_PER_68K; if (z80_enabled && !reset && !busreq) { if (need_reset) { z80_reset(z_context); @@ -151,11 +153,20 @@ z_context->int_cycle = ZVINT_CYCLE; } z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; - //printf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); + dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); z80_run(z_context); - //printf("Z80 ran to cycle %d\n", z_context->current_cycle); + dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); } } +} + +m68k_context * sync_components(m68k_context * context, uint32_t address) +{ + //TODO: Handle sync targets smaller than a single frame + vdp_context * v_context = context->video_context; + z80_context * z_context = context->next_cpu; + uint32_t mclks = context->current_cycle * MCLKS_PER_68K; + sync_z80(z_context, mclks); if (mclks >= MCLKS_PER_FRAME) { //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); vdp_run_context(v_context, MCLKS_PER_FRAME); @@ -373,11 +384,13 @@ } } else { if (location == 0x1100) { + sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K); if (busack_cycle > context->current_cycle) { busack = new_busack; busack_cycle = CYCLE_NEVER; } if (value & 1) { + puts("bus requesting Z80"); busreq = 1; if(!reset) { busack_cycle = context->current_cycle + Z80_ACK_DELAY; @@ -385,6 +398,7 @@ } } else { if (busreq) { + puts("releasing z80 bus"); z80_context * z_context = context->next_cpu; //TODO: Add necessary delay between release of busreq and resumption of execution z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; @@ -394,6 +408,7 @@ busack = 1; } } else if (location == 0x1200) { + sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K); if (value & 1) { if (reset && busreq) { new_busack = 0; @@ -453,11 +468,13 @@ } else { //printf("IO Write of %X to %X @ %d\n", value, location, context->current_cycle); if (location == 0x1100) { + sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K); if (busack_cycle > context->current_cycle) { busack = new_busack; busack_cycle = CYCLE_NEVER; } if (value & 0x100) { + printf("bus requesting Z80 @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); busreq = 1; if(!reset) { busack_cycle = context->current_cycle + Z80_ACK_DELAY; @@ -465,6 +482,7 @@ } } else { if (busreq) { + printf("releasing Z80 bus @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); z80_context * z_context = context->next_cpu; //TODO: Add necessary delay between release of busreq and resumption of execution z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; @@ -474,6 +492,7 @@ busack = 1; } } else if (location == 0x1200) { + sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K); if (value & 0x100) { if (reset && busreq) { new_busack = 0; diff -r 1788e3f29c28 -r 6c2d7e003a55 z80_to_x86.c --- a/z80_to_x86.c Thu May 02 00:10:24 2013 -0700 +++ b/z80_to_x86.c Thu May 02 21:54:04 2013 -0700 @@ -15,6 +15,12 @@ #define SCRATCH2 R14 #define CONTEXT RSI +#ifdef DO_DEBUG_PRINT +#define dprintf printf +#else +#define dprintf +#endif + void z80_read_byte(); void z80_read_word(); void z80_write_byte(); @@ -114,10 +120,16 @@ dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); } else if(opts->regs[inst->reg] >= 0) { ea->base = opts->regs[inst->reg]; - if (ea->base >= AH && ea->base <= BH && (inst->addr_mode & 0x1F) == Z80_REG) { - uint8_t other_reg = opts->regs[inst->ea_reg]; - if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { - //we can't mix an *H reg with a register that requires the REX prefix + if (ea->base >= AH && ea->base <= BH) { + if ((inst->addr_mode & 0x1F) == Z80_REG) { + uint8_t other_reg = opts->regs[inst->ea_reg]; + if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { + //we can't mix an *H reg with a register that requires the REX prefix + ea->base = opts->regs[z80_low_reg(inst->reg)]; + dst = ror_ir(dst, 8, ea->base, SZ_W); + } + } else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) { + //temp regs require REX prefix too ea->base = opts->regs[z80_low_reg(inst->reg)]; dst = ror_ir(dst, 8, ea->base, SZ_W); } @@ -135,10 +147,15 @@ { if (inst->reg == Z80_IYH) { dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); - } else if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) { - uint8_t other_reg = opts->regs[inst->ea_reg]; - if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { - //we can't mix an *H reg with a register that requires the REX prefix + } else if (opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) { + if ((inst->addr_mode & 0x1F) == Z80_REG) { + uint8_t other_reg = opts->regs[inst->ea_reg]; + if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) { + //we can't mix an *H reg with a register that requires the REX prefix + dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W); + } + } else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) { + //temp regs require REX prefix too dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W); } } @@ -1272,14 +1289,14 @@ address &= 0x7FFF; map = context->banked_code_map + (context->bank_reg << 15); } else { - printf("z80_get_native_address: %X NULL\n", address); + dprintf("z80_get_native_address: %X NULL\n", address); return NULL; } - if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET) { - printf("z80_get_native_address: %X NULL\n", address); + if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET || map->offsets[address] == EXTENSION_WORD) { + dprintf("z80_get_native_address: %X NULL\n", address); return NULL; } - printf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]); + dprintf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]); return map->base + map->offsets[address]; } @@ -1358,7 +1375,7 @@ uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); if (inst_start != INVALID_INSTRUCTION_START) { uint8_t * dst = z80_get_native_address(context, inst_start); - printf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address); + dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address); dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); dst = jmp(dst, (uint8_t *)z80_retrans_stub); } @@ -1399,14 +1416,16 @@ uint8_t * dst_end = opts->code_end; uint8_t *after, *inst = context->mem_pointers[0] + address; z80inst instbuf; - printf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); + dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); after = z80_decode(inst, &instbuf); + #ifdef DO_DEBUG_PRINT z80_disasm(&instbuf, disbuf); if (instbuf.op == Z80_NOP) { printf("%X\t%s(%d)\n", address, disbuf, instbuf.immed); } else { printf("%X\t%s\n", address, disbuf); } + #endif if (orig_size != ZMAX_NATIVE_SIZE) { if (dst_end - dst < ZMAX_NATIVE_SIZE) { size_t size = 1024*1024; @@ -1464,7 +1483,7 @@ while (encoded != NULL) { z80inst inst; - printf("translating Z80 code at address %X\n", address); + dprintf("translating Z80 code at address %X\n", address); do { if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { if (opts->code_end-opts->cur_code < 5) { @@ -1487,12 +1506,14 @@ break; } next = z80_decode(encoded, &inst); + #ifdef DO_DEBUG_PRINT z80_disasm(&inst, disbuf); if (inst.op == Z80_NOP) { printf("%X\t%s(%d)\n", address, disbuf, inst.immed); } else { printf("%X\t%s\n", address, disbuf); } + #endif uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address); z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code); opts->cur_code = after; @@ -1507,7 +1528,7 @@ process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address); if (opts->deferred) { address = opts->deferred->address; - printf("defferred address: %X\n", address); + dprintf("defferred address: %X\n", address); if (address < 0x4000) { encoded = context->mem_pointers[0] + (address & 0x1FFF); } else if (address > 0x8000 && context->mem_pointers[1]) { @@ -1570,6 +1591,7 @@ context->im = 0; context->iff1 = context->iff2 = 0; context->native_pc = z80_get_native_address_trans(context, 0); + context->extra_pc = NULL; }