+
+ return NO_NODE_ADDED;
+} /* sim_Return */
+
+typedef struct _perm_data_t {
+ const arch_register_t *in;
+ const arch_register_t *out;
+} perm_data_t;
+
+/**
+ * Simulate a be_Perm.
+ *
+ * @param state the x87 state
+ * @param irn the node that should be simulated (and patched)
+ *
+ * @return NO_NODE_ADDED
+ */
+static int sim_Perm(x87_state *state, ir_node *irn) {
+ int i, n;
+ x87_simulator *sim = state->sim;
+ ir_node *pred = get_irn_n(irn, 0);
+ int *stack_pos;
+ const ir_edge_t *edge;
+
+ /* handle only floating point Perms */
+ if (! mode_is_float(get_irn_mode(pred)))
+ return NO_NODE_ADDED;
+
+ DB((dbg, LEVEL_1, ">>> %+F\n", irn));
+
+ /* Perm is a pure virtual instruction on x87.
+ All inputs must be on the FPU stack and are pairwise
+ different from each other.
+ So, all we need to do is to permutate the stack state. */
+ n = get_irn_arity(irn);
+ NEW_ARR_A(int, stack_pos, n);
+
+ /* collect old stack positions */
+ for (i = 0; i < n; ++i) {
+ const arch_register_t *inreg = x87_get_irn_register(sim, get_irn_n(irn, i));
+ int idx = x87_on_stack(state, arch_register_get_index(inreg));
+
+ assert(idx >= 0 && "Perm argument not on x87 stack");
+
+ stack_pos[i] = idx;
+ }
+ /* now do the permutation */
+ foreach_out_edge(irn, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ const arch_register_t *out = x87_get_irn_register(sim, proj);
+ long num = get_Proj_proj(proj);
+
+ assert(0 <= num && num < n && "More Proj's than Perm inputs");
+ x87_set_st(state, arch_register_get_index(out), proj, stack_pos[(unsigned)num]);
+ }
+ DB((dbg, LEVEL_1, "<<< %+F\n", irn));
+
+ return NO_NODE_ADDED;
+} /* sim_Perm */
+
+static int sim_Barrier(x87_state *state, ir_node *node) {
+ //const arch_env_t *arch_env = state->sim->arch_env;
+ int i, arity;
+
+ /* materialize unknown if needed */
+ arity = get_irn_arity(node);
+ for(i = 0; i < arity; ++i) {
+ const arch_register_t *reg;
+ ir_node *zero;
+ ir_node *block;
+ ia32_x87_attr_t *attr;
+ ir_node *in = get_irn_n(node, i);
+
+ if(!is_ia32_Unknown_VFP(in))
+ continue;
+
+ /* TODO: not completely correct... */
+ reg = &ia32_vfp_regs[REG_VFP_UKNWN];
+
+ /* create a zero */
+ block = get_nodes_block(node);
+ zero = new_rd_ia32_fldz(NULL, current_ir_graph, 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];
+
+ sched_add_before(node, zero);
+
+ set_irn_n(node, i, zero);
+ }
+
+ return NO_NODE_ADDED;