changeset 653:a18e3923481e

Remove some of the hard coded assumptions about the memory map from the CPU cores
author Michael Pavone <pavone@retrodev.com>
date Thu, 01 Jan 2015 14:36:55 -0800
parents f822d9216968
children 98927f1b005b
files backend.c backend.h m68k_core.c m68k_core.h m68k_core_x86.c z80_to_x86.c
diffstat 6 files changed, 119 insertions(+), 162 deletions(-) [+]
line wrap: on
line diff
--- a/backend.c	Tue Dec 30 19:11:34 2014 -0800
+++ b/backend.c	Thu Jan 01 14:36:55 2015 -0800
@@ -51,3 +51,24 @@
 	}
 }
 
+void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts)
+{
+	memmap_chunk * memmap = opts->memmap;
+	address &= opts->address_mask;
+	for (uint32_t chunk = 0; chunk < opts->memmap_chunks; chunk++)
+	{
+		if (address >= memmap[chunk].start && address < memmap[chunk].end) {
+			if (!(memmap[chunk].flags & MMAP_READ)) {
+				return NULL;
+			}
+			uint8_t * base = memmap[chunk].flags & MMAP_PTR_IDX
+				? mem_pointers[memmap[chunk].ptr_index]
+				: memmap[chunk].buffer;
+			if (!base) {
+				return NULL;
+			}
+			return base + (address & memmap[chunk].mask);
+		}
+	}
+	return NULL;
+}
--- a/backend.h	Tue Dec 30 19:11:34 2014 -0800
+++ b/backend.h	Thu Jan 01 14:36:55 2015 -0800
@@ -46,33 +46,6 @@
 	WRITE_8
 } ftype;
 
-typedef struct {
-	uint32_t flags;
-	native_map_slot *native_code_map;
-	deferred_addr   *deferred;
-	code_info       code;
-	uint8_t         **ram_inst_sizes;
-	code_ptr        save_context;
-	code_ptr        load_context;
-	code_ptr        handle_cycle_limit;
-	code_ptr        handle_cycle_limit_int;
-	code_ptr        handle_code_write;
-	uint32_t        address_mask;
-	uint32_t        max_address;
-	uint32_t        bus_cycles;
-	int32_t         mem_ptr_off;
-	int32_t         ram_flags_off;
-	uint8_t         ram_flags_shift;
-	uint8_t         address_size;
-	uint8_t         byte_swap;
-	uint8_t         context_reg;
-	uint8_t         cycles;
-	uint8_t         limit;
-	uint8_t			scratch1;
-	uint8_t			scratch2;
-} cpu_options;
-
-
 #define MMAP_READ      0x01
 #define MMAP_WRITE     0x02
 #define MMAP_CODE      0x04
@@ -100,6 +73,34 @@
 	write_8_fun  write_8;
 } memmap_chunk;
 
+typedef struct {
+	uint32_t flags;
+	native_map_slot    *native_code_map;
+	deferred_addr      *deferred;
+	code_info          code;
+	uint8_t            **ram_inst_sizes;
+	memmap_chunk const *memmap;
+	code_ptr           save_context;
+	code_ptr           load_context;
+	code_ptr           handle_cycle_limit;
+	code_ptr           handle_cycle_limit_int;
+	code_ptr           handle_code_write;
+	uint32_t           memmap_chunks;
+	uint32_t           address_mask;
+	uint32_t           max_address;
+	uint32_t           bus_cycles;
+	int32_t            mem_ptr_off;
+	int32_t            ram_flags_off;
+	uint8_t            ram_flags_shift;
+	uint8_t            address_size;
+	uint8_t            byte_swap;
+	uint8_t            context_reg;
+	uint8_t            cycles;
+	uint8_t            limit;
+	uint8_t			   scratch1;
+	uint8_t			   scratch2;
+} cpu_options;
+
 typedef uint8_t * (*native_addr_func)(void * context, uint32_t address);
 
 deferred_addr * defer_address(deferred_addr * old_head, uint32_t address, uint8_t *dest);
@@ -112,6 +113,7 @@
 void check_code_prologue(code_info *code);
 
 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);
 
 #endif //BACKEND_H_
 
--- a/m68k_core.c	Tue Dec 30 19:11:34 2014 -0800
+++ b/m68k_core.c	Thu Jan 01 14:36:55 2015 -0800
@@ -754,26 +754,17 @@
 	m68kinst instbuf;
 	m68k_options * opts = context->options;
 	code_info *code = &opts->gen.code;
-	address &= 0xFFFFFF;
 	if(get_native_address(opts->gen.native_code_map, address)) {
 		return;
 	}
-	char disbuf[1024];
 	uint16_t *encoded, *next;
-	if ((address & 0xFFFFFF) < 0x400000) {
-		encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2;
-	} else if ((address & 0xFFFFFF) > 0xE00000) {
-		encoded = context->mem_pointers[1] + (address  & 0xFFFF)/2;
-	} else {
-		printf("attempt to translate non-memory address: %X\n", address);
-		exit(1);
-	}
 	do {
 		if (opts->address_log) {
 			fprintf(opts->address_log, "%X\n", address);
 		}
 		do {
-			if (address >= 0x400000 && address < 0xE00000) {
+			encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
+			if (!encoded) {
 				translate_out_of_bounds(code);
 				break;
 			}
@@ -788,7 +779,7 @@
 			}
 			uint16_t m68k_size = (next-encoded)*2;
 			address += m68k_size;
-			encoded = next;
+			//char disbuf[1024];
 			//m68k_disasm(&instbuf, disbuf);
 			//printf("%X: %s\n", instbuf.address, disbuf);
 
@@ -802,18 +793,8 @@
 		process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context);
 		if (opts->gen.deferred) {
 			address = opts->gen.deferred->address;
-			if ((address & 0xFFFFFF) < 0x400000) {
-				encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2;
-			} else if ((address & 0xFFFFFF) > 0xE00000) {
-				encoded = context->mem_pointers[1] + (address  & 0xFFFF)/2;
-			} else {
-				printf("attempt to translate non-memory address: %X\n", address);
-				exit(1);
-			}
-		} else {
-			encoded = NULL;
 		}
-	} while(encoded != NULL);
+	} while(opts->gen.deferred);
 }
 
 void * m68k_retranslate_inst(uint32_t address, m68k_context * context)
@@ -826,8 +807,7 @@
 	code_info orig_code;
 	orig_code.cur = orig_start;
 	orig_code.last = orig_start + orig_size + 5;
-	address &= 0xFFFF;
-	uint16_t *after, *inst = context->mem_pointers[1] + address/2;
+	uint16_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
 	m68kinst instbuf;
 	after = m68k_decode(inst, &instbuf, orig);
 	if (orig_size != MAX_NATIVE_SIZE) {
@@ -910,7 +890,7 @@
 void remove_breakpoint(m68k_context * context, uint32_t address)
 {
 	code_ptr native = get_native_address(context->native_code_map, address);
-	check_cycles_int(context->options, address);
+	check_cycles_int(&context->options->gen, address);
 }
 
 void start_68k_context(m68k_context * context, uint32_t address)
@@ -922,9 +902,10 @@
 
 void m68k_reset(m68k_context * context)
 {
-	//TODO: Make this actually use the normal read functions
-	context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1];
-	uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3];
+	//TODO: Actually execute the M68K reset vector rather than simulating some of its behavior
+	uint16_t *reset_vec = get_native_pointer(0, (void **)context->mem_pointers, &context->options->gen);
+	context->aregs[7] = reset_vec[0] << 16 | reset_vec[1];
+	uint32_t address = reset_vec[2] << 16 | reset_vec[3];
 	start_68k_context(context, address);
 }
 
--- a/m68k_core.h	Tue Dec 30 19:11:34 2014 -0800
+++ b/m68k_core.h	Thu Jan 01 14:36:55 2015 -0800
@@ -59,7 +59,7 @@
 	uint16_t        reserved;
 
 	native_map_slot *native_code_map;
-	void            *options;
+	m68k_options    *options;
 	uint8_t         ram_code_flags[32/8];
 	void            *system;
 } m68k_context;
--- a/m68k_core_x86.c	Tue Dec 30 19:11:34 2014 -0800
+++ b/m68k_core_x86.c	Thu Jan 01 14:36:55 2015 -0800
@@ -1464,7 +1464,7 @@
 	set_flag_cond(opts, CC_O, FLAG_V);
 	*no_adjust = code->cur - (no_adjust+1);
 	flag_to_flag(opts, FLAG_C, FLAG_X);
-	
+
 	cmp_ir(code, 0, opts->gen.scratch1, SZ_B);
 	set_flag_cond(opts, CC_S, FLAG_N);
 	jcc(code, CC_Z, code->cur + 4);
@@ -1664,7 +1664,7 @@
 	case MODE_ABSOLUTE_SHORT:
 	case MODE_PC_INDEX_DISP8:
 	case MODE_IMMEDIATE:
-		isize = 4;		
+		isize = 4;
 		break;
 	case MODE_ABSOLUTE:
 		isize = 6;
@@ -2230,6 +2230,8 @@
 void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks)
 {
 	memset(opts, 0, sizeof(*opts));
+	opts->gen.memmap = memmap;
+	opts->gen.memmap_chunks = num_chunks;
 	opts->gen.address_size = SZ_D;
 	opts->gen.address_mask = 0xFFFFFF;
 	opts->gen.byte_swap = 1;
--- a/z80_to_x86.c	Tue Dec 30 19:11:34 2014 -0800
+++ b/z80_to_x86.c	Thu Jan 01 14:36:55 2015 -0800
@@ -1331,7 +1331,7 @@
 			num_cycles += 4;
 		}
 		cycles(&opts->gen, num_cycles);
-		if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) {
+		if (inst->addr_mode != Z80_REG_INDIRECT) {
 			code_ptr call_dst = z80_get_native_address(context, inst->immed);
 			if (!call_dst) {
 				opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
@@ -1380,38 +1380,26 @@
 		jcc(code, cond, code->cur+2);
 		cycles(&opts->gen, 5);//T States: 5
 		uint16_t dest_addr = inst->immed;
-		if (dest_addr < 0x4000) {
-			code_ptr call_dst = z80_get_native_address(context, dest_addr);
-			if (!call_dst) {
-				opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
-				//fake address to force large displacement
-				call_dst = code->cur + 256;
-			}
-			jmp(code, call_dst);
-		} else {
-			mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
-			call(code, opts->native_addr);
-			jmp_r(code, opts->gen.scratch1);
+		code_ptr call_dst = z80_get_native_address(context, dest_addr);
+		if (!call_dst) {
+			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
+			//fake address to force large displacement
+			call_dst = code->cur + 256;
 		}
+		jmp(code, call_dst);
 		*no_jump_off = code->cur - (no_jump_off+1);
 		break;
 	}
 	case Z80_JR: {
 		cycles(&opts->gen, 12);//T States: 4,3,5
 		uint16_t dest_addr = address + inst->immed + 2;
-		if (dest_addr < 0x4000) {
-			code_ptr call_dst = z80_get_native_address(context, dest_addr);
-			if (!call_dst) {
-				opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
-				//fake address to force large displacement
-				call_dst = code->cur + 256;
-			}
-			jmp(code, call_dst);
-		} else {
-			mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
-			call(code, opts->native_addr);
-			jmp_r(code, opts->gen.scratch1);
+		code_ptr call_dst = z80_get_native_address(context, dest_addr);
+		if (!call_dst) {
+			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
+			//fake address to force large displacement
+			call_dst = code->cur + 256;
 		}
+		jmp(code, call_dst);
 		break;
 	}
 	case Z80_JRCC: {
@@ -1434,66 +1422,49 @@
 		jcc(code, cond, code->cur+2);
 		cycles(&opts->gen, 5);//T States: 5
 		uint16_t dest_addr = address + inst->immed + 2;
-		if (dest_addr < 0x4000) {
-			code_ptr call_dst = z80_get_native_address(context, dest_addr);
-			if (!call_dst) {
-				opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
-				//fake address to force large displacement
-				call_dst = code->cur + 256;
-			}
-			jmp(code, call_dst);
-		} else {
-			mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
-			call(code, opts->native_addr);
-			jmp_r(code, opts->gen.scratch1);
+		code_ptr call_dst = z80_get_native_address(context, dest_addr);
+		if (!call_dst) {
+			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
+			//fake address to force large displacement
+			call_dst = code->cur + 256;
 		}
+		jmp(code, call_dst);
 		*no_jump_off = code->cur - (no_jump_off+1);
 		break;
 	}
-	case Z80_DJNZ:
+	case Z80_DJNZ: {
 		cycles(&opts->gen, 8);//T States: 5,3
 		sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
 		uint8_t *no_jump_off = code->cur+1;
 		jcc(code, CC_Z, code->cur+2);
 		cycles(&opts->gen, 5);//T States: 5
 		uint16_t dest_addr = address + inst->immed + 2;
-		if (dest_addr < 0x4000) {
-			code_ptr call_dst = z80_get_native_address(context, dest_addr);
-			if (!call_dst) {
-				opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
-				//fake address to force large displacement
-				call_dst = code->cur + 256;
-			}
-			jmp(code, call_dst);
-		} else {
-			mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
-			call(code, opts->native_addr);
-			jmp_r(code, opts->gen.scratch1);
+		code_ptr call_dst = z80_get_native_address(context, dest_addr);
+		if (!call_dst) {
+			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
+			//fake address to force large displacement
+			call_dst = code->cur + 256;
 		}
+		jmp(code, call_dst);
 		*no_jump_off = code->cur - (no_jump_off+1);
 		break;
+	}
 	case Z80_CALL: {
 		cycles(&opts->gen, 11);//T States: 4,3,4
 		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
 		mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
 		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
 		call(code, opts->write_16_highfirst);//T States: 3, 3
-		if (inst->immed < 0x4000) {
-			code_ptr call_dst = z80_get_native_address(context, inst->immed);
-			if (!call_dst) {
-				opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
-				//fake address to force large displacement
-				call_dst = code->cur + 256;
-			}
-			jmp(code, call_dst);
-		} else {
-			mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
-			call(code, opts->native_addr);
-			jmp_r(code, opts->gen.scratch1);
+		code_ptr call_dst = z80_get_native_address(context, inst->immed);
+		if (!call_dst) {
+			opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
+			//fake address to force large displacement
+			call_dst = code->cur + 256;
 		}
+		jmp(code, call_dst);
 		break;
 	}
-	case Z80_CALLCC:
+	case Z80_CALLCC: {
 		cycles(&opts->gen, 10);//T States: 4,3,3 (false case)
 		uint8_t cond = CC_Z;
 		switch (inst->reg)
@@ -1526,21 +1497,16 @@
 		mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
 		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
 		call(code, opts->write_16_highfirst);//T States: 3, 3
-		if (inst->immed < 0x4000) {
-			code_ptr call_dst = z80_get_native_address(context, inst->immed);
-			if (!call_dst) {
-				opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
-				//fake address to force large displacement
-				call_dst = code->cur + 256;
-			}
-			jmp(code, call_dst);
-		} else {
-			mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
-			call(code, opts->native_addr);
-			jmp_r(code, opts->gen.scratch1);
+		code_ptr call_dst = z80_get_native_address(context, inst->immed);
+		if (!call_dst) {
+			opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
+			//fake address to force large displacement
+			call_dst = code->cur + 256;
 		}
+		jmp(code, call_dst);
 		*no_call_off = code->cur - (no_call_off+1);
 		break;
+	}
 	case Z80_RET:
 		cycles(&opts->gen, 4);//T States: 4
 		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
@@ -1850,10 +1816,8 @@
 	char disbuf[80];
 	z80_options * opts = context->options;
 	uint8_t orig_size = z80_get_native_inst_size(opts, address);
-	uint32_t orig = address;
-	address &= 0x1FFF;
 	code_info *code = &opts->gen.code;
-	uint8_t *after, *inst = context->mem_pointers[0] + address;
+	uint8_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
 	z80inst instbuf;
 	dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start);
 	after = z80_decode(inst, &instbuf);
@@ -1921,26 +1885,24 @@
 	}
 	z80_options * opts = context->options;
 	uint32_t start_address = address;
-	uint8_t * encoded = NULL, *next;
-	if (address < 0x4000) {
-		encoded = context->mem_pointers[0] + (address & 0x1FFF);
-	}
 
-	while (encoded != NULL || address >= 0x4000)
+	do
 	{
 		z80inst inst;
 		dprintf("translating Z80 code at address %X\n", address);
 		do {
-			if (address >= 0x4000) {
-				code_info stub = z80_make_interp_stub(context, address);
-				z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur);
-				break;
-			}
 			uint8_t * existing = z80_get_native_address(context, address);
 			if (existing) {
 				jmp(&opts->gen.code, existing);
 				break;
 			}
+			uint8_t * encoded, *next;
+			encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
+			if (!encoded) {
+				code_info stub = z80_make_interp_stub(context, address);
+				z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur);
+				break;
+			}
 			//make sure prologue is in a contiguous chunk of code
 			check_code_prologue(&opts->gen.code);
 			next = z80_decode(encoded, &inst);
@@ -1956,33 +1918,22 @@
 			translate_z80inst(&inst, context, address, 0);
 			z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start);
 			address += next-encoded;
-			if (address > 0xFFFF) {
-				address &= 0xFFFF;
-
-			} else {
-				encoded = next;
-			}
+			address &= 0xFFFF;
 		} while (!z80_is_terminal(&inst));
 		process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
 		if (opts->gen.deferred) {
 			address = opts->gen.deferred->address;
 			dprintf("defferred address: %X\n", address);
-			if (address < 0x4000) {
-				encoded = context->mem_pointers[0] + (address & 0x1FFF);
-			} else {
-				encoded = NULL;
-			}
-		} else {
-			encoded = NULL;
-			address = 0;
 		}
-	}
+	} while (opts->gen.deferred);
 }
 
 void init_x86_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks)
 {
 	memset(options, 0, sizeof(*options));
 
+	options->gen.memmap = chunks;
+	options->gen.memmap_chunks = num_chunks;
 	options->gen.address_size = SZ_W;
 	options->gen.address_mask = 0xFFFF;
 	options->gen.max_address = 0x10000;