We use the top of the x87 stack as is specified by the i386 SystemV ABI.
Signed-off-by: Arthur Huillet arthur.huil...@free.fr
---
arch/x86/emit-code.c| 12 +++
arch/x86/include/arch/instruction.h |3 +
arch/x86/insn-selector_32.brg | 126 ++-
arch/x86/instruction.c | 10 +++
arch/x86/lir-printer.c | 14
arch/x86/use-def.c |2 +
include/jit/expression.h|8 ++-
jit/expression.c| 20 ++
jit/invoke-bc.c | 18 -
jit/tree-printer.c |2 +
10 files changed, 210 insertions(+), 5 deletions(-)
diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c
index bb5b299..2a63e50 100644
--- a/arch/x86/emit-code.c
+++ b/arch/x86/emit-code.c
@@ -894,6 +894,16 @@ static void emit_fdiv_reg_reg(struct buffer *buf,
emit_reg_reg(buf, 0x5e, dest, src);
}
+static void emit_fld_membase(struct buffer *buf, struct operand *src)
+{
+ __emit_membase(buf, 0xd9, mach_reg(src-base_reg), src-disp, 0);
+}
+
+static void emit_fstp_membase(struct buffer *buf, struct operand *dest)
+{
+ __emit_membase(buf, 0xd9, mach_reg(dest-base_reg), dest-disp, 3);
+}
+
static void emit_add_membase_reg(struct buffer *buf,
struct operand *src, struct operand *dest)
{
@@ -1207,6 +1217,8 @@ struct emitter emitters[] = {
DECL_EMITTER(INSN_FSUB_REG_REG, emit_fsub_reg_reg, TWO_OPERANDS),
DECL_EMITTER(INSN_FMUL_REG_REG, emit_fmul_reg_reg, TWO_OPERANDS),
DECL_EMITTER(INSN_FDIV_REG_REG, emit_fdiv_reg_reg, TWO_OPERANDS),
+ DECL_EMITTER(INSN_FLD_MEMBASE, emit_fld_membase, TWO_OPERANDS),
+ DECL_EMITTER(INSN_FSTP_MEMBASE, emit_fstp_membase, TWO_OPERANDS),
DECL_EMITTER(INSN_CONV_GPR_TO_FPU, emit_conv_gpr_to_fpu, TWO_OPERANDS),
DECL_EMITTER(INSN_CONV_FPU_TO_GPR, emit_conv_fpu_to_gpr, TWO_OPERANDS),
DECL_EMITTER(INSN_MOV_MEMBASE_XMM, emit_mov_membase_xmm, TWO_OPERANDS),
diff --git a/arch/x86/include/arch/instruction.h
b/arch/x86/include/arch/instruction.h
index 056480f..42c3fbb 100644
--- a/arch/x86/include/arch/instruction.h
+++ b/arch/x86/include/arch/instruction.h
@@ -74,6 +74,8 @@ enum insn_type {
INSN_FMUL_REG_REG,
INSN_FDIV_REG_REG,
INSN_FSUB_REG_REG,
+ INSN_FLD_MEMBASE,
+ INSN_FSTP_MEMBASE,
INSN_CONV_FPU_TO_GPR,
INSN_CONV_GPR_TO_FPU,
INSN_JE_BRANCH,
@@ -197,6 +199,7 @@ struct insn *imm_insn(enum insn_type, unsigned long);
struct insn *rel_insn(enum insn_type, unsigned long);
struct insn *branch_insn(enum insn_type, struct basic_block *);
struct insn *memlocal_insn(enum insn_type, struct stack_slot *);
+struct insn *membase_insn(enum insn_type, struct var_info *, long);
/*
* These functions are used by generic code to insert spill/reload
diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg
index 86d81b9..1ba67b9 100644
--- a/arch/x86/insn-selector_32.brg
+++ b/arch/x86/insn-selector_32.brg
@@ -705,6 +705,63 @@ reg: EXPR_INVOKE(arg) 1
select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, edx,
state-reg2));
}
+freg: EXPR_FINVOKE(arg) 1
+{
+ struct compilation_unit *cu;
+ struct vm_method *method;
+ struct expression *expr;
+ struct insn *call_insn;
+ bool is_compiled;
+ void *target;
+ struct var_info *esp;
+
+ expr= to_expr(tree);
+ method = expr-target_method;
+ cu = method-compilation_unit;
+
+ if (cu == s-b_parent) {
+ /*
+* This is a recursive method invocation. Threfore, we are
+* already holding cu-mutex here because we entered
+* instruction selection through jit_magic_trampoline().
+*/
+ is_compiled = false;
+ target = vm_method_trampoline_ptr(method);
+ } else {
+ pthread_mutex_lock(cu-mutex);
+ is_compiled = cu-is_compiled;
+
+ if (is_compiled)
+ target = vm_method_native_ptr(method);
+ else
+ target = vm_method_trampoline_ptr(method);
+
+ pthread_mutex_unlock(cu-mutex);
+ }
+
+ state-reg1 = get_fpu_var(s-b_parent);
+
+ call_insn = rel_insn(INSN_CALL_REL, (unsigned long) target);
+ select_insn(s, tree, call_insn);
+
+ if (!is_compiled) {
+ struct fixup_site *fixup;
+
+ fixup = alloc_fixup_site();
+ fixup-cu = s-b_parent;
+ fixup-relcall_insn = call_insn;
+
+ trampoline_add_fixup_site(method-trampoline, fixup);
+ }
+
+ if (method-args_count)
+ method_args_cleanup(s, tree, method-args_count);
+
+ esp = get_fixed_var(s-b_parent, REG_ESP);
+ select_insn(s, tree, membase_insn(INSN_FSTP_MEMBASE, esp,