} else {
op2_idx = x87_on_stack(state, op2_reg_idx);
live_after_node = is_vfp_live(arch_register_get_index(op2), live);
- assert(op2_idx >= 0);
DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_register_get_name(op2)));
+ assert(op2_idx >= 0);
}
mode = get_ia32_ls_mode(n);
GEN_UNOP(fabs)
GEN_UNOP(fchs)
-GEN_UNOP(fsin)
-GEN_UNOP(fcos)
-GEN_UNOP(fsqrt)
GEN_LOAD(fld)
GEN_LOAD(fild)
ia32_x87_attr_t *attr;
ir_op *dst;
x87_simulator *sim = state->sim;
- const arch_register_t *op1 = x87_get_irn_register(sim, get_irn_n(n, BINOP_IDX_1));
- const arch_register_t *op2 = x87_get_irn_register(sim, get_irn_n(n, BINOP_IDX_2));
+ ir_node *op1_node = get_irn_n(n, n_ia32_vfCondJmp_left);
+ ir_node *op2_node = get_irn_n(n, n_ia32_vfCondJmp_right);
+ const arch_register_t *op1 = x87_get_irn_register(sim, op1_node);
+ const arch_register_t *op2 = x87_get_irn_register(sim, op2_node);
int reg_index_1 = arch_register_get_index(op1);
int reg_index_2 = arch_register_get_index(op2);
unsigned live = vfp_live_args_after(sim, n, 0);
return state;
} /* x87_kill_deads */
+/**
+ * If we have PhiEs with unknown operands then we have to make sure that some
+ * value is actually put onto the stack.
+ */
+static void fix_unknown_phis(x87_state *state, ir_node *block,
+ ir_node *pred_block, int pos)
+{
+ ir_node *node, *op;
+
+ sched_foreach(block, node) {
+ ir_node *zero;
+ const arch_register_t *reg;
+ ia32_x87_attr_t *attr;
+
+ if(!is_Phi(node))
+ break;
+
+ op = get_Phi_pred(node, pos);
+ if(!is_ia32_Unknown_VFP(op))
+ continue;
+
+ reg = arch_get_irn_register(state->sim->arch_env, node);
+
+ /* create a zero at end of pred block */
+ zero = new_rd_ia32_fldz(NULL, current_ir_graph, pred_block, mode_E);
+ x87_push(state, arch_register_get_index(reg), zero);
+
+ attr = get_ia32_x87_attr(zero);
+ attr->x87[2] = &ia32_st_regs[0];
+
+ assert(is_ia32_fldz(zero));
+ sched_add_before(sched_last(pred_block), zero);
+
+ set_Phi_pred(node, pos, zero);
+ }
+}
+
/**
* Run a simulation and fix all virtual instructions for a block.
*
/* 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);
/* beware, n might change */
for (n = sched_first(block); !sched_is_end(n); n = next) {
func = (sim_func)op->ops.generic;
- /* have work to do */
- if (state == bl_state->begin) {
- /* create a new state, will be changed */
- state = x87_clone_state(sim, state);
- }
-
/* simulate it */
node_inserted = (*func)(state, n);
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));
+
/* check if the state must be shuffled */
foreach_block_succ(block, edge) {
ir_node *succ = get_edge_src_irn(edge);
succ_state = x87_get_bl_state(sim, succ);
+ fix_unknown_phis(state, succ, block, get_edge_src_pos(edge));
+
if (succ_state->begin == NULL) {
+ DB((dbg, LEVEL_2, "Set begin state for succ %+F:\n", succ));
+ DEBUG_ONLY(x87_dump_stack(state));
succ_state->begin = state;
+
waitq_put(sim->worklist, succ);
} else {
+ DB((dbg, LEVEL_2, "succ %+F already has a state, shuffling\n", succ));
/* There is already a begin state for the successor, bad.
Do the necessary permutations.
Note that critical edges are removed, so this is always possible:
}
}
bl_state->end = state;
-
- DB((dbg, LEVEL_2, "State at Block end:\n ")); DEBUG_ONLY(x87_dump_stack(state));
} /* x87_simulate_block */
/**
ASSOC_IA32(fprem);
ASSOC_IA32(fabs);
ASSOC_IA32(fchs);
- ASSOC_IA32(fsin);
- ASSOC_IA32(fcos);
- ASSOC_IA32(fsqrt);
ASSOC_IA32(fist);
ASSOC_IA32(fst);
ASSOC_IA32(fCondJmp);