changeset 1130:8f14767661fa

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
author Michael Pavone <pavone@retrodev.com>
date Wed, 28 Dec 2016 20:39:27 -0800
parents 6b5c92b6205c
children 136b1676109b
files backend.c backend.h blastcpm.c debug.c genesis.c m68k_core.c m68k_core.h m68k_core_x86.c sms.c transz80.c z80_to_x86.c z80_to_x86.h ztestrun.c
diffstat 13 files changed, 186 insertions(+), 264 deletions(-) [+]
line wrap: on
line diff
--- a/backend.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/backend.c	Wed Dec 28 20:39:27 2016 -0800
@@ -51,6 +51,23 @@
 	}
 }
 
+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;
--- a/backend.h	Wed Dec 28 12:28:52 2016 -0800
+++ b/backend.h	Wed Dec 28 20:39:27 2016 -0800
@@ -122,6 +122,7 @@
 
 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);
 
--- a/blastcpm.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/blastcpm.c	Wed Dec 28 20:39:27 2016 -0800
@@ -62,13 +62,13 @@
 }
 
 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 @@
 	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
--- a/debug.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/debug.c	Wed Dec 28 20:39:27 2016 -0800
@@ -591,7 +591,7 @@
 					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;
--- a/genesis.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/genesis.c	Wed Dec 28 20:39:27 2016 -0800
@@ -925,15 +925,16 @@
 	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;
--- a/m68k_core.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/m68k_core.c	Wed Dec 28 20:39:27 2016 -0800
@@ -560,16 +560,12 @@
 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 @@
 	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 @@
 	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 @@
 
 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);
+	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);
 
-				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;
+			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;
 
-				//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);
-			}
-			//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;
+			//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 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 @@
 
 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 @@
 	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;
--- a/m68k_core.h	Wed Dec 28 12:28:52 2016 -0800
+++ b/m68k_core.h	Wed Dec 28 20:39:27 2016 -0800
@@ -63,7 +63,6 @@
 	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 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);
 
--- a/m68k_core_x86.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/m68k_core_x86.c	Wed Dec 28 20:39:27 2016 -0800
@@ -2266,8 +2266,7 @@
 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);
--- a/sms.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/sms.c	Wed Dec 28 20:39:27 2016 -0800
@@ -212,8 +212,7 @@
 	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;
--- a/transz80.c	Wed Dec 28 12:28:52 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-}
--- a/z80_to_x86.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/z80_to_x86.c	Wed Dec 28 20:39:27 2016 -0800
@@ -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 @@
 
 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);
 	}
-	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 chunk = address / NATIVE_CHUNK_SIZE;
+	if (!native_code_map[chunk].base) {
 		return NULL;
 	}
-	//dprintf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]);
-	return map->base + map->offsets[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;
+	}
+	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 = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
+		memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
 	}
-	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[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 @@
 	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 @@
 	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 @@
 	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)
--- a/z80_to_x86.h	Wed Dec 28 12:28:52 2016 -0800
+++ b/z80_to_x86.h	Wed Dec 28 20:39:27 2016 -0800
@@ -70,11 +70,8 @@
 	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 @@
 	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);
--- a/ztestrun.c	Wed Dec 28 12:28:52 2016 -0800
+++ b/ztestrun.c	Wed Dec 28 20:39:27 2016 -0800
@@ -34,12 +34,12 @@
 }
 
 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 @@
 	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 @@
 	}
 	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;
 }