summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2016-12-28 20:39:27 -0800
committerMichael Pavone <pavone@retrodev.com>2016-12-28 20:39:27 -0800
commit67b7c359a5a73f01eeba37af2d5fbae1027b4a7a (patch)
treef2542e2c1a6fc6ae59792e22cbc265e4267d78b6
parent96d5581219aec6c49fadaaf1d30623c0f2eed358 (diff)
Remove memory map assumptions from Z80 core and move a little bit of logic to the generic backend.c so it can be shared between CPU cores
-rw-r--r--backend.c17
-rw-r--r--backend.h1
-rw-r--r--blastcpm.c16
-rw-r--r--debug.c2
-rw-r--r--genesis.c5
-rw-r--r--m68k_core.c99
-rw-r--r--m68k_core.h3
-rw-r--r--m68k_core_x86.c3
-rw-r--r--sms.c3
-rw-r--r--transz80.c94
-rw-r--r--z80_to_x86.c159
-rw-r--r--z80_to_x86.h6
-rw-r--r--ztestrun.c46
13 files changed, 188 insertions, 266 deletions
diff --git a/backend.c b/backend.c
index c42a7a0..00a2d03 100644
--- a/backend.c
+++ b/backend.c
@@ -51,6 +51,23 @@ void process_deferred(deferred_addr ** head_ptr, void * context, native_addr_fun
}
}
+memmap_chunk const *find_map_chunk(uint32_t address, cpu_options *opts, uint16_t flags, uint32_t *size_sum)
+{
+ if (size_sum) {
+ *size_sum = 0;
+ }
+ address &= opts->address_mask;
+ for (memmap_chunk const *cur = opts->memmap, *end = opts->memmap + opts->memmap_chunks; cur != end; cur++)
+ {
+ if (address >= cur->start && address < cur->end) {
+ return cur;
+ } else if (size_sum && (cur->flags & flags) == flags) {
+ *size_sum += chunk_size(opts, cur);
+ }
+ }
+ return NULL;
+}
+
void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts)
{
memmap_chunk const * memmap = opts->memmap;
diff --git a/backend.h b/backend.h
index 89e5e2e..ae80846 100644
--- a/backend.h
+++ b/backend.h
@@ -122,6 +122,7 @@ void log_address(cpu_options *opts, uint32_t address, char * format);
code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk const * memmap, uint32_t num_chunks, ftype fun_type, code_ptr *after_inc);
void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts);
+memmap_chunk const *find_map_chunk(uint32_t address, cpu_options *opts, uint16_t flags, uint32_t *size_sum);
uint32_t chunk_size(cpu_options *opts, memmap_chunk const *chunk);
uint32_t ram_size(cpu_options *opts);
diff --git a/blastcpm.c b/blastcpm.c
index c75c30d..72a53cc 100644
--- a/blastcpm.c
+++ b/blastcpm.c
@@ -62,13 +62,13 @@ void *exit_write(uint32_t address, void *context, uint8_t value)
}
const memmap_chunk z80_map[] = {
- { 0x0000, 0x10000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, NULL, NULL, NULL, NULL},
+ { 0x0000, 0x10000, 0xFFFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, NULL, NULL, NULL, NULL},
};
const memmap_chunk io_map[] = {
- { 0x0, 0x1, 0xFFFF, 0, 0, NULL, NULL, NULL, console_read, console_write},
- { 0x1, 0x2, 0xFFFF, 0, 0, NULL, NULL, NULL, console_status_read, console_flush_write},
- { 0x2, 0x3, 0xFFFF, 0, 0, NULL, NULL, NULL, NULL, exit_write},
+ { 0x0, 0x1, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, console_read, console_write},
+ { 0x1, 0x2, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, console_status_read, console_flush_write},
+ { 0x2, 0x3, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, NULL, exit_write},
};
int main(int argc, char **argv)
@@ -100,13 +100,13 @@ int main(int argc, char **argv)
ram[7] = OS_START >> 8;
z80_options opts;
- z80_context context;
+ z80_context *context;
init_z80_opts(&opts, z80_map, 1, io_map, 3, 1, 0xFF);
- init_z80_context(&context, &opts);
+ context = init_z80_context(&opts);
for(;;)
{
- z80_run(&context, 1000000);
- context.current_cycle = 0;
+ z80_run(context, 1000000);
+ context->current_cycle = 0;
}
return 0;
} \ No newline at end of file
diff --git a/debug.c b/debug.c
index e0b8d56..4c7dcd9 100644
--- a/debug.c
+++ b/debug.c
@@ -591,7 +591,7 @@ int run_debugger_command(m68k_context *context, char *input_buf, m68kinst inst,
uint8_t non_adr_count = 0;
do {
uint32_t bt_address = system->work_ram[stack/2] << 16 | system->work_ram[stack/2+1];
- bt_address = get_instruction_start(context->options, context->native_code_map, bt_address - 2);
+ bt_address = get_instruction_start(context->options, bt_address - 2);
if (bt_address) {
stack += 4;
non_adr_count = 0;
diff --git a/genesis.c b/genesis.c
index a3d3386..6343986 100644
--- a/genesis.c
+++ b/genesis.c
@@ -925,15 +925,16 @@ genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on
gen->psg = malloc(sizeof(psg_context));
psg_init(gen->psg, render_sample_rate(), gen->master_clock, MCLKS_PER_PSG, render_audio_buffer(), lowpass_cutoff);
- gen->z80 = calloc(1, sizeof(z80_context));
gen->zram = calloc(1, Z80_RAM_BYTES);
z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES);
#ifndef NO_Z80
z80_options *z_opts = malloc(sizeof(z80_options));
init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80, 0xFFFF);
- init_z80_context(gen->z80, z_opts);
+ gen->z80 = init_z80_context(z_opts);
gen->z80->next_int_pulse = z80_next_int_pulse;
z80_assert_reset(gen->z80, 0);
+#else
+ gen->z80 = calloc(1, sizeof(z80_context));
#endif
gen->z80->system = gen;
diff --git a/m68k_core.c b/m68k_core.c
index c6b8d17..f2ffd29 100644
--- a/m68k_core.c
+++ b/m68k_core.c
@@ -560,16 +560,12 @@ static void translate_m68k_rte(m68k_options *opts, m68kinst *inst)
code_ptr get_native_address(m68k_options *opts, uint32_t address)
{
native_map_slot * native_code_map = opts->gen.native_code_map;
- address &= opts->gen.address_mask;
- //TODO: Refactor part of this loop into some kind of get_ram_chunk function
- for (int i = 0; i < opts->gen.memmap_chunks; i++) {
- if (address >= opts->gen.memmap[i].start && address < opts->gen.memmap[i].end) {
- //calculate the lowest alias for this address
- address = opts->gen.memmap[i].start + ((address - opts->gen.memmap[i].start) & opts->gen.memmap[i].mask);
- }
+ memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
+ if (mem_chunk) {
+ //calculate the lowest alias for this address
+ address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
}
-
uint32_t chunk = address / NATIVE_CHUNK_SIZE;
if (!native_code_map[chunk].base) {
return NULL;
@@ -586,16 +582,13 @@ code_ptr get_native_from_context(m68k_context * context, uint32_t address)
return get_native_address(context->options, address);
}
-uint32_t get_instruction_start(m68k_options *opts, native_map_slot * native_code_map, uint32_t address)
+uint32_t get_instruction_start(m68k_options *opts, uint32_t address)
{
- address &= opts->gen.address_mask;
- //TODO: Refactor part of this loop into some kind of get_ram_chunk function
- for (int i = 0; i < opts->gen.memmap_chunks; i++) {
- if (address >= opts->gen.memmap[i].start && address < opts->gen.memmap[i].end) {
- //calculate the lowest alias for this address
- address = opts->gen.memmap[i].start + ((address - opts->gen.memmap[i].start) & opts->gen.memmap[i].mask);
- break;
- }
+ native_map_slot * native_code_map = opts->gen.native_code_map;
+ memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
+ if (mem_chunk) {
+ //calculate the lowest alias for this address
+ address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
}
uint32_t chunk = address / NATIVE_CHUNK_SIZE;
@@ -606,7 +599,8 @@ uint32_t get_instruction_start(m68k_options *opts, native_map_slot * native_code
if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
return 0;
}
- while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD) {
+ while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD)
+ {
--address;
chunk = address / NATIVE_CHUNK_SIZE;
offset = address % NATIVE_CHUNK_SIZE;
@@ -616,38 +610,31 @@ uint32_t get_instruction_start(m68k_options *opts, native_map_slot * native_code
static void map_native_address(m68k_context * context, uint32_t address, code_ptr native_addr, uint8_t size, uint8_t native_size)
{
- native_map_slot * native_code_map = context->native_code_map;
m68k_options * opts = context->options;
- address &= opts->gen.address_mask;
- uint32_t meta_off = 0;
- //TODO: Refactor part of this loop into some kind of get_ram_chunk function
- for (int i = 0; i < opts->gen.memmap_chunks; i++) {
- if (address >= opts->gen.memmap[i].start && address < opts->gen.memmap[i].end) {
- if ((opts->gen.memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
- uint32_t masked = (address & opts->gen.memmap[i].mask);
- uint32_t final_off = masked + meta_off;
- uint32_t ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
- context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
-
- uint32_t slot = final_off / 1024;
- if (!opts->gen.ram_inst_sizes[slot]) {
- opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 512);
- }
- opts->gen.ram_inst_sizes[slot][(final_off/2) & 511] = native_size;
+ native_map_slot * native_code_map = opts->gen.native_code_map;
+ uint32_t meta_off;
+ memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_WRITE | MMAP_CODE, &meta_off);
+ if (mem_chunk) {
+ if ((mem_chunk->flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
+ uint32_t masked = (address & mem_chunk->mask);
+ uint32_t final_off = masked + meta_off;
+ uint32_t ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
+ context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
- //TODO: Deal with case in which end of instruction is in a different memory chunk
- masked = (address + size - 1) & opts->gen.memmap[i].mask;
- final_off = masked + meta_off;
- ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
- context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
+ uint32_t slot = final_off / 1024;
+ if (!opts->gen.ram_inst_sizes[slot]) {
+ opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 512);
}
- //calculate the lowest alias for this address
- address = opts->gen.memmap[i].start + ((address - opts->gen.memmap[i].start) & opts->gen.memmap[i].mask);
- break;
- } else if ((opts->gen.memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
- uint32_t size = chunk_size(&opts->gen, opts->gen.memmap + i);
- meta_off += size;
+ opts->gen.ram_inst_sizes[slot][(final_off/2) & 511] = native_size;
+
+ //TODO: Deal with case in which end of instruction is in a different memory chunk
+ masked = (address + size - 1) & mem_chunk->mask;
+ final_off = masked + meta_off;
+ ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
+ context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
}
+ //calculate the lowest alias for this address
+ address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
}
uint32_t chunk = address / NATIVE_CHUNK_SIZE;
@@ -676,19 +663,10 @@ static void map_native_address(m68k_context * context, uint32_t address, code_pt
static uint8_t get_native_inst_size(m68k_options * opts, uint32_t address)
{
- address &= opts->gen.address_mask;
- uint32_t meta_off = 0;
- for (int i = 0; i < opts->gen.memmap_chunks; i++) {
- if (address >= opts->gen.memmap[i].start && address < opts->gen.memmap[i].end) {
- if ((opts->gen.memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) != (MMAP_WRITE | MMAP_CODE)) {
- return 0;
- }
- meta_off += address & opts->gen.memmap[i].mask;
- break;
- } else if ((opts->gen.memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
- uint32_t size = chunk_size(&opts->gen, opts->gen.memmap + i);
- meta_off += size;
- }
+ uint32_t meta_off;
+ memmap_chunk const *chunk = find_map_chunk(address, &opts->gen, MMAP_WRITE | MMAP_CODE, &meta_off);
+ if (chunk) {
+ meta_off += (address - chunk->start) & chunk->mask;
}
uint32_t slot = meta_off/1024;
return opts->gen.ram_inst_sizes[slot][(meta_off/2)%512];
@@ -712,7 +690,7 @@ static void m68k_handle_deferred(m68k_context * context)
uint16_t m68k_get_ir(m68k_context *context)
{
- uint32_t inst_addr = get_instruction_start(context->options, context->native_code_map, context->last_prefetch_address-2);
+ uint32_t inst_addr = get_instruction_start(context->options, context->last_prefetch_address-2);
uint16_t *native_addr = get_native_pointer(inst_addr, (void **)context->mem_pointers, &context->options->gen);
if (native_addr) {
return *native_addr;
@@ -1065,7 +1043,6 @@ m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_ha
size_t ctx_size = sizeof(m68k_context) + ram_size(&opts->gen) / (1 << opts->gen.ram_flags_shift) / 8;
m68k_context * context = malloc(ctx_size);
memset(context, 0, ctx_size);
- context->native_code_map = opts->gen.native_code_map;
context->options = opts;
context->int_cycle = CYCLE_NEVER;
context->status = 0x27;
diff --git a/m68k_core.h b/m68k_core.h
index 4d3634e..1b1199e 100644
--- a/m68k_core.h
+++ b/m68k_core.h
@@ -63,7 +63,6 @@ typedef struct m68k_context {
uint16_t *mem_pointers[NUM_MEM_AREAS];
code_ptr resume_pc;
code_ptr reset_handler;
- native_map_slot *native_code_map;
m68k_options *options;
void *system;
uint8_t int_pending;
@@ -84,7 +83,7 @@ void m68k_options_free(m68k_options *opts);
void insert_breakpoint(m68k_context * context, uint32_t address, m68k_debug_handler bp_handler);
void remove_breakpoint(m68k_context * context, uint32_t address);
m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context);
-uint32_t get_instruction_start(m68k_options *opts, native_map_slot * native_code_map, uint32_t address);
+uint32_t get_instruction_start(m68k_options *opts, uint32_t address);
uint16_t m68k_get_ir(m68k_context *context);
void m68k_print_regs(m68k_context * context);
diff --git a/m68k_core_x86.c b/m68k_core_x86.c
index c1ba19d..0d68492 100644
--- a/m68k_core_x86.c
+++ b/m68k_core_x86.c
@@ -2266,8 +2266,7 @@ void nop_fill_or_jmp_next(code_info *code, code_ptr old_end, code_ptr next_inst)
m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context)
{
m68k_options * options = context->options;
- //TODO: Modify gen_mem_fun so that it passes the raw address instead of the masked one, then remove the OR below
- uint32_t inst_start = get_instruction_start(options, context->native_code_map, address);
+ uint32_t inst_start = get_instruction_start(options, address);
if (inst_start) {
code_info *code = &options->gen.code;
code_ptr dst = get_native_address(context->options, inst_start);
diff --git a/sms.c b/sms.c
index 79fb78b..11aeeba 100644
--- a/sms.c
+++ b/sms.c
@@ -212,8 +212,7 @@ sms_context *alloc_configure_sms(void *rom, uint32_t rom_size, void *extra_rom,
memcpy(info_out->map, memory_map, sizeof(memory_map));
z80_options *zopts = malloc(sizeof(z80_options));
init_z80_opts(zopts, info_out->map, 2, io_map, 4, 15, 0xFF);
- sms->z80 = malloc(sizeof(z80_context));
- init_z80_context(sms->z80, zopts);
+ sms->z80 = init_z80_context(zopts);
sms->z80->system = sms;
char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0").ptrval;
diff --git a/transz80.c b/transz80.c
deleted file mode 100644
index eec1736..0000000
--- a/transz80.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- Copyright 2013 Michael Pavone
- This file is part of BlastEm.
- BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
-*/
-#include "z80inst.h"
-#include "z80_to_x86.h"
-#include "mem.h"
-#include "vdp.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-uint8_t z80_ram[0x2000];
-uint16_t cart[0x200000];
-
-#define MCLKS_PER_Z80 15
-//TODO: Figure out the exact value for this
-#define MCLKS_PER_FRAME (MCLKS_LINE*262)
-#define VINT_CYCLE ((MCLKS_LINE * 226)/MCLKS_PER_Z80)
-#define CYCLE_NEVER 0xFFFFFFFF
-
-uint8_t z80_read_ym(uint16_t location, z80_context * context)
-{
- return 0xFF;
-}
-
-z80_context * z80_write_ym(uint16_t location, z80_context * context, uint8_t value)
-{
- return context;
-}
-
-z80_context * z80_vdp_port_write(uint16_t location, z80_context * context, uint8_t value)
-{
- return context;
-}
-
-int main(int argc, char ** argv)
-{
- long filesize;
- uint8_t *filebuf;
- z80_options opts;
- z80_context context;
- if (argc < 2) {
- fputs("usage: transz80 zrom [cartrom]\n", stderr);
- exit(1);
- }
- FILE * f = fopen(argv[1], "rb");
- if (!f) {
- fprintf(stderr, "unable to open file %s\n", argv[2]);
- exit(1);
- }
- fseek(f, 0, SEEK_END);
- filesize = ftell(f);
- fseek(f, 0, SEEK_SET);
- fread(z80_ram, 1, filesize < sizeof(z80_ram) ? filesize : sizeof(z80_ram), f);
- fclose(f);
- if (argc > 2) {
- f = fopen(argv[2], "rb");
- if (!f) {
- fprintf(stderr, "unable to open file %s\n", argv[2]);
- exit(1);
- }
- fseek(f, 0, SEEK_END);
- filesize = ftell(f);
- fseek(f, 0, SEEK_SET);
- fread(cart, 1, filesize < sizeof(cart) ? filesize : sizeof(cart), f);
- fclose(f);
- for(unsigned short * cur = cart; cur - cart < (filesize/2); ++cur)
- {
- *cur = (*cur >> 8) | (*cur << 8);
- }
- }
- init_z80_opts(&opts);
- init_z80_context(&context, &opts);
- //Z80 RAM
- context.mem_pointers[0] = z80_ram;
- context.sync_cycle = context.target_cycle = MCLKS_PER_FRAME/MCLKS_PER_Z80;
- context.int_cycle = CYCLE_NEVER;
- //cartridge/bank
- context.mem_pointers[1] = context.mem_pointers[2] = (uint8_t *)cart;
- z80_reset(&context);
- for(;;)
- {
- z80_run(&context);
- if (context.current_cycle >= MCLKS_PER_FRAME/MCLKS_PER_Z80) {
- context.current_cycle -= MCLKS_PER_FRAME/MCLKS_PER_Z80;
- }
- if (context.current_cycle < VINT_CYCLE && context.iff1) {
- context.int_cycle = VINT_CYCLE;
- }
- context.target_cycle = context.sync_cycle < context.int_cycle ? context.sync_cycle : context.int_cycle;
- }
- return 0;
-}
diff --git a/z80_to_x86.c b/z80_to_x86.c
index df7baeb..71d1dd2 100644
--- a/z80_to_x86.c
+++ b/z80_to_x86.c
@@ -15,6 +15,8 @@
#define MODE_UNUSED (MODE_IMMED-1)
#define MAX_MCYCLE_LENGTH 6
+#define NATIVE_CHUNK_SIZE 1024
+#define NATIVE_MAP_CHUNKS (0x10000 / NATIVE_CHUNK_SIZE)
//#define DO_DEBUG_PRINT
@@ -2881,94 +2883,120 @@ code_info z80_make_interp_stub(z80_context * context, uint16_t address)
uint8_t * z80_get_native_address(z80_context * context, uint32_t address)
{
- native_map_slot *map;
- if (address < 0x4000) {
- address &= 0x1FFF;
- map = context->static_code_map;
- } else {
- address -= 0x4000;
- map = context->banked_code_map;
+ z80_options *opts = context->options;
+ native_map_slot * native_code_map = opts->gen.native_code_map;
+
+ memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
+ if (mem_chunk) {
+ //calculate the lowest alias for this address
+ address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
+ }
+ uint32_t chunk = address / NATIVE_CHUNK_SIZE;
+ if (!native_code_map[chunk].base) {
+ return NULL;
}
- if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET || map->offsets[address] == EXTENSION_WORD) {
- //dprintf("z80_get_native_address: %X NULL\n", address);
+ uint32_t offset = address % NATIVE_CHUNK_SIZE;
+ if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET || native_code_map[chunk].offsets[offset] == EXTENSION_WORD) {
return NULL;
}
- //dprintf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]);
- return map->base + map->offsets[address];
+ return native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
}
uint8_t z80_get_native_inst_size(z80_options * opts, uint32_t address)
{
- //TODO: Fix for addresses >= 0x4000
- if (address >= 0x4000) {
- return 0;
+ uint32_t meta_off;
+ memmap_chunk const *chunk = find_map_chunk(address, &opts->gen, MMAP_WRITE | MMAP_CODE, &meta_off);
+ if (chunk) {
+ meta_off += (address - chunk->start) & chunk->mask;
}
- return opts->gen.ram_inst_sizes[0][address & 0x1FFF];
+ uint32_t slot = meta_off/1024;
+ return opts->gen.ram_inst_sizes[slot][meta_off%1024];
}
void z80_map_native_address(z80_context * context, uint32_t address, uint8_t * native_address, uint8_t size, uint8_t native_size)
{
uint32_t orig_address = address;
- native_map_slot *map;
+
z80_options * opts = context->options;
- if (address < 0x4000) {
- address &= 0x1FFF;
- map = context->static_code_map;
- opts->gen.ram_inst_sizes[0][address] = native_size;
- context->ram_code_flags[(address & 0x1C00) >> 10] |= 1 << ((address & 0x380) >> 7);
- context->ram_code_flags[((address + size) & 0x1C00) >> 10] |= 1 << (((address + size) & 0x380) >> 7);
- } else {
- //HERE
- address -= 0x4000;
- map = context->banked_code_map;
- if (!map->offsets) {
- map->offsets = malloc(sizeof(int32_t) * 0xC000);
- memset(map->offsets, 0xFF, sizeof(int32_t) * 0xC000);
- }
+ uint32_t meta_off;
+ memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_WRITE | MMAP_CODE, &meta_off);
+ if (mem_chunk) {
+ if ((mem_chunk->flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
+ uint32_t masked = (address & mem_chunk->mask);
+ uint32_t final_off = masked + meta_off;
+ uint32_t ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
+ context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
+
+ uint32_t slot = final_off / 1024;
+ if (!opts->gen.ram_inst_sizes[slot]) {
+ opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 1024);
+ }
+ opts->gen.ram_inst_sizes[slot][final_off % 1024] = native_size;
+
+ //TODO: Deal with case in which end of instruction is in a different memory chunk
+ masked = (address + size - 1) & mem_chunk->mask;
+ final_off = masked + meta_off;
+ ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
+ context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
+ }
+ //calculate the lowest alias for this address
+ address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
}
+
+ native_map_slot *map = opts->gen.native_code_map + address / NATIVE_CHUNK_SIZE;
if (!map->base) {
map->base = native_address;
- }
- map->offsets[address] = native_address - map->base;
- for(--size, orig_address++; size; --size, orig_address++) {
- address = orig_address;
- if (address < 0x4000) {
- address &= 0x1FFF;
- map = context->static_code_map;
- } else {
- address -= 0x4000;
- map = context->banked_code_map;
+ map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
+ memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
+ }
+ map->offsets[address % NATIVE_CHUNK_SIZE] = native_address - map->base;
+ for(--size, address++; size; --size, orig_address++) {
+ address &= opts->gen.address_mask;
+ map = opts->gen.native_code_map + address / NATIVE_CHUNK_SIZE;
+ if (!map->base) {
+ map->base = native_address;
+ map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
+ memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
}
- if (!map->offsets) {
- map->offsets = malloc(sizeof(int32_t) * 0xC000);
- memset(map->offsets, 0xFF, sizeof(int32_t) * 0xC000);
+
+ if (map->offsets[address % NATIVE_CHUNK_SIZE] == INVALID_OFFSET) {
+ map->offsets[address % NATIVE_CHUNK_SIZE] = EXTENSION_WORD;
}
- map->offsets[address] = EXTENSION_WORD;
}
}
#define INVALID_INSTRUCTION_START 0xFEEDFEED
-uint32_t z80_get_instruction_start(native_map_slot * static_code_map, uint32_t address)
-{
- //TODO: Fixme for address >= 0x4000
- if (!static_code_map->base || address >= 0x4000) {
+uint32_t z80_get_instruction_start(z80_context *context, uint32_t address)
+{
+ z80_options *opts = context->options;
+ native_map_slot * native_code_map = opts->gen.native_code_map;
+ memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
+ if (mem_chunk) {
+ //calculate the lowest alias for this address
+ address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
+ }
+
+ uint32_t chunk = address / NATIVE_CHUNK_SIZE;
+ if (!native_code_map[chunk].base) {
return INVALID_INSTRUCTION_START;
}
- address &= 0x1FFF;
- if (static_code_map->offsets[address] == INVALID_OFFSET) {
+ uint32_t offset = address % NATIVE_CHUNK_SIZE;
+ if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
return INVALID_INSTRUCTION_START;
}
- while (static_code_map->offsets[address] == EXTENSION_WORD) {
+ while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD)
+ {
--address;
- address &= 0x1FFF;
+ chunk = address / NATIVE_CHUNK_SIZE;
+ offset = address % NATIVE_CHUNK_SIZE;
}
return address;
}
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);
+ uint32_t inst_start = z80_get_instruction_start(context, address);
if (inst_start != INVALID_INSTRUCTION_START) {
code_ptr dst = z80_get_native_address(context, inst_start);
code_info code = {dst, dst+32, 0};
@@ -3178,12 +3206,12 @@ void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t
options->gen.cycles = RBP;
options->gen.limit = -1;
- options->gen.native_code_map = malloc(sizeof(native_map_slot));
- memset(options->gen.native_code_map, 0, sizeof(native_map_slot));
+ options->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
+ memset(options->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
options->gen.deferred = NULL;
- options->gen.ram_inst_sizes = malloc(sizeof(uint8_t) * 0x2000 + sizeof(uint8_t *));
- options->gen.ram_inst_sizes[0] = (uint8_t *)(options->gen.ram_inst_sizes + 1);
- memset(options->gen.ram_inst_sizes[0], 0, sizeof(uint8_t) * 0x2000);
+ uint32_t inst_size_size = sizeof(uint8_t *) * ram_size(&options->gen) / 1024;
+ options->gen.ram_inst_sizes = malloc(inst_size_size);
+ memset(options->gen.ram_inst_sizes, 0, inst_size_size);
code_info *code = &options->gen.code;
init_code_info(code);
@@ -3476,7 +3504,7 @@ void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t
call(code, options->gen.load_context);
jmp_r(code, options->gen.scratch1);
- options->run = code->cur;
+ options->run = (z80_ctx_fun)code->cur;
tmp_stack_off = code->stack_off;
save_callee_save_regs(code);
#ifdef X86_64
@@ -3496,19 +3524,16 @@ void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t
code->stack_off = tmp_stack_off;
}
-void init_z80_context(z80_context * context, z80_options * options)
+z80_context *init_z80_context(z80_options * options)
{
- memset(context, 0, sizeof(*context));
- context->static_code_map = malloc(sizeof(*context->static_code_map));
- context->static_code_map->base = NULL;
- context->static_code_map->offsets = malloc(sizeof(int32_t) * 0x2000);
- memset(context->static_code_map->offsets, 0xFF, sizeof(int32_t) * 0x2000);
- context->banked_code_map = malloc(sizeof(native_map_slot));
- memset(context->banked_code_map, 0, sizeof(native_map_slot));
+ size_t ctx_size = sizeof(z80_context) + ram_size(&options->gen) / (1 << options->gen.ram_flags_shift) / 8;
+ z80_context *context = calloc(1, ctx_size);
context->options = options;
context->int_cycle = CYCLE_NEVER;
context->int_pulse_start = CYCLE_NEVER;
context->int_pulse_end = CYCLE_NEVER;
+
+ return context;
}
void z80_run(z80_context * context, uint32_t target_cycle)
diff --git a/z80_to_x86.h b/z80_to_x86.h
index c82f895..4dcfdc3 100644
--- a/z80_to_x86.h
+++ b/z80_to_x86.h
@@ -70,11 +70,8 @@ struct z80_context {
void * extra_pc;
uint32_t sync_cycle;
uint32_t int_cycle;
- native_map_slot * static_code_map;
- native_map_slot * banked_code_map;
z80_options * options;
void * system;
- uint8_t ram_code_flags[(8 * 1024)/128/8];
uint32_t int_enable_cycle;
uint16_t pc;
uint32_t int_pulse_start;
@@ -87,12 +84,13 @@ struct z80_context {
uint8_t reset;
uint8_t busreq;
uint8_t busack;
+ uint8_t ram_code_flags[];
};
void translate_z80_stream(z80_context * context, uint32_t address);
void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, memmap_chunk const * io_chunks, uint32_t num_io_chunks, uint32_t clock_divider, uint32_t io_address_mask);
void z80_options_free(z80_options *opts);
-void init_z80_context(z80_context * context, z80_options * options);
+z80_context * init_z80_context(z80_options * options);
code_ptr z80_get_native_address(z80_context * context, uint32_t address);
code_ptr z80_get_native_address_trans(z80_context * context, uint32_t address);
z80_context * z80_handle_code_write(uint32_t address, z80_context * context);
diff --git a/ztestrun.c b/ztestrun.c
index 9147464..e64226a 100644
--- a/ztestrun.c
+++ b/ztestrun.c
@@ -34,12 +34,12 @@ void * z80_unmapped_write(uint32_t location, void * context, uint8_t value)
}
const memmap_chunk z80_map[] = {
- { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL },
- { 0x4000, 0x10000, 0xFFFF, 0, 0, NULL, NULL, NULL, z80_unmapped_read, z80_unmapped_write}
+ { 0x0000, 0x4000, 0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL },
+ { 0x4000, 0x10000, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, z80_unmapped_read, z80_unmapped_write}
};
const memmap_chunk port_map[] = {
- { 0x0000, 0x100, 0xFF, 0, 0, NULL, NULL, NULL, z80_unmapped_read, z80_unmapped_write}
+ { 0x0000, 0x100, 0xFF, 0, 0, 0, NULL, NULL, NULL, z80_unmapped_read, z80_unmapped_write}
};
void z80_next_int_pulse(z80_context * context)
@@ -52,7 +52,7 @@ int main(int argc, char ** argv)
long filesize;
uint8_t *filebuf;
z80_options opts;
- z80_context context;
+ z80_context *context;
char *fname = NULL;
uint8_t retranslate = 0;
for (int i = 1; i < argc; i++)
@@ -90,37 +90,37 @@ int main(int argc, char ** argv)
}
fclose(f);
init_z80_opts(&opts, z80_map, 2, port_map, 1, 1, 0xFF);
- init_z80_context(&context, &opts);
+ context = init_z80_context(&opts);
//Z80 RAM
- context.mem_pointers[0] = z80_ram;
+ context->mem_pointers[0] = z80_ram;
if (retranslate) {
//run core long enough to translate code
- z80_run(&context, 1);
+ z80_run(context, 1);
for (int i = 0; i < filesize; i++)
{
- z80_handle_code_write(i, &context);
+ z80_handle_code_write(i, context);
}
- z80_assert_reset(&context, context.current_cycle);
- z80_clear_reset(&context, context.current_cycle + 3);
- z80_adjust_cycles(&context, context.current_cycle);
+ z80_assert_reset(context, context->current_cycle);
+ z80_clear_reset(context, context->current_cycle + 3);
+ z80_adjust_cycles(context, context->current_cycle);
}
- z80_run(&context, 1000);
+ z80_run(context, 1000);
printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n\nIM: %d, IFF1: %d, IFF2: %d\n",
- context.regs[Z80_A], context.regs[Z80_B], context.regs[Z80_C],
- context.regs[Z80_D], context.regs[Z80_E],
- (context.regs[Z80_H] << 8) | context.regs[Z80_L],
- (context.regs[Z80_IXH] << 8) | context.regs[Z80_IXL],
- (context.regs[Z80_IYH] << 8) | context.regs[Z80_IYL],
- context.sp, context.im, context.iff1, context.iff2);
+ context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C],
+ context->regs[Z80_D], context->regs[Z80_E],
+ (context->regs[Z80_H] << 8) | context->regs[Z80_L],
+ (context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL],
+ (context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL],
+ context->sp, context->im, context->iff1, context->iff2);
printf("Flags: SZYHXVNC\n"
" %d%d%d%d%d%d%d%d\n",
- context.flags[ZF_S], context.flags[ZF_Z], context.flags[ZF_XY] >> 5 & 1, context.flags[ZF_H],
- context.flags[ZF_XY] >> 3 & 1, context.flags[ZF_PV], context.flags[ZF_N], context.flags[ZF_C]
+ context->flags[ZF_S], context->flags[ZF_Z], context->flags[ZF_XY] >> 5 & 1, context->flags[ZF_H],
+ context->flags[ZF_XY] >> 3 & 1, context->flags[ZF_PV], context->flags[ZF_N], context->flags[ZF_C]
);
puts("--Alternate Regs--");
printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\n",
- context.alt_regs[Z80_A], context.alt_regs[Z80_B], context.alt_regs[Z80_C],
- context.alt_regs[Z80_D], context.alt_regs[Z80_E],
- (context.alt_regs[Z80_H] << 8) | context.alt_regs[Z80_L]);
+ context->alt_regs[Z80_A], context->alt_regs[Z80_B], context->alt_regs[Z80_C],
+ context->alt_regs[Z80_D], context->alt_regs[Z80_E],
+ (context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L]);
return 0;
}