Pass the value to be pushed to x87_create_fpush().
[libfirm] / ir / be / ia32 / ia32_x87.c
index 917d575..2b1e41a 100644 (file)
@@ -52,8 +52,6 @@
 #include "ia32_x87.h"
 #include "ia32_architecture.h"
 
-#define MASK_TOS(x)    ((x) & (N_ia32_st_REGS - 1))
-
 /** the debug handle */
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
@@ -78,23 +76,21 @@ typedef struct exchange_tmpl {
  * An entry on the simulated x87 stack.
  */
 typedef struct st_entry {
-       int     reg_idx;        /**< the virtual register index of this stack value */
-       ir_node *node;          /**< the node that produced this value */
+       int      reg_idx; /**< the virtual register index of this stack value */
+       ir_node *node;    /**< the node that produced this value */
 } st_entry;
 
 /**
  * The x87 state.
  */
 typedef struct x87_state {
-       st_entry st[N_ia32_st_REGS]; /**< the register stack */
-       int depth;                   /**< the current stack depth */
-       int tos;                     /**< position of the tos */
-       x87_simulator *sim;          /**< The simulator. */
+       st_entry       st[N_ia32_st_REGS]; /**< the register stack */
+       int            depth;              /**< the current stack depth */
+       x87_simulator *sim;                /**< The simulator. */
 } x87_state;
 
 /** An empty state, used for blocks without fp instructions. */
-static x87_state _empty = { { {0, NULL}, }, 0, 0, NULL };
-static x87_state *empty = (x87_state *)&_empty;
+static x87_state empty = { { {0, NULL}, }, 0, NULL };
 
 /**
  * Return values of the instruction simulator functions.
@@ -132,12 +128,12 @@ typedef unsigned char vfp_liveness;
  * The x87 simulator.
  */
 struct x87_simulator {
-       struct obstack obst;        /**< An obstack for fast allocating. */
-       pmap *blk_states;           /**< Map blocks to states. */
-       be_lv_t *lv;                /**< intrablock liveness. */
-       vfp_liveness *live;         /**< Liveness information. */
-       unsigned n_idx;             /**< The cached get_irg_last_idx() result. */
-       waitq *worklist;            /**< Worklist of blocks that must be processed. */
+       struct obstack obst;       /**< An obstack for fast allocating. */
+       pmap          *blk_states; /**< Map blocks to states. */
+       be_lv_t       *lv;         /**< intrablock liveness. */
+       vfp_liveness  *live;       /**< Liveness information. */
+       unsigned       n_idx;      /**< The cached get_irg_last_idx() result. */
+       waitq         *worklist;   /**< Worklist of blocks that must be processed. */
 };
 
 /**
@@ -152,6 +148,12 @@ static int x87_get_depth(const x87_state *state)
        return state->depth;
 }
 
+static st_entry *x87_get_entry(x87_state *const state, int const pos)
+{
+       assert(0 <= pos && pos < state->depth);
+       return &state->st[N_ia32_st_REGS - state->depth + pos];
+}
+
 /**
  * Return the virtual register index at st(pos).
  *
@@ -162,25 +164,10 @@ static int x87_get_depth(const x87_state *state)
  */
 static int x87_get_st_reg(const x87_state *state, int pos)
 {
-       assert(pos < state->depth);
-       return state->st[MASK_TOS(state->tos + pos)].reg_idx;
+       return x87_get_entry((x87_state*)state, pos)->reg_idx;
 }
 
 #ifdef DEBUG_libfirm
-/**
- * Return the node at st(pos).
- *
- * @param state  the x87 state
- * @param pos    a stack position
- *
- * @return the IR node that produced the value at st(pos)
- */
-static ir_node *x87_get_st_node(const x87_state *state, int pos)
-{
-       assert(pos < state->depth);
-       return state->st[MASK_TOS(state->tos + pos)].node;
-}
-
 /**
  * Dump the stack for debugging.
  *
@@ -188,11 +175,9 @@ static ir_node *x87_get_st_node(const x87_state *state, int pos)
  */
 static void x87_dump_stack(const x87_state *state)
 {
-       int i;
-
-       for (i = state->depth - 1; i >= 0; --i) {
-               DB((dbg, LEVEL_2, "vf%d(%+F) ", x87_get_st_reg(state, i),
-                   x87_get_st_node(state, i)));
+       for (int i = state->depth; i-- != 0;) {
+               st_entry const *const entry = x87_get_entry((x87_state*)state, i);
+               DB((dbg, LEVEL_2, "vf%d(%+F) ", entry->reg_idx, entry->node));
        }
        DB((dbg, LEVEL_2, "<-- TOS\n"));
 }
@@ -208,9 +193,9 @@ static void x87_dump_stack(const x87_state *state)
  */
 static void x87_set_st(x87_state *state, int reg_idx, ir_node *node, int pos)
 {
-       assert(0 < state->depth);
-       state->st[MASK_TOS(state->tos + pos)].reg_idx = reg_idx;
-       state->st[MASK_TOS(state->tos + pos)].node    = node;
+       st_entry *const entry = x87_get_entry(state, pos);
+       entry->reg_idx = reg_idx;
+       entry->node    = node;
 
        DB((dbg, LEVEL_2, "After SET_REG: "));
        DEBUG_ONLY(x87_dump_stack(state);)
@@ -236,12 +221,11 @@ static void x87_set_tos(x87_state *state, int reg_idx, ir_node *node)
  */
 static void x87_fxch(x87_state *state, int pos)
 {
-       st_entry entry;
-       assert(pos < state->depth);
-
-       entry = state->st[MASK_TOS(state->tos + pos)];
-       state->st[MASK_TOS(state->tos + pos)] = state->st[MASK_TOS(state->tos)];
-       state->st[MASK_TOS(state->tos)] = entry;
+       st_entry *const a = x87_get_entry(state, pos);
+       st_entry *const b = x87_get_entry(state, 0);
+       st_entry  const t = *a;
+       *a = *b;
+       *b = t;
 
        DB((dbg, LEVEL_2, "After FXCH: "));
        DEBUG_ONLY(x87_dump_stack(state);)
@@ -258,11 +242,10 @@ static void x87_fxch(x87_state *state, int pos)
  */
 static int x87_on_stack(const x87_state *state, int reg_idx)
 {
-       int i, tos = state->tos;
-
-       for (i = 0; i < state->depth; ++i)
-               if (state->st[MASK_TOS(tos + i)].reg_idx == reg_idx)
+       for (int i = 0; i < state->depth; ++i) {
+               if (x87_get_st_reg(state, i) == reg_idx)
                        return i;
+       }
        return -1;
 }
 
@@ -278,9 +261,9 @@ static void x87_push_dbl(x87_state *state, int reg_idx, ir_node *node)
        assert(state->depth < N_ia32_st_REGS && "stack overrun");
 
        ++state->depth;
-       state->tos = MASK_TOS(state->tos - 1);
-       state->st[state->tos].reg_idx = reg_idx;
-       state->st[state->tos].node    = node;
+       st_entry *const entry = x87_get_entry(state, 0);
+       entry->reg_idx = reg_idx;
+       entry->node    = node;
 
        DB((dbg, LEVEL_2, "After PUSH: ")); DEBUG_ONLY(x87_dump_stack(state);)
 }
@@ -309,7 +292,6 @@ static void x87_pop(x87_state *state)
        assert(state->depth > 0 && "stack underrun");
 
        --state->depth;
-       state->tos = MASK_TOS(state->tos + 1);
 
        DB((dbg, LEVEL_2, "After POP: ")); DEBUG_ONLY(x87_dump_stack(state);)
 }
@@ -322,7 +304,6 @@ static void x87_pop(x87_state *state)
 static void x87_emms(x87_state *state)
 {
        state->depth = 0;
-       state->tos   = 0;
 }
 
 /**
@@ -348,21 +329,6 @@ static blk_state *x87_get_bl_state(x87_simulator *sim, ir_node *block)
        return res;
 }
 
-/**
- * Creates a new x87 state.
- *
- * @param sim    the x87 simulator handle
- *
- * @return a new x87 state
- */
-static x87_state *x87_alloc_state(x87_simulator *sim)
-{
-       x87_state *res = OALLOC(&sim->obst, x87_state);
-
-       res->sim = sim;
-       return res;
-}
-
 /**
  * Clone a x87 state.
  *
@@ -373,8 +339,7 @@ static x87_state *x87_alloc_state(x87_simulator *sim)
  */
 static x87_state *x87_clone_state(x87_simulator *sim, const x87_state *src)
 {
-       x87_state *res = x87_alloc_state(sim);
-
+       x87_state *const res = OALLOC(&sim->obst, x87_state);
        *res = *src;
        return res;
 }
@@ -510,19 +475,18 @@ static x87_state *x87_shuffle(ir_node *block, x87_state *state, const x87_state
        assert(state->depth == dst_state->depth);
 
        /* Some mathematics here:
-          If we have a cycle of length n that includes the tos,
-          we need n-1 exchange operations.
-          We can always add the tos and restore it, so we need
-          n+1 exchange operations for a cycle not containing the tos.
-          So, the maximum of needed operations is for a cycle of 7
-          not including the tos == 8.
-          This is the same number of ops we would need for using stores,
-          so exchange is cheaper (we save the loads).
-          On the other hand, we might need an additional exchange
-          in the next block to bring one operand on top, so the
-          number of ops in the first case is identical.
-          Further, no more than 4 cycles can exists (4 x 2).
-       */
+        * If we have a cycle of length n that includes the tos,
+        * we need n-1 exchange operations.
+        * We can always add the tos and restore it, so we need
+        * n+1 exchange operations for a cycle not containing the tos.
+        * So, the maximum of needed operations is for a cycle of 7
+        * not including the tos == 8.
+        * This is the same number of ops we would need for using stores,
+        * so exchange is cheaper (we save the loads).
+        * On the other hand, we might need an additional exchange
+        * in the next block to bring one operand on top, so the
+        * number of ops in the first case is identical.
+        * Further, no more than 4 cycles can exists (4 x 2). */
        all_mask = (1 << (state->depth)) - 1;
 
        for (n_cycles = 0; all_mask; ++n_cycles) {
@@ -655,18 +619,15 @@ static ir_node *x87_create_fxch(x87_state *state, ir_node *n, int pos)
  * @param state     the x87 state
  * @param n         the node after the fpush
  * @param pos       push st(pos) on stack
- * @param op_idx    replace input op_idx of n with the fpush result
+ * @param val       the value to push
  */
-static void x87_create_fpush(x87_state *state, ir_node *n, int pos, int op_idx)
+static void x87_create_fpush(x87_state *state, ir_node *n, int pos, ir_node *const val)
 {
-       ir_node               *fpush, *pred = get_irn_n(n, op_idx);
-       ia32_x87_attr_t       *attr;
-       const arch_register_t *out = x87_get_irn_register(pred);
+       arch_register_t const *const out = x87_get_irn_register(val);
+       x87_push_dbl(state, arch_register_get_index(out), val);
 
-       x87_push_dbl(state, arch_register_get_index(out), pred);
-
-       fpush = new_bd_ia32_fpush(NULL, get_nodes_block(n));
-       attr  = get_ia32_x87_attr(fpush);
+       ir_node         *const fpush = new_bd_ia32_fpush(NULL, get_nodes_block(n));
+       ia32_x87_attr_t *const attr  = get_ia32_x87_attr(fpush);
        attr->x87[0] = get_st_reg(pos);
        attr->x87[2] = get_st_reg(0);
 
@@ -912,7 +873,7 @@ static int sim_binop(x87_state *state, ir_node *n, const exchange_tmpl *tmpl)
                        if (op1_live_after) {
                                /* Both operands are live: push the first one.
                                   This works even for op1 == op2. */
-                               x87_create_fpush(state, n, op1_idx, n_ia32_binary_right);
+                               x87_create_fpush(state, n, op1_idx, op2);
                                /* now do fxxx (tos=tos X op) */
                                op1_idx = 0;
                                op2_idx += 1;
@@ -988,7 +949,7 @@ static int sim_binop(x87_state *state, ir_node *n, const exchange_tmpl *tmpl)
                /* second operand is an address mode */
                if (op1_live_after) {
                        /* first operand is live: push it here */
-                       x87_create_fpush(state, n, op1_idx, n_ia32_binary_left);
+                       x87_create_fpush(state, n, op1_idx, op1);
                        op1_idx = 0;
                } else {
                        /* first operand is dead: bring it to tos */
@@ -1040,21 +1001,18 @@ static int sim_binop(x87_state *state, ir_node *n, const exchange_tmpl *tmpl)
  */
 static int sim_unop(x87_state *state, ir_node *n, ir_op *op)
 {
-       x87_simulator         *sim = state->sim;
-       const arch_register_t *op1 = x87_get_irn_register(get_irn_n(n, 0));
-       const arch_register_t *out = x87_get_irn_register(n);
-       ia32_x87_attr_t *attr;
-       unsigned live = vfp_live_args_after(sim, n, REGMASK(out));
-
+       arch_register_t const *const out  = x87_get_irn_register(n);
+       unsigned               const live = vfp_live_args_after(state->sim, n, REGMASK(out));
        DB((dbg, LEVEL_1, ">>> %+F -> %s\n", n, out->name));
        DEBUG_ONLY(vfp_dump_live(live);)
 
-       int op1_idx = x87_on_stack(state, arch_register_get_index(op1));
-
-       if (is_vfp_live(arch_register_get_index(op1), live)) {
+       ir_node               *const op1         = get_irn_n(n, 0);
+       arch_register_t const *const op1_reg     = x87_get_irn_register(op1);
+       int                    const op1_reg_idx = arch_register_get_index(op1_reg);
+       int                    const op1_idx     = x87_on_stack(state, op1_reg_idx);
+       if (is_vfp_live(op1_reg_idx, live)) {
                /* push the operand here */
-               x87_create_fpush(state, n, op1_idx, 0);
-               op1_idx = 0;
+               x87_create_fpush(state, n, op1_idx, op1);
        } else {
                /* operand is dead, bring it to tos */
                if (op1_idx != 0) {
@@ -1063,10 +1021,9 @@ static int sim_unop(x87_state *state, ir_node *n, ir_op *op)
        }
 
        x87_set_tos(state, arch_register_get_index(out), x87_patch_insn(n, op));
-       attr = get_ia32_x87_attr(n);
-       attr->x87[0] = op1 = get_st_reg(0);
-       attr->x87[2] = out = get_st_reg(0);
-       DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), out->name));
+       ia32_x87_attr_t *const attr = get_ia32_x87_attr(n);
+       attr->x87[2] = attr->x87[0] = get_st_reg(0);
+       DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), attr->x87[2]->name));
 
        return NO_NODE_ADDED;
 }
@@ -1132,50 +1089,39 @@ static void collect_and_rewire_users(ir_node *store, ir_node *old_val, ir_node *
  */
 static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p)
 {
-       ir_node               *val = get_irn_n(n, n_ia32_vfst_val);
-       const arch_register_t *op2 = x87_get_irn_register(val);
-       unsigned              live = vfp_live_args_after(state->sim, n, 0);
-       int                   insn = NO_NODE_ADDED;
-       ia32_x87_attr_t *attr;
-       int op2_reg_idx, op2_idx, depth;
-       int live_after_node;
-       ir_mode *mode;
-
-       op2_reg_idx = arch_register_get_index(op2);
-       op2_idx = x87_on_stack(state, op2_reg_idx);
-       live_after_node = is_vfp_live(arch_register_get_index(op2), live);
+       ir_node               *const val = get_irn_n(n, n_ia32_vfst_val);
+       arch_register_t const *const op2 = x87_get_irn_register(val);
        DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_register_get_name(op2)));
-       assert(op2_idx >= 0);
-
-       mode  = get_ia32_ls_mode(n);
-       depth = x87_get_depth(state);
 
+       int            insn            = NO_NODE_ADDED;
+       int      const op2_reg_idx     = arch_register_get_index(op2);
+       int      const op2_idx         = x87_on_stack(state, op2_reg_idx);
+       unsigned const live            = vfp_live_args_after(state->sim, n, 0);
+       int      const live_after_node = is_vfp_live(op2_reg_idx, live);
+       assert(op2_idx >= 0);
        if (live_after_node) {
-               /*
-                       Problem: fst doesn't support 96bit modes (spills), only fstp does
-                                fist doesn't support 64bit mode, only fistp
-                       Solution:
-                               - stack not full: push value and fstp
-                               - stack full: fstp value and load again
-                       Note that we cannot test on mode_E, because floats might be 96bit ...
-               */
-               if (get_mode_size_bits(mode) > 64 || (mode_is_int(mode) && get_mode_size_bits(mode) > 32)) {
-                       if (depth < N_ia32_st_REGS) {
+               /* Problem: fst doesn't support 80bit modes (spills), only fstp does
+                *          fist doesn't support 64bit mode, only fistp
+                * Solution:
+                *   - stack not full: push value and fstp
+                *   - stack full: fstp value and load again
+                * Note that we cannot test on mode_E, because floats might be 80bit ... */
+               ir_mode *const mode = get_ia32_ls_mode(n);
+               if (get_mode_size_bits(mode) > (mode_is_int(mode) ? 32 : 64)) {
+                       if (x87_get_depth(state) < N_ia32_st_REGS) {
                                /* ok, we have a free register: push + fstp */
-                               x87_create_fpush(state, n, op2_idx, n_ia32_vfst_val);
+                               x87_create_fpush(state, n, op2_idx, val);
                                x87_pop(state);
                                x87_patch_insn(n, op_p);
                        } else {
-                               ir_node  *vfld, *mem, *block, *rproj, *mproj;
-                               ir_graph *irg   = get_irn_irg(n);
-                               ir_node  *nomem = get_irg_no_mem(irg);
-
                                /* stack full here: need fstp + load */
                                x87_pop(state);
                                x87_patch_insn(n, op_p);
 
-                               block = get_nodes_block(n);
-                               vfld  = new_bd_ia32_vfld(NULL, block, get_irn_n(n, 0), get_irn_n(n, 1), nomem, get_ia32_ls_mode(n));
+                               ir_node  *const block = get_nodes_block(n);
+                               ir_graph *const irg   = get_irn_irg(n);
+                               ir_node  *const nomem = get_irg_no_mem(irg);
+                               ir_node  *const vfld  = new_bd_ia32_vfld(NULL, block, get_irn_n(n, 0), get_irn_n(n, 1), nomem, mode);
 
                                /* copy all attributes */
                                set_ia32_frame_ent(vfld, get_ia32_frame_ent(n));
@@ -1184,11 +1130,11 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p)
                                set_ia32_op_type(vfld, ia32_AddrModeS);
                                add_ia32_am_offs_int(vfld, get_ia32_am_offs_int(n));
                                set_ia32_am_sc(vfld, get_ia32_am_sc(n));
-                               set_ia32_ls_mode(vfld, get_ia32_ls_mode(n));
+                               set_ia32_ls_mode(vfld, mode);
 
-                               rproj = new_r_Proj(vfld, get_ia32_ls_mode(vfld), pn_ia32_vfld_res);
-                               mproj = new_r_Proj(vfld, mode_M, pn_ia32_vfld_M);
-                               mem   = get_irn_Proj_for_mode(n, mode_M);
+                               ir_node *const rproj = new_r_Proj(vfld, mode, pn_ia32_vfld_res);
+                               ir_node *const mproj = new_r_Proj(vfld, mode_M, pn_ia32_vfld_M);
+                               ir_node *const mem   = get_irn_Proj_for_mode(n, mode_M);
 
                                assert(mem && "Store memory not found");
 
@@ -1224,9 +1170,9 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p)
                x87_patch_insn(n, op_p);
        }
 
-       attr = get_ia32_x87_attr(n);
-       attr->x87[1] = op2 = get_st_reg(0);
-       DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
+       ia32_x87_attr_t *const attr = get_ia32_x87_attr(n);
+       attr->x87[1] = get_st_reg(0);
+       DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), arch_register_get_name(attr->x87[1])));
 
        return insn;
 }
@@ -1731,33 +1677,23 @@ static ir_node *create_Copy(x87_state *state, ir_node *n)
  */
 static int sim_Copy(x87_state *state, ir_node *n)
 {
-       ir_node                     *pred;
-       const arch_register_t       *out;
-       const arch_register_t       *op1;
-       const arch_register_class_t *cls;
-       ir_node                     *node, *next;
-       int                         op1_idx, out_idx;
-       unsigned                    live;
-
-       cls = arch_get_irn_reg_class(n);
+       arch_register_class_t const *const cls = arch_get_irn_reg_class(n);
        if (cls != &ia32_reg_classes[CLASS_ia32_vfp])
-               return 0;
+               return NO_NODE_ADDED;
 
-       pred = be_get_Copy_op(n);
-       out  = x87_get_irn_register(n);
-       op1  = x87_get_irn_register(pred);
-       live = vfp_live_args_after(state->sim, n, REGMASK(out));
+       ir_node               *const pred = be_get_Copy_op(n);
+       arch_register_t const *const op1  = x87_get_irn_register(pred);
+       arch_register_t const *const out  = x87_get_irn_register(n);
+       unsigned               const live = vfp_live_args_after(state->sim, n, REGMASK(out));
 
        DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", n,
                arch_register_get_name(op1), arch_register_get_name(out)));
        DEBUG_ONLY(vfp_dump_live(live);)
 
-       op1_idx = x87_on_stack(state, arch_register_get_index(op1));
-
        if (is_vfp_live(arch_register_get_index(op1), live)) {
                /* Operand is still live, a real copy. We need here an fpush that can
                   hold a a register, so use the fpushCopy or recreate constants */
-               node = create_Copy(state, n);
+               ir_node *const node = create_Copy(state, n);
 
                /* We have to make sure the old value doesn't go dead (which can happen
                 * when we recreate constants). As the simulator expected that value in
@@ -1765,7 +1701,7 @@ static int sim_Copy(x87_state *state, ir_node *n)
                 * instruction, but we would have to rerun all the simulation to get
                 * this correct...
                 */
-               next = sched_next(n);
+               ir_node *const next = sched_next(n);
                sched_remove(n);
                exchange(n, node);
                sched_add_before(next, node);
@@ -1776,8 +1712,8 @@ static int sim_Copy(x87_state *state, ir_node *n)
 
                DB((dbg, LEVEL_1, "<<< %+F %s -> ?\n", node, op1->name));
        } else {
-               out_idx = x87_on_stack(state, arch_register_get_index(out));
-
+               int const op1_idx = x87_on_stack(state, arch_register_get_index(op1));
+               int const out_idx = x87_on_stack(state, arch_register_get_index(out));
                if (out_idx >= 0 && out_idx != op1_idx) {
                        /* Matze: out already on stack? how can this happen? */
                        panic("invalid stack state");
@@ -1840,7 +1776,7 @@ static ir_node *get_call_result_proj(ir_node *call)
                        return proj;
        }
 
-       return NULL;
+       panic("result Proj missing");
 }
 
 static int sim_Asm(x87_state *const state, ir_node *const n)
@@ -1872,38 +1808,24 @@ static int sim_Asm(x87_state *const state, ir_node *const n)
  */
 static int sim_Call(x87_state *state, ir_node *n)
 {
-       ir_type *call_tp = get_ia32_call_attr_const(n)->call_tp;
-       ir_type *res_type;
-       ir_mode *mode;
-       ir_node *resproj;
-       const arch_register_t *reg;
-
        DB((dbg, LEVEL_1, ">>> %+F\n", n));
 
        /* at the begin of a call the x87 state should be empty */
        assert(state->depth == 0 && "stack not empty before call");
 
-       if (get_method_n_ress(call_tp) <= 0)
-               goto end_call;
-
-       /*
-        * If the called function returns a float, it is returned in st(0).
-        * This even happens if the return value is NOT used.
-        * Moreover, only one return result is supported.
-        */
-       res_type = get_method_res_type(call_tp, 0);
-       mode     = get_type_mode(res_type);
-
-       if (mode == NULL || !mode_is_float(mode))
-               goto end_call;
-
-       resproj = get_call_result_proj(n);
-       assert(resproj != NULL);
-
-       reg = x87_get_irn_register(resproj);
-       x87_push(state, arch_register_get_index(reg), resproj);
-
-end_call:
+       ir_type *const call_tp = get_ia32_call_attr_const(n)->call_tp;
+       if (get_method_n_ress(call_tp) != 0) {
+               /* If the called function returns a float, it is returned in st(0).
+                * This even happens if the return value is NOT used.
+                * Moreover, only one return result is supported. */
+               ir_type *const res_type = get_method_res_type(call_tp, 0);
+               ir_mode *const mode     = get_type_mode(res_type);
+               if (mode && mode_is_float(mode)) {
+                       ir_node               *const resproj = get_call_result_proj(n);
+                       arch_register_t const *const reg     = x87_get_irn_register(resproj);
+                       x87_push(state, arch_register_get_index(reg), resproj);
+               }
+       }
        DB((dbg, LEVEL_1, "Stack after: "));
        DEBUG_ONLY(x87_dump_stack(state);)
 
@@ -1990,15 +1912,12 @@ static int sim_Perm(x87_state *state, ir_node *irn)
 /**
  * Kill any dead registers at block start by popping them from the stack.
  *
- * @param sim          the simulator handle
- * @param block        the current block
- * @param start_state  the x87 state at the begin of the block
- *
- * @return the x87 state after dead register killed
+ * @param sim    the simulator handle
+ * @param block  the current block
+ * @param state  the x87 state at the begin of the block
  */
-static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *start_state)
+static void x87_kill_deads(x87_simulator *const sim, ir_node *const block, x87_state *const state)
 {
-       x87_state *state = start_state;
        ir_node *first_insn = sched_first(block);
        ir_node *keep = NULL;
        unsigned live = vfp_live_args_after(sim, block, 0);
@@ -2015,9 +1934,6 @@ static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *
        }
 
        if (kill_mask) {
-               /* create a new state, will be changed */
-               state = x87_clone_state(sim, state);
-
                DB((dbg, LEVEL_1, "Killing deads:\n"));
                DEBUG_ONLY(vfp_dump_live(live);)
                DEBUG_ONLY(x87_dump_stack(state);)
@@ -2035,7 +1951,7 @@ static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *
                                sched_add_before(first_insn, keep);
                                keep_alive(keep);
                                x87_emms(state);
-                               return state;
+                               return;
                        }
                }
                /* now kill registers */
@@ -2071,7 +1987,6 @@ static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *
                }
                keep_alive(keep);
        }
-       return state;
 }
 
 /**
@@ -2096,10 +2011,10 @@ static void x87_simulate_block(x87_simulator *sim, ir_node *block)
        DB((dbg, LEVEL_2, "State at Block begin:\n "));
        DEBUG_ONLY(x87_dump_stack(state);)
 
-       /* at block begin, kill all dead registers */
-       state = x87_kill_deads(sim, block, state);
        /* create a new state, will be changed */
        state = x87_clone_state(sim, state);
+       /* at block begin, kill all dead registers */
+       x87_kill_deads(sim, block, state);
 
        /* beware, n might change */
        for (n = sched_first(block); !sched_is_end(n); n = next) {
@@ -2261,8 +2176,8 @@ void ia32_x87_simulate_graph(ir_graph *irg)
        bl_state    = x87_get_bl_state(&sim, start_block);
 
        /* start with the empty state */
-       bl_state->begin = empty;
-       empty->sim      = &sim;
+       empty.sim       = &sim;
+       bl_state->begin = &empty;
 
        sim.worklist = new_waitq();
        waitq_put(sim.worklist, start_block);