added new nodes for intrinsic lowering
[libfirm] / ir / be / ia32 / ia32_x87.c
index 85b915e..3c45ba7 100644 (file)
@@ -82,7 +82,7 @@ typedef struct _x87_state {
 } x87_state;
 
 /** An empty state, used for blocks without fp instructions. */
-static const x87_state _empty = { {0, NULL}, 0, 0 };
+static const x87_state _empty = { { {0, NULL}, }, 0, 0 };
 static x87_state *empty = (x87_state *)&_empty;
 
 /** The type of an instruction simulator */
@@ -795,15 +795,15 @@ static void sim_binop(x87_state *state, ir_node *n, const arch_env_t *env, const
        unsigned live = vfp_liveness_nodes_live_at(env, n);
 
        DB((dbg, LEVEL_1, ">>> %s %s, %s -> %s\n", get_irn_opname(n),
-               arch_register_get_name(op2), arch_register_get_name(op1),
+               arch_register_get_name(op1), arch_register_get_name(op2),
                arch_register_get_name(out)));
-  DEBUG_ONLY(vfp_dump_live(live));
+       DEBUG_ONLY(vfp_dump_live(live));
 
+       op1_idx = x87_on_stack(state, arch_register_get_index(op1));
        op2_idx = x87_on_stack(state, arch_register_get_index(op2));
 
-       if (op1->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]) {
-               /* first operand is a vfp register */
-               op1_idx = x87_on_stack(state, arch_register_get_index(op1));
+       if (op2->index != REG_VFP_NOREG) {
+               /* second operand is a vfp register */
 
                if (is_vfp_live(op2->index, live)) {
                        /* Second operand is live. */
@@ -889,17 +889,17 @@ static void sim_binop(x87_state *state, ir_node *n, const arch_env_t *env, const
                }
        }
        else {
-               /* first operand is an address mode */
-               if (is_vfp_live(op2->index, live)) {
-                       /* second operand is live: push it here */
-                       x87_create_fpush(env, state, n, op2_idx, BINOP_IDX_2);
+               /* second operand is an address mode */
+               if (is_vfp_live(op1->index, live)) {
+                       /* first operand is live: push it here */
+                       x87_create_fpush(env, state, n, op1_idx, BINOP_IDX_1);
                }
                else {
-                       /* second operand is dead: bring it to tos */
-                       if (op2_idx != 0)
-                               x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
+                       /* first operand is dead: bring it to tos */
+                       if (op1_idx != 0)
+                               x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
                }
-               op2_idx = out_idx = 0;
+               op1_idx = out_idx = 0;
                dst = tmpl->normal_op;
                do_pop = 0;
        }
@@ -910,14 +910,19 @@ static void sim_binop(x87_state *state, ir_node *n, const arch_env_t *env, const
 
        /* patch the operation */
        attr = get_ia32_attr(n);
-       if (op1_idx >= 0)
-               attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
-       attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
+       attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
+       if (op2_idx >= 0)
+               attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
        attr->x87[2] = out = &ia32_st_regs[out_idx];
 
-       DB((dbg, LEVEL_1, "<<< %s %s, %s -> %s\n", get_irn_opname(n),
-               arch_register_get_name(op2), arch_register_get_name(op1),
-               arch_register_get_name(out)));
+       if (op2_idx > 0)
+               DB((dbg, LEVEL_1, "<<< %s %s, %s -> %s\n", get_irn_opname(n),
+                       arch_register_get_name(op1), arch_register_get_name(op2),
+                       arch_register_get_name(out)));
+       else
+               DB((dbg, LEVEL_1, "<<< %s %s, [AM] -> %s\n", get_irn_opname(n),
+                       arch_register_get_name(op1),
+                       arch_register_get_name(out)));
 }
 
 /**
@@ -936,7 +941,7 @@ static void sim_unop(x87_state *state, ir_node *n, const arch_env_t *env, ir_op
        unsigned live = vfp_liveness_nodes_live_at(env, n);
 
        DB((dbg, LEVEL_1, ">>> %s -> %s\n", get_irn_opname(n), out->name));
-  DEBUG_ONLY(vfp_dump_live(live));
+       DEBUG_ONLY(vfp_dump_live(live));
 
        op1_idx = x87_on_stack(state, arch_register_get_index(op1));
 
@@ -993,6 +998,7 @@ static void sim_store(x87_state *state, ir_node *n, const arch_env_t *env, ir_op
        unsigned live = vfp_liveness_nodes_live_at(env, n);
 
        op2_idx = x87_on_stack(state, arch_register_get_index(op2));
+       assert(op2_idx >= 0);
 
        DB((dbg, LEVEL_1, ">>> %s %s ->\n", get_irn_opname(n), arch_register_get_name(op2)));
 
@@ -1091,15 +1097,15 @@ static void sim_fCondJmp(x87_state *state, ir_node *n, const arch_env_t *env) {
        unsigned live = vfp_liveness_nodes_live_at(env, n);
 
        DB((dbg, LEVEL_1, ">>> %s %s, %s\n", get_irn_opname(n),
-               arch_register_get_name(op2), arch_register_get_name(op1)));
-  DEBUG_ONLY(vfp_dump_live(live));
+               arch_register_get_name(op1), arch_register_get_name(op2)));
+       DEBUG_ONLY(vfp_dump_live(live));
 
+       op1_idx = x87_on_stack(state, arch_register_get_index(op1));
        op2_idx = x87_on_stack(state, arch_register_get_index(op2));
 
        /* BEWARE: check for comp a,a cases, they might happen */
-       if (op1->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]) {
-               /* first operand is a vfp register */
-               op1_idx = x87_on_stack(state, arch_register_get_index(op1));
+       if (op2->index != REG_VFP_NOREG) {
+               /* second operand is a vfp register */
 
                if (is_vfp_live(op2->index, live)) {
                        /* second operand is live */
@@ -1217,23 +1223,23 @@ static void sim_fCondJmp(x87_state *state, ir_node *n, const arch_env_t *env) {
                }
        }
        else {
-               /* first operand is an address mode */
-               if (is_vfp_live(op2->index, live)) {
-                       /* second operand is live: bring it to TOS */
-                       if (op2_idx != 0) {
-                               x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
-                               op2_idx = 0;
+               /* second operand is an address mode */
+               if (is_vfp_live(op1->index, live)) {
+                       /* first operand is live: bring it to TOS */
+                       if (op1_idx != 0) {
+                               x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
+                               op1_idx = 0;
                        }
-                       dst = op_ia32_fcomrJmp;
+                       dst = op_ia32_fcomJmp;
                }
                else {
-                       /* second operand is dead: bring it to tos */
-                       if (op2_idx != 0) {
-                               x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
-                               op2_idx = 0;
+                       /* first operand is dead: bring it to tos */
+                       if (op1_idx != 0) {
+                               x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
+                               op1_idx = 0;
                        }
                }
-               dst     = op_ia32_fcomrpJmp;
+               dst     = op_ia32_fcompJmp;
                pop_cnt = 1;
        }
 
@@ -1245,12 +1251,16 @@ static void sim_fCondJmp(x87_state *state, ir_node *n, const arch_env_t *env) {
 
        /* patch the operation */
        attr = get_ia32_attr(n);
-       if (op1_idx >= 0)
-               attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
-       attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
+       attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
+       if (op2_idx >= 0)
+               attr->x87[1] = op2 = &ia32_st_regs[op2_idx];
 
-       DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(n),
-               arch_register_get_name(op2), arch_register_get_name(op1)));
+       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
+               DB((dbg, LEVEL_1, "<<< %s %s, [AM]\n", get_irn_opname(n),
+                       arch_register_get_name(op1)));
 }
 
 /**
@@ -1275,7 +1285,7 @@ static void sim_Copy(x87_state *state, ir_node *n, const arch_env_t *env) {
 
                DB((dbg, LEVEL_1, ">>> %s %s -> %s\n", get_irn_opname(n),
                        arch_register_get_name(op1), arch_register_get_name(out)));
-         DEBUG_ONLY(vfp_dump_live(live));
+               DEBUG_ONLY(vfp_dump_live(live));
 
                if (is_vfp_live(op1->index, live)) {
                        /* operand is still live,a real copy */
@@ -1402,8 +1412,21 @@ static void sim_Reload(x87_state *state, ir_node *n, const arch_env_t *env) {
  * @param env    the architecture environment
  */
 static void sim_Return(x87_state *state, ir_node *n, const arch_env_t *env) {
-       assert(x87_get_depth(state) == 1);
-       x87_pop(state);
+       int n_res = be_Return_get_n_rets(n);
+       int i, n_float_res = 0;
+
+       /* only floating point return values must resist on stack */
+       for (i = 0; i < n_res; ++i) {
+               ir_node *res = get_irn_n(n, be_pos_Return_val + i);
+
+               if (mode_is_float(get_irn_mode(res)))
+                       ++n_float_res;
+       }
+       assert(x87_get_depth(state) == n_float_res);
+
+       /* pop them virtually */
+       for (i = n_float_res - 1; i >= 0; --i)
+               x87_pop(state);
 }
 
 /**
@@ -1567,7 +1590,6 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg, const arch_env
        sim->env        = env;
 
        FIRM_DBG_REGISTER(dbg, "firm.be.ia32.x87");
-       firm_dbg_set_mask(dbg, SET_LEVEL_2);
 
        DB((dbg, LEVEL_1, "--------------------------------\n"
                "x87 Simulator started for %+F\n", irg));