summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2017-09-13 21:06:25 -0700
committerMichael Pavone <pavone@retrodev.com>2017-09-13 21:06:25 -0700
commit44ccdde6fced7672b184be82b4eaf994c1c705c5 (patch)
tree7ee628871001a1704a9174ab600803d699dd0058
parent5ce0a0e79020bd6e9e42bc32f706b208066d7ec0 (diff)
Preserve original address when retranslating instructions instead of switching to the lowest alias
-rw-r--r--backend.h5
-rw-r--r--backend_x86.c36
-rw-r--r--gen_x86.c9
-rw-r--r--gen_x86.h1
-rw-r--r--m68k_core_x86.c14
5 files changed, 58 insertions, 7 deletions
diff --git a/backend.h b/backend.h
index a099031..b82f5a1 100644
--- a/backend.h
+++ b/backend.h
@@ -98,6 +98,8 @@ typedef struct {
uint32_t max_address;
uint32_t bus_cycles;
uint32_t clock_divider;
+ uint32_t move_pc_off;
+ uint32_t move_pc_size;
int32_t mem_ptr_off;
int32_t ram_flags_off;
uint8_t ram_flags_shift;
@@ -123,6 +125,9 @@ void check_cycles(cpu_options * opts);
void check_code_prologue(code_info *code);
void log_address(cpu_options *opts, uint32_t address, char * format);
+void retranslate_calc(cpu_options *opts);
+void patch_for_retranslate(cpu_options *opts, code_ptr native_address, code_ptr handler);
+
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);
uint16_t read_word(uint32_t address, void **mem_pointers, cpu_options *opts, void *context);
diff --git a/backend_x86.c b/backend_x86.c
index 4eca2a5..614df1b 100644
--- a/backend_x86.c
+++ b/backend_x86.c
@@ -1,5 +1,6 @@
#include "backend.h"
#include "gen_x86.h"
+#include <string.h>
void cycles(cpu_options *opts, uint32_t num)
{
@@ -28,6 +29,41 @@ void check_cycles_int(cpu_options *opts, uint32_t address)
*jmp_off = code->cur - (jmp_off+1);
}
+void retranslate_calc(cpu_options *opts)
+{
+ code_info *code = &opts->code;
+ code_info tmp = *code;
+ uint8_t cc;
+ if (opts->limit < 0) {
+ cmp_ir(code, 1, opts->cycles, SZ_D);
+ cc = CC_NS;
+ } else {
+ cmp_rr(code, opts->cycles, opts->limit, SZ_D);
+ cc = CC_A;
+ }
+ jcc(code, cc, code->cur+2);
+ opts->move_pc_off = code->cur - tmp.cur;
+ mov_ir(code, 0x1234, opts->scratch1, SZ_D);
+ opts->move_pc_size = code->cur - tmp.cur - opts->move_pc_off;
+ *code = tmp;
+}
+
+void patch_for_retranslate(cpu_options *opts, code_ptr native_address, code_ptr handler)
+{
+ if (!is_mov_ir(native_address)) {
+ //instruction is not already patched for either retranslation or a breakpoint
+ //copy original mov_ir instruction containing PC to beginning of native code area
+ memmove(native_address, native_address + opts->move_pc_off, opts->move_pc_size);
+ }
+ //jump to the retranslation handler
+ code_info tmp = {
+ .cur = native_address + opts->move_pc_size,
+ .last = native_address + 256,
+ .stack_off = 0
+ };
+ jmp(&tmp, handler);
+}
+
void check_cycles(cpu_options * opts)
{
code_info *code = &opts->code;
diff --git a/gen_x86.c b/gen_x86.c
index 2840ba0..d8dd157 100644
--- a/gen_x86.c
+++ b/gen_x86.c
@@ -1307,6 +1307,15 @@ void mov_ir(code_info *code, int64_t val, uint8_t dst, uint8_t size)
code->cur = out;
}
+uint8_t is_mov_ir(code_ptr inst)
+{
+ while (*inst == PRE_SIZE || *inst == PRE_REX)
+ {
+ inst++;
+ }
+ return (*inst & 0xF8) == OP_MOV_I8R || (*inst & 0xF8) == OP_MOV_IR || (*inst & 0xFE) == OP_MOV_IEA;
+}
+
void mov_irdisp(code_info *code, int32_t val, uint8_t dst, int32_t disp, uint8_t size)
{
check_alloc_code(code, 12);
diff --git a/gen_x86.h b/gen_x86.h
index 29de004..d384107 100644
--- a/gen_x86.h
+++ b/gen_x86.h
@@ -216,6 +216,7 @@ void call_r(code_info *code, uint8_t dst);
void retn(code_info *code);
void cdq(code_info *code);
void loop(code_info *code, code_ptr dst);
+uint8_t is_mov_ir(code_ptr inst);
#endif //GEN_X86_H_
diff --git a/m68k_core_x86.c b/m68k_core_x86.c
index 8ca25b7..c680a4b 100644
--- a/m68k_core_x86.c
+++ b/m68k_core_x86.c
@@ -2498,11 +2498,8 @@ m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context)
m68k_options * options = context->options;
uint32_t inst_start = get_instruction_start(options, address);
while (inst_start && (address - inst_start) < M68K_MAX_INST_SIZE) {
- code_info *code = &options->gen.code;
code_ptr dst = get_native_address(context->options, inst_start);
- code_info orig = {dst, dst + 128, 0};
- mov_ir(&orig, inst_start, options->gen.scratch2, SZ_D);
- jmp(&orig, options->retrans_stub);
+ patch_for_retranslate(&options->gen, dst, options->retrans_stub);
inst_start = get_instruction_start(options, inst_start - 2);
}
return context;
@@ -2531,12 +2528,13 @@ void m68k_invalidate_code_range(m68k_context *context, uint32_t start, uint32_t
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;
+ patch_for_retranslate(&opts->gen, native_code_map[chunk].base + native_code_map[chunk].offsets[offset], opts->retrans_stub);
+ /*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.scratch2, SZ_D);
- jmp(&code, opts->retrans_stub);
+ jmp(&code, opts->retrans_stub);*/
}
}
}
@@ -3182,7 +3180,7 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu
opts->retrans_stub = code->cur;
call(code, opts->gen.save_context);
push_r(code, opts->gen.context_reg);
- call_args(code,(code_ptr)m68k_retranslate_inst, 2, opts->gen.scratch2, opts->gen.context_reg);
+ call_args(code,(code_ptr)m68k_retranslate_inst, 2, opts->gen.scratch1, opts->gen.context_reg);
pop_r(code, opts->gen.context_reg);
mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR);
call(code, opts->gen.load_context);
@@ -3225,4 +3223,6 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu
add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR);
jmp_r(code, opts->gen.scratch1);
code->stack_off = tmp_stack_off;
+
+ retranslate_calc(&opts->gen);
}