changeset 1142:5c8b1c33ca10

Invalidate translated code on a cartridge bank change in SMS mode. Fix handling of bank 0
author Michael Pavone <pavone@retrodev.com>
date Mon, 02 Jan 2017 23:35:40 -0800
parents 7e199bebde2f
children d4d770cfbc62
files backend.c sms.c z80_to_x86.c z80_to_x86.h
diffstat 4 files changed, 57 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/backend.c	Mon Jan 02 22:54:24 2017 -0800
+++ b/backend.c	Mon Jan 02 23:35:40 2017 -0800
@@ -107,7 +107,7 @@
 	uint32_t size = 0;
 	for (int i = 0; i < opts->memmap_chunks; i++)
 	{
-		if ((opts->memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
+		if (opts->memmap[i].flags & MMAP_CODE) {
 			if (opts->memmap[i].mask == opts->address_mask) {
 				size += opts->memmap[i].end - opts->memmap[i].start;
 			} else {
--- a/sms.c	Mon Jan 02 22:54:24 2017 -0800
+++ b/sms.c	Mon Jan 02 23:35:40 2017 -0800
@@ -101,24 +101,19 @@
 {
 	z80_context *z80 = vcontext;
 	sms_context *sms = z80->system;
+	void *old_value;
 	sms->ram[location & (sizeof(sms->ram)-1)] = value;
-	switch (location & 3)
-	{
-	case 0:
+	location &= 3;
+	if (location) {
+		uint32_t idx = location - 1;
+		old_value = z80->mem_pointers[idx];
+		z80->mem_pointers[idx] = sms->rom + (value << 14 & (sms->rom_size-1));
+		if (old_value != z80->mem_pointers[idx]) {
+			//invalidate any code we translated for the relevant bank
+			z80_invalidate_code_range(z80, idx ? idx * 0x4000 : 0x400, idx * 0x4000 + 0x4000);
+		}
+	} else {
 		//TODO: implement me
-		break;
-	case 1:
-		z80->mem_pointers[0] = sms->rom + (value << 14 & (sms->rom_size-1)) + 0x400;
-		//TODO: invalidate translated code in range 0x400-0x4000
-		break;
-	case 2:
-		z80->mem_pointers[1] = sms->rom + (value << 14 & (sms->rom_size-1));
-		//TODO: invalidate translated code in range 0x4000-0x8000
-		break;
-	case 3:
-		z80->mem_pointers[2] = sms->rom + (value << 14 & (sms->rom_size-1));
-		//TODO: invalidate translated code in range 0x8000-0xC000
-		break;
 	}
 	return vcontext;
 }
@@ -234,12 +229,12 @@
 	if (orig_size > 0xC000)  {
 		info_out->map_chunks = 6;
 		uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4;
-		memory_map[0] = (memmap_chunk){0x0000, 0x0400,  0xFFFF,             0, 0, MMAP_READ,                      rom,      NULL, NULL, NULL, NULL};
-		memory_map[1] = (memmap_chunk){0x0400, 0x4000,  0xFFFF,             0, 0, MMAP_READ|MMAP_PTR_IDX,         NULL,     NULL, NULL, NULL, NULL};
-		memory_map[2] = (memmap_chunk){0x4000, 0x8000,  0x3FFF,             0, 1, MMAP_READ|MMAP_PTR_IDX,         NULL,     NULL, NULL, NULL, NULL};
-		memory_map[3] = (memmap_chunk){0x8000, 0xC000,  0x3FFF,             0, 2, MMAP_READ|MMAP_PTR_IDX,         NULL,     NULL, NULL, NULL, NULL};
-		memory_map[4] = (memmap_chunk){0xC000, 0xFFFC,  sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL};
-		memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0xFFFF,             0, 0, MMAP_READ,                      ram_reg_overlap, NULL, NULL, NULL, mapper_write};
+		memory_map[0] = (memmap_chunk){0x0000, 0x0400,  0xFFFF,             0, 0, MMAP_READ,                        rom,      NULL, NULL, NULL, NULL};
+		memory_map[1] = (memmap_chunk){0x0400, 0x4000,  0xFFFF,             0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
+		memory_map[2] = (memmap_chunk){0x4000, 0x8000,  0x3FFF,             0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
+		memory_map[3] = (memmap_chunk){0x8000, 0xC000,  0x3FFF,             0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
+		memory_map[4] = (memmap_chunk){0xC000, 0xFFFC,  sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE,   sms->ram, NULL, NULL, NULL, NULL};
+		memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0xFFFF,             0, 0, MMAP_READ,                        ram_reg_overlap, NULL, NULL, NULL, mapper_write};
 	} else {
 		info_out->map_chunks = 2;
 		memory_map[0] = (memmap_chunk){0x0000, 0xC000,  rom_size-1,         0, 0, MMAP_READ,                      rom,      NULL, NULL, NULL, NULL};
--- a/z80_to_x86.c	Mon Jan 02 22:54:24 2017 -0800
+++ b/z80_to_x86.c	Mon Jan 02 23:35:40 2017 -0800
@@ -2905,7 +2905,7 @@
 uint8_t z80_get_native_inst_size(z80_options * opts, uint32_t address)
 {
 	uint32_t meta_off;
-	memmap_chunk const *chunk = find_map_chunk(address, &opts->gen, MMAP_WRITE | MMAP_CODE, &meta_off);
+	memmap_chunk const *chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
 	if (chunk) {
 		meta_off += (address - chunk->start) & chunk->mask;
 	}
@@ -2919,9 +2919,9 @@
 	
 	z80_options * opts = context->options;
 	uint32_t meta_off;
-	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_WRITE | MMAP_CODE, &meta_off);
+	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
 	if (mem_chunk) {
-		if ((mem_chunk->flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
+		if (mem_chunk->flags & 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);
@@ -3008,6 +3008,41 @@
 	return context;
 }
 
+void z80_invalidate_code_range(z80_context *context, uint32_t start, uint32_t end)
+{
+	z80_options *opts = context->options;
+	native_map_slot * native_code_map = opts->gen.native_code_map;
+	memmap_chunk const *mem_chunk = find_map_chunk(start, &opts->gen, 0, NULL);
+	if (mem_chunk) {
+		//calculate the lowest alias for this address
+		start = mem_chunk->start + ((start - mem_chunk->start) & mem_chunk->mask);
+	}
+	mem_chunk = find_map_chunk(end, &opts->gen, 0, NULL);
+	if (mem_chunk) {
+		//calculate the lowest alias for this address
+		end = mem_chunk->start + ((end - mem_chunk->start) & mem_chunk->mask);
+	}
+	uint32_t start_chunk = start / NATIVE_CHUNK_SIZE, end_chunk = end / NATIVE_CHUNK_SIZE;
+	for (uint32_t chunk = start_chunk; chunk <= end_chunk; chunk++)
+	{
+		if (native_code_map[chunk].base) {
+			uint32_t start_offset = chunk == start_chunk ? start % NATIVE_CHUNK_SIZE : 0;
+			uint32_t end_offset = chunk == end_chunk ? end % NATIVE_CHUNK_SIZE : NATIVE_CHUNK_SIZE;
+			for (uint32_t offset = start_offset; offset < end_offset; offset++)
+			{
+				if (native_code_map[chunk].offsets[offset] != INVALID_OFFSET && native_code_map[chunk].offsets[offset] != EXTENSION_WORD) {
+					code_info code;
+					code.cur = native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
+					code.last = code.cur + 32;
+					code.stack_off = 0;
+					mov_ir(&code, chunk * NATIVE_CHUNK_SIZE + offset, opts->gen.scratch1, SZ_D);
+					call(&code, opts->retrans_stub);
+				}
+			}
+		}
+	}
+}
+
 uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address)
 {
 	uint8_t * addr = z80_get_native_address(context, address);
--- a/z80_to_x86.h	Mon Jan 02 22:54:24 2017 -0800
+++ b/z80_to_x86.h	Mon Jan 02 23:35:40 2017 -0800
@@ -94,6 +94,7 @@
 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);
+void z80_invalidate_code_range(z80_context *context, uint32_t start, uint32_t end);
 void z80_reset(z80_context * context);
 void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler);
 void zremove_breakpoint(z80_context * context, uint16_t address);