summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend_x86.c1
-rw-r--r--gen.c1
-rw-r--r--gen.h4
-rw-r--r--gen_x86.c40
-rw-r--r--m68k_core.c4
-rw-r--r--m68k_core_x86.c12
-rw-r--r--z80_to_x86.c2
7 files changed, 60 insertions, 4 deletions
diff --git a/backend_x86.c b/backend_x86.c
index 56b0f8d..2892f83 100644
--- a/backend_x86.c
+++ b/backend_x86.c
@@ -173,6 +173,7 @@ code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk const * memmap, uint32_t n
pop_r(code, opts->scratch2);
} else {
add_ir(code, sizeof(void*), RSP, SZ_D);
+ code->stack_off -= sizeof(void *);
}
} else {
push_r(code, opts->scratch2);
diff --git a/gen.c b/gen.c
index 52be6a0..dafe5af 100644
--- a/gen.c
+++ b/gen.c
@@ -12,4 +12,5 @@ void init_code_info(code_info *code)
fatal_error("Failed to allocate memory for generated code\n");
}
code->last = code->cur + size/sizeof(code_word) - RESERVE_WORDS;
+ code->stack_off = 0;
}
diff --git a/gen.h b/gen.h
index 5087b57..16dcab8 100644
--- a/gen.h
+++ b/gen.h
@@ -15,6 +15,7 @@ typedef code_word * code_ptr;
typedef struct {
code_ptr cur;
code_ptr last;
+ uint32_t stack_off;
} code_info;
void check_alloc_code(code_info *code, uint32_t inst_size);
@@ -26,7 +27,8 @@ void jmp_r(code_info *code, uint8_t dst);
//call a function and put the arguments in the appropriate place according to the host ABI
void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...);
//like the above, but follows other aspects of the ABI like stack alignment
-void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...);
+//void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...);
+#define call_args_abi call_args
void save_callee_save_regs(code_info *code);
void restore_callee_save_regs(code_info *code);
diff --git a/gen_x86.c b/gen_x86.c
index 3860236..fc5b2fe 100644
--- a/gen_x86.c
+++ b/gen_x86.c
@@ -1592,6 +1592,7 @@ void push_r(code_info *code, uint8_t reg)
}
*(out++) = OP_PUSH | reg;
code->cur = out;
+ code->stack_off += sizeof(void *);
}
void push_rdisp(code_info *code, uint8_t base, int32_t disp)
@@ -1599,6 +1600,7 @@ void push_rdisp(code_info *code, uint8_t base, int32_t disp)
//This instruction has no explicit size, so we pass SZ_B
//to avoid any prefixes or bits being set
x86_rdisp_size(code, OP_SINGLE_EA, OP_EX_PUSH_EA, base, disp, SZ_B);
+ code->stack_off += sizeof(void *);
}
void pop_r(code_info *code, uint8_t reg)
@@ -1611,6 +1613,7 @@ void pop_r(code_info *code, uint8_t reg)
}
*(out++) = OP_POP | reg;
code->cur = out;
+ code->stack_off -= sizeof(void *);
}
void pop_rind(code_info *code, uint8_t reg)
@@ -1624,6 +1627,7 @@ void pop_rind(code_info *code, uint8_t reg)
*(out++) = PRE_XOP;
*(out++) = MODE_REG_INDIRECT | reg;
code->cur = out;
+ code->stack_off -= sizeof(void *);
}
void setcc_r(code_info *code, uint8_t cc, uint8_t dst)
@@ -1966,6 +1970,13 @@ void jmp_rind(code_info *code, uint8_t dst)
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);
+ }
check_alloc_code(code, 5);
code_ptr out = code->cur;
ptrdiff_t disp = fun-(out+5);
@@ -1983,6 +1994,10 @@ 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;
+ if (adjust) {
+ add_ir(code, adjust, RSP, SZ_PTR);
+ }
+ code->stack_off -= sizeof(void *) + adjust;
}
void call_raxfallback(code_info *code, code_ptr fun)
@@ -2008,11 +2023,22 @@ void call_raxfallback(code_info *code, code_ptr fun)
void call_r(code_info *code, uint8_t dst)
{
+ 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, 2);
code_ptr out = code->cur;
*(out++) = OP_SINGLE_EA;
*(out++) = MODE_REG_DIRECT | dst | (OP_EX_CALL_EA << 3);
code->cur = out;
+ if (adjust) {
+ add_ir(code, adjust, RSP, SZ_PTR);
+ }
+ code->stack_off -= sizeof(void *) + adjust;
}
void retn(code_info *code)
@@ -2084,8 +2110,15 @@ uint32_t prep_args(code_info *code, uint32_t num_args, va_list args)
{
push_r(code, arg_arr[i]);
}
+ uint32_t stack_off_call = code->stack_off + sizeof(void *);
+ uint32_t adjust = 0;
+ if (stack_off_call & 0xF) {
+ adjust = 16 - (stack_off_call & 0xF);
+ sub_ir(code, adjust, RSP, SZ_PTR);
+ code->stack_off += adjust;
+ }
- return stack_args * sizeof(void *);
+ return stack_args * sizeof(void *) + adjust;
}
void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...)
@@ -2097,9 +2130,10 @@ void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...)
call_raxfallback(code, fun);
if (adjust) {
add_ir(code, adjust, RSP, SZ_PTR);
+ code->stack_off -= adjust;
}
}
-
+/*
void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...)
{
va_list args;
@@ -2125,7 +2159,7 @@ void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...)
*no_adjust_rsp = code->cur - (no_adjust_rsp+1);
#endif
}
-
+*/
void save_callee_save_regs(code_info *code)
{
push_r(code, RBX);
diff --git a/m68k_core.c b/m68k_core.c
index 6a7283f..f751fe8 100644
--- a/m68k_core.c
+++ b/m68k_core.c
@@ -827,6 +827,10 @@ void translate_m68k(m68k_options * opts, m68kinst * inst)
m68k_disasm(inst, disasm_buf);
fatal_error("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op);
}
+ if (opts->gen.code.stack_off) {
+ m68k_disasm(inst, disasm_buf);
+ fatal_error("Stack offset is %X after %X: %s\n", opts->gen.code.stack_off, inst->address, disasm_buf);
+ }
}
void translate_m68k_stream(uint32_t address, m68k_context * context)
diff --git a/m68k_core_x86.c b/m68k_core_x86.c
index 59f92bc..d4958ad 100644
--- a/m68k_core_x86.c
+++ b/m68k_core_x86.c
@@ -1674,6 +1674,7 @@ void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, hos
set_flag(opts, 0, FLAG_C);
push_r(code, RDX);
push_r(code, RAX);
+ uint32_t tmp_stack_off = code->stack_off;
if (dst_op->mode == MODE_REG_DIRECT) {
mov_rr(code, dst_op->base, RAX, SZ_D);
} else {
@@ -1717,6 +1718,8 @@ void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, hos
mov_ir(code, VECTOR_INT_DIV_ZERO, opts->gen.scratch2, SZ_D);
mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
jmp(code, opts->trap);
+
+ code->stack_off = tmp_stack_off;
*not_zero = code->cur - (not_zero+1);
if (inst->op == M68K_DIVS) {
cdq(code);
@@ -1761,6 +1764,7 @@ void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, hos
}
code_ptr end_off = code->cur + 1;
jmp(code, code->cur + 2);
+ code->stack_off = tmp_stack_off;
*norm_off = code->cur - (norm_off + 1);
if (inst->op == M68K_DIVS) {
*skip_sec_check = code->cur - (skip_sec_check+1);
@@ -2514,9 +2518,14 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu
jcc(code, CC_NZ, do_ret);
retn(code);
*do_ret = code->cur - (do_ret+1);
+ uint32_t tmp_stack_off = code->stack_off;
+ //fetch return address and adjust RSP
pop_r(code, opts->gen.scratch1);
+ add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
+ //save return address for restoring later
mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, resume_pc), SZ_PTR);
retn(code);
+ code->stack_off = tmp_stack_off;
*do_int = code->cur - (do_int+1);
//implement 1 instruction latency
cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
@@ -2593,9 +2602,12 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chu
call(code, opts->native_addr_and_sync);
//2 prefetch bus operations + 2 idle bus cycles
cycles(&opts->gen, 10);
+ tmp_stack_off = code->stack_off;
//discard function return address
pop_r(code, opts->gen.scratch2);
+ add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
jmp_r(code, opts->gen.scratch1);
+ code->stack_off = tmp_stack_off;
opts->trap = code->cur;
push_r(code, opts->gen.scratch2);
diff --git a/z80_to_x86.c b/z80_to_x86.c
index a114da3..4dacbba 100644
--- a/z80_to_x86.c
+++ b/z80_to_x86.c
@@ -2695,6 +2695,7 @@ void zcreate_stub(z80_context * context)
{
z80_options * opts = context->options;
code_info *code = &opts->gen.code;
+ uint32_t start_stack_off = code->stack_off;
check_code_prologue(code);
context->bp_stub = code->cur;
@@ -2727,6 +2728,7 @@ void zcreate_stub(z80_context * context)
pop_r(code, opts->gen.scratch1);
add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR);
jmp_r(code, opts->gen.scratch1);
+ code->stack_off = start_stack_off;
}
void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler)