summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2013-05-02 21:54:04 -0700
committerMike Pavone <pavone@retrodev.com>2013-05-02 21:54:04 -0700
commit6705b8290babee89f7561eeb120694a98ef98f38 (patch)
treecf5d0b783595f6642792e709bcd9789473ca9a88
parentcb7600f819e01e4f6f5e6a9fad7e2331e37e5bc3 (diff)
Sync Z80 on writes to busreq/reset ports. NULL out extra_pc on z80 reset
-rw-r--r--blastem.c33
-rw-r--r--z80_to_x86.c54
2 files changed, 64 insertions, 23 deletions
diff --git a/blastem.c b/blastem.c
index 2e210a5..9b3ff58 100644
--- a/blastem.c
+++ b/blastem.c
@@ -134,12 +134,14 @@ uint8_t busack = 0;
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 @@ m68k_context * sync_components(m68k_context * context, uint32_t address)
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 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value
}
} 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 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value
}
} 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 @@ m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value
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 @@ m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t va
} 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 @@ m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t va
}
} 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 @@ m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t va
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 --git a/z80_to_x86.c b/z80_to_x86.c
index 63f56d2..4eeb84b 100644
--- a/z80_to_x86.c
+++ b/z80_to_x86.c
@@ -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 @@ uint8_t * translate_z80_reg(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_
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 @@ uint8_t * z80_save_reg(uint8_t * dst, z80inst * inst, x86_z80_options * opts)
{
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 @@ uint8_t * z80_get_native_address(z80_context * context, uint32_t address)
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 @@ z80_context * z80_handle_code_write(uint32_t address, z80_context * context)
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 @@ void * z80_retranslate_inst(uint32_t address, z80_context * context)
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 @@ void translate_z80_stream(z80_context * context, uint32_t address)
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 @@ void translate_z80_stream(z80_context * context, uint32_t address)
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 @@ void translate_z80_stream(z80_context * context, uint32_t address)
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 @@ void z80_reset(z80_context * context)
context->im = 0;
context->iff1 = context->iff2 = 0;
context->native_pc = z80_get_native_address_trans(context, 0);
+ context->extra_pc = NULL;
}