arch_register_class_put() is only used locally
[libfirm] / ir / be / ia32 / ia32_x87.c
index 965d11e..c724764 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -52,6 +52,7 @@
 #include "gen_ia32_new_nodes.h"
 #include "gen_ia32_regalloc_if.h"
 #include "ia32_x87.h"
+#include "ia32_architecture.h"
 
 #define N_x87_REGS 8
 
@@ -169,6 +170,7 @@ static int x87_get_st_reg(const x87_state *state, int pos) {
        return state->st[MASK_TOS(state->tos + pos)].reg_idx;
 }  /* x87_get_st_reg */
 
+#ifdef DEBUG_libfirm
 /**
  * Return the node at st(pos).
  *
@@ -182,7 +184,6 @@ static ir_node *x87_get_st_node(const x87_state *state, int pos) {
        return state->st[MASK_TOS(state->tos + pos)].node;
 }  /* x87_get_st_node */
 
-#ifdef DEBUG_libfirm
 /**
  * Dump the stack for debugging.
  *
@@ -671,13 +672,13 @@ static void x87_create_fpush(x87_state *state, ir_node *n, int pos, int op_idx)
  */
 static ir_node *x87_create_fpop(x87_state *state, ir_node *n, int num)
 {
-       ir_node *fpop;
+       ir_node         *fpop = NULL;
        ia32_x87_attr_t *attr;
-       int cpu = state->sim->isa->opt_arch;
 
+       assert(num > 0);
        while (num > 0) {
                x87_pop(state);
-               if (ARCH_ATHLON(cpu))
+               if (ia32_cg_config.use_ffreep)
                        fpop = new_rd_ia32_ffreep(NULL, get_irn_irg(n), get_nodes_block(n));
                else
                        fpop = new_rd_ia32_fpop(NULL, get_irn_irg(n), get_nodes_block(n));
@@ -1212,8 +1213,9 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p) {
                        Solution:
                                - stack not full: push value and fstp
                                - stack full: fstp value and load again
+                       Note that we cannot test on mode_E, because floats might be 96bit ...
                */
-               if (mode == mode_E || mode == mode_Ls) {
+               if (get_mode_size_bits(mode) > 64 || mode == mode_Ls) {
                        if (depth < N_x87_REGS) {
                                /* ok, we have a free register: push + fstp */
                                x87_create_fpush(state, n, op2_idx, n_ia32_vfst_val);
@@ -1329,6 +1331,58 @@ GEN_LOAD(fld1)
 GEN_STORE(fst)
 GEN_STORE(fist)
 
+/**
+* Simulate a virtual fisttp.
+*
+* @param state  the x87 state
+* @param n      the node that should be simulated (and patched)
+*/
+static int sim_fisttp(x87_state *state, ir_node *n) {
+       x87_simulator         *sim = state->sim;
+       ir_node               *val = get_irn_n(n, n_ia32_vfst_val);
+       const arch_register_t *op2 = x87_get_irn_register(sim, val);
+       int                   insn = NO_NODE_ADDED;
+       ia32_x87_attr_t *attr;
+       int op2_reg_idx, op2_idx, depth;
+
+       op2_reg_idx = arch_register_get_index(op2);
+       if (op2_reg_idx == REG_VFP_UKNWN) {
+               /* just take any value from stack */
+               if (state->depth > 0) {
+                       op2_idx = 0;
+                       DEBUG_ONLY(op2 = NULL);
+               } else {
+                       /* produce a new value which we will consume immediately */
+                       x87_create_fldz(state, n, op2_reg_idx);
+                       op2_idx = x87_on_stack(state, op2_reg_idx);
+                       assert(op2_idx >= 0);
+               }
+       } else {
+               op2_idx = x87_on_stack(state, op2_reg_idx);
+               DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_register_get_name(op2)));
+               assert(op2_idx >= 0);
+       }
+
+       depth = x87_get_depth(state);
+
+       /* Note: although the value is still live here, it is destroyed because
+          of the pop. The register allocator is aware of that and introduced a copy
+          if the value must be alive. */
+
+       /* we can only store the tos to memory */
+       if (op2_idx != 0)
+               x87_create_fxch(state, n, op2_idx);
+
+       x87_pop(state);
+       x87_patch_insn(n, op_ia32_fisttp);
+
+       attr = get_ia32_x87_attr(n);
+       attr->x87[1] = op2 = &ia32_st_regs[0];
+       DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
+
+       return insn;
+}  /* sim_fisttp */
+
 static int sim_FtstFnstsw(x87_state *state, ir_node *n) {
        x87_simulator         *sim         = state->sim;
        ia32_x87_attr_t       *attr        = get_ia32_x87_attr(n);
@@ -1382,7 +1436,7 @@ static int sim_Fucom(x87_state *state, ir_node *n) {
        int reg_index_1 = arch_register_get_index(op1);
        int reg_index_2 = arch_register_get_index(op2);
        unsigned live = vfp_live_args_after(sim, n, 0);
-       int                    flipped  = attr->attr.data.cmp_flipped;
+       int                    permuted = attr->attr.data.ins_permuted;
        int xchg = 0;
        int pops = 0;
        int node_added = NO_NODE_ADDED;
@@ -1412,7 +1466,7 @@ static int sim_Fucom(x87_state *state, ir_node *n) {
                                        /* res = tos X op */
                                } else if (op2_idx == 0) {
                                        /* res = op X tos */
-                                       flipped = !flipped;
+                                       permuted = !permuted;
                                        xchg    = 1;
                                } else {
                                        /* bring the first one to tos */
@@ -1449,7 +1503,7 @@ static int sim_Fucom(x87_state *state, ir_node *n) {
                                }
                                /* res = op X tos, pop */
                                pops    = 1;
-                               flipped = !flipped;
+                               permuted = !permuted;
                                xchg    = 1;
                        } else {
                                /* both operands are dead here, check first for identity. */
@@ -1484,7 +1538,7 @@ static int sim_Fucom(x87_state *state, ir_node *n) {
                                                op2_idx = 0;
                                        }
                                        /* res = op X tos, pop, pop */
-                                       flipped = !flipped;
+                                       permuted = !permuted;
                                        xchg    = 1;
                                        pops    = 2;
                                } else {
@@ -1498,7 +1552,7 @@ static int sim_Fucom(x87_state *state, ir_node *n) {
                                                op2_idx = 0;
                                                /* res = op X tos, pop, pop */
                                                pops    = 2;
-                                               flipped = !flipped;
+                                               permuted = !permuted;
                                                xchg    = 1;
                                        } else if (op2_idx == 0) {
                                                /* second one is TOS, move to st(1) */
@@ -1542,7 +1596,7 @@ static int sim_Fucom(x87_state *state, ir_node *n) {
        }
 
        /* patch the operation */
-       if(is_ia32_vFucomFnstsw(n)) {
+       if (is_ia32_vFucomFnstsw(n)) {
                int i;
 
                switch(pops) {
@@ -1585,14 +1639,15 @@ static int sim_Fucom(x87_state *state, ir_node *n) {
                attr->x87[1] = op2;
        }
        attr->x87[2] = NULL;
-       attr->attr.data.cmp_flipped = flipped;
+       attr->attr.data.ins_permuted = permuted;
 
-       if (op2_idx >= 0)
+       if (op2_idx >= 0) {
                DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(n),
                        arch_register_get_name(op1), arch_register_get_name(op2)));
-       else
+       } else {
                DB((dbg, LEVEL_1, "<<< %s %s, [AM]\n", get_irn_opname(n),
                        arch_register_get_name(op1)));
+       }
 
        return node_added;
 }
@@ -1740,14 +1795,14 @@ static int sim_Copy(x87_state *state, ir_node *n) {
        ir_node                     *pred;
        const arch_register_t       *out;
        const arch_register_t       *op1;
-       const arch_register_class_t *class;
+       const arch_register_class_t *cls;
        ir_node                     *node, *next;
        ia32_x87_attr_t             *attr;
        int                         op1_idx, out_idx;
        unsigned                    live;
 
-       class = arch_get_irn_reg_class(sim->arch_env, n, -1);
-       if (class->regs != ia32_vfp_regs)
+       cls = arch_get_irn_reg_class(sim->arch_env, n, -1);
+       if (cls->regs != ia32_vfp_regs)
                return 0;
 
        pred = get_irn_n(n, 0);
@@ -1800,8 +1855,7 @@ static int sim_Copy(x87_state *state, ir_node *n) {
                        keep_float_node_alive(state, pred);
                }
 
-               DB((dbg, LEVEL_1, "<<< %+F %s -> %s\n", node, op1->name,
-                   arch_get_irn_register(sim->arch_env, node)->name));
+               DB((dbg, LEVEL_1, "<<< %+F %s -> ?\n", node, op1->name));
        } else {
                out_idx = x87_on_stack(state, arch_register_get_index(out));
 
@@ -2095,11 +2149,9 @@ static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *
                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)) {
+                       if (ia32_cg_config.use_femms || ia32_cg_config.use_emms) {
+                               if (ia32_cg_config.use_femms) {
                                        /* use FEMMS on AMD processors to clear all */
                                        keep = new_rd_ia32_femms(NULL, get_irn_irg(block), block);
                                } else {
@@ -2294,7 +2346,6 @@ 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));
@@ -2314,6 +2365,7 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg,
        register_sim(op_ia32_vfabs,        sim_fabs);
        register_sim(op_ia32_vfchs,        sim_fchs);
        register_sim(op_ia32_vfist,        sim_fist);
+       register_sim(op_ia32_vfisttp,      sim_fisttp);
        register_sim(op_ia32_vfst,         sim_fst);
        register_sim(op_ia32_vFtstFnstsw,  sim_FtstFnstsw);
        register_sim(op_ia32_vFucomFnstsw, sim_Fucom);