summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2015-11-26 22:30:41 -0800
committerMichael Pavone <pavone@retrodev.com>2015-11-26 22:30:41 -0800
commitd4911175da08bac1d7c60a0af6c3c7566dc04a54 (patch)
treeba443a89a5835f6e966ce5f03a98afa6a54382eb
parentfbd2fe929040bfd505eeed728611d7eabd2b93ea (diff)
Fix for Z80 retranslation post alignment rework
-rw-r--r--gen_x86.c23
-rw-r--r--gen_x86.h1
-rw-r--r--z80_to_x86.c15
3 files changed, 28 insertions, 11 deletions
diff --git a/gen_x86.c b/gen_x86.c
index fc5b2fe..cfc826a 100644
--- a/gen_x86.c
+++ b/gen_x86.c
@@ -1968,15 +1968,8 @@ void jmp_rind(code_info *code, uint8_t dst)
code->cur = out;
}
-void call(code_info *code, code_ptr fun)
+void call_noalign(code_info *code, code_ptr fun)
{
- code->stack_off += sizeof(void *);
- int32_t adjust = 0;
- if (code->stack_off & 0xF) {
- adjust = 16 - (code->stack_off & 0xF);
- code->stack_off += adjust;
- sub_ir(code, adjust, RSP, SZ_PTR);
- }
check_alloc_code(code, 5);
code_ptr out = code->cur;
ptrdiff_t disp = fun-(out+5);
@@ -1994,12 +1987,24 @@ void call(code_info *code, code_ptr fun)
fatal_error("call: %p - %p = %lX which is out of range for a 32-bit displacement\n", fun, out + 5, (long)disp);
}
code->cur = out;
+}
+
+
+void call(code_info *code, code_ptr fun)
+{
+ code->stack_off += sizeof(void *);
+ int32_t adjust = 0;
+ if (code->stack_off & 0xF) {
+ adjust = 16 - (code->stack_off & 0xF);
+ code->stack_off += adjust;
+ sub_ir(code, adjust, RSP, SZ_PTR);
+ }
+ call_noalign(code, fun);
if (adjust) {
add_ir(code, adjust, RSP, SZ_PTR);
}
code->stack_off -= sizeof(void *) + adjust;
}
-
void call_raxfallback(code_info *code, code_ptr fun)
{
check_alloc_code(code, 5);
diff --git a/gen_x86.h b/gen_x86.h
index 0e614dc..b836086 100644
--- a/gen_x86.h
+++ b/gen_x86.h
@@ -210,6 +210,7 @@ void btc_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
void btc_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size);
void jcc(code_info *code, uint8_t cc, code_ptr dest);
void jmp_rind(code_info *code, uint8_t dst);
+void call_noalign(code_info *code, code_ptr fun);
void call_r(code_info *code, uint8_t dst);
void retn(code_info *code);
void cdq(code_info *code);
diff --git a/z80_to_x86.c b/z80_to_x86.c
index f29840d..ab55183 100644
--- a/z80_to_x86.c
+++ b/z80_to_x86.c
@@ -2095,7 +2095,7 @@ z80_context * z80_handle_code_write(uint32_t address, z80_context * context)
uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address);
if (inst_start != INVALID_INSTRUCTION_START) {
code_ptr dst = z80_get_native_address(context, inst_start);
- code_info code = {dst, dst+16};
+ code_info code = {dst, dst+32, 0};
z80_options * opts = context->options;
dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", code.cur, inst_start, address);
mov_ir(&code, inst_start, opts->gen.scratch1, SZ_D);
@@ -2536,13 +2536,24 @@ void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t
options->retrans_stub = code->cur;
tmp_stack_off = code->stack_off;
+ //calculate size of patch
+ mov_ir(code, 0x7FFF, options->gen.scratch1, SZ_D);
+ code->stack_off += sizeof(void *);
+ if (code->stack_off & 0xF) {
+ sub_ir(code, 16 - (code->stack_off & 0xF), RSP, SZ_PTR);
+ }
+ call_noalign(code, options->retrans_stub);
+ uint32_t patch_size = code->cur - options->retrans_stub;
+ code->cur = options->retrans_stub;
+ code->stack_off = tmp_stack_off;
+
//pop return address
pop_r(code, options->gen.scratch2);
add_ir(code, 16-sizeof(void*), RSP, SZ_PTR);
code->stack_off = tmp_stack_off;
call(code, options->gen.save_context);
//adjust pointer before move and call instructions that got us here
- sub_ir(code, options->gen.scratch1 >= R8 ? 11 : 10, options->gen.scratch2, SZ_PTR);
+ sub_ir(code, patch_size, options->gen.scratch2, SZ_PTR);
push_r(code, options->gen.context_reg);
call_args(code, (code_ptr)z80_retranslate_inst, 3, options->gen.scratch1, options->gen.context_reg, options->gen.scratch2);
pop_r(code, options->gen.context_reg);