2 * This file implements the x87 support and virtual to stack
3 * register translation for the ia32 backend.
5 * @author: Michael Beck
12 #endif /* HAVE_CONFIG_H */
19 #include "iredges_t.h"
28 #include "../belive_t.h"
29 #include "../besched_t.h"
30 #include "../benode_t.h"
31 #include "ia32_new_nodes.h"
32 #include "gen_ia32_new_nodes.h"
33 #include "gen_ia32_regalloc_if.h"
38 /* first and second binop index */
45 /* the store val index */
46 #define STORE_VAL_IDX 2
48 #define MASK_TOS(x) ((x) & (N_x87_REGS - 1))
50 /** the debug handle */
51 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
53 /* Forward declaration. */
54 typedef struct _x87_simulator x87_simulator;
57 * An exchange template.
58 * Note that our virtual functions have the same inputs
59 * and attributes as the real ones, so we can simple exchange
61 * Further, x87 supports inverse instructions, so we can handle them.
63 typedef struct _exchange_tmpl {
64 ir_op *normal_op; /**< the normal one */
65 ir_op *reverse_op; /**< the reverse one if exists */
66 ir_op *normal_pop_op; /**< the normal one with tos pop */
67 ir_op *reverse_pop_op; /**< the reverse one with tos pop */
71 * An entry on the simulated x87 stack.
73 typedef struct _st_entry {
74 int reg_idx; /**< the virtual register index of this stack value */
75 ir_node *node; /**< the node that produced this value */
81 typedef struct _x87_state {
82 st_entry st[N_x87_REGS]; /**< the register stack */
83 int depth; /**< the current stack depth */
84 int tos; /**< position of the tos */
85 x87_simulator *sim; /**< The simulator. */
88 /** An empty state, used for blocks without fp instructions. */
89 static x87_state _empty = { { {0, NULL}, }, 0, 0 };
90 static x87_state *empty = (x87_state *)&_empty;
92 /** The type of an instruction simulator */
93 typedef int (*sim_func)(x87_state *state, ir_node *n, const arch_env_t *env);
96 * A block state: Every block has a x87 state at the beginning and at the end.
98 typedef struct _blk_state {
99 x87_state *begin; /**< state at the begin or NULL if not assigned */
100 x87_state *end; /**< state at the end or NULL if not assigned */
103 #define PTR_TO_BLKSTATE(p) ((blk_state *)(p))
108 struct _x87_simulator {
109 struct obstack obst; /**< an obstack for fast allocating */
110 pmap *blk_states; /**< map blocks to states */
111 const arch_env_t *env; /**< architecture environment */
112 be_lv_t *lv; /**< Liveness information. */
116 * Returns the stack depth.
118 * @param state the x87 state
120 * @return the x87 stack depth
122 static int x87_get_depth(const x87_state *state) {
127 * Check if the state is empty.
129 * @param state the x87 state
131 * returns non-zero if the x87 stack is empty
133 static int x87_state_is_empty(const x87_state *state) {
134 return state->depth == 0;
138 * Return the virtual register index at st(pos).
140 * @param state the x87 state
141 * @param pos a stack position
143 * @return the vfp register index that produced the value at st(pos)
145 static int x87_get_st_reg(const x87_state *state, int pos) {
146 assert(pos < state->depth);
147 return state->st[MASK_TOS(state->tos + pos)].reg_idx;
151 * Return the node at st(pos).
153 * @param state the x87 state
154 * @param pos a stack position
156 * @return the IR node that produced the value at st(pos)
158 static ir_node *x87_get_st_node(const x87_state *state, int pos) {
159 assert(pos < state->depth);
160 return state->st[MASK_TOS(state->tos + pos)].node;
165 * Dump the stack for debugging.
167 * @param state the x87 state
169 static void x87_dump_stack(const x87_state *state) {
172 for (i = state->depth - 1; i >= 0; --i) {
173 DB((dbg, LEVEL_2, "vf%d ", x87_get_st_reg(state, i)));
175 DB((dbg, LEVEL_2, "<-- TOS\n"));
177 #endif /* DEBUG_libfirm */
180 * Set a virtual register to st(pos).
182 * @param state the x87 state
183 * @param reg_idx the vfp register index that should be set
184 * @param node the IR node that produces the value of the vfp register
185 * @param pos the stack position where the new value should be entered
187 static void x87_set_st(x87_state *state, int reg_idx, ir_node *node, int pos) {
188 assert(0 < state->depth);
189 state->st[MASK_TOS(state->tos + pos)].reg_idx = reg_idx;
190 state->st[MASK_TOS(state->tos + pos)].node = node;
192 DB((dbg, LEVEL_2, "After SET_REG:\n ")); DEBUG_ONLY(x87_dump_stack(state));
196 * Set the tos virtual register.
198 * @param state the x87 state
199 * @param reg_idx the vfp register index that should be set
200 * @param node the IR node that produces the value of the vfp register
202 static void x87_set_tos(x87_state *state, int reg_idx, ir_node *node) {
203 x87_set_st(state, reg_idx, node, 0);
207 * Flush the x87 stack.
209 * @param state the x87 state
211 static void x87_flush(x87_state *state) {
217 * Swap st(0) with st(pos).
219 * @param state the x87 state
220 * @param pos the stack position to change the tos with
222 static void x87_fxch(x87_state *state, int pos) {
224 assert(pos < state->depth);
226 entry = state->st[MASK_TOS(state->tos + pos)];
227 state->st[MASK_TOS(state->tos + pos)] = state->st[MASK_TOS(state->tos)];
228 state->st[MASK_TOS(state->tos)] = entry;
230 DB((dbg, LEVEL_2, "After FXCH:\n ")); DEBUG_ONLY(x87_dump_stack(state));
234 * Convert a virtual register to the stack index.
236 * @param state the x87 state
237 * @param reg_idx the register vfp index
239 * @return the stack position where the register is stacked
240 * or -1 if the virtual register was not found
242 static int x87_on_stack(const x87_state *state, int reg_idx) {
243 int i, tos = state->tos;
245 for (i = 0; i < state->depth; ++i)
246 if (state->st[MASK_TOS(tos + i)].reg_idx == reg_idx)
252 * Push a virtual Register onto the stack.
254 * @param state the x87 state
255 * @param reg_idx the register vfp index
256 * @param node the node that produces the value of the vfp register
257 * @param dbl_push if != 0 double pushes are allowd
259 static void x87_push(x87_state *state, int reg_idx, ir_node *node, int dbl_push) {
260 assert((dbl_push || x87_on_stack(state, reg_idx) == -1) && "double push");
261 assert(state->depth < N_x87_REGS && "stack overrun");
264 state->tos = MASK_TOS(state->tos - 1);
265 state->st[state->tos].reg_idx = reg_idx;
266 state->st[state->tos].node = node;
268 DB((dbg, LEVEL_2, "After PUSH:\n ")); DEBUG_ONLY(x87_dump_stack(state));
272 * Pop a virtual Register from the stack.
274 static void x87_pop(x87_state *state) {
275 assert(state->depth > 0 && "stack underrun");
278 state->tos = MASK_TOS(state->tos + 1);
280 DB((dbg, LEVEL_2, "After POP:\n ")); DEBUG_ONLY(x87_dump_stack(state));
284 * Returns the block state of a block.
286 * @param sim the x87 simulator handle
287 * @param block the current block
289 * @return the block state
291 static blk_state *x87_get_bl_state(x87_simulator *sim, ir_node *block) {
292 pmap_entry *entry = pmap_find(sim->blk_states, block);
295 blk_state *bl_state = obstack_alloc(&sim->obst, sizeof(*bl_state));
296 bl_state->begin = NULL;
297 bl_state->end = NULL;
299 pmap_insert(sim->blk_states, block, bl_state);
303 return entry ? PTR_TO_BLKSTATE(entry->value) : NULL;
307 * Creates a new x87 state.
309 * @param sim the x87 simulator handle
310 * @return a new x87 state
312 static x87_state *x87_alloc_state(x87_simulator *sim) {
313 x87_state *res = obstack_alloc(&sim->obst, sizeof(*res));
319 * Create a new empty x87 state.
321 * @param sim the x87 simulator handle
322 * @return a new empty x87 state
324 static x87_state *x87_alloc_empty_state(x87_simulator *sim) {
325 x87_state *res = x87_alloc_state(sim);
334 * @param sim the x87 simulator handle
335 * @param src the x87 state that will be cloned
337 * @return a cloned copy of the src state
339 static x87_state *x87_clone_state(x87_simulator *sim, const x87_state *src) {
340 x87_state *res = x87_alloc_state(sim);
342 memcpy(res, src, sizeof(*res));
347 * Patch a virtual instruction into a x87 one and return
350 * @param n the IR node to patch
351 * @param op the x87 opcode to patch in
353 static ir_node *x87_patch_insn(ir_node *n, ir_op *op) {
354 ir_mode *mode = get_irn_mode(n);
359 if (mode == mode_T) {
360 /* patch all Proj's */
361 const ir_edge_t *edge;
363 foreach_out_edge(n, edge) {
364 ir_node *proj = get_edge_src_irn(edge);
366 mode = get_irn_mode(proj);
367 if (mode_is_float(mode)) {
369 set_irn_mode(proj, mode_E);
374 else if (mode_is_float(mode))
375 set_irn_mode(n, mode_E);
380 * Returns the first Proj of a mode_T node having a given mode.
382 * @param n the mode_T node
383 * @param m the desired mode of the Proj
384 * @return The first Proj of mode @p m found or NULL.
386 static ir_node *get_irn_Proj_for_mode(ir_node *n, ir_mode *m) {
387 const ir_edge_t *edge;
389 assert(get_irn_mode(n) == mode_T && "Need mode_T node");
391 foreach_out_edge(n, edge) {
392 ir_node *proj = get_edge_src_irn(edge);
393 if (get_irn_mode(proj) == m)
400 /* -------------- x87 perm --------------- */
403 * Creates a fxch for shuffle.
405 * @param state the x87 state
406 * @param pos parameter for fxch
407 * @param dst_block the block of the user
409 * Creates a new fxch node and reroute the user of the old node
412 * @return the fxch node
414 static ir_node *x87_fxch_shuffle(x87_state *state, int pos, ir_node *block, ir_node *dst_block)
416 const ir_edge_t *edge;
417 ir_node *n = x87_get_st_node(state, pos);
418 ir_node *user = NULL;
423 if (block == get_nodes_block(n)) {
424 /* this is a node from out block: change it's user */
425 foreach_out_edge(n, edge) {
426 ir_node *succ = get_edge_src_irn(edge);
428 if (is_Phi(succ) && get_nodes_block(succ) == dst_block) {
430 node_idx = get_edge_src_pos(edge);
437 fxch = new_rd_ia32_fxch(NULL, get_irn_irg(block), block, n, get_irn_mode(n));
438 attr = get_ia32_attr(fxch);
439 attr->x87[0] = &ia32_st_regs[pos];
440 attr->x87[2] = &ia32_st_regs[0];
443 DB((dbg, LEVEL_2, "%+F replaced input %d of %+F\n", fxch, node_idx, user));
444 set_irn_n(user, node_idx, fxch);
448 * This is a node from a dominator block. Changing it's user might be wrong,
449 * so just keep it alive.
450 * The "right" solution would require a new Phi, but we don't care here.
455 x87_fxch(state, pos);
460 * Calculate the necessary permutations to reach dst_state.
462 * These permutations are done with fxch instructions and placed
463 * at the end of the block.
465 * Note that critical edges are removed here, so we need only
466 * a shuffle if the current block has only one successor.
468 * @param sim the simulator handle
469 * @param block the current block
470 * @param state the current x87 stack state, might be modified
471 * @param dst_block the destination block
472 * @param dst_state destination state
476 static x87_state *x87_shuffle(x87_simulator *sim, ir_node *block, x87_state *state, ir_node *dst_block, const x87_state *dst_state) {
477 int i, n_cycles, k, ri;
478 unsigned cycles[4], all_mask;
479 char cycle_idx[4][8];
481 ir_node *before, *after;
483 assert(state->depth == dst_state->depth);
485 /* Some mathematics here:
486 If we have a cycle of lenght n that includes the tos,
487 we need n-1 exchange operations.
488 We can always add the tos and restore it, so we need
489 n+1 exchange operations for a cycle not containing the tos.
490 So, the maximum of needed operations is for a cycle of 7
491 not including the tos == 8.
492 This is so same number of ops we would need for store,
493 so exchange is cheaper (we save the loads).
494 On the other hand, we might need an additional exchange
495 in the next block to bring one operand on top, so the
496 number of ops in the first case is identical.
497 Further, no more than 4 cycles can exists.
499 all_mask = (1 << (state->depth)) - 1;
501 for (n_cycles = 0; all_mask; ++n_cycles) {
502 int src_idx, dst_idx;
504 /* find the first free slot */
505 for (i = 0; i < state->depth; ++i) {
506 if (all_mask & (1 << i)) {
507 all_mask &= ~(1 << i);
509 /* check if there are differences here */
510 if (x87_get_st_reg(state, i) != x87_get_st_reg(dst_state, i))
516 /* no more cycles found */
521 cycles[n_cycles] = (1 << i);
522 cycle_idx[n_cycles][k++] = i;
523 for (src_idx = i; ; src_idx = dst_idx) {
524 dst_idx = x87_on_stack(dst_state, x87_get_st_reg(state, src_idx));
526 if ((all_mask & (1 << dst_idx)) == 0)
529 cycle_idx[n_cycles][k++] = dst_idx;
530 cycles[n_cycles] |= (1 << dst_idx);
531 all_mask &= ~(1 << dst_idx);
533 cycle_idx[n_cycles][k] = -1;
537 /* no permutation needed */
541 /* Hmm: permutation needed */
542 DB((dbg, LEVEL_2, "\n%+F needs permutation: from\n", block));
543 DEBUG_ONLY(x87_dump_stack(state));
544 DB((dbg, LEVEL_2, " to\n"));
545 DEBUG_ONLY(x87_dump_stack(dst_state));
549 DB((dbg, LEVEL_2, "Need %d cycles\n", n_cycles));
550 for (ri = 0; ri < n_cycles; ++ri) {
551 DB((dbg, LEVEL_2, " Ring %d:\n ", ri));
552 for (k = 0; cycle_idx[ri][k] != -1; ++k)
553 DB((dbg, LEVEL_2, " st%d ->", cycle_idx[ri][k]));
554 DB((dbg, LEVEL_2, "\n"));
561 * Find the place node must be insert.
562 * We have only one successor block, so the last instruction should
565 before = sched_last(block);
566 assert(is_cfop(before));
568 /* now do the permutations */
569 for (ri = 0; ri < n_cycles; ++ri) {
570 if ((cycles[ri] & 1) == 0) {
571 /* this cycle does not include the tos */
572 fxch = x87_fxch_shuffle(state, cycle_idx[ri][0], block, dst_block);
574 sched_add_after(after, fxch);
576 sched_add_before(before, fxch);
579 for (k = 1; cycle_idx[ri][k] != -1; ++k) {
580 fxch = x87_fxch_shuffle(state, cycle_idx[ri][k], block, dst_block);
582 sched_add_after(after, fxch);
584 sched_add_before(before, fxch);
587 if ((cycles[ri] & 1) == 0) {
588 /* this cycle does not include the tos */
589 fxch = x87_fxch_shuffle(state, cycle_idx[ri][0], block, dst_block);
590 sched_add_after(after, fxch);
597 * Create a fxch node before another node.
599 * @param state the x87 state
600 * @param n the node before the fxch
601 * @param pos exchange st(pos) with st(0)
602 * @param op_idx if >= 0, replace input op_idx of n with the fxch result
606 static ir_node *x87_create_fxch(x87_state *state, ir_node *n, int pos, int op_idx) {
607 ir_node *fxch, *pred;
610 x87_fxch(state, pos);
613 pred = get_irn_n(n, op_idx);
615 pred = x87_get_st_node(state, pos);
617 fxch = new_rd_ia32_fxch(NULL, get_irn_irg(n), get_nodes_block(n), pred, get_irn_mode(pred));
618 attr = get_ia32_attr(fxch);
619 attr->x87[0] = &ia32_st_regs[pos];
620 attr->x87[2] = &ia32_st_regs[0];
623 set_irn_n(n, op_idx, fxch);
625 sched_add_before(n, fxch);
626 DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(fxch), attr->x87[0]->name, attr->x87[2]->name));
631 * Create a fpush before node n.
633 * @param state the x87 state
634 * @param n the node before the fpush
635 * @param pos push st(pos) on stack
636 * @param op_idx if >= 0, replace input op_idx of n with the fpush result
637 * @param dbl_push if != 0 double pushes are allowd
639 static void x87_create_fpush(const arch_env_t *env, x87_state *state, ir_node *n, int pos, int op_idx, int dbl_push) {
640 ir_node *fpush, *pred = get_irn_n(n, op_idx);
642 const arch_register_t *out = arch_get_irn_register(env, pred);
644 x87_push(state, arch_register_get_index(out), pred, dbl_push);
646 fpush = new_rd_ia32_fpush(NULL, get_irn_irg(n), get_nodes_block(n), pred, get_irn_mode(pred));
647 attr = get_ia32_attr(fpush);
648 attr->x87[0] = &ia32_st_regs[pos];
649 attr->x87[2] = &ia32_st_regs[0];
651 set_irn_n(n, op_idx, fpush);
653 sched_add_before(n, fpush);
654 DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(fpush), attr->x87[0]->name, attr->x87[2]->name));
658 * Create a fpop before node n.
660 * @param state the x87 state
661 * @param n the node before the fpop
662 * @param num pop 1 or 2 values
663 * @param pred node to use as predecessor of the fpop
665 * @return the fpop node
667 static ir_node *x87_create_fpop(const arch_env_t *env, x87_state *state, ir_node *n, int num, ir_node *pred) {
673 fpop = new_rd_ia32_fpop(NULL, get_irn_irg(n), get_nodes_block(n), pred, mode_E);
674 attr = get_ia32_attr(fpop);
675 attr->x87[0] = &ia32_st_regs[0];
676 attr->x87[1] = &ia32_st_regs[0];
677 attr->x87[2] = &ia32_st_regs[0];
679 sched_add_before(n, fpop);
680 DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fpop), attr->x87[0]->name));
688 /* --------------------------------- liveness ------------------------------------------ */
691 * The liveness transfer function.
692 * Updates a live set over a single step from a given node to its predecessor.
693 * Everything defined at the node is removed from the set, the uses of the node get inserted.
694 * @param arch_env The architecture environment.
695 * @param irn The node at which liveness should be computed.
696 * @param live The bitset of registers live before @p irn. This set gets modified by updating it to
697 * the registers live after irn.
700 static unsigned vfp_liveness_transfer(const arch_env_t *arch_env, ir_node *irn, unsigned live)
703 const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
705 if (arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
706 const arch_register_t *reg = arch_get_irn_register(arch_env, irn);
707 live &= ~(1 << reg->index);
710 for (i = 0, n = get_irn_arity(irn); i < n; ++i) {
711 ir_node *op = get_irn_n(irn, i);
713 if (mode_is_float(get_irn_mode(op)) && arch_irn_consider_in_reg_alloc(arch_env, cls, op)) {
714 const arch_register_t *reg = arch_get_irn_register(arch_env, op);
715 live |= 1 << reg->index;
723 * Put all live virtual registers at the end of a block into a bitset.
724 * @param arch_env The architecture environment.
725 * @param bl The block.
726 * @return The live bitset.
728 static unsigned vfp_liveness_end_of_block(x87_simulator *sim, const ir_node *bl)
732 const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
734 be_lv_foreach(sim->lv, bl, be_lv_state_end, i) {
735 ir_node *irn = be_lv_get_irn(sim->lv, bl, i);
736 if (arch_irn_consider_in_reg_alloc(sim->env, cls, irn)) {
737 const arch_register_t *reg = arch_get_irn_register(sim->env, irn);
738 live |= 1 << reg->index;
746 * Compute a bitset of registers which are live at another node.
747 * @param arch_env The architecture environment.
748 * @param pos The node.
749 * @return The live bitset.
751 static unsigned vfp_liveness_nodes_live_at(x87_simulator *sim, const ir_node *pos)
753 const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
757 live = vfp_liveness_end_of_block(sim, bl);
759 sched_foreach_reverse(bl, irn) {
761 * If we encounter the node we want to insert the Perm after,
762 * exit immediately, so that this node is still live
767 live = vfp_liveness_transfer(sim->env, irn, live);
774 * Returns true if a register is live in a set.
776 * @param reg_idx the vfp register index
777 * @param live a live bitset
779 static unsigned is_vfp_live(int reg_idx, unsigned live) {
780 return live & (1 << reg_idx);
785 * Dump liveness info.
787 * @param live the live bitset
789 static void vfp_dump_live(unsigned live) {
792 DB((dbg, LEVEL_2, "Live registers here: \n"));
793 for (i = 0; i < 8; ++i) {
794 if (live & (1 << i)) {
795 DB((dbg, LEVEL_2, " vf%d", i));
798 DB((dbg, LEVEL_2, "\n"));
800 #endif /* DEBUG_libfirm */
802 /* --------------------------------- simulators ---------------------------------------- */
804 #define XCHG(a, b) do { int t = (a); (a) = (b); (b) = t; } while (0)
807 * Simulate a virtual binop.
809 * @param state the x87 state
810 * @param n the node that should be simulated (and patched)
811 * @param env the architecture environment
812 * @param tmpl the template containing the 4 possible x87 opcodes
814 static int sim_binop(x87_state *state, ir_node *n, const arch_env_t *env, const exchange_tmpl *tmpl) {
815 int op2_idx, op1_idx = -1;
816 int out_idx, do_pop =0;
819 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_1));
820 const arch_register_t *op2 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_2));
821 const arch_register_t *out = arch_get_irn_register(env, n);
822 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
824 DB((dbg, LEVEL_1, ">>> %s %s, %s -> %s\n", get_irn_opname(n),
825 arch_register_get_name(op1), arch_register_get_name(op2),
826 arch_register_get_name(out)));
827 DEBUG_ONLY(vfp_dump_live(live));
829 op1_idx = x87_on_stack(state, arch_register_get_index(op1));
830 op2_idx = x87_on_stack(state, arch_register_get_index(op2));
832 if (op2->index != REG_VFP_NOREG) {
833 /* second operand is a vfp register */
835 if (is_vfp_live(op2->index, live)) {
836 /* Second operand is live. */
838 if (is_vfp_live(op1->index, live)) {
839 /* Both operands are live: push the first one.
840 This works even for op1 == op2. */
841 x87_create_fpush(env, state, n, op2_idx, BINOP_IDX_2, 0);
842 out_idx = op2_idx = 0;
844 dst = tmpl->normal_op;
848 /* Second live, first operand is dead here, bring it to tos. */
850 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
854 op1_idx = out_idx = 0;
855 dst = tmpl->normal_op;
860 /* Second operand is dead. */
861 if (is_vfp_live(op1->index, live)) {
862 /* First operand is live: bring second to tos. */
864 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
868 op2_idx = out_idx = 0;
869 dst = tmpl->normal_op;
873 /* Both operands are dead here, pop them from the stack. */
876 XCHG(op2_idx, op1_idx);
877 if (op1_idx == op2_idx) {
878 /* Both are identically, no pop needed. */
879 dst = tmpl->reverse_op;
883 dst = tmpl->reverse_pop_op;
887 else if (op1_idx == 0) {
889 if (op1_idx == op2_idx) {
890 /* Both are identically, no pop needed. */
891 dst = tmpl->normal_op;
895 dst = tmpl->normal_pop_op;
900 /* Bring the first on top. */
901 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
902 if (op1_idx == op2_idx) {
903 /* Both are identically, no pop needed. */
904 out_idx = op1_idx = op2_idx = 0;
905 dst = tmpl->normal_op;
911 dst = tmpl->normal_pop_op;
919 /* second operand is an address mode */
920 if (is_vfp_live(op1->index, live)) {
921 /* first operand is live: push it here */
922 x87_create_fpush(env, state, n, op1_idx, BINOP_IDX_1, 0);
925 /* first operand is dead: bring it to tos */
927 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
929 op1_idx = out_idx = 0;
930 dst = tmpl->normal_op;
934 x87_set_st(state, arch_register_get_index(out), x87_patch_insn(n, dst), out_idx);
938 /* patch the operation */
939 attr = get_ia32_attr(n);
940 attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
942 attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
943 attr->x87[2] = out = &ia32_st_regs[out_idx];
946 DB((dbg, LEVEL_1, "<<< %s %s, %s -> %s\n", get_irn_opname(n),
947 arch_register_get_name(op1), arch_register_get_name(op2),
948 arch_register_get_name(out)));
950 DB((dbg, LEVEL_1, "<<< %s %s, [AM] -> %s\n", get_irn_opname(n),
951 arch_register_get_name(op1),
952 arch_register_get_name(out)));
958 * Simulate a virtual Unop.
960 * @param state the x87 state
961 * @param n the node that should be simulated (and patched)
962 * @param env the architecture environment
963 * @param op the x87 opcode that will replace n's opcode
965 static int sim_unop(x87_state *state, ir_node *n, const arch_env_t *env, ir_op *op) {
966 int op1_idx, out_idx;
967 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, UNOP_IDX));
968 const arch_register_t *out = arch_get_irn_register(env, n);
970 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
972 DB((dbg, LEVEL_1, ">>> %s -> %s\n", get_irn_opname(n), out->name));
973 DEBUG_ONLY(vfp_dump_live(live));
975 op1_idx = x87_on_stack(state, arch_register_get_index(op1));
977 if (is_vfp_live(op1->index, live)) {
978 /* push the operand here */
979 x87_create_fpush(env, state, n, op1_idx, UNOP_IDX, 0);
982 /* operand is dead, bring it to tos */
984 x87_create_fxch(state, n, op1_idx, UNOP_IDX);
987 x87_set_tos(state, arch_register_get_index(out), x87_patch_insn(n, op));
988 op1_idx = out_idx = 0;
989 attr = get_ia32_attr(n);
990 attr->x87[0] = op1 = &ia32_st_regs[0];
991 attr->x87[2] = out = &ia32_st_regs[0];
992 DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), out->name));
998 * Simulate a virtual Load instruction.
1000 * @param state the x87 state
1001 * @param n the node that should be simulated (and patched)
1002 * @param env the architecture environment
1003 * @param op the x87 opcode that will replace n's opcode
1005 static int sim_load(x87_state *state, ir_node *n, const arch_env_t *env, ir_op *op) {
1006 const arch_register_t *out = arch_get_irn_register(env, n);
1009 DB((dbg, LEVEL_1, ">>> %s -> %s\n", get_irn_opname(n), arch_register_get_name(out)));
1010 x87_push(state, arch_register_get_index(out), x87_patch_insn(n, op), 0);
1011 attr = get_ia32_attr(n);
1012 attr->x87[2] = out = &ia32_st_regs[0];
1013 DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), arch_register_get_name(out)));
1019 * Rewire all users of @p old_val to @new_val iff they are scheduled after @p store.
1021 * @param store The store
1022 * @param old_val The former value
1023 * @param new_val The new value
1025 static void collect_and_rewire_users(ir_node *store, ir_node *old_val, ir_node *new_val) {
1026 const ir_edge_t *edge, *ne;
1028 foreach_out_edge_safe(old_val, edge, ne) {
1029 ir_node *user = get_edge_src_irn(edge);
1031 if (! user || user == store)
1034 /* if the user is scheduled after the store: rewire */
1035 if (sched_is_scheduled(user) && sched_comes_after(store, user)) {
1037 /* find the input of the user pointing to the old value */
1038 for (i = get_irn_arity(user) - 1; i >= 0; i--) {
1039 if (get_irn_n(user, i) == old_val)
1040 set_irn_n(user, i, new_val);
1047 * Simulate a virtual Store.
1049 * @param state the x87 state
1050 * @param n the node that should be simulated (and patched)
1051 * @param env the architecture environment
1052 * @param op the x87 store opcode
1053 * @param op_p the x87 store and pop opcode
1055 static int sim_store(x87_state *state, ir_node *n, const arch_env_t *env, ir_op *op, ir_op *op_p) {
1056 ir_node *val = get_irn_n(n, STORE_VAL_IDX);
1057 const arch_register_t *op2 = arch_get_irn_register(env, val);
1058 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
1064 op2_idx = x87_on_stack(state, arch_register_get_index(op2));
1065 assert(op2_idx >= 0);
1067 DB((dbg, LEVEL_1, ">>> %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
1069 mode = get_ia32_ls_mode(n);
1070 depth = x87_get_depth(state);
1073 We can only store the tos to memory.
1074 A store of mode_E with free registers
1075 pushes value to tos, so skip it here.
1077 if (! (mode == mode_E && depth < N_x87_REGS) && op2_idx != 0)
1078 x87_create_fxch(state, n, op2_idx, STORE_VAL_IDX);
1080 if (is_vfp_live(op2->index, live)) {
1082 Problem: fst doesn't support mode_E (spills), only fstp does
1084 - stack not full: push value and fstp
1085 - stack full: fstp value and load again
1087 if (mode == mode_E) {
1088 if (depth < N_x87_REGS) {
1089 /* ok, we have a free register: push + fstp */
1090 x87_create_fpush(env, state, n, op2_idx, STORE_VAL_IDX, 1);
1092 x87_patch_insn(n, op_p);
1095 ir_node *vfld, *mem, *block, *rproj, *mproj;
1098 /* stack full here: need fstp + load */
1100 x87_patch_insn(n, op_p);
1102 block = get_nodes_block(n);
1103 irg = get_irn_irg(n);
1104 vfld = new_rd_ia32_vfld(NULL, irg, block, get_irn_n(n, 0), get_irn_n(n, 1), new_rd_NoMem(irg));
1106 /* copy all attributes */
1107 set_ia32_frame_ent(vfld, get_ia32_frame_ent(n));
1108 if (is_ia32_use_frame(n))
1109 set_ia32_use_frame(vfld);
1110 set_ia32_am_flavour(vfld, get_ia32_am_flavour(n));
1111 set_ia32_op_type(vfld, ia32_am_Source);
1112 add_ia32_am_offs(vfld, get_ia32_am_offs(n));
1113 set_ia32_am_sc(vfld, get_ia32_am_sc(n));
1114 set_ia32_ls_mode(vfld, get_ia32_ls_mode(n));
1116 rproj = new_r_Proj(irg, block, vfld, get_ia32_ls_mode(vfld), pn_ia32_vfld_res);
1117 mproj = new_r_Proj(irg, block, vfld, mode_M, pn_ia32_vfld_M);
1118 mem = get_irn_Proj_for_mode(n, mode_M);
1120 assert(mem && "Store memory not found");
1122 arch_set_irn_register(env, rproj, op2);
1124 /* reroute all former users of the store memory to the load memory */
1125 edges_reroute(mem, mproj, irg);
1126 /* set the memory input of the load to the store memory */
1127 set_irn_n(vfld, 2, mem);
1129 sched_add_after(n, vfld);
1130 sched_add_after(vfld, rproj);
1132 /* rewire all users, scheduled after the store, to the loaded value */
1133 collect_and_rewire_users(n, val, rproj);
1139 /* mode != mode_E -> use normal fst */
1140 x87_patch_insn(n, op);
1145 x87_patch_insn(n, op_p);
1148 attr = get_ia32_attr(n);
1149 attr->x87[1] = op2 = &ia32_st_regs[0];
1150 DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
1156 * Simulate a virtual Phi.
1157 * Just for cosmetic reasons change the mode of Phi nodes to mode_E.
1159 * @param state the x87 state
1160 * @param n the node that should be simulated (and patched)
1161 * @param env the architecture environment
1163 static int sim_Phi(x87_state *state, ir_node *n, const arch_env_t *env) {
1164 ir_mode *mode = get_irn_mode(n);
1166 if (mode_is_float(mode))
1167 set_irn_mode(n, mode_E);
1173 #define _GEN_BINOP(op, rev) \
1174 static int sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
1175 exchange_tmpl tmpl = { op_ia32_##op, op_ia32_##rev, op_ia32_##op##p, op_ia32_##rev##p }; \
1176 return sim_binop(state, n, env, &tmpl); \
1179 #define GEN_BINOP(op) _GEN_BINOP(op, op)
1180 #define GEN_BINOPR(op) _GEN_BINOP(op, op##r)
1182 #define GEN_LOAD2(op, nop) \
1183 static int sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
1184 return sim_load(state, n, env, op_ia32_##nop); \
1187 #define GEN_LOAD(op) GEN_LOAD2(op, op)
1189 #define GEN_UNOP(op) \
1190 static int sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
1191 return sim_unop(state, n, env, op_ia32_##op); \
1194 #define GEN_STORE(op) \
1195 static int sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
1196 return sim_store(state, n, env, op_ia32_##op, op_ia32_##op##p); \
1215 GEN_LOAD2(fConst, fldConst)
1221 * Simulate a fCondJmp.
1223 * @param state the x87 state
1224 * @param n the node that should be simulated (and patched)
1225 * @param env the architecture environment
1227 static int sim_fCondJmp(x87_state *state, ir_node *n, const arch_env_t *env) {
1228 int op2_idx, op1_idx = -1, pop_cnt = 0;
1231 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_1));
1232 const arch_register_t *op2 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_2));
1233 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
1235 DB((dbg, LEVEL_1, ">>> %s %s, %s\n", get_irn_opname(n),
1236 arch_register_get_name(op1), arch_register_get_name(op2)));
1237 DEBUG_ONLY(vfp_dump_live(live));
1239 op1_idx = x87_on_stack(state, arch_register_get_index(op1));
1240 op2_idx = x87_on_stack(state, arch_register_get_index(op2));
1242 /* BEWARE: check for comp a,a cases, they might happen */
1243 if (op2->index != REG_VFP_NOREG) {
1244 /* second operand is a vfp register */
1246 if (is_vfp_live(op2->index, live)) {
1247 /* second operand is live */
1249 if (is_vfp_live(op1->index, live)) {
1250 /* both operands are live: move one of them to tos */
1252 XCHG(op2_idx, op1_idx);
1253 dst = op_ia32_fcomrJmp;
1255 else if (op1_idx == 0) {
1256 dst = op_ia32_fcomJmp;
1259 /* bring the first on top */
1260 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1261 if (op1_idx == op2_idx)
1264 dst = op_ia32_fcomJmp;
1268 /* second live, first operand is dead here, bring it to tos.
1269 This means further, op1_idx != op2_idx. */
1271 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1276 dst = op_ia32_fcompJmp;
1281 /* second operand is dead */
1282 if (is_vfp_live(op1->index, live)) {
1283 /* first operand is live: bring second to tos.
1284 This means further, op1_idx != op2_idx. */
1286 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
1291 dst = op_ia32_fcomrpJmp;
1295 /* both operands are dead here, check first for identity. */
1296 if (op1_idx == op2_idx) {
1297 /* identically, one one needed */
1299 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1300 op1_idx = op2_idx = 0;
1302 dst = op_ia32_fcompJmp;
1305 /* different, move them to st and st(1) and pop both.
1306 The tricky part is to get one into st(1).*/
1307 else if (op2_idx == 1) {
1308 /* good, second operand is already in the right place, move the first */
1310 /* bring the first on top */
1311 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1314 dst = op_ia32_fcomppJmp;
1317 else if (op1_idx == 1) {
1318 /* good, first operand is already in the right place, move the second */
1320 /* bring the first on top */
1321 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
1324 dst = op_ia32_fcomrppJmp;
1328 /* if one is already the TOS, we need two fxch */
1330 /* first one is TOS, move to st(1) */
1331 x87_create_fxch(state, n, 1, BINOP_IDX_1);
1333 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
1335 dst = op_ia32_fcomrppJmp;
1338 else if (op2_idx == 0) {
1339 /* second one is TOS, move to st(1) */
1340 x87_create_fxch(state, n, 1, BINOP_IDX_2);
1342 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1344 dst = op_ia32_fcomrppJmp;
1348 /* none of them is either TOS or st(1), 3 fxch needed */
1349 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
1350 x87_create_fxch(state, n, 1, BINOP_IDX_2);
1351 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1354 dst = op_ia32_fcomppJmp;
1362 /* second operand is an address mode */
1363 if (is_vfp_live(op1->index, live)) {
1364 /* first operand is live: bring it to TOS */
1366 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1369 dst = op_ia32_fcomJmp;
1372 /* first operand is dead: bring it to tos */
1374 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1378 dst = op_ia32_fcompJmp;
1382 x87_patch_insn(n, dst);
1388 /* patch the operation */
1389 attr = get_ia32_attr(n);
1390 attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
1392 attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
1395 DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(n),
1396 arch_register_get_name(op1), arch_register_get_name(op2)));
1398 DB((dbg, LEVEL_1, "<<< %s %s, [AM]\n", get_irn_opname(n),
1399 arch_register_get_name(op1)));
1405 * Simulate a be_Copy.
1407 * @param state the x87 state
1408 * @param n the node that should be simulated (and patched)
1409 * @param env the architecture environment
1411 static int sim_Copy(x87_state *state, ir_node *n, const arch_env_t *env) {
1412 ir_mode *mode = get_irn_mode(n);
1414 if (mode_is_float(mode)) {
1415 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, 0));
1416 const arch_register_t *out = arch_get_irn_register(env, n);
1417 ir_node *node, *next;
1419 int op1_idx, out_idx;
1420 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
1422 op1_idx = x87_on_stack(state, arch_register_get_index(op1));
1424 DB((dbg, LEVEL_1, ">>> %s %s -> %s\n", get_irn_opname(n),
1425 arch_register_get_name(op1), arch_register_get_name(out)));
1426 DEBUG_ONLY(vfp_dump_live(live));
1428 if (is_vfp_live(op1->index, live)) {
1429 /* operand is still live,a real copy */
1430 node = new_rd_ia32_fpush(get_irn_dbg_info(n), get_irn_irg(n), get_nodes_block(n), get_irn_n(n, 0), mode);
1431 arch_set_irn_register(env, node, out);
1433 x87_push(state, arch_register_get_index(out), node, 0);
1435 attr = get_ia32_attr(node);
1436 attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
1437 attr->x87[2] = out = &ia32_st_regs[0];
1439 next = sched_next(n);
1442 sched_add_before(next, node);
1443 DB((dbg, LEVEL_1, ">>> %s %s -> %s\n", get_irn_opname(node), op1->name, out->name));
1446 out_idx = x87_on_stack(state, arch_register_get_index(out));
1448 if (out_idx >= 0 && out_idx != op1_idx) {
1449 /* op1 must be killed and placed where out is */
1451 /* best case, simple remove and rename */
1452 x87_patch_insn(n, op_ia32_Pop);
1453 attr = get_ia32_attr(n);
1454 attr->x87[0] = op1 = &ia32_st_regs[0];
1457 x87_set_st(state, arch_register_get_index(out), n, op1_idx - 1);
1460 /* move op1 to tos, store and pop it */
1462 x87_create_fxch(state, n, op1_idx, 0);
1465 x87_patch_insn(n, op_ia32_Pop);
1466 attr = get_ia32_attr(n);
1467 attr->x87[0] = op1 = &ia32_st_regs[out_idx];
1470 x87_set_st(state, arch_register_get_index(out), n, out_idx - 1);
1472 DB((dbg, LEVEL_1, ">>> %s %s\n", get_irn_opname(n), op1->name));
1475 /* just a virtual copy */
1476 x87_set_st(state, arch_register_get_index(out), get_unop_op(n), op1_idx);
1478 DB((dbg, LEVEL_1, ">>> KILLED %s\n", get_irn_opname(n)));
1479 exchange(n, get_unop_op(n));
1488 * Simulate a be_Call.
1490 * @param state the x87 state
1491 * @param n the node that should be simulated
1492 * @param env the architecture environment
1494 static int sim_Call(x87_state *state, ir_node *n, const arch_env_t *env) {
1495 ir_type *call_tp = be_Call_get_type(n);
1497 /* at the begin of a call the x87 state should be empty */
1498 assert(state->depth == 0 && "stack not empty before call");
1501 * If the called function returns a float, it is returned in st(0).
1502 * This even happens if the return value is NOT used.
1503 * Moreover, only one return result is supported.
1505 if (get_method_n_ress(call_tp) > 0) {
1506 ir_type *res_type = get_method_res_type(call_tp, 0);
1507 ir_mode *mode = get_type_mode(res_type);
1509 if (mode && mode_is_float(mode)) {
1511 * TODO: what to push here? The result might be unused and currently
1512 * we have no possibility to detect this :-(
1514 x87_push(state, 0, n, 0);
1522 * Simulate a be_Spill.
1524 * @param state the x87 state
1525 * @param n the node that should be simulated (and patched)
1526 * @param env the architecture environment
1528 * Should not happen, spills are lowered before x87 simulator see them.
1530 static int sim_Spill(x87_state *state, ir_node *n, const arch_env_t *env) {
1531 assert(0 && "Spill not lowered");
1532 return sim_fst(state, n, env);
1536 * Simulate a be_Reload.
1538 * @param state the x87 state
1539 * @param n the node that should be simulated (and patched)
1540 * @param env the architecture environment
1542 * Should not happen, reloads are lowered before x87 simulator see them.
1544 static int sim_Reload(x87_state *state, ir_node *n, const arch_env_t *env) {
1545 assert(0 && "Reload not lowered");
1546 return sim_fld(state, n, env);
1550 * Simulate a be_Return.
1552 * @param state the x87 state
1553 * @param n the node that should be simulated (and patched)
1554 * @param env the architecture environment
1556 static int sim_Return(x87_state *state, ir_node *n, const arch_env_t *env) {
1557 int n_res = be_Return_get_n_rets(n);
1558 int i, n_float_res = 0;
1560 /* only floating point return values must resist on stack */
1561 for (i = 0; i < n_res; ++i) {
1562 ir_node *res = get_irn_n(n, be_pos_Return_val + i);
1564 if (mode_is_float(get_irn_mode(res)))
1567 assert(x87_get_depth(state) == n_float_res);
1569 /* pop them virtually */
1570 for (i = n_float_res - 1; i >= 0; --i)
1577 * Kill any dead registers at block start by popping them from the stack.
1579 * @param sim the simulator handle
1580 * @param block the current block
1581 * @param start_state the x87 state at the begin of the block
1583 static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *start_state) {
1584 x87_state *state = start_state;
1585 ir_node *first_insn = sched_first(block);
1586 ir_node *keep = NULL;
1587 unsigned live = vfp_liveness_nodes_live_at(sim, block);
1589 int i, depth, num_pop;
1592 depth = x87_get_depth(state);
1593 for (i = depth - 1; i >= 0; --i) {
1594 int reg = x87_get_st_reg(state, i);
1596 if (! is_vfp_live(reg, live))
1597 kill_mask |= (1 << i);
1601 /* create a new state, will be changed */
1602 state = x87_clone_state(sim, state);
1604 DB((dbg, LEVEL_1, "Killing deads:\n"));
1605 DEBUG_ONLY(vfp_dump_live(live));
1606 DEBUG_ONLY(x87_dump_stack(state));
1608 /* now kill registers */
1610 /* we can only kill from TOS, so bring them up */
1611 if (! (kill_mask & 1)) {
1612 /* search from behind, because we can to a double-pop */
1613 for (i = depth - 1; i >= 0; --i) {
1614 if (kill_mask & (1 << i)) {
1615 kill_mask &= ~(1 << i);
1622 x87_set_st(state, -1, keep, i);
1623 keep = x87_create_fxch(state, first_insn, i, -1);
1626 keep = x87_get_st_node(state, 0);
1628 if ((kill_mask & 3) == 3) {
1629 /* we can do a double-pop */
1633 /* only a single pop */
1638 kill_mask >>= num_pop;
1639 keep = x87_create_fpop(sim->env, state, first_insn, num_pop, keep);
1641 add_End_keepalive(get_irg_end(get_irn_irg(block)), keep);
1647 * Run a simulation and fix all virtual instructions for a block.
1649 * @param sim the simulator handle
1650 * @param block the current block
1652 * @return non-zero if simulation is complete,
1653 * zero if the simulation must be rerun
1655 static int x87_simulate_block(x87_simulator *sim, ir_node *block) {
1657 blk_state *bl_state = x87_get_bl_state(sim, block);
1658 x87_state *state = bl_state->begin;
1659 const ir_edge_t *edge;
1660 ir_node *start_block;
1662 /* if we have no assigned start state, we must wait ... */
1666 assert(bl_state->end == NULL);
1668 DB((dbg, LEVEL_1, "Simulate %+F\n", block));
1670 /* at block begin, kill all dead registers */
1671 state = x87_kill_deads(sim, block, state);
1673 /* beware, n might changed */
1674 for (n = sched_first(block); !sched_is_end(n); n = next) {
1675 ir_op *op = get_irn_op(n);
1677 next = sched_next(n);
1678 if (op->ops.generic) {
1680 sim_func func = (sim_func)op->ops.generic;
1682 /* have work to do */
1683 if (state == bl_state->begin) {
1684 /* create a new state, will be changed */
1685 state = x87_clone_state(sim, state);
1689 node_inserted = (*func)(state, n, sim->env);
1692 sim_func might have added additional nodes after n,
1694 beware: n must not be changed by sim_func
1695 (i.e. removed from schedule) in this case
1698 next = sched_next(n);
1702 start_block = get_irg_start_block(get_irn_irg(block));
1704 /* check if the state must be shuffled */
1705 foreach_block_succ(block, edge) {
1706 ir_node *succ = get_edge_src_irn(edge);
1707 blk_state *succ_state = x87_get_bl_state(sim, succ);
1709 if (succ_state->begin && succ != start_block) {
1710 /* There is already a begin state for this block, bad.
1711 Do the necessary permutations.
1712 Note that critical edges are removed, so this is always possible. */
1713 x87_shuffle(sim, block, state, succ, succ_state->begin);
1715 /* Note further, that there can be only one such situation,
1716 so we can break here. */
1720 bl_state->end = state;
1722 /* now propagate the state to all successor blocks */
1723 foreach_block_succ(block, edge) {
1724 ir_node *succ = get_edge_src_irn(edge);
1725 blk_state *succ_state = x87_get_bl_state(sim, succ);
1727 if (! succ_state->begin)
1728 succ_state->begin = state;
1735 * Create a new x87 simulator.
1737 * @param sim a simulator handle, will be initialized
1738 * @param irg the current graph
1739 * @param env the architecture environment
1741 static void x87_init_simulator(x87_simulator *sim, ir_graph *irg, const arch_env_t *env) {
1742 obstack_init(&sim->obst);
1743 sim->blk_states = pmap_create();
1745 sim->lv = be_liveness(irg);
1747 FIRM_DBG_REGISTER(dbg, "firm.be.ia32.x87");
1749 DB((dbg, LEVEL_1, "--------------------------------\n"
1750 "x87 Simulator started for %+F\n", irg));
1752 /* set the generic function pointer of instruction we must simulate */
1753 clear_irp_opcodes_generic_func();
1755 #define ASSOC(op) (op_ ## op)->ops.generic = (op_func)(sim_##op)
1756 #define ASSOC_IA32(op) (op_ia32_v ## op)->ops.generic = (op_func)(sim_##op)
1757 #define ASSOC_BE(op) (op_be_ ## op)->ops.generic = (op_func)(sim_##op)
1775 ASSOC_IA32(fCondJmp);
1788 * Destroy a x87 simulator.
1790 * @param sim the simulator handle
1792 static void x87_destroy_simulator(x87_simulator *sim) {
1793 pmap_destroy(sim->blk_states);
1794 obstack_free(&sim->obst, NULL);
1795 be_liveness_free(sim->lv);
1796 DB((dbg, LEVEL_1, "x87 Simulator stopped\n\n"));
1800 * Run a simulation and fix all virtual instructions for a graph.
1802 * @param env the architecture environment
1803 * @param irg the current graph
1804 * @param blk_list the block schedule list
1806 * Needs a block-schedule.
1808 void x87_simulate_graph(const arch_env_t *env, ir_graph *irg, ir_node **blk_list) {
1809 ir_node *block, *start_block;
1811 blk_state *bl_state;
1815 /* create the simulator */
1816 x87_init_simulator(&sim, irg, env);
1818 start_block = get_irg_start_block(irg);
1819 bl_state = x87_get_bl_state(&sim, start_block);
1821 /* start with the empty state */
1822 bl_state->begin = empty;
1825 worklist = new_pdeq();
1827 /* create the worklist for the schedule. */
1828 for (i = 0; i < ARR_LEN(blk_list); ++i)
1829 pdeq_putr(worklist, blk_list[i]);
1833 block = pdeq_getl(worklist);
1834 if (! x87_simulate_block(&sim, block)) {
1835 pdeq_putr(worklist, block);
1838 } while (! pdeq_empty(worklist));
1841 x87_destroy_simulator(&sim);