}
/* Restore the callee save registers that we used */
- offset = -(func->builder->frame_size);
- for(reg = 0; reg <= 7; ++reg)
+ if(gen->stack_changed)
{
- if(jit_reg_is_used(gen->touched, reg) &&
- (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
+ offset = -(func->builder->frame_size);
+ for(reg = 0; reg <= 7; ++reg)
{
- offset -= sizeof(void *);
- x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
- X86_EBP, offset, sizeof(void *));
+ if(jit_reg_is_used(gen->touched, reg) &&
+ (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
+ {
+ offset -= sizeof(void *);
+ x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
+ X86_EBP, offset, sizeof(void *));
+ }
+ }
+ }
+ else
+ {
+ for(reg = 7; reg >= 0; --reg)
+ {
+ if(jit_reg_is_used(gen->touched, reg) &&
+ (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
+ {
+ x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg);
+ }
}
}
/* Pop the stack frame and restore the saved copy of ebp */
- x86_mov_reg_reg(inst, X86_ESP, X86_EBP, sizeof(void *));
+ if(gen->stack_changed || func->builder->frame_size > 0)
+ {
+ x86_mov_reg_reg(inst, X86_ESP, X86_EBP, sizeof(void *));
+ }
x86_pop_reg(inst, X86_EBP);
/* Return from the current function */
JIT_OP_PUSH_INT: unary_note
[imm] -> {
x86_push_imm(inst, $1);
+ gen->stack_changed = 1;
}
[local] -> {
x86_push_membase(inst, X86_EBP, $1);
+ gen->stack_changed = 1;
}
[reg] -> {
x86_push_reg(inst, $1);
+ gen->stack_changed = 1;
}
JIT_OP_PUSH_LONG: spill_before
x86_push_membase(inst, X86_EBP, offset + 4);
x86_push_membase(inst, X86_EBP, offset);
}
+ gen->stack_changed = 1;
}
JIT_OP_PUSH_FLOAT32: unary_note, stack
[imm] -> {
jit_int *ptr = (jit_int *)($1);
x86_push_imm(inst, ptr[0]);
+ gen->stack_changed = 1;
}
[local] -> {
x86_push_membase(inst, X86_EBP, $1);
+ gen->stack_changed = 1;
}
[reg] -> {
x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_float32));
x86_fst_membase(inst, X86_ESP, 0, 0, 1);
_jit_regs_free_reg(gen, reg, 1);
+ gen->stack_changed = 1;
}
JIT_OP_PUSH_FLOAT64: unary_note, stack
jit_int *ptr = (jit_int *)($1);
x86_push_imm(inst, ptr[1]);
x86_push_imm(inst, ptr[0]);
+ gen->stack_changed = 1;
}
[local] -> {
x86_push_membase(inst, X86_EBP, $1 + 4);
x86_push_membase(inst, X86_EBP, $1);
+ gen->stack_changed = 1;
}
[reg] -> {
x86_alu_reg_imm(inst, X86_SUB, X86_ESP, sizeof(jit_float64));
x86_fst_membase(inst, X86_ESP, 0, 1, 1);
_jit_regs_free_reg(gen, reg, 1);
+ gen->stack_changed = 1;
}
JIT_OP_PUSH_NFLOAT: unary_note, stack
}
x86_push_imm(inst, ptr[1]);
x86_push_imm(inst, ptr[0]);
+ gen->stack_changed = 1;
}
[local] -> {
if(sizeof(jit_nfloat) != sizeof(jit_float64))
}
x86_push_membase(inst, X86_EBP, $1 + 4);
x86_push_membase(inst, X86_EBP, $1);
+ gen->stack_changed = 1;
}
[freg] -> {
if(sizeof(jit_nfloat) != sizeof(jit_float64))
x86_fst_membase(inst, X86_ESP, 0, 1, 1);
}
_jit_regs_free_reg(gen, reg, 1);
+ gen->stack_changed = 1;
}
JIT_OP_PUSH_STRUCT: unary_note
[reg] -> {
/* TODO */
TODO();
+ gen->stack_changed = 1;
}
JIT_OP_POP_STACK:
[] -> {
x86_alu_reg_imm(inst, X86_ADD, X86_ESP, insn->value1->address);
+ gen->stack_changed = 1;
}
JIT_OP_FLUSH_SMALL_STRUCT:
x86_alu_reg_imm(inst, X86_AND, $1, ~15);
x86_alu_reg_reg(inst, X86_SUB, X86_ESP, $1);
x86_mov_reg_reg(inst, $1, X86_ESP, 4);
+ gen->stack_changed = 1;
}