build TestJmp for compares with zero
[libfirm] / ir / be / ia32 / ia32_transform.c
index a357551..396efe8 100644 (file)
@@ -86,8 +86,8 @@
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
-/** holdd the current code generator during transformation */
-static ia32_code_gen_t *env_cg;
+/** hold the current code generator during transformation */
+static ia32_code_gen_t *env_cg = NULL;
 
 extern ir_op *get_op_Mulh(void);
 
@@ -95,6 +95,10 @@ typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
         ir_node *block, ir_node *base, ir_node *index, ir_node *op1,
         ir_node *op2, ir_node *mem);
 
+typedef ir_node *construct_binop_float_func(dbg_info *db, ir_graph *irg,
+        ir_node *block, ir_node *base, ir_node *index, ir_node *op1,
+        ir_node *op2, ir_node *mem, ir_node *fpcw);
+
 typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg,
         ir_node *block, ir_node *base, ir_node *index, ir_node *op,
         ir_node *mem);
@@ -112,6 +116,9 @@ typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg,
 static ir_node *try_create_Immediate(ir_node *node,
                                      char immediate_constraint_type);
 
+static ir_node *create_immediate_or_transform(ir_node *node,
+                                              char immediate_constraint_type);
+
 /**
  * Return true if a mode can be stored in the GP register set
  */
@@ -284,22 +291,22 @@ static ir_node *gen_Const(ir_node *node) {
                                floatent = get_entity_for_tv(env_cg, node);
 
                                load     = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode);
-                               set_ia32_am_support(load, ia32_am_Source);
                                set_ia32_op_type(load, ia32_AddrModeS);
                                set_ia32_am_flavour(load, ia32_am_N);
                                set_ia32_am_sc(load, floatent);
-                               res      = new_r_Proj(irg, block, load, mode_vfp, pn_ia32_vfld_res);
+                               set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
+                               res = new_r_Proj(irg, block, load, mode_vfp, pn_ia32_vfld_res);
                        }
                        set_ia32_ls_mode(load, mode);
                } else {
                        floatent = get_entity_for_tv(env_cg, node);
 
                        load     = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem);
-                       set_ia32_am_support(load, ia32_am_Source);
                        set_ia32_op_type(load, ia32_AddrModeS);
                        set_ia32_am_flavour(load, ia32_am_N);
                        set_ia32_am_sc(load, floatent);
                        set_ia32_ls_mode(load, mode);
+                       set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
 
                        res = new_r_Proj(irg, block, load, mode_xmm, pn_ia32_xLoad_res);
                }
@@ -369,49 +376,6 @@ static ir_node *gen_SymConst(ir_node *node) {
        return cnst;
 }
 
-#if 0
-/**
- * SSE convert of an integer node into a floating point node.
- */
-static ir_node *gen_sse_conv_int2float(ia32_code_gen_t *cg, dbg_info *dbgi,
-                                       ir_graph *irg, ir_node *block,
-                                       ir_node *in, ir_node *old_node, ir_mode *tgt_mode)
-{
-       ir_node *noreg    = ia32_new_NoReg_gp(cg);
-       ir_node *nomem    = new_rd_NoMem(irg);
-       ir_node *old_pred = get_Cmp_left(old_node);
-       ir_mode *in_mode  = get_irn_mode(old_pred);
-       int     in_bits   = get_mode_size_bits(in_mode);
-       ir_node *conv     = new_rd_ia32_Conv_I2FP(dbgi, irg, block, noreg, noreg, in, nomem);
-
-       set_ia32_ls_mode(conv, tgt_mode);
-       if (in_bits == 32) {
-               set_ia32_am_support(conv, ia32_am_Source);
-       }
-       SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node));
-
-       return conv;
-}
-
-/**
- * SSE convert of an float node into a double node.
- */
-static ir_node *gen_sse_conv_f2d(ia32_code_gen_t *cg, dbg_info *dbgi,
-                                 ir_graph *irg, ir_node *block,
-                                 ir_node *in, ir_node *old_node)
-{
-       ir_node *noreg = ia32_new_NoReg_gp(cg);
-       ir_node *nomem = new_rd_NoMem(irg);
-       ir_node *conv  = new_rd_ia32_Conv_FP2FP(dbgi, irg, block, noreg, noreg, in, nomem);
-
-       set_ia32_am_support(conv, ia32_am_Source);
-       set_ia32_ls_mode(conv, mode_xmm);
-       SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node));
-
-       return conv;
-}
-#endif
-
 /* Generates an entity for a known FP const (used for FP Neg + Abs) */
 ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) {
        static const struct {
@@ -518,7 +482,8 @@ static void fold_immediate(ir_node *node, int in1, int in2) {
        }
 
        clear_ia32_commutative(node);
-       set_ia32_am_support(node, get_ia32_am_support(node) & ~ia32_am_Source);
+       set_ia32_am_support(node, get_ia32_am_support(node) & ~ia32_am_Source,
+                           get_ia32_am_arity(node));
 }
 
 /**
@@ -533,40 +498,23 @@ static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
                           construct_binop_func *func, int commutative)
 {
        ir_node  *block    = be_transform_node(get_nodes_block(node));
-       ir_node  *new_op1  = NULL;
-       ir_node  *new_op2  = NULL;
-       ir_node  *new_node = NULL;
        ir_graph *irg      = current_ir_graph;
        dbg_info *dbgi     = get_irn_dbg_info(node);
        ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
        ir_node  *nomem    = new_NoMem();
+       ir_node  *new_node;
 
-       if(commutative) {
-               new_op2 = try_create_Immediate(op1, 0);
-               if(new_op2 != NULL) {
-                       new_op1 = be_transform_node(op2);
-                       commutative = 0;
-               }
-       }
-
-       if(new_op2 == NULL) {
-               new_op2 = try_create_Immediate(op2, 0);
-               if(new_op2 != NULL) {
-                       new_op1  = be_transform_node(op1);
-                       commutative = 0;
-               }
-       }
-
-       if(new_op2 == NULL) {
-               new_op1 = be_transform_node(op1);
-               new_op2 = be_transform_node(op2);
+       ir_node *new_op1 = be_transform_node(op1);
+       ir_node *new_op2 = create_immediate_or_transform(op2, 0);
+       if (is_ia32_Immediate(new_op2)) {
+               commutative = 0;
        }
 
        new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2, nomem);
        if (func == new_rd_ia32_IMul) {
-               set_ia32_am_support(new_node, ia32_am_Source);
+               set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
        } else {
-               set_ia32_am_support(new_node, ia32_am_Full);
+               set_ia32_am_support(new_node, ia32_am_Full, ia32_am_binary);
        }
 
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
@@ -585,8 +533,8 @@ static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
  * @param func  The node constructor function
  * @return The constructed ia32 node.
  */
-static ir_node *gen_binop_float(ir_node *node, ir_node *op1, ir_node *op2,
-                                construct_binop_func *func)
+static ir_node *gen_binop_sse_float(ir_node *node, ir_node *op1, ir_node *op2,
+                                    construct_binop_func *func)
 {
        ir_node  *block    = be_transform_node(get_nodes_block(node));
        ir_node  *new_op1  = be_transform_node(op1);
@@ -598,8 +546,9 @@ static ir_node *gen_binop_float(ir_node *node, ir_node *op1, ir_node *op2,
        ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
        ir_node  *nomem    = new_NoMem();
 
-       new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2, nomem);
-       set_ia32_am_support(new_node, ia32_am_Source);
+       new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2,
+                       nomem);
+       set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
        if (is_op_commutative(get_irn_op(node))) {
                set_ia32_commutative(new_node);
        }
@@ -612,6 +561,43 @@ static ir_node *gen_binop_float(ir_node *node, ir_node *op1, ir_node *op2,
        return new_node;
 }
 
+/**
+ * Construct a standard binary operation, set AM and immediate if required.
+ *
+ * @param op1   The first operand
+ * @param op2   The second operand
+ * @param func  The node constructor function
+ * @return The constructed ia32 node.
+ */
+static ir_node *gen_binop_x87_float(ir_node *node, ir_node *op1, ir_node *op2,
+                                    construct_binop_float_func *func)
+{
+       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  *fpcw     = be_abi_get_ignore_irn(env_cg->birg->abi,
+                                                  &ia32_fp_cw_regs[REG_FPCW]);
+
+       new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2,
+                       nomem, fpcw);
+       set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
+       if (is_op_commutative(get_irn_op(node))) {
+               set_ia32_commutative(new_node);
+       }
+       if (USE_SSE2(env_cg)) {
+               set_ia32_ls_mode(new_node, mode);
+       }
+
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+
+       return new_node;
+}
 
 /**
  * Construct a shift/rotate binary operation, sets AM and immediate if required.
@@ -626,59 +612,22 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
 {
        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_op2;
        ir_node  *new_op  = NULL;
        dbg_info *dbgi    = get_irn_dbg_info(node);
        ir_graph *irg     = current_ir_graph;
        ir_node  *noreg   = ia32_new_NoReg_gp(env_cg);
        ir_node  *nomem   = new_NoMem();
-       ir_node  *expr_op;
-       ir_node  *imm_op;
-       tarval   *tv;
 
        assert(! mode_is_float(get_irn_mode(node))
                 && "Shift/Rotate with float not supported");
 
-       /* Check if immediate optimization is on and */
-       /* if it's an operation with immediate.      */
-       imm_op  = (env_cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(NULL, new_op2) : NULL;
-       expr_op = get_expr_op(new_op1, new_op2);
-
-       assert((expr_op || imm_op) && "invalid operands");
-
-       if (!expr_op) {
-               /* We have two consts here: not yet supported */
-               imm_op = NULL;
-       }
-
-       /* Limit imm_op within range imm8 */
-       if (imm_op) {
-               tv = get_ia32_Immop_tarval(imm_op);
-
-               if (tv) {
-                       tv = tarval_mod(tv, new_tarval_from_long(32, get_tarval_mode(tv)));
-                       set_ia32_Immop_tarval(imm_op, tv);
-               }
-               else {
-                       imm_op = NULL;
-               }
-       }
-
-       /* integer operations */
-       if (imm_op) {
-               /* This is shift/rot with const */
-               DB((dbg, LEVEL_1, "Shift/Rot with immediate ..."));
+       new_op2 = create_immediate_or_transform(op2, 'N');
 
-               new_op = func(dbgi, irg, block, noreg, noreg, expr_op, noreg, nomem);
-               copy_ia32_Immop_attr(new_op, imm_op);
-       } else {
-               /* This is a normal shift/rot */
-               DB((dbg, LEVEL_1, "Shift/Rot binop ..."));
-               new_op = func(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
-       }
+       new_op = func(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
 
        /* set AM support */
-       set_ia32_am_support(new_op, ia32_am_Dest);
+       set_ia32_am_support(new_op, ia32_am_Dest, ia32_am_binary);
 
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
@@ -707,7 +656,7 @@ static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func)
 
        new_node = func(dbgi, irg, block, noreg, noreg, new_op, nomem);
        DB((dbg, LEVEL_1, "INT unop ..."));
-       set_ia32_am_support(new_node, ia32_am_Dest);
+       set_ia32_am_support(new_node, ia32_am_Dest, ia32_am_unary);
 
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
@@ -743,9 +692,9 @@ static ir_node *gen_Add(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg))
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_xAdd);
+                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xAdd);
                else
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_vfadd);
+                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd);
        }
 
        /* integer ADD */
@@ -766,7 +715,6 @@ static ir_node *gen_Add(ir_node *node) {
                        new_op = new_rd_ia32_Lea(dbgi, irg, block, new_op1, noreg);
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
                        set_ia32_am_flavour(new_op, ia32_am_B);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
 
                        DBG_OPT_LEA3(new_op1, new_op2, node, new_op);
@@ -781,7 +729,6 @@ static ir_node *gen_Add(ir_node *node) {
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op1));
                        add_ia32_am_offs_int(new_op, offs);
                        set_ia32_am_flavour(new_op, ia32_am_OB);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
                } else if (tp2 == ia32_ImmSymConst) {
                        tarval *tv = get_ia32_Immop_tarval(new_op1);
@@ -794,7 +741,6 @@ static ir_node *gen_Add(ir_node *node) {
                        add_ia32_am_offs_int(new_op, offs);
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
                        set_ia32_am_flavour(new_op, ia32_am_OB);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
                } else {
                        tarval *tv1 = get_ia32_Immop_tarval(new_op1);
@@ -837,7 +783,7 @@ static ir_node *gen_Add(ir_node *node) {
        new_op = new_rd_ia32_Add(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
 
        /* set AM support */
-       set_ia32_am_support(new_op, ia32_am_Full);
+       set_ia32_am_support(new_op, ia32_am_Full, ia32_am_binary);
        set_ia32_commutative(new_op);
 
        fold_immediate(new_op, 2, 3);
@@ -847,36 +793,6 @@ static ir_node *gen_Add(ir_node *node) {
        return new_op;
 }
 
-#if 0
-static ir_node *create_ia32_Mul(ir_node *node) {
-       ir_graph *irg = current_ir_graph;
-       dbg_info *dbgi = get_irn_dbg_info(node);
-       ir_node *block = be_transform_node(get_nodes_block(node));
-       ir_node *op1 = get_Mul_left(node);
-       ir_node *op2 = get_Mul_right(node);
-       ir_node *new_op1 = be_transform_node(op1);
-       ir_node *new_op2 = be_transform_node(op2);
-       ir_node *noreg = ia32_new_NoReg_gp(env_cg);
-       ir_node *proj_EAX, *proj_EDX, *res;
-       ir_node *in[1];
-
-       res = new_rd_ia32_Mul(dbgi, irg, block, noreg, noreg, new_op1, new_op2, new_NoMem());
-       set_ia32_commutative(res);
-       set_ia32_am_support(res, ia32_am_Source);
-
-       /* imediates are not supported, so no fold_immediate */
-       proj_EAX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EAX);
-       proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EDX);
-
-       /* keep EAX */
-       in[0] = proj_EDX;
-       be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in);
-
-       return proj_EAX;
-}
-#endif /* if 0 */
-
-
 /**
  * Creates an ia32 Mul.
  *
@@ -890,9 +806,9 @@ static ir_node *gen_Mul(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg))
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_xMul);
+                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xMul);
                else
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_vfmul);
+                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul);
        }
 
        /*
@@ -931,9 +847,7 @@ static ir_node *gen_Mulh(ir_node *node) {
        }
 
        set_ia32_commutative(res);
-       set_ia32_am_support(res, ia32_am_Source);
-
-       set_ia32_am_support(res, ia32_am_Source);
+       set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
 
        proj_EAX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EAX);
        proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EDX);
@@ -1014,7 +928,7 @@ static ir_node *gen_Max(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg)) {
-                       new_op = gen_binop_float(node, new_op1, new_op2, new_rd_ia32_xMax);
+                       new_op = gen_binop_sse_float(node, new_op1, new_op2, new_rd_ia32_xMax);
                } else {
                        panic("Can't create Max node");
                }
@@ -1053,7 +967,7 @@ static ir_node *gen_Min(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg)) {
-                       new_op = gen_binop_float(node, op1, op2, new_rd_ia32_xMin);
+                       new_op = gen_binop_sse_float(node, op1, op2, new_rd_ia32_xMin);
                } else {
                        panic("can't create Min node");
                }
@@ -1100,9 +1014,9 @@ static ir_node *gen_Sub(ir_node *node) {
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
                if (USE_SSE2(env_cg))
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_xSub);
+                       return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xSub);
                else
-                       return gen_binop_float(node, op1, op2, new_rd_ia32_vfsub);
+                       return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfsub);
        }
 
        /* integer SUB */
@@ -1136,7 +1050,6 @@ static ir_node *gen_Sub(ir_node *node) {
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op1));
                        add_ia32_am_offs_int(new_op, -offs);
                        set_ia32_am_flavour(new_op, ia32_am_OB);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
                } else if (tp2 == ia32_ImmSymConst) {
                        tarval *tv = get_ia32_Immop_tarval(new_op1);
@@ -1150,7 +1063,6 @@ static ir_node *gen_Sub(ir_node *node) {
                        set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
                        set_ia32_am_sc_sign(new_op);
                        set_ia32_am_flavour(new_op, ia32_am_OB);
-                       set_ia32_am_support(new_op, ia32_am_Source);
                        set_ia32_op_type(new_op, ia32_AddrModeS);
                } else {
                        tarval *tv1 = get_ia32_Immop_tarval(new_op1);
@@ -1193,7 +1105,7 @@ static ir_node *gen_Sub(ir_node *node) {
        new_op = new_rd_ia32_Sub(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
 
        /* set AM support */
-       set_ia32_am_support(new_op, ia32_am_Full);
+       set_ia32_am_support(new_op, ia32_am_Full, ia32_am_binary);
 
        fold_immediate(new_op, 2, 3);
 
@@ -1224,7 +1136,7 @@ static ir_node *generate_DivMod(ir_node *node, ir_node *dividend,
        ir_mode  *mode         = get_irn_mode(node);
        ir_node  *noreg        = ia32_new_NoReg_gp(env_cg);
        ir_node  *res, *proj_div, *proj_mod;
-       ir_node  *edx_node, *cltd;
+       ir_node  *sign_extension;
        ir_node  *in_keep[2];
        ir_node  *mem, *new_mem;
        ir_node  *projs[pn_DivMod_max];
@@ -1261,19 +1173,20 @@ static ir_node *generate_DivMod(ir_node *node, ir_node *dividend,
 
        if (mode_is_signed(mode)) {
                /* in signed mode, we need to sign extend the dividend */
-               cltd         = new_rd_ia32_Cltd(dbgi, irg, block, new_dividend);
-               new_dividend = new_rd_Proj(dbgi, irg, block, cltd, mode_Iu, pn_ia32_Cltd_EAX);
-               edx_node     = new_rd_Proj(dbgi, irg, block, cltd, mode_Iu, pn_ia32_Cltd_EDX);
+               sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_dividend);
        } else {
-               edx_node = new_rd_ia32_Const(dbgi, irg, block);
-               add_irn_dep(edx_node, be_abi_get_start_barrier(env_cg->birg->abi));
-               set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
+               sign_extension = new_rd_ia32_Const(dbgi, irg, block);
+               set_ia32_Immop_tarval(sign_extension, get_tarval_null(mode_Iu));
+
+               add_irn_dep(sign_extension, get_irg_frame(irg));
        }
 
        if (mode_is_signed(mode)) {
-               res = new_rd_ia32_IDiv(dbgi, irg, block, noreg, noreg, new_dividend, edx_node, new_divisor, new_mem, dm_flav);
+               res = new_rd_ia32_IDiv(dbgi, irg, block, noreg, noreg, new_dividend,
+                                      sign_extension, new_divisor, new_mem, dm_flav);
        } else {
-               res = new_rd_ia32_Div(dbgi, irg, block, noreg, noreg, new_dividend, edx_node, new_divisor, new_mem, dm_flav);
+               res = new_rd_ia32_Div(dbgi, irg, block, noreg, noreg, new_dividend,
+                                     sign_extension, new_divisor, new_mem, dm_flav);
        }
 
        set_ia32_exc_label(res, has_exc);
@@ -1282,7 +1195,7 @@ static ir_node *generate_DivMod(ir_node *node, ir_node *dividend,
        /* Matze: code can't handle this at the moment... */
 #if 0
        /* set AM support */
-       set_ia32_am_support(res, ia32_am_Source);
+       set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
 #endif
 
        /* check, which Proj-Keep, we need to add */
@@ -1356,18 +1269,21 @@ static ir_node *gen_Quot(ir_node *node) {
                ir_mode *mode = get_irn_mode(op1);
                if (is_ia32_xConst(new_op2)) {
                        new_op = new_rd_ia32_xDiv(dbgi, irg, block, noreg, noreg, new_op1, noreg, nomem);
-                       set_ia32_am_support(new_op, ia32_am_None);
+                       set_ia32_am_support(new_op, ia32_am_None, ia32_am_arity_none);
                        copy_ia32_Immop_attr(new_op, new_op2);
                } else {
                        new_op = new_rd_ia32_xDiv(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
                        // Matze: disabled for now, spillslot coalescer fails
-                       //set_ia32_am_support(new_op, ia32_am_Source);
+                       //set_ia32_am_support(new_op, ia32_am_Source | ia32_am_binary);
                }
                set_ia32_ls_mode(new_op, mode);
        } else {
-               new_op = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
+               ir_node  *fpcw = be_abi_get_ignore_irn(env_cg->birg->abi,
+                                                      &ia32_fp_cw_regs[REG_FPCW]);
+               new_op = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_op1,
+                                          new_op2, nomem, fpcw);
                // Matze: disabled for now (spillslot coalescer fails)
-               //set_ia32_am_support(new_op, ia32_am_Source);
+               //set_ia32_am_support(new_op, ia32_am_Source | ia32_am_binary);
        }
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
        return new_op;
@@ -1404,8 +1320,24 @@ static ir_node *gen_Shr(ir_node *node) {
  * @return The created ia32 Shrs node
  */
 static ir_node *gen_Shrs(ir_node *node) {
-       return gen_shift_binop(node, get_Shrs_left(node),
-                              get_Shrs_right(node), new_rd_ia32_Sar);
+       ir_node *left  = get_Shrs_left(node);
+       ir_node *right = get_Shrs_right(node);
+       if(is_Const(right) && get_irn_mode(left) == mode_Is) {
+               tarval *tv = get_Const_tarval(right);
+               long val = get_tarval_long(tv);
+               if(val == 31) {
+                       /* this is a sign extension */
+                       ir_graph *irg    = current_ir_graph;
+                       dbg_info *dbgi   = get_irn_dbg_info(node);
+                       ir_node  *block  = be_transform_node(get_nodes_block(node));
+                       ir_node  *op     = left;
+                       ir_node  *new_op = be_transform_node(op);
+
+                       return new_rd_ia32_Cltd(dbgi, irg, block, new_op);
+               }
+       }
+
+       return gen_shift_binop(node, left, right, new_rd_ia32_Sar);
 }
 
 
@@ -1564,7 +1496,7 @@ static ir_node *gen_Abs(ir_node *node) {
        ir_node   *noreg_gp = ia32_new_NoReg_gp(env_cg);
        ir_node   *noreg_fp = ia32_new_NoReg_fp(env_cg);
        ir_node   *nomem    = new_NoMem();
-       ir_node   *res, *p_eax, *p_edx;
+       ir_node   *res;
        int       size;
        ir_entity *ent;
 
@@ -1587,18 +1519,18 @@ static ir_node *gen_Abs(ir_node *node) {
                        res = new_rd_ia32_vfabs(dbgi, irg, block, new_op);
                        SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
                }
-       }
-       else {
-               res   = new_rd_ia32_Cltd(dbgi, irg, block, new_op);
-               SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
-
-               p_eax = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EAX);
-               p_edx = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EDX);
+       } else {
+               ir_node *xor;
+               ir_node *sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_op);
+               SET_IA32_ORIG_NODE(sign_extension,
+                                  ia32_get_old_node_name(env_cg, node));
 
-               res   = new_rd_ia32_Xor(dbgi, irg, block, noreg_gp, noreg_gp, p_eax, p_edx, nomem);
-               SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
+               xor = new_rd_ia32_Xor(dbgi, irg, block, noreg_gp, noreg_gp, new_op,
+                                     sign_extension, nomem);
+               SET_IA32_ORIG_NODE(xor, ia32_get_old_node_name(env_cg, node));
 
-               res   = new_rd_ia32_Sub(dbgi, irg, block, noreg_gp, noreg_gp, res, p_edx, nomem);
+               res = new_rd_ia32_Sub(dbgi, irg, block, noreg_gp, noreg_gp, xor,
+                                     sign_extension, nomem);
                SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
        }
 
@@ -1676,7 +1608,6 @@ static ir_node *gen_Load(ir_node *node) {
        }
 
        set_irn_pinned(new_op, get_irn_pinned(node));
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, am_flav);
        set_ia32_ls_mode(new_op, mode);
@@ -1706,7 +1637,7 @@ static ir_node *gen_Store(ir_node *node) {
        ir_node  *ptr     = get_Store_ptr(node);
        ir_node  *new_ptr = be_transform_node(ptr);
        ir_node  *val     = get_Store_value(node);
-       ir_node  *new_val = be_transform_node(val);
+       ir_node  *new_val;
        ir_node  *mem     = get_Store_mem(node);
        ir_node  *new_mem = be_transform_node(mem);
        ir_graph *irg     = current_ir_graph;
@@ -1714,16 +1645,10 @@ static ir_node *gen_Store(ir_node *node) {
        ir_node  *noreg   = ia32_new_NoReg_gp(env_cg);
        ir_node  *sptr    = new_ptr;
        ir_mode  *mode    = get_irn_mode(val);
-       ir_node  *sval    = new_val;
        int      is_imm   = 0;
        ir_node  *new_op;
        ia32_am_flavour_t am_flav = ia32_am_B;
 
-       if (is_ia32_Const(new_val)) {
-               assert(!mode_is_float(mode));
-               sval = noreg;
-       }
-
        /* address might be a constant (symconst or absolute address) */
        if (is_ia32_Const(new_ptr)) {
                sptr   = noreg;
@@ -1732,21 +1657,25 @@ static ir_node *gen_Store(ir_node *node) {
 
        if (mode_is_float(mode)) {
                FP_USED(env_cg);
+
+               new_val = be_transform_node(val);
                if (USE_SSE2(env_cg)) {
-                       new_op = new_rd_ia32_xStore(dbgi, irg, block, sptr, noreg, sval, new_mem);
+                       new_op = new_rd_ia32_xStore(dbgi, irg, block, sptr, noreg, new_val,
+                                                   new_mem);
                } else {
-                       new_op = new_rd_ia32_vfst(dbgi, irg, block, sptr, noreg, sval, new_mem, mode);
+                       new_op = new_rd_ia32_vfst(dbgi, irg, block, sptr, noreg, new_val,
+                                                 new_mem, mode);
                }
-       } else if (get_mode_size_bits(mode) == 8) {
-               new_op = new_rd_ia32_Store8Bit(dbgi, irg, block, sptr, noreg, sval, new_mem);
        } else {
-               new_op = new_rd_ia32_Store(dbgi, irg, block, sptr, noreg, sval, new_mem);
-       }
+               new_val = create_immediate_or_transform(val, 0);
 
-       /* stored const is an immediate value */
-       if (is_ia32_Const(new_val)) {
-               assert(!mode_is_float(mode));
-               copy_ia32_Immop_attr(new_op, new_val);
+               if (get_mode_size_bits(mode) == 8) {
+                       new_op = new_rd_ia32_Store8Bit(dbgi, irg, block, sptr, noreg,
+                                                      new_val, new_mem);
+               } else {
+                       new_op = new_rd_ia32_Store(dbgi, irg, block, sptr, noreg, new_val,
+                                                  new_mem);
+               }
        }
 
        /* base is an constant address */
@@ -1764,7 +1693,6 @@ static ir_node *gen_Store(ir_node *node) {
        }
 
        set_irn_pinned(new_op, get_irn_pinned(node));
-       set_ia32_am_support(new_op, ia32_am_Dest);
        set_ia32_op_type(new_op, ia32_AddrModeD);
        set_ia32_am_flavour(new_op, am_flav);
        set_ia32_ls_mode(new_op, mode);
@@ -1775,7 +1703,89 @@ static ir_node *gen_Store(ir_node *node) {
        return new_op;
 }
 
+static ir_node *try_create_TestJmp(ir_node *block, ir_node *node, long pnc)
+{
+       ir_node  *cmp_a     = get_Cmp_left(node);
+       ir_node  *new_cmp_a;
+       ir_node  *cmp_b     = get_Cmp_right(node);
+       ir_node  *new_cmp_b;
+       ir_node  *and_left;
+       ir_node  *and_right;
+       ir_node  *res;
+       ir_node  *noreg;
+       ir_node  *nomem;
+       dbg_info *dbgi;
+       tarval  *tv;
+
+       if(!is_Const(cmp_b))
+               return NULL;
+
+       tv = get_Const_tarval(cmp_b);
+       if(!tarval_is_null(tv))
+               return NULL;
+
+
+       if(is_And(cmp_a) && (pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg)) {
+               and_left  = get_And_left(cmp_a);
+               and_right = get_And_right(cmp_a);
+
+               new_cmp_a = be_transform_node(and_left);
+               new_cmp_b = create_immediate_or_transform(and_right, 0);
+       } else {
+               new_cmp_a = be_transform_node(cmp_a);
+               new_cmp_b = be_transform_node(cmp_a);
+       }
+
+       dbgi      = get_irn_dbg_info(node);
+       noreg     = ia32_new_NoReg_gp(env_cg);
+       nomem     = new_NoMem();
+
+       res = new_rd_ia32_TestJmp(dbgi, current_ir_graph, block, noreg, noreg,
+                                 new_cmp_a, new_cmp_b, nomem, pnc);
+       set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
+       SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
+
+       return res;
+}
+
+static ir_node *create_Switch(ir_node *node)
+{
+       ir_graph *irg     = current_ir_graph;
+       dbg_info *dbgi    = get_irn_dbg_info(node);
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *sel     = get_Cond_selector(node);
+       ir_node  *new_sel = be_transform_node(sel);
+       ir_node  *res;
+       int switch_min    = INT_MAX;
+       const ir_edge_t *edge;
 
+       /* determine the smallest switch case value */
+       foreach_out_edge(node, edge) {
+               ir_node *proj = get_edge_src_irn(edge);
+               int      pn   = get_Proj_proj(proj);
+               if(pn < switch_min)
+                       switch_min = pn;
+       }
+
+       if (switch_min != 0) {
+               ir_node  *noreg    = ia32_new_NoReg_gp(env_cg);
+
+               /* if smallest switch case is not 0 we need an additional sub */
+               new_sel = new_rd_ia32_Lea(dbgi, irg, block, new_sel, noreg);
+               add_ia32_am_offs_int(new_sel, -switch_min);
+               set_ia32_am_flavour(new_sel, ia32_am_OB);
+               set_ia32_op_type(new_sel, ia32_AddrModeS);
+
+               SET_IA32_ORIG_NODE(new_sel, ia32_get_old_node_name(env_cg, node));
+       }
+
+       res = new_rd_ia32_SwitchJmp(dbgi, irg, block, new_sel);
+       set_ia32_pncode(res, get_Cond_defaultProj(node));
+
+       SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
+
+       return res;
+}
 
 /**
  * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp, CondJmp_i or TestJmp
@@ -1790,130 +1800,64 @@ static ir_node *gen_Cond(ir_node *node) {
        ir_mode  *sel_mode = get_irn_mode(sel);
        ir_node  *res      = NULL;
        ir_node  *noreg    = ia32_new_NoReg_gp(env_cg);
-       ir_node  *cnst, *expr;
-
-       if (is_Proj(sel) && sel_mode == mode_b) {
-               ir_node *pred      = get_Proj_pred(sel);
-               ir_node *cmp_a     = get_Cmp_left(pred);
-               ir_node *new_cmp_a = be_transform_node(cmp_a);
-               ir_node *cmp_b     = get_Cmp_right(pred);
-               ir_node *new_cmp_b = be_transform_node(cmp_b);
-               ir_mode *cmp_mode  = get_irn_mode(cmp_a);
-               ir_node *nomem     = new_NoMem();
-
-               int pnc = get_Proj_proj(sel);
-               if(mode_is_float(cmp_mode) || !mode_is_signed(cmp_mode)) {
-                       pnc |= ia32_pn_Cmp_Unsigned;
-               }
-
-               /* check if we can use a CondJmp with immediate */
-               cnst = (env_cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(new_cmp_a, new_cmp_b) : NULL;
-               expr = get_expr_op(new_cmp_a, new_cmp_b);
-
-               if (cnst != NULL && expr != NULL) {
-                       /* immop has to be the right operand, we might need to flip pnc */
-                       if(cnst != new_cmp_b) {
-                               pnc = get_inversed_pnc(pnc);
-                       }
+       ir_node  *cmp;
+       ir_node  *cmp_a;
+       ir_node  *cmp_b;
+       ir_node  *new_cmp_a;
+       ir_node  *new_cmp_b;
+       ir_mode  *cmp_mode;
+       ir_node  *nomem = new_NoMem();
+       long      pnc;
 
-                       if ((pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) && mode_needs_gp_reg(get_irn_mode(expr))) {
-                               if (get_ia32_immop_type(cnst) == ia32_ImmConst &&
-                                       classify_tarval(get_ia32_Immop_tarval(cnst)) == TV_CLASSIFY_NULL)
-                               {
-                                       /* a Cmp A =/!= 0 */
-                                       ir_node    *op1  = expr;
-                                       ir_node    *op2  = expr;
-                                       int is_and = 0;
-
-                                       /* check, if expr is an only once used And operation */
-                                       if (is_ia32_And(expr) && get_irn_n_edges(expr)) {
-                                               op1 = get_irn_n(expr, 2);
-                                               op2 = get_irn_n(expr, 3);
-
-                                               is_and = (is_ia32_ImmConst(expr) || is_ia32_ImmSymConst(expr));
-                                       }
-                                       res = new_rd_ia32_TestJmp(dbgi, irg, block, op1, op2);
-                                       set_ia32_pncode(res, pnc);
-
-                                       if (is_and) {
-                                               copy_ia32_Immop_attr(res, expr);
-                                       }
-
-                                       SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
-                                       return res;
-                               }
-                       }
+       if (sel_mode != mode_b) {
+               return create_Switch(node);
+       }
 
-                       if (mode_is_float(cmp_mode)) {
-                               FP_USED(env_cg);
-                               if (USE_SSE2(env_cg)) {
-                                       res = new_rd_ia32_xCondJmp(dbgi, irg, block, noreg, noreg, expr, noreg, nomem);
-                                       set_ia32_ls_mode(res, cmp_mode);
-                               } else {
-                                       assert(0);
-                               }
-                       }
-                       else {
-                               assert(get_mode_size_bits(cmp_mode) == 32);
-                               res = new_rd_ia32_CondJmp(dbgi, irg, block, noreg, noreg, expr, noreg, nomem);
-                       }
-                       copy_ia32_Immop_attr(res, cnst);
-               }
-               else {
-                       ir_mode *cmp_mode = get_irn_mode(cmp_a);
-
-                       if (mode_is_float(cmp_mode)) {
-                               FP_USED(env_cg);
-                               if (USE_SSE2(env_cg)) {
-                                       res = new_rd_ia32_xCondJmp(dbgi, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);
-                                       set_ia32_ls_mode(res, cmp_mode);
-                               } else {
-                                       ir_node *proj_eax;
-                                       res = new_rd_ia32_vfCondJmp(dbgi, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);
-                                       proj_eax = new_r_Proj(irg, block, res, mode_Iu, pn_ia32_vfCondJmp_temp_reg_eax);
-                                       be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, &proj_eax);
-                               }
-                       }
-                       else {
-                               assert(get_mode_size_bits(cmp_mode) == 32);
-                               res = new_rd_ia32_CondJmp(dbgi, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);
-                               set_ia32_commutative(res);
-                       }
-               }
+       cmp      = get_Proj_pred(sel);
+       cmp_a    = get_Cmp_left(cmp);
+       cmp_b    = get_Cmp_right(cmp);
+       cmp_mode = get_irn_mode(cmp_a);
+       pnc = get_Proj_proj(sel);
+       if(mode_is_float(cmp_mode) || !mode_is_signed(cmp_mode)) {
+               pnc |= ia32_pn_Cmp_Unsigned;
+       }
 
-               set_ia32_pncode(res, pnc);
-               // Matze: disabled for now, because the default collect_spills_walker
-               // is not able to detect the mode of the spilled value
-               // moreover, the lea optimize phase freely exchanges left/right
-               // without updating the pnc
-               //set_ia32_am_support(res, ia32_am_Source);
+       if(mode_needs_gp_reg(cmp_mode)) {
+               res = try_create_TestJmp(block, cmp, pnc);
+               if(res != NULL)
+                       return res;
        }
-       else {
-               /* determine the smallest switch case value */
-               ir_node *new_sel = be_transform_node(sel);
-               int switch_min = INT_MAX;
-               const ir_edge_t *edge;
-
-               foreach_out_edge(node, edge) {
-                       int pn = get_Proj_proj(get_edge_src_irn(edge));
-                       switch_min = pn < switch_min ? pn : switch_min;
-               }
 
-               if (switch_min) {
-                       /* if smallest switch case is not 0 we need an additional sub */
-                       res = new_rd_ia32_Lea(dbgi, irg, block, new_sel, noreg);
-                       SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
-                       add_ia32_am_offs_int(res, -switch_min);
-                       set_ia32_am_flavour(res, ia32_am_OB);
-                       set_ia32_am_support(res, ia32_am_Source);
-                       set_ia32_op_type(res, ia32_AddrModeS);
-               }
+       new_cmp_a = be_transform_node(cmp_a);
+       new_cmp_b = create_immediate_or_transform(cmp_b, 0);
 
-               res = new_rd_ia32_SwitchJmp(dbgi, irg, block, switch_min ? res : new_sel, mode_T);
-               set_ia32_pncode(res, get_Cond_defaultProj(node));
+       if (mode_is_float(cmp_mode)) {
+               FP_USED(env_cg);
+               if (USE_SSE2(env_cg)) {
+                       res = new_rd_ia32_xCondJmp(dbgi, irg, block, noreg, noreg, cmp_a,
+                                                  cmp_b, nomem, pnc);
+                       set_ia32_commutative(res);
+                       set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
+                       set_ia32_ls_mode(res, cmp_mode);
+               } else {
+                       ir_node *proj_eax;
+                       res = new_rd_ia32_vfCondJmp(dbgi, irg, block, cmp_a, cmp_b, pnc);
+                       set_ia32_commutative(res);
+                       proj_eax = new_r_Proj(irg, block, res, mode_Iu,
+                                             pn_ia32_vfCondJmp_temp_reg_eax);
+                       be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1,
+                                   &proj_eax);
+               }
+       } else {
+               assert(get_mode_size_bits(cmp_mode) == 32);
+               res = new_rd_ia32_CondJmp(dbgi, irg, block, noreg, noreg,
+                                         new_cmp_a, new_cmp_b, nomem, pnc);
+               set_ia32_commutative(res);
+               set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
        }
 
        SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
+
        return res;
 }
 
@@ -2035,9 +1979,7 @@ static ir_node *gen_Psi(ir_node *node) {
 
        if(is_And(cond) || is_Or(cond)) {
                ir_node *new_cond = be_transform_node(cond);
-               tarval  *tv_zero  = new_tarval_from_long(0, mode_Iu);
-               ir_node *zero     = new_rd_ia32_Immediate(NULL, irg, block, NULL, 0,
-                                                         tv_zero);
+               ir_node *zero     = new_rd_ia32_Immediate(NULL, irg, block, NULL, 0, 0);
                arch_set_irn_register(env_cg->arch_env, zero,
                                      &ia32_gp_regs[REG_GP_NOREG]);
 
@@ -2053,20 +1995,8 @@ static ir_node *gen_Psi(ir_node *node) {
                cmp_mode  = get_irn_mode(cmp_a);
                pnc       = get_Proj_proj(cond);
 
-               new_cmp_b = try_create_Immediate(cmp_b, 0);
-               if(new_cmp_b == NULL) {
-                       new_cmp_b = try_create_Immediate(cmp_a, 0);
-                       if(new_cmp_b != NULL) {
-                               pnc       = get_inversed_pnc(pnc);
-                               new_cmp_a = be_transform_node(cmp_b);
-                       }
-               } else {
-                       new_cmp_a = be_transform_node(cmp_a);
-               }
-               if(new_cmp_b == NULL) {
-                       new_cmp_a = be_transform_node(cmp_a);
-                       new_cmp_b = be_transform_node(cmp_b);
-               }
+               new_cmp_a = be_transform_node(cmp_a);
+               new_cmp_b = create_immediate_or_transform(cmp_b, 0);
 
                if (!mode_is_signed(cmp_mode)) {
                        pnc |= ia32_pn_Cmp_Unsigned;
@@ -2139,7 +2069,6 @@ static ir_node *gen_x87_fp_to_gp(ir_node *node) {
 
        set_irn_pinned(fist, op_pin_state_floats);
        set_ia32_use_frame(fist);
-       set_ia32_am_support(fist, ia32_am_Dest);
        set_ia32_op_type(fist, ia32_AddrModeD);
        set_ia32_am_flavour(fist, ia32_am_B);
        set_ia32_ls_mode(fist, mode_Iu);
@@ -2150,7 +2079,6 @@ static ir_node *gen_x87_fp_to_gp(ir_node *node) {
 
        set_irn_pinned(load, op_pin_state_floats);
        set_ia32_use_frame(load);
-       set_ia32_am_support(load, ia32_am_Source);
        set_ia32_op_type(load, ia32_AddrModeS);
        set_ia32_am_flavour(load, ia32_am_B);
        set_ia32_ls_mode(load, mode_Iu);
@@ -2177,12 +2105,12 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
        src_bits = get_mode_size_bits(src_mode);
        if (src_bits == 8) {
                new_op = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, block, noreg, noreg, new_op, nomem);
-               set_ia32_am_support(new_op, ia32_am_Source);
+               set_ia32_am_support(new_op, ia32_am_Source, ia32_am_unary);
                set_ia32_ls_mode(new_op, src_mode);
                SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
        } else if (src_bits < 32) {
                new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, noreg, noreg, new_op, nomem);
-               set_ia32_am_support(new_op, ia32_am_Source);
+               set_ia32_am_support(new_op, ia32_am_Source, ia32_am_unary);
                set_ia32_ls_mode(new_op, src_mode);
                SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
        }
@@ -2191,7 +2119,6 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
        store = new_rd_ia32_Store(dbgi, irg, block, get_irg_frame(irg), noreg, new_op, nomem);
 
        set_ia32_use_frame(store);
-       set_ia32_am_support(store, ia32_am_Dest);
        set_ia32_op_type(store, ia32_AddrModeD);
        set_ia32_am_flavour(store, ia32_am_OB);
        set_ia32_ls_mode(store, mode_Iu);
@@ -2200,7 +2127,6 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
        fild = new_rd_ia32_vfild(dbgi, irg, block, get_irg_frame(irg), noreg, store);
 
        set_ia32_use_frame(fild);
-       set_ia32_am_support(fild, ia32_am_Source);
        set_ia32_op_type(fild, ia32_AddrModeS);
        set_ia32_am_flavour(fild, ia32_am_OB);
        set_ia32_ls_mode(fild, mode_Iu);
@@ -2231,14 +2157,12 @@ static ir_node *create_Strict_conv(ir_mode *src_mode, ir_mode *tgt_mode,
        store = new_rd_ia32_vfst(dbgi, irg, block, frame, noreg, node, nomem,
                                 smaller_mode);
        set_ia32_use_frame(store);
-       set_ia32_am_support(store, ia32_am_Dest);
        set_ia32_op_type(store, ia32_AddrModeD);
        set_ia32_am_flavour(store, ia32_am_OB);
 
        load = new_rd_ia32_vfld(dbgi, irg, block, frame, noreg, store,
                                smaller_mode);
        set_ia32_use_frame(load);
-       set_ia32_am_support(load, ia32_am_Source);
        set_ia32_op_type(load, ia32_AddrModeS);
        set_ia32_am_flavour(load, ia32_am_OB);
 
@@ -2323,7 +2247,7 @@ static ir_node *gen_Conv(ir_node *node) {
                                res = new_rd_ia32_Conv_I2FP(dbgi, irg, block, noreg, noreg, new_op, nomem);
                                set_ia32_ls_mode(res, tgt_mode);
                                if(src_bits == 32) {
-                                       set_ia32_am_support(res, ia32_am_Source);
+                                       set_ia32_am_support(res, ia32_am_Source, ia32_am_unary);
                                }
                        } else {
                                return gen_x87_gp_to_fp(node, src_mode);
@@ -2354,7 +2278,7 @@ static ir_node *gen_Conv(ir_node *node) {
                                res = new_rd_ia32_Conv_I2I(dbgi, irg, block, noreg, noreg, new_op, nomem);
                                set_ia32_ls_mode(res, smaller_mode);
                        }
-                       set_ia32_am_support(res, ia32_am_Source);
+                       set_ia32_am_support(res, ia32_am_Source, ia32_am_unary);
                }
        }
 
@@ -2364,13 +2288,8 @@ static ir_node *gen_Conv(ir_node *node) {
 }
 
 static
-int check_immediate_constraint(tarval *tv, char immediate_constraint_type)
+int check_immediate_constraint(long val, char immediate_constraint_type)
 {
-       long val;
-
-       assert(tarval_is_long(tv));
-       val = get_tarval_long(tv);
-
        switch (immediate_constraint_type) {
        case 0:
                return 1;
@@ -2401,6 +2320,7 @@ ir_node *try_create_Immediate(ir_node *node, char immediate_constraint_type)
        int          minus         = 0;
        tarval      *offset        = NULL;
        int          offset_sign   = 0;
+       long         val = 0;
        ir_entity   *symconst_ent  = NULL;
        int          symconst_sign = 0;
        ir_mode     *mode;
@@ -2464,13 +2384,17 @@ ir_node *try_create_Immediate(ir_node *node, char immediate_constraint_type)
 
        if(cnst != NULL) {
                offset = get_Const_tarval(cnst);
-               if(!tarval_is_long(offset)) {
+               if(tarval_is_long(offset)) {
+                       val = get_tarval_long(offset);
+               } else if(tarval_is_null(offset)) {
+                       val = 0;
+               } else {
                        ir_fprintf(stderr, "Optimisation Warning: tarval from %+F is not a "
                                   "long?\n", cnst);
                        return NULL;
                }
 
-               if(!check_immediate_constraint(offset, immediate_constraint_type))
+               if(!check_immediate_constraint(val, immediate_constraint_type))
                        return NULL;
        }
        if(symconst != NULL) {
@@ -2494,7 +2418,7 @@ ir_node *try_create_Immediate(ir_node *node, char immediate_constraint_type)
        dbgi  = get_irn_dbg_info(node);
        block = get_irg_start_block(irg);
        res   = new_rd_ia32_Immediate(dbgi, irg, block, symconst_ent, symconst_sign,
-                                     offset);
+                                     val);
        arch_set_irn_register(env_cg->arch_env, res, &ia32_gp_regs[REG_GP_NOREG]);
 
        /* make sure we don't schedule stuff before the barrier */
@@ -2503,6 +2427,16 @@ ir_node *try_create_Immediate(ir_node *node, char immediate_constraint_type)
        return res;
 }
 
+static
+ir_node *create_immediate_or_transform(ir_node *node, char immediate_constraint_type)
+{
+       ir_node *new_node = try_create_Immediate(node, immediate_constraint_type);
+       if (new_node == NULL) {
+               new_node = be_transform_node(node);
+       }
+       return new_node;
+}
+
 typedef struct constraint_t constraint_t;
 struct constraint_t {
        int                         is_in;
@@ -2908,7 +2842,6 @@ static ir_node *gen_be_StackParam(ir_node *node) {
        set_ia32_frame_ent(new_op, ent);
        set_ia32_use_frame(new_op);
 
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, ia32_am_B);
        set_ia32_ls_mode(new_op, load_mode);
@@ -2933,7 +2866,6 @@ static ir_node *gen_be_FrameAddr(ir_node *node) {
 
        res = new_rd_ia32_Lea(dbgi, irg, block, new_op, noreg);
        set_ia32_frame_ent(res, arch_get_frame_entity(env_cg->arch_env, node));
-       set_ia32_am_support(res, ia32_am_Full);
        set_ia32_use_frame(res);
        set_ia32_am_flavour(res, ia32_am_OB);
 
@@ -2978,10 +2910,10 @@ static ir_node *gen_be_FrameLoad(ir_node *node) {
        set_ia32_frame_ent(new_op, ent);
        set_ia32_use_frame(new_op);
 
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, ia32_am_B);
        set_ia32_ls_mode(new_op, mode);
+       set_ia32_flags(new_op, get_ia32_flags(new_op) | arch_irn_flags_rematerializable);
 
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
@@ -3023,7 +2955,6 @@ static ir_node *gen_be_FrameStore(ir_node *node) {
        set_ia32_frame_ent(new_op, ent);
        set_ia32_use_frame(new_op);
 
-       set_ia32_am_support(new_op, ia32_am_Dest);
        set_ia32_op_type(new_op, ia32_AddrModeD);
        set_ia32_am_flavour(new_op, ia32_am_B);
        set_ia32_ls_mode(new_op, mode);
@@ -3097,7 +3028,6 @@ static ir_node *gen_be_Return(ir_node *node) {
        set_ia32_op_type(sse_store, ia32_AddrModeD);
        set_ia32_use_frame(sse_store);
        set_ia32_am_flavour(sse_store, ia32_am_B);
-       set_ia32_am_support(sse_store, ia32_am_Dest);
 
        /* load into st0 */
        fld = new_rd_ia32_SetST0(dbgi, irg, block, frame, noreg, sse_store);
@@ -3105,7 +3035,6 @@ static ir_node *gen_be_Return(ir_node *node) {
        set_ia32_op_type(fld, ia32_AddrModeS);
        set_ia32_use_frame(fld);
        set_ia32_am_flavour(fld, ia32_am_B);
-       set_ia32_am_support(fld, ia32_am_Source);
 
        mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_SetST0_M);
        fld   = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_SetST0_res);
@@ -3146,7 +3075,7 @@ static ir_node *gen_be_Return(ir_node *node) {
 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 = be_transform_node(sz);
+       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;
@@ -3155,11 +3084,12 @@ static ir_node *gen_be_AddSP(ir_node *node) {
        ir_node  *nomem  = new_NoMem();
        ir_node  *new_op;
 
-       /* ia32 stack grows in reverse direction, make a SubSP */
-       new_op = new_rd_ia32_SubSP(dbgi, irg, block, noreg, noreg, new_sp, new_sz, nomem);
-       set_ia32_am_support(new_op, ia32_am_Source);
-       fold_immediate(new_op, 2, 3);
+       new_sz = create_immediate_or_transform(sz, 0);
 
+       /* ia32 stack grows in reverse direction, make a SubSP */
+       new_op = new_rd_ia32_SubSP(dbgi, irg, block, noreg, noreg, new_sp, new_sz,
+                                  nomem);
+       set_ia32_am_support(new_op, ia32_am_Source, ia32_am_binary);
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
        return new_op;
@@ -3171,7 +3101,7 @@ static ir_node *gen_be_AddSP(ir_node *node) {
 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 = be_transform_node(sz);
+       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;
@@ -3180,11 +3110,11 @@ static ir_node *gen_be_SubSP(ir_node *node) {
        ir_node  *nomem  = new_NoMem();
        ir_node  *new_op;
 
+       new_sz = create_immediate_or_transform(sz, 0);
+
        /* ia32 stack grows in reverse direction, make an AddSP */
        new_op = new_rd_ia32_AddSP(dbgi, irg, block, noreg, noreg, new_sp, new_sz, nomem);
-       set_ia32_am_support(new_op, ia32_am_Source);
-       fold_immediate(new_op, 2, 3);
-
+       set_ia32_am_support(new_op, ia32_am_Source, ia32_am_binary);
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
        return new_op;
@@ -3292,7 +3222,6 @@ static ir_node *gen_lowered_Load(ir_node *node, construct_load_func func, char f
 
        new_op  = func(dbgi, irg, block, new_ptr, noreg, new_mem);
 
-       set_ia32_am_support(new_op, ia32_am_Source);
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_am_flavour(new_op, ia32_am_OB);
        set_ia32_am_offs_int(new_op, 0);
@@ -3347,7 +3276,6 @@ static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func, char
                add_ia32_am_offs_int(new_op, am_offs);
        }
 
-       set_ia32_am_support(new_op, ia32_am_Dest);
        set_ia32_op_type(new_op, ia32_AddrModeD);
        set_ia32_am_flavour(new_op, am_flav);
        set_ia32_ls_mode(new_op, mode);
@@ -3376,11 +3304,11 @@ static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func, char
        }
 
 #define GEN_LOWERED_x87_OP(op)                                                 \
-       static ir_node *gen_ia32_l_##op(ir_node *node) {\
+       static ir_node *gen_ia32_l_##op(ir_node *node) {                           \
                ir_node *new_op;                                                       \
-               FORCE_x87(env_cg);                                                    \
-               new_op = gen_binop_float(node, get_binop_left(node),              \
-                                        get_binop_right(node), new_rd_ia32_##op);     \
+               FORCE_x87(env_cg);                                                     \
+               new_op = gen_binop_x87_float(node, get_binop_left(node),               \
+                                            get_binop_right(node), new_rd_ia32_##op); \
                return new_op;                                                         \
        }
 
@@ -3433,12 +3361,14 @@ static ir_node *gen_ia32_l_vfdiv(ir_node *node) {
        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      = be_abi_get_ignore_irn(env_cg->birg->abi,
+                                                   &ia32_fp_cw_regs[REG_FPCW]);
        ir_node  *vfdiv;
 
-       vfdiv = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_left, new_right, new_NoMem());
+       vfdiv = new_rd_ia32_vfdiv(dbgi, irg, block, noreg, noreg, new_left,
+                                 new_right, new_NoMem(), fpcw);
        clear_ia32_commutative(vfdiv);
-       set_ia32_am_support(vfdiv, ia32_am_Source);
-       fold_immediate(vfdiv, 2, 3);
+       set_ia32_am_support(vfdiv, ia32_am_Source, ia32_am_binary);
 
        SET_IA32_ORIG_NODE(vfdiv, ia32_get_old_node_name(env_cg, node));
 
@@ -3466,10 +3396,10 @@ static ir_node *gen_ia32_l_Mul(ir_node *node) {
 
        /* l_Mul is already a mode_T node, so we create the Mul in the normal way   */
        /* and then skip the result Proj, because all needed Projs are already there. */
-       ir_node *muls = new_rd_ia32_Mul(dbgi, irg, block, noreg, noreg, new_left, new_right, new_NoMem());
+       ir_node *muls = new_rd_ia32_Mul(dbgi, irg, block, noreg, noreg, new_left,
+                                       new_right, new_NoMem());
        clear_ia32_commutative(muls);
-       set_ia32_am_support(muls, ia32_am_Source);
-       fold_immediate(muls, 2, 3);
+       set_ia32_am_support(muls, ia32_am_Source, ia32_am_binary);
 
        /* check if EAX and EDX proj exist, add missing one */
        in[0] = new_rd_Proj(dbgi, irg, block, muls, mode_Iu, pn_EAX);
@@ -3551,8 +3481,7 @@ static ir_node *gen_lowered_64bit_shifts(ir_node *node, ir_node *op1,
        }
 
        /* set AM support */
-       // Matze: node has unsupported format (6inputs)
-       //set_ia32_am_support(new_op, ia32_am_Dest);
+       set_ia32_am_support(new_op, ia32_am_Dest, ia32_am_binary);
 
        SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
 
@@ -3601,7 +3530,6 @@ static ir_node *gen_ia32_l_X87toSSE(ir_node *node) {
        set_ia32_frame_ent(res, get_ia32_frame_ent(node));
        set_ia32_use_frame(res);
        set_ia32_ls_mode(res, get_ia32_ls_mode(node));
-       set_ia32_am_support(res, ia32_am_Dest);
        set_ia32_am_flavour(res, ia32_B);
        set_ia32_op_type(res, ia32_AddrModeD);
 
@@ -3610,7 +3538,6 @@ static ir_node *gen_ia32_l_X87toSSE(ir_node *node) {
        set_ia32_frame_ent(res, get_ia32_frame_ent(node));
        set_ia32_use_frame(res);
        set_ia32_ls_mode(res, get_ia32_ls_mode(node));
-       set_ia32_am_support(res, ia32_am_Source);
        set_ia32_am_flavour(res, ia32_B);
        set_ia32_op_type(res, ia32_AddrModeS);
        res = new_rd_Proj(dbgi, irg, block, res, mode_xmm, pn_ia32_xLoad_res);
@@ -3660,7 +3587,6 @@ static ir_node *gen_ia32_l_SSEtoX87(ir_node *node) {
                set_ia32_frame_ent(res, fent);
                set_ia32_use_frame(res);
                set_ia32_ls_mode(res, lsmode);
-               set_ia32_am_support(res, ia32_am_Dest);
                set_ia32_am_flavour(res, ia32_B);
                set_ia32_op_type(res, ia32_AddrModeD);
                mem = res;
@@ -3671,7 +3597,6 @@ static ir_node *gen_ia32_l_SSEtoX87(ir_node *node) {
        set_ia32_frame_ent(res, fent);
        set_ia32_use_frame(res);
        add_ia32_am_offs_int(res, offs);
-       set_ia32_am_support(res, ia32_am_Source);
        set_ia32_am_flavour(res, ia32_B);
        set_ia32_op_type(res, ia32_AddrModeS);
        res = new_rd_Proj(dbgi, irg, block, res, mode_vfp, pn_ia32_vfld_res);
@@ -3990,7 +3915,6 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
                set_ia32_op_type(fstp, ia32_AddrModeD);
                set_ia32_use_frame(fstp);
                set_ia32_am_flavour(fstp, ia32_am_B);
-               set_ia32_am_support(fstp, ia32_am_Dest);
 
                /* load into SSE register */
                sse_load = new_rd_ia32_xLoad(dbgi, irg, block, frame, noreg, fstp);
@@ -3998,7 +3922,6 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
                set_ia32_op_type(sse_load, ia32_AddrModeS);
                set_ia32_use_frame(sse_load);
                set_ia32_am_flavour(sse_load, ia32_am_B);
-               set_ia32_am_support(sse_load, ia32_am_Source);
 
                sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm, pn_ia32_xLoad_res);
 
@@ -4067,30 +3990,16 @@ static ir_node *gen_Proj_Cmp(ir_node *node)
        }
        /* TODO:
         * (a == b) -> !(a ^ b)
-        * (a < 0)  -> (a & 0x80000000)
-        * (a <= 0) -> !(a & 0x7fffffff)
-        * (a > 0)  -> (a & 0x7fffffff)
-        * (a >= 0) -> !(a & 0x80000000)
+        * (a < 0)  -> (a & 0x80000000) oder a >> 31
+        * (a >= 0) -> (a >> 31) ^ 1
         */
 
        if(!mode_is_signed(cmp_mode)) {
                pnc |= ia32_pn_Cmp_Unsigned;
        }
 
-       new_cmp_right = try_create_Immediate(cmp_right, 0);
-       if(new_cmp_right == NULL) {
-               new_cmp_right = try_create_Immediate(cmp_left, 0);
-               if(new_cmp_right != NULL) {
-                       pnc = get_inversed_pnc(pnc);
-                       new_cmp_left = be_transform_node(cmp_right);
-               }
-       } else {
-               new_cmp_left = be_transform_node(cmp_left);
-       }
-       if(new_cmp_right == NULL) {
-               new_cmp_left  = be_transform_node(cmp_left);
-               new_cmp_right = be_transform_node(cmp_right);
-       }
+       new_cmp_left = be_transform_node(cmp_left);
+       new_cmp_right = create_immediate_or_transform(cmp_right, 0);
 
        new_op = new_rd_ia32_CmpSet(dbgi, irg, block, noreg, noreg, new_cmp_left,
                                    new_cmp_right, nomem, pnc);