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 const 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);
754 const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
758 live = vfp_liveness_end_of_block(sim, bl);
760 sched_foreach_reverse(bl, irn) {
762 * If we encounter the node we want to insert the Perm after,
763 * exit immediately, so that this node is still live
768 live = vfp_liveness_transfer(sim->env, irn, live);
775 * Returns true if a register is live in a set.
777 * @param reg_idx the vfp register index
778 * @param live a live bitset
780 static unsigned is_vfp_live(int reg_idx, unsigned live) {
781 return live & (1 << reg_idx);
786 * Dump liveness info.
788 * @param live the live bitset
790 static void vfp_dump_live(unsigned live) {
793 DB((dbg, LEVEL_2, "Live registers here: \n"));
794 for (i = 0; i < 8; ++i) {
795 if (live & (1 << i)) {
796 DB((dbg, LEVEL_2, " vf%d", i));
799 DB((dbg, LEVEL_2, "\n"));
801 #endif /* DEBUG_libfirm */
803 /* --------------------------------- simulators ---------------------------------------- */
805 #define XCHG(a, b) do { int t = (a); (a) = (b); (b) = t; } while (0)
808 * Simulate a virtual binop.
810 * @param state the x87 state
811 * @param n the node that should be simulated (and patched)
812 * @param env the architecture environment
813 * @param tmpl the template containing the 4 possible x87 opcodes
815 static int sim_binop(x87_state *state, ir_node *n, const arch_env_t *env, const exchange_tmpl *tmpl) {
816 int op2_idx, op1_idx = -1;
817 int out_idx, do_pop =0;
820 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_1));
821 const arch_register_t *op2 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_2));
822 const arch_register_t *out = arch_get_irn_register(env, n);
823 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
825 DB((dbg, LEVEL_1, ">>> %s %s, %s -> %s\n", get_irn_opname(n),
826 arch_register_get_name(op1), arch_register_get_name(op2),
827 arch_register_get_name(out)));
828 DEBUG_ONLY(vfp_dump_live(live));
830 op1_idx = x87_on_stack(state, arch_register_get_index(op1));
831 op2_idx = x87_on_stack(state, arch_register_get_index(op2));
833 if (op2->index != REG_VFP_NOREG) {
834 /* second operand is a vfp register */
836 if (is_vfp_live(op2->index, live)) {
837 /* Second operand is live. */
839 if (is_vfp_live(op1->index, live)) {
840 /* Both operands are live: push the first one.
841 This works even for op1 == op2. */
842 x87_create_fpush(env, state, n, op2_idx, BINOP_IDX_2, 0);
843 out_idx = op2_idx = 0;
845 dst = tmpl->normal_op;
849 /* Second live, first operand is dead here, bring it to tos. */
851 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
855 op1_idx = out_idx = 0;
856 dst = tmpl->normal_op;
861 /* Second operand is dead. */
862 if (is_vfp_live(op1->index, live)) {
863 /* First operand is live: bring second to tos. */
865 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
869 op2_idx = out_idx = 0;
870 dst = tmpl->normal_op;
874 /* Both operands are dead here, pop them from the stack. */
877 XCHG(op2_idx, op1_idx);
878 if (op1_idx == op2_idx) {
879 /* Both are identically, no pop needed. */
880 dst = tmpl->reverse_op;
884 dst = tmpl->reverse_pop_op;
888 else if (op1_idx == 0) {
890 if (op1_idx == op2_idx) {
891 /* Both are identically, no pop needed. */
892 dst = tmpl->normal_op;
896 dst = tmpl->normal_pop_op;
901 /* Bring the first on top. */
902 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
903 if (op1_idx == op2_idx) {
904 /* Both are identically, no pop needed. */
905 out_idx = op1_idx = op2_idx = 0;
906 dst = tmpl->normal_op;
912 dst = tmpl->normal_pop_op;
920 /* second operand is an address mode */
921 if (is_vfp_live(op1->index, live)) {
922 /* first operand is live: push it here */
923 x87_create_fpush(env, state, n, op1_idx, BINOP_IDX_1, 0);
926 /* first operand is dead: bring it to tos */
928 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
930 op1_idx = out_idx = 0;
931 dst = tmpl->normal_op;
935 x87_set_st(state, arch_register_get_index(out), x87_patch_insn(n, dst), out_idx);
939 /* patch the operation */
940 attr = get_ia32_attr(n);
941 attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
943 attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
944 attr->x87[2] = out = &ia32_st_regs[out_idx];
947 DB((dbg, LEVEL_1, "<<< %s %s, %s -> %s\n", get_irn_opname(n),
948 arch_register_get_name(op1), arch_register_get_name(op2),
949 arch_register_get_name(out)));
951 DB((dbg, LEVEL_1, "<<< %s %s, [AM] -> %s\n", get_irn_opname(n),
952 arch_register_get_name(op1),
953 arch_register_get_name(out)));
959 * Simulate a virtual Unop.
961 * @param state the x87 state
962 * @param n the node that should be simulated (and patched)
963 * @param env the architecture environment
964 * @param op the x87 opcode that will replace n's opcode
966 static int sim_unop(x87_state *state, ir_node *n, const arch_env_t *env, ir_op *op) {
967 int op1_idx, out_idx;
968 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, UNOP_IDX));
969 const arch_register_t *out = arch_get_irn_register(env, n);
971 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
973 DB((dbg, LEVEL_1, ">>> %s -> %s\n", get_irn_opname(n), out->name));
974 DEBUG_ONLY(vfp_dump_live(live));
976 op1_idx = x87_on_stack(state, arch_register_get_index(op1));
978 if (is_vfp_live(op1->index, live)) {
979 /* push the operand here */
980 x87_create_fpush(env, state, n, op1_idx, UNOP_IDX, 0);
983 /* operand is dead, bring it to tos */
985 x87_create_fxch(state, n, op1_idx, UNOP_IDX);
988 x87_set_tos(state, arch_register_get_index(out), x87_patch_insn(n, op));
989 op1_idx = out_idx = 0;
990 attr = get_ia32_attr(n);
991 attr->x87[0] = op1 = &ia32_st_regs[0];
992 attr->x87[2] = out = &ia32_st_regs[0];
993 DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), out->name));
999 * Simulate a virtual Load instruction.
1001 * @param state the x87 state
1002 * @param n the node that should be simulated (and patched)
1003 * @param env the architecture environment
1004 * @param op the x87 opcode that will replace n's opcode
1006 static int sim_load(x87_state *state, ir_node *n, const arch_env_t *env, ir_op *op) {
1007 const arch_register_t *out = arch_get_irn_register(env, n);
1010 DB((dbg, LEVEL_1, ">>> %s -> %s\n", get_irn_opname(n), arch_register_get_name(out)));
1011 x87_push(state, arch_register_get_index(out), x87_patch_insn(n, op), 0);
1012 attr = get_ia32_attr(n);
1013 attr->x87[2] = out = &ia32_st_regs[0];
1014 DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), arch_register_get_name(out)));
1020 * Rewire all users of @p old_val to @new_val iff they are scheduled after @p store.
1022 * @param store The store
1023 * @param old_val The former value
1024 * @param new_val The new value
1026 static void collect_and_rewire_users(ir_node *store, ir_node *old_val, ir_node *new_val) {
1027 const ir_edge_t *edge, *ne;
1029 foreach_out_edge_safe(old_val, edge, ne) {
1030 ir_node *user = get_edge_src_irn(edge);
1032 if (! user || user == store)
1035 /* if the user is scheduled after the store: rewire */
1036 if (sched_is_scheduled(user) && sched_comes_after(store, user)) {
1038 /* find the input of the user pointing to the old value */
1039 for (i = get_irn_arity(user) - 1; i >= 0; i--) {
1040 if (get_irn_n(user, i) == old_val)
1041 set_irn_n(user, i, new_val);
1048 * Simulate a virtual Store.
1050 * @param state the x87 state
1051 * @param n the node that should be simulated (and patched)
1052 * @param env the architecture environment
1053 * @param op the x87 store opcode
1054 * @param op_p the x87 store and pop opcode
1056 static int sim_store(x87_state *state, ir_node *n, const arch_env_t *env, ir_op *op, ir_op *op_p) {
1057 ir_node *val = get_irn_n(n, STORE_VAL_IDX);
1058 const arch_register_t *op2 = arch_get_irn_register(env, val);
1059 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
1065 op2_idx = x87_on_stack(state, arch_register_get_index(op2));
1066 assert(op2_idx >= 0);
1068 DB((dbg, LEVEL_1, ">>> %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
1070 mode = get_ia32_ls_mode(n);
1071 depth = x87_get_depth(state);
1074 We can only store the tos to memory.
1075 A store of mode_E with free registers
1076 pushes value to tos, so skip it here.
1078 if (! (mode == mode_E && depth < N_x87_REGS) && op2_idx != 0)
1079 x87_create_fxch(state, n, op2_idx, STORE_VAL_IDX);
1081 if (is_vfp_live(op2->index, live)) {
1083 Problem: fst doesn't support mode_E (spills), only fstp does
1085 - stack not full: push value and fstp
1086 - stack full: fstp value and load again
1088 if (mode == mode_E) {
1089 if (depth < N_x87_REGS) {
1090 /* ok, we have a free register: push + fstp */
1091 x87_create_fpush(env, state, n, op2_idx, STORE_VAL_IDX, 1);
1093 x87_patch_insn(n, op_p);
1096 ir_node *vfld, *mem, *block, *rproj, *mproj;
1099 /* stack full here: need fstp + load */
1101 x87_patch_insn(n, op_p);
1103 block = get_nodes_block(n);
1104 irg = get_irn_irg(n);
1105 vfld = new_rd_ia32_vfld(NULL, irg, block, get_irn_n(n, 0), get_irn_n(n, 1), new_rd_NoMem(irg));
1107 /* copy all attributes */
1108 set_ia32_frame_ent(vfld, get_ia32_frame_ent(n));
1109 if (is_ia32_use_frame(n))
1110 set_ia32_use_frame(vfld);
1111 set_ia32_am_flavour(vfld, get_ia32_am_flavour(n));
1112 set_ia32_op_type(vfld, ia32_am_Source);
1113 add_ia32_am_offs(vfld, get_ia32_am_offs(n));
1114 set_ia32_am_sc(vfld, get_ia32_am_sc(n));
1115 set_ia32_ls_mode(vfld, get_ia32_ls_mode(n));
1117 rproj = new_r_Proj(irg, block, vfld, get_ia32_ls_mode(vfld), pn_ia32_vfld_res);
1118 mproj = new_r_Proj(irg, block, vfld, mode_M, pn_ia32_vfld_M);
1119 mem = get_irn_Proj_for_mode(n, mode_M);
1121 assert(mem && "Store memory not found");
1123 arch_set_irn_register(env, rproj, op2);
1125 /* reroute all former users of the store memory to the load memory */
1126 edges_reroute(mem, mproj, irg);
1127 /* set the memory input of the load to the store memory */
1128 set_irn_n(vfld, 2, mem);
1130 sched_add_after(n, vfld);
1131 sched_add_after(vfld, rproj);
1133 /* rewire all users, scheduled after the store, to the loaded value */
1134 collect_and_rewire_users(n, val, rproj);
1140 /* mode != mode_E -> use normal fst */
1141 x87_patch_insn(n, op);
1146 x87_patch_insn(n, op_p);
1149 attr = get_ia32_attr(n);
1150 attr->x87[1] = op2 = &ia32_st_regs[0];
1151 DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
1157 * Simulate a virtual Phi.
1158 * Just for cosmetic reasons change the mode of Phi nodes to mode_E.
1160 * @param state the x87 state
1161 * @param n the node that should be simulated (and patched)
1162 * @param env the architecture environment
1164 static int sim_Phi(x87_state *state, ir_node *n, const arch_env_t *env) {
1165 ir_mode *mode = get_irn_mode(n);
1167 if (mode_is_float(mode))
1168 set_irn_mode(n, mode_E);
1174 #define _GEN_BINOP(op, rev) \
1175 static int sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
1176 exchange_tmpl tmpl = { op_ia32_##op, op_ia32_##rev, op_ia32_##op##p, op_ia32_##rev##p }; \
1177 return sim_binop(state, n, env, &tmpl); \
1180 #define GEN_BINOP(op) _GEN_BINOP(op, op)
1181 #define GEN_BINOPR(op) _GEN_BINOP(op, op##r)
1183 #define GEN_LOAD2(op, nop) \
1184 static int sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
1185 return sim_load(state, n, env, op_ia32_##nop); \
1188 #define GEN_LOAD(op) GEN_LOAD2(op, op)
1190 #define GEN_UNOP(op) \
1191 static int sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
1192 return sim_unop(state, n, env, op_ia32_##op); \
1195 #define GEN_STORE(op) \
1196 static int sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
1197 return sim_store(state, n, env, op_ia32_##op, op_ia32_##op##p); \
1216 GEN_LOAD2(fConst, fldConst)
1222 * Simulate a fCondJmp.
1224 * @param state the x87 state
1225 * @param n the node that should be simulated (and patched)
1226 * @param env the architecture environment
1228 static int sim_fCondJmp(x87_state *state, ir_node *n, const arch_env_t *env) {
1229 int op2_idx, op1_idx = -1, pop_cnt = 0;
1232 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_1));
1233 const arch_register_t *op2 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_2));
1234 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
1236 DB((dbg, LEVEL_1, ">>> %s %s, %s\n", get_irn_opname(n),
1237 arch_register_get_name(op1), arch_register_get_name(op2)));
1238 DEBUG_ONLY(vfp_dump_live(live));
1240 op1_idx = x87_on_stack(state, arch_register_get_index(op1));
1241 op2_idx = x87_on_stack(state, arch_register_get_index(op2));
1243 /* BEWARE: check for comp a,a cases, they might happen */
1244 if (op2->index != REG_VFP_NOREG) {
1245 /* second operand is a vfp register */
1247 if (is_vfp_live(op2->index, live)) {
1248 /* second operand is live */
1250 if (is_vfp_live(op1->index, live)) {
1251 /* both operands are live: move one of them to tos */
1253 XCHG(op2_idx, op1_idx);
1254 dst = op_ia32_fcomrJmp;
1256 else if (op1_idx == 0) {
1257 dst = op_ia32_fcomJmp;
1260 /* bring the first on top */
1261 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1262 if (op1_idx == op2_idx)
1265 dst = op_ia32_fcomJmp;
1269 /* second live, first operand is dead here, bring it to tos.
1270 This means further, op1_idx != op2_idx. */
1272 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1277 dst = op_ia32_fcompJmp;
1282 /* second operand is dead */
1283 if (is_vfp_live(op1->index, live)) {
1284 /* first operand is live: bring second to tos.
1285 This means further, op1_idx != op2_idx. */
1287 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
1292 dst = op_ia32_fcomrpJmp;
1296 /* both operands are dead here, check first for identity. */
1297 if (op1_idx == op2_idx) {
1298 /* identically, one one needed */
1300 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1301 op1_idx = op2_idx = 0;
1303 dst = op_ia32_fcompJmp;
1306 /* different, move them to st and st(1) and pop both.
1307 The tricky part is to get one into st(1).*/
1308 else if (op2_idx == 1) {
1309 /* good, second operand is already in the right place, move the first */
1311 /* bring the first on top */
1312 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1315 dst = op_ia32_fcomppJmp;
1318 else if (op1_idx == 1) {
1319 /* good, first operand is already in the right place, move the second */
1321 /* bring the first on top */
1322 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
1325 dst = op_ia32_fcomrppJmp;
1329 /* if one is already the TOS, we need two fxch */
1331 /* first one is TOS, move to st(1) */
1332 x87_create_fxch(state, n, 1, BINOP_IDX_1);
1334 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
1336 dst = op_ia32_fcomrppJmp;
1339 else if (op2_idx == 0) {
1340 /* second one is TOS, move to st(1) */
1341 x87_create_fxch(state, n, 1, BINOP_IDX_2);
1343 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1345 dst = op_ia32_fcomrppJmp;
1349 /* none of them is either TOS or st(1), 3 fxch needed */
1350 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
1351 x87_create_fxch(state, n, 1, BINOP_IDX_2);
1352 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1355 dst = op_ia32_fcomppJmp;
1363 /* second operand is an address mode */
1364 if (is_vfp_live(op1->index, live)) {
1365 /* first operand is live: bring it to TOS */
1367 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1370 dst = op_ia32_fcomJmp;
1373 /* first operand is dead: bring it to tos */
1375 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
1379 dst = op_ia32_fcompJmp;
1383 x87_patch_insn(n, dst);
1389 /* patch the operation */
1390 attr = get_ia32_attr(n);
1391 attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
1393 attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
1396 DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(n),
1397 arch_register_get_name(op1), arch_register_get_name(op2)));
1399 DB((dbg, LEVEL_1, "<<< %s %s, [AM]\n", get_irn_opname(n),
1400 arch_register_get_name(op1)));
1406 * Simulate a be_Copy.
1408 * @param state the x87 state
1409 * @param n the node that should be simulated (and patched)
1410 * @param env the architecture environment
1412 static int sim_Copy(x87_state *state, ir_node *n, const arch_env_t *env) {
1413 ir_mode *mode = get_irn_mode(n);
1415 if (mode_is_float(mode)) {
1416 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, 0));
1417 const arch_register_t *out = arch_get_irn_register(env, n);
1418 ir_node *node, *next;
1420 int op1_idx, out_idx;
1421 unsigned live = vfp_liveness_nodes_live_at(state->sim, n);
1423 op1_idx = x87_on_stack(state, arch_register_get_index(op1));
1425 DB((dbg, LEVEL_1, ">>> %s %s -> %s\n", get_irn_opname(n),
1426 arch_register_get_name(op1), arch_register_get_name(out)));
1427 DEBUG_ONLY(vfp_dump_live(live));
1429 if (is_vfp_live(op1->index, live)) {
1430 /* operand is still live,a real copy */
1431 node = new_rd_ia32_fpush(get_irn_dbg_info(n), get_irn_irg(n), get_nodes_block(n), get_irn_n(n, 0), mode);
1432 arch_set_irn_register(env, node, out);
1434 x87_push(state, arch_register_get_index(out), node, 0);
1436 attr = get_ia32_attr(node);
1437 attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
1438 attr->x87[2] = out = &ia32_st_regs[0];
1440 next = sched_next(n);
1443 sched_add_before(next, node);
1444 DB((dbg, LEVEL_1, ">>> %s %s -> %s\n", get_irn_opname(node), op1->name, out->name));
1447 out_idx = x87_on_stack(state, arch_register_get_index(out));
1449 if (out_idx >= 0 && out_idx != op1_idx) {
1450 /* op1 must be killed and placed where out is */
1452 /* best case, simple remove and rename */
1453 x87_patch_insn(n, op_ia32_Pop);
1454 attr = get_ia32_attr(n);
1455 attr->x87[0] = op1 = &ia32_st_regs[0];
1458 x87_set_st(state, arch_register_get_index(out), n, op1_idx - 1);
1461 /* move op1 to tos, store and pop it */
1463 x87_create_fxch(state, n, op1_idx, 0);
1466 x87_patch_insn(n, op_ia32_Pop);
1467 attr = get_ia32_attr(n);
1468 attr->x87[0] = op1 = &ia32_st_regs[out_idx];
1471 x87_set_st(state, arch_register_get_index(out), n, out_idx - 1);
1473 DB((dbg, LEVEL_1, ">>> %s %s\n", get_irn_opname(n), op1->name));
1476 /* just a virtual copy */
1477 x87_set_st(state, arch_register_get_index(out), get_unop_op(n), op1_idx);
1479 DB((dbg, LEVEL_1, ">>> KILLED %s\n", get_irn_opname(n)));
1480 exchange(n, get_unop_op(n));
1489 * Simulate a be_Call.
1491 * @param state the x87 state
1492 * @param n the node that should be simulated
1493 * @param env the architecture environment
1495 static int sim_Call(x87_state *state, ir_node *n, const arch_env_t *env) {
1496 ir_type *call_tp = be_Call_get_type(n);
1498 /* at the begin of a call the x87 state should be empty */
1499 assert(state->depth == 0 && "stack not empty before call");
1502 * If the called function returns a float, it is returned in st(0).
1503 * This even happens if the return value is NOT used.
1504 * Moreover, only one return result is supported.
1506 if (get_method_n_ress(call_tp) > 0) {
1507 ir_type *res_type = get_method_res_type(call_tp, 0);
1508 ir_mode *mode = get_type_mode(res_type);
1510 if (mode && mode_is_float(mode)) {
1512 * TODO: what to push here? The result might be unused and currently
1513 * we have no possibility to detect this :-(
1515 x87_push(state, 0, n, 0);
1523 * Simulate a be_Spill.
1525 * @param state the x87 state
1526 * @param n the node that should be simulated (and patched)
1527 * @param env the architecture environment
1529 * Should not happen, spills are lowered before x87 simulator see them.
1531 static int sim_Spill(x87_state *state, ir_node *n, const arch_env_t *env) {
1532 assert(0 && "Spill not lowered");
1533 return sim_fst(state, n, env);
1537 * Simulate a be_Reload.
1539 * @param state the x87 state
1540 * @param n the node that should be simulated (and patched)
1541 * @param env the architecture environment
1543 * Should not happen, reloads are lowered before x87 simulator see them.
1545 static int sim_Reload(x87_state *state, ir_node *n, const arch_env_t *env) {
1546 assert(0 && "Reload not lowered");
1547 return sim_fld(state, n, env);
1551 * Simulate a be_Return.
1553 * @param state the x87 state
1554 * @param n the node that should be simulated (and patched)
1555 * @param env the architecture environment
1557 static int sim_Return(x87_state *state, ir_node *n, const arch_env_t *env) {
1558 int n_res = be_Return_get_n_rets(n);
1559 int i, n_float_res = 0;
1561 /* only floating point return values must resist on stack */
1562 for (i = 0; i < n_res; ++i) {
1563 ir_node *res = get_irn_n(n, be_pos_Return_val + i);
1565 if (mode_is_float(get_irn_mode(res)))
1568 assert(x87_get_depth(state) == n_float_res);
1570 /* pop them virtually */
1571 for (i = n_float_res - 1; i >= 0; --i)
1578 * Kill any dead registers at block start by popping them from the stack.
1580 * @param sim the simulator handle
1581 * @param block the current block
1582 * @param start_state the x87 state at the begin of the block
1584 static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *start_state) {
1585 x87_state *state = start_state;
1586 ir_node *first_insn = sched_first(block);
1587 ir_node *keep = NULL;
1588 unsigned live = vfp_liveness_nodes_live_at(sim, block);
1590 int i, depth, num_pop;
1593 depth = x87_get_depth(state);
1594 for (i = depth - 1; i >= 0; --i) {
1595 int reg = x87_get_st_reg(state, i);
1597 if (! is_vfp_live(reg, live))
1598 kill_mask |= (1 << i);
1602 /* create a new state, will be changed */
1603 state = x87_clone_state(sim, state);
1605 DB((dbg, LEVEL_1, "Killing deads:\n"));
1606 DEBUG_ONLY(vfp_dump_live(live));
1607 DEBUG_ONLY(x87_dump_stack(state));
1609 /* now kill registers */
1611 /* we can only kill from TOS, so bring them up */
1612 if (! (kill_mask & 1)) {
1613 /* search from behind, because we can to a double-pop */
1614 for (i = depth - 1; i >= 0; --i) {
1615 if (kill_mask & (1 << i)) {
1616 kill_mask &= ~(1 << i);
1623 x87_set_st(state, -1, keep, i);
1624 keep = x87_create_fxch(state, first_insn, i, -1);
1627 keep = x87_get_st_node(state, 0);
1629 if ((kill_mask & 3) == 3) {
1630 /* we can do a double-pop */
1634 /* only a single pop */
1639 kill_mask >>= num_pop;
1640 keep = x87_create_fpop(sim->env, state, first_insn, num_pop, keep);
1642 add_End_keepalive(get_irg_end(get_irn_irg(block)), keep);
1648 * Run a simulation and fix all virtual instructions for a block.
1650 * @param sim the simulator handle
1651 * @param block the current block
1653 * @return non-zero if simulation is complete,
1654 * zero if the simulation must be rerun
1656 static int x87_simulate_block(x87_simulator *sim, ir_node *block) {
1658 blk_state *bl_state = x87_get_bl_state(sim, block);
1659 x87_state *state = bl_state->begin;
1660 const ir_edge_t *edge;
1661 ir_node *start_block;
1663 /* if we have no assigned start state, we must wait ... */
1667 assert(bl_state->end == NULL);
1669 DB((dbg, LEVEL_1, "Simulate %+F\n", block));
1671 /* at block begin, kill all dead registers */
1672 state = x87_kill_deads(sim, block, state);
1674 /* beware, n might changed */
1675 for (n = sched_first(block); !sched_is_end(n); n = next) {
1676 ir_op *op = get_irn_op(n);
1678 next = sched_next(n);
1679 if (op->ops.generic) {
1681 sim_func func = (sim_func)op->ops.generic;
1683 /* have work to do */
1684 if (state == bl_state->begin) {
1685 /* create a new state, will be changed */
1686 state = x87_clone_state(sim, state);
1690 node_inserted = (*func)(state, n, sim->env);
1693 sim_func might have added additional nodes after n,
1695 beware: n must not be changed by sim_func
1696 (i.e. removed from schedule) in this case
1699 next = sched_next(n);
1703 start_block = get_irg_start_block(get_irn_irg(block));
1705 /* check if the state must be shuffled */
1706 foreach_block_succ(block, edge) {
1707 ir_node *succ = get_edge_src_irn(edge);
1708 blk_state *succ_state = x87_get_bl_state(sim, succ);
1710 if (succ_state->begin && succ != start_block) {
1711 /* There is already a begin state for this block, bad.
1712 Do the necessary permutations.
1713 Note that critical edges are removed, so this is always possible. */
1714 x87_shuffle(sim, block, state, succ, succ_state->begin);
1716 /* Note further, that there can be only one such situation,
1717 so we can break here. */
1721 bl_state->end = state;
1723 /* now propagate the state to all successor blocks */
1724 foreach_block_succ(block, edge) {
1725 ir_node *succ = get_edge_src_irn(edge);
1726 blk_state *succ_state = x87_get_bl_state(sim, succ);
1728 if (! succ_state->begin)
1729 succ_state->begin = state;
1736 * Create a new x87 simulator.
1738 * @param sim a simulator handle, will be initialized
1739 * @param irg the current graph
1740 * @param env the architecture environment
1742 static void x87_init_simulator(x87_simulator *sim, ir_graph *irg, const arch_env_t *env) {
1743 obstack_init(&sim->obst);
1744 sim->blk_states = pmap_create();
1746 sim->lv = be_liveness(irg);
1748 FIRM_DBG_REGISTER(dbg, "firm.be.ia32.x87");
1750 DB((dbg, LEVEL_1, "--------------------------------\n"
1751 "x87 Simulator started for %+F\n", irg));
1753 /* set the generic function pointer of instruction we must simulate */
1754 clear_irp_opcodes_generic_func();
1756 #define ASSOC(op) (op_ ## op)->ops.generic = (op_func)(sim_##op)
1757 #define ASSOC_IA32(op) (op_ia32_v ## op)->ops.generic = (op_func)(sim_##op)
1758 #define ASSOC_BE(op) (op_be_ ## op)->ops.generic = (op_func)(sim_##op)
1776 ASSOC_IA32(fCondJmp);
1789 * Destroy a x87 simulator.
1791 * @param sim the simulator handle
1793 static void x87_destroy_simulator(x87_simulator *sim) {
1794 pmap_destroy(sim->blk_states);
1795 obstack_free(&sim->obst, NULL);
1796 be_liveness_free(sim->lv);
1797 DB((dbg, LEVEL_1, "x87 Simulator stopped\n\n"));
1801 * Run a simulation and fix all virtual instructions for a graph.
1803 * @param env the architecture environment
1804 * @param irg the current graph
1805 * @param blk_list the block schedule list
1807 * Needs a block-schedule.
1809 void x87_simulate_graph(const arch_env_t *env, ir_graph *irg, ir_node **blk_list) {
1810 ir_node *block, *start_block;
1812 blk_state *bl_state;
1816 /* create the simulator */
1817 x87_init_simulator(&sim, irg, env);
1819 start_block = get_irg_start_block(irg);
1820 bl_state = x87_get_bl_state(&sim, start_block);
1822 /* start with the empty state */
1823 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);