Remove classify_tarval(). Use tarval_is_null(), tarval_is_one() and tarval_is_all_one...
[libfirm] / ir / be / ia32 / ia32_x87.c
index 4bbd9bd..50ffd35 100644 (file)
@@ -47,6 +47,7 @@
 #include "../belive_t.h"
 #include "../besched_t.h"
 #include "../benode_t.h"
+#include "bearch_ia32_t.h"
 #include "ia32_new_nodes.h"
 #include "gen_ia32_new_nodes.h"
 #include "gen_ia32_regalloc_if.h"
@@ -141,6 +142,7 @@ struct _x87_simulator {
        vfp_liveness *live;         /**< Liveness information. */
        unsigned n_idx;             /**< The cached get_irg_last_idx() result. */
        waitq *worklist;            /**< Worklist of blocks that must be processed. */
+       ia32_isa_t *isa;            /**< the ISA object */
 };
 
 /**
@@ -306,6 +308,16 @@ static void x87_pop(x87_state *state) {
        DB((dbg, LEVEL_2, "After POP: ")); DEBUG_ONLY(x87_dump_stack(state));
 }  /* x87_pop */
 
+/**
+ * Empty the fpu stack
+ *
+ * @param state     the x87 state
+ */
+static void x87_emms(x87_state *state) {
+       state->depth = 0;
+       state->tos   = 0;
+}
+
 /**
  * Returns the block state of a block.
  *
@@ -661,10 +673,14 @@ static ir_node *x87_create_fpop(x87_state *state, ir_node *n, int num)
 {
        ir_node *fpop;
        ia32_x87_attr_t *attr;
+       int cpu = state->sim->isa->opt_arch;
 
        while (num > 0) {
                x87_pop(state);
-               fpop = new_rd_ia32_fpop(NULL, get_irn_irg(n), get_nodes_block(n), mode_E);
+               if (ARCH_ATHLON(cpu))
+                       fpop = new_rd_ia32_ffreep(NULL, get_irn_irg(n), get_nodes_block(n), mode_E);
+               else
+                       fpop = new_rd_ia32_fpop(NULL, get_irn_irg(n), get_nodes_block(n), mode_E);
                attr = get_ia32_x87_attr(fpop);
                attr->x87[0] = &ia32_st_regs[0];
                attr->x87[1] = &ia32_st_regs[0];
@@ -2021,6 +2037,24 @@ static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *
                DEBUG_ONLY(vfp_dump_live(live));
                DEBUG_ONLY(x87_dump_stack(state));
 
+               if (kill_mask != 0 && live == 0) {
+                       int cpu = sim->isa->arch;
+
+                       /* special case: kill all registers */
+                       if (ARCH_ATHLON(sim->isa->opt_arch) && ARCH_MMX(cpu)) {
+                               if (ARCH_AMD(cpu)) {
+                                       /* use FEMMS on AMD processors to clear all */
+                                       keep = new_rd_ia32_femms(NULL, get_irn_irg(block), block, mode_E);
+                               } else {
+                                       /* use EMMS to clear all */
+                                       keep = new_rd_ia32_emms(NULL, get_irn_irg(block), block, mode_E);
+                               }
+                               sched_add_before(first_insn, keep);
+                               keep_alive(keep);
+                               x87_emms(state);
+                               return state;
+                       }
+               }
                /* now kill registers */
                while (kill_mask) {
                        /* we can only kill from TOS, so bring them up */
@@ -2197,6 +2231,7 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg,
        sim->arch_env   = arch_env;
        sim->n_idx      = get_irg_last_idx(irg);
        sim->live       = obstack_alloc(&sim->obst, sizeof(*sim->live) * sim->n_idx);
+       sim->isa        = (ia32_isa_t *)arch_env->isa;
 
        DB((dbg, LEVEL_1, "--------------------------------\n"
                "x87 Simulator started for %+F\n", irg));