Changed transformer to be like ia32: do a transform- and copy
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 15 Jun 2007 15:26:41 +0000 (15:26 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 15 Jun 2007 15:26:41 +0000 (15:26 +0000)
added some more isntructions, some fixes
at least HelloWorld compiles again :-)

[r14532]

ir/be/arm/arm_emitter.c
ir/be/arm/arm_map_regs.c
ir/be/arm/arm_map_regs.h
ir/be/arm/arm_new_nodes.c
ir/be/arm/arm_new_nodes.h
ir/be/arm/arm_nodes_attr.h
ir/be/arm/arm_spec.pl
ir/be/arm/arm_transform.c
ir/be/arm/arm_transform.h
ir/be/arm/bearch_arm.c
ir/be/arm/bearch_arm_t.h

index 868d349..c64480c 100644 (file)
@@ -20,7 +20,7 @@
 /**
  * @file
  * @brief   arm emitter
- * @author  Oliver Richter, Tobias Gneist
+ * @author  Oliver Richter, Tobias Gneist, Michael Beck
  * @version $Id$
  */
 #define SILENCER
@@ -823,6 +823,11 @@ static void emit_arm_fpaDbl2GP(arm_emit_env_t *env, const ir_node *irn) {
        be_emit_finish_line_gas(env->emit, irn);
 }
 
+static void emit_arm_LdTls(arm_emit_env_t *env, const ir_node *irn) {
+       panic("TLS not supported for this target\n");
+       /* Er... our gcc does not support it... Install a newer toolchain. */
+}
+
 /***********************************************************************************
  *                  _          __                                             _
  *                 (_)        / _|                                           | |
@@ -875,11 +880,11 @@ static void arm_register_emitters(void) {
        ARM_EMIT(SwitchJmp);
        ARM_EMIT(fpaDbl2GP);
        ARM_EMIT(fpaConst);
+       ARM_EMIT(LdTls);
 
        /* benode emitter */
        BE_EMIT(Call);
        BE_EMIT(IncSP);
-//     BE_EMIT(AddSP);
        BE_EMIT(Copy);
        BE_EMIT(Spill);
        BE_EMIT(Reload);
index be81948..19a3ff1 100644 (file)
@@ -78,51 +78,6 @@ void arm_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) {
 }
 
 const arch_register_t *arm_get_firm_reg(const ir_node *irn, set *reg_set) {
-       struct arm_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
+       const struct arm_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
        return assoc->reg;
 }
-
-
-
-/**
- * Translates the proj number into a "real" argument position for register
- * requirements depended on the predecessor.
- */
-long arm_translate_proj_pos(const ir_node *proj) {
-       ir_node *pred = get_Proj_pred(proj);
-       long nr       = get_Proj_proj(proj);
-
-       if (is_irn_machine_op(pred)) {
-               switch (get_arm_irn_opcode(pred)) {
-
-               case iro_arm_Loadb:
-               case iro_arm_Loadbs:
-               case iro_arm_Loadh:
-               case iro_arm_Loadhs:
-               case iro_arm_Load:
-               case iro_arm_fpaLdf:
-                       if (nr == pn_Load_res)
-                               return 0;
-                       assert(0 && "unsupported Proj(Load) number");
-                       break;
-               case iro_arm_Storeb:
-               case iro_arm_Storebs:
-               case iro_arm_Storeh:
-               case iro_arm_Storehs:
-               case iro_arm_Store:
-               case iro_arm_fpaStf:
-                       return 0;
-               case iro_arm_fpaDiv:
-               case iro_arm_fpaRdv:
-                       if (nr == pn_Quot_res)
-                               return 0;
-                       assert(0 && "there should be no more Projs for a fDiv");
-                       break;
-               default:
-                       break;
-               }
-       }
-
-//     assert(0 && "unsupported Proj(X)");
-       return nr;
-}
index 4a59c3a..6a79d84 100644 (file)
@@ -19,8 +19,8 @@
 
 /**
  * @file
- * @brief  declarations for arm register allocation
- * @author Oliver Richter, Tobias Gneist
+ * @brief  declarations for ARM register allocation
+ * @author Oliver Richter, Tobias Gneist, Michael Beck
  * @version $Id$
  */
 #ifndef FIRM_BE_ARM_ARM_MAP_REGS_H
@@ -38,6 +38,4 @@ int  arm_cmp_irn_reg_assoc(const void *a, const void *b, size_t len);
 void arm_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set);
 const arch_register_t *arm_get_firm_reg(const ir_node *irn, set *reg_set);
 
-long arm_translate_proj_pos(const ir_node *proj);
-
 #endif
index e1b6e1f..3a98f69 100644 (file)
@@ -416,6 +416,24 @@ const arch_register_t *get_arm_out_reg(const ir_node *node, int pos) {
        return attr->slots[pos];
 }
 
+/**
+ * Sets the flags for the n'th out.
+ */
+void set_arm_out_flags(ir_node *node, arch_irn_flags_t flags, int pos) {
+       arm_attr_t *attr = get_arm_attr(node);
+       assert(pos < ARR_LEN(attr->out_flags) && "Invalid OUT position.");
+       attr->out_flags[pos] = flags;
+}
+
+/**
+ * Gets the flags for the n'th out.
+ */
+arch_irn_flags_t get_arm_out_flags(const ir_node *node, int pos) {
+       const arm_attr_t *attr = get_arm_attr_const(node);
+       assert(pos < ARR_LEN(attr->out_flags) && "Invalid OUT position.");
+       return attr->out_flags[pos];
+}
+
 /**
  * Returns the number of results.
  */
@@ -525,6 +543,9 @@ void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t **
        attr->instr_fl         = (ARM_COND_AL << 3) | ARM_SHF_NONE;
        attr->value            = NULL;
 
+       attr->out_flags = NEW_ARR_D(int, obst, n_res);
+       memset(attr->out_flags, 0, n_res * sizeof(attr->out_flags[0]));
+
        attr->slots = NEW_ARR_D(const arch_register_t*, obst, n_res);
        memset((arch_register_t **)attr->slots, 0, n_res * sizeof(attr->slots[0]));
 }
@@ -668,7 +689,38 @@ static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b) {
        return 1;
 }
 
+/** copies the ARM attributes of a node. */
+static void arm_copy_attr(const ir_node *old_node, ir_node *new_node) {
+       ir_graph          *irg     = get_irn_irg(new_node);
+       struct obstack    *obst    = get_irg_obstack(irg);
+       const arm_attr_t *attr_old = get_arm_attr_const(old_node);
+       arm_attr_t       *attr_new = get_arm_attr(new_node);
+
+       /* copy the attributes */
+       memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
+
+       /* copy out flags */
+       attr_new->out_flags =
+               DUP_ARR_D(int, obst, attr_old->out_flags);
+       /* copy register assignments */
+       attr_new->slots =
+               DUP_ARR_D(arch_register_t*, obst, attr_old->slots);
+}
+
 
 
 /* Include the generated constructor functions */
 #include "gen_arm_new_nodes.c.inl"
+
+/**
+ * Registers the arm_copy_attr function for all ARM opcodes.
+ */
+void arm_register_copy_attr_func(void) {
+       int i;
+
+       for (i = get_irp_n_opcodes() - 1; i >= 0; --i) {
+               ir_op *op = get_irp_opcode(i);
+               if (is_arm_op(op))
+                       op->ops.copy_attr = arm_copy_attr;
+       }
+}
index 6fe6a7b..3116c2b 100644 (file)
@@ -140,6 +140,16 @@ int get_arm_n_res(const ir_node *node);
 void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** in_reqs,
                          const arch_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency);
 
+/**
+ * Sets the flags for the n'th out.
+ */
+void set_arm_out_flags(ir_node *node, arch_irn_flags_t flags, int pos);
+
+/**
+ * Gets the flags for the n'th out.
+ */
+arch_irn_flags_t get_arm_out_flags(const ir_node *node, int pos);
+
 /**
  * Returns the tarval
  */
@@ -196,6 +206,11 @@ arm_shift_modifier get_arm_shift_modifier(const ir_node *node);
  */
 unsigned int arm_decode_imm_w_shift(tarval *tv);
 
+/**
+ * Registers the arm_copy_attr function for all ARM opcodes.
+ */
+void arm_register_copy_attr_func(void);
+
 /* Include the generated headers */
 #include "gen_arm_new_nodes.h"
 
index ae98d1a..8a0ace3 100644 (file)
@@ -82,16 +82,17 @@ typedef enum _arm_condition {
 
 /** Generic ARM node attributes. */
 typedef struct _arm_attr_t {
-       arch_irn_flags_t flags;             /**< indicating if spillable, rematerializeable ... etc. */
+       arch_irn_flags_t flags;              /**< indicating if spillable, rematerializeable ... etc. */
 
        const arch_register_req_t **in_req;  /**< register requirements for arguments */
        const arch_register_req_t **out_req; /**< register requirements for results */
 
-       ir_mode *op_mode;                   /**< operation mode if different from node's mode */
-       unsigned instr_fl;                  /**< condition code, shift modifier */
-       tarval *value;                      /**< immediate */
+       ir_mode  *op_mode;                   /**< operation mode if different from node's mode */
+       unsigned instr_fl;                   /**< condition code, shift modifier */
+       tarval   *value;                     /**< immediate */
+       int      *out_flags;                 /**< flags for each produced value */
 
-       const arch_register_t **slots;      /**< register slots for assigned registers */
+       const arch_register_t **slots;       /**< register slots for assigned registers */
 } arm_attr_t;
 
 /** Attributes for a SymConst */
index ae90b2d..c1d510c 100644 (file)
@@ -472,6 +472,9 @@ Abs => {
 
 # other operations
 
+#
+# this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
+#
 EmptyReg => {
   op_flags  => "c",
   irn_flags => "R",
@@ -490,7 +493,10 @@ CopyB => {
   op_flags => "F|H",
   state    => "pinned",
   comment  => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
+  attr      => "tarval *tv",
+  init_attr => 'attr->value = tv;',
   reg_req  => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
+  outs     => [ "M" ],
 },
 
 SymConst => {
@@ -586,16 +592,6 @@ Storeb => {
   outs      => [ "M" ],
 },
 
-Storebs => {
-  op_flags  => "L|F",
-  irn_flags => "R",
-  state     => "exc_pinned",
-  comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
-  reg_req   => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
-  emit      => '. strsb %S1, [%S0, #0]',
-  outs      => [ "M" ],
-},
-
 Storeh => {
   op_flags  => "L|F",
   irn_flags => "R",
@@ -606,16 +602,6 @@ Storeh => {
   outs      => [ "M" ],
 },
 
-Storehs => {
-  op_flags  => "L|F",
-  irn_flags => "R",
-  state     => "exc_pinned",
-  comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
-  reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
-  emit      => '. strhs %S1, [%S0, #0]',
-  outs      => [ "M" ],
-},
-
 Store => {
   op_flags  => "L|F",
   irn_flags => "R",
@@ -716,26 +702,38 @@ fpaRsb => {
 
 fpaDiv => {
   comment   => "construct FPA Div: Div(a, b) = a / b",
-  reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  attr      => "ir_mode *op_mode",
+  init_attr => "attr->op_mode = op_mode;",
+  reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
   emit      =>'. dvf%M %D0, %S0, %S1',
+  outs      => [ "res", "M" ],
 },
 
 fpaRdv => {
   comment   => "construct FPA reverse Div: Div(a, b) = b / a",
-  reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  attr      => "ir_mode *op_mode",
+  init_attr => "attr->op_mode = op_mode;",
+  reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
   emit      =>'. rdf%M %D0, %S0, %S1',
+  outs      => [ "res", "M" ],
 },
 
 fpaFDiv => {
   comment   => "construct FPA Fast Div: Div(a, b) = a / b",
-  reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  attr      => "ir_mode *op_mode",
+  init_attr => "attr->op_mode = op_mode;",
+  reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
   emit      =>'. fdv%M %D0, %S0, %S1',
+  outs      => [ "res", "M" ],
 },
 
 fpaFRdv => {
   comment   => "construct FPA Fast reverse Div: Div(a, b) = b / a",
-  reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+  attr      => "ir_mode *op_mode",
+  init_attr => "attr->op_mode = op_mode;",
+  reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
   emit      =>'. frd%M %D0, %S0, %S1',
+  outs      => [ "res", "M" ],
 },
 
 fpaMov => {
@@ -810,6 +808,29 @@ fpaDbl2GP => {
   outs      => [ "low", "high", "M" ],
 },
 
+AddSP => {
+  irn_flags => "I",
+  comment   => "construct Add to stack pointer",
+  reg_req   => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] },
+  emit      => '. add %D0, %S0, %S1',
+  outs      => [ "stack:S", "M" ],
+},
+
+SubSP => {
+  irn_flags => "I",
+  comment   => "construct Sub from stack pointer",
+  reg_req   => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] },
+  emit      => '. sub %D0, %S0, %S1',
+  outs      => [ "stack:S", "M" ],
+},
+
+LdTls => {
+  irn_flags => "R",
+  comment   => "load the TLS address",
+  reg_req   => { out => [ "gp" ] },
+},
+
+
 #
 # floating point constants
 #
index 21e2877..5c11cd4 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "../benode_t.h"
 #include "../beirg_t.h"
+#include "../betranshlp.h"
 #include "bearch_arm_t.h"
 
 #include "arm_nodes_attr.h"
 #include <limits.h>
 
 
-extern ir_op *get_op_Mulh(void);
+/** hold the current code generator during transformation */
+static arm_code_gen_t *env_cg;
 
+extern ir_op *get_op_Mulh(void);
 
 
 /****************************************************************************************************
@@ -69,6 +72,10 @@ 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);
+}
+
 typedef struct vals_ {
        int ops;
        unsigned char values[4];
@@ -81,7 +88,7 @@ static unsigned do_rol(unsigned v, unsigned rol) {
 }
 
 /**
- * construct 8bit values und rot amounts for a value
+ * construct 8bit values and rot amounts for a value
  */
 static void gen_vals_from_word(unsigned int value, vals *result)
 {
@@ -125,9 +132,14 @@ 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_node *res = new_rd_arm_Mov_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv);
+       tarval   *tv   = new_tarval_from_long(value, mode_Iu);
+       dbg_info *dbg  = get_irn_dbg_info(irn);
+       ir_mode  *mode = get_irn_mode(irn);
+       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));
        return res;
@@ -137,9 +149,14 @@ static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *bloc
  * 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_node *res = new_rd_arm_Mvn_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv);
+       tarval   *tv   = new_tarval_from_long(value, mode_Iu);
+       dbg_info *dbg  = get_irn_dbg_info(irn);
+       ir_mode  *mode = get_irn_mode(irn);
+       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 */
        return res;
@@ -177,6 +194,9 @@ static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_nod
        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]));
@@ -206,7 +226,16 @@ 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) {
-       int value = get_tarval_long(get_Const_tarval(irn));
+       tarval  *tv = get_Const_tarval(irn);
+       ir_mode *mode = get_tarval_mode(tv);
+       int     value;
+
+       if (mode_is_reference(mode)) {
+               /* ARM is 32bit, so we can safely convert a reference tarval into Iu */
+               assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Iu));
+               tv = tarval_convert_to(tv, mode_Iu);
+       }
+       value = get_tarval_long(tv);
        return create_const_graph_value(abi, irn, block, value);
 }
 
@@ -219,7 +248,7 @@ static ir_node *gen_arm_Const(ir_node *irn, ir_node *block, arm_code_gen_t *cg)
        dbg_info *dbg = get_irn_dbg_info(irn);
 
        if (mode_is_float(mode)) {
-               cg->have_fp = 1;
+               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 */
@@ -230,8 +259,6 @@ static ir_node *gen_arm_Const(ir_node *irn, ir_node *block, arm_code_gen_t *cg)
                        assert(mode != mode_E && "IEEE Extended FP not supported");
                assert(0 && "NYI");
        }
-       else if (mode_is_reference(mode))
-               return irn;
        return create_const_graph(cg->birg->abi, irn, block);
 }
 
@@ -257,106 +284,110 @@ static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op,
 /**
  * Transforms a Conv node.
  *
- * @param env   The transformation environment
- * @return the created arm Conv node
+ * @return The created ia32 Conv node
  */
-static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) {
-       ir_graph *irg = current_ir_graph;
-       ir_node *block   = get_nodes_block(irn);
-       ir_node *op      = get_Conv_op(irn);
-       ir_mode *in_mode = get_irn_mode(op);
-       ir_mode *out_mode = get_irn_mode(irn);
-       dbg_info *dbg    = get_irn_dbg_info(irn);
-
-       if (in_mode == out_mode)
-               return op;
-
-       if (mode_is_float(in_mode) || mode_is_float(out_mode)) {
-               cg->have_fp = 1;
-
-               if (USE_FPA(cg->isa)) {
-                       if (mode_is_float(in_mode)) {
-                               if (mode_is_float(out_mode)) {
+static ir_node *gen_Conv(ir_node *node) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *op       = get_Conv_op(node);
+       ir_node  *new_op   = be_transform_node(op);
+       ir_graph *irg      = current_ir_graph;
+       ir_mode  *src_mode = get_irn_mode(op);
+       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;
+
+       if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
+               env_cg->have_fp_insn = 1;
+
+               if (USE_FPA(env_cg->isa)) {
+                       if (mode_is_float(src_mode)) {
+                               if (mode_is_float(dst_mode)) {
                                        /* from float to float */
-                                       return new_rd_arm_fpaMov(dbg, irg, block, op, out_mode);
+                                       return new_rd_arm_fpaMov(dbg, irg, block, new_op, dst_mode);
                                }
                                else {
                                        /* from float to int */
-                                       return new_rd_arm_fpaFix(dbg, irg, block, op, out_mode);
+                                       return new_rd_arm_fpaFix(dbg, irg, block, new_op, dst_mode);
                                }
                        }
                        else {
                                /* from int to float */
-                               return new_rd_arm_fpaFlt(dbg, irg, block, op, out_mode);
+                               return new_rd_arm_fpaFlt(dbg, irg, block, new_op, dst_mode);
                        }
                }
-               assert(0 && "NYI");
+               else {
+                       panic("VFP not supported yet\n");
+                       return NULL;
+               }
        }
        else { /* complete in gp registers */
-               int in_bits  = get_mode_size_bits(in_mode);
-               int out_bits = get_mode_size_bits(out_mode);
-               int in_sign  = get_mode_sign(in_mode);
-               int out_sign = get_mode_sign(out_mode);
-
-               // 32 -> 32
-                       // NOPpen
-               if (in_bits == out_bits && in_bits == 32)
-                       return op;
-
-               // 16 -> 16
-                       // unsigned -> unsigned
-                               // NOP
-                       // unsigned -> signed
-                               // sign extension (31:16)=(15)
-                       // signed -> unsigned
-                               // maskieren (31:16)=0
-                       // signed -> signed
-                               // NOP
-               if (in_bits == out_bits && out_bits < 32) {
-                       if (in_sign && !out_sign) {
-                               return gen_mask(cg->birg->abi, irn, op, out_bits);
+               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);
+
+               if (src_bits == dst_bits) {
+                       /* kill 32 -> 32 convs */
+                       if (src_bits == 32) {
+                               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 {
-                               return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
+                               panic("Cannot handle mode %+F with %d bits\n", dst_mode, dst_bits);
+                               return NULL;
                        }
                }
-
-               // 16 -> 32
-                       // unsigned -> unsigned
-                               // NOP
-                       // unsigned -> signed
-                               // NOP
-                       // signed -> unsigned
-                               // sign extension (31:16)=(15)
-                       // signed -> signed
-                               // sign extension (31:16)=(15)
-               if (in_bits < out_bits) {
-                       if (in_sign) {
-                               return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
+               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);
                        } else {
-                               return op;
+                               return new_op;
                        }
                }
-
-               // 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 (in_bits > out_bits) {
-                       if (in_sign && out_sign) {
-                               return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
+               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);
                        } else {
-                               return gen_mask(cg->birg->abi, irn, op, out_bits);
+                               return gen_mask(env_cg->birg->abi, node, new_op, dst_bits);
                        }
                }
-               assert(0 && "recheck integer conversion logic!");
-               return irn;
        }
-       return NULL;
 }
 
 /**
@@ -378,492 +409,517 @@ static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
 }
 
 /**
- * Creates an arm Add.
+ * Creates an ARM Add.
  *
- * @param env   The transformation environment
  * @return the created arm Add node
  */
-static ir_node *gen_Add(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op1 = get_Add_left(irn);
-       ir_node *op2 = get_Add_right(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       ir_graph *irg = current_ir_graph;
-       ir_node *op3;
+static ir_node *gen_Add(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_Add_left(node);
+       ir_node  *new_op1 = be_transform_node(op1);
+       ir_node  *op2     = get_Add_right(node);
+       ir_node  *new_op2 = be_transform_node(op2);
+       ir_mode  *mode    = get_irn_mode(node);
+       ir_graph *irg     = current_ir_graph;
+       ir_node  *new_op3;
        int v;
        arm_shift_modifier mod;
-       dbg_info *dbg = get_irn_dbg_info(irn);
+       dbg_info *dbg = get_irn_dbg_info(node);
 
        if (mode_is_float(mode)) {
-               cg->have_fp = 1;
-               if (USE_FPA(cg->isa))
-                       return new_rd_arm_fpaAdd(dbg, irg, block, op1, op2, mode);
-               else if (USE_VFP(cg->isa)) {
+               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)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
+                       panic("VFP not supported yet\n");
+                       return NULL;
                }
-               assert(0 && "NYI");
-       }
-       if (mode_is_numP(mode)) {
-               if (is_arm_Mov_i(op1))
-                       return new_rd_arm_Add_i(dbg, irg, block, op2, mode, get_arm_value(op1));
-               if (is_arm_Mov_i(op2))
-                       return new_rd_arm_Add_i(dbg, irg, block, op1, mode, get_arm_value(op2));
+               else {
+                       panic("Softfloat not supported yet\n");
+                       return NULL;
+               }
+       } else {
+               assert(mode_is_numP(mode));
+
+               if (is_arm_Mov_i(new_op1))
+                       return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_value(op1));
+               if (is_arm_Mov_i(new_op2))
+                       return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_value(op2));
 
                /* check for MLA */
-               if (is_arm_Mul(op1) && get_irn_n_edges(op1) == 1) {
-                       op3 = op2;
-                       op2 = get_irn_n(op1, 1);
-                       op1 = get_irn_n(op1, 0);
+               if (is_arm_Mul(new_op1) && get_irn_n_edges(new_op1) == 1) {
+                       new_op3 = new_op2;
+                       op2 = get_irn_n(new_op1, 1);
+                       op1 = get_irn_n(new_op1, 0);
 
-                       return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
+                       return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode);
                }
-               if (is_arm_Mul(op2) && get_irn_n_edges(op2) == 1) {
-                       op3 = op1;
-                       op1 = get_irn_n(op2, 0);
-                       op2 = get_irn_n(op2, 1);
+               if (is_arm_Mul(new_op2) && get_irn_n_edges(new_op2) == 1) {
+                       new_op3 = new_op1;
+                       new_op1 = get_irn_n(new_op2, 0);
+                       new_op2 = get_irn_n(new_op2, 1);
 
-                       return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
+                       return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode);
                }
 
                /* is the first a shifter */
-               v = is_shifter_operand(op1, &mod);
+               v = is_shifter_operand(new_op1, &mod);
                if (v) {
-                       op1 = get_irn_n(op1, 0);
-                       return new_rd_arm_Add(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
+                       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));
                }
                /* is the second a shifter */
-               v = is_shifter_operand(op2, &mod);
+               v = is_shifter_operand(new_op2, &mod);
                if (v) {
-                       op2 = get_irn_n(op2, 0);
-                       return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu));
+                       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));
                }
 
                /* normal ADD */
-               return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
+               return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL);
        }
-
-       assert(0 && "unknown mode for add");
-       return NULL;
 }
 
 /**
- * Creates an arm Mul.
+ * Creates an ARM Mul.
  *
- * @param env   The transformation environment
  * @return the created arm Mul node
  */
-static ir_node *gen_Mul(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op1 = get_Mul_left(irn);
-       ir_node *op2 = get_Mul_right(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       ir_graph *irg = current_ir_graph;
-       dbg_info *dbg = get_irn_dbg_info(irn);
+static ir_node *gen_Mul(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_Mul_left(node);
+       ir_node  *new_op1 = be_transform_node(op1);
+       ir_node  *op2     = get_Mul_right(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);
 
        if (mode_is_float(mode)) {
-               cg->have_fp = 1;
-               if (USE_FPA(cg->isa))
-                       return new_rd_arm_fpaMul(dbg, irg, block, op1, op2, mode);
-               else if (USE_VFP(cg->isa)) {
+               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);
+               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;
                }
-               assert(0 && "NYI");
        }
-       return new_rd_arm_Mul(dbg, irg, block, op1, op2, mode);
+       return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode);
 }
 
 /**
- * Creates an arm floating point Div.
+ * Creates an ARM floating point Div.
  *
  * @param env   The transformation environment
  * @return the created arm fDiv node
  */
-static ir_node *gen_Quot(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op1 = get_Quot_left(irn);
-       ir_node *op2 = get_Quot_right(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       dbg_info *dbg = get_irn_dbg_info(irn);
+static ir_node *gen_Quot(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_Quot_left(node);
+       ir_node  *new_op1 = be_transform_node(op1);
+       ir_node  *op2     = get_Quot_right(node);
+       ir_node  *new_op2 = be_transform_node(op2);
+       ir_mode  *mode    = get_irn_mode(node);
+       dbg_info *dbg     = get_irn_dbg_info(node);
 
        assert(mode != mode_E && "IEEE Extended FP not supported");
 
-       cg->have_fp = 1;
-       if (USE_FPA(cg->isa))
+       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(cg->isa)) {
+       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;
        }
-       assert(0 && "NYI");
-
-       return NULL;
 }
 
 #define GEN_INT_OP(op) \
-static ir_node *gen_ ## op(ir_node *irn, arm_code_gen_t *cg) { \
-       ir_graph *irg = current_ir_graph; \
-       ir_node *block = get_nodes_block(irn); \
-       ir_node *op1 = get_ ## op ## _left(irn); \
-       ir_node *op2 = get_ ## op ## _right(irn); \
-       int v; \
+       ir_node  *block   = be_transform_node(get_nodes_block(node)); \
+       ir_node  *op1     = get_ ## op ## _left(node); \
+       ir_node  *new_op1 = be_transform_node(op1); \
+       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); \
+       dbg_info *dbg     = get_irn_dbg_info(node); \
+       int      v; \
        arm_shift_modifier mod; \
-       ir_mode *mode = get_irn_mode(irn); \
-       dbg_info *dbg = get_irn_dbg_info(irn); \
  \
-       if (is_arm_Mov_i(op1)) \
-               return new_rd_arm_ ## op ## _i(dbg, irg, block, op2, mode, get_arm_value(op1)); \
-       if (is_arm_Mov_i(op2)) \
-               return new_rd_arm_ ## op ## _i(dbg, irg, block, op1, mode, get_arm_value(op2)); \
+       if (is_arm_Mov_i(new_op1)) \
+               return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_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)); \
        /* is the first a shifter */ \
-       v = is_shifter_operand(op1, &mod); \
+       v = is_shifter_operand(new_op1, &mod); \
        if (v) { \
-               op1 = get_irn_n(op1, 0); \
-               return new_rd_arm_ ## op(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \
+               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)); \
        } \
        /* is the second a shifter */ \
-       v = is_shifter_operand(op2, &mod); \
+       v = is_shifter_operand(new_op2, &mod); \
        if (v) { \
-               op2 = get_irn_n(op2, 0); \
-               return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \
+               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)); \
        } \
        /* Normal op */ \
-       return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL); \
-}
-
+       return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL) \
 
 /**
- * Creates an arm And.
+ * Creates an ARM And.
  *
- * @param env   The transformation environment
  * @return the created arm And node
  */
-static ir_node *gen_And(ir_node *irn, arm_code_gen_t *cg);
-GEN_INT_OP(And)
+static ir_node *gen_And(ir_node *node) {
+       GEN_INT_OP(And);
+}
 
 /**
- * Creates an arm Orr.
+ * Creates an ARM Orr.
  *
  * @param env   The transformation environment
  * @return the created arm Or node
  */
-static ir_node *gen_Or(ir_node *irn, arm_code_gen_t *cg);
-GEN_INT_OP(Or)
+static ir_node *gen_Or(ir_node *node) {
+       GEN_INT_OP(Or);
+}
 
 /**
- * Creates an arm Eor.
+ * Creates an ARM Eor.
  *
- * @param env   The transformation environment
  * @return the created arm Eor node
  */
-static ir_node *gen_Eor(ir_node *irn, arm_code_gen_t *cg);
-GEN_INT_OP(Eor)
+static ir_node *gen_Eor(ir_node *node) {
+       GEN_INT_OP(Eor);
+}
 
 /**
- * Creates an arm Sub.
+ * Creates an ARM Sub.
  *
- * @param env   The transformation environment
  * @return the created arm Sub node
  */
-static ir_node *gen_Sub(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op1 = get_Sub_left(irn);
-       ir_node *op2 = get_Sub_right(irn);
-       int v;
+static ir_node *gen_Sub(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(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_mode  *mode    = get_irn_mode(node);
+       ir_graph *irg     = current_ir_graph;
+       dbg_info *dbg     = get_irn_dbg_info(node);
+       int      v;
        arm_shift_modifier mod;
-       ir_mode *mode = get_irn_mode(irn);
-       ir_graph *irg = current_ir_graph;
-       dbg_info *dbg = get_irn_dbg_info(irn);
 
        if (mode_is_float(mode)) {
-               cg->have_fp = 1;
-               if (USE_FPA(cg->isa))
-                       return new_rd_arm_fpaSub(dbg, irg, block, op1, op2, mode);
-               else if (USE_VFP(cg->isa)) {
+               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)) {
                        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(0 && "NYI");
        }
-       if (mode_is_numP(mode)) {
-               if (is_arm_Mov_i(op1))
-                       return new_rd_arm_Rsb_i(dbg, irg, block, op2, mode, get_arm_value(op1));
-               if (is_arm_Mov_i(op2))
-                       return new_rd_arm_Sub_i(dbg, irg, block, op1, mode, get_arm_value(op2));
+       else {
+               assert(mode_is_numP(mode) && "unknown mode for Sub");
+
+               if (is_arm_Mov_i(new_op1))
+                       return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_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));
 
                /* is the first a shifter */
-               v = is_shifter_operand(op1, &mod);
+               v = is_shifter_operand(new_op1, &mod);
                if (v) {
-                       op1 = get_irn_n(op1, 0);
-                       return new_rd_arm_Rsb(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
+                       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));
                }
                /* is the second a shifter */
-               v = is_shifter_operand(op2, &mod);
+               v = is_shifter_operand(new_op2, &mod);
                if (v) {
-                       op2 = get_irn_n(op2, 0);
-                       return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu));
+                       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));
                }
                /* normal sub */
-               return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
+               return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, NULL);
        }
-       assert(0 && "unknown mode for sub");
-       return NULL;
 }
 
 /**
- * Creates an arm Shl.
+ * Creates an ARM Shl.
  *
- * @param env   The transformation environment
- * @return the created arm Shl node
+ * @return the created ARM Shl node
  */
-static ir_node *gen_Shl(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *result;
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op1 = get_Shl_left(irn);
-       ir_node *op2 = get_Shl_right(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       ir_graph *irg = current_ir_graph;
-       dbg_info *dbg = get_irn_dbg_info(irn);
-
-       if (is_arm_Mov_i(op2)) {
-               result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSL, get_arm_value(op2));
-       } else {
-               result = new_rd_arm_Shl(dbg, irg, block, op1, op2, mode);
+static ir_node *gen_Shl(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_Shl_left(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);
+       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 result;
+       return new_rd_arm_Shl(dbg, current_ir_graph, block, new_op1, new_op2, mode);
 }
 
 /**
- * Creates an arm Shr.
+ * Creates an ARM Shr.
  *
- * @param env   The transformation environment
- * @return the created arm Shr node
+ * @return the created ARM Shr node
  */
-static ir_node *gen_Shr(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *result;
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op1 = get_Shr_left(irn);
-       ir_node *op2 = get_Shr_right(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       ir_graph *irg = current_ir_graph;
-       dbg_info *dbg = get_irn_dbg_info(irn);
-
-       if (is_arm_Mov_i(op2)) {
-               result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSR, get_arm_value(op2));
-       } else {
-               result = new_rd_arm_Shr(dbg, irg, block, op1, op2, mode);
+static ir_node *gen_Shr(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_Shr_left(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);
+       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 result;
+       return new_rd_arm_Shr(dbg, current_ir_graph, block, new_op1, new_op2, mode);
 }
 
 /**
- * Creates an arm Shrs.
+ * Creates an ARM Shrs.
  *
- * @param env   The transformation environment
- * @return the created arm Shrs node
+ * @return the created ARM Shrs node
  */
-static ir_node *gen_Shrs(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *result;
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op1 = get_Shrs_left(irn);
-       ir_node *op2 = get_Shrs_right(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       dbg_info *dbg = get_irn_dbg_info(irn);
-
-       if (is_arm_Mov_i(op2)) {
-               result = new_rd_arm_Mov(dbg, current_ir_graph, block, op1, mode, ARM_SHF_ASR, get_arm_value(op2));
-       } else {
-               result = new_rd_arm_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
+static ir_node *gen_Shrs(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_Shrs_left(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);
+       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 result;
+       return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode);
 }
 
 /**
  * Transforms a Not node.
  *
- * @param env   The transformation environment
- * @return the created arm Not node
+ * @return the created ARM Not node
  */
-static ir_node *gen_Not(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op = get_Not_op(irn);
-       int v;
+static ir_node *gen_Not(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(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;
        arm_shift_modifier mod = ARM_SHF_NONE;
-       tarval  *tv = NULL;
-       dbg_info *dbg = get_irn_dbg_info(irn);
+       int      v        = is_shifter_operand(new_op, &mod);
 
-       v = is_shifter_operand(op, &mod);
        if (v) {
-               op = get_irn_n(op, 0);
+               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, op, get_irn_mode(irn), mod, tv);
+       return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, get_irn_mode(node), mod, tv);
 }
 
 /**
  * Transforms an Abs node.
  *
  * @param env   The transformation environment
- * @return the created arm Abs node
+ * @return the created ARM Abs node
  */
-static ir_node *gen_Abs(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op = get_Abs_op(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       dbg_info *dbg = get_irn_dbg_info(irn);
+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  *new_op  = be_transform_node(op);
+       dbg_info *dbg     = get_irn_dbg_info(node);
+       ir_mode  *mode    = get_irn_mode(node);
 
        if (mode_is_float(mode)) {
-               cg->have_fp = 1;
-               if (USE_FPA(cg->isa))
-                       return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, op, mode);
-               else if (USE_VFP(cg->isa)) {
+               env_cg->have_fp_insn = 1;
+               if (USE_FPA(env_cg->isa))
+                       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");
                }
-               assert(0 && "NYI");
        }
-       return new_rd_arm_Abs(dbg, current_ir_graph, block, op, mode);
+       return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode);
 }
 
 /**
  * Transforms a Minus node.
  *
- * @param env   The transformation environment
- * @return the created arm Minus node
+ * @return the created ARM Minus node
  */
-static ir_node *gen_Minus(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_node *op = get_Minus_op(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       ir_graph *irg = current_ir_graph;
-       dbg_info *dbg = get_irn_dbg_info(irn);
+static ir_node *gen_Minus(ir_node *node) {
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op      = get_Minus_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);
 
        if (mode_is_float(mode)) {
-               cg->have_fp = 1;
-               if (USE_FPA(cg->isa))
-                       return new_rd_arm_fpaMnv(dbg, irg, block, op, mode);
-               else if (USE_VFP(cg->isa)) {
+               env_cg->have_fp_insn = 1;
+               if (USE_FPA(env_cg->isa))
+                       return new_rd_arm_fpaMnv(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");
                }
-               assert(0 && "NYI");
        }
-       return new_rd_arm_Rsb_i(dbg, irg, block, op, mode, get_mode_null(mode));
+       return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode));
 }
 
 /**
  * Transforms a Load.
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Load node
- * @param mode    node mode
- * @return the created arm Load node
+ * @return the created ARM Load node
  */
-static ir_node *gen_Load(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_mode *mode = get_Load_mode(irn);
-       ir_graph *irg = current_ir_graph;
-       dbg_info *dbg = get_irn_dbg_info(irn);
+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);
 
        if (mode_is_float(mode)) {
-               cg->have_fp = 1;
-               if (USE_FPA(cg->isa))
-                       return new_rd_arm_fpaLdf(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn),
-                               get_Load_mode(irn));
-               else if (USE_VFP(cg->isa)) {
+               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);
+               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;
                }
-               assert(0 && "NYI");
-       }
-       if (mode == mode_Bu) {
-               return new_rd_arm_Loadb(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
-       }
-       if (mode == mode_Bs) {
-               return new_rd_arm_Loadbs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
-       }
-       if (mode == mode_Hu) {
-               return new_rd_arm_Loadh(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
-       }
-       if (mode == mode_Hs) {
-               return new_rd_arm_Loadhs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
        }
-       if (mode_is_reference(mode)) {
-               return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
+       else {
+               assert(mode_is_numP(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);
+                       case 16:
+                               return new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem);
+                       case 32:
+                               break;
+                       default:
+                               assert(!"mode size not supported");
+                       }
+               } else {
+                       /* zero extended loads */
+                       switch (get_mode_size_bits(mode)) {
+                       case 8:
+                               return new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem);
+                       case 16:
+                               return new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem);
+                       case 32:
+                               break;
+                       default:
+                               assert(!"mode size not supported");
+                       }
+               }
+               return new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
        }
-       return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
 }
 
 /**
  * Transforms a Store.
  *
- * @param mod     the debug module
- * @param block   the block the new node should belong to
- * @param node    the ir Store node
- * @param mode    node mode
- * @return the created arm Store node
+ * @return the created ARM Store node
  */
-static ir_node *gen_Store(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_mode *mode = get_irn_mode(get_Store_value(irn));
-       ir_graph *irg = current_ir_graph;
-       dbg_info *dbg = get_irn_dbg_info(irn);
+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);
 
-       assert(mode != mode_E && "IEEE Extended FP not supported");
        if (mode_is_float(mode)) {
-               cg->have_fp = 1;
-               if (USE_FPA(cg->isa))
-                       return new_rd_arm_fpaStf(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn),
-                               get_Store_mem(irn), get_irn_mode(get_Store_value(irn)));
-               else if (USE_VFP(cg->isa)) {
+               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);
+               else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
+                       assert(0 && "NYI");
                }
-               assert(0 && "NYI");
        }
-       if (mode == mode_Bu) {
-               return new_rd_arm_Storeb(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
-       }
-       if (mode == mode_Bs) {
-               return new_rd_arm_Storebs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
-       }
-       if (mode == mode_Hu) {
-               return new_rd_arm_Storeh(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
-       }
-       if (mode == mode_Hs) {
-               return new_rd_arm_Storehs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
+
+       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);
        }
-       return new_rd_arm_Store(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
 }
 
-
-static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *result   = NULL;
-       ir_node *selector = get_Cond_selector(irn);
-       ir_node *block    = get_nodes_block(irn);
-       ir_graph *irg     = current_ir_graph;
-       dbg_info *dbg     = get_irn_dbg_info(irn);
-
-       if ( get_irn_mode(selector) == mode_b ) {
-               //CondJmp
-               ir_node *proj_node = get_Cond_selector(irn);
-               ir_node *cmp_node = get_Proj_pred(proj_node);
-               ir_node *op1 = get_Cmp_left(cmp_node);
-               ir_node *op2 = get_Cmp_right(cmp_node);
-               result = new_rd_arm_CondJmp(dbg, irg, block, op1, op2, get_Proj_proj(proj_node));
+/**
+ * Transforms a Cond.
+ *
+ * @return the created ARM Cond node
+ */
+static ir_node *gen_Cond(ir_node *node) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *selector = get_Cond_selector(node);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbg      = get_irn_dbg_info(node);
+       ir_mode  *mode     = get_irn_mode(selector);
+
+       if (mode == mode_b) {
+               /* CondJmp */
+               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));
        } else {
-               //SwitchJmp
-               ir_node *op = get_irn_n(irn, 0);
+               /* SwitchJmp */
+               ir_node *new_op = be_transform_node(selector);
                ir_node *const_graph;
                ir_node *sub;
-               ir_node *const_node;
 
                ir_node *proj;
                const ir_edge_t *edge;
                int min = INT_MAX;
                int max = INT_MIN;
                int translation;
-               int norm_max;
-               int norm_min;
                int pn;
                int n_projs;
-               ir_node **projs;
 
-               foreach_out_edge(irn, edge) {
+               foreach_out_edge(node, edge) {
                        proj = get_edge_src_irn(edge);
                        assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
 
@@ -873,14 +929,9 @@ static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) {
                        max = pn>max ? pn : max;
                }
                translation = min;
-               norm_max = max - translation;
-               norm_min = min - translation;
+               n_projs = max - translation + 1;
 
-               n_projs = norm_max + 1;
-               projs = xcalloc(n_projs , sizeof(ir_node*));
-
-
-               foreach_out_edge(irn, edge) {
+               foreach_out_edge(node, edge) {
                        proj = get_edge_src_irn(edge);
                        assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
 
@@ -889,13 +940,10 @@ static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) {
                }
 
 
-               const_node  = new_rd_Const(dbg, irg, block, mode_Iu, new_tarval_from_long(translation, mode_Iu));
-               const_graph = create_const_graph(cg->birg->abi, const_node, block);
-               sub = new_rd_arm_Sub(dbg, irg, block, op, const_graph, get_irn_mode(op), ARM_SHF_NONE, NULL);
-               result = new_rd_arm_SwitchJmp(dbg, irg, block, sub,
-                       n_projs, get_Cond_defaultProj(irn)-translation);
+               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);
+               return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation);
        }
-       return result;
 }
 
 /**
@@ -923,47 +971,64 @@ static ident *get_sc_ident(ir_node *symc) {
 }
 
 /**
- * Transforms a SymConst node.
+ * Transforms a Const node.
+ *
+ * @return The transformed ARM node.
  */
-static ir_node *gen_SymConst(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block = get_nodes_block(irn);
-       ir_mode *mode = get_irn_mode(irn);
-       dbg_info *dbg = get_irn_dbg_info(irn);
-       return new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(irn));
-}
+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);
 
+       return create_const_graph(env_cg->birg->abi, node, block);
+}
 
 
 /**
- * Transforms a CopyB node.
+ * Transforms a SymConst node.
  *
- * @param env   The transformation environment
- * @return The transformed node.
+ * @return The transformed ARM node.
  */
-static ir_node *gen_CopyB(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node  *res   = NULL;
-       dbg_info *dbg   = get_irn_dbg_info(irn);
-       ir_mode  *mode  = get_irn_mode(irn);
-       ir_node  *src   = get_CopyB_src(irn);
-       ir_node  *dst   = get_CopyB_dst(irn);
-       ir_node  *mem   = get_CopyB_mem(irn);
-       ir_node  *block = get_nodes_block(irn);
-       int       size  = get_type_size_bytes(get_CopyB_type(irn));
-       ir_graph *irg   = current_ir_graph;
-       ir_node *src_copy;
-       ir_node *dst_copy;
-
-       src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, src);
-       dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, dst);
-
-       res = new_rd_arm_CopyB( dbg, irg, block, dst_copy, src_copy, 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, mode);
-       set_arm_value(res, new_tarval_from_long(size, mode_Iu));
-
+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);
+       dbg_info *dbg   = get_irn_dbg_info(node);
+       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 */
        return res;
 }
 
-
-
+/**
+ * Transforms a CopyB node.
+ *
+ * @return The transformed ARM node.
+ */
+static ir_node *gen_CopyB(ir_node *node) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *src      = get_CopyB_src(node);
+       ir_node  *new_src  = be_transform_node(src);
+       ir_node  *dst      = get_CopyB_dst(node);
+       ir_node  *new_dst  = be_transform_node(dst);
+       ir_node  *mem      = get_CopyB_mem(node);
+       ir_node  *new_mem  = be_transform_node(mem);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbg      = get_irn_dbg_info(node);
+       int      size      = get_type_size_bytes(get_CopyB_type(node));
+       ir_node  *src_copy;
+       ir_node  *dst_copy;
+
+       src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, new_src);
+       dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, new_dst);
+
+       return new_rd_arm_CopyB(dbg, irg, block, dst_copy, src_copy,
+                       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));
+}
 
 
 /********************************************
@@ -994,9 +1059,9 @@ static int get_sp_expand_offset(ir_node *inc_sp) {
 }
 
 #if 0
-static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
+static ir_node *gen_StackParam(ir_node *irn) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
        ir_node   *new_op = NULL;
-       ir_node   *block  = get_nodes_block(irn);
        ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
        ir_node   *mem    = new_rd_NoMem(env->irg);
        ir_node   *ptr    = get_irn_n(irn, 0);
@@ -1036,33 +1101,34 @@ static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
 #endif
 
 /**
- * Transforms a FrameAddr into an ia32 Add.
+ * Transforms a FrameAddr into an ARM Add.
  */
-static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) {
-       ir_node *block  = get_nodes_block(irn);
-       ir_entity *ent  = be_get_frame_entity(irn);
-       int     offset  = get_entity_offset(ent);
-       ir_node *op     = get_irn_n(irn, 0);
-       ir_node *cnst;
-       ir_mode *mode   = get_irn_mode(irn);
-       dbg_info *dbg   = get_irn_dbg_info(irn);
+static ir_node *gen_be_FrameAddr(ir_node *node) {
+       ir_node   *block  = be_transform_node(get_nodes_block(node));
+       ir_entity *ent    = be_get_frame_entity(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_node   *cnst;
 
        if (be_is_IncSP(op)) {
                /* BEWARE: we get an offset which is absolute from an offset that
                   is relative. Both must be merged */
                offset += get_sp_expand_offset(op);
        }
-       cnst = create_const_graph_value(cg->birg->abi, irn, block, (unsigned)offset);
+       cnst = create_const_graph_value(env_cg->birg->abi, node, block, (unsigned)offset);
        if (is_arm_Mov_i(cnst))
-               return new_rd_arm_Add_i(dbg, current_ir_graph, block, op, mode, get_arm_value(cnst));
-       return new_rd_arm_Add(dbg, current_ir_graph, block, op, cnst, mode, ARM_SHF_NONE, NULL);
+               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);
 }
 
 #if 0
 /**
- * Transforms a FrameLoad into an ia32 Load.
+ * Transforms a FrameLoad into an ARM Load.
  */
-static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
+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);
@@ -1096,210 +1162,400 @@ static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
 }
 #endif
 
-#if 0
 /**
- * Transforms a FrameStore into an ia32 Store.
+ * Transform a be_AddSP into an arm_AddSP. Eat up const sizes.
  */
-static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
-       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_node   *val    = get_irn_n(irn, 2);
-       ir_entity *ent    = be_get_frame_entity(irn);
-       ir_mode   *mode   = get_irn_mode(val);
+static ir_node *gen_be_AddSP(ir_node *node) {
+       ir_node  *block  = be_transform_node(get_nodes_block(node));
+       ir_node  *sz     = get_irn_n(node, be_pos_AddSP_size);
+       ir_node  *new_sz = be_transform_node(sz);
+       ir_node  *sp     = get_irn_n(node, be_pos_AddSP_old_sp);
+       ir_node  *new_sp = be_transform_node(sp);
+       ir_graph *irg    = current_ir_graph;
+       dbg_info *dbgi   = get_irn_dbg_info(node);
+       ir_node  *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);
 
-       if (mode_is_float(mode)) {
-               if (USE_SSE2(env->cg))
-                       new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
-               else {
-                       env->cg->used_x87 = 1;
-                       new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
+       return new_op;
+}
+
+/**
+ * Transform a be_SubSP into an arm_SubSP. Eat up const sizes.
+ */
+static ir_node *gen_be_SubSP(ir_node *node) {
+       ir_node  *block  = be_transform_node(get_nodes_block(node));
+       ir_node  *sz     = get_irn_n(node, be_pos_SubSP_size);
+       ir_node  *new_sz = be_transform_node(sz);
+       ir_node  *sp     = get_irn_n(node, be_pos_SubSP_old_sp);
+       ir_node  *new_sp = be_transform_node(sp);
+       ir_graph *irg    = current_ir_graph;
+       dbg_info *dbgi   = get_irn_dbg_info(node);
+       ir_node  *nomem  = new_NoMem();
+       ir_node  *new_op;
+
+       /* ARM stack grows in reverse direction, make an AddSP */
+       new_op = new_rd_arm_AddSP(dbgi, irg, block, new_sp, new_sz, nomem);
+
+       return new_op;
+}
+
+/**
+ * Transform a be_Copy.
+ */
+static ir_node *gen_be_Copy(ir_node *node) {
+       ir_node *result = be_duplicate_node(node);
+       ir_mode *mode   = get_irn_mode(result);
+
+       if (mode_needs_gp_reg(mode)) {
+               set_irn_mode(node, mode_Iu);
+       }
+
+       return result;
+}
+
+/**
+ * Transform a Proj from a Load.
+ */
+static ir_node *gen_Proj_Load(ir_node *node) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *load     = get_Proj_pred(node);
+       ir_node  *new_load = be_transform_node(load);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       long     proj      = get_Proj_proj(node);
+
+       /* renumber the proj */
+       switch (get_arm_irn_opcode(new_load)) {
+       case iro_arm_Load:
+       case iro_arm_Loadb:
+       case iro_arm_Loadbs:
+       case iro_arm_Loadh:
+       case iro_arm_Loadhs:
+               /* handle all gp loads equal: they have the same proj numbers. */
+               if (proj == pn_Load_res) {
+                       return new_rd_Proj(dbgi, irg, block, new_load, mode_Iu, pn_arm_Load_res);
+               } else if (proj == pn_Load_M) {
+                       return new_rd_Proj(dbgi, irg, block, new_load, mode_M, pn_arm_Load_M);
+               }
+               break;
+       case iro_arm_fpaLdf:
+               if (proj == pn_Load_res) {
+                       ir_mode *mode = get_Load_mode(load);
+                       return new_rd_Proj(dbgi, irg, block, new_load, mode, pn_arm_fpaLdf_res);
+               } else if (proj == pn_Load_M) {
+                       return new_rd_Proj(dbgi, irg, block, new_load, mode_M, pn_arm_fpaLdf_M);
                }
+               break;
+       default:
+               break;
        }
-       else if (get_mode_size_bits(mode) == 8) {
-               new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
+       assert(0);
+       return new_rd_Unknown(irg, get_irn_mode(node));
+}
+
+/**
+ * Transform and renumber the Projs from a CopyB.
+ */
+static ir_node *gen_Proj_CopyB(ir_node *node) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *pred     = get_Proj_pred(node);
+       ir_node  *new_pred = be_transform_node(pred);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_mode  *mode     = get_irn_mode(node);
+       long     proj      = get_Proj_proj(node);
+
+       switch(proj) {
+       case pn_CopyB_M_regular:
+               if (is_arm_CopyB(new_pred)) {
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_CopyB_M);
+               }
+               break;
+       default:
+               break;
        }
-       else {
-               new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
+       assert(0);
+       return new_rd_Unknown(irg, mode);
+}
+
+/**
+ * Transform and renumber the Projs from a Quot.
+ */
+static ir_node *gen_Proj_Quot(ir_node *node) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *pred     = get_Proj_pred(node);
+       ir_node  *new_pred = be_transform_node(pred);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_mode  *mode     = get_irn_mode(node);
+       long     proj      = get_Proj_proj(node);
+
+       switch (proj) {
+       case pn_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);
+               }
+               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);
+               }
+               break;
+       default:
+               break;
        }
+       assert(0);
+       return new_rd_Unknown(irg, mode);
+}
 
-       set_ia32_frame_ent(new_op, ent);
-       set_ia32_use_frame(new_op);
+/**
+ * Transform the Projs of an AddSP.
+ */
+static ir_node *gen_Proj_be_AddSP(ir_node *node) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *pred     = get_Proj_pred(node);
+       ir_node  *new_pred = be_transform_node(pred);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       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]);
+               return res;
+       } else if (proj == pn_be_AddSP_M) {
+               return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_AddSP_M);
+       }
 
-       set_ia32_am_support(new_op, ia32_am_Dest);
-       set_ia32_op_type(new_op, ia32_AddrModeD);
-       set_ia32_am_flavour(new_op, ia32_B);
-       set_ia32_ls_mode(new_op, mode);
+       assert(0);
+       return new_rd_Unknown(irg, get_irn_mode(node));
+}
 
-       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
+/**
+ * Transform the Projs of a SubSP.
+ */
+static ir_node *gen_Proj_be_SubSP(ir_node *node) {
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *pred     = get_Proj_pred(node);
+       ir_node  *new_pred = be_transform_node(pred);
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       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);
+               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_op;
+       assert(0);
+       return new_rd_Unknown(irg, get_irn_mode(node));
 }
-#endif
 
+/**
+ * Transform the Projs from a Cmp.
+ */
+static ir_node *gen_Proj_Cmp(ir_node *node) {
+       panic("Psi NYI\n");
+}
 
-// static ir_node *gen_be_Copy(ir_node *irn, arm_code_gen_t *cg) {
-//     return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
-// }
-
-/*********************************************************
- *                  _             _      _
- *                 (_)           | |    (_)
- *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
- * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
- * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
- * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
- *
- *********************************************************/
 
 /**
- * move constants out of the start block
+ * Transform the Thread Local Storage Proj.
  */
-void arm_move_consts(ir_node *node, void *env) {
-       arm_code_gen_t *cg = env;
-       int i;
+static ir_node *gen_Proj_tls(ir_node *node) {
+       ir_node  *block = be_transform_node(get_nodes_block(node));
+       ir_graph *irg   = current_ir_graph;
+       dbg_info *dbgi  = NULL;
 
-       if (is_Block(node))
-               return;
+       return new_rd_arm_LdTls(dbgi, irg, block, mode_Iu);
+}
 
-       if (is_Phi(node)) {
-               for (i = get_irn_arity(node) - 1; i >= 0; --i) {
-                       ir_node *pred = get_irn_n(node,i);
-                       ir_opcode pred_code = get_irn_opcode(pred);
-                       if (pred_code == iro_Const) {
-                               ir_node *block = get_nodes_block(get_irn_n(get_nodes_block(node),i));
-                               ir_node *nn    = gen_arm_Const(pred, block, cg);
-                               set_irn_n(node, i, nn);
-                       }
-                       else if (pred_code == iro_SymConst) {
-                               /* FIXME: in general, SymConst always require a load, so it
-                                  might be better to place them into the first real block
-                                  and let the spiller rematerialize them. */
-                               ident *id = get_sc_ident(pred);
-                               ir_node *symconst_node;
-                               symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
-                                       current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)),
-                                       get_irn_mode(pred), id);
-                               set_irn_n(node, i, symconst_node);
-                       }
+/**
+ * Transform a Proj node.
+ */
+static ir_node *gen_Proj(ir_node *node) {
+       ir_graph *irg  = current_ir_graph;
+       dbg_info *dbgi = get_irn_dbg_info(node);
+       ir_node  *pred = get_Proj_pred(node);
+       long     proj  = get_Proj_proj(node);
+
+       if (is_Store(pred) || be_is_FrameStore(pred)) {
+               if (proj == pn_Store_M) {
+                       return be_transform_node(pred);
+               } else {
+                       assert(0);
+                       return new_r_Bad(irg);
                }
-               return;
-       }
-       for (i = 0; i < get_irn_arity(node); i++) {
-               ir_node *pred = get_irn_n(node,i);
-               ir_opcode pred_code = get_irn_opcode(pred);
-
-               if (pred_code == iro_Const) {
-                       ir_node *block = get_nodes_block(node);
-                       ir_node *nn    = gen_arm_Const(pred, block, cg);
-                       set_irn_n(node, i, nn);
-               } else if (pred_code == iro_SymConst) {
-                       ident *id = get_sc_ident(pred);
-                       ir_node *symconst_node;
-                       symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
-                               current_ir_graph, get_nodes_block(node),
-                               get_irn_mode(pred), id);
-                       set_irn_n(node, i, symconst_node);
+       } else if (is_Load(pred) || be_is_FrameLoad(pred)) {
+               return gen_Proj_Load(node);
+       } else if (is_CopyB(pred)) {
+               return gen_Proj_CopyB(node);
+       } else if (is_Quot(pred)) {
+               return gen_Proj_Quot(node);
+       } else if (be_is_SubSP(pred)) {
+               return gen_Proj_be_SubSP(node);
+       } else if (be_is_AddSP(pred)) {
+               return gen_Proj_be_AddSP(node);
+       } else if (is_Cmp(pred)) {
+               return gen_Proj_Cmp(node);
+       } else if (get_irn_op(pred) == op_Start) {
+               if (proj == pn_Start_X_initial_exec) {
+                       ir_node *block = get_nodes_block(pred);
+                       ir_node *jump;
+
+                       /* 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 == be_get_old_anchor(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 *new_proj = new_r_Proj(irg, block, new_pred, mode_Iu,
+                                                      get_Proj_proj(node));
+#ifdef DEBUG_libfirm
+                       new_proj->node_nr = node->node_nr;
+#endif
+                       return new_proj;
                }
        }
+
+       return be_duplicate_node(node);
 }
 
 /**
- * Do not transform Proj, but check for floating point value.
+ * Change some phi modes
  */
-static ir_node *gen_Proj(ir_node *irn, arm_code_gen_t *cg) {
-       if (mode_is_float(get_irn_mode(irn)))
-               cg->have_fp = 1;
-       return NULL;
+static ir_node *gen_Phi(ir_node *node) {
+       ir_node  *block = be_transform_node(get_nodes_block(node));
+       ir_graph *irg   = current_ir_graph;
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_mode  *mode  = get_irn_mode(node);
+       ir_node  *phi;
+
+       if (mode_needs_gp_reg(mode)) {
+               /* we shouldn't have any 64bit stuff around anymore */
+               assert(get_mode_size_bits(mode) <= 32);
+               /* all integer operations are on 32bit registers now */
+               mode = mode_Iu;
+       }
+
+       /* phi nodes allow loops, so we use the old arguments for now
+        * and fix this later */
+       phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), get_irn_in(node) + 1);
+       copy_node_attr(node, phi);
+       be_duplicate_deps(node, phi);
+
+       be_set_transformed_node(node, phi);
+       be_enqueue_preds(node);
+
+       return phi;
 }
 
+/*********************************************************
+ *                  _             _      _
+ *                 (_)           | |    (_)
+ *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
+ * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
+ * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
+ * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
+ *
+ *********************************************************/
 
 /**
  * the BAD transformer.
  */
-static ir_node *bad_transform(ir_node *irn, arm_code_gen_t *cg) {
+static ir_node *bad_transform(ir_node *irn) {
        panic("ARM backend: Not implemented: %+F\n", irn);
-       return NULL;
+       return irn;
 }
 
-/**
- * The type of a transform function.
- */
-typedef ir_node *(transform_func)(ir_node *irn, arm_code_gen_t *cg);
-
 /**
  * Set a node emitter. Make it a bit more type safe.
  */
-static INLINE void set_transformer(ir_op *op, transform_func arm_transform_func) {
+static INLINE void set_transformer(ir_op *op, be_transform_func arm_transform_func) {
        op->ops.generic = (op_func)arm_transform_func;
 }
 
 /**
  * Enters all transform functions into the generic pointer
  */
-void arm_register_transformers(void) {
+static void arm_register_transformers(void) {
        ir_op *op_Max, *op_Min, *op_Mulh;
 
        /* first clear the generic function pointer for all ops */
        clear_irp_opcodes_generic_func();
 
-#define FIRM_OP(a)     set_transformer(op_##a, gen_##a)
-#define BAD(a)         set_transformer(op_##a, bad_transform)
+#define GEN(a)     set_transformer(op_##a, gen_##a)
+#define BAD(a)     set_transformer(op_##a, bad_transform)
 #define IGN(a)
 
-       FIRM_OP(Add);  // done
-       FIRM_OP(Mul);  // done
-       FIRM_OP(Quot); // done
-       FIRM_OP(And);  // done
-       FIRM_OP(Or);   // done
-       FIRM_OP(Eor);  // done
-
-       FIRM_OP(Sub);  // done
-       FIRM_OP(Shl);  // done
-       FIRM_OP(Shr);  // done
-       FIRM_OP(Shrs); // done
-
-       FIRM_OP(Minus); // done
-       FIRM_OP(Not);   // done
-       FIRM_OP(Abs);   // done
-
-       FIRM_OP(CopyB); // done
-       BAD(Const);     /* should be handled by arm_move_const */
-       FIRM_OP(Conv); // TODO: floating point conversions
-
-       FIRM_OP(Load);   // done
-       FIRM_OP(Store);  // done
-
-       FIRM_OP(SymConst);
-       FIRM_OP(Cond);    // integer done
-
-       /* TODO: implement these nodes */
-
-       IGN(Div);    // intrinsic lowering
-       IGN(Mod);    // intrinsic lowering
-       IGN(DivMod); // TODO: implement DivMod
-
-       IGN(Mux);
-       IGN(Unknown);
-       IGN(Cmp);     // done, implemented in cond
-
-       /* You probably don't need to handle the following nodes */
-
-       IGN(Call);
-       FIRM_OP(Proj);
-       IGN(Alloc);
+       GEN(Add);
+       GEN(Sub);
+       GEN(Mul);
+       GEN(And);
+       GEN(Or);
+       GEN(Eor);
+
+       GEN(Shl);
+       GEN(Shr);
+       GEN(Shrs);
+       BAD(Rot);       /* unsupported yet */
+
+       GEN(Quot);
+
+       /* should be lowered */
+       BAD(Div);
+       BAD(Mod);
+       BAD(DivMod);
+
+       GEN(Minus);
+       GEN(Conv);
+       GEN(Abs);
+       GEN(Not);
+
+       GEN(Load);
+       GEN(Store);
+       GEN(Cond);
+
+       BAD(ASM);       /* unsupported yet */
+       GEN(CopyB);
+       BAD(Mux);
+       BAD(Psi);       /* unsupported yet */
+       GEN(Proj);
+       GEN(Phi);
 
        IGN(Block);
-       IGN(Start);
        IGN(End);
-       IGN(NoMem);
-       IGN(Phi);
-       IGN(IJmp);
-       IGN(Jmp);     // emitter done
-       IGN(Break);
-       IGN(Sync);
 
+       GEN(Const);
+       GEN(SymConst);
+
+       /* we should never see these nodes */
        BAD(Raise);
        BAD(Sel);
        BAD(InstOf);
@@ -1307,58 +1563,58 @@ void arm_register_transformers(void) {
        BAD(Free);
        BAD(Tuple);
        BAD(Id);
-       BAD(Bad);
+       //BAD(Bad);
        BAD(Confirm);
        BAD(Filter);
        BAD(CallBegin);
        BAD(EndReg);
        BAD(EndExcept);
 
-       FIRM_OP(be_FrameAddr);
+       /* handle generic backend nodes */
+       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);
 
        op_Max = get_op_Max();
        if (op_Max)
-               BAD(Max);
+               BAD(Max);       /* unsupported yet */
        op_Min = get_op_Min();
        if (op_Min)
-               BAD(Min);
+               BAD(Min);       /* unsupported yet */
        op_Mulh = get_op_Mulh();
        if (op_Mulh)
-               BAD(Mulh);
+               BAD(Mulh);      /* unsupported yet */
 
 #undef IGN
-#undef FIRM_OP
+#undef GEN
 #undef BAD
 }
 
 /**
- * Transforms the given firm node (and maybe some other related nodes)
- * into one or more assembler nodes.
- *
- * @param node    the firm node
- * @param env     the debug module
+ * Pre-transform all unknown and noreg nodes.
  */
-void arm_transform_node(ir_node *node, void *env) {
-       arm_code_gen_t *cg = (arm_code_gen_t *)env;
-       ir_op *op          = get_irn_op(node);
-       ir_node *asm_node  = NULL;
-
-       if (op == op_Block)
-               return;
-
-       DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
-
-       if (op->ops.generic) {
-               transform_func *transform = (transform_func *)op->ops.generic;
+static void arm_pretransform_node(void *arch_cg) {
+       arm_code_gen_t *cg = arch_cg;
+}
 
-               asm_node = (*transform)(node, cg);
-       }
+/**
+ * Transform a Firm graph into an ARM graph.
+ */
+void arm_transform_graph(arm_code_gen_t *cg) {
+       arm_register_transformers();
+       env_cg = cg;
+       be_transform_graph(cg->birg, /*arm_pretransform_node*/ NULL, cg);
+}
 
-       if (asm_node) {
-               exchange(node, asm_node);
-               DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
-       }
-       else {
-               DB((cg->mod, LEVEL_1, "ignored\n"));
-       }
+void arm_init_transform(void) {
+       // FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
 }
index 27efeae..ec4adeb 100644 (file)
 #ifndef FIRM_BE_ARM_ARM_TRANSFORM_H
 #define FIRM_BE_ARM_ARM_TRANSFORM_H
 
-void arm_move_consts(ir_node *node, void *env);
+/**
+ * Transform a Firm graph into an ARM graph.
+ */
+void arm_transform_graph(arm_code_gen_t *cg);
 
-void arm_register_transformers(void);
-void arm_transform_node(ir_node *node, void *env);
+void arm_init_transform(void);
 
 #endif
index e0c6273..15adde9 100644 (file)
@@ -36,6 +36,7 @@
 #include "irprintf.h"
 #include "ircons.h"
 #include "irgmod.h"
+#include "irgopt.h"
 #include "lowering.h"
 
 #include "bitset.h"
@@ -91,30 +92,22 @@ arch_register_req_t *arm_get_irn_reg_req(const void *self, const ir_node *node,
        FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
 
        if (is_Block(node) || mode == mode_X || mode == mode_M) {
-               DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", node));
                return arch_no_register_req;
        }
 
        if (mode == mode_T && pos < 0) {
-               DBG((mod, LEVEL_1, "ignoring request for OUT requirements at %+F\n", node));
                return arch_no_register_req;
        }
 
-       DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, node));
-
        if (is_Proj(node)) {
                /* in case of a proj, we need to get the correct OUT slot */
                /* of the node corresponding to the proj number */
-               if (pos == -1) {
-                       node_pos = arm_translate_proj_pos(node);
-               }
-               else {
-                       node_pos = pos;
+               if(pos >= 0) {
+                       return arch_no_register_req;
                }
 
-               node = skip_Proj_const(node);
-
-               DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", node, node_pos));
+               node_pos = (pos == -1) ? get_Proj_proj(node) : pos;
+               node     = skip_Proj_const(node);
        }
 
        /* get requirements for our own nodes */
@@ -126,27 +119,23 @@ arch_register_req_t *arm_get_irn_reg_req(const void *self, const ir_node *node,
                        req = get_arm_out_req(node, node_pos);
                }
 
-               DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", node, pos));
                return req;
        }
 
-       /* unknown should be tranformed by now */
+       /* unknown should be transformed by now */
        assert(!is_Unknown(node));
-       DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", node));
-
        return arch_no_register_req;
 }
 
 static void arm_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
        int pos = 0;
 
-       if (is_Proj(irn)) {
-
-               if (get_irn_mode(irn) == mode_X) {
-                       return;
-               }
+       if (get_irn_mode(irn) == mode_X) {
+               return;
+       }
 
-               pos = arm_translate_proj_pos(irn);
+       if (is_Proj(irn)) {
+               pos = get_Proj_proj(irn);
                irn = skip_Proj(irn);
        }
 
@@ -172,7 +161,7 @@ static const arch_register_t *arm_get_irn_reg(const void *self, const ir_node *i
                        return NULL;
                }
 
-               pos = arm_translate_proj_pos(irn);
+               pos = get_Proj_proj(irn);
                irn = skip_Proj_const(irn);
        }
 
@@ -278,12 +267,21 @@ arm_irn_ops_t arm_irn_ops = {
 static void arm_prepare_graph(void *self) {
        arm_code_gen_t *cg = self;
 
-       arm_register_transformers();
-       irg_walk_blkwise_graph(cg->irg, NULL, arm_move_consts, cg);
-       irg_walk_blkwise_graph(cg->irg, NULL, arm_transform_node, cg);
-}
+       /* transform nodes into assembler instructions */
+       arm_transform_graph(cg);
 
+       /* do local optimizations (mainly CSE) */
+       local_optimize_graph(cg->irg);
 
+       if (cg->dump)
+               be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
+
+       /* do code placement, to optimize the position of constants */
+       place_code(cg->irg);
+
+       if (cg->dump)
+               be_dump(cg->irg, "-place", dump_ir_block_graph_sched);
+}
 
 /**
  * Called immediately before emit phase.
@@ -525,6 +523,7 @@ static void arm_before_abi(void *self) {
        irg_walk_graph(cg->irg, NULL, handle_calls, cg);
 }
 
+/* forward */
 static void *arm_cg_init(be_irg_t *birg);
 
 static const arch_code_generator_if_t arm_code_gen_if = {
@@ -553,14 +552,15 @@ static void *arm_cg_init(be_irg_t *birg) {
        }
 
        cg = xmalloc(sizeof(*cg));
-       cg->impl     = &arm_code_gen_if;
-       cg->irg      = birg->irg;
-       cg->reg_set  = new_set(arm_cmp_irn_reg_assoc, 1024);
-       cg->arch_env = birg->main_env->arch_env;
-       cg->isa      = isa;
-       cg->birg     = birg;
-       cg->int_tp   = int_tp;
-       cg->have_fp  = 0;
+       cg->impl         = &arm_code_gen_if;
+       cg->irg          = birg->irg;
+       cg->reg_set      = new_set(arm_cmp_irn_reg_assoc, 1024);
+       cg->arch_env     = birg->main_env->arch_env;
+       cg->isa          = isa;
+       cg->birg         = birg;
+       cg->int_tp       = int_tp;
+       cg->have_fp_insn = 0;
+       cg->dump         = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
 
        FIRM_DBG_REGISTER(cg->mod, "firm.be.arm.cg");
 
@@ -744,6 +744,7 @@ static void *arm_init(FILE *file_handle) {
        be_emit_init_env(&isa->emit, file_handle);
 
        arm_create_opcodes();
+       arm_register_copy_attr_func();
        arm_handle_intrinsics();
 
        /* we mark referenced global entities, so we can only emit those which
@@ -782,7 +783,7 @@ static int arm_get_n_reg_class(const void *self) {
 
        /* ARGH! is called BEFORE transform */
        return 2;
-       return isa->cg->have_fp ? 2 : 1;
+       return isa->cg->have_fp_insn ? 2 : 1;
 }
 
 /**
@@ -1174,6 +1175,8 @@ void be_init_arch_arm(void)
        lc_opt_add_table(arm_grp, arm_options);
 
        be_register_isa_if("arm", &arm_isa_if);
+
+       arm_init_transform();
 }
 
 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm);
index 0a3e73c..33187a3 100644 (file)
@@ -116,10 +116,10 @@ enum arm_fp_architectures {
 };
 
 /** Returns non-zero if FPA instructions should be issued. */
-#define USE_FPA(cg)     ((cg)->fpu_arch & ARM_FPU_FPA_EXT_V1)
+#define USE_FPA(isa)    ((isa)->fpu_arch & ARM_FPU_FPA_EXT_V1)
 
 /** Returns non-zero if VFP instructions should be issued. */
-#define USE_VFP(cg)     ((cg)->fpu_arch & ARM_FPU_VFP_EXT_V1xD)
+#define USE_VFP(isa)    ((isa)->fpu_arch & ARM_FPU_VFP_EXT_V1xD)
 
 /** Types of processor to generate code for. */
 enum arm_processor_types {
@@ -142,23 +142,24 @@ typedef struct _arm_code_gen_t {
        arm_isa_t                      *isa;            /**< the isa instance */
        be_irg_t                       *birg;           /**< The be-irg (contains additional information about the irg) */
        ir_type                        *int_tp;         /**< the int type, needed for Call conversion */
-       int                             have_fp;        /**< non-zero, if fp hardware instructions are emitted */
+       int                            have_fp_insn;         /**< non-zero, if fp hardware instructions are emitted */
+       char                           dump;            /**< set to 1 if graphs should be dumped */
        DEBUG_ONLY(firm_dbg_module_t   *mod;)            /**< debugging module */
 } arm_code_gen_t;
 
 
 struct _arm_isa_t {
-       arch_isa_t             arch_isa;      /**< must be derived from arch_isa_t */
-       int                    gen_reg_names; /**< use generic register names instead of SP, LR, PC */
-       int                    fpu_arch;      /**< FPU architecture */
-       arm_code_gen_t        *cg;            /**< current code generator */
-       be_emit_env_t          emit;          /**< An emitter environment for the GAS emitter. */
+       arch_isa_t     arch_isa;      /**< must be derived from arch_isa_t */
+       int            gen_reg_names; /**< use generic register names instead of SP, LR, PC */
+       int            fpu_arch;      /**< FPU architecture */
+       arm_code_gen_t *cg;           /**< current code generator */
+       be_emit_env_t  emit;          /**< An emitter environment for the GAS emitter. */
 };
 
 
 typedef struct _arm_irn_ops_t {
        const arch_irn_ops_if_t *impl;
-       arm_code_gen_t     *cg;
+       arm_code_gen_t          *cg;
 } arm_irn_ops_t;