diff m68k_core.c @ 587:55c5b0f913ce

Made m68k_retranslate_inst host-cpu generic and moved it to m68k_core.c
author Michael Pavone <pavone@retrodev.com>
date Fri, 07 Mar 2014 23:26:46 -0800
parents b6713c1b6f55
children 963d5901f583
line wrap: on
line diff
--- a/m68k_core.c	Fri Mar 07 19:45:05 2014 -0800
+++ b/m68k_core.c	Fri Mar 07 23:26:46 2014 -0800
@@ -674,6 +674,86 @@
 	} while(encoded != NULL);
 }
 
+void * m68k_retranslate_inst(uint32_t address, m68k_context * context)
+{
+	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);
+	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;
+	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);
+		code_ptr native_start = code->cur;
+		translate_m68k(opts, &instbuf);
+		code_ptr native_end = code->cur;
+		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))) {
+				remove_deferred_until(&opts->gen.deferred, orig_deferred);
+				code_info tmp;
+				tmp.cur = code->cur;
+				tmp.last = code->last;
+				code->cur = orig_code.cur;
+				code->last = orig_code.last;
+				translate_m68k(opts, &instbuf);
+				native_end = orig_code.cur = code->cur;
+				code->cur = tmp.cur;
+				code->last = tmp.last;
+				if (!is_terminal) {
+					nop_fill_or_jmp_next(&orig_code, orig_start + orig_size, native_next);
+				}
+				m68k_handle_deferred(context);
+				return orig_start;
+			}
+		}
+
+		map_native_address(context, instbuf.address, native_start, (after-inst)*2, MAX_NATIVE_SIZE);
+
+		jmp(&orig_code, native_start);
+		if (!m68k_is_terminal(&instbuf)) {
+			code_ptr native_end = code->cur;
+			code->cur = native_start + MAX_NATIVE_SIZE;
+			code_ptr rest = get_native_address_trans(context, orig + (after-inst)*2);
+			code_ptr tmp = code->cur;
+			code->cur = native_end;
+			jmp(code, rest);
+			code->cur = tmp;
+		} else {
+			code->cur = native_start + MAX_NATIVE_SIZE;
+		}
+		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;
+		translate_m68k(opts, &instbuf);
+		if (!m68k_is_terminal(&instbuf)) {
+			jmp(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;
+	}
+}
+
 code_ptr get_native_address_trans(m68k_context * context, uint32_t address)
 {
 	address &= 0xFFFFFF;