2 * This file implements the x87 support and virtual to stack
3 * register translation for the ia32 backend.
5 * @author: Michael Beck
14 #include "iredges_t.h"
22 #include "..\belive_t.h"
23 #include "..\besched.h"
24 #include "..\benode_t.h"
25 #include "ia32_new_nodes.h"
26 #include "gen_ia32_new_nodes.h"
27 #include "gen_ia32_regalloc_if.h"
32 /* first and second binop index */
39 /* the store val index */
40 #define STORE_VAL_IDX 2
42 #define MASK_TOS(x) ((x) & (N_x87_REGS - 1))
44 /** the debug handle */
45 static firm_dbg_module_t *dbg = NULL;
48 * An exchange template.
49 * Note that our virtual functions have the same inputs
50 * and attributes as the real ones, so we can simple exchange
52 * Further, x87 supports inverse instructions, so we can handle them.
54 typedef struct _exchange_tmpl {
55 ir_op *normal_op; /**< the normal one */
56 ir_op *reverse_op; /**< the reverse one if exists */
57 ir_op *normal_pop_op; /**< the normal one with tos pop */
58 ir_op *reverse_pop_op; /**< the reverse one with tos pop */
64 typedef struct _x87_state {
65 const arch_register_t *st[N_x87_REGS]; /**< the register stack */
66 int depth; /**< the current stack depth */
67 int tos; /**< position of the tos */
70 /** An empty state, used for blocks without fp instructions. */
71 static const x87_state _empty = { {0}, 0, 0 };
72 static x87_state *empty = (x87_state *)&_empty;
74 /** The type of an instruction simulator */
75 typedef void (*sim_func)(x87_state *state, ir_node *n, const arch_env_t *env);
78 * A block state: Every block has a x87 state at the beginning and at the end.
80 typedef struct _blk_state {
81 x87_state *begin; /**< state at the begin or NULL if not assigned */
82 x87_state *end; /**< state at the end or NULL if not assigned */
85 #define PTR_TO_BLKSTATE(p) ((blk_state *)(p))
90 typedef struct _x87_simulator {
91 struct obstack obst; /**< an obstack for fast allocating */
92 pmap *blk_states; /**< map blocks to states */
93 const arch_env_t *env; /**< architecture environment */
97 * Check if the state is empty.
99 static int x87_state_is_empty(const x87_state *state) {
100 return state->depth == 0;
104 * Return the virtual register at st(pos).
106 static const arch_register_t *x87_get_reg(const x87_state *state, int pos) {
107 assert(pos < state->depth);
108 return state->st[MASK_TOS(state->tos + pos)];
113 * Dump the stack for debugging.
115 static void x87_dump_stack(const x87_state *state) {
118 for (i = state->depth - 1; i >= 0; --i) {
119 const arch_register_t *vreg = x87_get_reg(state, i);
120 DB((dbg, LEVEL_2, "%s ", vreg->name));
122 DB((dbg, LEVEL_2, "<-- TOS\n"));
124 #endif /* DEBUG_libfirm */
127 * Set a virtual register to st(pos)
129 static void x87_set_reg(x87_state *state, const arch_register_t *vreg, int pos) {
130 assert(0 < state->depth);
131 state->st[MASK_TOS(state->tos + pos)] = vreg;
133 DB((dbg, LEVEL_2, "After SET_REG:\n ")); DEBUG_ONLY(x87_dump_stack(state));
137 * Set the tos virtual register
139 static void x87_set_tos_reg(x87_state *state, const arch_register_t *vreg) {
140 x87_set_reg(state, vreg, 0);
144 * Flush the x87 stack.
146 static void x87_flush(x87_state *state) {
152 * Swap st(0) with st(pos).
154 static void x87_fxch(x87_state *state, int pos) {
155 const arch_register_t *vreg;
156 assert(pos < state->depth);
158 vreg = state->st[MASK_TOS(state->tos + pos)];
159 state->st[MASK_TOS(state->tos + pos)] = state->st[MASK_TOS(state->tos)];
160 state->st[MASK_TOS(state->tos)] = vreg;
162 DB((dbg, LEVEL_2, "After FXCH:\n ")); DEBUG_ONLY(x87_dump_stack(state));
166 * Convert a virtual register to the stack index.
167 * Return -1 if the virtual register was not found.
169 static int x87_on_stack(const x87_state *state, const arch_register_t *vreg) {
170 int i, tos = state->tos;
172 for (i = 0; i < state->depth; ++i)
173 if (state->st[MASK_TOS(tos + i)] == vreg)
179 * Push a virtual Register onto the stack.
181 static void x87_push(x87_state *state, const arch_register_t *vreg) {
182 // assert(x87_on_stack(state, vreg) == -1 && "double push");
183 assert(state->depth < N_x87_REGS && "stack overrun");
186 state->tos = MASK_TOS(state->tos - 1);
187 state->st[state->tos] = vreg;
189 DB((dbg, LEVEL_2, "After PUSH:\n ")); DEBUG_ONLY(x87_dump_stack(state));
193 * Pop a virtual Register from the stack.
195 static void x87_pop(x87_state *state) {
196 assert(state->depth > 0 && "stack underrun");
199 state->tos = MASK_TOS(state->tos + 1);
201 DB((dbg, LEVEL_2, "After POP:\n ")); DEBUG_ONLY(x87_dump_stack(state));
205 * Returns the block state of a block.
207 static blk_state *x87_get_bl_state(x87_simulator *sim, ir_node *block) {
208 pmap_entry *entry = pmap_find(sim->blk_states, block);
211 blk_state *bl_state = obstack_alloc(&sim->obst, sizeof(*bl_state));
212 bl_state->begin = NULL;
213 bl_state->end = NULL;
215 pmap_insert(sim->blk_states, block, bl_state);
219 return entry ? PTR_TO_BLKSTATE(entry->value) : NULL;
223 * Create a new x87 state.
225 static x87_state *x87_alloc_state(x87_simulator *sim) {
226 x87_state *res = obstack_alloc(&sim->obst, sizeof(*res));
231 * Create a new empty x87 state.
233 static x87_state *x87_alloc_empty_state(x87_simulator *sim) {
234 x87_state *res = x87_alloc_state(sim);
243 static x87_state *x87_clone_state(x87_simulator *sim, const x87_state *src) {
244 x87_state *res = x87_alloc_state(sim);
246 memcpy(res, src, sizeof(*res));
250 /* -------------- x87 perm --------------- */
253 * Calculate the necessary permutations to reach dst_state.
255 static x87_state *x87_shuffle(x87_simulator *sim, ir_node *block, x87_state *state, const x87_state *dst_state) {
256 int i, n_rings, k, ri;
257 unsigned rings[4], all_mask;
260 assert(state->depth == dst_state->depth);
262 /* Some mathematics here:
263 If we have a ring of lenght n that includes the tos,
264 we need n-1 exchange operations.
265 We can always add the tos and restore it, so we need
266 n+1 exchange operations for a ring not containing the tos.
267 So, the maximum of needed operations is for a ring of 7
268 not including the tos == 8.
269 This is so same number of ops we would need for store,
270 so exchange is cheaper (we save the loads).
271 On the other hand, we might need an additional exchange
272 in the next block to bring one operand on top, so the
273 number of ops in the first case is identical.
274 Further, no more than 4 rings can exists.
276 all_mask = (1 << (state->depth)) - 1;
278 for (n_rings = 0; all_mask; ++n_rings) {
279 int src_idx, dst_idx;
281 /* find the first free slot */
282 for (i = 0; i < state->depth; ++i) {
283 if (all_mask & (1 << i)) {
284 all_mask &= ~(1 << i);
286 /* check if there are differences here */
287 if (x87_get_reg(state, i) != x87_get_reg(dst_state, i))
293 /* no more rings found */
298 rings[n_rings] = (1 << i);
299 ring_idx[n_rings][k++] = i;
300 for (src_idx = i; ; src_idx = dst_idx) {
301 dst_idx = x87_on_stack(dst_state, x87_get_reg(state, src_idx));
303 if ((all_mask & (1 << dst_idx)) == 0)
306 ring_idx[n_rings][k++] = dst_idx;
307 rings[n_rings] |= (1 << dst_idx);
308 all_mask &= ~(1 << dst_idx);
310 ring_idx[n_rings][k] = -1;
314 /* no permutation needed */
318 /* Hmm: permutation needed */
319 DB((dbg, LEVEL_2, "\nNeed permutation: from\n"));
320 DEBUG_ONLY(x87_dump_stack(state));
321 DB((dbg, LEVEL_2, " to\n"));
322 DEBUG_ONLY(x87_dump_stack(dst_state));
326 DB((dbg, LEVEL_2, "Need %d rings\n", n_rings));
327 for (ri = 0; ri < n_rings; ++ri) {
328 DB((dbg, LEVEL_2, " Ring %d:\n ", ri));
329 for (k = 0; ring_idx[ri][k] != -1; ++k)
330 DB((dbg, LEVEL_2, " st%d ->", ring_idx[ri][k]));
331 DB((dbg, LEVEL_2, "\n"));
335 /* now do the permutations */
336 for (ri = 0; ri < n_rings; ++ri) {
337 if ((rings[ri] & 1) == 0) {
338 /* this ring does not include the tos */
339 x87_fxch(state, ring_idx[ri][0]);
341 for (k = 1; ring_idx[ri][k] != -1; ++k) {
342 x87_fxch(state, ring_idx[ri][k]);
344 if ((rings[ri] & 1) == 0) {
345 /* this ring does not include the tos */
346 x87_fxch(state, ring_idx[ri][0]);
354 * Create a fxch before node n.
356 static void x87_create_fxch(x87_state *state, ir_node *n, int pos, int op_idx) {
357 ir_node *fxch, *pred;
360 x87_fxch(state, pos);
362 pred = get_irn_n(n, op_idx);
363 fxch = new_rd_ia32_fxch(NULL, get_irn_irg(n), get_nodes_block(n), pred, get_irn_mode(pred));
364 attr = get_ia32_attr(fxch);
365 attr->x87[0] = &ia32_st_regs[pos];
366 attr->x87[2] = &ia32_st_regs[0];
367 set_irn_n(n, op_idx, fxch);
369 sched_add_before(n, fxch);
370 DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(fxch), attr->x87[0]->name, attr->x87[2]->name));
374 * Create a fpush before node n.
376 static void x87_create_fpush(const arch_env_t *env, x87_state *state, ir_node *n, int pos, int op_idx) {
377 ir_node *fpush, *pred;
380 x87_push(state, arch_get_irn_register(env, n));
382 pred = get_irn_n(n, op_idx);
383 fpush = new_rd_ia32_fpush(NULL, get_irn_irg(n), get_nodes_block(n), pred, get_irn_mode(pred));
384 attr = get_ia32_attr(fpush);
385 attr->x87[0] = &ia32_st_regs[pos];
386 attr->x87[2] = &ia32_st_regs[0];
387 set_irn_n(n, op_idx, fpush);
389 sched_add_before(n, fpush);
390 DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(fpush), attr->x87[0]->name, attr->x87[2]->name));
393 /* --------------------------------- liveness ------------------------------------------ */
396 * The liveness transfer function.
397 * Updates a live set over a single step from a given node to its predecessor.
398 * Everything defined at the node is removed from the set, the uses of the node get inserted.
399 * @param arch_env The architecture environment.
400 * @param irn The node at which liveness should be computed.
401 * @param live The bitset of registers live before @p irn. This set gets modified by updating it to
402 * the registers live after irn.
405 static unsigned vfp_liveness_transfer(const arch_env_t *arch_env, ir_node *irn, unsigned live)
408 const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
410 if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
411 const arch_register_t *reg = arch_get_irn_register(arch_env, irn);
412 live &= ~(1 << reg->index);
415 for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
416 ir_node *op = get_irn_n(irn, i);
418 if (arch_irn_consider_in_reg_alloc(arch_env, cls, op)) {
419 const arch_register_t *reg = arch_get_irn_register(arch_env, op);
420 live |= 1 << reg->index;
428 * Put all live virtual registers at the end of a block into a bitset.
429 * @param arch_env The architecture environment.
430 * @param bl The block.
431 * @return The live bitset.
433 static unsigned vfp_liveness_end_of_block(const arch_env_t *arch_env, const ir_node *bl)
437 const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
439 live_foreach(bl, li) {
440 ir_node *irn = (ir_node *) li->irn;
441 if (live_is_end(li) && arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
442 const arch_register_t *reg = arch_get_irn_register(arch_env, irn);
443 live |= 1 << reg->index;
451 * Compute a bitset of registers which are live at another node.
452 * @param arch_env The architecture environment.
453 * @param pos The node.
454 * @return The live bitset.
456 static unsigned vfp_liveness_nodes_live_at(const arch_env_t *arch_env, const ir_node *pos)
458 const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
459 const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
463 live = vfp_liveness_end_of_block(arch_env, bl);
465 sched_foreach_reverse(bl, irn) {
467 * If we encounter the node we want to insert the Perm after,
468 * exit immediately, so that this node is still live
473 live = vfp_liveness_transfer(arch_env, irn, live);
480 * Returns true if a register is live in a set.
482 static unsigned is_vfp_live(const arch_register_t *reg, unsigned live) {
483 return live & (1 << reg->index);
488 * dump liveness info.
490 static vfp_dump_live(unsigned live) {
493 DB((dbg, LEVEL_2, "Live registers here: \n"));
494 for (i = 0; i < 8; ++i) {
495 if (live & (1 << i)) {
496 DB((dbg, LEVEL_2, " vf%d", i));
499 DB((dbg, LEVEL_2, "\n"));
501 #endif /* DEBUG_libfirm */
503 /* --------------------------------- simulators ---------------------------------------- */
505 #define XCHG(a, b) do { int t =(a); (a) = (b); (b) = t; } while (0)
508 * Simulate a virtual binop
510 static void sim_binop(x87_state *state, ir_node *n, const arch_env_t *env, const exchange_tmpl *tmpl) {
511 int op1_idx, op2_idx = -1;
512 int out_idx, do_pop =0;
515 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_1));
516 const arch_register_t *op2 = arch_get_irn_register(env, get_irn_n(n, BINOP_IDX_2));
517 const arch_register_t *out = arch_get_irn_register(env, n);
518 unsigned live = vfp_liveness_nodes_live_at(env, n);
520 DB((dbg, LEVEL_1, ">>> %s %s, %s -> %s\n", get_irn_opname(n), op1->name, op2->name, out->name));
521 DEBUG_ONLY(vfp_dump_live(live));
523 op1_idx = x87_on_stack(state, op1);
525 if (op2->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]) {
526 /* second operand is a vfp register */
527 op2_idx = x87_on_stack(state, op2);
529 if (is_vfp_live(op1, live)) {
530 /* first operand is live */
532 if (is_vfp_live(op2, live)) {
533 /* both operands are live: push the first one */
534 x87_create_fpush(env, state, n, op1_idx, BINOP_IDX_1);
535 out_idx = op1_idx = 0;
537 dst = tmpl->normal_op;
541 /* first live, second operand is dead here, bring it to tos */
543 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
547 op2_idx = out_idx = 0;
548 dst = tmpl->normal_op;
553 /* first operand is dead */
554 if (is_vfp_live(op2, live)) {
555 /* second operand is live: bring first to tos */
557 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
561 op1_idx = out_idx = 0;
562 dst = tmpl->normal_op;
566 /* both operands are dead here, pop them from the stack */
569 XCHG(op1_idx, op2_idx);
570 dst = tmpl->reverse_pop_op;
573 else if (op2_idx == 0) {
575 dst = tmpl->normal_pop_op;
579 /* bring the second on top */
580 x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
583 dst = tmpl->normal_pop_op;
590 /* second operand is an address mode */
591 if (is_vfp_live(op1, live)) {
592 /* first operand is live: push it here */
593 x87_create_fpush(env, state, n, op1_idx, BINOP_IDX_1);
596 /* first operand is dead: bring it to tos */
598 x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
600 op1_idx = out_idx = 0;
601 dst = tmpl->normal_op;
605 x87_set_reg(state, out, out_idx);
609 /* patch the operation */
611 attr = get_ia32_attr(n);
612 attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
613 attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
614 attr->x87[2] = out = &ia32_st_regs[out_idx];
616 DB((dbg, LEVEL_1, "<<< %s %s, %s -> %s\n", get_irn_opname(n), op1->name, op2->name, out->name));
620 * Simulate a virtual Unop
622 static void sim_unop(x87_state *state, ir_node *n, const arch_env_t *env, ir_op *op) {
623 int op1_idx, out_idx;
624 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, UNOP_IDX));
625 const arch_register_t *out = arch_get_irn_register(env, n);
627 unsigned live = vfp_liveness_nodes_live_at(env, n);
629 DB((dbg, LEVEL_1, ">>> %s -> %s\n", get_irn_opname(n), out->name));
630 DEBUG_ONLY(vfp_dump_live(live));
632 op1_idx = x87_on_stack(state, op1);
634 if (is_vfp_live(op1, live)) {
635 /* push the operand here */
636 x87_create_fpush(env, state, n, op1_idx, UNOP_IDX);
639 /* operand is dead, bring it to tos */
641 x87_create_fxch(state, n, op1_idx, UNOP_IDX);
644 x87_set_tos_reg(state, out);
645 op1_idx = out_idx = 0;
647 attr = get_ia32_attr(n);
648 attr->x87[0] = op1 = &ia32_st_regs[0];
649 attr->x87[2] = out = &ia32_st_regs[0];
650 DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), out->name));
654 * Simulate a virtual Load instructions
656 static void sim_load(x87_state *state, ir_node *n, const arch_env_t *env, ir_op *op) {
657 const arch_register_t *out = arch_get_irn_register(env, n);
660 DB((dbg, LEVEL_1, ">>> %s -> %s\n", get_irn_opname(n), out->name));
661 x87_push(state, out);
663 attr = get_ia32_attr(n);
664 attr->x87[2] = out = &ia32_st_regs[0];
665 DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), out->name));
669 * Simulate a virtual Store
671 static void sim_fst(x87_state *state, ir_node *n, const arch_env_t *env) {
673 const arch_register_t *op2 = arch_get_irn_register(env, get_irn_n(n, STORE_VAL_IDX));
675 unsigned live = vfp_liveness_nodes_live_at(env, n);
677 op2_idx = x87_on_stack(state, op2);
679 DB((dbg, LEVEL_1, ">>> %s %s ->\n", get_irn_opname(n), op2->name));
681 /* we can only store the tos to memory */
683 x87_create_fxch(state, n, op2_idx, STORE_VAL_IDX);
685 if (is_vfp_live(op2, live))
689 n->op = op_ia32_fstp;
692 attr = get_ia32_attr(n);
693 attr->x87[1] = op2 = &ia32_st_regs[0];
694 DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), op2->name));
697 #define _GEN_BINOP(op, rev) \
698 static void sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
699 exchange_tmpl tmpl = { op_ia32_##op, op_ia32_##rev, op_ia32_##op##p, op_ia32_##rev##p }; \
700 sim_binop(state, n, env, &tmpl); \
703 #define GEN_BINOP(op) _GEN_BINOP(op, op)
704 #define GEN_BINOPR(op) _GEN_BINOP(op, op##r)
706 #define GEN_LOAD2(op, nop) \
707 static void sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
708 sim_load(state, n, env, op_ia32_##nop); \
711 #define GEN_LOAD(op) GEN_LOAD2(op, op)
713 #define GEN_UNOP(op) \
714 static void sim_##op(x87_state *state, ir_node *n, const arch_env_t *env) { \
715 sim_unop(state, n, env, op_ia32_##op); \
727 GEN_LOAD2(fConst, fldConst)
736 * Simulate a virtual Copy
738 static void sim_Copy(x87_state *state, ir_node *n, const arch_env_t *env) {
739 ir_mode *mode = get_irn_mode(n);
741 if (mode_is_float(mode)) {
742 const arch_register_t *op1 = arch_get_irn_register(env, get_irn_n(n, 0));
743 const arch_register_t *out = arch_get_irn_register(env, n);
744 ir_node *node, *next;
747 unsigned live = vfp_liveness_nodes_live_at(env, n);
749 op1_idx = x87_on_stack(state, op1);
751 DB((dbg, LEVEL_1, ">>> %s %s -> %s\n", get_irn_opname(n), op1->name, out->name));
752 DEBUG_ONLY(vfp_dump_live(live));
754 if (is_vfp_live(op1, live)) {
755 /* operand is still live,a real copy */
756 x87_push(state, out);
758 node = new_rd_ia32_fpush(get_irn_dbg_info(n), get_irn_irg(n), get_nodes_block(n), get_irn_n(n, 0), mode);
759 arch_set_irn_register(env, node, out);
761 attr = get_ia32_attr(node);
762 attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
763 attr->x87[2] = out = &ia32_st_regs[0];
765 next = sched_next(n);
768 sched_add_before(next, node);
769 DB((dbg, LEVEL_1, ">>> %s %s -> %s\n", get_irn_opname(node), op1->name, out->name));
772 /* just a virtual copy */
773 x87_set_reg(state, out, op1_idx);
775 DB((dbg, LEVEL_1, ">>> KILLED %s\n", get_irn_opname(n)));
781 * Run a simulation and fix all virtual instructions for a block.
783 * @return non-zero if simulation is complete,
784 * zero if the simulation must be rerun
786 static int x87_simulate_block(x87_simulator *sim, ir_node *block) {
788 blk_state *bl_state = x87_get_bl_state(sim, block);
789 x87_state *state = bl_state->begin;
790 const ir_edge_t *edge;
791 ir_node *start_block;
793 /* if we have no assigned start state, we must wait ... */
797 assert(bl_state->end == NULL);
799 DB((dbg, LEVEL_1, "Simulate %+F\n", block));
801 /* beware, n might changed */
802 for (n = sched_first(block); !sched_is_end(n); n = next) {
803 ir_op *op = get_irn_op(n);
805 next = sched_next(n);
806 if (op->ops.generic) {
807 sim_func func = (sim_func)op->ops.generic;
809 /* have work to do */
810 if (state == bl_state->begin) {
811 /* create a new state, will be changed */
812 state = x87_clone_state(sim, state);
816 (*func)(state, n, sim->env);
820 start_block = get_irg_start_block(get_irn_irg(block));
822 /* check if the state must be shuffled */
823 foreach_block_succ(block, edge) {
824 ir_node *succ = get_edge_src_irn(edge);
825 blk_state *succ_state = x87_get_bl_state(sim, succ);
827 if (succ_state->begin && succ != start_block) {
828 /* There is already a begin state for this block, bad.
829 Do the necessary permutations.
830 Note that critical edges are removed, so this is always possible. */
831 x87_shuffle(sim, block, state, succ_state->begin);
833 /* Note further, that there can be only one such situation,
834 so we can break here. */
838 bl_state->end = state;
840 /* now propagate the state to all successor blocks */
841 foreach_block_succ(block, edge) {
842 ir_node *succ = get_edge_src_irn(edge);
843 blk_state *succ_state = x87_get_bl_state(sim, succ);
845 if (! succ_state->begin)
846 succ_state->begin = state;
853 * Create a new x87 simulator.
855 static void x87_init_simulator(x87_simulator *sim, const arch_env_t *env) {
856 obstack_init(&sim->obst);
857 sim->blk_states = pmap_create();
860 FIRM_DBG_REGISTER(dbg, "firm.be.ia32.x87");
861 firm_dbg_set_mask(dbg, SET_LEVEL_2);
863 DB((dbg, LEVEL_1, "x87 Simulator started\n"));
865 /* set the generic function pointer of instruction we must simulate */
866 clear_irp_opcodes_generic_func();
868 #define ASSOC(op) (op_ia32_v ## op)->ops.generic = (op_func)(sim_##op)
869 #define ASSOC_BE(op) (op_be_ ## op)->ops.generic = (op_func)(sim_##op)
891 * Destroy a x87 simulator.
893 static void x87_destroy_simulator(x87_simulator *sim) {
894 pmap_destroy(sim->blk_states);
895 obstack_free(&sim->obst, NULL);
896 DB((dbg, LEVEL_1, "x87 Simulator stopped\n"));
900 * Run a simulation and fix all virtual instructions for a graph.
902 * Needs a block-schedule.
904 void x87_simulate_graph(const arch_env_t *env, ir_graph *irg, ir_node **blk_list) {
905 ir_node *block, *start_block;
911 /* we need liveness info for the current graph */
914 /* create the simulator */
915 x87_init_simulator(&sim, env);
917 start_block = get_irg_start_block(irg);
918 bl_state = x87_get_bl_state(&sim, start_block);
920 /* start with the empty state */
921 bl_state->begin = empty;
923 worklist = new_pdeq();
925 /* create the worklist for the schedule. */
926 for (i = 0; i < ARR_LEN(blk_list); ++i)
927 pdeq_putr(worklist, blk_list[i]);
931 block = pdeq_getl(worklist);
932 if (! x87_simulate_block(&sim, block)) {
933 pdeq_putr(worklist, block);
936 } while (! pdeq_empty(worklist));
939 x87_destroy_simulator(&sim);