Remove the unused parameter const arch_env_t *env from arch_irn_get_flags(), arch_irn...
[libfirm] / ir / be / arm / arm_transform.c
index deb99f5..0921fd0 100644 (file)
@@ -49,6 +49,7 @@
 #include "arm_nodes_attr.h"
 #include "archop.h"
 #include "arm_transform.h"
+#include "arm_optimize.h"
 #include "arm_new_nodes.h"
 #include "arm_map_regs.h"
 
@@ -77,140 +78,67 @@ static INLINE int mode_needs_gp_reg(ir_mode *mode) {
        return mode_is_int(mode) || mode_is_reference(mode);
 }
 
-typedef struct vals_ {
-       int ops;
-       unsigned char values[4];
-       unsigned char shifts[4];
-} vals;
-
-/** Execute ROL. */
-static unsigned do_rol(unsigned v, unsigned rol) {
-       return (v << rol) | (v >> (32 - rol));
-}
-
-/**
- * construct 8bit values and rot amounts for a value
- */
-static void gen_vals_from_word(unsigned int value, vals *result)
-{
-       int initial = 0;
-
-       memset(result, 0, sizeof(*result));
-
-       /* special case: we prefer shift amount 0 */
-       if (value < 0x100) {
-               result->values[0] = value;
-               result->ops       = 1;
-               return;
-       }
-
-       while (value != 0) {
-               if (value & 0xFF) {
-                       unsigned v = do_rol(value, 8) & 0xFFFFFF;
-                       int shf = 0;
-                       for (;;) {
-                               if ((v & 3) != 0)
-                                       break;
-                               shf += 2;
-                               v >>= 2;
-                       }
-                       v  &= 0xFF;
-                       shf = (initial + shf - 8) & 0x1F;
-                       result->values[result->ops] = v;
-                       result->shifts[result->ops] = shf;
-                       ++result->ops;
-
-                       value ^= do_rol(v, shf) >> initial;
-               }
-               else {
-                       value >>= 8;
-                       initial += 8;
-               }
-       }
-}
-
 /**
  * Creates a arm_Const node.
  */
-static ir_node *create_const_node(dbg_info *dbg, ir_node *block, long value) {
+static ir_node *create_mov_node(dbg_info *dbg, ir_node *block, long value) {
        ir_mode *mode  = mode_Iu;
-       tarval   *tv   = new_tarval_from_long(value, mode);
        ir_graph *irg  = current_ir_graph;
        ir_node *res;
 
        if (mode_needs_gp_reg(mode))
                mode = mode_Iu;
-       res = new_rd_arm_Mov_i(dbg, irg, block, mode, tv);
-       /* ensure the const is scheduled AFTER the stack frame */
-       add_irn_dep(res, get_irg_frame(irg));
+       res = new_rd_arm_Mov_i(dbg, irg, block, mode, value);
+       be_dep_on_frame(res);
        return res;
 }
 
 /**
  * Creates a arm_Const_Neg node.
  */
-static ir_node *create_const_neg_node(dbg_info *dbg, ir_node *block, long value) {
+static ir_node *create_mvn_node(dbg_info *dbg, ir_node *block, long value) {
        ir_mode *mode = mode_Iu;
-       tarval  *tv   = new_tarval_from_long(value, mode);
-       ir_graph *irg  = current_ir_graph;
+       ir_graph *irg = current_ir_graph;
        ir_node *res;
 
        if (mode_needs_gp_reg(mode))
                mode = mode_Iu;
-       res = new_rd_arm_Mvn_i(dbg, irg, block, mode, tv);
-       /* ensure the const is scheduled AFTER the stack frame */
-       add_irn_dep(res, get_irg_frame(irg));
+       res = new_rd_arm_Mvn_i(dbg, irg, block, mode, value);
+       be_dep_on_frame(res);
        return res;
 }
 
 #define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode)
 
-/**
- * Encodes an immediate with shifter operand
- */
-static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
-       return immediate | ((shift>>1)<<8);
-}
-
-/**
- * Decode an immediate with shifter operand
- */
-unsigned int arm_decode_imm_w_shift(tarval *tv) {
-       unsigned l = get_tarval_long(tv);
-       unsigned rol = (l & ~0xFF) >> 7;
-
-       return do_rol(l & 0xFF, rol);
-}
-
 /**
  * Creates a possible DAG for an constant.
  */
 static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned int value) {
        ir_node *result;
-       vals v, vn;
+       arm_vals v, vn;
        int cnt;
        ir_mode *mode = mode_Iu;
 
-       gen_vals_from_word(value, &v);
-       gen_vals_from_word(~value, &vn);
+       arm_gen_vals_from_word(value, &v);
+       arm_gen_vals_from_word(~value, &vn);
 
        if (vn.ops < v.ops) {
                /* remove bits */
-               result = create_const_neg_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
+               result = create_mvn_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
 
                for (cnt = 1; cnt < vn.ops; ++cnt) {
-                       tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode);
-                       ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, tv);
+                       long value = arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]);
+                       ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, value);
                        result = bic_i_node;
                }
        }
        else {
                /* add bits */
-               result = create_const_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
+               result = create_mov_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
 
                for (cnt = 1; cnt < v.ops; ++cnt) {
-                       tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode);
-                       ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, tv);
+                       long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]);
+                       ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, value);
                        result = orr_i_node;
                }
        }
@@ -242,7 +170,7 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
 static ir_node *gen_zero_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
        unsigned mask_bits = (1 << result_bits) - 1;
        ir_node *mask_node = create_const_graph_value(dbg, block, mask_bits);
-       return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, mode_Iu, ARM_SHF_NONE, NULL);
+       return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, mode_Iu, ARM_SHF_NONE, 0);
 }
 
 /**
@@ -294,11 +222,11 @@ static ir_node *gen_Conv(ir_node *node) {
                        }
                }
                else if (USE_VFP(env_cg->isa)) {
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                        return NULL;
                }
                else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                        return NULL;
                }
        }
@@ -334,7 +262,7 @@ static ir_node *gen_Conv(ir_node *node) {
                                return gen_zero_extension(dbg, block, new_op, min_bits);
                        }
                } else {
-                       panic("Cannot handle Conv %+F->%+F with %d->%d bits\n", src_mode, dst_mode,
+                       panic("Cannot handle Conv %+F->%+F with %d->%d bits", src_mode, dst_mode,
                                src_bits, dst_bits);
                        return NULL;
                }
@@ -352,7 +280,7 @@ static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
 
        *pmod = mod;
        if (mod != ARM_SHF_NONE) {
-               long v = get_tarval_long(get_arm_value(n));
+               long v = get_arm_imm_value(n);
                if (v < 32)
                        return (int)v;
        }
@@ -381,17 +309,17 @@ static ir_node *gen_Add(ir_node *node) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa)) {
                        if (is_arm_fpaMvf_i(new_op1))
-                               return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
+                               return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
                        if (is_arm_fpaMvf_i(new_op2))
-                               return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2));
+                               return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
                        return new_rd_arm_fpaAdf(dbg, irg, block, new_op1, new_op2, mode);
                } else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                        return NULL;
                }
                else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                        return NULL;
                }
        } else {
@@ -399,9 +327,9 @@ static ir_node *gen_Add(ir_node *node) {
                mode = mode_Iu;
 
                if (is_arm_Mov_i(new_op1))
-                       return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
+                       return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
                if (is_arm_Mov_i(new_op2))
-                       return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2));
+                       return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
 
                /* check for MLA */
                if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
@@ -423,17 +351,17 @@ static ir_node *gen_Add(ir_node *node) {
                v = is_shifter_operand(new_op1, &mod);
                if (v) {
                        new_op1 = get_irn_n(new_op1, 0);
-                       return new_rd_arm_Add(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu));
+                       return new_rd_arm_Add(dbg, irg, block, new_op2, new_op1, mode, mod, v);
                }
                /* is the second a shifter */
                v = is_shifter_operand(new_op2, &mod);
                if (v) {
                        new_op2 = get_irn_n(new_op2, 0);
-                       return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu));
+                       return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, mod, v);
                }
 
                /* normal ADD */
-               return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL);
+               return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
        }
 }
 
@@ -456,18 +384,18 @@ static ir_node *gen_Mul(ir_node *node) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa)) {
                        if (is_arm_Mov_i(new_op1))
-                               return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
+                               return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
                        if (is_arm_Mov_i(new_op2))
-                               return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2));
+                               return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
                        return new_rd_arm_fpaMuf(dbg, irg, block, new_op1, new_op2, mode);
                }
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                        return NULL;
                }
                else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                        return NULL;
                }
        }
@@ -496,16 +424,16 @@ static ir_node *gen_Quot(ir_node *node) {
        env_cg->have_fp_insn = 1;
        if (USE_FPA(env_cg->isa)) {
                if (is_arm_Mov_i(new_op1))
-                       return new_rd_arm_fpaRdf_i(dbg, current_ir_graph, block, new_op2, mode, get_arm_value(new_op1));
+                       return new_rd_arm_fpaRdf_i(dbg, current_ir_graph, block, new_op2, mode, get_arm_imm_value(new_op1));
                if (is_arm_Mov_i(new_op2))
-                       return new_rd_arm_fpaDvf_i(dbg, current_ir_graph, block, new_op1, mode, get_arm_value(new_op2));
+                       return new_rd_arm_fpaDvf_i(dbg, current_ir_graph, block, new_op1, mode, get_arm_imm_value(new_op2));
                return new_rd_arm_fpaDvf(dbg, current_ir_graph, block, new_op1, new_op2, mode);
        } else if (USE_VFP(env_cg->isa)) {
                assert(mode != mode_E && "IEEE Extended FP not supported");
-               panic("VFP not supported yet\n");
+               panic("VFP not supported yet");
        }
        else {
-               panic("Softfloat not supported yet\n");
+               panic("Softfloat not supported yet");
                return NULL;
        }
 }
@@ -523,23 +451,23 @@ static ir_node *gen_Quot(ir_node *node) {
        arm_shift_modifier mod; \
  \
        if (is_arm_Mov_i(new_op1)) \
-               return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1)); \
+               return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); \
        if (is_arm_Mov_i(new_op2)) \
-               return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2)); \
+               return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); \
        /* is the first a shifter */ \
        v = is_shifter_operand(new_op1, &mod); \
        if (v) { \
                new_op1 = get_irn_n(new_op1, 0); \
-               return new_rd_arm_ ## op(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \
+               return new_rd_arm_ ## op(dbg, irg, block, new_op2, new_op1, mode, mod, v); \
        } \
        /* is the second a shifter */ \
        v = is_shifter_operand(new_op2, &mod); \
        if (v) { \
                new_op2 = get_irn_n(new_op2, 0); \
-               return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \
+               return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, mod, v); \
        } \
        /* Normal op */ \
-       return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL) \
+       return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0) \
 
 /**
  * Creates an ARM And.
@@ -590,17 +518,17 @@ static ir_node *gen_Sub(ir_node *node) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa)) {
                        if (is_arm_Mov_i(new_op1))
-                               return new_rd_arm_fpaRsf_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
+                               return new_rd_arm_fpaRsf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
                        if (is_arm_Mov_i(new_op2))
-                               return new_rd_arm_fpaSuf_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2));
+                               return new_rd_arm_fpaSuf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
                        return new_rd_arm_fpaSuf(dbg, irg, block, new_op1, new_op2, mode);
                } else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                        return NULL;
                }
                else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                        return NULL;
                }
        }
@@ -609,24 +537,24 @@ static ir_node *gen_Sub(ir_node *node) {
                mode = mode_Iu;
 
                if (is_arm_Mov_i(new_op1))
-                       return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1));
+                       return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
                if (is_arm_Mov_i(new_op2))
-                       return new_rd_arm_Sub_i(dbg, irg, block, new_op1, mode, get_arm_value(new_op2));
+                       return new_rd_arm_Sub_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
 
                /* is the first a shifter */
                v = is_shifter_operand(new_op1, &mod);
                if (v) {
                        new_op1 = get_irn_n(new_op1, 0);
-                       return new_rd_arm_Rsb(dbg, irg, block, new_op2, new_op1, mode, mod, new_tarval_from_long(v, mode_Iu));
+                       return new_rd_arm_Rsb(dbg, irg, block, new_op2, new_op1, mode, mod, v);
                }
                /* is the second a shifter */
                v = is_shifter_operand(new_op2, &mod);
                if (v) {
                        new_op2 = get_irn_n(new_op2, 0);
-                       return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, mod, new_tarval_from_long(v, mode_Iu));
+                       return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, mod, v);
                }
                /* normal sub */
-               return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL);
+               return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
        }
 }
 
@@ -645,7 +573,7 @@ static ir_node *gen_Shl(ir_node *node) {
        dbg_info *dbg     = get_irn_dbg_info(node);
 
        if (is_arm_Mov_i(new_op2)) {
-               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSL, get_arm_value(new_op2));
+               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSL, get_arm_imm_value(new_op2));
        }
        return new_rd_arm_Shl(dbg, current_ir_graph, block, new_op1, new_op2, mode);
 }
@@ -665,7 +593,7 @@ static ir_node *gen_Shr(ir_node *node) {
        dbg_info *dbg     = get_irn_dbg_info(node);
 
        if (is_arm_Mov_i(new_op2)) {
-               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSR, get_arm_value(new_op2));
+               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSR, get_arm_imm_value(new_op2));
        }
        return new_rd_arm_Shr(dbg, current_ir_graph, block, new_op1, new_op2, mode);
 }
@@ -685,11 +613,111 @@ static ir_node *gen_Shrs(ir_node *node) {
        dbg_info *dbg     = get_irn_dbg_info(node);
 
        if (is_arm_Mov_i(new_op2)) {
-               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_value(new_op2));
+               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_imm_value(new_op2));
        }
        return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode);
 }
 
+/**
+ * Creates an ARM Ror.
+ *
+ * @return the created ARM Ror node
+ */
+static ir_node *gen_Ror(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_mode  *mode    = mode_Iu;
+       dbg_info *dbg     = get_irn_dbg_info(node);
+
+       if (is_arm_Mov_i(new_op2)) {
+               return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, get_arm_imm_value(new_op2));
+       }
+       return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode);
+}
+
+/**
+ * Creates an ARM Rol.
+ *
+ * @return the created ARM Rol node
+ *
+ * Note: there is no Rol on arm, we have to use Ror
+ */
+static ir_node *gen_Rol(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_mode  *mode    = mode_Iu;
+       dbg_info *dbg     = get_irn_dbg_info(node);
+       ir_node  *new_op2 = be_transform_node(op2);
+
+       new_op2 = new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op2, mode, 32);
+       return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode);
+}
+
+/**
+ * Creates an ARM ROR from a Firm Rotl.
+ *
+ * @return the created ARM Ror node
+ */
+static ir_node *gen_Rotl(ir_node *node) {
+       ir_node *rotate = NULL;
+       ir_node *op1    = get_Rotl_left(node);
+       ir_node *op2    = get_Rotl_right(node);
+
+       /* Firm has only RotL, so we are looking for a right (op2)
+          operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
+          that means we can create a RotR. */
+
+       if (is_Add(op2)) {
+               ir_node *right = get_Add_right(op2);
+               if (is_Const(right)) {
+                       tarval  *tv   = get_Const_tarval(right);
+                       ir_mode *mode = get_irn_mode(node);
+                       long     bits = get_mode_size_bits(mode);
+                       ir_node *left = get_Add_left(op2);
+
+                       if (is_Minus(left) &&
+                           tarval_is_long(tv)          &&
+                           get_tarval_long(tv) == bits &&
+                           bits                == 32)
+                               rotate = gen_Ror(node, op1, get_Minus_op(left));
+               }
+       } else if (is_Sub(op2)) {
+               ir_node *left = get_Sub_left(op2);
+               if (is_Const(left)) {
+                       tarval  *tv   = get_Const_tarval(left);
+                       ir_mode *mode = get_irn_mode(node);
+                       long     bits = get_mode_size_bits(mode);
+                       ir_node *right = get_Sub_right(op2);
+
+                       if (tarval_is_long(tv)          &&
+                           get_tarval_long(tv) == bits &&
+                           bits                == 32)
+                               rotate = gen_Ror(node, op1, right);
+               }
+       } else if (is_Const(op2)) {
+                       tarval  *tv   = get_Const_tarval(op2);
+                       ir_mode *mode = get_irn_mode(node);
+                       long     bits = get_mode_size_bits(mode);
+
+                       if (tarval_is_long(tv) && bits == 32) {
+                               ir_node  *block   = be_transform_node(get_nodes_block(node));
+                               ir_node  *new_op1 = be_transform_node(op1);
+                               ir_mode  *mode    = mode_Iu;
+                               dbg_info *dbg     = get_irn_dbg_info(node);
+
+                               bits = (bits - get_tarval_long(tv)) & 31;
+                               rotate = new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, bits);
+                       }
+       }
+
+       if (rotate == NULL) {
+               rotate = gen_Rol(node, op1, op2);
+       }
+
+       return rotate;
+}
+
 /**
  * Transforms a Not node.
  *
@@ -700,16 +728,14 @@ static ir_node *gen_Not(ir_node *node) {
        ir_node  *op      = get_Not_op(node);
        ir_node  *new_op  = be_transform_node(op);
        dbg_info *dbg     = get_irn_dbg_info(node);
-       tarval   *tv      = NULL;
        ir_mode  *mode    = mode_Iu;
        arm_shift_modifier mod = ARM_SHF_NONE;
        int      v        = is_shifter_operand(new_op, &mod);
 
        if (v) {
                new_op = get_irn_n(new_op, 0);
-               tv = new_tarval_from_long(v, mode_Iu);
        }
-       return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, tv);
+       return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, v);
 }
 
 /**
@@ -731,10 +757,10 @@ static ir_node *gen_Abs(ir_node *node) {
                        return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, new_op, mode);
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                }
                else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                }
        }
        assert(mode_is_data(mode));
@@ -760,15 +786,15 @@ static ir_node *gen_Minus(ir_node *node) {
                        return new_rd_arm_fpaMvf(dbg, current_ir_graph, block, op, mode);
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                }
                else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                }
        }
        assert(mode_is_data(mode));
        mode = mode_Iu;
-       return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode));
+       return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, 0);
 }
 
 /**
@@ -793,10 +819,10 @@ static ir_node *gen_Load(ir_node *node) {
                        new_load = new_rd_arm_fpaLdf(dbg, irg, block, new_ptr, new_mem, mode);
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                }
                else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                }
        }
        else {
@@ -815,7 +841,7 @@ static ir_node *gen_Load(ir_node *node) {
                                new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
                                break;
                        default:
-                               panic("mode size not supported\n");
+                               panic("mode size not supported");
                        }
                } else {
                        /* zero extended loads */
@@ -830,7 +856,7 @@ static ir_node *gen_Load(ir_node *node) {
                                new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
                                break;
                        default:
-                               panic("mode size not supported\n");
+                               panic("mode size not supported");
                        }
                }
        }
@@ -840,7 +866,7 @@ static ir_node *gen_Load(ir_node *node) {
        if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
                /* add a result proj and a Keep to produce a pseudo use */
                ir_node *proj = new_r_Proj(irg, block, new_load, mode_Iu, pn_arm_Load_res);
-               be_new_Keep(arch_get_irn_reg_class(env_cg->arch_env, proj, -1), irg, block, 1, &proj);
+               be_new_Keep(arch_get_irn_reg_class(proj, -1), irg, block, 1, &proj);
        }
 
        return new_load;
@@ -870,9 +896,9 @@ static ir_node *gen_Store(ir_node *node) {
                        new_store = new_rd_arm_fpaStf(dbg, irg, block, new_ptr, new_val, new_mem, mode);
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                } else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                }
        } else {
                assert(mode_is_data(mode) && "unsupported mode for Store");
@@ -907,9 +933,9 @@ static ir_node *gen_Cond(ir_node *node) {
                ir_node *op1      = get_Cmp_left(cmp_node);
                ir_node *new_op1  = be_transform_node(op1);
                ir_node *op2      = get_Cmp_right(cmp_node);
-               ir_node *new_op2  = be_transform_node(op2);
 
                if (mode_is_float(get_irn_mode(op1))) {
+                       ir_node *new_op2  = be_transform_node(op2);
                        /* floating point compare */
                        pn_Cmp pnc = get_Proj_proj(selector);
 
@@ -919,8 +945,12 @@ static ir_node *gen_Cond(ir_node *node) {
                        }
                        /* Hmm: use need cmfe */
                        return new_rd_arm_fpaCmfeBra(dbg, irg, block, new_op1, new_op2, pnc);
+               } else if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
+                       /* compare with 0 */
+                       return new_rd_arm_TstBra(dbg, irg, block, new_op1, new_op1, get_Proj_proj(selector));
                } else {
                        /* integer compare */
+                       ir_node *new_op2  = be_transform_node(op2);
                        return new_rd_arm_CmpBra(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector));
                }
        } else {
@@ -958,7 +988,7 @@ static ir_node *gen_Cond(ir_node *node) {
                }
 
                const_graph = create_const_graph_value(dbg, block, translation);
-               sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, NULL);
+               sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, 0);
                return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation);
        }
 }
@@ -987,18 +1017,6 @@ static ident *get_sc_ident(ir_node *symc) {
        return NULL;
 }
 
-enum fpa_immediates {
-       fpa_null = 0,
-       fpa_one,
-       fpa_two,
-       fpa_three,
-       fpa_four,
-       fpa_five,
-       fpa_ten,
-       fpa_half,
-       fpa_max
-};
-
 static tarval *fpa_imm[3][fpa_max];
 
 /**
@@ -1027,9 +1045,9 @@ static int is_fpa_immediate(tarval *tv) {
 
        for (j = 0; j < fpa_max; ++j) {
                if (tv == fpa_imm[i][j])
-                       return res;
+                       return res * j;
        }
-       return 0;
+       return fpa_max;
 }
 
 /**
@@ -1049,24 +1067,23 @@ static ir_node *gen_Const(ir_node *node) {
                        tarval *tv = get_Const_tarval(node);
                        int imm = is_fpa_immediate(tv);
 
-                       if (imm) {
+                       if (imm != fpa_max) {
                                if (imm > 0)
-                                       node = new_rd_arm_fpaMvf_i(dbg, irg, block, tv);
+                                       node = new_rd_arm_fpaMvf_i(dbg, irg, block, mode, imm);
                                else
-                                       node = new_rd_arm_fpaMnf_i(dbg, irg, block, tv);
+                                       node = new_rd_arm_fpaMnf_i(dbg, irg, block, mode, -imm);
                        } else {
                                node = new_rd_arm_fpaConst(dbg, irg, block, tv);
                        }
-                       /* ensure the const is scheduled AFTER the stack frame */
-                       add_irn_dep(node, get_irg_frame(irg));
+                       be_dep_on_frame(node);
                        return node;
                }
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
-                       panic("VFP not supported yet\n");
+                       panic("VFP not supported yet");
                }
                else {
-                       panic("Softfloat not supported yet\n");
+                       panic("Softfloat not supported yet");
                }
        }
        return create_const_graph(node, block);
@@ -1085,8 +1102,7 @@ static ir_node *gen_SymConst(ir_node *node) {
        ir_node  *res;
 
        res = new_rd_arm_SymConst(dbg, irg, block, mode, get_sc_ident(node));
-       /* ensure the const is scheduled AFTER the stack frame */
-       add_irn_dep(res, get_irg_frame(irg));
+       be_dep_on_frame(res);
        return res;
 }
 
@@ -1116,7 +1132,7 @@ static ir_node *gen_CopyB(ir_node *node) {
                        new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
                        new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
                        new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu),
-                       new_mem, new_tarval_from_long(size, mode_Iu));
+                       new_mem, size);
 }
 
 
@@ -1209,48 +1225,10 @@ static ir_node *gen_be_FrameAddr(ir_node *node) {
        }
        cnst = create_const_graph_value(dbg, block, (unsigned)offset);
        if (is_arm_Mov_i(cnst))
-               return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_value(cnst));
-       return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, NULL);
+               return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_imm_value(cnst));
+       return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, 0);
 }
 
-#if 0
-/**
- * Transforms a FrameLoad into an ARM Load.
- */
-static ir_node *gen_FrameLoad(ir_node *irn) {
-       ir_node   *new_op = NULL;
-       ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
-       ir_node   *mem    = get_irn_n(irn, 0);
-       ir_node   *ptr    = get_irn_n(irn, 1);
-       ir_entity *ent    = be_get_frame_entity(irn);
-       ir_mode   *mode   = get_type_mode(get_entity_type(ent));
-
-       if (mode_is_float(mode)) {
-               if (USE_SSE2(env->cg))
-                       new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
-               else {
-                       env->cg->used_x87 = 1;
-                       new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
-               }
-       }
-       else {
-               new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
-       }
-
-       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_B);
-       set_ia32_ls_mode(new_op, mode);
-
-       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
-
-       return new_op;
-}
-#endif
-
 /**
  * Transform a be_AddSP into an arm_AddSP. Eat up const sizes.
  */
@@ -1265,8 +1243,8 @@ static ir_node *gen_be_AddSP(ir_node *node) {
        ir_node  *nomem  = new_NoMem();
        ir_node  *new_op;
 
-       /* ARM stack grows in reverse direction, make a SubSP */
-       new_op = new_rd_arm_SubSP(dbgi, irg, block, new_sp, new_sz, nomem);
+       /* ARM stack grows in reverse direction, make a SubSPandCopy */
+       new_op = new_rd_arm_SubSPandCopy(dbgi, irg, block, new_sp, new_sz, nomem);
 
        return new_op;
 }
@@ -1341,8 +1319,7 @@ static ir_node *gen_Proj_Load(ir_node *node) {
        default:
                break;
        }
-       assert(0);
-       return new_rd_Unknown(irg, get_irn_mode(node));
+       panic("Unsupported Proj from Load");
 }
 
 /**
@@ -1354,7 +1331,6 @@ static ir_node *gen_Proj_CopyB(ir_node *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) {
@@ -1366,8 +1342,7 @@ static ir_node *gen_Proj_CopyB(ir_node *node) {
        default:
                break;
        }
-       assert(0);
-       return new_rd_Unknown(irg, mode);
+       panic("Unsupported Proj from CopyB");
 }
 
 /**
@@ -1408,12 +1383,11 @@ static ir_node *gen_Proj_Quot(ir_node *node) {
        default:
                break;
        }
-       assert(0);
-       return new_rd_Unknown(irg, mode);
+       panic("Unsupported Proj from Quot");
 }
 
 /**
- * Transform the Projs of aAddSP.
+ * Transform the Projs of a be_AddSP.
  */
 static ir_node *gen_Proj_be_AddSP(ir_node *node) {
        ir_node  *block    = be_transform_node(get_nodes_block(node));
@@ -1423,20 +1397,22 @@ static ir_node *gen_Proj_be_AddSP(ir_node *node) {
        dbg_info *dbgi     = get_irn_dbg_info(node);
        long     proj      = get_Proj_proj(node);
 
-       if (proj == pn_be_AddSP_res) {
-               ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_arm_AddSP_stack);
-               arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]);
+       if (proj == pn_be_AddSP_sp) {
+               ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
+                                          pn_arm_SubSPandCopy_stack);
+               arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
                return res;
+       } else if(proj == pn_be_AddSP_res) {
+               return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
+                                  pn_arm_SubSPandCopy_addr);
        } else if (proj == pn_be_AddSP_M) {
-               return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_AddSP_M);
+               return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSPandCopy_M);
        }
-
-       assert(0);
-       return new_rd_Unknown(irg, get_irn_mode(node));
+       panic("Unsupported Proj from AddSP");
 }
 
 /**
- * Transform the Projs of a SubSP.
+ * Transform the Projs of a be_SubSP.
  */
 static ir_node *gen_Proj_be_SubSP(ir_node *node) {
        ir_node  *block    = be_transform_node(get_nodes_block(node));
@@ -1448,15 +1424,13 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) {
 
        if (proj == pn_be_SubSP_sp) {
                ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
-                                          pn_arm_SubSP_stack);
-               arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]);
+                                          pn_arm_AddSP_stack);
+               arch_set_irn_register(res, &arm_gp_regs[REG_SP]);
                return res;
        } else if (proj == pn_be_SubSP_M) {
-               return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSP_M);
+               return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_AddSP_M);
        }
-
-       assert(0);
-       return new_rd_Unknown(irg, get_irn_mode(node));
+       panic("Unsupported Proj from SubSP");
 }
 
 /**
@@ -1464,7 +1438,7 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) {
  */
 static ir_node *gen_Proj_Cmp(ir_node *node) {
        (void) node;
-       panic("Psi NYI\n");
+       panic("Mux NYI");
 }
 
 
@@ -1492,8 +1466,7 @@ static ir_node *gen_Proj(ir_node *node) {
                if (proj == pn_Store_M) {
                        return be_transform_node(pred);
                } else {
-                       assert(0);
-                       return new_r_Bad(irg);
+                       panic("Unsupported Proj from Store");
                }
        } else if (is_Load(pred)) {
                return gen_Proj_Load(node);
@@ -1507,7 +1480,7 @@ static ir_node *gen_Proj(ir_node *node) {
                return gen_Proj_be_AddSP(node);
        } else if (is_Cmp(pred)) {
                return gen_Proj_Cmp(node);
-       } else if (get_irn_op(pred) == op_Start) {
+       } else if (is_Start(pred)) {
                if (proj == pn_Start_X_initial_exec) {
                        ir_node *block = get_nodes_block(pred);
                        ir_node *jump;
@@ -1515,7 +1488,6 @@ static ir_node *gen_Proj(ir_node *node) {
                        /* we exchange the ProjX with a jump */
                        block = be_transform_node(block);
                        jump  = new_rd_Jmp(dbgi, irg, block);
-                       ir_fprintf(stderr, "created jump: %+F\n", jump);
                        return jump;
                }
                if (node == get_irg_anchor(irg, anchor_tls)) {
@@ -1551,7 +1523,7 @@ static INLINE ir_node *create_const(ir_node **place,
 
        block = get_irg_start_block(env_cg->irg);
        res = func(NULL, env_cg->irg, block);
-       arch_set_irn_register(env_cg->arch_env, res, reg);
+       arch_set_irn_register(res, reg);
        *place = res;
 
        add_irn_dep(get_irg_end(env_cg->irg), res);
@@ -1614,7 +1586,6 @@ static ir_node *gen_Phi(ir_node *node) {
        copy_node_attr(node, phi);
        be_duplicate_deps(node, phi);
 
-       be_set_transformed_node(node, phi);
        be_enqueue_preds(node);
 
        return phi;
@@ -1634,7 +1605,7 @@ static ir_node *gen_Phi(ir_node *node) {
  * the BAD transformer.
  */
 static ir_node *bad_transform(ir_node *irn) {
-       panic("ARM backend: Not implemented: %+F\n", irn);
+       panic("ARM backend: Not implemented: %+F", irn);
        return irn;
 }
 
@@ -1667,7 +1638,7 @@ static void arm_register_transformers(void) {
        GEN(Shl);
        GEN(Shr);
        GEN(Shrs);
-       BAD(Rot);       /* unsupported yet */
+       GEN(Rotl);
 
        GEN(Quot);
 
@@ -1687,8 +1658,7 @@ static void arm_register_transformers(void) {
 
        BAD(ASM);       /* unsupported yet */
        GEN(CopyB);
-       BAD(Mux);
-       BAD(Psi);       /* unsupported yet */
+       BAD(Mux);       /* unsupported yet */
        GEN(Proj);
        GEN(Phi);
 
@@ -1738,8 +1708,9 @@ static void arm_register_transformers(void) {
 /**
  * Pre-transform all unknown nodes.
  */
-static void arm_pretransform_node(void *arch_cg) {
-       arm_code_gen_t *cg = arch_cg;
+static void arm_pretransform_node(void)
+{
+       arm_code_gen_t *cg = env_cg;
 
        cg->unknown_gp  = be_pre_transform_node(cg->unknown_gp);
        cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
@@ -1790,7 +1761,7 @@ void arm_transform_graph(arm_code_gen_t *cg) {
        }
        arm_register_transformers();
        env_cg = cg;
-       be_transform_graph(cg->birg, arm_pretransform_node, cg);
+       be_transform_graph(cg->birg, arm_pretransform_node);
 }
 
 void arm_init_transform(void) {