* @brief This file implements the x87 support and virtual to stack
* register translation for the ia32 backend.
* @author Michael Beck
- * @version $Id$
*/
#include "config.h"
#include "debug.h"
#include "error.h"
-#include "../belive_t.h"
-#include "../besched.h"
-#include "../benode.h"
+#include "belive_t.h"
+#include "besched.h"
+#include "benode.h"
#include "bearch_ia32_t.h"
#include "ia32_new_nodes.h"
#include "gen_ia32_new_nodes.h"
static int x87_get_depth(const x87_state *state)
{
return state->depth;
-} /* x87_get_depth */
+}
/**
* Return the virtual register index at st(pos).
{
assert(pos < state->depth);
return state->st[MASK_TOS(state->tos + pos)].reg_idx;
-} /* x87_get_st_reg */
+}
#ifdef DEBUG_libfirm
/**
{
assert(pos < state->depth);
return state->st[MASK_TOS(state->tos + pos)].node;
-} /* x87_get_st_node */
+}
/**
* Dump the stack for debugging.
x87_get_st_node(state, i)));
}
DB((dbg, LEVEL_2, "<-- TOS\n"));
-} /* x87_dump_stack */
+}
#endif /* DEBUG_libfirm */
/**
state->st[MASK_TOS(state->tos + pos)].node = node;
DB((dbg, LEVEL_2, "After SET_REG: "));
- DEBUG_ONLY(x87_dump_stack(state));
-} /* x87_set_st */
+ DEBUG_ONLY(x87_dump_stack(state);)
+}
/**
* Set the tos virtual register.
static void x87_set_tos(x87_state *state, int reg_idx, ir_node *node)
{
x87_set_st(state, reg_idx, node, 0);
-} /* x87_set_tos */
+}
/**
* Swap st(0) with st(pos).
state->st[MASK_TOS(state->tos)] = entry;
DB((dbg, LEVEL_2, "After FXCH: "));
- DEBUG_ONLY(x87_dump_stack(state));
-} /* x87_fxch */
+ DEBUG_ONLY(x87_dump_stack(state);)
+}
/**
* Convert a virtual register to the stack index.
if (state->st[MASK_TOS(tos + i)].reg_idx == reg_idx)
return i;
return -1;
-} /* x87_on_stack */
+}
/**
* Push a virtual Register onto the stack, double pushed allowed.
state->st[state->tos].reg_idx = reg_idx;
state->st[state->tos].node = node;
- DB((dbg, LEVEL_2, "After PUSH: ")); DEBUG_ONLY(x87_dump_stack(state));
-} /* x87_push_dbl */
+ DB((dbg, LEVEL_2, "After PUSH: ")); DEBUG_ONLY(x87_dump_stack(state);)
+}
/**
* Push a virtual Register onto the stack, double pushes are NOT allowed.
assert(x87_on_stack(state, reg_idx) == -1 && "double push");
x87_push_dbl(state, reg_idx, node);
-} /* x87_push */
+}
/**
* Pop a virtual Register from the stack.
--state->depth;
state->tos = MASK_TOS(state->tos + 1);
- DB((dbg, LEVEL_2, "After POP: ")); DEBUG_ONLY(x87_dump_stack(state));
-} /* x87_pop */
+ DB((dbg, LEVEL_2, "After POP: ")); DEBUG_ONLY(x87_dump_stack(state);)
+}
/**
* Empty the fpu stack
}
return PTR_TO_BLKSTATE(entry->value);
-} /* x87_get_bl_state */
+}
/**
* Creates a new x87 state.
res->sim = sim;
return res;
-} /* x87_alloc_state */
+}
/**
* Clone a x87 state.
*res = *src;
return res;
-} /* x87_clone_state */
+}
/**
* Patch a virtual instruction into a x87 one and return
} else if (mode_is_float(mode))
set_irn_mode(n, ia32_reg_classes[CLASS_ia32_st].mode);
return res;
-} /* x87_patch_insn */
+}
/**
* Returns the first Proj of a mode_T node having a given mode.
}
return NULL;
-} /* get_irn_Proj_for_mode */
+}
/**
* Wrap the arch_* function here so we can check for errors.
assert(res->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]);
return res;
-} /* x87_get_irn_register */
+}
static inline const arch_register_t *x87_irn_get_register(const ir_node *irn,
int pos)
{
- const arch_register_t *res = arch_irn_get_register(irn, pos);
+ const arch_register_t *res = arch_get_irn_register_out(irn, pos);
assert(res->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]);
return res;
-} /* x87_irn_get_register */
+}
static inline const arch_register_t *get_st_reg(int index)
{
x87_fxch(state, pos);
return fxch;
-} /* x87_fxch_shuffle */
+}
/**
* Calculate the necessary permutations to reach dst_state.
/* Hmm: permutation needed */
DB((dbg, LEVEL_2, "\n%+F needs permutation: from\n", block));
- DEBUG_ONLY(x87_dump_stack(state));
+ DEBUG_ONLY(x87_dump_stack(state);)
DB((dbg, LEVEL_2, " to\n"));
- DEBUG_ONLY(x87_dump_stack(dst_state));
+ DEBUG_ONLY(x87_dump_stack(dst_state);)
#ifdef DEBUG_libfirm
}
}
return state;
-} /* x87_shuffle */
+}
/**
* Create a fxch node before another node.
sched_add_before(n, fxch);
DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(fxch), attr->x87[0]->name, attr->x87[2]->name));
return fxch;
-} /* x87_create_fxch */
+}
/**
* Create a fpush before node n.
sched_add_before(n, fpush);
DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(fpush), attr->x87[0]->name, attr->x87[2]->name));
-} /* x87_create_fpush */
+}
/**
* Create a fpop before node n.
DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fpop), attr->x87[0]->name));
} while (--num > 0);
return fpop;
-} /* x87_create_fpop */
+}
/* --------------------------------- liveness ------------------------------------------ */
}
}
return live;
-} /* vfp_liveness_transfer */
+}
/**
* Put all live virtual registers at the end of a block into a bitset.
}
return live;
-} /* vfp_liveness_end_of_block */
+}
/** get the register mask from an arch_register */
#define REGMASK(reg) (1 << (arch_register_get_index(reg)))
assert(idx < sim->n_idx);
return sim->live[idx] & ~kill;
-} /* vfp_live_args_after */
+}
/**
* Calculate the liveness for a whole block and cache it.
}
idx = get_irn_idx(block);
sim->live[idx] = live;
-} /* update_liveness */
+}
/**
* Returns true if a register is live in a set.
}
}
DB((dbg, LEVEL_2, "\n"));
-} /* vfp_dump_live */
+}
#endif /* DEBUG_libfirm */
/* --------------------------------- simulators ---------------------------------------- */
DB((dbg, LEVEL_1, ">>> %+F %s, %s -> %s\n", n,
arch_register_get_name(op1_reg), arch_register_get_name(op2_reg),
arch_register_get_name(out)));
- DEBUG_ONLY(vfp_dump_live(live));
+ DEBUG_ONLY(vfp_dump_live(live);)
DB((dbg, LEVEL_1, "Stack before: "));
- DEBUG_ONLY(x87_dump_stack(state));
+ DEBUG_ONLY(x87_dump_stack(state);)
op1_idx = x87_on_stack(state, reg_index_1);
assert(op1_idx >= 0);
}
return NO_NODE_ADDED;
-} /* sim_binop */
+}
/**
* Simulate a virtual Unop.
unsigned live = vfp_live_args_after(sim, n, REGMASK(out));
DB((dbg, LEVEL_1, ">>> %+F -> %s\n", n, out->name));
- DEBUG_ONLY(vfp_dump_live(live));
+ DEBUG_ONLY(vfp_dump_live(live);)
op1_idx = x87_on_stack(state, arch_register_get_index(op1));
DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), out->name));
return NO_NODE_ADDED;
-} /* sim_unop */
+}
/**
* Simulate a virtual Load instruction.
DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), arch_register_get_name(out)));
return NO_NODE_ADDED;
-} /* sim_load */
+}
/**
* Rewire all users of @p old_val to @new_val iff they are scheduled after @p store.
}
}
}
-} /* collect_and_rewire_users */
+}
/**
* Simulate a virtual Store.
DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
return insn;
-} /* sim_store */
+}
#define _GEN_BINOP(op, rev) \
static int sim_##op(x87_state *state, ir_node *n) { \
DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
return NO_NODE_ADDED;
-} /* sim_fisttp */
+}
/**
* Simulate a virtual FtstFnstsw.
unsigned live = vfp_live_args_after(sim, n, 0);
DB((dbg, LEVEL_1, ">>> %+F %s\n", n, arch_register_get_name(reg1)));
- DEBUG_ONLY(vfp_dump_live(live));
+ DEBUG_ONLY(vfp_dump_live(live);)
DB((dbg, LEVEL_1, "Stack before: "));
- DEBUG_ONLY(x87_dump_stack(state));
+ DEBUG_ONLY(x87_dump_stack(state);)
assert(op1_idx >= 0);
if (op1_idx != 0) {
x87_create_fpop(state, sched_next(n), 1);
return NO_NODE_ADDED;
-} /* sim_FtstFnstsw */
+}
/**
* Simulate a Fucom
DB((dbg, LEVEL_1, ">>> %+F %s, %s\n", n,
arch_register_get_name(op1), arch_register_get_name(op2)));
- DEBUG_ONLY(vfp_dump_live(live));
+ DEBUG_ONLY(vfp_dump_live(live);)
DB((dbg, LEVEL_1, "Stack before: "));
- DEBUG_ONLY(x87_dump_stack(state));
+ DEBUG_ONLY(x87_dump_stack(state);)
op1_idx = x87_on_stack(state, reg_index_1);
assert(op1_idx >= 0);
}
return NO_NODE_ADDED;
-} /* sim_Fucom */
+}
/**
* Simulate a Keep.
}
DB((dbg, LEVEL_1, "Stack after: "));
- DEBUG_ONLY(x87_dump_stack(state));
+ DEBUG_ONLY(x87_dump_stack(state);)
return NO_NODE_ADDED;
-} /* sim_Keep */
+}
/**
* Keep the given node alive by adding a be_Keep.
arch_set_irn_register(res, out);
return res;
-} /* create_Copy */
+}
/**
* Simulate a be_Copy.
int op1_idx, out_idx;
unsigned live;
- cls = arch_get_irn_reg_class_out(n);
+ cls = arch_get_irn_reg_class(n);
if (cls != &ia32_reg_classes[CLASS_ia32_vfp])
return 0;
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));
+ DEBUG_ONLY(vfp_dump_live(live);)
op1_idx = x87_on_stack(state, arch_register_get_index(op1));
}
}
return NO_NODE_ADDED;
-} /* sim_Copy */
+}
/**
* Returns the vf0 result Proj of a Call.
}
return NULL;
-} /* get_call_result_proj */
+}
/**
* Simulate a ia32_Call.
end_call:
DB((dbg, LEVEL_1, "Stack after: "));
- DEBUG_ONLY(x87_dump_stack(state));
+ DEBUG_ONLY(x87_dump_stack(state);)
return NO_NODE_ADDED;
-} /* sim_Call */
+}
/**
* Simulate a be_Return.
x87_pop(state);
return NO_NODE_ADDED;
-} /* sim_Return */
+}
typedef struct perm_data_t {
const arch_register_t *in;
DB((dbg, LEVEL_1, "<<< %+F\n", irn));
return NO_NODE_ADDED;
-} /* sim_Perm */
+}
/**
* Kill any dead registers at block start by popping them from the stack.
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));
+ DEBUG_ONLY(vfp_dump_live(live);)
+ DEBUG_ONLY(x87_dump_stack(state);)
if (kill_mask != 0 && live == 0) {
/* special case: kill all registers */
keep_alive(keep);
}
return state;
-} /* x87_kill_deads */
+}
/**
* Run a simulation and fix all virtual instructions for a block.
DB((dbg, LEVEL_1, "Simulate %+F\n", block));
DB((dbg, LEVEL_2, "State at Block begin:\n "));
- DEBUG_ONLY(x87_dump_stack(state));
+ DEBUG_ONLY(x87_dump_stack(state);)
/* at block begin, kill all dead registers */
state = x87_kill_deads(sim, block, state);
start_block = get_irg_start_block(get_irn_irg(block));
- DB((dbg, LEVEL_2, "State at Block end:\n ")); DEBUG_ONLY(x87_dump_stack(state));
+ DB((dbg, LEVEL_2, "State at Block end:\n ")); DEBUG_ONLY(x87_dump_stack(state);)
/* check if the state must be shuffled */
foreach_block_succ(block, edge) {
if (succ_state->begin == NULL) {
DB((dbg, LEVEL_2, "Set begin state for succ %+F:\n", succ));
- DEBUG_ONLY(x87_dump_stack(state));
+ DEBUG_ONLY(x87_dump_stack(state);)
succ_state->begin = state;
waitq_put(sim->worklist, succ);
}
}
bl_state->end = state;
-} /* x87_simulate_block */
+}
/**
* Register a simulator function.
{
assert(op->ops.generic == NULL);
op->ops.generic = (op_func) func;
-} /* register_sim */
+}
/**
* Create a new x87 simulator.
register_sim(op_be_Return, sim_Return);
register_sim(op_be_Perm, sim_Perm);
register_sim(op_be_Keep, sim_Keep);
-} /* x87_init_simulator */
+}
/**
* Destroy a x87 simulator.
pmap_destroy(sim->blk_states);
obstack_free(&sim->obst, NULL);
DB((dbg, LEVEL_1, "x87 Simulator stopped\n\n"));
-} /* x87_destroy_simulator */
+}
/**
* Pre-block walker: calculate the liveness information for the block
{
x87_simulator *sim = (x87_simulator*)data;
update_liveness(sim, block);
-} /* update_liveness_walker */
+}
/*
* Run a simulation and fix all virtual instructions for a graph.
/* kill it */
del_waitq(sim.worklist);
x87_destroy_simulator(&sim);
-} /* ia32_x87_simulate_graph */
+}
/* Initializes the x87 simulator. */
void ia32_init_x87(void)
{
FIRM_DBG_REGISTER(dbg, "firm.be.ia32.x87");
-} /* ia32_init_x87 */
+}