refactored immediates:
[libfirm] / ir / be / arm / arm_transform.c
index 5c11cd4..2ef8019 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -42,6 +42,7 @@
 
 #include "../benode_t.h"
 #include "../beirg_t.h"
+#include "../beutil.h"
 #include "../betranshlp.h"
 #include "bearch_arm_t.h"
 
@@ -73,7 +74,7 @@ extern ir_op *get_op_Mulh(void);
  ****************************************************************************************************/
 
 static INLINE int mode_needs_gp_reg(ir_mode *mode) {
-       return mode_is_int(mode) || mode_is_character(mode) || mode_is_reference(mode);
+       return mode_is_int(mode) || mode_is_reference(mode);
 }
 
 typedef struct vals_ {
@@ -131,34 +132,32 @@ static void gen_vals_from_word(unsigned int value, vals *result)
 /**
  * Creates a arm_Const node.
  */
-static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
-       tarval   *tv   = new_tarval_from_long(value, mode_Iu);
-       dbg_info *dbg  = get_irn_dbg_info(irn);
-       ir_mode  *mode = get_irn_mode(irn);
+static ir_node *create_const_node(dbg_info *dbg, ir_node *block, long value) {
+       ir_mode *mode  = mode_Iu;
+       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, current_ir_graph, block, mode, tv);
-       /* ensure the const is schedules AFTER the barrier */
-       add_irn_dep(res, be_abi_get_start_barrier(abi));
+       res = new_rd_arm_Mov_i(dbg, irg, block, mode, value);
+       /* ensure the const is scheduled AFTER the stack frame */
+       add_irn_dep(res, get_irg_frame(irg));
        return res;
 }
 
 /**
  * Creates a arm_Const_Neg node.
  */
-static ir_node *create_const_neg_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
-       tarval   *tv   = new_tarval_from_long(value, mode_Iu);
-       dbg_info *dbg  = get_irn_dbg_info(irn);
-       ir_mode  *mode = get_irn_mode(irn);
+static ir_node *create_const_neg_node(dbg_info *dbg, ir_node *block, long value) {
+       ir_mode *mode = mode_Iu;
+       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, current_ir_graph, block, mode, tv);
-       add_irn_dep(res, be_abi_get_start_barrier(abi));
-       /* ensure the const is schedules AFTER the barrier */
+       res = new_rd_arm_Mvn_i(dbg, irg, block, mode, value);
+       /* ensure the const is scheduled AFTER the stack frame */
+       add_irn_dep(res, get_irg_frame(irg));
        return res;
 }
 
@@ -174,8 +173,8 @@ static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int imme
 /**
  * Decode an immediate with shifter operand
  */
-unsigned int arm_decode_imm_w_shift(tarval *tv) {
-       unsigned l = get_tarval_long(tv);
+unsigned int arm_decode_imm_w_shift(long imm_value) {
+       unsigned l = (unsigned)imm_value;
        unsigned rol = (l & ~0xFF) >> 7;
 
        return do_rol(l & 0xFF, rol);
@@ -184,36 +183,32 @@ unsigned int arm_decode_imm_w_shift(tarval *tv) {
 /**
  * Creates a possible DAG for an constant.
  */
-static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_node *block, unsigned int value) {
+static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned int value) {
        ir_node *result;
        vals v, vn;
        int cnt;
-       ir_mode *mode = get_irn_mode(irn);
-       dbg_info *dbg = get_irn_dbg_info(irn);
+       ir_mode *mode = mode_Iu;
 
        gen_vals_from_word(value, &v);
        gen_vals_from_word(~value, &vn);
 
-       if (mode_needs_gp_reg(mode))
-               mode = mode_Iu;
-
        if (vn.ops < v.ops) {
                /* remove bits */
-               result = create_const_neg_node(abi, irn, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
+               result = create_const_neg_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_Iu);
-                       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(abi, irn, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
+               result = create_const_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_Iu);
-                       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;
                }
        }
@@ -225,7 +220,7 @@ static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_nod
  *
  * @param irn  a Firm const
  */
-static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *block) {
+static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
        tarval  *tv = get_Const_tarval(irn);
        ir_mode *mode = get_tarval_mode(tv);
        int     value;
@@ -236,48 +231,27 @@ static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *blo
                tv = tarval_convert_to(tv, mode_Iu);
        }
        value = get_tarval_long(tv);
-       return create_const_graph_value(abi, irn, block, value);
+       return create_const_graph_value(get_irn_dbg_info(irn), block, value);
 }
 
 /**
- * Creates code for a Firm Const node.
+ * Create an And that will mask all upper bits
  */
-static ir_node *gen_arm_Const(ir_node *irn, ir_node *block, arm_code_gen_t *cg) {
-       ir_graph *irg = current_ir_graph;
-       ir_mode *mode = get_irn_mode(irn);
-       dbg_info *dbg = get_irn_dbg_info(irn);
-
-       if (mode_is_float(mode)) {
-               cg->have_fp_insn = 1;
-               if (USE_FPA(cg->isa)) {
-                       irn = new_rd_arm_fpaConst(dbg, irg, block, get_Const_tarval(irn));
-                       /* ensure the const is schedules AFTER the barrier */
-                       add_irn_dep(irn, be_abi_get_start_barrier(cg->birg->abi));
-                       return irn;
-               }
-               else if (USE_VFP(cg->isa))
-                       assert(mode != mode_E && "IEEE Extended FP not supported");
-               assert(0 && "NYI");
-       }
-       return create_const_graph(cg->birg->abi, irn, block);
-}
-
-static ir_node *gen_mask(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
-       ir_node *block = get_nodes_block(irn);
+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(abi, irn, block, mask_bits);
-       dbg_info *dbg = get_irn_dbg_info(irn);
-       return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, get_irn_mode(irn), ARM_SHF_NONE, NULL);
+       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, 0);
 }
 
-static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
-       ir_node *block = get_nodes_block(irn);
+/**
+ * Generate code for a sign extension.
+ */
+static ir_node *gen_sign_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
+       ir_graph *irg   = current_ir_graph;
        int shift_width = 32 - result_bits;
-       ir_graph *irg = current_ir_graph;
-       ir_node *shift_const_node = create_const_graph_value(abi, irn, block, shift_width);
-       dbg_info *dbg = get_irn_dbg_info(irn);
-       ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, get_irn_mode(op));
-       ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, get_irn_mode(irn));
+       ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width);
+       ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, mode_Iu);
+       ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, mode_Iu);
        return rshift_node;
 }
 
@@ -295,9 +269,6 @@ static ir_node *gen_Conv(ir_node *node) {
        ir_mode  *dst_mode = get_irn_mode(node);
        dbg_info *dbg      = get_irn_dbg_info(node);
 
-       if (mode_needs_gp_reg(dst_mode))
-               dst_mode = mode_Iu;
-
        if (src_mode == dst_mode)
                return new_op;
 
@@ -308,7 +279,7 @@ static ir_node *gen_Conv(ir_node *node) {
                        if (mode_is_float(src_mode)) {
                                if (mode_is_float(dst_mode)) {
                                        /* from float to float */
-                                       return new_rd_arm_fpaMov(dbg, irg, block, new_op, dst_mode);
+                                       return new_rd_arm_fpaMvf(dbg, irg, block, new_op, dst_mode);
                                }
                                else {
                                        /* from float to int */
@@ -320,72 +291,50 @@ static ir_node *gen_Conv(ir_node *node) {
                                return new_rd_arm_fpaFlt(dbg, irg, block, new_op, dst_mode);
                        }
                }
-               else {
+               else if (USE_VFP(env_cg->isa)) {
                        panic("VFP not supported yet\n");
                        return NULL;
                }
+               else {
+                       panic("Softfloat not supported yet\n");
+                       return NULL;
+               }
        }
        else { /* complete in gp registers */
                int src_bits = get_mode_size_bits(src_mode);
                int dst_bits = get_mode_size_bits(dst_mode);
-               int src_sign = get_mode_sign(src_mode);
-               int dst_sign = get_mode_sign(dst_mode);
+               int min_bits;
+               ir_mode *min_mode;
 
-               if (src_bits == dst_bits) {
-                       /* kill 32 -> 32 convs */
-                       if (src_bits == 32) {
+               if (is_Load(skip_Proj(op))) {
+                       if (src_bits == dst_bits) {
+                               /* kill unneccessary conv */
                                return new_op;
-                       } else if (dst_bits < 32) {
-                       // 16 -> 16
-                               // unsigned -> unsigned
-                                       // NOP
-                               // unsigned -> signed
-                                       // sign extension (31:16)=(15)
-                               // signed -> unsigned
-                                       // zero extension (31:16)=0
-                               // signed -> signed
-                                       // NOP
-                               if (src_sign && !dst_sign) {
-                                       return gen_mask(env_cg->birg->abi, node, new_op, dst_bits);
-                               } else {
-                                       return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
-                               }
-                       } else {
-                               panic("Cannot handle mode %+F with %d bits\n", dst_mode, dst_bits);
-                               return NULL;
                        }
+                       /* after a load, the bit size is already converted */
+                       src_bits = 32;
                }
-               else if (src_bits < dst_bits) {
-                       // 16 -> 32
-                               // unsigned -> unsigned
-                                       // NOP
-                               // unsigned -> signed
-                                       // NOP
-                               // signed -> unsigned
-                                       // sign extension (31:16)=(15)
-                               // signed -> signed
-                                       // sign extension (31:16)=(15)
-                       if (src_sign) {
-                               return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
+
+               if (src_bits == dst_bits) {
+                       /* kill unneccessary conv */
+                       return new_op;
+               } else if (dst_bits <= 32 && src_bits <= 32) {
+                       if (src_bits < dst_bits) {
+                               min_bits = src_bits;
+                               min_mode = src_mode;
                        } else {
-                               return new_op;
+                               min_bits = dst_bits;
+                               min_mode = dst_mode;
                        }
-               }
-               else {
-                       // 32 -> 16
-                               // unsigned -> unsigned
-                                       // maskieren (31:16)=0
-                               // unsigned -> signed
-                                       // maskieren (31:16)=0
-                               // signed -> unsigned
-                                       // maskieren (31:16)=0
-                               // signed -> signed
-                                       // sign extension (erledigt auch maskieren) (31:16)=(15)
-                       if (src_sign && dst_sign) {
-                               return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits);
+                       if (mode_is_signed(min_mode)) {
+                               return gen_sign_extension(dbg, block, new_op, min_bits);
                        } else {
-                               return gen_mask(env_cg->birg->abi, node, new_op, dst_bits);
+                               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,
+                               src_bits, dst_bits);
+                       return NULL;
                }
        }
 }
@@ -401,7 +350,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;
        }
@@ -428,9 +377,13 @@ static ir_node *gen_Add(ir_node *node) {
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
-               if (USE_FPA(env_cg->isa))
-                       return new_rd_arm_fpaAdd(dbg, irg, block, new_op1, new_op2, mode);
-               else if (USE_VFP(env_cg->isa)) {
+               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_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_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");
                        return NULL;
@@ -440,22 +393,23 @@ static ir_node *gen_Add(ir_node *node) {
                        return NULL;
                }
        } else {
-               assert(mode_is_numP(mode));
+               assert(mode_is_data(mode));
+               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(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(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(new_op1) == 1) {
+               if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
                        new_op3 = new_op2;
-                       op2 = get_irn_n(new_op1, 1);
-                       op1 = get_irn_n(new_op1, 0);
+                       new_op2 = get_irn_n(new_op1, 1);
+                       new_op1 = get_irn_n(new_op1, 0);
 
                        return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode);
                }
-               if (is_arm_Mul(new_op2) && get_irn_n_edges(new_op2) == 1) {
+               if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
                        new_op3 = new_op1;
                        new_op1 = get_irn_n(new_op2, 0);
                        new_op2 = get_irn_n(new_op2, 1);
@@ -467,17 +421,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);
        }
 }
 
@@ -498,17 +452,25 @@ static ir_node *gen_Mul(ir_node *node) {
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
-               if (USE_FPA(env_cg->isa))
-                       return new_rd_arm_fpaMul(dbg, irg, block, new_op1, new_op2, mode);
+               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_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_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");
+                       return NULL;
                }
                else {
                        panic("Softfloat not supported yet\n");
                        return NULL;
                }
        }
+       assert(mode_is_data(mode));
+       mode = mode_Iu;
        return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode);
 }
 
@@ -530,9 +492,13 @@ static ir_node *gen_Quot(ir_node *node) {
        assert(mode != mode_E && "IEEE Extended FP not supported");
 
        env_cg->have_fp_insn = 1;
-       if (USE_FPA(env_cg->isa))
-               return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, op1, op2, mode);
-       else if (USE_VFP(env_cg->isa)) {
+       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_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_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");
        }
@@ -549,29 +515,29 @@ static ir_node *gen_Quot(ir_node *node) {
        ir_node  *op2     = get_ ## op ## _right(node); \
        ir_node  *new_op2 = be_transform_node(op2); \
        ir_graph *irg     = current_ir_graph; \
-       ir_mode  *mode    = get_irn_mode(node); \
+       ir_mode  *mode    = mode_Iu; \
        dbg_info *dbg     = get_irn_dbg_info(node); \
        int      v; \
        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.
@@ -611,7 +577,7 @@ static ir_node *gen_Sub(ir_node *node) {
        ir_node  *op1     = get_Sub_left(node);
        ir_node  *new_op1 = be_transform_node(op1);
        ir_node  *op2     = get_Sub_right(node);
-       ir_node  *new_op2 = be_transform_node(node);
+       ir_node  *new_op2 = be_transform_node(op2);
        ir_mode  *mode    = get_irn_mode(node);
        ir_graph *irg     = current_ir_graph;
        dbg_info *dbg     = get_irn_dbg_info(node);
@@ -620,9 +586,13 @@ static ir_node *gen_Sub(ir_node *node) {
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
-               if (USE_FPA(env_cg->isa))
-                       return new_rd_arm_fpaSub(dbg, irg, block, new_op1, new_op2, mode);
-               else if (USE_VFP(env_cg->isa)) {
+               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_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_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");
                        return NULL;
@@ -633,27 +603,28 @@ static ir_node *gen_Sub(ir_node *node) {
                }
        }
        else {
-               assert(mode_is_numP(mode) && "unknown mode for Sub");
+               assert(mode_is_data(mode) && "unknown mode for Sub");
+               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);
        }
 }
 
@@ -668,11 +639,11 @@ static ir_node *gen_Shl(ir_node *node) {
        ir_node  *new_op1 = be_transform_node(op1);
        ir_node  *op2     = get_Shl_right(node);
        ir_node  *new_op2 = be_transform_node(op2);
-       ir_mode  *mode    = get_irn_mode(node);
+       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_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);
 }
@@ -688,11 +659,11 @@ static ir_node *gen_Shr(ir_node *node) {
        ir_node  *new_op1 = be_transform_node(op1);
        ir_node  *op2     = get_Shr_right(node);
        ir_node  *new_op2 = be_transform_node(op2);
-       ir_mode  *mode    = get_irn_mode(node);
+       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_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);
 }
@@ -708,11 +679,11 @@ static ir_node *gen_Shrs(ir_node *node) {
        ir_node  *new_op1 = be_transform_node(op1);
        ir_node  *op2     = get_Shrs_right(node);
        ir_node  *new_op2 = be_transform_node(op2);
-       ir_mode  *mode    = get_irn_mode(node);
+       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_ASR, get_arm_value(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);
 }
@@ -727,15 +698,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, get_irn_mode(node), mod, tv);
+       return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, v);
 }
 
 /**
@@ -746,7 +716,7 @@ static ir_node *gen_Not(ir_node *node) {
  */
 static ir_node *gen_Abs(ir_node *node) {
        ir_node  *block   = be_transform_node(get_nodes_block(node));
-       ir_node  *op      = get_Not_op(node);
+       ir_node  *op      = get_Abs_op(node);
        ir_node  *new_op  = be_transform_node(op);
        dbg_info *dbg     = get_irn_dbg_info(node);
        ir_mode  *mode    = get_irn_mode(node);
@@ -757,9 +727,14 @@ 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");
-                       assert(0 && "NYI");
+                       panic("VFP not supported yet\n");
+               }
+               else {
+                       panic("Softfloat not supported yet\n");
                }
        }
+       assert(mode_is_data(mode));
+       mode = mode_Iu;
        return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode);
 }
 
@@ -778,13 +753,18 @@ static ir_node *gen_Minus(ir_node *node) {
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa))
-                       return new_rd_arm_fpaMnv(dbg, current_ir_graph, block, op, mode);
+                       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");
-                       assert(0 && "NYI");
+                       panic("VFP not supported yet\n");
+               }
+               else {
+                       panic("Softfloat not supported yet\n");
                }
        }
-       return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode));
+       assert(mode_is_data(mode));
+       mode = mode_Iu;
+       return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, 0);
 }
 
 /**
@@ -793,58 +773,73 @@ static ir_node *gen_Minus(ir_node *node) {
  * @return the created ARM Load node
  */
 static ir_node *gen_Load(ir_node *node) {
-       ir_node  *block   = be_transform_node(get_nodes_block(node));
-       ir_node  *ptr     = get_Load_ptr(node);
-       ir_node  *new_ptr = be_transform_node(ptr);
-       ir_node  *mem     = get_Load_mem(node);
-       ir_node  *new_mem = be_transform_node(mem);
-       ir_mode  *mode    = get_Load_mode(node);
-       ir_graph *irg     = current_ir_graph;
-       dbg_info *dbg     = get_irn_dbg_info(node);
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *ptr      = get_Load_ptr(node);
+       ir_node  *new_ptr  = be_transform_node(ptr);
+       ir_node  *mem      = get_Load_mem(node);
+       ir_node  *new_mem  = be_transform_node(mem);
+       ir_mode  *mode     = get_Load_mode(node);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbg      = get_irn_dbg_info(node);
+       ir_node  *new_load = NULL;
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa))
-                       return new_rd_arm_fpaLdf(dbg, irg, block, new_ptr, new_mem, mode);
+                       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");
                }
                else {
                        panic("Softfloat not supported yet\n");
-                       return NULL;
                }
        }
        else {
-               assert(mode_is_numP(mode) && "unsupported mode for Load");
+               assert(mode_is_data(mode) && "unsupported mode for Load");
 
                if (mode_is_signed(mode)) {
                        /* sign extended loads */
                        switch (get_mode_size_bits(mode)) {
                        case 8:
-                               return new_rd_arm_Loadbs(dbg, irg, block, new_ptr, new_mem);
+                               new_load = new_rd_arm_Loadbs(dbg, irg, block, new_ptr, new_mem);
+                               break;
                        case 16:
-                               return new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem);
+                               new_load = new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem);
+                               break;
                        case 32:
+                               new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
                                break;
                        default:
-                               assert(!"mode size not supported");
+                               panic("mode size not supported\n");
                        }
                } else {
                        /* zero extended loads */
                        switch (get_mode_size_bits(mode)) {
                        case 8:
-                               return new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem);
+                               new_load = new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem);
+                               break;
                        case 16:
-                               return new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem);
+                               new_load = new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem);
+                               break;
                        case 32:
+                               new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
                                break;
                        default:
-                               assert(!"mode size not supported");
+                               panic("mode size not supported\n");
                        }
                }
-               return new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
        }
+       set_irn_pinned(new_load, get_irn_pinned(node));
+
+       /* check for special case: the loaded value might not be used */
+       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);
+       }
+
+       return new_load;
 }
 
 /**
@@ -853,35 +848,41 @@ static ir_node *gen_Load(ir_node *node) {
  * @return the created ARM Store node
  */
 static ir_node *gen_Store(ir_node *node) {
-       ir_node  *block   = be_transform_node(get_nodes_block(node));
-       ir_node  *ptr     = get_Store_ptr(node);
-       ir_node  *new_ptr = be_transform_node(ptr);
-       ir_node  *mem     = get_Store_mem(node);
-       ir_node  *new_mem = be_transform_node(mem);
-       ir_node  *val     = get_Store_value(node);
-       ir_node  *new_val = be_transform_node(val);
-       ir_mode  *mode    = get_irn_mode(val);
-       ir_graph *irg     = current_ir_graph;
-       dbg_info *dbg     = get_irn_dbg_info(node);
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *ptr      = get_Store_ptr(node);
+       ir_node  *new_ptr  = be_transform_node(ptr);
+       ir_node  *mem      = get_Store_mem(node);
+       ir_node  *new_mem  = be_transform_node(mem);
+       ir_node  *val      = get_Store_value(node);
+       ir_node  *new_val  = be_transform_node(val);
+       ir_mode  *mode     = get_irn_mode(val);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbg      = get_irn_dbg_info(node);
+       ir_node *new_store = NULL;
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa))
-                       return new_rd_arm_fpaStf(dbg, irg, block, new_ptr, new_val, new_mem, mode);
+                       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");
-                       assert(0 && "NYI");
+                       panic("VFP not supported yet\n");
+               } else {
+                       panic("Softfloat not supported yet\n");
+               }
+       } else {
+               assert(mode_is_data(mode) && "unsupported mode for Store");
+               switch (get_mode_size_bits(mode)) {
+               case 8:
+                       new_store = new_rd_arm_Storeb(dbg, irg, block, new_ptr, new_val, new_mem);
+               case 16:
+                       new_store = new_rd_arm_Storeh(dbg, irg, block, new_ptr, new_val, new_mem);
+               default:
+                       new_store = new_rd_arm_Store(dbg, irg, block, new_ptr, new_val, new_mem);
                }
        }
-
-       switch (get_mode_size_bits(mode)) {
-       case 8:
-               return new_rd_arm_Storeb(dbg, irg, block, new_ptr, new_val, new_mem);
-       case 16:
-               return new_rd_arm_Storeh(dbg, irg, block, new_ptr, new_val, new_mem);
-       default:
-               return new_rd_arm_Store(dbg, irg, block, new_ptr, new_val, new_mem);
-       }
+       set_irn_pinned(new_store, get_irn_pinned(node));
+       return new_store;
 }
 
 /**
@@ -897,14 +898,27 @@ static ir_node *gen_Cond(ir_node *node) {
        ir_mode  *mode     = get_irn_mode(selector);
 
        if (mode == mode_b) {
-               /* CondJmp */
+               /* an conditional jump */
                ir_node *cmp_node = get_Proj_pred(selector);
                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);
 
-               return new_rd_arm_CondJmp(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector));
+               if (mode_is_float(get_irn_mode(op1))) {
+                       /* floating point compare */
+                       pn_Cmp pnc = get_Proj_proj(selector);
+
+                       if (pnc & pn_Cmp_Uo) {
+                               /* check for unordered, need cmf */
+                               return new_rd_arm_fpaCmfBra(dbg, irg, block, new_op1, new_op2, pnc);
+                       }
+                       /* Hmm: use need cmfe */
+                       return new_rd_arm_fpaCmfeBra(dbg, irg, block, new_op1, new_op2, pnc);
+               } else {
+                       /* integer compare */
+                       return new_rd_arm_CmpBra(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector));
+               }
        } else {
                /* SwitchJmp */
                ir_node *new_op = be_transform_node(selector);
@@ -939,9 +953,8 @@ static ir_node *gen_Cond(ir_node *node) {
                        set_Proj_proj(proj, pn);
                }
 
-
-               const_graph = create_const_graph_value(env_cg->birg->abi, node, block, translation);
-               sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, NULL);
+               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, 0);
                return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation);
        }
 }
@@ -960,7 +973,7 @@ static ident *get_sc_ident(ir_node *symc) {
 
                case symconst_addr_ent:
                        ent = get_SymConst_entity(symc);
-                       mark_entity_visited(ent);
+                       set_entity_backend_marked(ent, 1);
                        return get_entity_ld_ident(ent);
 
                default:
@@ -970,6 +983,39 @@ static ident *get_sc_ident(ir_node *symc) {
        return NULL;
 }
 
+static tarval *fpa_imm[3][fpa_max];
+
+/**
+ * Check, if a floating point tarval is an fpa immediate, i.e.
+ * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
+ */
+static int is_fpa_immediate(tarval *tv) {
+       ir_mode *mode = get_tarval_mode(tv);
+       int i, j, res = 1;
+
+       switch (get_mode_size_bits(mode)) {
+       case 32:
+               i = 0;
+               break;
+       case 64:
+               i = 1;
+               break;
+       default:
+               i = 2;
+       }
+
+       if (tarval_cmp(tv, get_tarval_null(mode)) & pn_Cmp_Lt) {
+               tv = tarval_neg(tv);
+               res = -1;
+       }
+
+       for (j = 0; j < fpa_max; ++j) {
+               if (tv == fpa_imm[i][j])
+                       return res * j;
+       }
+       return fpa_max;
+}
+
 /**
  * Transforms a Const node.
  *
@@ -977,13 +1023,39 @@ static ident *get_sc_ident(ir_node *symc) {
  */
 static ir_node *gen_Const(ir_node *node) {
        ir_node  *block = be_transform_node(get_nodes_block(node));
-       ir_mode  *mode  = get_irn_mode(node);
-       dbg_info *dbg   = get_irn_dbg_info(node);
+       ir_graph *irg = current_ir_graph;
+       ir_mode *mode = get_irn_mode(node);
+       dbg_info *dbg = get_irn_dbg_info(node);
 
-       return create_const_graph(env_cg->birg->abi, node, block);
+       if (mode_is_float(mode)) {
+               env_cg->have_fp_insn = 1;
+               if (USE_FPA(env_cg->isa)) {
+                       tarval *tv = get_Const_tarval(node);
+                       int imm = is_fpa_immediate(tv);
+
+                       if (imm != fpa_max) {
+                               if (imm > 0)
+                                       node = new_rd_arm_fpaMvf_i(dbg, irg, block, mode, imm);
+                               else
+                                       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));
+                       return node;
+               }
+               else if (USE_VFP(env_cg->isa)) {
+                       assert(mode != mode_E && "IEEE Extended FP not supported");
+                       panic("VFP not supported yet\n");
+               }
+               else {
+                       panic("Softfloat not supported yet\n");
+               }
+       }
+       return create_const_graph(node, block);
 }
 
-
 /**
  * Transforms a SymConst node.
  *
@@ -991,13 +1063,14 @@ static ir_node *gen_Const(ir_node *node) {
  */
 static ir_node *gen_SymConst(ir_node *node) {
        ir_node  *block = be_transform_node(get_nodes_block(node));
-       ir_mode  *mode  = get_irn_mode(node);
+       ir_mode  *mode  = mode_Iu;
        dbg_info *dbg   = get_irn_dbg_info(node);
+       ir_graph *irg   = current_ir_graph;
        ir_node  *res;
 
-       res = new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(node));
-       add_irn_dep(res, be_abi_get_start_barrier(env_cg->birg->abi));
-       /* ensure the const is schedules AFTER the barrier */
+       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));
        return res;
 }
 
@@ -1027,7 +1100,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),
-                       mem, new_tarval_from_long(size, mode_Iu));
+                       new_mem, size);
 }
 
 
@@ -1109,8 +1182,8 @@ static ir_node *gen_be_FrameAddr(ir_node *node) {
        int       offset  = get_entity_offset(ent);
        ir_node   *op     = be_get_FrameAddr_frame(node);
        ir_node   *new_op = be_transform_node(op);
-       ir_mode   *mode   = get_irn_mode(node);
        dbg_info  *dbg    = get_irn_dbg_info(node);
+       ir_mode   *mode   = mode_Iu;
        ir_node   *cnst;
 
        if (be_is_IncSP(op)) {
@@ -1118,10 +1191,10 @@ static ir_node *gen_be_FrameAddr(ir_node *node) {
                   is relative. Both must be merged */
                offset += get_sp_expand_offset(op);
        }
-       cnst = create_const_graph_value(env_cg->birg->abi, node, block, (unsigned)offset);
+       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
@@ -1295,25 +1368,25 @@ static ir_node *gen_Proj_Quot(ir_node *node) {
 
        switch (proj) {
        case pn_Quot_M:
-               if (is_arm_fpaDiv(new_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaDiv_M);
-               } else if (is_arm_fpaRdv(new_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaRdv_M);
-               } else if (is_arm_fpaFDiv(new_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFDiv_M);
-               } else if (is_arm_fpaFRdv(new_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFRdv_M);
+               if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaDvf_M);
+               } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaRdf_M);
+               } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFdv_M);
+               } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_fpaFrd_M);
                }
                break;
        case pn_Quot_res:
-               if (is_arm_fpaDiv(new_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaDiv_res);
-               } else if (is_arm_fpaFDiv(new_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaRdv_res);
-               } else if (is_arm_fpaFDiv(new_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFDiv_res);
-               } else if (is_arm_fpaFDiv(new_pred)) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFRdv_res);
+               if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaDvf_res);
+               } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaRdf_res);
+               } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFdv_res);
+               } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode, pn_arm_fpaFrd_res);
                }
                break;
        default:
@@ -1324,7 +1397,7 @@ static ir_node *gen_Proj_Quot(ir_node *node) {
 }
 
 /**
- * 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));
@@ -1334,12 +1407,16 @@ 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);
+       if (proj == pn_be_AddSP_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]);
                return res;
+       } else if(proj == pn_be_AddSP_res) {
+               return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
+                                  pn_arm_SubSP_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_SubSP_M);
        }
 
        assert(0);
@@ -1347,7 +1424,7 @@ static ir_node *gen_Proj_be_AddSP(ir_node *node) {
 }
 
 /**
- * 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));
@@ -1357,12 +1434,13 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) {
        dbg_info *dbgi     = get_irn_dbg_info(node);
        long     proj      = get_Proj_proj(node);
 
-       if (proj == pn_be_SubSP_res) {
-               ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_arm_SubSP_stack);
+       if (proj == pn_be_SubSP_sp) {
+               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]);
                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);
@@ -1373,6 +1451,7 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) {
  * Transform the Projs from a Cmp.
  */
 static ir_node *gen_Proj_Cmp(ir_node *node) {
+       (void) node;
        panic("Psi NYI\n");
 }
 
@@ -1397,14 +1476,14 @@ static ir_node *gen_Proj(ir_node *node) {
        ir_node  *pred = get_Proj_pred(node);
        long     proj  = get_Proj_proj(node);
 
-       if (is_Store(pred) || be_is_FrameStore(pred)) {
+       if (is_Store(pred)) {
                if (proj == pn_Store_M) {
                        return be_transform_node(pred);
                } else {
                        assert(0);
                        return new_r_Bad(irg);
                }
-       } else if (is_Load(pred) || be_is_FrameLoad(pred)) {
+       } else if (is_Load(pred)) {
                return gen_Proj_Load(node);
        } else if (is_CopyB(pred)) {
                return gen_Proj_CopyB(node);
@@ -1427,14 +1506,14 @@ static ir_node *gen_Proj(ir_node *node) {
                        ir_fprintf(stderr, "created jump: %+F\n", jump);
                        return jump;
                }
-               if (node == be_get_old_anchor(anchor_tls)) {
+               if (node == get_irg_anchor(irg, anchor_tls)) {
                        return gen_Proj_tls(node);
                }
        } else {
                ir_node *new_pred = be_transform_node(pred);
-               ir_node *block    = be_transform_node(get_nodes_block(node));
                ir_mode *mode     = get_irn_mode(node);
                if (mode_needs_gp_reg(mode)) {
+                       ir_node *block    = be_transform_node(get_nodes_block(node));
                        ir_node *new_proj = new_r_Proj(irg, block, new_pred, mode_Iu,
                                                       get_Proj_proj(node));
 #ifdef DEBUG_libfirm
@@ -1447,6 +1526,59 @@ static ir_node *gen_Proj(ir_node *node) {
        return be_duplicate_node(node);
 }
 
+typedef ir_node *(*create_const_node_func)(dbg_info *db, ir_graph *irg, ir_node *block);
+
+static INLINE ir_node *create_const(ir_node **place,
+                                    create_const_node_func func,
+                                    const arch_register_t* reg)
+{
+       ir_node *block, *res;
+
+       if (*place != NULL)
+               return *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);
+       *place = res;
+
+       add_irn_dep(get_irg_end(env_cg->irg), res);
+       return res;
+}
+
+static ir_node *arm_new_Unknown_gp(void) {
+       return create_const(&env_cg->unknown_gp, new_rd_arm_Unknown_GP,
+                           &arm_gp_regs[REG_GP_UKNWN]);
+}
+
+static ir_node *arm_new_Unknown_fpa(void) {
+       return create_const(&env_cg->unknown_fpa, new_rd_arm_Unknown_FPA,
+                           &arm_fpa_regs[REG_FPA_UKNWN]);
+}
+
+/**
+ * This function just sets the register for the Unknown node
+ * as this is not done during register allocation because Unknown
+ * is an "ignore" node.
+ */
+static ir_node *gen_Unknown(ir_node *node) {
+       ir_mode *mode = get_irn_mode(node);
+       if (mode_is_float(mode)) {
+               if (USE_FPA(env_cg->isa))
+                       return arm_new_Unknown_fpa();
+               else if (USE_VFP(env_cg->isa))
+                       panic("VFP not supported yet");
+               else
+                       panic("Softfloat not supported yet");
+       } else if (mode_needs_gp_reg(mode)) {
+               return arm_new_Unknown_gp();
+       } else {
+               assert(0 && "unsupported Unknown-Mode");
+       }
+
+       return NULL;
+}
+
 /**
  * Change some phi modes
  */
@@ -1512,7 +1644,6 @@ static void arm_register_transformers(void) {
 
 #define GEN(a)     set_transformer(op_##a, gen_##a)
 #define BAD(a)     set_transformer(op_##a, bad_transform)
-#define IGN(a)
 
        GEN(Add);
        GEN(Sub);
@@ -1549,9 +1680,6 @@ static void arm_register_transformers(void) {
        GEN(Proj);
        GEN(Phi);
 
-       IGN(Block);
-       IGN(End);
-
        GEN(Const);
        GEN(SymConst);
 
@@ -1574,15 +1702,12 @@ static void arm_register_transformers(void) {
        GEN(be_FrameAddr);
        //GEN(be_Call);
        //GEN(be_Return);
-       BAD(be_FrameLoad);      /* unsupported yet */
-       BAD(be_FrameStore);     /* unsupported yet */
-       BAD(be_StackParam);     /* unsupported yet */
        GEN(be_AddSP);
        GEN(be_SubSP);
        GEN(be_Copy);
 
        /* set the register for all Unknown nodes */
-       BAD(Unknown);
+       GEN(Unknown);
 
        op_Max = get_op_Max();
        if (op_Max)
@@ -1594,25 +1719,66 @@ static void arm_register_transformers(void) {
        if (op_Mulh)
                BAD(Mulh);      /* unsupported yet */
 
-#undef IGN
 #undef GEN
 #undef BAD
 }
 
 /**
- * Pre-transform all unknown and noreg nodes.
+ * Pre-transform all unknown nodes.
  */
 static void arm_pretransform_node(void *arch_cg) {
        arm_code_gen_t *cg = arch_cg;
+
+       cg->unknown_gp  = be_pre_transform_node(cg->unknown_gp);
+       cg->unknown_fpa = be_pre_transform_node(cg->unknown_fpa);
+}
+
+/**
+ * Initialize fpa Immediate support.
+ */
+static void arm_init_fpa_immediate(void) {
+       /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
+       fpa_imm[0][fpa_null]  = get_tarval_null(mode_F);
+       fpa_imm[0][fpa_one]   = get_tarval_one(mode_F);
+       fpa_imm[0][fpa_two]   = new_tarval_from_str("2", 1, mode_F);
+       fpa_imm[0][fpa_three] = new_tarval_from_str("3", 1, mode_F);
+       fpa_imm[0][fpa_four]  = new_tarval_from_str("4", 1, mode_F);
+       fpa_imm[0][fpa_five]  = new_tarval_from_str("5", 1, mode_F);
+       fpa_imm[0][fpa_ten]   = new_tarval_from_str("10", 2, mode_F);
+       fpa_imm[0][fpa_half]  = new_tarval_from_str("0.5", 3, mode_F);
+
+       fpa_imm[1][fpa_null]  = get_tarval_null(mode_D);
+       fpa_imm[1][fpa_one]   = get_tarval_one(mode_D);
+       fpa_imm[1][fpa_two]   = new_tarval_from_str("2", 1, mode_D);
+       fpa_imm[1][fpa_three] = new_tarval_from_str("3", 1, mode_D);
+       fpa_imm[1][fpa_four]  = new_tarval_from_str("4", 1, mode_D);
+       fpa_imm[1][fpa_five]  = new_tarval_from_str("5", 1, mode_D);
+       fpa_imm[1][fpa_ten]   = new_tarval_from_str("10", 2, mode_D);
+       fpa_imm[1][fpa_half]  = new_tarval_from_str("0.5", 3, mode_D);
+
+       fpa_imm[2][fpa_null]  = get_tarval_null(mode_E);
+       fpa_imm[2][fpa_one]   = get_tarval_one(mode_E);
+       fpa_imm[2][fpa_two]   = new_tarval_from_str("2", 1, mode_E);
+       fpa_imm[2][fpa_three] = new_tarval_from_str("3", 1, mode_E);
+       fpa_imm[2][fpa_four]  = new_tarval_from_str("4", 1, mode_E);
+       fpa_imm[2][fpa_five]  = new_tarval_from_str("5", 1, mode_E);
+       fpa_imm[2][fpa_ten]   = new_tarval_from_str("10", 2, mode_E);
+       fpa_imm[2][fpa_half]  = new_tarval_from_str("0.5", 3, mode_E);
 }
 
 /**
  * Transform a Firm graph into an ARM graph.
  */
 void arm_transform_graph(arm_code_gen_t *cg) {
+       static int imm_initialized = 0;
+
+       if (! imm_initialized) {
+               arm_init_fpa_immediate();
+               imm_initialized = 1;
+       }
        arm_register_transformers();
        env_cg = cg;
-       be_transform_graph(cg->birg, /*arm_pretransform_node*/ NULL, cg);
+       be_transform_graph(cg->birg, arm_pretransform_node, cg);
 }
 
 void arm_init_transform(void) {