- bring arm backend back to shape: cleanup and fix lots of stuff
authorMatthias Braun <matze@braunis.de>
Thu, 24 Sep 2009 13:41:56 +0000 (13:41 +0000)
committerMatthias Braun <matze@braunis.de>
Thu, 24 Sep 2009 13:41:56 +0000 (13:41 +0000)
  disabled some broken transformers. (Queens, Quicksort and several other stuff from the
  testsuite work, but still lots of stuff broken)

[r26649]

ir/be/arm/arm_emitter.c
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_optimize.c
ir/be/arm/arm_spec.pl
ir/be/arm/arm_transform.c
ir/be/arm/bearch_arm.c

index c444ddc..bad7fb0 100644 (file)
@@ -23,8 +23,6 @@
  * @author  Oliver Richter, Tobias Gneist, Michael Beck
  * @version $Id$
  */
-#define SILENCER
-
 #include "config.h"
 
 #include <limits.h>
@@ -60,7 +58,6 @@
 #include "../benode.h"
 
 #define BLOCK_PREFIX ".L"
-
 #define SNPRINTF_BUF_LEN 128
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
@@ -439,7 +436,7 @@ static void emit_arm_CmpBra(const ir_node *irn) {
                        be_emit_cstring(" */");
                        be_emit_finish_line_gas(proj_false);
                } else {
-                       be_emit_cstring("b ");
+                       be_emit_cstring("\tb ");
                        arm_emit_cfop_target(proj_false);
                        be_emit_finish_line_gas(proj_false);
                }
@@ -765,17 +762,27 @@ static void emit_arm_SwitchJmp(const ir_node *irn) {
 /* emit_be                                                              */
 /************************************************************************/
 
-static void emit_be_Call(const ir_node *irn) {
-       ir_entity *ent = be_Call_get_entity(irn);
+static void arm_emit_entity(ir_entity *entity)
+{
+       set_entity_backend_marked(entity, 1);
+       be_emit_ident(get_entity_ld_ident(entity));
+}
+
+static void emit_be_Call(const ir_node *irn)
+{
+       ir_entity *entity = be_Call_get_entity(irn);
 
-       be_emit_cstring("\tbl ");
-       if (ent) {
-               set_entity_backend_marked(ent, 1);
-               be_emit_ident(get_entity_ld_ident(ent));
+       if (entity != NULL) {
+               be_emit_cstring("\tbl ");
+               arm_emit_entity(entity);
+               be_emit_finish_line_gas(irn);
        } else {
+               be_emit_cstring("\tmov lr, pc");
+               be_emit_finish_line_gas(irn);
+               be_emit_cstring("\tmov pc, ");
                arm_emit_source_register(irn, be_pos_Call_ptr);
+               be_emit_finish_line_gas(irn);
        }
-       be_emit_finish_line_gas(irn);
 }
 
 /** Emit an IncSP node */
@@ -893,7 +900,8 @@ static void emit_be_Reload(const ir_node *irn) {
        be_emit_finish_line_gas(irn);
 }
 
-static void emit_be_Perm(const ir_node *irn) {
+static void emit_be_Perm(const ir_node *irn)
+{
        be_emit_cstring("\teor ");
        arm_emit_source_register(irn, 0);
        be_emit_cstring(", ");
@@ -919,11 +927,61 @@ static void emit_be_Perm(const ir_node *irn) {
        be_emit_finish_line_gas(irn);
 }
 
+static void emit_be_MemPerm(const ir_node *node)
+{
+       int i;
+       int memperm_arity;
+       int sp_change = 0;
+
+       /* TODO: this implementation is slower than necessary.
+          The longterm goal is however to avoid the memperm node completely */
+
+       memperm_arity = be_get_MemPerm_entity_arity(node);
+       if (memperm_arity > 12)
+               panic("memperm with more than 12 inputs not supported yet");
+
+       for (i = 0; i < memperm_arity; ++i) {
+               int offset;
+               ir_entity *entity = be_get_MemPerm_in_entity(node, i);
+
+               /* spill register */
+               be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
+               be_emit_finish_line_gas(node);
+               sp_change += 4;
+               /* load from entity */
+               offset = get_entity_offset(entity) + sp_change;
+               be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
+               be_emit_finish_line_gas(node);
+       }
+
+       for (i = memperm_arity-1; i >= 0; --i) {
+               int        offset;
+               ir_entity *entity = be_get_MemPerm_out_entity(node, i);
+
+               /* store to new entity */
+               offset = get_entity_offset(entity) + sp_change;
+               be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
+               be_emit_finish_line_gas(node);
+               /* restore register */
+               be_emit_irprintf("\tldr r%d, [sp], #4", i);
+               sp_change -= 4;
+               be_emit_finish_line_gas(node);
+       }
+       assert(sp_change == 0);
+}
+
+static void emit_be_Return(const ir_node *node)
+{
+       be_emit_cstring("\tmov pc, lr");
+       be_emit_finish_line_gas(node);
+}
+
 /************************************************************************/
 /* emit                                                                 */
 /************************************************************************/
 
-static void emit_Jmp(const ir_node *node) {
+static void emit_arm_Jmp(const ir_node *node)
+{
        ir_node *block, *next_block;
 
        /* for now, the code works for scheduled and non-schedules blocks */
@@ -976,9 +1034,9 @@ static void emit_arm_LdTls(const ir_node *irn) {
  *
  ***********************************************************************************/
 
-static void emit_silence(const ir_node *irn) {
+static void emit_nothing(const ir_node *irn)
+{
        (void) irn;
-       /* Do nothing. */
 }
 
 /**
@@ -989,7 +1047,8 @@ typedef void (emit_func)(const ir_node *irn);
 /**
  * Set a node emitter. Make it a bit more type safe.
  */
-static inline void set_emitter(ir_op *op, emit_func arm_emit_node) {
+static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
+{
        op->ops.generic = (op_func)arm_emit_node;
 }
 
@@ -997,59 +1056,40 @@ static inline void set_emitter(ir_op *op, emit_func arm_emit_node) {
  * Enters the emitter functions for handled nodes into the generic
  * pointer of an opcode.
  */
-static void arm_register_emitters(void) {
-
-#define ARM_EMIT(a)  set_emitter(op_arm_##a, emit_arm_##a)
-#define EMIT(a)      set_emitter(op_##a, emit_##a)
-#define BE_EMIT(a)   set_emitter(op_be_##a, emit_be_##a)
-#define SILENCE(a)   set_emitter(op_##a, emit_silence)
-
+static void arm_register_emitters(void)
+{
        /* first clear the generic function pointer for all ops */
        clear_irp_opcodes_generic_func();
 
        /* register all emitter functions defined in spec */
        arm_register_spec_emitters();
 
-       /* other emitter functions */
-       ARM_EMIT(CmpBra);
-       ARM_EMIT(TstBra);
-       ARM_EMIT(fpaCmfBra);
-       ARM_EMIT(fpaCmfeBra);
-       ARM_EMIT(CopyB);
-//     ARM_EMIT(CopyB_i);
-//     ARM_EMIT(Const);
-       ARM_EMIT(SymConst);
-       ARM_EMIT(SwitchJmp);
-       ARM_EMIT(fpaDbl2GP);
-       ARM_EMIT(fpaConst);
-       ARM_EMIT(LdTls);
-
-       /* benode emitter */
-       BE_EMIT(Call);
-       BE_EMIT(IncSP);
-       BE_EMIT(Copy);
-       BE_EMIT(Spill);
-       BE_EMIT(Reload);
-       BE_EMIT(Perm);
-
-       /* firm emitter */
-       EMIT(Jmp);
-
-       /* noisy stuff */
-#ifdef SILENCER
-       SILENCE(Proj);
-       SILENCE(Phi);
-       SILENCE(be_Keep);
-       SILENCE(be_CopyKeep);
-       SILENCE(be_Start);
-       SILENCE(be_Barrier);
-       SILENCE(be_Return);
-#endif
-
-#undef ARM_EMIT
-#undef BE_EMIT
-#undef EMIT
-#undef SILENCE
+       /* custom emitter */
+       set_emitter(op_arm_CmpBra,     emit_arm_CmpBra);
+       set_emitter(op_arm_CopyB,      emit_arm_CopyB);
+       set_emitter(op_arm_fpaCmfBra,  emit_arm_fpaCmfBra);
+       set_emitter(op_arm_fpaCmfeBra, emit_arm_fpaCmfeBra);
+       set_emitter(op_arm_fpaConst,   emit_arm_fpaConst);
+       set_emitter(op_arm_fpaDbl2GP,  emit_arm_fpaDbl2GP);
+       set_emitter(op_arm_Jmp,        emit_arm_Jmp);
+       set_emitter(op_arm_LdTls,      emit_arm_LdTls);
+       set_emitter(op_arm_SwitchJmp,  emit_arm_SwitchJmp);
+       set_emitter(op_arm_SymConst,   emit_arm_SymConst);
+       set_emitter(op_arm_TstBra,     emit_arm_TstBra);
+       set_emitter(op_be_Call,        emit_be_Call);
+       set_emitter(op_be_Copy,        emit_be_Copy);
+       set_emitter(op_be_IncSP,       emit_be_IncSP);
+       set_emitter(op_be_MemPerm,     emit_be_MemPerm);
+       set_emitter(op_be_Perm,        emit_be_Perm);
+       set_emitter(op_be_Reload,      emit_be_Reload);
+       set_emitter(op_be_Return,      emit_be_Return);
+       set_emitter(op_be_Spill,       emit_be_Spill);
+
+       /* no need to emit anything for the following nodes */
+       set_emitter(op_Phi,            emit_nothing);
+       set_emitter(op_be_Keep,        emit_nothing);
+       set_emitter(op_be_Start,       emit_nothing);
+       set_emitter(op_be_Barrier,     emit_nothing);
 }
 
 /**
@@ -1063,8 +1103,8 @@ static void arm_emit_node(const ir_node *irn) {
                be_dbg_set_dbg_info(get_irn_dbg_info(irn));
                (*emit)(irn);
        } else {
-               be_emit_cstring("\t/* TODO */");
-               be_emit_finish_line_gas(irn);
+               panic("Error: No emit handler for node %+F (graph %+F)\n",
+                     irn, current_ir_graph);
        }
 }
 
index 4a0dd01..9f052ff 100644 (file)
@@ -363,7 +363,8 @@ arm_shift_modifier get_arm_shift_modifier(const ir_node *node) {
 static void init_arm_attributes(ir_node *node, int flags,
                          const arch_register_req_t ** in_reqs,
                          const be_execution_unit_t ***execution_units,
-                                                int n_res) {
+                                                int n_res)
+{
        ir_graph       *irg  = get_irn_irg(node);
        struct obstack *obst = get_irg_obstack(irg);
        arm_attr_t     *attr = get_arm_attr(node);
@@ -380,6 +381,15 @@ static void init_arm_attributes(ir_node *node, int flags,
        memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
 }
 
+void init_arm_load_store_attributes(ir_node *res, ir_entity *entity,
+                                    int entity_sign, long offset)
+{
+       arm_load_store_attr_t *attr = get_irn_generic_attr(res);
+       attr->entity      = entity;
+       attr->entity_sign = entity_sign;
+       attr->offset      = offset;
+}
+
 /************************************************
  *   ___        _   _           _               *
  *  / _ \ _ __ | |_(_)_ __ ___ (_)_______ _ __  *
@@ -473,6 +483,29 @@ static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b) {
        return attr_a->tv != attr_b->tv;
 }
 
+arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
+{
+       return (arm_load_store_attr_t*) get_irn_generic_attr(node);
+}
+
+static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
+{
+       const arm_load_store_attr_t *attr_a;
+       const arm_load_store_attr_t *attr_b;
+
+       if (cmp_attr_arm(a, b))
+               return 1;
+
+       attr_a = get_arm_load_store_attr(a);
+       attr_b = get_arm_load_store_attr(b);
+       if (attr_a->entity != attr_b->entity
+                       || attr_a->entity_sign != attr_b->entity_sign
+                       || attr_a->offset != attr_b->offset)
+               return 1;
+
+       return 0;
+}
+
 /** 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);
index 6d4637f..31cdbab 100644 (file)
@@ -140,6 +140,9 @@ void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num);
  */
 arm_shift_modifier get_arm_shift_modifier(const ir_node *node);
 
+void init_arm_load_store_attributes(ir_node *res, ir_entity *entity,
+                                    int entity_sign, long offset);
+
 /* Include the generated headers */
 #include "gen_arm_new_nodes.h"
 
index fca77ec..4b546ee 100644 (file)
@@ -111,6 +111,13 @@ typedef struct _arm_attr_t {
        long     imm_value;                  /**< immediate */
 } arm_attr_t;
 
+typedef struct arm_load_store_attr_t {
+       arm_attr_t  attr;
+       ir_entity  *entity;
+       long        offset;
+       bool        entity_sign : 1;
+} arm_load_store_attr_t;
+
 /** Attributes for a SymConst */
 typedef struct _arm_SymConst_attr_t {
        arm_attr_t  attr;                   /**< base attributes */
index 5b5aa0c..64e49a6 100644 (file)
@@ -231,9 +231,10 @@ static void peephole_be_Spill(ir_node *node) {
                        panic("peephole_be_Spill: spill not supported for this mode");
                }
        } else if (mode_is_dataM(mode)) {
-                /* transform into Store */;
-                store = new_bd_arm_Store(dbg, block, ptr, value, get_irg_no_mem(irg));
-                sched_add_before(node, store);
+               /* transform into Store */;
+               store = new_bd_arm_Str(dbg, block, ptr, value, get_irg_no_mem(irg),
+                                      NULL, 0, 0);
+               sched_add_before(node, store);
        } else {
                panic("peephole_be_Spill: spill not supported for this mode");
        }
@@ -285,9 +286,9 @@ static void peephole_be_Reload(ir_node *node) {
                }
        } else if (mode_is_dataM(mode)) {
                /* transform into Store */;
-               load = new_bd_arm_Load(dbg, block, ptr, mem);
+               load = new_bd_arm_Ldr(dbg, block, ptr, mem, NULL, 0, 0);
                sched_add_before(node, load);
-               proj = new_rd_Proj(dbg, block, load, mode_Iu, pn_arm_Load_res);
+               proj = new_rd_Proj(dbg, block, load, mode_Iu, pn_arm_Ldr_res);
                arch_set_irn_register(proj, reg);
        } else {
                panic("peephole_be_Spill: spill not supported for this mode");
index ffd0132..a3c6033 100644 (file)
@@ -5,7 +5,6 @@
 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
 
 $arch = "arm";
-$new_emit_syntax = 1;
 
 # the number of additional opcodes you want to register
 #$additional_opcodes = 0;
@@ -27,38 +26,38 @@ $state       = 32; # register represents a state
 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
 %reg_classes = (
        gp => [
-               { "name" => "r0", "type"  => $caller_save },
-               { "name" => "r1", "type"  => $caller_save },
-               { "name" => "r2", "type"  => $caller_save },
-               { "name" => "r3", "type"  => $caller_save },
-               { "name" => "r4", "type"  => $callee_save },
-               { "name" => "r5", "type"  => $callee_save },
-               { "name" => "r6", "type"  => $callee_save },
-               { "name" => "r7", "type"  => $callee_save },
-               { "name" => "r8", "type"  => $callee_save },
-               { "name" => "r9", "type"  => $callee_save },
-               { "name" => "r10", "type" => $callee_save },
-               { "name" => "r11", "type" => $callee_save },
-               { "name" => "r12", "type" => $ignore | $callee_save }, # reserved for linker
-               { "name" => "sp", "type"  => $ignore | $callee_save }, # this is our stack pointer
-               { "name" => "lr", "type"  => $callee_save | $caller_save }, # this is our return address
-               { "name" => "pc", "type"  => $ignore | $callee_save }, # this is our program counter
+               { name => "r0",  type => $caller_save },
+               { name => "r1",  type => $caller_save },
+               { name => "r2",  type => $caller_save },
+               { name => "r3",  type => $caller_save },
+               { name => "r4",  type => $callee_save },
+               { name => "r5",  type => $callee_save },
+               { name => "r6",  type => $callee_save },
+               { name => "r7",  type => $callee_save },
+               { name => "r8",  type => $callee_save },
+               { name => "r9",  type => $callee_save },
+               { name => "r10", type => $callee_save },
+               { name => "r11", type => $callee_save },
+               { name => "r12", type => $ignore | $callee_save }, # reserved for linker
+               { name => "sp",  type => $ignore | $callee_save }, # this is our stack pointer
+               { name => "lr",  type => $callee_save | $caller_save }, # this is our return address
+               { name => "pc",  type => $ignore | $callee_save }, # this is our program counter
                { name => "gp_UKNWN", type => $ignore | $arbitrary | $virtual },  # we need a dummy register for Unknown nodes
-               { "mode" => $mode_gp }
+               { mode => $mode_gp }
        ],
        fpa  => [
-               { "name" => "f0", "type" => 1 },
-               { "name" => "f1", "type" => 1 },
-               { "name" => "f2", "type" => 1 },
-               { "name" => "f3", "type" => 1 },
-               { "name" => "f4", "type" => 1 },
-               { "name" => "f5", "type" => 1 },
-               { "name" => "f6", "type" => 1 },
-               { "name" => "f7", "type" => 1 },
-               { name => "fpa_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
-               { "mode" => $mode_fpa }
+               { name => "f0", type => $caller_save },
+               { name => "f1", type => $caller_save },
+               { name => "f2", type => $caller_save },
+               { name => "f3", type => $caller_save },
+               { name => "f4", type => $caller_save },
+               { name => "f5", type => $caller_save },
+               { name => "f6", type => $caller_save },
+               { name => "f7", type => $caller_save },
+               { name => "fpa_UKNWN", type => $ignore | $arbitrary | $virtual },  # we need a dummy register for Unknown nodes
+               { mode => $mode_fpa }
        ]
-); # %reg_classes
+);
 
 %emit_templates = (
        M  => "${arch}_emit_mode(node);",
@@ -95,14 +94,18 @@ $default_copy_attr = "arm_copy_attr";
        arm_CondJmp_attr_t   => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
        arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
        arm_fpaConst_attr_t  => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
+       arm_load_store_attr_t =>
+               "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
+               "\tinit_arm_load_store_attributes(res, entity, entity_sign, offset);",
 );
 
 %compare_attr = (
-       arm_attr_t           => "cmp_attr_arm",
-       arm_SymConst_attr_t  => "cmp_attr_arm_SymConst",
-       arm_CondJmp_attr_t   => "cmp_attr_arm_CondJmp",
-       arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
-       arm_fpaConst_attr_t  => "cmp_attr_arm_fpaConst",
+       arm_attr_t            => "cmp_attr_arm",
+       arm_SymConst_attr_t   => "cmp_attr_arm_SymConst",
+       arm_CondJmp_attr_t    => "cmp_attr_arm_CondJmp",
+       arm_SwitchJmp_attr_t  => "cmp_attr_arm_SwitchJmp",
+       arm_fpaConst_attr_t   => "cmp_attr_arm_fpaConst",
+       arm_load_store_attr_t => "cmp_attr_arm_load_store",
 );
 
 #%operands = (
@@ -171,7 +174,6 @@ Add => {
        comment   => "construct Add: Add(a, b) = Add(b, a) = a + b",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
        emit      => '. add %D0, %S0, %S1%X'
 },
@@ -181,7 +183,6 @@ Add_i => {
        comment   => "construct Add: Add(a, const) = Add(const, a) = a + const",
        attr      => "long imm",
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
        emit      => '. add %D0, %S0, %C'
 },
@@ -226,7 +227,6 @@ And => {
        comment   => "construct And: And(a, b) = And(b, a) = a AND b",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
        emit      => '. and %D0, %S0, %S1%X'
 },
@@ -238,7 +238,6 @@ And_i => {
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
        emit      => '. and %D0, %S0, %C',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;'
 },
 
 Or => {
@@ -247,7 +246,6 @@ Or => {
        comment   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
        emit      => '. orr %D0, %S0, %S1%X'
 },
@@ -258,7 +256,6 @@ Or_i => {
        attr      => "long imm",
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        emit      => '. orr %D0, %S0, %C'
 },
 
@@ -268,7 +265,6 @@ Eor => {
        comment   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
        emit      => '. eor %D0, %S0, %S1%X'
 },
@@ -279,7 +275,6 @@ Eor_i => {
        attr      => "long imm",
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        emit      => '. eor %D0, %S0, %C'
 },
 
@@ -290,7 +285,6 @@ Bic => {
        comment   => "construct Bic: Bic(a, b) = a AND ~b",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
        emit      => '. bic %D0, %S0, %S1%X'
 },
@@ -302,7 +296,6 @@ Bic_i => {
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
        emit      => '. bic %D0, %S0, %C',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;'
 },
 
 Sub => {
@@ -310,7 +303,6 @@ Sub => {
        comment   => "construct Sub: Sub(a, b) = a - b",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
        emit      => '. sub %D0, %S0, %S1%X'
 },
@@ -320,7 +312,6 @@ Sub_i => {
        comment   => "construct Sub: Sub(a, const) = a - const",
        attr      => "long imm",
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
        emit      => '. sub %D0, %S0, %C',
 },
@@ -330,7 +321,6 @@ Rsb => {
        comment   => "construct Rsb: Rsb(a, b) = b - a",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
        emit      => '. rsb %D0, %S0, %S1%X'
 },
@@ -342,7 +332,6 @@ Rsb_i => {
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
        emit      => '. rsb %D0, %S0, %C',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;'
 },
 
 Shl => {
@@ -392,7 +381,6 @@ Mov => {
        comment   => "construct Mov: a = b",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
        emit      => '. mov %D0, %S0%X'
 },
@@ -404,7 +392,6 @@ Mov_i => {
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
        reg_req   => { "out" => [ "gp" ] },
        emit      => '. mov %D0, %C',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;'
 },
 
 Mvn => {
@@ -412,7 +399,6 @@ Mvn => {
        comment   => "construct Not: Not(a) = !a",
        attr      => "arm_shift_modifier mod, long shf",
        init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       cmp_attr  => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
        reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
        emit      => '. mvn %D0, %S0%X'
 },
@@ -422,7 +408,6 @@ Mvn_i => {
        comment   => "represents a negated integer constant",
        attr      => "long imm",
        init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "out" => [ "gp" ] },
        emit      => '. mvn %D0, %C',
 },
@@ -461,7 +446,6 @@ CopyB => {
        comment   => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
        attr      => "long imm",
        init_attr => 'attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
        outs      => [ "M" ],
 },
@@ -498,6 +482,14 @@ TstBra => {
        attr_type => "arm_CondJmp_attr_t",
 },
 
+Jmp => {
+       state     => "pinned",
+       op_flags  => "X",
+       irn_flags => "J",
+       reg_req   => { out => [ "none" ] },
+       mode      => "mode_X",
+},
+
 SwitchJmp => {
        op_flags  => "L|X|Y",
        state     => "pinned",
@@ -512,84 +504,95 @@ SwitchJmp => {
 
 # Load / Store
 
-Load => {
+Ldr => {
        op_flags  => "L|F",
-       irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
        reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
        emit      => '. ldr %D0, [%S0, #0]',
-       outs      => [ "res", "M" ],
+       attr_type => "arm_load_store_attr_t",
+       attr      => "ir_entity *entity, int entity_sign, long offset",
 },
 
-Loadb => {
+Ldrb => {
        op_flags  => "L|F",
-       irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
        reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
        emit      => '. ldrb %D0, [%S0, #0]',
-       outs      => [ "res", "M" ],
+       attr_type => "arm_load_store_attr_t",
+       attr      => "ir_entity *entity, int entity_sign, long offset",
 },
 
-Loadbs => {
+Ldrbs => {
        op_flags  => "L|F",
-       irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
        reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
        emit      => '. ldrsb %D0, [%S0, #0]',
-       outs      => [ "res", "M" ],
+       attr_type => "arm_load_store_attr_t",
+       attr      => "ir_entity *entity, int entity_sign, long offset",
 },
 
-Loadh => {
+Ldrh => {
        op_flags  => "L|F",
-       irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
        reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
        emit      => '. ldrh %D0, [%S0, #0]',
-       outs      => [ "res", "M" ],
+       attr_type => "arm_load_store_attr_t",
+       attr      => "ir_entity *entity, int entity_sign, long offset",
 },
 
-Loadhs => {
+Ldrhs => {
        op_flags  => "L|F",
-       irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
        reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
        emit      => '. ldrsh %D0, [%S0, #0]',
-       outs      => [ "res", "M" ],
+       attr_type => "arm_load_store_attr_t",
+       attr      => "ir_entity *entity, int entity_sign, long offset",
 },
 
-Storeb => {
+Strb => {
        op_flags  => "L|F",
-       irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+       ins       => [ "ptr", "val", "mem" ],
+       outs      => [ "mem" ],
        reg_req   => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
        emit      => '. strb %S1, [%S0, #0]',
        mode      => "mode_M",
+       attr_type => "arm_load_store_attr_t",
+       attr      => "ir_entity *entity, int entity_sign, long offset",
 },
 
-Storeh => {
+Strh => {
        op_flags  => "L|F",
-       irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+       ins       => [ "ptr", "val", "mem" ],
+       outs      => [ "mem" ],
        reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
        emit      => '. strh %S1, [%S0, #0]',
        mode      => "mode_M",
+       attr_type => "arm_load_store_attr_t",
+       attr      => "ir_entity *entity, int entity_sign, long offset",
 },
 
-Store => {
+Str => {
        op_flags  => "L|F",
-       irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+       ins       => [ "ptr", "val", "mem" ],
+       outs      => [ "mem" ],
        reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
        emit      => '. str %S1, [%S0, #0]',
        mode      => "mode_M",
+       attr_type => "arm_load_store_attr_t",
+       attr      => "ir_entity *entity, int entity_sign, long offset",
 },
 
 StoreStackM4Inc => {
@@ -639,7 +642,6 @@ fpaAdf_i => {
        comment   => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
        attr      => "long imm",
        init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
        emit      => '. adf%M %D0, %S0, %C',
 },
@@ -657,7 +659,6 @@ fpaMuf_i => {
        comment   => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
        attr      => "long imm",
        init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
        emit      => '. muf%M %D0, %S0, %C',
 },
@@ -700,7 +701,6 @@ fpaSuf_i => {
        comment   => "construct FPA Sub: Sub(a, b) = a - b",
        attr      => "long imm",
        init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
        emit      => '. suf%M %D0, %S0, %C'
 },
@@ -717,7 +717,6 @@ fpaRsf_i => {
        comment   => "construct FPA reverse Sub: Sub(a, b) = b - a",
        attr      => "long imm",
        init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
        emit      => '. rsf%M %D0, %S0, %C'
 },
@@ -735,7 +734,6 @@ fpaDvf_i => {
        comment   => "construct FPA Div: Div(a, b) = a / b",
        attr      => "ir_mode *op_mode, long imm",
        init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
        emit      =>'. dvf%M %D0, %S0, %C',
        outs      => [ "res", "M" ],
@@ -754,7 +752,6 @@ fpaRdf_i => {
        comment   => "construct FPA reverse Div: Div(a, b) = b / a",
        attr      => "ir_mode *op_mode, long imm",
        init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
        emit      =>'. rdf%M %D0, %S0, %S1',
        outs      => [ "res", "M" ],
@@ -773,7 +770,6 @@ fpaFdv_i => {
        comment   => "construct FPA Fast Div: Div(a, b) = a / b",
        attr      => "ir_mode *op_mode, long imm",
        init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
        emit      =>'. fdv%M %D0, %S0, %C',
        outs      => [ "res", "M" ],
@@ -792,7 +788,6 @@ fpaFrd_i => {
        comment   => "construct FPA Fast reverse Div: Div(a, b) = b / a",
        attr      => "ir_mode *op_mode, long imm",
        init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;',
        reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
        emit      =>'. frd%M %D0, %S0, %C',
        outs      => [ "res", "M" ],
@@ -812,7 +807,6 @@ fpaMvf_i => {
        init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
        reg_req   => { "out" => [ "fpa" ] },
        emit      => '. mvf%M %D0, %C',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;'
 },
 
 fpaMnf => {
@@ -829,7 +823,6 @@ fpaMnf_i => {
        init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
        reg_req   => { "out" => [ "fpa" ] },
        emit      => '. mnf%M %D0, %C',
-       cmp_attr  => 'return attr_a->imm_value != attr_b->imm_value;'
 },
 
 fpaAbs => {
index acf7945..73055ef 100644 (file)
@@ -339,6 +339,7 @@ static ir_node *gen_Add(ir_node *node) {
                        return new_bd_arm_Mla(dbg, block, new_op1, new_op2, new_op3, mode);
                }
 
+#if 0
                /* is the first a shifter */
                v = is_shifter_operand(new_op1, &mod);
                if (v) {
@@ -351,6 +352,7 @@ static ir_node *gen_Add(ir_node *node) {
                        new_op2 = get_irn_n(new_op2, 0);
                        return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, mod, v);
                }
+#endif
 
                /* normal ADD */
                return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
@@ -820,13 +822,16 @@ static ir_node *gen_Load(ir_node *node) {
                        /* sign extended loads */
                        switch (get_mode_size_bits(mode)) {
                        case 8:
-                               new_load = new_bd_arm_Loadbs(dbg, block, new_ptr, new_mem);
+                               new_load = new_bd_arm_Ldrbs(dbg, block, new_ptr, new_mem, NULL,
+                                                           0, 0);
                                break;
                        case 16:
-                               new_load = new_bd_arm_Loadhs(dbg, block, new_ptr, new_mem);
+                               new_load = new_bd_arm_Ldrhs(dbg, block, new_ptr, new_mem, NULL,
+                                                           0, 0);
                                break;
                        case 32:
-                               new_load = new_bd_arm_Load(dbg, block, new_ptr, new_mem);
+                               new_load = new_bd_arm_Ldr(dbg, block, new_ptr, new_mem, NULL,
+                                                         0, 0);
                                break;
                        default:
                                panic("mode size not supported");
@@ -835,13 +840,16 @@ static ir_node *gen_Load(ir_node *node) {
                        /* zero extended loads */
                        switch (get_mode_size_bits(mode)) {
                        case 8:
-                               new_load = new_bd_arm_Loadb(dbg, block, new_ptr, new_mem);
+                               new_load = new_bd_arm_Ldrb(dbg, block, new_ptr, new_mem, NULL,
+                                                          0, 0);
                                break;
                        case 16:
-                               new_load = new_bd_arm_Loadh(dbg, block, new_ptr, new_mem);
+                               new_load = new_bd_arm_Ldrh(dbg, block, new_ptr, new_mem, NULL,
+                                                          0, 0);
                                break;
                        case 32:
-                               new_load = new_bd_arm_Load(dbg, block, new_ptr, new_mem);
+                               new_load = new_bd_arm_Ldr(dbg, block, new_ptr, new_mem, NULL,
+                                                         0, 0);
                                break;
                        default:
                                panic("mode size not supported");
@@ -853,7 +861,7 @@ static ir_node *gen_Load(ir_node *node) {
        /* check for special case: the loaded value might not be used */
        if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
                /* add a result proj and a Keep to produce a pseudo use */
-               ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Load_res);
+               ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Ldr_res);
                be_new_Keep(block, 1, &proj);
        }
 
@@ -865,7 +873,8 @@ static ir_node *gen_Load(ir_node *node) {
  *
  * @return the created ARM Store node
  */
-static ir_node *gen_Store(ir_node *node) {
+static ir_node *gen_Store(ir_node *node)
+{
        ir_node  *block    = be_transform_node(get_nodes_block(node));
        ir_node  *ptr      = get_Store_ptr(node);
        ir_node  *new_ptr  = be_transform_node(ptr);
@@ -891,17 +900,34 @@ static ir_node *gen_Store(ir_node *node) {
                assert(mode_is_data(mode) && "unsupported mode for Store");
                switch (get_mode_size_bits(mode)) {
                case 8:
-                       new_store = new_bd_arm_Storeb(dbg, block, new_ptr, new_val, new_mem);
+                       new_store = new_bd_arm_Strb(dbg, block, new_ptr, new_val, new_mem,
+                                                   NULL, 0, 0);
+                       break;
                case 16:
-                       new_store = new_bd_arm_Storeh(dbg, block, new_ptr, new_val, new_mem);
+                       new_store = new_bd_arm_Strh(dbg, block, new_ptr, new_val, new_mem,
+                                                   NULL, 0, 0);
+                       break;
+               case 32:
+                       new_store = new_bd_arm_Str(dbg, block, new_ptr, new_val, new_mem,
+                                                  NULL, 0, 0);
+                       break;
                default:
-                       new_store = new_bd_arm_Store(dbg, block, new_ptr, new_val, new_mem);
+                       panic("unsupported store size %d bits\n", get_mode_size_bits(mode));
                }
        }
        set_irn_pinned(new_store, get_irn_pinned(node));
        return new_store;
 }
 
+static ir_node *gen_Jmp(ir_node *node)
+{
+       ir_node  *block     = get_nodes_block(node);
+       ir_node  *new_block = be_transform_node(block);
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+
+       return new_bd_arm_Jmp(dbgi, new_block);
+}
+
 /**
  * Transforms a Cond.
  *
@@ -1276,16 +1302,16 @@ static ir_node *gen_Proj_Load(ir_node *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:
+       case iro_arm_Ldr:
+       case iro_arm_Ldrb:
+       case iro_arm_Ldrbs:
+       case iro_arm_Ldrh:
+       case iro_arm_Ldrhs:
                /* handle all gp loads equal: they have the same proj numbers. */
                if (proj == pn_Load_res) {
-                       return new_rd_Proj(dbgi, block, new_load, mode_Iu, pn_arm_Load_res);
+                       return new_rd_Proj(dbgi, block, new_load, mode_Iu, pn_arm_Ldr_res);
                } else if (proj == pn_Load_M) {
-                       return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_Load_M);
+                       return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_Ldr_M);
                }
                break;
        case iro_arm_fpaLdf:
@@ -1536,7 +1562,9 @@ static ir_node *gen_Unknown(ir_node *node) {
 /**
  * Change some phi modes
  */
-static ir_node *gen_Phi(ir_node *node) {
+static ir_node *gen_Phi(ir_node *node)
+{
+       const arch_register_req_t *req;
        ir_node  *block = be_transform_node(get_nodes_block(node));
        ir_graph *irg   = current_ir_graph;
        dbg_info *dbgi  = get_irn_dbg_info(node);
@@ -1548,14 +1576,20 @@ static ir_node *gen_Phi(ir_node *node) {
                assert(get_mode_size_bits(mode) <= 32);
                /* all integer operations are on 32bit registers now */
                mode = mode_Iu;
+               req  = arm_reg_classes[CLASS_arm_gp].class_req;
+       } else {
+               req = arch_no_register_req;
        }
 
        /* 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);
+       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);
 
+       arch_set_out_register_req(phi, 0, req);
+
        be_enqueue_preds(node);
 
        return phi;
@@ -1624,6 +1658,7 @@ static void arm_register_transformers(void) {
        GEN(Load);
        GEN(Store);
        GEN(Cond);
+       GEN(Jmp);
 
        BAD(ASM);       /* unsupported yet */
        GEN(CopyB);
index fe90c96..1add634 100644 (file)
@@ -186,10 +186,41 @@ static void arm_before_ra(void *self)
        /* Some stuff you need to do immediately after register allocation */
 }
 
-/**
- * We transform Spill and Reload here. This needs to be done before
- * stack biasing otherwise we would miss the corrected offset for these nodes.
- */
+#if 0
+static void transform_Reload(ir_node *node)
+{
+       ir_graph  *irg    = get_irn_irg(node);
+       ir_node   *block  = get_nodes_block(node);
+       dbg_info  *dbgi   = get_irn_dbg_info(node);
+       ir_node   *ptr    = get_irg_frame(irg);
+       ir_node   *mem    = get_irn_n(node, be_pos_Reload_mem);
+       ir_entity *entity = be_get_frame_entity(node);
+       ir_node   *load;
+
+       ir_node  *sched_point = sched_prev(node);
+
+       load = new_bd_arm_Ldr(dbgi, block, ptr, mem, entity, false, 0);
+}
+
+static void after_ra_walker(ir_node *block, void *data)
+{
+       ir_node *node, *prev;
+       (void) data;
+
+       for (node = sched_last(block); !sched_is_begin(node); node = prev) {
+               prev = sched_prev(node);
+
+               if (be_is_Reload(node)) {
+                       transform_Reload(node);
+               } else if (be_is_Spill(node)) {
+                       transform_Spill(node);
+               } else if (be_is_MemPerm(node)) {
+                       panic("memperm not implemented yet");
+               }
+       }
+}
+#endif
+
 static void arm_after_ra(void *self)
 {
        arm_code_gen_t *cg = self;
@@ -632,6 +663,8 @@ static arch_env_t *arm_init(FILE *file_handle) {
        arm_create_opcodes(&arm_irn_ops);
        arm_handle_intrinsics();
 
+       be_gas_emit_types = false;
+
        /* needed for the debug support */
        be_gas_emit_switch_section(GAS_SECTION_TEXT);
        be_emit_cstring(".Ltext0:\n");
@@ -816,7 +849,8 @@ static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap *
 /**
  * Builds the ARM epilogue
  */
-static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map) {
+static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
+{
        arm_abi_env_t *env = self;
        ir_node *curr_sp = be_abi_reg_map_get(reg_map, env->arch_env->sp);
        ir_node *curr_bp = be_abi_reg_map_get(reg_map, env->arch_env->bp);
@@ -825,13 +859,8 @@ static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_m
 
        // TODO: Activate Omit fp in epilogue
        if (env->flags.try_omit_fp) {
-               curr_sp = be_new_IncSP(env->arch_env->sp, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
-
-               curr_lr = be_new_CopyKeep_single(&arm_reg_classes[CLASS_arm_gp], bl, curr_lr, curr_sp, get_irn_mode(curr_lr));
-               be_set_constr_single_reg_out(curr_lr, 0, &arm_gp_regs[REG_LR], 0);
-
-               curr_pc = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], bl, curr_lr );
-               be_set_constr_single_reg_out(curr_pc, BE_OUT_POS(0), &arm_gp_regs[REG_PC], 0);
+               ir_node *incsp = be_new_IncSP(env->arch_env->sp, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
+               curr_sp = incsp;
        } else {
                ir_node *load_node;