Replace the parameter int commutative of gen_binop(), gen_binop_sse_float() and gen_b...
[libfirm] / ir / be / ia32 / ia32_transform.c
index 88d8ac1..e41108b 100644 (file)
@@ -583,8 +583,10 @@ typedef enum {
        match_commutative       = 1 << 0,
        match_am_and_immediates = 1 << 1,
        match_no_am             = 1 << 2,
-       match_8_16_bit_am       = 1 << 3,
-       match_no_immediate      = 1 << 4
+       match_8_bit_am          = 1 << 3,
+       match_16_bit_am         = 1 << 4,
+       match_no_immediate      = 1 << 5,
+       match_force_32bit_op    = 1 << 6
 } match_flags_t;
 
 static void match_arguments(ia32_address_mode_t *am, ir_node *block,
@@ -599,6 +601,7 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
        int             commutative;
        int             use_am_and_immediates;
        int             use_immediate;
+       int             mode_bits = get_mode_size_bits(mode);
 
        memset(am, 0, sizeof(am[0]));
 
@@ -610,9 +613,11 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
        assert(op2 != NULL);
        assert(!commutative || op1 != NULL);
 
-       if(!(flags & match_8_16_bit_am)
-                       && get_mode_size_bits(mode) < 32)
+       if(mode_bits == 8 && !(flags & match_8_bit_am)) {
                use_am = 0;
+       } else if(mode_bits == 16 && !(flags & match_16_bit_am)) {
+               use_am = 0;
+       }
 
        new_op2 = (use_immediate ? try_create_Immediate(op2, 0) : NULL);
        if(new_op2 == NULL && use_am && use_source_address_mode(block, op2, op1)) {
@@ -648,6 +653,11 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
                if(new_op2 == NULL)
                        new_op2 = be_transform_node(op2);
                am->op_type = ia32_Normal;
+               if(flags & match_force_32bit_op) {
+                       am->ls_mode = mode_Iu;
+               } else {
+                       am->ls_mode = get_irn_mode(op2);
+               }
        }
        if(addr->base == NULL)
                addr->base = noreg_gp;
@@ -694,23 +704,21 @@ static ir_node *fix_mem_proj(ir_node *node, ia32_address_mode_t *am)
  * @return The constructed ia32 node.
  */
 static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
-                          construct_binop_func *func, int commutative)
+                          construct_binop_func *func, match_flags_t flags)
 {
-       ir_node  *src_block = get_nodes_block(node);
-       ir_node  *block     = be_transform_node(src_block);
+       ir_node  *block     = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(block);
        ir_graph *irg       = current_ir_graph;
        dbg_info *dbgi      = get_irn_dbg_info(node);
        ir_node  *new_node;
        ia32_address_mode_t  am;
        ia32_address_t      *addr = &am.addr;
-       match_flags_t        flags = 0;
 
-       if(commutative)
-               flags |= match_commutative;
+       flags |= match_force_32bit_op;
 
-       match_arguments(&am, src_block, op1, op2, flags);
+       match_arguments(&am, block, op1, op2, flags);
 
-       new_node = func(dbgi, irg, block, addr->base, addr->index, addr->mem,
+       new_node = func(dbgi, irg, new_block, addr->base, addr->index, addr->mem,
                        am.new_op1, am.new_op2);
        set_am_attributes(new_node, &am);
        /* we can't use source address mode anymore when using immediates */
@@ -733,27 +741,26 @@ static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
  */
 static ir_node *gen_binop_sse_float(ir_node *node, ir_node *op1, ir_node *op2,
                                     construct_binop_func *func,
-                                    int commutative)
+                                    match_flags_t flags)
 {
-       ir_node  *block    = be_transform_node(get_nodes_block(node));
-       ir_node  *new_op1  = be_transform_node(op1);
-       ir_node  *new_op2  = be_transform_node(op2);
-       ir_node  *new_node = NULL;
-       dbg_info *dbgi     = get_irn_dbg_info(node);
-       ir_graph *irg      = current_ir_graph;
-       ir_mode  *mode     = get_irn_mode(node);
-       ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
-       ir_node  *nomem    = new_NoMem();
+       ir_node  *block     = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(block);
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_graph *irg       = current_ir_graph;
+       ir_node  *new_node;
+       ia32_address_mode_t  am;
+       ia32_address_t      *addr = &am.addr;
 
-       new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, nomem, new_op1,
-                       new_op2);
-       if (commutative) {
-               set_ia32_commutative(new_node);
-       }
-       set_ia32_ls_mode(new_node, mode);
+       match_arguments(&am, block, op1, op2, flags);
+
+       new_node = func(dbgi, irg, new_block, addr->base, addr->index, addr->mem,
+                       am.new_op1, am.new_op2);
+       set_am_attributes(new_node, &am);
 
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
+       new_node = fix_mem_proj(new_node, &am);
+
        return new_node;
 }
 
@@ -780,21 +787,17 @@ static ir_node *get_fpcw(void)
  */
 static ir_node *gen_binop_x87_float(ir_node *node, ir_node *op1, ir_node *op2,
                                     construct_binop_float_func *func,
-                                    int commutative)
+                                    match_flags_t flags)
 {
        ir_graph *irg       = current_ir_graph;
        dbg_info *dbgi      = get_irn_dbg_info(node);
-       ir_node  *src_block = get_nodes_block(node);
-       ir_node  *new_block = be_transform_node(src_block);
+       ir_node  *block     = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(block);
        ir_node  *new_node;
        ia32_address_mode_t  am;
        ia32_address_t      *addr = &am.addr;
-       match_flags_t        flags = 0;
-
-       if(commutative)
-               flags |= match_commutative;
 
-       match_arguments(&am, src_block, op1, op2, flags);
+       match_arguments(&am, block, op1, op2, flags);
 
        new_node = func(dbgi, irg, new_block, addr->base, addr->index, addr->mem,
                        am.new_op1, am.new_op2, get_fpcw());
@@ -903,25 +906,25 @@ static int am_has_immediates(const ia32_address_t *addr)
  * @return the created ia32 Add node
  */
 static ir_node *gen_Add(ir_node *node) {
-       ir_node  *block   = be_transform_node(get_nodes_block(node));
-       ir_node  *op1     = get_Add_left(node);
-       ir_node  *op2     = get_Add_right(node);
-       ir_node  *new_op;
+       ir_graph *irg       = current_ir_graph;
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *block     = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(block);
+       ir_node  *op1       = get_Add_left(node);
+       ir_node  *op2       = get_Add_right(node);
+       ir_mode  *mode      = get_irn_mode(node);
+       ir_node  *noreg     = ia32_new_NoReg_gp(env_cg);
+       ir_node  *new_node;
        ir_node  *new_op1;
-       ir_graph *irg     = current_ir_graph;
-       dbg_info *dbgi    = get_irn_dbg_info(node);
-       ir_mode  *mode    = get_irn_mode(node);
-       ir_node  *noreg   = ia32_new_NoReg_gp(env_cg);
-       ir_node  *src_block = get_nodes_block(node);
        ir_node  *add_immediate_op;
        ia32_address_t       addr;
        ia32_address_mode_t  am;
 
        if (mode_is_float(mode)) {
                if (USE_SSE2(env_cg))
-                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xAdd, 1);
+                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xAdd, match_commutative);
                else
-                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd, 1);
+                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd, match_commutative);
        }
 
        /**
@@ -936,11 +939,11 @@ static ir_node *gen_Add(ir_node *node) {
        add_immediate_op = NULL;
        /* a constant? */
        if(addr.base == NULL && addr.index == NULL) {
-               new_op = new_rd_ia32_Const(dbgi, irg, block, addr.symconst_ent,
-                                                                  addr.symconst_sign, addr.offset);
-               add_irn_dep(new_op, get_irg_frame(irg));
-               SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
-               return new_op;
+               new_node = new_rd_ia32_Const(dbgi, irg, new_block, addr.symconst_ent,
+                                            addr.symconst_sign, addr.offset);
+               add_irn_dep(new_node, get_irg_frame(irg));
+               SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+               return new_node;
        }
        /* add with immediate? */
        if(addr.index == NULL) {
@@ -958,41 +961,41 @@ static ir_node *gen_Add(ir_node *node) {
                        return be_transform_node(add_immediate_op);
                }
 
-               new_op = create_lea_from_address(dbgi, block, &addr);
-               SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
-               return new_op;
+               new_node = create_lea_from_address(dbgi, new_block, &addr);
+               SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+               return new_node;
        }
 
        /* test if we can use source address mode */
        memset(&am, 0, sizeof(am));
        new_op1 = NULL;
-       if(use_source_address_mode(src_block, op2, op1)) {
+       if(use_source_address_mode(block, op2, op1)) {
                build_address(&am, op2);
                new_op1 = be_transform_node(op1);
-       } else if(use_source_address_mode(src_block, op1, op2)) {
+       } else if(use_source_address_mode(block, op1, op2)) {
                build_address(&am, op1);
                new_op1 = be_transform_node(op2);
        }
        /* construct an Add with source address mode */
        if(new_op1 != NULL) {
                ia32_address_t *am_addr = &am.addr;
-               new_op = new_rd_ia32_Add(dbgi, irg, block, am_addr->base, am_addr->index,
-                                        am_addr->mem, new_op1, noreg);
-               set_address(new_op, am_addr);
-               set_ia32_op_type(new_op, ia32_AddrModeS);
-               set_ia32_ls_mode(new_op, am.ls_mode);
-               set_ia32_commutative(new_op);
-               SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
+               new_node = new_rd_ia32_Add(dbgi, irg, new_block, am_addr->base,
+                                        am_addr->index, am_addr->mem, new_op1, noreg);
+               set_address(new_node, am_addr);
+               set_ia32_op_type(new_node, ia32_AddrModeS);
+               set_ia32_ls_mode(new_node, am.ls_mode);
+               set_ia32_commutative(new_node);
+               SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
-               new_op = fix_mem_proj(new_op, &am);
+               new_node = fix_mem_proj(new_node, &am);
 
-               return new_op;
+               return new_node;
        }
 
        /* otherwise construct a lea */
-       new_op = create_lea_from_address(dbgi, block, &addr);
-       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
-       return new_op;
+       new_node = create_lea_from_address(dbgi, new_block, &addr);
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+       return new_node;
 }
 
 /**
@@ -1007,9 +1010,9 @@ static ir_node *gen_Mul(ir_node *node) {
 
        if (mode_is_float(mode)) {
                if (USE_SSE2(env_cg))
-                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xMul, 1);
+                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xMul, match_commutative);
                else
-                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul, 1);
+                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul, match_commutative);
        }
 
        /*
@@ -1017,7 +1020,7 @@ static ir_node *gen_Mul(ir_node *node) {
                signed or unsigned multiplication so we use IMul as it has fewer
                constraints
        */
-       return gen_binop(node, op1, op2, new_rd_ia32_IMul, 1);
+       return gen_binop(node, op1, op2, new_rd_ia32_IMul, match_commutative);
 }
 
 /**
@@ -1050,7 +1053,7 @@ static ir_node *gen_Mulh(ir_node *node) {
 
        set_ia32_commutative(res);
 
-       proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EDX);
+       proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_ia32_IMul1OP_EDX);
 
        return proj_EDX;
 }
@@ -1090,7 +1093,7 @@ static ir_node *gen_And(ir_node *node) {
                }
        }
 
-       return gen_binop(node, op1, op2, new_rd_ia32_And, 1);
+       return gen_binop(node, op1, op2, new_rd_ia32_And, match_commutative);
 }
 
 
@@ -1105,7 +1108,7 @@ static ir_node *gen_Or(ir_node *node) {
        ir_node *op2 = get_Or_right(node);
 
        assert (! mode_is_float(get_irn_mode(node)));
-       return gen_binop(node, op1, op2, new_rd_ia32_Or, 1);
+       return gen_binop(node, op1, op2, new_rd_ia32_Or, match_commutative);
 }
 
 
@@ -1120,7 +1123,7 @@ static ir_node *gen_Eor(ir_node *node) {
        ir_node *op2 = get_Eor_right(node);
 
        assert(! mode_is_float(get_irn_mode(node)));
-       return gen_binop(node, op1, op2, new_rd_ia32_Xor, 1);
+       return gen_binop(node, op1, op2, new_rd_ia32_Xor, match_commutative);
 }
 
 
@@ -1149,7 +1152,7 @@ static ir_node *gen_Sub(ir_node *node) {
        return gen_binop(node, op1, op2, new_rd_ia32_Sub, 0);
 }
 
-
+typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod } ia32_op_flavour_t;
 
 /**
  * Generates an ia32 DivMod with additional infrastructure for the
@@ -1216,10 +1219,10 @@ static ir_node *generate_DivMod(ir_node *node, ir_node *dividend,
 
        if (mode_is_signed(mode)) {
                res = new_rd_ia32_IDiv(dbgi, irg, block, noreg, noreg, new_mem,
-                                      new_dividend, sign_extension, new_divisor, dm_flav);
+                                      new_dividend, sign_extension, new_divisor);
        } else {
-               res = new_rd_ia32_Div(dbgi, irg, block, noreg, noreg, new_mem, new_dividend,
-                                     sign_extension, new_divisor, dm_flav);
+               res = new_rd_ia32_Div(dbgi, irg, block, noreg, noreg, new_mem,
+                                     new_dividend, sign_extension, new_divisor);
        }
 
        set_ia32_exc_label(res, has_exc);
@@ -1474,12 +1477,12 @@ static ir_node *gen_Minus(ir_node *node)
        if (mode_is_float(mode)) {
                ir_node *new_op = be_transform_node(op);
                if (USE_SSE2(env_cg)) {
-                       ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
-                       ir_node *noreg_fp = ia32_new_NoReg_fp(env_cg);
-                       ir_node *nomem    = new_rd_NoMem(irg);
+                       ir_node *noreg_gp  = ia32_new_NoReg_gp(env_cg);
+                       ir_node *noreg_xmm = ia32_new_NoReg_xmm(env_cg);
+                       ir_node *nomem     = new_rd_NoMem(irg);
 
                        res = new_rd_ia32_xXor(dbgi, irg, block, noreg_gp, noreg_gp, nomem,
-                                              new_op, noreg_fp);
+                                              new_op, noreg_xmm);
 
                        size = get_mode_size_bits(mode);
                        ent  = ia32_gen_fp_known_const(size == 32 ? ia32_SSIGN : ia32_DSIGN);
@@ -2172,7 +2175,7 @@ static ir_node *try_create_Test(ir_node *node)
        assert(get_mode_size_bits(mode) <= 32);
 
        match_arguments(&am, block, left, right, match_commutative |
-                       match_8_16_bit_am | match_am_and_immediates);
+                       match_8_bit_am | match_16_bit_am | match_am_and_immediates);
 
        cmp_unsigned = !mode_is_signed(mode);
        if(get_mode_size_bits(mode) == 8) {
@@ -2206,7 +2209,7 @@ static ir_node *create_Fucom(ir_node *node)
        ir_node  *new_right;
        ir_node  *res;
 
-       if(1 || transform_config.use_fucomi) {
+       if(transform_config.use_fucomi) {
                new_right = be_transform_node(right);
                res = new_rd_ia32_vFucomi(dbgi, irg, new_block, new_left, new_right, 0);
                set_ia32_commutative(res);
@@ -2235,25 +2238,25 @@ static ir_node *create_Ucomi(ir_node *node)
 {
        ir_graph *irg       = current_ir_graph;
        dbg_info *dbgi      = get_irn_dbg_info(node);
-       ir_node  *block     = get_nodes_block(node);
-       ir_node  *new_block = be_transform_node(block);
+       ir_node  *src_block = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(src_block);
        ir_node  *left      = get_Cmp_left(node);
-       ir_node  *new_left  = be_transform_node(left);
        ir_node  *right     = get_Cmp_right(node);
-       ir_node  *new_right = be_transform_node(right);
-       ir_mode  *mode      = get_irn_mode(left);
-       ir_node  *noreg     = ia32_new_NoReg_gp(env_cg);
-       ir_node  *nomem     = new_NoMem();
-       ir_node  *res;
+       ir_node  *new_node;
+       ia32_address_mode_t  am;
+       ia32_address_t      *addr = &am.addr;
 
-       res = new_rd_ia32_Ucomi(dbgi, irg, new_block, noreg, noreg, nomem, new_left,
-                               new_right, 0);
-       set_ia32_commutative(res);
-       set_ia32_ls_mode(res, mode);
+       match_arguments(&am, src_block, left, right, match_commutative);
 
-       SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
+       new_node = new_rd_ia32_Ucomi(dbgi, irg, new_block, addr->base, addr->index,
+                                    addr->mem, am.new_op1, am.new_op2, am.flipped);
+       set_am_attributes(new_node, &am);
 
-       return res;
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+
+       new_node = fix_mem_proj(new_node, &am);
+
+       return new_node;
 }
 
 static ir_node *gen_Cmp(ir_node *node)
@@ -2290,7 +2293,7 @@ static ir_node *gen_Cmp(ir_node *node)
        }
 
        match_arguments(&am, block, left, right,
-                       match_commutative | match_8_16_bit_am |
+                       match_commutative | match_8_bit_am | match_16_bit_am |
                        match_am_and_immediates);
 
        cmp_unsigned = !mode_is_signed(get_irn_mode(left));
@@ -2316,26 +2319,37 @@ static ir_node *gen_Cmp(ir_node *node)
 
 static ir_node *create_CMov(ir_node *node, ir_node *new_flags, pn_Cmp pnc)
 {
-       ir_graph *irg           = current_ir_graph;
-       dbg_info *dbgi          = get_irn_dbg_info(node);
-       ir_node  *block         = get_nodes_block(node);
-       ir_node  *new_block     = be_transform_node(block);
-       ir_node  *val_true      = get_Psi_val(node, 0);
-       ir_node  *new_val_true  = be_transform_node(val_true);
-       ir_node  *val_false     = get_Psi_default(node);
-       ir_node  *new_val_false = be_transform_node(val_false);
-       ir_mode  *mode          = get_irn_mode(node);
-       ir_node  *noreg         = ia32_new_NoReg_gp(env_cg);
-       ir_node  *nomem         = new_NoMem();
-       ir_node  *res;
+       ir_graph            *irg           = current_ir_graph;
+       dbg_info            *dbgi          = get_irn_dbg_info(node);
+       ir_node             *block         = get_nodes_block(node);
+       ir_node             *new_block     = be_transform_node(block);
+       ir_node             *val_true      = get_Psi_val(node, 0);
+       ir_node             *val_false     = get_Psi_default(node);
+       ir_node             *new_node;
+       match_flags_t        match_flags;
 
-       assert(mode_needs_gp_reg(mode));
+       assert(transform_config.use_cmov);
 
-       res = new_rd_ia32_CMov(dbgi, irg, new_block, noreg, noreg, nomem,
-                              new_val_false, new_val_true, new_flags, pnc);
-       SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
+       assert(mode_needs_gp_reg(get_irn_mode(val_true)));
 
-       return res;
+       ia32_address_mode_t  am;
+       ia32_address_t      *addr = &am.addr;
+
+       match_flags = match_commutative | match_no_immediate | match_16_bit_am
+               | match_force_32bit_op;
+
+       match_arguments(&am, block, val_false, val_true, match_flags);
+
+       new_node = new_rd_ia32_CMov(dbgi, irg, new_block, addr->base, addr->index,
+                                   addr->mem, am.new_op1, am.new_op2, new_flags,
+                                   am.flipped, pnc);
+       set_am_attributes(new_node, &am);
+
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+
+       new_node = fix_mem_proj(new_node, &am);
+
+       return new_node;
 }
 
 
@@ -3402,53 +3416,65 @@ static ir_node *gen_be_Return(ir_node *node) {
 }
 
 /**
- * Transform a be_AddSP into an ia32_AddSP. Eat up const sizes.
+ * Transform a be_AddSP into an ia32_SubSP.
  */
-static ir_node *gen_be_AddSP(ir_node *node) {
-       ir_node  *block  = be_transform_node(get_nodes_block(node));
-       ir_node  *sz     = get_irn_n(node, be_pos_AddSP_size);
-       ir_node  *new_sz;
-       ir_node  *sp     = get_irn_n(node, be_pos_AddSP_old_sp);
-       ir_node  *new_sp = be_transform_node(sp);
-       ir_graph *irg    = current_ir_graph;
-       dbg_info *dbgi   = get_irn_dbg_info(node);
-       ir_node  *noreg  = ia32_new_NoReg_gp(env_cg);
-       ir_node  *nomem  = new_NoMem();
-       ir_node  *new_op;
+static ir_node *gen_be_AddSP(ir_node *node)
+{
+       ir_node  *src_block = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(src_block);
+       ir_node  *sz        = get_irn_n(node, be_pos_AddSP_size);
+       ir_node  *sp        = get_irn_n(node, be_pos_AddSP_old_sp);
+       ir_graph *irg       = current_ir_graph;
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *new_node;
+       ia32_address_mode_t  am;
+       ia32_address_t      *addr = &am.addr;
+       match_flags_t        flags = 0;
 
-       new_sz = create_immediate_or_transform(sz, 0);
+       match_arguments(&am, src_block, sp, sz, flags);
 
-       /* ia32 stack grows in reverse direction, make a SubSP */
-       new_op = new_rd_ia32_SubSP(dbgi, irg, block, noreg, noreg, nomem, new_sp,
-                                  new_sz);
-       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
+       new_node = new_rd_ia32_SubSP(dbgi, irg, new_block, addr->base, addr->index,
+                                    addr->mem, am.new_op1, am.new_op2);
+       set_am_attributes(new_node, &am);
+       /* we can't use source address mode anymore when using immediates */
+       if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
+               set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
-       return new_op;
+       new_node = fix_mem_proj(new_node, &am);
+
+       return new_node;
 }
 
 /**
- * Transform a be_SubSP into an ia32_SubSP. Eat up const sizes.
+ * Transform a be_SubSP into an ia32_AddSP
  */
-static ir_node *gen_be_SubSP(ir_node *node) {
-       ir_node  *block  = be_transform_node(get_nodes_block(node));
-       ir_node  *sz     = get_irn_n(node, be_pos_SubSP_size);
-       ir_node  *new_sz;
-       ir_node  *sp     = get_irn_n(node, be_pos_SubSP_old_sp);
-       ir_node  *new_sp = be_transform_node(sp);
-       ir_graph *irg    = current_ir_graph;
-       dbg_info *dbgi   = get_irn_dbg_info(node);
-       ir_node  *noreg  = ia32_new_NoReg_gp(env_cg);
-       ir_node  *nomem  = new_NoMem();
-       ir_node  *new_op;
+static ir_node *gen_be_SubSP(ir_node *node)
+{
+       ir_node  *src_block = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(src_block);
+       ir_node  *sz        = get_irn_n(node, be_pos_SubSP_size);
+       ir_node  *sp        = get_irn_n(node, be_pos_SubSP_old_sp);
+       ir_graph *irg       = current_ir_graph;
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *new_node;
+       ia32_address_mode_t  am;
+       ia32_address_t      *addr = &am.addr;
+       match_flags_t        flags = 0;
 
-       new_sz = create_immediate_or_transform(sz, 0);
+       match_arguments(&am, src_block, sp, sz, flags);
 
-       /* ia32 stack grows in reverse direction, make an AddSP */
-       new_op = new_rd_ia32_AddSP(dbgi, irg, block, noreg, noreg, nomem, new_sp,
-                                  new_sz);
-       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
+       new_node = new_rd_ia32_AddSP(dbgi, irg, new_block, addr->base, addr->index,
+                                    addr->mem, am.new_op1, am.new_op2);
+       set_am_attributes(new_node, &am);
+       /* we can't use source address mode anymore when using immediates */
+       if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
+               set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
-       return new_op;
+       new_node = fix_mem_proj(new_node, &am);
+
+       return new_node;
 }
 
 /**
@@ -3617,38 +3643,20 @@ static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func)
  * @param node   The node to transform
  * @return the created ia32 XXX node
  */
-#define GEN_LOWERED_OP(op)                                                \
-       static ir_node *gen_ia32_l_##op(ir_node *node) {                      \
-               return gen_binop(node, get_binop_left(node),                      \
-                                get_binop_right(node), new_rd_ia32_##op,0);      \
-       }
-
-#define GEN_LOWERED_x87_OP(op)                                                 \
-       static ir_node *gen_ia32_l_##op(ir_node *node) {                           \
-               ir_node *new_op;                                                       \
-               new_op = gen_binop_x87_float(node, get_binop_left(node),               \
-                                            get_binop_right(node), new_rd_ia32_##op, 0); \
-               return new_op;                                                         \
-       }
-
 #define GEN_LOWERED_SHIFT_OP(l_op, op)                                         \
        static ir_node *gen_ia32_##l_op(ir_node *node) {                           \
                return gen_shift_binop(node, get_irn_n(node, 0),                       \
                                       get_irn_n(node, 1), new_rd_ia32_##op);          \
        }
 
-GEN_LOWERED_x87_OP(vfprem)
-GEN_LOWERED_x87_OP(vfmul)
-GEN_LOWERED_x87_OP(vfsub)
 GEN_LOWERED_SHIFT_OP(l_ShlDep, Shl)
 GEN_LOWERED_SHIFT_OP(l_ShrDep, Shr)
-GEN_LOWERED_SHIFT_OP(l_Sar,    Sar)
 GEN_LOWERED_SHIFT_OP(l_SarDep, Sar)
 
 static ir_node *gen_ia32_l_Add(ir_node *node) {
        ir_node *left    = get_irn_n(node, n_ia32_l_Add_left);
        ir_node *right   = get_irn_n(node, n_ia32_l_Add_right);
-       ir_node *lowered = gen_binop(node, left, right, new_rd_ia32_Add, 1);
+       ir_node *lowered = gen_binop(node, left, right, new_rd_ia32_Add, match_commutative);
 
        if(is_Proj(lowered)) {
                lowered = get_Proj_pred(lowered);
@@ -3766,37 +3774,9 @@ static ir_node *gen_ia32_l_vfist(ir_node *node) {
        return new_op;
 }
 
-/**
- * Transforms a l_vfdiv into a "real" vfdiv node.
- *
- * @param env   The transformation environment
- * @return the created ia32 vfdiv node
- */
-static ir_node *gen_ia32_l_vfdiv(ir_node *node) {
-       ir_node  *block     = be_transform_node(get_nodes_block(node));
-       ir_node  *left      = get_binop_left(node);
-       ir_node  *new_left  = be_transform_node(left);
-       ir_node  *right     = get_binop_right(node);
-       ir_node  *new_right = be_transform_node(right);
-       ir_node  *noreg     = ia32_new_NoReg_gp(env_cg);
-       ir_graph *irg       = current_ir_graph;
-       dbg_info *dbgi      = get_irn_dbg_info(node);
-       ir_node  *fpcw      = get_fpcw();
-       ir_node  *vfdiv;
-
-       vfdiv = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_NoMem(),
-                                 new_left, new_right, fpcw);
-       clear_ia32_commutative(vfdiv);
-
-       SET_IA32_ORIG_NODE(vfdiv, ia32_get_old_node_name(env_cg, node));
-
-       return vfdiv;
-}
-
 /**
  * Transforms a l_MulS into a "real" MulS node.
  *
- * @param env   The transformation environment
  * @return the created ia32 Mul node
  */
 static ir_node *gen_ia32_l_Mul(ir_node *node) {
@@ -3823,7 +3803,6 @@ static ir_node *gen_ia32_l_Mul(ir_node *node) {
 /**
  * Transforms a l_IMulS into a "real" IMul1OPS node.
  *
- * @param env   The transformation environment
  * @return the created ia32 IMul1OP node
  */
 static ir_node *gen_ia32_l_IMul(ir_node *node) {
@@ -4264,30 +4243,6 @@ static ir_node *gen_Proj_CopyB(ir_node *node) {
        return new_rd_Unknown(irg, mode);
 }
 
-/**
- * Transform and renumber the Projs from a vfdiv.
- */
-static ir_node *gen_Proj_l_vfdiv(ir_node *node) {
-       ir_node  *block    = be_transform_node(get_nodes_block(node));
-       ir_node  *pred     = get_Proj_pred(node);
-       ir_node  *new_pred = be_transform_node(pred);
-       ir_graph *irg      = current_ir_graph;
-       dbg_info *dbgi     = get_irn_dbg_info(node);
-       ir_mode  *mode     = get_irn_mode(node);
-       long     proj      = get_Proj_proj(node);
-
-       switch (proj) {
-       case pn_ia32_l_vfdiv_M:
-               return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_vfdiv_M);
-       case pn_ia32_l_vfdiv_res:
-               return new_rd_Proj(dbgi, irg, block, new_pred, mode_vfp, pn_ia32_vfdiv_res);
-       default:
-               assert(0);
-       }
-
-       return new_rd_Unknown(irg, mode);
-}
-
 /**
  * Transform and renumber the Projs from a Quot.
  */
@@ -4479,8 +4434,6 @@ static ir_node *gen_Proj(ir_node *node) {
                return gen_Proj_CopyB(node);
        } else if (is_Quot(pred)) {
                return gen_Proj_Quot(node);
-       } else if (is_ia32_l_vfdiv(pred)) {
-               return gen_Proj_l_vfdiv(node);
        } else if (be_is_SubSP(pred)) {
                return gen_Proj_be_SubSP(node);
        } else if (be_is_AddSP(pred)) {
@@ -4580,16 +4533,11 @@ static void register_transformers(void)
        GEN(ia32_l_IMul);
        GEN(ia32_l_ShlDep);
        GEN(ia32_l_ShrDep);
-       GEN(ia32_l_Sar);
        GEN(ia32_l_SarDep);
        GEN(ia32_l_ShlD);
        GEN(ia32_l_ShrD);
        GEN(ia32_l_Sub);
        GEN(ia32_l_Sbb);
-       GEN(ia32_l_vfdiv);
-       GEN(ia32_l_vfprem);
-       GEN(ia32_l_vfmul);
-       GEN(ia32_l_vfsub);
        GEN(ia32_l_vfild);
        GEN(ia32_l_Load);
        GEN(ia32_l_vfist);
@@ -4730,6 +4678,15 @@ void ia32_add_missing_keeps(ia32_code_gen_t *cg)
 void ia32_transform_graph(ia32_code_gen_t *cg) {
        ir_graph *irg = cg->irg;
 
+       /* TODO: look at cpu and fill transform config in with that... */
+       transform_config.use_incdec = 1;
+       transform_config.use_sse2   = 0;
+       transform_config.use_ffreep = 0;
+       transform_config.use_ftst   = 0;
+       transform_config.use_femms  = 0;
+       transform_config.use_fucomi = 1;
+       transform_config.use_cmov   = 1;
+
        register_transformers();
        env_cg       = cg;
        initial_fpcw = NULL;