summaryrefslogtreecommitdiff
path: root/m68k_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'm68k_core.c')
-rw-r--r--m68k_core.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/m68k_core.c b/m68k_core.c
index af6d544..d7a78a0 100644
--- a/m68k_core.c
+++ b/m68k_core.c
@@ -674,6 +674,86 @@ void translate_m68k_stream(uint32_t address, m68k_context * context)
} 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;