diff m68k_core.c @ 744:fc68992cf18d

Merge windows branch with latest changes
author Michael Pavone <pavone@retrodev.com>
date Thu, 28 May 2015 21:19:55 -0700
parents 7367b14ac01c
children 724bbec47f86 41f73c76b978
line wrap: on
line diff
--- a/m68k_core.c	Thu May 28 21:09:33 2015 -0700
+++ b/m68k_core.c	Thu May 28 21:19:55 2015 -0700
@@ -86,6 +86,28 @@
 	}
 }
 
+void m68k_save_result(m68kinst * inst, m68k_options * opts)
+{
+	code_info *code = &opts->gen.code;
+	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_UNUSED) {
+		if (inst->dst.addr_mode == MODE_AREG_PREDEC && inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) {
+			areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2);
+		}
+		switch (inst->extra.size)
+		{
+		case OPSIZE_BYTE:
+			call(code, opts->write_8);
+			break;
+		case OPSIZE_WORD:
+			call(code, opts->write_16);
+			break;
+		case OPSIZE_LONG:
+			call(code, opts->write_32_lowfirst);
+			break;
+		}
+	}
+}
+
 void translate_m68k_lea_pea(m68k_options * opts, m68kinst * inst)
 {
 	code_info *code = &opts->gen.code;
@@ -173,7 +195,7 @@
 void jump_m68k_abs(m68k_options * opts, uint32_t address)
 {
 	code_info *code = &opts->gen.code;
-	code_ptr dest_addr = get_native_address(opts->gen.native_code_map, address);
+	code_ptr dest_addr = get_native_address(opts, address);
 	if (!dest_addr) {
 		opts->gen.deferred = defer_address(opts->gen.deferred, address, code->cur + 1);
 		//dummy address to be replaced later, make sure it generates a 4-byte displacement
@@ -503,9 +525,39 @@
 	native_to_areg(opts, opts->gen.scratch2, 8);
 }
 
-code_ptr get_native_address(native_map_slot * native_code_map, uint32_t address)
+void translate_m68k_reset(m68k_options *opts, m68kinst *inst)
+{
+	code_info *code = &opts->gen.code;
+	call(code, opts->gen.save_context);
+	call_args(code, (code_ptr)print_regs_exit, 1, opts->gen.context_reg);
+}
+
+void translate_m68k_rte(m68k_options *opts, m68kinst *inst)
 {
-	address &= 0xFFFFFF;
+	code_info *code = &opts->gen.code;
+	//TODO: Trap if not in system mode
+	//Read saved SR
+	areg_to_native(opts, 7, opts->gen.scratch1);
+	call(code, opts->read_16);
+	addi_areg(opts, 2, 7);
+	call(code, opts->set_sr);
+	//Read saved PC
+	areg_to_native(opts, 7, opts->gen.scratch1);
+	call(code, opts->read_32);
+	addi_areg(opts, 4, 7);
+	check_user_mode_swap_ssp_usp(opts);
+	//Get native address, sync components, recalculate integer points and jump to returned address
+	call(code, opts->native_addr_and_sync);
+	jmp_r(code, opts->gen.scratch1);
+}
+
+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;
+	if (address & 1) {
+		return opts->odd_address;
+	}
 	address /= 2;
 	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
 	if (!native_code_map[chunk].base) {
@@ -520,11 +572,12 @@
 
 code_ptr get_native_from_context(m68k_context * context, uint32_t address)
 {
-	return get_native_address(context->native_code_map, address);
+	return get_native_address(context->options, address);
 }
 
 uint32_t get_instruction_start(native_map_slot * native_code_map, uint32_t address)
 {
+	//FIXME: Use opts->gen.address_mask
 	address &= 0xFFFFFF;
 	address /= 2;
 	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
@@ -547,17 +600,34 @@
 {
 	native_map_slot * native_code_map = context->native_code_map;
 	m68k_options * opts = context->options;
-	address &= 0xFFFFFF;
-	if (address > 0xE00000) {
-		context->ram_code_flags[(address & 0xC000) >> 14] |= 1 << ((address & 0x3800) >> 11);
-		if (((address & 0x3FFF) + size) & 0xC000) {
-			context->ram_code_flags[((address+size) & 0xC000) >> 14] |= 1 << (((address+size) & 0x3800) >> 11);
+	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;
+
+				//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);
+			}
+			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 slot = (address & 0xFFFF)/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][((address & 0xFFFF)/2)%512] = native_size;
 	}
 	address/= 2;
 	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
@@ -569,6 +639,7 @@
 	uint32_t offset = address % NATIVE_CHUNK_SIZE;
 	native_code_map[chunk].offsets[offset] = native_addr-native_code_map[chunk].base;
 	for(address++,size-=2; size; address++,size-=2) {
+		address &= opts->gen.address_mask >> 1;
 		chunk = address / NATIVE_CHUNK_SIZE;
 		offset = address % NATIVE_CHUNK_SIZE;
 		if (!native_code_map[chunk].base) {
@@ -576,17 +647,31 @@
 			native_code_map[chunk].offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
 			memset(native_code_map[chunk].offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
 		}
-		native_code_map[chunk].offsets[offset] = EXTENSION_WORD;
+		if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
+			//TODO: Better handling of overlapping instructions
+			native_code_map[chunk].offsets[offset] = EXTENSION_WORD;
+		}
 	}
 }
 
 uint8_t get_native_inst_size(m68k_options * opts, uint32_t address)
 {
-	if (address < 0xE00000) {
-		return 0;
+	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 slot = (address & 0xFFFF)/1024;
-	return opts->gen.ram_inst_sizes[slot][((address & 0xFFFF)/2)%512];
+	uint32_t slot = meta_off/1024;
+	return opts->gen.ram_inst_sizes[slot][(meta_off/2)%512];
 }
 
 uint8_t m68k_is_terminal(m68kinst * inst)
@@ -649,7 +734,7 @@
 	RAW_IMPL(M68K_EXT, translate_m68k_ext),
 	UNARY_IMPL(M68K_NEG, X|N|Z|V|C),
 	OP_IMPL(M68K_NEGX, translate_m68k_negx),
-	UNARY_IMPL(M68K_NOT, X|N|Z|V|C),
+	UNARY_IMPL(M68K_NOT, N|Z|V|C),
 	UNARY_IMPL(M68K_TST, N|Z|V0|C0),
 
 	//shift/rotate
@@ -723,6 +808,7 @@
 void translate_m68k(m68k_options * opts, m68kinst * inst)
 {
 	check_cycles_int(&opts->gen, inst->address);
+	//log_address(&opts->gen, inst->address, "M68K: %X @ %d\n");
 	impl_info * info = m68k_impls + inst->op;
 	if (info->itype == RAW_FUNC) {
 		info->impl.raw(opts, inst);
@@ -754,30 +840,26 @@
 	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)) {
+	if(get_native_address(opts, 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);
+			fflush(opts->address_log);
 		}
 		do {
-			if (address >= 0x400000 && address < 0xE00000) {
+			if (address & 1) {
+				break;
+			}
+			encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
+			if (!encoded) {
+				map_native_address(context, address, code->cur, 2, 1);
 				translate_out_of_bounds(code);
 				break;
 			}
-			code_ptr existing = get_native_address(opts->gen.native_code_map, address);
+			code_ptr existing = get_native_address(opts, address);
 			if (existing) {
 				jmp(code, existing);
 				break;
@@ -788,7 +870,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 +884,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)
@@ -821,30 +893,30 @@
 	m68k_options * opts = context->options;
 	code_info *code = &opts->gen.code;
 	uint8_t orig_size = get_native_inst_size(opts, address);
-	code_ptr orig_start = get_native_address(context->native_code_map, address);
+	code_ptr orig_start = get_native_address(context->options, address);
 	uint32_t orig = address;
 	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) {
 		deferred_addr * orig_deferred = opts->gen.deferred;
 
-		//make sure the beginning of the code for an instruction is contiguous
-		check_code_prologue(code);
+		//make sure we have enough code space for the max size instruction
+		check_alloc_code(code, MAX_NATIVE_SIZE);
 		code_ptr native_start = code->cur;
 		translate_m68k(opts, &instbuf);
 		code_ptr native_end = code->cur;
-		uint8_t is_terminal = m68k_is_terminal(&instbuf);
+		/*uint8_t is_terminal = m68k_is_terminal(&instbuf);
 		if ((native_end - native_start) <= orig_size) {
 			code_ptr native_next;
 			if (!is_terminal) {
 				native_next = get_native_address(context->native_code_map, orig + (after-inst)*2);
 			}
 			if (is_terminal || (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - native_start)) > 5))) {
+				printf("Using original location: %p\n", orig_code.cur);
 				remove_deferred_until(&opts->gen.deferred, orig_deferred);
 				code_info tmp;
 				tmp.cur = code->cur;
@@ -861,7 +933,7 @@
 				m68k_handle_deferred(context);
 				return orig_start;
 			}
-		}
+		}*/
 
 		map_native_address(context, instbuf.address, native_start, (after-inst)*2, MAX_NATIVE_SIZE);
 
@@ -880,17 +952,14 @@
 		m68k_handle_deferred(context);
 		return native_start;
 	} else {
-		code_info tmp;
-		tmp.cur = code->cur;
-		tmp.last = code->last;
-		code->cur = orig_code.cur;
-		code->last = orig_code.last;
+		code_info tmp = *code;
+		*code = orig_code;
 		translate_m68k(opts, &instbuf);
+		orig_code = *code;
+		*code = tmp;
 		if (!m68k_is_terminal(&instbuf)) {
-			jmp(code, get_native_address_trans(context, orig + (after-inst)*2));
+			jmp(&orig_code, get_native_address_trans(context, orig + (after-inst)*2));
 		}
-		code->cur = tmp.cur;
-		code->last = tmp.last;
 		m68k_handle_deferred(context);
 		return orig_start;
 	}
@@ -898,19 +967,22 @@
 
 code_ptr get_native_address_trans(m68k_context * context, uint32_t address)
 {
-	address &= 0xFFFFFF;
-	code_ptr ret = get_native_address(context->native_code_map, address);
+	code_ptr ret = get_native_address(context->options, address);
 	if (!ret) {
 		translate_m68k_stream(address, context);
-		ret = get_native_address(context->native_code_map, address);
+		ret = get_native_address(context->options, address);
 	}
 	return ret;
 }
 
 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);
+	code_ptr native = get_native_address(context->options, address);
+	code_info tmp = context->options->gen.code;
+	context->options->gen.code.cur = native;
+	context->options->gen.code.last = native + MAX_NATIVE_SIZE;
+	check_cycles_int(&context->options->gen, address);
+	context->options->gen.code = tmp;
 }
 
 void start_68k_context(m68k_context * context, uint32_t address)
@@ -922,18 +994,21 @@
 
 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);
 }
 
 
-void init_68k_context(m68k_context * context, native_map_slot * native_code_map, void * opts)
+m68k_context * init_68k_context(m68k_options * opts)
 {
+	m68k_context * context = malloc(sizeof(m68k_context) + ram_size(&opts->gen) / (1 << opts->gen.ram_flags_shift) / 8);
 	memset(context, 0, sizeof(m68k_context));
-	context->native_code_map = native_code_map;
+	context->native_code_map = opts->gen.native_code_map;
 	context->options = opts;
-	context->int_cycle = 0xFFFFFFFF;
+	context->int_cycle = CYCLE_NEVER;
 	context->status = 0x27;
+	return context;
 }