allow backend to specify endianess, rewrite bitfield emitter to handle little and...
[libfirm] / ir / be / ia32 / ia32_finish.c
index 768bb3b..2be7d29 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "../bearch.h"
 #include "../besched.h"
-#include "../benode_t.h"
+#include "../benode.h"
 
 #include "bearch_ia32_t.h"
 #include "ia32_finish.h"
@@ -51,7 +51,7 @@
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
 /**
- * Transforms a Sub or xSub into Neg--Add iff OUT_REG == SRC2_REG.
+ * Transforms a Sub or xSub into Neg--Add iff OUT_REG != SRC1_REG && OUT_REG == SRC2_REG.
  * THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
  */
 static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg)
@@ -75,14 +75,16 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg)
        in2_reg  = arch_get_irn_register(in2);
        out_reg  = arch_irn_get_register(irn, 0);
 
-       irg     = cg->irg;
-       block   = get_nodes_block(irn);
+       if (out_reg == in1_reg)
+               return;
 
        /* in case of sub and OUT == SRC2 we can transform the sequence into neg src2 -- add */
        if (out_reg != in2_reg)
                return;
 
-       dbg = get_irn_dbg_info(irn);
+       irg   = cg->irg;
+       block = get_nodes_block(irn);
+       dbg   = get_irn_dbg_info(irn);
 
        /* generate the neg src2 */
        if (is_ia32_xSub(irn)) {
@@ -177,7 +179,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg)
                        sched_add_before(irn, adc);
 
                        set_irn_mode(adc, mode_T);
-                       adc_flags = new_r_Proj(block, adc, mode_Iu, pn_ia32_Adc_flags);
+                       adc_flags = new_r_Proj(adc, mode_Iu, pn_ia32_Adc_flags);
                        arch_set_irn_register(adc_flags, &ia32_flags_regs[REG_EFLAGS]);
 
                        cmc = new_bd_ia32_Cmc(dbg, block, adc_flags);
@@ -218,7 +220,7 @@ static inline int need_constraint_copy(ir_node *irn)
                case iro_ia32_Lea:
                case iro_ia32_Conv_I2I:
                case iro_ia32_Conv_I2I8Bit:
-               case iro_ia32_CMov:
+               case iro_ia32_CMovcc:
                        return 0;
 
                default:
@@ -238,8 +240,7 @@ static int get_first_same(const arch_register_req_t* req)
        for (i = 0; i < 32; ++i) {
                if (other & (1U << i)) return i;
        }
-       assert(! "same position not found");
-       return 32;
+       panic("same position not found");
 }
 
 /**
@@ -249,12 +250,10 @@ static int get_first_same(const arch_register_req_t* req)
  */
 static void assure_should_be_same_requirements(ir_node *node)
 {
-       const arch_register_req_t **reqs;
        const arch_register_t      *out_reg, *in_reg;
        int                         n_res, i;
        ir_node                    *in_node, *block;
 
-       reqs  = get_ia32_out_req_all(node);
        n_res = arch_irn_get_n_outs(node);
        block = get_nodes_block(node);
 
@@ -267,7 +266,7 @@ static void assure_should_be_same_requirements(ir_node *node)
                ir_node                     *perm_proj0;
                ir_node                     *perm_proj1;
                ir_node                     *uses_out_reg;
-               const arch_register_req_t   *req = reqs[i];
+               const arch_register_req_t   *req = arch_get_out_register_req(node, i);
                const arch_register_class_t *cls;
                int                         uses_out_reg_pos;
 
@@ -277,16 +276,13 @@ static void assure_should_be_same_requirements(ir_node *node)
                same_pos = get_first_same(req);
 
                /* get in and out register */
-               out_reg  = arch_irn_get_register(node, i);
-               in_node  = get_irn_n(node, same_pos);
-               in_reg   = arch_get_irn_register(in_node);
+               out_reg = arch_irn_get_register(node, i);
+               in_node = get_irn_n(node, same_pos);
+               in_reg  = arch_get_irn_register(in_node);
 
                /* requirement already fulfilled? */
                if (in_reg == out_reg)
                        continue;
-               /* unknowns can be changed to any register we want on emitting */
-               if (is_unknown_reg(in_reg))
-                       continue;
                cls = arch_register_get_class(in_reg);
                assert(cls == arch_register_get_class(out_reg));
 
@@ -357,8 +353,8 @@ static void assure_should_be_same_requirements(ir_node *node)
                in[1] = uses_out_reg;
                perm  = be_new_Perm(cls, block, 2, in);
 
-               perm_proj0 = new_r_Proj(block, perm, get_irn_mode(in[0]), 0);
-               perm_proj1 = new_r_Proj(block, perm, get_irn_mode(in[1]), 1);
+               perm_proj0 = new_r_Proj(perm, get_irn_mode(in[0]), 0);
+               perm_proj1 = new_r_Proj(perm, get_irn_mode(in[1]), 1);
 
                arch_set_irn_register(perm_proj0, out_reg);
                arch_set_irn_register(perm_proj1, in_reg);
@@ -392,7 +388,6 @@ static void assure_should_be_same_requirements(ir_node *node)
  */
 static void fix_am_source(ir_node *irn)
 {
-       const arch_register_req_t **reqs;
        int                         n_res, i;
 
        /* check only ia32 nodes with source address mode */
@@ -402,22 +397,22 @@ static void fix_am_source(ir_node *irn)
        if (get_ia32_am_support(irn) != ia32_am_binary)
                return;
 
-       reqs  = get_ia32_out_req_all(irn);
        n_res = arch_irn_get_n_outs(irn);
 
        for (i = 0; i < n_res; i++) {
-               const arch_register_t *out_reg;
-               int                    same_pos;
-               ir_node               *same_node;
-               const arch_register_t *same_reg;
-               ir_node               *load_res;
+               const arch_register_req_t *req = arch_get_out_register_req(irn, i);
+               const arch_register_t     *out_reg;
+               int                        same_pos;
+               ir_node                   *same_node;
+               const arch_register_t     *same_reg;
+               ir_node                   *load_res;
 
-               if (!arch_register_req_is(reqs[i], should_be_same))
+               if (!arch_register_req_is(req, should_be_same))
                        continue;
 
                /* get in and out register */
                out_reg   = arch_irn_get_register(irn, i);
-               same_pos  = get_first_same(reqs[i]);
+               same_pos  = get_first_same(req);
                same_node = get_irn_n(irn, same_pos);
                same_reg  = arch_get_irn_register(same_node);