Re: [PATCH] x86: floating point returning is now ABI conformant

2009-07-03 Thread Pekka Enberg
applied


--
___
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel


[PATCH] x86: floating point returning is now ABI conformant

2009-07-03 Thread Arthur Huillet
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,