- refactoring of backend generator scripts: You can create multiple constructors
authorMatthias Braun <matze@braunis.de>
Thu, 1 Oct 2009 16:43:13 +0000 (16:43 +0000)
committerMatthias Braun <matze@braunis.de>
Thu, 1 Oct 2009 16:43:13 +0000 (16:43 +0000)
  (with different arguments and register constraints for the same node now)
- Lots of cleanups/changes in the arm backend. We can represent all
  "shifter operands" now (but the code selection isn't optimal yet)
- More fixes all over the place - arm backend handles 164.gzip now

[r26673]

24 files changed:
ir/be/TEMPLATE/TEMPLATE_new_nodes.c
ir/be/TEMPLATE/TEMPLATE_spec.pl
ir/be/TEMPLATE/TEMPLATE_transform.c
ir/be/TEMPLATE/bearch_TEMPLATE.c
ir/be/arm/arm_emitter.c
ir/be/arm/arm_emitter.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_optimize.c
ir/be/arm/arm_optimize.h
ir/be/arm/arm_spec.pl
ir/be/arm/arm_transform.c
ir/be/arm/bearch_arm.c
ir/be/beabi.c
ir/be/beflags.c
ir/be/bespillslots.c
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_simd_spec.pl [deleted file]
ir/be/ia32/ia32_spec.pl
ir/be/mips/mips_spec.pl
ir/be/ppc32/ppc32_spec.pl
ir/be/scripts/generate_new_opcodes.pl
ir/opt/code_placement.c

index 095a918..100150b 100644 (file)
 #include "TEMPLATE_new_nodes.h"
 #include "gen_TEMPLATE_regalloc_if.h"
 
-
-
-/***********************************************************************************
- *      _                                   _       _             __
- *     | |                                 (_)     | |           / _|
- *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
- *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
- * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
- *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
- *                       | |
- *                       |_|
- ***********************************************************************************/
-
 /**
  * Dumper interface for dumping TEMPLATE nodes in vcg.
  * @param n        the node to dump
@@ -99,17 +86,6 @@ static int TEMPLATE_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
        return 0;
 }
 
-/***************************************************************************************************
- *        _   _                   _       __        _                    _   _               _
- *       | | | |                 | |     / /       | |                  | | | |             | |
- *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
- *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
- * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
- *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
- *                                        __/ |
- *                                       |___/
- ***************************************************************************************************/
-
 const TEMPLATE_attr_t *get_TEMPLATE_attr_const(const ir_node *node)
 {
        assert(is_TEMPLATE_irn(node) && "need TEMPLATE node to get attributes");
@@ -171,16 +147,6 @@ void init_TEMPLATE_attributes(ir_node *node, arch_irn_flags_t flags,
        memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
 }
 
-/***************************************************************************************
- *                  _                            _                   _
- *                 | |                          | |                 | |
- *  _ __   ___   __| | ___    ___ ___  _ __  ___| |_ _ __ _   _  ___| |_ ___  _ __ ___
- * | '_ \ / _ \ / _` |/ _ \  / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
- * | | | | (_) | (_| |  __/ | (_| (_) | | | \__ \ |_| |  | |_| | (__| || (_) | |  \__ \
- * |_| |_|\___/ \__,_|\___|  \___\___/|_| |_|___/\__|_|   \__,_|\___|\__\___/|_|  |___/
- *
- ***************************************************************************************/
-
 static int TEMPLATE_compare_attr(ir_node *a, ir_node *b)
 {
        const TEMPLATE_attr_t *attr_a = get_TEMPLATE_attr_const(a);
@@ -191,6 +157,5 @@ static int TEMPLATE_compare_attr(ir_node *a, ir_node *b)
        return 0;
 }
 
-
 /* Include the generated constructor functions */
 #include "gen_TEMPLATE_new_nodes.c.inl"
index 49d31a9..f24a58d 100644 (file)
@@ -1,6 +1,5 @@
 # Creation: 2006/02/13
 # $Id$
-# This is a template specification for the Firm-Backend
 
 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
 
index 28c0505..289cf78 100644 (file)
@@ -286,15 +286,6 @@ static ir_node *gen_Jmp(TEMPLATE_transform_env_t *env)
        return new_bd_TEMPLATE_Jmp(env->dbg, env->block);
 }
 
-/*********************************************************
- *                  _             _      _
- *                 (_)           | |    (_)
- *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
- * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
- * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
- * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
- *
- *********************************************************/
 
 
 
@@ -404,8 +395,7 @@ bad:
        if (asm_node) {
                exchange(node, asm_node);
                DB((dbg, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
-       }
-       else {
+       } else {
                DB((dbg, LEVEL_1, "ignored\n"));
        }
 }
index e00e5c3..4e0a233 100644 (file)
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
-/**************************************************
- *                         _ _              _  __
- *                        | | |            (_)/ _|
- *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
- * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
- * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
- * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
- *            __/ |
- *           |___/
- **************************************************/
-
 static arch_irn_class_t TEMPLATE_classify(const ir_node *irn)
 {
        (void) irn;
@@ -116,16 +105,7 @@ static const arch_irn_ops_t TEMPLATE_irn_ops = {
        NULL,    /* perform_memory_operand  */
 };
 
-/**************************************************
- *                _                         _  __
- *               | |                       (_)/ _|
- *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
- *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
- * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
- *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
- *                        __/ |
- *                       |___/
- **************************************************/
+
 
 /**
  * Transforms the standard firm graph into
@@ -214,16 +194,6 @@ static void *TEMPLATE_cg_init(be_irg_t *birg)
 
 
 
-/*****************************************************************
- *  ____             _                  _   _____  _____
- * |  _ \           | |                | | |_   _|/ ____|  /\
- * | |_) | __ _  ___| | _____ _ __   __| |   | | | (___   /  \
- * |  _ < / _` |/ __| |/ / _ \ '_ \ / _` |   | |  \___ \ / /\ \
- * | |_) | (_| | (__|   <  __/ | | | (_| |  _| |_ ____) / ____ \
- * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/    \_\
- *
- *****************************************************************/
-
 const arch_isa_if_t TEMPLATE_isa_if;
 static TEMPLATE_isa_t TEMPLATE_isa_template = {
        {
@@ -240,7 +210,7 @@ static TEMPLATE_isa_t TEMPLATE_isa_template = {
 };
 
 /**
- * Initializes the backend ISA and opens the output file.
+ * Initializes the backend ISA
  */
 static arch_env_t *TEMPLATE_init(FILE *outfile)
 {
index bad7fb0..62a8d85 100644 (file)
@@ -68,7 +68,8 @@ static set                  *sym_or_tv;
 /**
  * Returns the register at in position pos.
  */
-static const arch_register_t *get_in_reg(const ir_node *irn, int pos) {
+static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
+{
        ir_node                *op;
        const arch_register_t  *reg = NULL;
 
@@ -133,17 +134,6 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos)
     return reg;
 }
 
-/*************************************************************
- *             _       _    __   _          _
- *            (_)     | |  / _| | |        | |
- *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
- * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
- * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
- * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
- * | |                                       | |
- * |_|                                       |_|
- *************************************************************/
-
 /**
  * Emit the name of the source register at given input position.
  */
@@ -163,18 +153,12 @@ void arm_emit_dest_register(const ir_node *node, int pos) {
 /**
  * Emit a node's offset.
  */
-void arm_emit_offset(const ir_node *node) {
-       int offset = 0;
-       ir_opcode opc = get_irn_opcode(node);
+void arm_emit_offset(const ir_node *node)
+{
+       const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
+       assert(attr->base.is_load_store);
 
-       if (opc == beo_Reload || opc == beo_Spill) {
-               ir_entity *ent = be_get_frame_entity(node);
-               offset = get_entity_offset(ent);
-       } else {
-               assert(!"unimplemented arm_emit_offset for this node type");
-               panic("unimplemented arm_emit_offset for this node type");
-       }
-       be_emit_irprintf("%d", offset);
+       be_emit_irprintf("0x%X", attr->offset);
 }
 
 /**
@@ -209,32 +193,119 @@ void arm_emit_mode(const ir_node *node) {
 /**
  * Emit a const or SymConst value.
  */
-void arm_emit_immediate(const ir_node *node) {
+void arm_emit_immediate(const ir_node *node)
+{
        const arm_attr_t *attr = get_arm_attr_const(node);
 
-       if (ARM_GET_SHF_MOD(attr) == ARM_SHF_IMM) {
-               be_emit_irprintf("#0x%X", arm_decode_imm_w_shift(get_arm_imm_value(node)));
-       } else if (ARM_GET_FPA_IMM(attr)) {
-               be_emit_irprintf("#%s", arm_get_fpa_imm_name(get_arm_imm_value(node)));
-       } else if (is_arm_SymConst(node))
-               be_emit_ident(get_arm_symconst_id(node));
-       else {
+       if (ARM_GET_FPA_IMM(attr)) {
+               /* TODO */
+               //be_emit_irprintf("#%s", arm_get_fpa_imm_name(get_arm_imm_value(node)));
+       } else {
                assert(!"not a Constant");
        }
 }
 
-/**
- * Returns the tarval or offset of an arm node as a string.
- */
-void arm_emit_shift(const ir_node *node) {
-       arm_shift_modifier mod;
+void arm_emit_load_mode(const ir_node *node)
+{
+       const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
+       ir_mode *mode      = attr->load_store_mode;
+       int      bits      = get_mode_size_bits(mode);
+       bool     is_signed = mode_is_signed(mode);
+       if (bits == 16) {
+               be_emit_string(is_signed ? "sh" : "h");
+       } else if (bits == 8) {
+               be_emit_string(is_signed ? "sb" : "b");
+       } else {
+               assert(bits == 32);
+       }
+}
+
+void arm_emit_store_mode(const ir_node *node)
+{
+       const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
+       ir_mode *mode      = attr->load_store_mode;
+       int      bits      = get_mode_size_bits(mode);
+       if (bits == 16) {
+               be_emit_cstring("h");
+       } else if (bits == 8) {
+               be_emit_cstring("b");
+       } else {
+               assert(bits == 32);
+       }
+}
+
+
+static void emit_shf_mod_name(arm_shift_modifier mod)
+{
+       switch (mod) {
+       case ARM_SHF_ASR_REG:
+       case ARM_SHF_ASR_IMM:
+               be_emit_cstring("asr");
+               return;
+       case ARM_SHF_LSL_REG:
+       case ARM_SHF_LSL_IMM:
+               be_emit_cstring("lsl");
+               return;
+       case ARM_SHF_LSR_REG:
+       case ARM_SHF_LSR_IMM:
+               be_emit_cstring("lsr");
+               return;
+       case ARM_SHF_ROR_REG:
+       case ARM_SHF_ROR_IMM:
+               be_emit_cstring("ror");
+               return;
+       default:
+               break;
+       }
+       panic("can't emit this shf_mod_name %d", (int) mod);
+}
+
+void arm_emit_shifter_operand(const ir_node *node)
+{
+       const arm_shifter_operand_t *attr = get_irn_generic_attr_const(node);
 
-       mod = get_arm_shift_modifier(node);
-       if (ARM_HAS_SHIFT(mod)) {
-               int v = get_arm_imm_value(node);
+       switch (attr->shift_modifier) {
+       case ARM_SHF_REG:
+               arm_emit_source_register(node, get_irn_arity(node) - 1);
+               return;
+       case ARM_SHF_IMM: {
+               unsigned val = attr->immediate_value;
+               val = (val >> attr->shift_immediate)
+                       | (val << (32-attr->shift_immediate));
+               val &= 0xFFFFFFFF;
+               be_emit_irprintf("#0x%X", val);
+               return;
+       }
+       case ARM_SHF_ASR_IMM:
+       case ARM_SHF_LSL_IMM:
+       case ARM_SHF_LSR_IMM:
+       case ARM_SHF_ROR_IMM:
+               arm_emit_source_register(node, get_irn_arity(node) - 1);
+               be_emit_cstring(", ");
+               emit_shf_mod_name(attr->shift_modifier);
+               be_emit_irprintf(" #0x%X", attr->shift_immediate);
+               return;
+
+       case ARM_SHF_ASR_REG:
+       case ARM_SHF_LSL_REG:
+       case ARM_SHF_LSR_REG:
+       case ARM_SHF_ROR_REG:
+               arm_emit_source_register(node, get_irn_arity(node) - 2);
+               be_emit_cstring(", ");
+               emit_shf_mod_name(attr->shift_modifier);
+               be_emit_cstring(" ");
+               arm_emit_source_register(node, get_irn_arity(node) - 1);
+               return;
+
+       case ARM_SHF_RRX:
+               arm_emit_source_register(node, get_irn_arity(node) - 1);
+               panic("RRX shifter emitter TODO");
+               return;
 
-               be_emit_irprintf(", %s #%d", arm_shf_mod_name(mod), v);
+       case ARM_SHF_INVALID:
+               break;
        }
+       panic("Invalid shift_modifier while emitting %+F", node);
 }
 
 /** An entry in the sym_or_tv set. */
@@ -259,11 +330,15 @@ static unsigned get_unique_label(void) {
 /**
  * Emit a SymConst.
  */
-static void emit_arm_SymConst(const ir_node *irn) {
+static void emit_arm_SymConst(const ir_node *irn)
+{
+       const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
        sym_or_tv_t key, *entry;
        unsigned label;
 
-       key.u.id     = get_arm_symconst_id(irn);
+       set_entity_backend_marked(attr->entity, 1);
+
+       key.u.id     = get_entity_ld_ident(attr->entity);
        key.is_ident = 1;
        key.label    = 0;
        entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
@@ -280,6 +355,19 @@ static void emit_arm_SymConst(const ir_node *irn) {
        be_emit_finish_line_gas(irn);
 }
 
+static void emit_arm_FrameAddr(const ir_node *irn)
+{
+       const arm_SymConst_attr_t *attr = get_irn_generic_attr_const(irn);
+
+       be_emit_cstring("\tadd ");
+       arm_emit_dest_register(irn, 0);
+       be_emit_cstring(", ");
+       arm_emit_source_register(irn, 0);
+       be_emit_cstring(", ");
+       be_emit_irprintf("#0x%X", attr->fp_offset);
+       be_emit_finish_line_gas(irn);
+}
+
 /**
  * Emit a floating point fpa constant.
  */
@@ -348,16 +436,20 @@ static void arm_emit_cfop_target(const ir_node *irn) {
 /**
  * Emit a Compare with conditional branch.
  */
-static void emit_arm_CmpBra(const ir_node *irn) {
+static void emit_arm_B(const ir_node *irn)
+{
        const ir_edge_t *edge;
        const ir_node *proj_true  = NULL;
        const ir_node *proj_false = NULL;
        const ir_node *block;
        const ir_node *next_block;
        ir_node *op1 = get_irn_n(irn, 0);
-       ir_mode *opmode = get_irn_mode(op1);
        const char *suffix;
        int proj_num = get_arm_CondJmp_proj_num(irn);
+       const arm_cmp_attr_t *cmp_attr = get_irn_generic_attr_const(op1);
+       bool is_signed = !cmp_attr->is_unsigned;
+
+       assert(is_arm_Cmp(op1) || is_arm_Tst(op1));
 
        foreach_out_edge(irn, edge) {
                ir_node *proj = get_edge_src_irn(edge);
@@ -369,102 +461,8 @@ static void emit_arm_CmpBra(const ir_node *irn) {
                }
        }
 
-       /* for now, the code works for scheduled and non-schedules blocks */
-       block = get_nodes_block(irn);
-
-       /* we have a block schedule */
-       next_block = sched_next_block(block);
-
-       if (proj_num == pn_Cmp_False) {
-               /* always false: should not happen */
-               be_emit_cstring("\tb ");
-               arm_emit_cfop_target(proj_false);
-               be_emit_finish_line_gas(proj_false);
-       } else if (proj_num == pn_Cmp_True) {
-               /* always true: should not happen */
-               be_emit_cstring("\tb ");
-               arm_emit_cfop_target(proj_true);
-               be_emit_finish_line_gas(proj_true);
-       } else {
-               if (mode_is_float(opmode)) {
-                       suffix = "ICHWILLIMPLEMENTIERTWERDEN";
-
-                       be_emit_cstring("\tfcmp ");
-                       arm_emit_source_register(irn, 0);
-                       be_emit_cstring(", ");
-                       arm_emit_source_register(irn, 1);
-                       be_emit_finish_line_gas(irn);
-
-                       be_emit_cstring("\tfmstat");
-                       be_emit_pad_comment();
-                       be_emit_cstring("/* FCSPR -> CPSR */");
-                       be_emit_finish_line_gas(NULL);
-               } else {
-                       if (get_cfop_target_block(proj_true) == next_block) {
-                               /* exchange both proj's so the second one can be omitted */
-                               const ir_node *t = proj_true;
-
-                               proj_true  = proj_false;
-                               proj_false = t;
-                               proj_num   = get_negated_pnc(proj_num, mode_Iu);
-                       }
-                       switch (proj_num) {
-                               case pn_Cmp_Eq:  suffix = "eq"; break;
-                               case pn_Cmp_Lt:  suffix = "lt"; break;
-                               case pn_Cmp_Le:  suffix = "le"; break;
-                               case pn_Cmp_Gt:  suffix = "gt"; break;
-                               case pn_Cmp_Ge:  suffix = "ge"; break;
-                               case pn_Cmp_Lg:  suffix = "ne"; break;
-                               case pn_Cmp_Leg: suffix = "al"; break;
-                               default: assert(!"Cmp unsupported"); suffix = "al";
-                       }
-                       be_emit_cstring("\tcmp ");
-                       arm_emit_source_register(irn, 0);
-                       be_emit_cstring(", ");
-                       arm_emit_source_register(irn, 1);
-                       be_emit_finish_line_gas(irn);
-               }
-
-               /* emit the true proj */
-               be_emit_irprintf("\tb%s ", suffix);
-               arm_emit_cfop_target(proj_true);
-               be_emit_finish_line_gas(proj_true);
-
-               if (get_cfop_target_block(proj_false) == next_block) {
-                       be_emit_cstring("\t/* fallthrough to ");
-                       arm_emit_cfop_target(proj_false);
-                       be_emit_cstring(" */");
-                       be_emit_finish_line_gas(proj_false);
-               } else {
-                       be_emit_cstring("\tb ");
-                       arm_emit_cfop_target(proj_false);
-                       be_emit_finish_line_gas(proj_false);
-               }
-       }
-}
-
-
-/**
- * Emit a Tst with conditional branch.
- */
-static void emit_arm_TstBra(const ir_node *irn)
-{
-       const ir_edge_t *edge;
-       const ir_node *proj_true  = NULL;
-       const ir_node *proj_false = NULL;
-       const ir_node *block;
-       const ir_node *next_block;
-       const char *suffix;
-       int proj_num = get_arm_CondJmp_proj_num(irn);
-
-       foreach_out_edge(irn, edge) {
-               ir_node *proj = get_edge_src_irn(edge);
-               long nr = get_Proj_proj(proj);
-               if (nr == pn_Cond_true) {
-                       proj_true = proj;
-               } else {
-                       proj_false = proj;
-               }
+       if (cmp_attr->ins_permuted) {
+               proj_num = get_mirrored_pnc(proj_num);
        }
 
        /* for now, the code works for scheduled and non-schedules blocks */
@@ -484,21 +482,17 @@ static void emit_arm_TstBra(const ir_node *irn)
                proj_false = t;
                proj_num   = get_negated_pnc(proj_num, mode_Iu);
        }
+
        switch (proj_num) {
                case pn_Cmp_Eq:  suffix = "eq"; break;
-               case pn_Cmp_Lt:  suffix = "lt"; break;
-               case pn_Cmp_Le:  suffix = "le"; break;
-               case pn_Cmp_Gt:  suffix = "gt"; break;
-               case pn_Cmp_Ge:  suffix = "ge"; break;
+               case pn_Cmp_Lt:  suffix = is_signed ? "lt" : "lo"; break;
+               case pn_Cmp_Le:  suffix = is_signed ? "le" : "ls"; break;
+               case pn_Cmp_Gt:  suffix = is_signed ? "gt" : "hi"; break;
+               case pn_Cmp_Ge:  suffix = is_signed ? "ge" : "hs"; break;
                case pn_Cmp_Lg:  suffix = "ne"; break;
                case pn_Cmp_Leg: suffix = "al"; break;
-               default: assert(!"Cmp unsupported"); suffix = "al";
+               default: panic("Cmp has unsupported pnc");
        }
-       be_emit_cstring("\ttst ");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", ");
-       arm_emit_source_register(irn, 1);
-       be_emit_finish_line_gas(irn);
 
        /* emit the true proj */
        be_emit_irprintf("\tb%s ", suffix);
@@ -511,26 +505,12 @@ static void emit_arm_TstBra(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);
        }
 }
 
-/**
- * Emit a Compare with conditional branch.
- */
-static void emit_arm_fpaCmfBra(const ir_node *irn) {
-       (void) irn;
-}
-
-/**
- * Emit a Compare with conditional branch.
- */
-static void emit_arm_fpaCmfeBra(const ir_node *irn) {
-       (void) irn;
-}
-
 /** Sort register in ascending order. */
 static int reg_cmp(const void *a, const void *b) {
        const arch_register_t * const *ra = a;
@@ -542,8 +522,10 @@ static int reg_cmp(const void *a, const void *b) {
 /**
  * Create the CopyB instruction sequence.
  */
-static void emit_arm_CopyB(const ir_node *irn) {
-       unsigned size = (unsigned)get_arm_imm_value(irn);
+static void emit_arm_CopyB(const ir_node *irn)
+{
+       const arm_CopyB_attr_t *attr = get_irn_generic_attr_const(irn);
+       unsigned size = attr->size;
 
        const char *tgt = arch_register_get_name(get_in_reg(irn, 0));
        const char *src = arch_register_get_name(get_in_reg(irn, 1));
@@ -840,66 +822,6 @@ static void emit_be_Copy(const ir_node *irn) {
        }
 }
 
-/**
- * Emit code for a Spill.
- */
-static void emit_be_Spill(const ir_node *irn) {
-       ir_mode *mode = get_irn_mode(be_get_Spill_val(irn));
-
-       if (mode_is_float(mode)) {
-               if (USE_FPA(cg->isa)) {
-                       be_emit_cstring("\tstf");
-                       arm_emit_fpa_postfix(mode);
-                       be_emit_char(' ');
-               } else {
-                       assert(0 && "spill not supported for this mode");
-                       panic("emit_be_Spill: spill not supported for this mode");
-               }
-       } else if (mode_is_dataM(mode)) {
-               be_emit_cstring("\tstr ");
-       } else {
-               assert(0 && "spill not supported for this mode");
-               panic("emit_be_Spill: spill not supported for this mode");
-       }
-       arm_emit_source_register(irn, 1);
-       be_emit_cstring(", [");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", #");
-       arm_emit_offset(irn);
-       be_emit_char(']');
-       be_emit_finish_line_gas(irn);
-}
-
-/**
- * Emit code for a Reload.
- */
-static void emit_be_Reload(const ir_node *irn) {
-       ir_mode *mode = get_irn_mode(irn);
-
-       if (mode_is_float(mode)) {
-               if (USE_FPA(cg->isa)) {
-                       be_emit_cstring("\tldf");
-                       arm_emit_fpa_postfix(mode);
-                       be_emit_char(' ');
-               } else {
-                       assert(0 && "reload not supported for this mode");
-                       panic("emit_be_Reload: reload not supported for this mode");
-               }
-       } else if (mode_is_dataM(mode)) {
-               be_emit_cstring("\tldr ");
-       } else {
-               assert(0 && "reload not supported for this mode");
-               panic("emit_be_Reload: reload not supported for this mode");
-       }
-       arm_emit_dest_register(irn, 0);
-       be_emit_cstring(", [");
-       arm_emit_source_register(irn, 0);
-       be_emit_cstring(", #");
-       arm_emit_offset(irn);
-       be_emit_char(']');
-       be_emit_finish_line_gas(irn);
-}
-
 static void emit_be_Perm(const ir_node *irn)
 {
        be_emit_cstring("\teor ");
@@ -1024,16 +946,6 @@ static void emit_arm_LdTls(const ir_node *irn) {
        /* Er... our gcc does not support it... Install a newer toolchain. */
 }
 
-/***********************************************************************************
- *                  _          __                                             _
- *                 (_)        / _|                                           | |
- *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
- * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
- * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
- * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
- *
- ***********************************************************************************/
-
 static void emit_nothing(const ir_node *irn)
 {
        (void) irn;
@@ -1065,25 +977,22 @@ static void arm_register_emitters(void)
        arm_register_spec_emitters();
 
        /* custom emitter */
-       set_emitter(op_arm_CmpBra,     emit_arm_CmpBra);
+       set_emitter(op_arm_B,          emit_arm_B);
        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_FrameAddr,  emit_arm_FrameAddr);
        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_CopyKeep,    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);
index 0048dd3..0faeea4 100644 (file)
@@ -39,8 +39,10 @@ void arm_emit_mode(const ir_node *node);
 void arm_emit_source_register(const ir_node *node, int pos);
 void arm_emit_dest_register(const ir_node *node, int pos);
 void arm_emit_offset(const ir_node *node);
-void arm_emit_immediate(const ir_node *node);
 void arm_emit_shift(const ir_node *node);
+void arm_emit_shifter_operand(const ir_node *node);
+void arm_emit_load_mode(const ir_node *node);
+void arm_emit_store_mode(const ir_node *node);
 
 void arm_gen_routine(const arm_code_gen_t *cg, ir_graph *irg);
 
index 9f052ff..051e527 100644 (file)
 #include "../beabi.h"
 #include "bearch_arm_t.h"
 
-/**
- * Returns the shift modifier string.
- */
-const char *arm_shf_mod_name(arm_shift_modifier mod) {
-       static const char *names[] = { NULL, NULL, "asr", "lsl", "lsr", "ror", "rrx" };
-       return names[mod];
-}
-
 /**
  * Return the fpa immediate from the encoding.
  */
@@ -74,16 +66,6 @@ const char *arm_get_fpa_imm_name(long imm_value) {
        return fpa_imm[imm_value];
 }
 
-/***********************************************************************************
- *      _                                   _       _             __
- *     | |                                 (_)     | |           / _|
- *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
- *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
- * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
- *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
- *                       | |
- *                       |_|
- ***********************************************************************************/
 
 /**
  * Dumper interface for dumping arm nodes in vcg.
@@ -95,8 +77,7 @@ const char *arm_get_fpa_imm_name(long imm_value) {
 static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
 {
        ir_mode     *mode = NULL;
-       arm_attr_t  *attr = get_arm_attr(n);
-       arm_shift_modifier        mod;
+       //arm_attr_t  *attr = get_arm_attr(n);
 
        switch (reason) {
                case dump_node_opcode_txt:
@@ -115,33 +96,31 @@ static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
                        break;
 
                case dump_node_nodeattr_txt:
-                       mod = ARM_GET_SHF_MOD(attr);
-                       if (ARM_HAS_SHIFT(mod)) {
-                               fprintf(F, "[%s #%ld]", arm_shf_mod_name(mod), attr->imm_value);
-                       }
-                       else if (mod == ARM_SHF_IMM) {
-                               /* immediate */
-                               fprintf(F, "[#0x%X]", arm_decode_imm_w_shift(attr->imm_value));
-                       }
+                       /* TODO: dump shift modifiers */
                        break;
 
                case dump_node_info_txt:
                        arch_dump_reqs_and_registers(F, n);
 
                        if (is_arm_CopyB(n)) {
-                               fprintf(F, "size = %lu\n", get_arm_imm_value(n));
+                               //fprintf(F, "size = %lu\n", get_arm_imm_value(n));
                        } else {
+                               /* TODO */
+#if 0
                                long v =  get_arm_imm_value(n);
                                if (ARM_GET_FPA_IMM(attr)) {
                                        fprintf(F, "immediate float value = %s\n", arm_get_fpa_imm_name(v));
                                } else {
                                        fprintf(F, "immediate value = %ld (0x%08lx)\n", v, v);
                                }
+#endif
                        }
 
+#if 0
                        if (is_arm_CmpBra(n) && get_arm_CondJmp_proj_num(n) >= 0) {
                                fprintf(F, "proj_num = (%d)\n", get_arm_CondJmp_proj_num(n));
                        }
+#endif
                        break;
        }
 
@@ -149,25 +128,15 @@ static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
 }
 
 
-
-/***************************************************************************************************
- *        _   _                   _       __        _                    _   _               _
- *       | | | |                 | |     / /       | |                  | | | |             | |
- *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
- *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
- * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
- *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
- *                                        __/ |
- *                                       |___/
- ***************************************************************************************************/
-
 /* Returns the attributes of a generic Arm node. */
-arm_attr_t *get_arm_attr(ir_node *node) {
+arm_attr_t *get_arm_attr(ir_node *node)
+{
        assert(is_arm_irn(node) && "need arm node to get attributes");
        return get_irn_generic_attr(node);
 }
 
-const arm_attr_t *get_arm_attr_const(const ir_node *node) {
+const arm_attr_t *get_arm_attr_const(const ir_node *node)
+{
        assert(is_arm_irn(node) && "need arm node to get attributes");
        return get_irn_generic_attr_const(node);
 }
@@ -175,13 +144,15 @@ const arm_attr_t *get_arm_attr_const(const ir_node *node) {
 /**
  * Returns the attributes of an ARM SymConst node.
  */
-arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node) {
-       assert(is_arm_SymConst(node));
+arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
+{
+       assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
        return get_irn_generic_attr(node);
 }
 
-const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node) {
-       assert(is_arm_SymConst(node));
+const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
+{
+       assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
        return get_irn_generic_attr_const(node);
 }
 
@@ -199,24 +170,16 @@ static arm_fpaConst_attr_t *get_arm_fpaConst_attr(ir_node *node) {
        return fpa_attr;
 }
 
-#ifndef NDEBUG
-static int is_arm_CondJmp(const ir_node *node) {
-       int code = get_arm_irn_opcode(node);
-
-       return (code == iro_arm_CmpBra || code == iro_arm_fpaCmfBra ||
-               code == iro_arm_fpaCnfBra || iro_arm_fpaCmfeBra ||
-               code == iro_arm_fpaCnfeBra);
-}
-#endif
-
 /* Returns the attributes of a CondJmp node. */
-arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node) {
-       assert(is_arm_CondJmp(node));
+arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
+{
+       assert(is_arm_B(node));
        return get_irn_generic_attr(node);
 }
 
-const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node) {
-       assert(is_arm_CondJmp(node));
+const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
+{
+       assert(is_arm_B(node));
        return get_irn_generic_attr_const(node);
 }
 
@@ -255,22 +218,6 @@ void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
        attr->in_req[pos] = req;
 }
 
-/**
- * Returns the immediate value
- */
-long get_arm_imm_value(const ir_node *node) {
-       const arm_attr_t *attr = get_arm_attr_const(node);
-       return attr->imm_value;
-}
-
-/**
- * Sets the tarval value
- */
-void set_arm_imm_value(ir_node *node, long imm_value) {
-       arm_attr_t *attr = get_arm_attr(node);
-       attr->imm_value = imm_value;
-}
-
 /**
  * Returns the fpaConst value
  */
@@ -303,22 +250,6 @@ void set_arm_CondJmp_proj_num(ir_node *node, int proj_num) {
        attr->proj_num   = proj_num;
 }
 
-/**
- * Returns the SymConst label
- */
-ident *get_arm_symconst_id(const ir_node *node) {
-       const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(node);
-       return attr->symconst_id;
-}
-
-/**
- * Sets the SymConst label
- */
-void set_arm_symconst_id(ir_node *node, ident *symconst_id) {
-       arm_SymConst_attr_t *attr = get_arm_SymConst_attr(node);
-       attr->symconst_id = symconst_id;
-}
-
 /**
  * Returns the number of projs of a SwitchJmp.
  */
@@ -351,14 +282,6 @@ void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num) {
        attr->default_proj_num = default_proj_num;
 }
 
-/**
- * Gets the shift modifier attribute.
- */
-arm_shift_modifier get_arm_shift_modifier(const ir_node *node) {
-       const arm_attr_t *attr = get_arm_attr_const(node);
-       return ARM_GET_SHF_MOD(attr);
-}
-
 /* Set the ARM machine node attributes to default values. */
 static void init_arm_attributes(ir_node *node, int flags,
                          const arch_register_req_t ** in_reqs,
@@ -373,78 +296,66 @@ static void init_arm_attributes(ir_node *node, int flags,
 
        arch_irn_set_flags(node, flags);
        attr->in_req           = in_reqs;
-       attr->instr_fl         = (ARM_COND_AL << 3) | ARM_SHF_NONE;
-       attr->imm_value        = 0;
+       attr->instr_fl         = 0;
 
        info            = be_get_info(node);
        info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
        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)
+static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
+                                           ir_entity *entity,
+                                           int entity_sign, long offset,
+                                           bool is_frame_entity)
 {
        arm_load_store_attr_t *attr = get_irn_generic_attr(res);
-       attr->entity      = entity;
-       attr->entity_sign = entity_sign;
-       attr->offset      = offset;
-}
-
-/************************************************
- *   ___        _   _           _               *
- *  / _ \ _ __ | |_(_)_ __ ___ (_)_______ _ __  *
- * | | | | '_ \| __| | '_ ` _ \| |_  / _ \ '__| *
- * | |_| | |_) | |_| | | | | | | |/ /  __/ |    *
- *  \___/| .__/ \__|_|_| |_| |_|_/___\___|_|    *
- *       |_|                                    *
- ************************************************/
-
-typedef struct _opt_tuple {
-       ir_op *op_imm_left;             /**< immediate is left */
-       ir_op *op_imm_right;    /**< immediate is right */
-       ir_op *op_shf_left;             /**< shift operand on left */
-       ir_op *op_shf_right;    /**< shift operand on right */
-} opt_tuple;
-
-//static const opt_tuple *opt_ops[iro_arm_last];
-
-void arm_set_optimizers(void) {
-       /*
-#define STD(op)                p_##op = { op_arm_##op##_i, op_arm_##op##_i, op_arm_##op, op_arm_##op }
-#define LEFT(op)       p_##op = { op_arm_##op##_i, NULL, op_arm_##op, NULL }
-#define SET(op)   opt_ops[iro_arm_##op] = &p_##op;
-
-       static const opt_tuple
-               STD(Add),
-               STD(And),
-               STD(Or),
-               STD(Eor),
-               LEFT(Bic),
-               LEFT(Shl),
-               LEFT(Shr),
-               LEFT(Shrs),
-               p_Sub = { op_arm_Sub_i, op_arm_Rsb_i, op_arm_Sub, op_arm_Rsb },
-
-       memset(opt_ops, 0, sizeof(opt_ops));
-       SET(Add);
-       SET(And);
-       SET(Or);
-       SET(Eor);
-       SET(Sub);
-       SET(Bic);
-       SET(Shl);
-       SET(Shr);
-       SET(Shrs);
-       */
-}
-
-static int cmp_attr_arm(ir_node *a, ir_node *b) {
+       attr->load_store_mode    = ls_mode;
+       attr->entity             = entity;
+       attr->entity_sign        = entity_sign;
+       attr->is_frame_entity    = is_frame_entity;
+       attr->offset             = offset;
+       attr->base.is_load_store = true;
+}
+
+static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
+                                     arm_shift_modifier shift_modifier,
+                                     unsigned shift_immediate)
+{
+       arm_shifter_operand_t *attr = get_irn_generic_attr(res);
+       attr->immediate_value = immediate_value;
+       attr->shift_modifier  = shift_modifier;
+       attr->shift_immediate = shift_immediate;
+}
+
+static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
+{
+       arm_cmp_attr_t *attr = get_irn_generic_attr(res);
+       attr->ins_permuted = ins_permuted;
+       attr->is_unsigned  = is_unsigned;
+}
+
+static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity)
+{
+       arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
+       attr->entity    = entity;
+       attr->fp_offset = 0;
+}
+
+static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
+{
+       arm_CopyB_attr_t *attr = get_irn_generic_attr(res);
+       attr->size = size;
+}
+
+static int cmp_attr_arm(ir_node *a, ir_node *b)
+{
        arm_attr_t *attr_a = get_irn_generic_attr(a);
        arm_attr_t *attr_b = get_irn_generic_attr(b);
-       return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);
+       return attr_a->instr_fl != attr_b->instr_fl;
 }
 
-static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b) {
+static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b)
+{
        const arm_SymConst_attr_t *attr_a;
        const arm_SymConst_attr_t *attr_b;
 
@@ -453,24 +364,41 @@ static int cmp_attr_arm_SymConst(ir_node *a, ir_node *b) {
 
        attr_a = get_irn_generic_attr_const(a);
        attr_b = get_irn_generic_attr_const(b);
-       return attr_a->symconst_id != attr_b->symconst_id;
+       return attr_a->entity != attr_b->entity
+               || attr_a->fp_offset != attr_b->fp_offset;
 }
 
-static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b) {
+static int cmp_attr_arm_CopyB(ir_node *a, ir_node *b)
+{
+       const arm_CopyB_attr_t *attr_a;
+       const arm_CopyB_attr_t *attr_b;
+
+       if (cmp_attr_arm(a, b))
+               return 1;
+
+       attr_a = get_irn_generic_attr_const(a);
+       attr_b = get_irn_generic_attr_const(b);
+       return attr_a->size != attr_b->size;
+}
+
+static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b)
+{
        (void) a;
        (void) b;
        /* never identical */
        return 1;
 }
 
-static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b) {
+static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b)
+{
        (void) a;
        (void) b;
        /* never identical */
        return 1;
 }
 
-static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b) {
+static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b)
+{
        const arm_fpaConst_attr_t *attr_a;
        const arm_fpaConst_attr_t *attr_b;
 
@@ -483,11 +411,22 @@ 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);
 }
 
+const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
+{
+       return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
+}
+
+arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
+{
+       return (arm_shifter_operand_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;
@@ -506,6 +445,40 @@ static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
        return 0;
 }
 
+static int cmp_attr_arm_shifter_operand(ir_node *a, ir_node *b)
+{
+       const arm_shifter_operand_t *attr_a;
+       const arm_shifter_operand_t *attr_b;
+
+       if (cmp_attr_arm(a, b))
+               return 1;
+
+       attr_a = get_arm_shifter_operand_attr(a);
+       attr_b = get_arm_shifter_operand_attr(b);
+       if (attr_a->shift_modifier != attr_b->shift_modifier
+                       || attr_a->immediate_value != attr_b->immediate_value
+                       || attr_a->shift_immediate != attr_b->shift_immediate)
+               return 1;
+
+       return 0;
+}
+
+static int cmp_attr_arm_cmp(ir_node *a, ir_node *b)
+{
+       const arm_cmp_attr_t *attr_a;
+       const arm_cmp_attr_t *attr_b;
+
+       if (cmp_attr_arm(a, b))
+               return 1;
+
+       attr_a = get_irn_generic_attr_const(a);
+       attr_b = get_irn_generic_attr_const(b);
+       if (attr_a->ins_permuted != attr_b->ins_permuted
+                       || attr_a->is_unsigned != attr_b->is_unsigned)
+               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 31cdbab..9c3bb23 100644 (file)
 #include "arm_nodes_attr.h"
 #include "bearch_arm_t.h"
 
-/***************************************************************************************************
- *        _   _                   _       __        _                    _   _               _
- *       | | | |                 | |     / /       | |                  | | | |             | |
- *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
- *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
- * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
- *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
- *                                        __/ |
- *                                       |___/
- ***************************************************************************************************/
-
 /**
  * Returns the attributes of a generic Arm node.
  */
@@ -64,6 +53,9 @@ const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node);
 arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node);
 const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node);
 
+arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node);
+const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node);
+
 /**
  * Returns the argument register requirements of an arm node.
  */
@@ -79,16 +71,6 @@ const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos);
  */
 void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos);
 
-/**
- * Returns the immediate value
- */
-long get_arm_imm_value(const ir_node *node);
-
-/**
- * Sets the immediate value
- */
-void set_arm_imm_value(ir_node *node, long imm_value);
-
 /**
 * Return the tarval of a fpaConst
 */
@@ -109,9 +91,6 @@ int get_arm_CondJmp_proj_num(const ir_node *node);
  */
 void set_arm_CondJmp_proj_num(ir_node *node, int proj_num);
 
-ident *get_arm_symconst_id(const ir_node *node);
-void set_arm_symconst_id(ir_node *node, ident *symconst_id);
-
 ir_node *new_r_arm_StoreStackMInc(ir_graph *irg, ir_node *block, ir_node *mem, ir_node *sp,
                                                              int n_regs, ir_node **regs, ir_mode *mode);
 
@@ -140,9 +119,6 @@ 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 4b546ee..df4d421 100644 (file)
 #include "../bearch.h"
 
 /**
- * Possible ARM register shift types.
+ * Possible ARM "shifter operand" addressing mode types.
  */
 typedef enum _arm_shift_modifier {
-       ARM_SHF_NONE = 0,   /**< no shift */
-       ARM_SHF_IMM  = 1,   /**< immediate operand with implicit ROR */
-       ARM_SHF_ASR  = 2,   /**< arithmetic shift right */
-       ARM_SHF_LSL  = 3,   /**< logical shift left */
-       ARM_SHF_LSR  = 4,   /**< logical shift right */
-       ARM_SHF_ROR  = 5,   /**< rotate right */
-       ARM_SHF_RRX  = 6,   /**< rotate right through carry bits */
+       ARM_SHF_INVALID,   /**< invalid shift */
+       ARM_SHF_REG,       /**< simple register operand */
+       ARM_SHF_IMM,       /**< immediate operand with implicit ROR */
+       ARM_SHF_ASR_IMM,   /**< arithmetic shift right */
+       ARM_SHF_ASR_REG,   /**< arithmetic shift right */
+       ARM_SHF_LSL_IMM,   /**< logical shift left */
+       ARM_SHF_LSL_REG,   /**< logical shift left */
+       ARM_SHF_LSR_IMM,   /**< logical shift right */
+       ARM_SHF_LSR_REG,   /**< logical shift right */
+       ARM_SHF_ROR_IMM,   /**< rotate right */
+       ARM_SHF_ROR_REG,   /**< rotate right */
+       ARM_SHF_RRX,       /**< rotate right through carry bits */
 } arm_shift_modifier;
 
-/** True, if the modifier implies a shift argument */
-#define ARM_HAS_SHIFT(mod)          ((mod) > ARM_SHF_IMM)
-
-/** get the shift modifier from flags */
-#define ARM_GET_SHF_MOD(attr)       ((attr)->instr_fl & 7)
-
-/** set the shift modifier to flags */
-#define ARM_SET_SHF_MOD(attr, mod)  ((attr)->instr_fl = (((attr)->instr_fl & ~7) | (mod)))
-
 /** fpa immediate bit */
 #define ARM_FPA_IMM  (1 << 3)   /**< fpa floating point immediate */
 
@@ -59,34 +55,6 @@ typedef enum _arm_shift_modifier {
 #define ARM_SET_FPA_IMM(attr)        ((attr)->instr_fl |= ARM_FPA_IMM)
 #define ARM_CLR_FPA_IMM(attr)        ((attr)->instr_fl &= ~ARM_FPA_IMM)
 
-/**
- * Possible ARM condition codes.
- */
-typedef enum _arm_condition {
-       ARM_COND_EQ = 0,   /**< Equal, Z set. */
-       ARM_COND_NE = 1,   /**< Not Equal, Z clear */
-       ARM_COND_CS = 2,   /**< Carry set, unsigned >=, C set */
-       ARM_COND_CC = 3,   /**< Carry clear, unsigned <, C clear */
-       ARM_COND_MI = 4,   /**< Minus/Negative, N set */
-       ARM_COND_PL = 5,   /**< Plus/Positive or Zero, N clear */
-       ARM_COND_VS = 6,   /**< Overflow, V set */
-       ARM_COND_VC = 7,   /**< No overflow, V clear */
-       ARM_COND_HI = 8,   /**< unsigned >, C set and Z clear */
-       ARM_COND_LS = 9,   /**< unsigned <=, C clear or Z set */
-       ARM_COND_GE = 10,  /**< signed >=, N == V */
-       ARM_COND_LT = 11,  /**< signed <, N != V */
-       ARM_COND_GT = 12,  /**< signed >, Z clear and N == V */
-       ARM_COND_LE = 13,  /**< signed <=, Z set or N != V */
-       ARM_COND_AL = 14,  /**< Always (unconditional) */
-       ARM_COND_NV = 15   /**< forbidden */
-} arm_condition;
-
-/** Get the condition code from flags */
-#define ARM_GET_COND(attr)        (((attr)->instr_fl >> 4) & 15)
-
-/** Set the condition code to flags */
-#define ARM_SET_COND(attr, code)  ((attr)->instr_fl = (((attr)->instr_fl & ~(15 << 4)) | ((code) << 4)))
-
 /** Encoding for fpa immediates */
 enum fpa_immediates {
        fpa_null = 0,
@@ -106,48 +74,73 @@ typedef struct _arm_attr_t {
 
        const arch_register_req_t **in_req;  /**< register requirements for arguments */
 
-       ir_mode  *op_mode;                   /**< operation mode if different from node's mode */
-       unsigned instr_fl;                   /**< condition code, shift modifier */
-       long     imm_value;                  /**< immediate */
+       ir_mode  *op_mode;                   /**< operation mode if different from node's mode (used for fpa nodes) */
+       unsigned  instr_fl;                  /**< deprecated (was sometimes used for shift modifiers) */
+       bool      is_load_store : 1;
 } arm_attr_t;
 
+/**
+ * This struct holds information needed to produce the arm
+ * "data processing operands" also called "shifter operand" addressing modes
+ */
+typedef struct arm_shifter_operand_t {
+       arm_attr_t          base;
+       arm_shift_modifier  shift_modifier;
+       unsigned char       immediate_value;
+       unsigned char       shift_immediate;
+} arm_shifter_operand_t;
+
+typedef struct arm_cmp_attr_t {
+       arm_shifter_operand_t  base;
+       bool                   ins_permuted : 1;
+       bool                   is_unsigned  : 1;
+} arm_cmp_attr_t;
+
+/**
+ * this struct holds information needed to produce the arm addressing modes
+ * for "Load and Store Word or Unsigned Byte", "Miscellaneous Loads and Stores"
+ * and "Load and Store Multiple" */
 typedef struct arm_load_store_attr_t {
-       arm_attr_t  attr;
+       arm_attr_t  base;
+       ir_mode    *load_store_mode;
        ir_entity  *entity;
        long        offset;
-       bool        entity_sign : 1;
+       bool        is_frame_entity : 1;
+       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 */
-       ident       *symconst_id;           /**< for SymConsts: its ident */
+       arm_attr_t  base;
+       ir_entity  *entity;
+       int         fp_offset;
 } arm_SymConst_attr_t;
 
 /** Attributes for a CondJmp */
 typedef struct _arm_CondJmp_attr_t {
-       arm_attr_t  attr;                   /**< base attributes */
+       arm_attr_t  base;
        int         proj_num;
 } arm_CondJmp_attr_t;
 
 /** Attributes for a SwitchJmp */
 typedef struct _arm_SwitchJmp_attr_t {
-       arm_attr_t  attr;                   /**< base attributes */
+       arm_attr_t  base;
        int         n_projs;
        long        default_proj_num;
 } arm_SwitchJmp_attr_t;
 
+/** CopyB attributes */
+typedef struct {
+       arm_attr_t  base;
+       unsigned    size;
+} arm_CopyB_attr_t;
+
 /** Attributes for a fpaConst */
 typedef struct _arm_fpaConst_attr_t {
-       arm_attr_t  attr;                   /**< base attributes */
-       tarval      *tv;                    /**< the tarval representing the FP const */
+       arm_attr_t  base;
+       tarval     *tv;              /**< the tarval representing the FP const */
 } arm_fpaConst_attr_t;
 
-/**
- * Returns the shift modifier string.
- */
-const char *arm_shf_mod_name(arm_shift_modifier mod);
-
 /**
  * Return the fpa immediate from the encoding.
  */
index 64e49a6..fd4e0eb 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "irgmod.h"
 #include "ircons.h"
+#include "iredges.h"
 #include "error.h"
 
 #include "benode.h"
 #include "arm_optimize.h"
 #include "gen_arm_regalloc_if.h"
 #include "gen_arm_new_nodes.h"
+#include "arm_nodes_attr.h"
+#include "arm_new_nodes.h"
 
 static arm_code_gen_t  *cg;
 
-/** Execute ARM ROL. */
-static unsigned arm_rol(unsigned v, unsigned rol) {
-       return (v << rol) | (v >> (32 - rol));
+static unsigned arm_ror(unsigned v, unsigned ror)
+{
+       return (v << (32 - ror)) | (v >> ror);
 }
 
 /*
@@ -51,61 +54,38 @@ void arm_gen_vals_from_word(unsigned int value, arm_vals *result)
 {
        int initial = 0;
 
-       memset(result, 0, sizeof(*result));
+       /* TODO: not optimal yet, as we only "shift" the value and don't take advantage of rotations */
 
        /* special case: we prefer shift amount 0 */
-       if (value < 0x100) {
+       if (value <= 0xFF) {
                result->values[0] = value;
+               result->rors[0]   = 0;
                result->ops       = 1;
                return;
        }
 
-       while (value != 0) {
-               if (value & 0xFF) {
-                       unsigned v = arm_rol(value, 8) & 0xFFFFFF;
-                       int shf = 0;
-                       for (;;) {
-                               if ((v & 3) != 0)
-                                       break;
-                               shf += 2;
-                               v >>= 2;
-                       }
-                       v  &= 0xFF;
-                       shf = (initial + shf - 8) & 0x1F;
-                       result->values[result->ops] = v;
-                       result->shifts[result->ops] = shf;
-                       ++result->ops;
-
-                       value ^= arm_rol(v, shf) >> initial;
-               }
-               else {
-                       value >>= 8;
-                       initial += 8;
+       result->ops = 0;
+       do {
+               while ( (value & 0x3) == 0) {
+                       value  >>= 2;
+                       initial += 2;
                }
-       }
-}
 
-/**
- * Encodes an immediate with shifter operand
- */
-unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
-       return immediate | ((shift>>1)<<8);
-}
+               result->values[result->ops] = value & 0xFF;
+               result->rors[result->ops]   = (32-initial) % 32;
+               ++result->ops;
 
-/**
- * Decode an immediate with shifter operand
- */
-unsigned int arm_decode_imm_w_shift(long imm_value) {
-       unsigned l = (unsigned)imm_value;
-       unsigned rol = (l & ~0xFF) >> 7;
-
-       return arm_rol(l & 0xFF, rol);
+               value  >>= 8;
+               initial += 8;
+       } while(value != 0);
 }
 
 /**
- * Returns non.zero if the given offset can be directly encoded into an ARM instruction.
+ * Returns non.zero if the given offset can be directly encoded into an ARM
+ * instruction.
  */
-static int allowed_arm_immediate(int offset, arm_vals *result) {
+static int allowed_arm_immediate(int offset, arm_vals *result)
+{
        arm_gen_vals_from_word(offset, result);
        return result->ops <= 1;
 }
@@ -113,10 +93,17 @@ static int allowed_arm_immediate(int offset, arm_vals *result) {
 /**
  * Fix an IncSP node if the offset gets too big
  */
-static void peephole_be_IncSP(ir_node *node) {
+static void peephole_be_IncSP(ir_node *node)
+{
+       ir_node  *first;
+       ir_node  *last;
        ir_node  *block;
-       int      offset, cnt, align, sign = 1;
-       arm_vals v;
+       int       offset;
+       int       cnt;
+       int       sign = 1;
+       arm_vals  v;
+       const ir_edge_t *edge;
+       const ir_edge_t *next;
 
        /* first optimize incsp->incsp combinations */
        node = be_peephole_IncSP_IncSP(node);
@@ -130,16 +117,28 @@ static void peephole_be_IncSP(ir_node *node) {
        if (allowed_arm_immediate(offset, &v))
                return;
 
-       be_set_IncSP_offset(node, (int)arm_rol(v.values[0], v.shifts[0]) * sign);
+       be_set_IncSP_offset(node, sign * arm_ror(v.values[0], v.rors[0]));
 
+       first = node;
        block = get_nodes_block(node);
-       align = be_get_IncSP_align(node);
        for (cnt = 1; cnt < v.ops; ++cnt) {
-               int value = (int)arm_rol(v.values[cnt], v.shifts[cnt]);
-               ir_node *next = be_new_IncSP(&arm_gp_regs[REG_SP], block, node, value * sign, align);
+               int value = sign * arm_ror(v.values[cnt], v.rors[cnt]);
+               ir_node *next = be_new_IncSP(&arm_gp_regs[REG_SP], block, node,
+                                            value, 1);
                sched_add_after(node, next);
                node = next;
        }
+
+       /* reattach IncSP users */
+       last = node;
+       node = sched_next(first);
+       foreach_out_edge_safe(first, edge, next) {
+               ir_node *user = get_edge_src_irn(edge);
+               int      pos  = get_edge_src_pos(edge);
+               if (user == node)
+                       continue;
+               set_irn_n(user, pos, last);
+       }
 }
 
 /**
@@ -147,18 +146,18 @@ static void peephole_be_IncSP(ir_node *node) {
  */
 static ir_node *gen_ptr_add(ir_node *node, ir_node *frame, arm_vals *v)
 {
-       dbg_info *dbg   = get_irn_dbg_info(node);
+       dbg_info *dbgi  = get_irn_dbg_info(node);
        ir_node  *block = get_nodes_block(node);
        int     cnt;
        ir_node *ptr;
 
-       ptr = new_bd_arm_Add_i(dbg, block, frame, mode_Iu, arm_encode_imm_w_shift(v->shifts[0], v->values[0]));
+       ptr = new_bd_arm_Add_imm(dbgi, block, frame, v->values[0], v->rors[0]);
        arch_set_irn_register(ptr, &arm_gp_regs[REG_R12]);
        sched_add_before(node, ptr);
 
        for (cnt = 1; cnt < v->ops; ++cnt) {
-               long value = arm_encode_imm_w_shift(v->shifts[cnt], v->values[cnt]);
-               ir_node *next = new_bd_arm_Add_i(dbg, block, ptr, mode_Iu, value);
+               ir_node *next = new_bd_arm_Add_imm(dbgi, block, ptr, v->values[cnt],
+                                                  v->rors[cnt]);
                arch_set_irn_register(next, &arm_gp_regs[REG_R12]);
                sched_add_before(node, next);
                ptr = next;
@@ -171,18 +170,18 @@ static ir_node *gen_ptr_add(ir_node *node, ir_node *frame, arm_vals *v)
 */
 static ir_node *gen_ptr_sub(ir_node *node, ir_node *frame, arm_vals *v)
 {
-       dbg_info *dbg   = get_irn_dbg_info(node);
+       dbg_info *dbgi  = get_irn_dbg_info(node);
        ir_node  *block = get_nodes_block(node);
        int     cnt;
        ir_node *ptr;
 
-       ptr = new_bd_arm_Sub_i(dbg, block, frame, mode_Iu, arm_encode_imm_w_shift(v->shifts[0], v->values[0]));
+       ptr = new_bd_arm_Sub_imm(dbgi, block, frame, v->values[0], v->rors[0]);
        arch_set_irn_register(ptr, &arm_gp_regs[REG_R12]);
        sched_add_before(node, ptr);
 
        for (cnt = 1; cnt < v->ops; ++cnt) {
-               long value = arm_encode_imm_w_shift(v->shifts[cnt], v->values[cnt]);
-               ir_node *next = new_bd_arm_Sub_i(dbg, block, ptr, mode_Iu, value);
+               ir_node *next = new_bd_arm_Sub_imm(dbgi, block, ptr, v->values[cnt],
+                                                  v->rors[cnt]);
                arch_set_irn_register(next, &arm_gp_regs[REG_R12]);
                sched_add_before(node, next);
                ptr = next;
@@ -190,117 +189,79 @@ static ir_node *gen_ptr_sub(ir_node *node, ir_node *frame, arm_vals *v)
        return ptr;
 }
 
-/**
- * Fix an be_Spill node if the offset gets too big
- */
-static void peephole_be_Spill(ir_node *node) {
-       ir_entity *ent   = be_get_frame_entity(node);
-       int       use_add = 1, offset = get_entity_offset(ent);
-       ir_node   *block, *ptr, *frame, *value, *store;
-       ir_mode   *mode;
-       dbg_info  *dbg;
-       ir_graph  *irg;
-       arm_vals  v;
+/** fix frame addresses which are too big */
+static void peephole_arm_FrameAddr(ir_node *node)
+{
+       arm_SymConst_attr_t *attr   = get_arm_SymConst_attr(node);
+       int                  offset = attr->fp_offset;
+       arm_vals             v;
+       ir_node             *base;
+       ir_node             *ptr;
 
        if (allowed_arm_immediate(offset, &v))
                return;
-       if (offset < 0) {
-               use_add = 0;
-               offset = -offset;
-       }
-
-       frame = be_get_Spill_frame(node);
-       if (use_add) {
-               ptr = gen_ptr_add(node, frame, &v);
-       } else {
-               ptr = gen_ptr_sub(node, frame, &v);
-       }
 
-       value = be_get_Spill_val(node);
-       mode  = get_irn_mode(value);
-       irg   = current_ir_graph;
-       dbg   = get_irn_dbg_info(node);
-       block = get_nodes_block(node);
+       base = get_irn_n(node, n_arm_FrameAddr_base);
+       /* TODO: suboptimal */
+       ptr = gen_ptr_add(node, base, &v);
 
-       if (mode_is_float(mode)) {
-               if (USE_FPA(cg->isa)) {
-                       /* transform into fpaStf */
-                       store = new_bd_arm_fpaStf(dbg, block, ptr, value, get_irg_no_mem(irg), mode);
-                       sched_add_before(node, store);
-               } else {
-                       panic("peephole_be_Spill: spill not supported for this mode");
-               }
-       } else if (mode_is_dataM(mode)) {
-               /* 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");
-       }
-
-       be_peephole_exchange(node, store);
+       attr->fp_offset = 0;
+       set_irn_n(node, n_arm_FrameAddr_base, ptr);
 }
 
 /**
- * Fix an be_Reload node if the offset gets too big
+ * Fix stackpointer relative stores if the offset gets too big
  */
-static void peephole_be_Reload(ir_node *node) {
-       ir_entity *ent   = be_get_frame_entity(node);
-       int       use_add = 1, offset = get_entity_offset(ent);
-       ir_node   *block, *ptr, *frame, *load, *mem, *proj;
-       ir_mode   *mode;
-       dbg_info  *dbg;
-       arm_vals  v;
-       const arch_register_t *reg;
+static void peephole_arm_Str_Ldr(ir_node *node)
+{
+       arm_load_store_attr_t *attr    = get_arm_load_store_attr(node);
+       int                    offset  = attr->offset;
+       int                    use_add = 1;
+       ir_node               *ptr;
+       arm_vals              v;
 
        if (allowed_arm_immediate(offset, &v))
                return;
+
+       /* we should only have too big offsets for frame entities */
+       if (!attr->is_frame_entity) {
+               fprintf(stderr,
+                       "POSSIBLE ARM BACKEND PROBLEM: offset in Store too big\n");
+       }
        if (offset < 0) {
                use_add = 0;
                offset = -offset;
        }
 
-       frame = be_get_Reload_frame(node);
-       if (use_add) {
-               ptr = gen_ptr_add(node, frame, &v);
+       if (is_arm_Str(node)) {
+               ptr = get_irn_n(node, n_arm_Str_ptr);
        } else {
-               ptr = gen_ptr_sub(node, frame, &v);
+               assert(is_arm_Ldr(node));
+               ptr = get_irn_n(node, n_arm_Ldr_ptr);
        }
 
-       reg   = arch_get_irn_register(node);
-       mem   = be_get_Reload_mem(node);
-       mode  = get_irn_mode(node);
-       dbg   = get_irn_dbg_info(node);
-       block = get_nodes_block(node);
-
-       if (mode_is_float(mode)) {
-               if (USE_FPA(cg->isa)) {
-                       /* transform into fpaLdf */
-                       load = new_bd_arm_fpaLdf(dbg, block, ptr, mem, mode);
-                       sched_add_before(node, load);
-                       proj = new_rd_Proj(dbg, block, load, mode, pn_arm_fpaLdf_res);
-                       arch_set_irn_register(proj, reg);
-               } else {
-                       panic("peephole_be_Spill: spill not supported for this mode");
-               }
-       } else if (mode_is_dataM(mode)) {
-               /* transform into Store */;
-               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_Ldr_res);
-               arch_set_irn_register(proj, reg);
+       if (use_add) {
+               ptr = gen_ptr_add(node, ptr, &v);
        } else {
-               panic("peephole_be_Spill: spill not supported for this mode");
+               ptr = gen_ptr_sub(node, ptr, &v);
        }
 
-       be_peephole_exchange(node, proj);
+       /* TODO: sub-optimal, the last offset could probably be left inside the
+          store */
+       if (is_arm_Str(node)) {
+               set_irn_n(node, n_arm_Str_ptr, ptr);
+       } else {
+               assert(is_arm_Ldr(node));
+               set_irn_n(node, n_arm_Ldr_ptr, ptr);
+       }
+       attr->offset = 0;
 }
 
 /**
  * Register a peephole optimization function.
  */
-static void register_peephole_optimisation(ir_op *op, peephole_opt_func func) {
+static void register_peephole_optimisation(ir_op *op, peephole_opt_func func)
+{
        assert(op->ops.generic == NULL);
        op->ops.generic = (op_func)func;
 }
@@ -312,9 +273,10 @@ void arm_peephole_optimization(arm_code_gen_t *new_cg)
 
        /* register peephole optimizations */
        clear_irp_opcodes_generic_func();
-       register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP);
-       register_peephole_optimisation(op_be_Spill, peephole_be_Spill);
-       register_peephole_optimisation(op_be_Reload, peephole_be_Reload);
+       register_peephole_optimisation(op_be_IncSP,      peephole_be_IncSP);
+       register_peephole_optimisation(op_arm_Str,       peephole_arm_Str_Ldr);
+       register_peephole_optimisation(op_arm_Ldr,       peephole_arm_Str_Ldr);
+       register_peephole_optimisation(op_arm_FrameAddr, peephole_arm_FrameAddr);
 
        be_peephole_opt(cg->birg);
 }
index 92f7243..9f487f5 100644 (file)
@@ -32,7 +32,7 @@
 typedef struct arm_vals {
        int ops;
        unsigned char values[4];
-       unsigned char shifts[4];
+       unsigned char rors[4];
 } arm_vals;
 
 /**
index a3c6033..968b364 100644 (file)
@@ -1,18 +1,15 @@
 # Creation: 2006/02/13
 # $Id$
-# This is a template specification for the Firm-Backend
 
 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
 
 $arch = "arm";
 
-# the number of additional opcodes you want to register
-#$additional_opcodes = 0;
-
 #
 # Modes
 #
 $mode_gp      = "mode_Iu";
+$mode_flags   = "mode_Bu";
 $mode_fpa     = "mode_E";
 
 # register types:
@@ -38,11 +35,10 @@ $state       = 32; # register represents a state
                { 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 => "r12", type => $ignore }, # reserved for linker/immediate fixups
+               { name => "sp",  type => $ignore }, # 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
+               { name => "pc",  type => $ignore }, # this is our program counter
                { mode => $mode_gp }
        ],
        fpa  => [
@@ -54,49 +50,51 @@ $state       = 32; # register represents a state
                { 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 }
-       ]
+       ],
+       flags => [
+               { name => "fl", type => 0 },
+               { mode => $mode_flags, flags => "manual_ra" }
+       ],
 );
 
 %emit_templates = (
-       M  => "${arch}_emit_mode(node);",
-       X  => "${arch}_emit_shift(node);",
-       S0 => "${arch}_emit_source_register(node, 0);",
-       S1 => "${arch}_emit_source_register(node, 1);",
-       S2 => "${arch}_emit_source_register(node, 2);",
-       S3 => "${arch}_emit_source_register(node, 3);",
-       S4 => "${arch}_emit_source_register(node, 4);",
-       D0 => "${arch}_emit_dest_register(node, 0);",
-       D1 => "${arch}_emit_dest_register(node, 1);",
-       D2 => "${arch}_emit_dest_register(node, 2);",
-       C  => "${arch}_emit_immediate(node);",
-       O  => "${arch}_emit_offset(mode);",
+       M   => "${arch}_emit_mode(node);",
+       LM  => "${arch}_emit_load_mode(node);",
+       SM  => "${arch}_emit_store_mode(node);",
+       SO  => "${arch}_emit_shifter_operand(node);",
+       S0  => "${arch}_emit_source_register(node, 0);",
+       S1  => "${arch}_emit_source_register(node, 1);",
+       S2  => "${arch}_emit_source_register(node, 2);",
+       S3  => "${arch}_emit_source_register(node, 3);",
+       S4  => "${arch}_emit_source_register(node, 4);",
+       D0  => "${arch}_emit_dest_register(node, 0);",
+       D1  => "${arch}_emit_dest_register(node, 1);",
+       D2  => "${arch}_emit_dest_register(node, 2);",
+       O   => "${arch}_emit_offset(node);",
 );
 
-#--------------------------------------------------#
-#                        _                         #
-#                       (_)                        #
-#  _ __   _____      __  _ _ __    ___  _ __  ___  #
-# | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
-# | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
-# |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
-#                                      | |         #
-#                                      |_|         #
-#--------------------------------------------------#
-
 $default_attr_type = "arm_attr_t";
 $default_copy_attr = "arm_copy_attr";
 
 %init_attr = (
        arm_attr_t           => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
-       arm_SymConst_attr_t  => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
+       arm_SymConst_attr_t  =>
+               "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
+               "\tinit_arm_SymConst_attributes(res, entity);",
        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);",
+               "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
+       arm_shifter_operand_t =>
+               "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
+       arm_cmp_attr_t =>
+               "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
+       arm_CopyB_attr_t =>
+               "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
+               "\tinit_arm_CopyB_attributes(res, size);",
 );
 
 %compare_attr = (
@@ -106,380 +104,272 @@ $default_copy_attr = "arm_copy_attr";
        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",
+       arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
+       arm_CopyB_attr_t      => "cmp_attr_arm_CopyB",
+       arm_cmp_attr_t        => "cmp_attr_arm_cmp",
 );
 
-#%operands = (
-#
-#Immediate => {
-#      comment   => "blup di dup",
-#      irn_flags => "R",
-#      emit      => ". [%S0]-10",
-#      reg_req   => { },
-#      attr      => "tarval *tv",
-#      init_attr => "(void) attri;",
-#      # op_flags => O
-#      # cmp => "return 1;"
-#},
-#
-#ShfOp_I => {
-#      irn_flags => "R",
-#      emit      => ". ...",
-#      reg_req   => { in => [ "gp" ] },
-#      attr      => "tarval *tv",
-#      init_attr => "(void) tv;",
-#},
-#
-#ShfOp => {
-#      irn_flags => "R",
-#      emit      => ". ...",
-#      reg_req   => { in => [ "gp", "gp" ] },
-#},
-#
-#);
-
-%nodes = (
+my %unop_shifter_operand_constructors = (
+       imm => {
+               attr       => "unsigned char immediate_value, unsigned char immediate_rot",
+               custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
+               reg_req    => { in => [], out => [ "gp" ] },
+       },
+       reg => {
+               custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
+               reg_req    => { in => [ "gp" ], out => [ "gp" ] },
+       },
+       reg_shift_reg => {
+               attr       => "arm_shift_modifier shift_modifier",
+               custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
+               reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
+       },
+       reg_shift_imm => {
+               attr       => "arm_shift_modifier shift_modifier, unsigned shift_immediate",
+               custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
+               reg_req    => { in => [ "gp" ], out => [ "gp" ] },
+       },
+);
 
-Unknown_GP => {
-       state     => "pinned",
-       op_flags  => "c",
-       reg_req   => { out => [ "gp_UKNWN:I" ] },
-       emit      => "",
-       mode      => $mode_gp,
-},
+my %binop_shifter_operand_constructors = (
+       imm => {
+               attr       => "unsigned char immediate_value, unsigned char immediate_rot",
+               custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
+               reg_req    => { in => [ "gp" ], out => [ "gp" ] },
+               ins        => [ "left" ],
+       },
+       reg => {
+               custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
+               reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
+               ins        => [ "left", "right" ],
+       },
+       reg_shift_reg => {
+               attr       => "arm_shift_modifier shift_modifier",
+               custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
+               reg_req    => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
+               ins        => [ "left", "right", "shift" ],
+       },
+       reg_shift_imm => {
+               attr       => "arm_shift_modifier shift_modifier, unsigned shift_immediate",
+               custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
+               reg_req    => { in => [ "gp", "gp" ], out => [ "gp" ] },
+               ins        => [ "left", "right" ],
+       },
+);
 
-Unknown_FPA => {
-       state     => "pinned",
-       op_flags  => "c",
-       reg_req   => { out => [ "fpa_UKNWN:I" ] },
-       emit      => "",
-       mode      => $mode_fpa,
-},
+my %cmp_shifter_operand_constructors = (
+       imm => {
+               attr       => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
+               custominit =>
+                       "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
+                       "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
+               reg_req    => { in => [ "gp" ], out => [ "flags" ] },
+               ins        => [ "left" ],
+       },
+       reg => {
+               attr       => "bool ins_permuted, bool is_unsigned",
+               custominit =>
+                       "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
+                       "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
+               reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
+               ins        => [ "left", "right" ],
+       },
+       reg_shift_reg => {
+               attr       => "arm_shift_modifier shift_modifier, bool ins_permuted, bool is_unsigned",
+               custominit =>
+                       "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
+                       "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
+               reg_req    => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
+               ins        => [ "left", "right", "shift" ],
+       },
+       reg_shift_imm => {
+               attr       => "arm_shift_modifier shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
+               custominit =>
+                       "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
+                       "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
+               reg_req    => { in => [ "gp", "gp" ], out => [ "flags" ] },
+               ins        => [ "left", "right" ],
+       },
+);
 
-#-----------------------------------------------------------------#
-#  _       _                                         _            #
-# (_)     | |                                       | |           #
-#  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
-# | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
-# | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
-# |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
-#                   __/ |                                         #
-#                  |___/                                          #
-#-----------------------------------------------------------------#
 
-# commutative operations
+%nodes = (
 
 Add => {
-       op_flags  => "C",
        irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. add %D0, %S0, %S1%X'
-},
-
-Add_i => {
-       irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-       emit      => '. add %D0, %S0, %C'
+       emit      => '. add %D0, %S0, %SO',
+       mode      => $mode_gp,
+       attr_type => "arm_shifter_operand_t",
+       constructors => \%binop_shifter_operand_constructors,
 },
 
 Mul => {
-       #op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] },
-       emit      =>'. mul %D0, %S0, %S1'
+       reg_req   => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
+       emit      =>'. mul %D0, %S0, %S1',
+       mode      => $mode_gp,
 },
 
 Smull => {
-       #op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct signed 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
+       reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
        emit      =>'. smull %D0, %D1, %S0, %S1',
        outs      => [ "low", "high" ],
 },
 
 Umull => {
-       #op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct unsigned 64bit Mul: Mul(a, b) = Mul(b, a) = a * b",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] },
+       reg_req   => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
        emit      =>'. umull %D0, %D1, %S0, %S1',
        outs      => [ "low", "high" ],
+       mode      => $mode_gp,
 },
 
 Mla => {
-       #op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct Mla: Mla(a, b, c) = a * b + c",
-       reg_req   => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] },
-       emit      =>'. mla %D0, %S0, %S1, %S2'
+       reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
+       emit      =>'. mla %D0, %S0, %S1, %S2',
+       mode      => $mode_gp,
 },
 
 And => {
-       op_flags  => "C",
-       irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. and %D0, %S0, %S1%X'
-},
-
-And_i => {
        irn_flags => "R",
-       comment   => "construct And: And(a, const) = And(const, a) = a AND const",
-       attr      => "long imm",
-       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',
+       emit      => '. and %D0, %S0, %SO',
+       mode      => $mode_gp,
+       attr_type => "arm_shifter_operand_t",
+       constructors => \%binop_shifter_operand_constructors,
 },
 
 Or => {
-       op_flags  => "C",
        irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. orr %D0, %S0, %S1%X'
-},
-
-Or_i => {
-       irn_flags => "R",
-       comment   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
-       attr      => "long imm",
-       init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
-       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-       emit      => '. orr %D0, %S0, %C'
+       emit      => '. orr %D0, %S0, %SO',
+       mode      => $mode_gp,
+       attr_type => "arm_shifter_operand_t",
+       constructors => \%binop_shifter_operand_constructors,
 },
 
 Eor => {
-       op_flags  => "C",
-       irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. eor %D0, %S0, %S1%X'
-},
-
-Eor_i => {
        irn_flags => "R",
-       comment   => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
-       attr      => "long imm",
-       init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
-       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-       emit      => '. eor %D0, %S0, %C'
+       emit      => '. eor %D0, %S0, %SO',
+       mode      => $mode_gp,
+       attr_type => "arm_shifter_operand_t",
+       constructors => \%binop_shifter_operand_constructors,
 },
 
-# not commutative operations
-
 Bic => {
        irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. bic %D0, %S0, %S1%X'
-},
-
-Bic_i => {
-       irn_flags => "R",
-       comment   => "construct Bic: Bic(a, const) = a AND ~const",
-       attr      => "long imm",
-       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',
+       emit      => '. bic %D0, %S0, %SO',
+       mode      => $mode_gp,
+       attr_type => "arm_shifter_operand_t",
+       constructors => \%binop_shifter_operand_constructors,
 },
 
 Sub => {
        irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. sub %D0, %S0, %S1%X'
-},
-
-Sub_i => {
-       irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-       emit      => '. sub %D0, %S0, %C',
+       emit      => '. sub %D0, %S0, %SO',
+       mode      => $mode_gp,
+       attr_type => "arm_shifter_operand_t",
+       constructors => \%binop_shifter_operand_constructors,
 },
 
 Rsb => {
        irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. rsb %D0, %S0, %S1%X'
-},
-
-Rsb_i => {
-       irn_flags => "R",
-       comment   => "construct Rsb: Rsb(a, const) = const - a",
-       attr      => "long imm",
-       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',
-},
-
-Shl => {
-       irn_flags => "R",
-       comment   => "construct Shl: Shl(a, b) = a << b",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. mov %D0, %S0, lsl %S1'
-},
-
-Shr => {
-       irn_flags => "R",
-       comment   => "construct Shr: Shr(a, b) = a >>u b",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. mov %D0, %S0, lsr %S1'
-},
-
-Shrs => {
-       irn_flags => "R",
-       comment   => "construct Shrs: Shrs(a, b) = a >>s b",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. mov %D0, %S0, asr %S1'
-},
-
-Ror => {
-       irn_flags => "R",
-       comment   => "construct Ror: Ror(a, b) = a <<r>> b",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-       emit      => '. mov %D0, %S0, ror %S1'
+       emit      => '. rsb %D0, %S0, %SO',
+       mode      => $mode_gp,
+       attr_type => "arm_shifter_operand_t",
+       constructors => \%binop_shifter_operand_constructors,
 },
 
-#RotL => {
-#  irn_flags => "R",
-#  comment   => "construct RotL: RotL(a, b) = a ROTL b",
-#  reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
-#  emit      => '. rol %S0, %S1, %D0'
-#},
-
-#RotL_i => {
-#      irn_flags => "R",
-#      comment   => "construct RotL: RotL(a, const) = a ROTL const",
-#      reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-#      emit      => '. rol %S0, %C, %D0'
-#},
-
 Mov => {
        irn_flags => "R",
-       comment   => "construct Mov: a = b",
-       attr      => "arm_shift_modifier mod, long shf",
-       init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
-       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-       emit      => '. mov %D0, %S0%X'
-},
-
-Mov_i => {
-       irn_flags => "R",
-       comment   => "represents an integer constant",
-       attr      => "long imm",
-       init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
-       reg_req   => { "out" => [ "gp" ] },
-       emit      => '. mov %D0, %C',
+       arity     => "variable",
+       emit      => '. mov %D0, %SO',
+       mode      => $mode_gp,
+       attr_type => "arm_shifter_operand_t",
+       constructors => \%unop_shifter_operand_constructors,
 },
 
 Mvn => {
        irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
-       emit      => '. mvn %D0, %S0%X'
-},
-
-Mvn_i => {
-       irn_flags => "R",
-       comment   => "represents a negated integer constant",
-       attr      => "long imm",
-       init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
-       reg_req   => { "out" => [ "gp" ] },
-       emit      => '. mvn %D0, %C',
+       attr_type => "arm_shifter_operand_t",
+       arity     => "variable",
+       emit      => '. mvn %D0, %SO',
+       mode      => $mode_gp,
+       constructors => \%unop_shifter_operand_constructors,
 },
 
+# Deprecated - we should construct the movs and rsbmi directly...
 Abs => {
        irn_flags => "R",
-       comment   => "construct Abs: Abs(a) = |a|",
-       reg_req   => { "in" => [ "gp" ], "out" => [ "gp" ] },
+       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
        emit      =>
 '. movs %S0, %S0, #0
-. rsbmi %D0, %S0, #0'
+. rsbmi %D0, %S0, #0',
+       mode      => $mode_gp,
 },
 
-# other operations
-
-#
 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
-#
 EmptyReg => {
        op_flags  => "c",
        irn_flags => "R",
-       comment   => "allocate an empty register for calculations",
-       reg_req   => { "out" => [ "gp" ] },
+       reg_req   => { out => [ "gp" ] },
        emit      => '. /* %D0 now available for calculations */',
-       cmp_attr  => 'return 1;'
-},
-
-Copy => {
-       comment  => "implements a register copy",
-       reg_req  => { "in" => [ "gp" ], "out" => [ "gp" ] },
+       cmp_attr  => 'return 1;',
+       mode      => $mode_gp,
 },
 
 CopyB => {
        op_flags  => "F|H",
        state     => "pinned",
-       comment   => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
-       attr      => "long imm",
-       init_attr => 'attr->imm_value = imm;',
-       reg_req   => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
+       attr      => "unsigned size",
+       attr_type => "arm_CopyB_attr_t",
+       reg_req   => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
        outs      => [ "M" ],
 },
 
+FrameAddr => {
+       op_flags  => "c",
+       irn_flags => "R",
+       attr      => "ir_entity *entity",
+       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+       ins       => [ "base" ],
+       attr_type => "arm_SymConst_attr_t",
+       mode      => $mode_gp,
+},
+
 SymConst => {
        op_flags  => "c",
        irn_flags => "R",
-       comment   => "represents a symbolic constant",
-       attr      => "ident *id",
-       init_attr => "\tset_arm_symconst_id(res, id);",
-       reg_req   => { "out" => [ "gp" ] },
-       attr_type   => "arm_SymConst_attr_t",
+       attr      => "ir_entity *entity",
+       reg_req   => { out => [ "gp" ] },
+       attr_type => "arm_SymConst_attr_t",
+       mode      => $mode_gp,
 },
 
-CmpBra => {
-       op_flags  => "L|X|Y",
-       state     => "pinned",
-       comment   => "construct conditional branch: CMP A, B && JMPxx LABEL",
-       mode      => "mode_T",
-       attr      => "int proj_num",
-       init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
-       attr_type => "arm_CondJmp_attr_t",
+Cmp => {
+       irn_flags    => "R|F",
+       emit         => '. cmp %S0, %SO',
+       mode         => $mode_flags,
+       attr_type    => "arm_cmp_attr_t",
+       constructors => \%cmp_shifter_operand_constructors,
 },
 
-TstBra => {
+Tst => {
+       irn_flags    => "R|F",
+       emit         => '. tst %S0, %SO',
+       mode         => $mode_flags,
+       attr_type    => "arm_cmp_attr_t",
+       constructors => \%cmp_shifter_operand_constructors,
+},
+
+B => {
        op_flags  => "L|X|Y",
        state     => "pinned",
-       comment   => "construct conditional branch: TST A, B && JMPxx LABEL",
        mode      => "mode_T",
+       reg_req   => { in => [ "flags" ], out => [ "none", "none" ] },
        attr      => "int proj_num",
-       init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
-       reg_req   => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] },
        attr_type => "arm_CondJmp_attr_t",
+       init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
 },
 
 Jmp => {
@@ -493,94 +383,23 @@ Jmp => {
 SwitchJmp => {
        op_flags  => "L|X|Y",
        state     => "pinned",
-       comment   => "construct switch",
        mode      => "mode_T",
        attr      => "int n_projs, long def_proj_num",
        init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
                     "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
-       reg_req   => { "in" => [ "gp" ], "out" => [ "none" ] },
+       reg_req   => { in => [ "gp" ], out => [ "none" ] },
        attr_type => "arm_SwitchJmp_attr_t",
 },
 
-# Load / Store
-
 Ldr => {
        op_flags  => "L|F",
        state     => "exc_pinned",
        ins       => [ "ptr", "mem" ],
        outs      => [ "res", "M" ],
-       reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-       emit      => '. ldr %D0, [%S0, #0]',
-       attr_type => "arm_load_store_attr_t",
-       attr      => "ir_entity *entity, int entity_sign, long offset",
-},
-
-Ldrb => {
-       op_flags  => "L|F",
-       state     => "exc_pinned",
-       ins       => [ "ptr", "mem" ],
-       outs      => [ "res", "M" ],
-       reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-       emit      => '. ldrb %D0, [%S0, #0]',
-       attr_type => "arm_load_store_attr_t",
-       attr      => "ir_entity *entity, int entity_sign, long offset",
-},
-
-Ldrbs => {
-       op_flags  => "L|F",
-       state     => "exc_pinned",
-       ins       => [ "ptr", "mem" ],
-       outs      => [ "res", "M" ],
-       reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-       emit      => '. ldrsb %D0, [%S0, #0]',
-       attr_type => "arm_load_store_attr_t",
-       attr      => "ir_entity *entity, int entity_sign, long offset",
-},
-
-Ldrh => {
-       op_flags  => "L|F",
-       state     => "exc_pinned",
-       ins       => [ "ptr", "mem" ],
-       outs      => [ "res", "M" ],
-       reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-       emit      => '. ldrh %D0, [%S0, #0]',
+       reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
+       emit      => '. ldr%LM %D0, [%S0, #%O]',
        attr_type => "arm_load_store_attr_t",
-       attr      => "ir_entity *entity, int entity_sign, long offset",
-},
-
-Ldrhs => {
-       op_flags  => "L|F",
-       state     => "exc_pinned",
-       ins       => [ "ptr", "mem" ],
-       outs      => [ "res", "M" ],
-       reg_req   => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
-       emit      => '. ldrsh %D0, [%S0, #0]',
-       attr_type => "arm_load_store_attr_t",
-       attr      => "ir_entity *entity, int entity_sign, long offset",
-},
-
-Strb => {
-       op_flags  => "L|F",
-       state     => "exc_pinned",
-       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",
-},
-
-Strh => {
-       op_flags  => "L|F",
-       state     => "exc_pinned",
-       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",
+       attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
 },
 
 Str => {
@@ -588,19 +407,18 @@ Str => {
        state     => "exc_pinned",
        ins       => [ "ptr", "val", "mem" ],
        outs      => [ "mem" ],
-       reg_req   => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
-       emit      => '. str %S1, [%S0, #0]',
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       emit      => '. str%SM %S1, [%S0, #%O]',
        mode      => "mode_M",
        attr_type => "arm_load_store_attr_t",
-       attr      => "ir_entity *entity, int entity_sign, long offset",
+       attr      => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
 },
 
 StoreStackM4Inc => {
        op_flags  => "L|F",
        irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Store: Push 4 Registers = ST ptr,val",
-       reg_req   => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "sp:I|S", "none" ] },
+       reg_req   => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
        emit      => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
        outs      => [ "ptr", "M" ],
 },
@@ -609,299 +427,164 @@ LoadStackM3Epilogue => {
        op_flags  => "L|F",
        irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
-       reg_req   => { "in" => [ "sp", "none" ], "out" => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
+       reg_req   => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
        emit      => '. ldmfd %S0, {%D0, %D1, %D2}',
        outs      => [ "res0", "res1", "res2", "M" ],
 },
 
 
-#---------------------------------------------------#
-#    __                               _             #
-#   / _|                             | |            #
-#  | |_ _ __   __ _   _ __   ___   __| | ___  ___   #
-#  |  _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __|  #
-#  | | | |_) | (_| | | | | | (_) | (_| |  __/\__ \  #
-#  |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/  #
-#      | |                                          #
-#      |_|                                          #
-#---------------------------------------------------#
-
-# commutative operations
 
 fpaAdf => {
-       op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
        emit      => '. adf%M %D0, %S0, %S1',
 },
 
-fpaAdf_i => {
-       irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
-       emit      => '. adf%M %D0, %S0, %C',
-},
-
 fpaMuf => {
-       op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
        emit      =>'. muf%M %D0, %S0, %S1',
 },
 
-fpaMuf_i => {
-       irn_flags => "R",
-       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;',
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
-       emit      => '. muf%M %D0, %S0, %C',
-},
-
 fpaFml => {
-       op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct FPA Fast Mul: Mul(a, b) = Mul(b, a) = a * b",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
        emit      =>'. fml%M %D0, %S0, %S1',
 },
 
 fpaMax => {
-       op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct FPA Max: Max(a, b) = Max(b, a) = a > b ? a : b",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
        emit      =>'. fmax %S0, %S1, %D0',
 },
 
 fpaMin => {
-       op_flags  => "C",
        irn_flags => "R",
-       comment   => "construct FPA Min: Min(a, b) = Min(b, a) = a < b ? a : b",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
        emit      =>'. fmin %S0, %S1, %D0',
 },
 
-# not commutative operations
-
 fpaSuf => {
        irn_flags => "R",
-       comment   => "construct FPA Sub: Sub(a, b) = a - b",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
        emit      => '. suf%M %D0, %S0, %S1'
 },
 
-fpaSuf_i => {
-       irn_flags => "R",
-       comment   => "construct FPA Sub: Sub(a, b) = a - b",
-       attr      => "long imm",
-       init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
-       emit      => '. suf%M %D0, %S0, %C'
-},
-
 fpaRsf => {
        irn_flags => "R",
-       comment   => "construct FPA reverse Sub: Sub(a, b) = b - a",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
        emit      => '. rsf%M %D0, %S0, %S1'
 },
 
-fpaRsf_i => {
-       irn_flags => "R",
-       comment   => "construct FPA reverse Sub: Sub(a, b) = b - a",
-       attr      => "long imm",
-       init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
-       emit      => '. rsf%M %D0, %S0, %C'
-},
-
 fpaDvf => {
-       comment   => "construct FPA Div: Div(a, b) = a / b",
        attr      => "ir_mode *op_mode",
        init_attr => "attr->op_mode = op_mode;",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
        emit      =>'. dvf%M %D0, %S0, %S1',
        outs      => [ "res", "M" ],
 },
 
-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;',
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
-       emit      =>'. dvf%M %D0, %S0, %C',
-       outs      => [ "res", "M" ],
-},
-
 fpaRdf => {
-       comment   => "construct FPA reverse Div: Div(a, b) = b / a",
        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" ],
-},
-
-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;',
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
        emit      =>'. rdf%M %D0, %S0, %S1',
        outs      => [ "res", "M" ],
 },
 
 fpaFdv => {
-       comment   => "construct FPA Fast Div: Div(a, b) = a / b",
        attr      => "ir_mode *op_mode",
        init_attr => "attr->op_mode = op_mode;",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
        emit      =>'. fdv%M %D0, %S0, %S1',
        outs      => [ "res", "M" ],
 },
 
-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;',
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
-       emit      =>'. fdv%M %D0, %S0, %C',
-       outs      => [ "res", "M" ],
-},
-
 fpaFrd => {
-       comment   => "construct FPA Fast reverse Div: Div(a, b) = b / a",
        attr      => "ir_mode *op_mode",
        init_attr => "attr->op_mode = op_mode;",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
        emit      =>'. frd%M %D0, %S0, %S1',
        outs      => [ "res", "M" ],
 },
 
-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;',
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
-       emit      =>'. frd%M %D0, %S0, %C',
-       outs      => [ "res", "M" ],
-},
-
 fpaMvf => {
        irn_flags => "R",
-       comment   => "construct FPA Move: b = a",
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
        emit      => '. mvf%M %S0, %D0',
 },
 
-fpaMvf_i => {
-       irn_flags => "R",
-       comment   => "represents a float constant",
-       attr      => "long imm",
-       init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       reg_req   => { "out" => [ "fpa" ] },
-       emit      => '. mvf%M %D0, %C',
-},
-
 fpaMnf => {
        irn_flags => "R",
-       comment   => "construct FPA Move Negated: b = -a",
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
        emit      => '. mnf%M %S0, %D0',
 },
 
-fpaMnf_i => {
-       irn_flags => "R",
-       comment   => "represents a float constant",
-       attr      => "long imm",
-       init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
-       reg_req   => { "out" => [ "fpa" ] },
-       emit      => '. mnf%M %D0, %C',
-},
-
 fpaAbs => {
        irn_flags => "R",
-       comment   => "construct FPA Absolute value: fAbsd(a) = |a|",
-       reg_req   => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
+       reg_req   => { in => [ "fpa" ], out => [ "fpa" ] },
        emit      => '. abs%M %D0, %S0',
 },
 
-# other operations
-
 fpaFlt => {
        irn_flags => "R",
-       comment   => "construct a FPA integer->float conversion",
-       reg_req   => { "in" => ["gp"], "out" => [ "fpa" ] },
+       reg_req   => { in => ["gp"], out => [ "fpa" ] },
        emit      => '. flt%M %D0, %S0',
 },
 
 fpaFix => {
        irn_flags => "R",
-       comment   => "construct a FPA float->integer conversion",
-       reg_req   => { "in" => ["fpa"], "out" => [ "gp" ] },
+       reg_req   => { in => ["fpa"], out => [ "gp" ] },
        emit      => '. fix %D0, %S0',
 },
 
 fpaCmfBra => {
        op_flags  => "L|X|Y",
        state     => "pinned",
-       comment   => "construct floating point Compare and Branch: CMF A, B && JMPxx LABEL",
        mode      => "mode_T",
        attr      => "int proj_num",
        init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "none", "none"] },
        attr_type => "arm_CondJmp_attr_t",
 },
 
 fpaCnfBra => {
        op_flags  => "L|X|Y",
        state     => "pinned",
-       comment   => "construct floating point Compare negative and Branch: CMF A, -B && JMPxx LABEL",
        mode      => "mode_T",
        attr      => "int proj_num",
        init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "none", "none"] },
        attr_type => "arm_CondJmp_attr_t",
 },
 
 fpaCmfeBra => {
        op_flags  => "L|X|Y",
        state     => "pinned",
-       comment   => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL",
        mode      => "mode_T",
        attr      => "int proj_num",
        init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "none", "none"] },
        attr_type => "arm_CondJmp_attr_t",
 },
 
 fpaCnfeBra => {
        op_flags  => "L|X|Y",
        state     => "pinned",
-       comment   => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL",
        mode      => "mode_T",
        attr      => "int proj_num",
        init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
-       reg_req   => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] },
+       reg_req   => { in => [ "fpa", "fpa" ], out => [ "none", "none"] },
        attr_type => "arm_CondJmp_attr_t",
 },
 
-# Load / Store
-
 fpaLdf => {
        op_flags  => "L|F",
        irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct FPA Load: Load(ptr, mem) = LD ptr",
        attr      => "ir_mode *op_mode",
        init_attr => "attr->op_mode = op_mode;",
-       reg_req   => { "in" => [ "gp", "none" ], "out" => [ "fpa", "none" ] },
+       reg_req   => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
        emit      => '. ldf%M %D0, [%S0]',
        outs      => [ "res", "M" ],
 },
@@ -910,10 +593,9 @@ fpaStf => {
        op_flags  => "L|F",
        irn_flags => "R",
        state     => "exc_pinned",
-       comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
        attr      => "ir_mode *op_mode",
        init_attr => "attr->op_mode = op_mode;",
-       reg_req   => { "in" => [ "gp", "fpa", "none" ], "out" => [ "none" ] },
+       reg_req   => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
        emit      => '. stf%M %S1, [%S0]',
        mode      => "mode_M",
 },
@@ -921,20 +603,17 @@ fpaStf => {
 fpaDbl2GP => {
        op_flags  => "L|F",
        irn_flags => "R",
-       comment   => "construct fp double to 2 gp register transfer",
-       reg_req   => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp", "none" ] },
+       reg_req   => { in => [ "fpa", "none" ], out => [ "gp", "gp", "none" ] },
        outs      => [ "low", "high", "M" ],
 },
 
 AddSP => {
-       comment   => "construct Add to stack pointer",
        reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
        emit      => '. add %D0, %S0, %S1',
        outs      => [ "stack", "M" ],
 },
 
 SubSPandCopy => {
-       comment   => "construct Sub from stack pointer and copy to Register",
        reg_req   => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
        ins       => [ "stack", "size", "mem" ],
        emit      => ". sub %D0, %S0, %S1\n".
@@ -944,7 +623,6 @@ SubSPandCopy => {
 
 LdTls => {
        irn_flags => "R",
-       comment   => "load the TLS address",
        reg_req   => { out => [ "gp" ] },
 },
 
@@ -955,23 +633,11 @@ LdTls => {
 fpaConst => {
        op_flags  => "c",
        irn_flags => "R",
-       comment   => "construct a floating point constant",
        attr      => "tarval *tv",
        init_attr => "attr->tv = tv;",
        mode      => "get_tarval_mode(tv)",
-       reg_req   => { "out" => [ "fpa" ] },
+       reg_req   => { out => [ "fpa" ] },
        attr_type => "arm_fpaConst_attr_t",
 }
 
-#---------------------------------------------------#
-#          __                         _             #
-#         / _|                       | |            #
-#  __   _| |_ _ __    _ __   ___   __| | ___  ___   #
-#  \ \ / /  _| '_ \  | '_ \ / _ \ / _` |/ _ \/ __|  #
-#   \ V /| | | |_) | | | | | (_) | (_| |  __/\__ \  #
-#    \_/ |_| | .__/  |_| |_|\___/ \__,_|\___||___/  #
-#            | |                                    #
-#            |_|                                    #
-#---------------------------------------------------#
-
 ); # end of %nodes
index 73055ef..88827ba 100644 (file)
 
 #include <limits.h>
 
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
 /** hold the current code generator during transformation */
 static arm_code_gen_t *env_cg;
 
-extern ir_op *get_op_Mulh(void);
-
-
-/****************************************************************************************************
- *                  _        _                        __                           _   _
- *                 | |      | |                      / _|                         | | (_)
- *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
- * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
- * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
- * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
- *
- ****************************************************************************************************/
-
-static inline int mode_needs_gp_reg(ir_mode *mode) {
+static inline int mode_needs_gp_reg(ir_mode *mode)
+{
        return mode_is_int(mode) || mode_is_reference(mode);
 }
 
-/**
- * Creates a arm_Const node.
- */
-static ir_node *create_mov_node(dbg_info *dbg, ir_node *block, long value) {
-       ir_mode *mode  = mode_Iu;
-       ir_node *res;
-
-       if (mode_needs_gp_reg(mode))
-               mode = mode_Iu;
-       res = new_bd_arm_Mov_i(dbg, block, mode, value);
-       be_dep_on_frame(res);
-       return res;
-}
-
-/**
- * Creates a arm_Const_Neg node.
- */
-static ir_node *create_mvn_node(dbg_info *dbg, ir_node *block, long value) {
-       ir_mode *mode = mode_Iu;
-       ir_node *res;
-
-       if (mode_needs_gp_reg(mode))
-               mode = mode_Iu;
-       res = new_bd_arm_Mvn_i(dbg, block, mode, value);
-       be_dep_on_frame(res);
-       return res;
-}
-
-#define NEW_BINOP_NODE(opname, env, op1, op2) new_bd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode)
-
 /**
  * Creates a possible DAG for an constant.
  */
-static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned int value) {
+static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
+                                         unsigned int value)
+{
        ir_node *result;
        arm_vals v, vn;
        int cnt;
-       ir_mode *mode = mode_Iu;
 
        arm_gen_vals_from_word(value, &v);
        arm_gen_vals_from_word(~value, &vn);
 
        if (vn.ops < v.ops) {
                /* remove bits */
-               result = create_mvn_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
+               result = new_bd_arm_Mvn_imm(dbgi, block, vn.values[0], vn.rors[0]);
+               be_dep_on_frame(result);
 
                for (cnt = 1; cnt < vn.ops; ++cnt) {
-                       long value = arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]);
-                       ir_node *bic_i_node = new_bd_arm_Bic_i(dbg, block, result, mode, value);
-                       result = bic_i_node;
+                       result = new_bd_arm_Bic_imm(dbgi, block, result,
+                                                   vn.values[cnt], vn.rors[cnt]);
                }
-       }
-       else {
+       } else {
                /* add bits */
-               result = create_mov_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
+               result = new_bd_arm_Mov_imm(dbgi, block, v.values[0], v.rors[0]);
+               be_dep_on_frame(result);
 
                for (cnt = 1; cnt < v.ops; ++cnt) {
-                       long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]);
-                       ir_node *orr_i_node = new_bd_arm_Or_i(dbg, block, result, mode, value);
-                       result = orr_i_node;
+                       result = new_bd_arm_Or_imm(dbgi, block, result,
+                                                  v.values[cnt], v.rors[cnt]);
                }
        }
        return result;
@@ -145,10 +104,11 @@ static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned
  *
  * @param irn  a Firm const
  */
-static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
+static ir_node *create_const_graph(ir_node *irn, ir_node *block)
+{
        tarval  *tv = get_Const_tarval(irn);
        ir_mode *mode = get_tarval_mode(tv);
-       int     value;
+       unsigned value;
 
        if (mode_is_reference(mode)) {
                /* ARM is 32bit, so we can safely convert a reference tarval into Iu */
@@ -162,23 +122,60 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
 /**
  * Create an And that will mask all upper bits
  */
-static ir_node *gen_zero_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
-       unsigned mask_bits = (1 << result_bits) - 1;
-       ir_node *mask_node = create_const_graph_value(dbg, block, mask_bits);
-       return new_bd_arm_And(dbg, block, op, mask_node, mode_Iu, ARM_SHF_NONE, 0);
+static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
+                                   int src_bits)
+{
+       if (src_bits == 8) {
+               return new_bd_arm_And_imm(dbgi, block, op, 0xFF, 0);
+       } else if (src_bits == 16) {
+               ir_node *lshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, 16);
+               ir_node *rshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift, ARM_SHF_LSR_IMM, 16);
+               return rshift;
+       } else {
+               panic("zero extension only supported for 8 and 16 bits");
+       }
 }
 
 /**
  * Generate code for a sign extension.
  */
-static ir_node *gen_sign_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
-       int shift_width = 32 - result_bits;
-       ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width);
-       ir_node *lshift_node = new_bd_arm_Shl(dbg, block, op, shift_const_node, mode_Iu);
-       ir_node *rshift_node = new_bd_arm_Shrs(dbg, block, lshift_node, shift_const_node, mode_Iu);
+static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
+                                   int src_bits)
+{
+       int shift_width = 32 - src_bits;
+       ir_node *lshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, shift_width);
+       ir_node *rshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift_node, ARM_SHF_ASR_IMM, shift_width);
        return rshift_node;
 }
 
+static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
+                              ir_mode *orig_mode)
+{
+       int bits = get_mode_size_bits(orig_mode);
+       if (bits == 32)
+               return op;
+
+       if (mode_is_signed(orig_mode)) {
+               return gen_sign_extension(dbgi, block, op, bits);
+       } else {
+               return gen_zero_extension(dbgi, block, op, bits);
+       }
+}
+
+/**
+ * returns true if it is assured, that the upper bits of a node are "clean"
+ * which means for a 16 or 8 bit value, that the upper bits in the register
+ * are 0 for unsigned and a copy of the last significant bit for signed
+ * numbers.
+ */
+static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
+{
+       (void) transformed_node;
+       (void) mode;
+       /* TODO */
+       return false;
+}
+
 /**
  * Transforms a Conv node.
  *
@@ -213,71 +210,163 @@ static ir_node *gen_Conv(ir_node *node) {
                                /* from int to float */
                                return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
                        }
-               }
-               else if (USE_VFP(env_cg->isa)) {
+               } else if (USE_VFP(env_cg->isa)) {
                        panic("VFP not supported yet");
                        return NULL;
-               }
-               else {
+               } else {
                        panic("Softfloat not supported yet");
                        return NULL;
                }
-       }
-       else { /* complete in gp registers */
+       } else { /* complete in gp registers */
                int src_bits = get_mode_size_bits(src_mode);
                int dst_bits = get_mode_size_bits(dst_mode);
                int min_bits;
                ir_mode *min_mode;
 
-               if (is_Load(skip_Proj(op))) {
-                       if (src_bits == dst_bits) {
-                               /* kill unneccessary conv */
-                               return new_op;
-                       }
-                       /* after a load, the bit size is already converted */
-                       src_bits = 32;
-               }
-
                if (src_bits == dst_bits) {
                        /* kill unneccessary conv */
                        return new_op;
-               } else if (dst_bits <= 32 && src_bits <= 32) {
-                       if (src_bits < dst_bits) {
-                               min_bits = src_bits;
-                               min_mode = src_mode;
-                       } else {
-                               min_bits = dst_bits;
-                               min_mode = dst_mode;
-                       }
-                       if (mode_is_signed(min_mode)) {
-                               return gen_sign_extension(dbg, block, new_op, min_bits);
-                       } else {
-                               return gen_zero_extension(dbg, block, new_op, min_bits);
-                       }
+               }
+
+               if (src_bits < dst_bits) {
+                       min_bits = src_bits;
+                       min_mode = src_mode;
                } else {
-                       panic("Cannot handle Conv %+F->%+F with %d->%d bits", src_mode, dst_mode,
-                               src_bits, dst_bits);
-                       return NULL;
+                       min_bits = dst_bits;
+                       min_mode = dst_mode;
+               }
+
+               if (upper_bits_clean(new_op, min_mode)) {
+                       return new_op;
+               }
+
+               if (mode_is_signed(min_mode)) {
+                       return gen_sign_extension(dbg, block, new_op, min_bits);
+               } else {
+                       return gen_zero_extension(dbg, block, new_op, min_bits);
                }
        }
 }
 
-/**
- * Return true if an operand is a shifter operand
- */
-static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
-       arm_shift_modifier mod = ARM_SHF_NONE;
+typedef struct {
+       unsigned char  imm_8;
+       unsigned char  rot;
+} arm_immediate_t;
+
+static bool try_encode_as_immediate(const ir_node *node, arm_immediate_t *res)
+{
+       unsigned val;
+
+       if (!is_Const(node))
+               return false;
 
-       if (is_arm_Mov(n))
-               mod = get_arm_shift_modifier(n);
+       val = get_tarval_long(get_Const_tarval(node));
 
-       *pmod = mod;
-       if (mod != ARM_SHF_NONE) {
-               long v = get_arm_imm_value(n);
-               if (v < 32)
-                       return (int)v;
+       if (val == 0) {
+               res->imm_8 = 0;
+               res->rot   = 0;
+               return true;
+       }
+       if (val <= 0xff) {
+               res->imm_8 = val;
+               res->rot   = 0;
+               return true;
        }
-       return 0;
+       /* arm allows to use to rotate an 8bit immediate value by a multiple of 2
+          (= 0, 2, 4, 6, ...).
+          So we determine the smallest even position with a bit set
+          and the highest even position with no bit set anymore.
+          If the difference between these 2 is <= 8, then we can encode the value
+          as immediate.
+        */
+       unsigned low_pos  = ntz(val) & ~1u;
+       unsigned high_pos = (32-nlz(val)+1) & ~1u;
+
+       if (high_pos - low_pos <= 8) {
+               res->imm_8 = val >> low_pos;
+               res->rot   = 32 - low_pos;
+               return true;
+       }
+
+       if (high_pos > 24) {
+               res->rot = 34 - high_pos;
+               val      = val >> (32-res->rot) | val << (res->rot);
+               if (val <= 0xff) {
+                       res->imm_8 = val;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static int is_downconv(const ir_node *node)
+{
+       ir_mode *src_mode;
+       ir_mode *dest_mode;
+
+       if (!is_Conv(node))
+               return 0;
+
+       /* we only want to skip the conv when we're the only user
+        * (not optimal but for now...)
+        */
+       if (get_irn_n_edges(node) > 1)
+               return 0;
+
+       src_mode  = get_irn_mode(get_Conv_op(node));
+       dest_mode = get_irn_mode(node);
+       return
+               mode_needs_gp_reg(src_mode)  &&
+               mode_needs_gp_reg(dest_mode) &&
+               get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
+}
+
+static ir_node *arm_skip_downconv(ir_node *node)
+{
+       while (is_downconv(node))
+               node = get_Conv_op(node);
+       return node;
+}
+
+typedef enum {
+       MATCH_NONE         = 0,
+       MATCH_COMMUTATIVE  = 1 << 0,
+       MATCH_SIZE_NEUTRAL = 1 << 1,
+} match_flags_t;
+
+typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
+typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot);
+
+static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
+               new_binop_reg_func new_reg, new_binop_imm_func new_imm)
+{
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_binop_left(node);
+       ir_node  *new_op1;
+       ir_node  *op2     = get_binop_right(node);
+       ir_node  *new_op2;
+       dbg_info *dbgi    = get_irn_dbg_info(node);
+       arm_immediate_t imm;
+
+       if (flags & MATCH_SIZE_NEUTRAL) {
+               op1 = arm_skip_downconv(op1);
+               op2 = arm_skip_downconv(op2);
+       } else {
+               assert(get_mode_size_bits(get_irn_mode(node)) == 32);
+       }
+
+       if (try_encode_as_immediate(op2, &imm)) {
+               ir_node *new_op1 = be_transform_node(op1);
+               return new_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
+       }
+       new_op2 = be_transform_node(op2);
+    if ((flags & MATCH_COMMUTATIVE) && try_encode_as_immediate(op1, &imm)) {
+               return new_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
+       }
+       new_op1 = be_transform_node(op1);
+
+       return new_reg(dbgi, block, new_op1, new_op2);
 }
 
 /**
@@ -285,26 +374,26 @@ static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
  *
  * @return the created arm Add node
  */
-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);
+static ir_node *gen_Add(ir_node *node)
+{
        ir_mode  *mode    = get_irn_mode(node);
-       ir_node  *new_op3;
-       int v;
-       arm_shift_modifier mod;
-       dbg_info *dbg = get_irn_dbg_info(node);
 
        if (mode_is_float(mode)) {
+               ir_node  *block   = be_transform_node(get_nodes_block(node));
+               ir_node  *op1     = get_Add_left(node);
+               ir_node  *op2     = get_Add_right(node);
+               dbg_info *dbgi    = get_irn_dbg_info(node);
+               ir_node  *new_op1 = be_transform_node(op1);
+               ir_node  *new_op2 = be_transform_node(op2);
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa)) {
+#if 0
                        if (is_arm_fpaMvf_i(new_op1))
-                               return new_bd_arm_fpaAdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
+                               return new_bd_arm_fpaAdf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
                        if (is_arm_fpaMvf_i(new_op2))
-                               return new_bd_arm_fpaAdf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
-                       return new_bd_arm_fpaAdf(dbg, block, new_op1, new_op2, mode);
+                               return new_bd_arm_fpaAdf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
+#endif
+                       return new_bd_arm_fpaAdf(dbgi, 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");
@@ -315,47 +404,26 @@ static ir_node *gen_Add(ir_node *node) {
                        return NULL;
                }
        } else {
-               assert(mode_is_data(mode));
-               mode = mode_Iu;
-
-               if (is_arm_Mov_i(new_op1))
-                       return new_bd_arm_Add_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
-               if (is_arm_Mov_i(new_op2))
-                       return new_bd_arm_Add_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
-
+#if 0
                /* check for MLA */
                if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
                        new_op3 = new_op2;
                        new_op2 = get_irn_n(new_op1, 1);
                        new_op1 = get_irn_n(new_op1, 0);
 
-                       return new_bd_arm_Mla(dbg, block, new_op1, new_op2, new_op3, mode);
+                       return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
                }
                if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
                        new_op3 = new_op1;
                        new_op1 = get_irn_n(new_op2, 0);
                        new_op2 = get_irn_n(new_op2, 1);
 
-                       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) {
-                       new_op1 = get_irn_n(new_op1, 0);
-                       return new_bd_arm_Add(dbg, block, new_op2, new_op1, mode, mod, v);
-               }
-               /* is the second a shifter */
-               v = is_shifter_operand(new_op2, &mod);
-               if (v) {
-                       new_op2 = get_irn_n(new_op2, 0);
-                       return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, mod, v);
+                       return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
                }
 #endif
 
-               /* normal ADD */
-               return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
+               return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
+                               new_bd_arm_Add_reg, new_bd_arm_Add_imm);
        }
 }
 
@@ -376,10 +444,12 @@ static ir_node *gen_Mul(ir_node *node) {
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa)) {
+#if 0
                        if (is_arm_Mov_i(new_op1))
                                return new_bd_arm_fpaMuf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
                        if (is_arm_Mov_i(new_op2))
                                return new_bd_arm_fpaMuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
+#endif
                        return new_bd_arm_fpaMuf(dbg, block, new_op1, new_op2, mode);
                }
                else if (USE_VFP(env_cg->isa)) {
@@ -393,8 +463,7 @@ static ir_node *gen_Mul(ir_node *node) {
                }
        }
        assert(mode_is_data(mode));
-       mode = mode_Iu;
-       return new_bd_arm_Mul(dbg, block, new_op1, new_op2, mode);
+       return new_bd_arm_Mul(dbg, block, new_op1, new_op2);
 }
 
 /**
@@ -416,10 +485,12 @@ static ir_node *gen_Quot(ir_node *node) {
 
        env_cg->have_fp_insn = 1;
        if (USE_FPA(env_cg->isa)) {
+#if 0
                if (is_arm_Mov_i(new_op1))
                        return new_bd_arm_fpaRdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
                if (is_arm_Mov_i(new_op2))
                        return new_bd_arm_fpaDvf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
+#endif
                return new_bd_arm_fpaDvf(dbg, block, new_op1, new_op2, mode);
        } else if (USE_VFP(env_cg->isa)) {
                assert(mode != mode_E && "IEEE Extended FP not supported");
@@ -431,43 +502,15 @@ static ir_node *gen_Quot(ir_node *node) {
        }
 }
 
-#define GEN_INT_OP(op) \
-       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_mode  *mode    = mode_Iu; \
-       dbg_info *dbg     = get_irn_dbg_info(node); \
-       int      v; \
-       arm_shift_modifier mod; \
- \
-       if (is_arm_Mov_i(new_op1)) \
-               return new_bd_arm_ ## op ## _i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1)); \
-       if (is_arm_Mov_i(new_op2)) \
-               return new_bd_arm_ ## op ## _i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2)); \
-       /* is the first a shifter */ \
-       v = is_shifter_operand(new_op1, &mod); \
-       if (v) { \
-               new_op1 = get_irn_n(new_op1, 0); \
-               return new_bd_arm_ ## op(dbg, block, new_op2, new_op1, mode, mod, v); \
-       } \
-       /* is the second a shifter */ \
-       v = is_shifter_operand(new_op2, &mod); \
-       if (v) { \
-               new_op2 = get_irn_n(new_op2, 0); \
-               return new_bd_arm_ ## op(dbg, block, new_op1, new_op2, mode, mod, v); \
-       } \
-       /* Normal op */ \
-       return new_bd_arm_ ## op(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0) \
-
 /**
  * Creates an ARM And.
  *
  * @return the created arm And node
  */
-static ir_node *gen_And(ir_node *node) {
-       GEN_INT_OP(And);
+static ir_node *gen_And(ir_node *node)
+{
+       return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
+                       new_bd_arm_And_reg, new_bd_arm_And_imm);
 }
 
 /**
@@ -476,8 +519,10 @@ static ir_node *gen_And(ir_node *node) {
  * @param env   The transformation environment
  * @return the created arm Or node
  */
-static ir_node *gen_Or(ir_node *node) {
-       GEN_INT_OP(Or);
+static ir_node *gen_Or(ir_node *node)
+{
+       return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
+                       new_bd_arm_Or_reg, new_bd_arm_Or_imm);
 }
 
 /**
@@ -485,8 +530,10 @@ static ir_node *gen_Or(ir_node *node) {
  *
  * @return the created arm Eor node
  */
-static ir_node *gen_Eor(ir_node *node) {
-       GEN_INT_OP(Eor);
+static ir_node *gen_Eor(ir_node *node)
+{
+       return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
+                       new_bd_arm_Eor_reg, new_bd_arm_Eor_imm);
 }
 
 /**
@@ -494,59 +541,57 @@ static ir_node *gen_Eor(ir_node *node) {
  *
  * @return the created arm Sub node
  */
-static ir_node *gen_Sub(ir_node *node) {
+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(op2);
        ir_mode  *mode    = get_irn_mode(node);
-       dbg_info *dbg     = get_irn_dbg_info(node);
-       int      v;
-       arm_shift_modifier mod;
+       dbg_info *dbgi    = get_irn_dbg_info(node);
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa)) {
+#if 0
                        if (is_arm_Mov_i(new_op1))
-                               return new_bd_arm_fpaRsf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
+                               return new_bd_arm_fpaRsf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
                        if (is_arm_Mov_i(new_op2))
-                               return new_bd_arm_fpaSuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
-                       return new_bd_arm_fpaSuf(dbg, block, new_op1, new_op2, mode);
+                               return new_bd_arm_fpaSuf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
+#endif
+                       return new_bd_arm_fpaSuf(dbgi, 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");
                        return NULL;
-               }
-               else {
+               } else {
                        panic("Softfloat not supported yet");
                        return NULL;
                }
+       } else {
+               return gen_int_binop(node, MATCH_SIZE_NEUTRAL,
+                               new_bd_arm_Sub_reg, new_bd_arm_Sub_imm);
        }
-       else {
-               assert(mode_is_data(mode) && "unknown mode for Sub");
-               mode = mode_Iu;
-
-               if (is_arm_Mov_i(new_op1))
-                       return new_bd_arm_Rsb_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
-               if (is_arm_Mov_i(new_op2))
-                       return new_bd_arm_Sub_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
+}
 
-               /* is the first a shifter */
-               v = is_shifter_operand(new_op1, &mod);
-               if (v) {
-                       new_op1 = get_irn_n(new_op1, 0);
-                       return new_bd_arm_Rsb(dbg, block, new_op2, new_op1, mode, mod, v);
-               }
-               /* is the second a shifter */
-               v = is_shifter_operand(new_op2, &mod);
-               if (v) {
-                       new_op2 = get_irn_n(new_op2, 0);
-                       return new_bd_arm_Sub(dbg, block, new_op1, new_op2, mode, mod, v);
-               }
-               /* normal sub */
-               return new_bd_arm_Sub(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
+static ir_node *make_shift(ir_node *node, match_flags_t flags,
+               arm_shift_modifier shift_modifier)
+{
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *op1     = get_binop_left(node);
+       ir_node  *op2     = get_binop_right(node);
+       dbg_info *dbgi    = get_irn_dbg_info(node);
+       ir_node  *new_op1;
+       ir_node  *new_op2;
+
+       if (flags & MATCH_SIZE_NEUTRAL) {
+               op1 = arm_skip_downconv(op1);
+               op2 = arm_skip_downconv(op2);
        }
+       new_op1 = be_transform_node(op1);
+       new_op2 = be_transform_node(op2);
+       return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2, shift_modifier);
 }
 
 /**
@@ -554,19 +599,9 @@ static ir_node *gen_Sub(ir_node *node) {
  *
  * @return the created ARM Shl node
  */
-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    = mode_Iu;
-       dbg_info *dbg     = get_irn_dbg_info(node);
-
-       if (is_arm_Mov_i(new_op2)) {
-               return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_LSL, get_arm_imm_value(new_op2));
-       }
-       return new_bd_arm_Shl(dbg, block, new_op1, new_op2, mode);
+static ir_node *gen_Shl(ir_node *node)
+{
+       return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
 }
 
 /**
@@ -574,19 +609,9 @@ static ir_node *gen_Shl(ir_node *node) {
  *
  * @return the created ARM Shr node
  */
-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    = mode_Iu;
-       dbg_info *dbg     = get_irn_dbg_info(node);
-
-       if (is_arm_Mov_i(new_op2)) {
-               return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_LSR, get_arm_imm_value(new_op2));
-       }
-       return new_bd_arm_Shr(dbg, block, new_op1, new_op2, mode);
+static ir_node *gen_Shr(ir_node *node)
+{
+       return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
 }
 
 /**
@@ -594,19 +619,9 @@ static ir_node *gen_Shr(ir_node *node) {
  *
  * @return the created ARM Shrs node
  */
-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    = mode_Iu;
-       dbg_info *dbg     = get_irn_dbg_info(node);
-
-       if (is_arm_Mov_i(new_op2)) {
-               return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ASR, get_arm_imm_value(new_op2));
-       }
-       return new_bd_arm_Shrs(dbg, block, new_op1, new_op2, mode);
+static ir_node *gen_Shrs(ir_node *node)
+{
+       return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
 }
 
 /**
@@ -614,17 +629,15 @@ static ir_node *gen_Shrs(ir_node *node) {
  *
  * @return the created ARM Ror node
  */
-static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
+{
        ir_node  *block   = be_transform_node(get_nodes_block(node));
        ir_node  *new_op1 = be_transform_node(op1);
+       dbg_info *dbgi    = get_irn_dbg_info(node);
        ir_node  *new_op2 = be_transform_node(op2);
-       ir_mode  *mode    = mode_Iu;
-       dbg_info *dbg     = get_irn_dbg_info(node);
 
-       if (is_arm_Mov_i(new_op2)) {
-               return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ROR, get_arm_imm_value(new_op2));
-       }
-       return new_bd_arm_Ror(dbg, block, new_op1, new_op2, mode);
+       return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
+                                           ARM_SHF_ROR_REG);
 }
 
 /**
@@ -634,15 +647,16 @@ static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) {
  *
  * Note: there is no Rol on arm, we have to use Ror
  */
-static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2)
+{
        ir_node  *block   = be_transform_node(get_nodes_block(node));
        ir_node  *new_op1 = be_transform_node(op1);
-       ir_mode  *mode    = mode_Iu;
-       dbg_info *dbg     = get_irn_dbg_info(node);
+       dbg_info *dbgi    = get_irn_dbg_info(node);
        ir_node  *new_op2 = be_transform_node(op2);
 
-       new_op2 = new_bd_arm_Rsb_i(dbg, block, new_op2, mode, 32);
-       return new_bd_arm_Ror(dbg, block, new_op1, new_op2, mode);
+       new_op2 = new_bd_arm_Rsb_imm(dbgi, block, new_op2, 32, 0);
+       return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
+                                           ARM_SHF_ROR_REG);
 }
 
 /**
@@ -650,7 +664,8 @@ static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) {
  *
  * @return the created ARM Ror node
  */
-static ir_node *gen_Rotl(ir_node *node) {
+static ir_node *gen_Rotl(ir_node *node)
+{
        ir_node *rotate = NULL;
        ir_node *op1    = get_Rotl_left(node);
        ir_node *op2    = get_Rotl_right(node);
@@ -687,19 +702,18 @@ static ir_node *gen_Rotl(ir_node *node) {
                                rotate = gen_Ror(node, op1, right);
                }
        } else if (is_Const(op2)) {
-                       tarval  *tv   = get_Const_tarval(op2);
-                       ir_mode *mode = get_irn_mode(node);
-                       long     bits = get_mode_size_bits(mode);
+               tarval  *tv   = get_Const_tarval(op2);
+               ir_mode *mode = get_irn_mode(node);
+               long     bits = get_mode_size_bits(mode);
 
-                       if (tarval_is_long(tv) && bits == 32) {
-                               ir_node  *block   = be_transform_node(get_nodes_block(node));
-                               ir_node  *new_op1 = be_transform_node(op1);
-                               ir_mode  *mode    = mode_Iu;
-                               dbg_info *dbg     = get_irn_dbg_info(node);
+               if (tarval_is_long(tv) && bits == 32) {
+                       ir_node  *block   = be_transform_node(get_nodes_block(node));
+                       ir_node  *new_op1 = be_transform_node(op1);
+                       dbg_info *dbgi    = get_irn_dbg_info(node);
 
-                               bits = (bits - get_tarval_long(tv)) & 31;
-                               rotate = new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ROR, bits);
-                       }
+                       bits = (bits - get_tarval_long(tv)) & 31;
+                       rotate = new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1, ARM_SHF_ROR_IMM, bits);
+               }
        }
 
        if (rotate == NULL) {
@@ -714,19 +728,16 @@ static ir_node *gen_Rotl(ir_node *node) {
  *
  * @return the created ARM Not node
  */
-static ir_node *gen_Not(ir_node *node) {
+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);
-       ir_mode  *mode    = mode_Iu;
-       arm_shift_modifier mod = ARM_SHF_NONE;
-       int      v        = is_shifter_operand(new_op, &mod);
+       dbg_info *dbgi    = get_irn_dbg_info(node);
 
-       if (v) {
-               new_op = get_irn_n(new_op, 0);
-       }
-       return new_bd_arm_Mvn(dbg, block, new_op, mode, mod, v);
+       /* TODO: we could do alot more here with all the Mvn variations */
+
+       return new_bd_arm_Mvn_reg(dbgi, block, new_op);
 }
 
 /**
@@ -735,17 +746,18 @@ static ir_node *gen_Not(ir_node *node) {
  * @param env   The transformation environment
  * @return the created ARM Abs node
  */
-static ir_node *gen_Abs(ir_node *node) {
+static ir_node *gen_Abs(ir_node *node)
+{
        ir_node  *block   = be_transform_node(get_nodes_block(node));
        ir_node  *op      = get_Abs_op(node);
        ir_node  *new_op  = be_transform_node(op);
-       dbg_info *dbg     = get_irn_dbg_info(node);
+       dbg_info *dbgi    = get_irn_dbg_info(node);
        ir_mode  *mode    = get_irn_mode(node);
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa))
-                       return new_bd_arm_fpaAbs(dbg, block, new_op, mode);
+                       return new_bd_arm_fpaAbs(dbgi, block, new_op, mode);
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
                        panic("VFP not supported yet");
@@ -755,8 +767,7 @@ static ir_node *gen_Abs(ir_node *node) {
                }
        }
        assert(mode_is_data(mode));
-       mode = mode_Iu;
-       return new_bd_arm_Abs(dbg, block, new_op, mode);
+       return new_bd_arm_Abs(dbgi, block, new_op);
 }
 
 /**
@@ -764,17 +775,18 @@ static ir_node *gen_Abs(ir_node *node) {
  *
  * @return the created ARM Minus node
  */
-static ir_node *gen_Minus(ir_node *node) {
+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);
+       dbg_info *dbgi    = get_irn_dbg_info(node);
        ir_mode  *mode    = get_irn_mode(node);
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa))
-                       return new_bd_arm_fpaMvf(dbg, block, op, mode);
+                       return new_bd_arm_fpaMvf(dbgi, block, op, mode);
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
                        panic("VFP not supported yet");
@@ -784,8 +796,7 @@ static ir_node *gen_Minus(ir_node *node) {
                }
        }
        assert(mode_is_data(mode));
-       mode = mode_Iu;
-       return new_bd_arm_Rsb_i(dbg, block, new_op, mode, 0);
+       return new_bd_arm_Rsb_imm(dbgi, block, new_op, 0, 0);
 }
 
 /**
@@ -800,61 +811,23 @@ static ir_node *gen_Load(ir_node *node) {
        ir_node  *mem      = get_Load_mem(node);
        ir_node  *new_mem  = be_transform_node(mem);
        ir_mode  *mode     = get_Load_mode(node);
-       dbg_info *dbg      = get_irn_dbg_info(node);
+       dbg_info *dbgi      = get_irn_dbg_info(node);
        ir_node  *new_load = NULL;
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa))
-                       new_load = new_bd_arm_fpaLdf(dbg, block, new_ptr, new_mem, mode);
+                       new_load = new_bd_arm_fpaLdf(dbgi, 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");
-               }
-               else {
+               } else {
                        panic("Softfloat not supported yet");
                }
-       }
-       else {
+       } else {
                assert(mode_is_data(mode) && "unsupported mode for Load");
 
-               if (mode_is_signed(mode)) {
-                       /* sign extended loads */
-                       switch (get_mode_size_bits(mode)) {
-                       case 8:
-                               new_load = new_bd_arm_Ldrbs(dbg, block, new_ptr, new_mem, NULL,
-                                                           0, 0);
-                               break;
-                       case 16:
-                               new_load = new_bd_arm_Ldrhs(dbg, block, new_ptr, new_mem, NULL,
-                                                           0, 0);
-                               break;
-                       case 32:
-                               new_load = new_bd_arm_Ldr(dbg, block, new_ptr, new_mem, NULL,
-                                                         0, 0);
-                               break;
-                       default:
-                               panic("mode size not supported");
-                       }
-               } else {
-                       /* zero extended loads */
-                       switch (get_mode_size_bits(mode)) {
-                       case 8:
-                               new_load = new_bd_arm_Ldrb(dbg, block, new_ptr, new_mem, NULL,
-                                                          0, 0);
-                               break;
-                       case 16:
-                               new_load = new_bd_arm_Ldrh(dbg, block, new_ptr, new_mem, NULL,
-                                                          0, 0);
-                               break;
-                       case 32:
-                               new_load = new_bd_arm_Ldr(dbg, block, new_ptr, new_mem, NULL,
-                                                         0, 0);
-                               break;
-                       default:
-                               panic("mode size not supported");
-                       }
-               }
+               new_load = new_bd_arm_Ldr(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
        }
        set_irn_pinned(new_load, get_irn_pinned(node));
 
@@ -883,13 +856,14 @@ static ir_node *gen_Store(ir_node *node)
        ir_node  *val      = get_Store_value(node);
        ir_node  *new_val  = be_transform_node(val);
        ir_mode  *mode     = get_irn_mode(val);
-       dbg_info *dbg      = get_irn_dbg_info(node);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
        ir_node *new_store = NULL;
 
        if (mode_is_float(mode)) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa))
-                       new_store = new_bd_arm_fpaStf(dbg, block, new_ptr, new_val, new_mem, mode);
+                       new_store = new_bd_arm_fpaStf(dbgi, block, new_ptr, new_val,
+                                                     new_mem, mode);
                else if (USE_VFP(env_cg->isa)) {
                        assert(mode != mode_E && "IEEE Extended FP not supported");
                        panic("VFP not supported yet");
@@ -898,22 +872,8 @@ static ir_node *gen_Store(ir_node *node)
                }
        } else {
                assert(mode_is_data(mode) && "unsupported mode for Store");
-               switch (get_mode_size_bits(mode)) {
-               case 8:
-                       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_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:
-                       panic("unsupported store size %d bits\n", get_mode_size_bits(mode));
-               }
+               new_store = new_bd_arm_Str(dbgi, block, new_ptr, new_val, new_mem, mode,
+                                          NULL, 0, 0, false);
        }
        set_irn_pinned(new_store, get_irn_pinned(node));
        return new_store;
@@ -928,114 +888,144 @@ static ir_node *gen_Jmp(ir_node *node)
        return new_bd_arm_Jmp(dbgi, new_block);
 }
 
-/**
- * Transforms a Cond.
- *
- * @return the created ARM Cond node
- */
-static ir_node *gen_Cond(ir_node *node) {
+static ir_node *gen_be_Call(ir_node *node)
+{
+       ir_node *res = be_duplicate_node(node);
+       arch_irn_add_flags(res, arch_irn_flags_modify_flags);
+
+       return res;
+}
+
+static ir_node *gen_SwitchJmp(ir_node *node)
+{
        ir_node  *block    = be_transform_node(get_nodes_block(node));
        ir_node  *selector = get_Cond_selector(node);
-       dbg_info *dbg      = get_irn_dbg_info(node);
-       ir_mode  *mode     = get_irn_mode(selector);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_node *new_op = be_transform_node(selector);
+       ir_node *const_graph;
+       ir_node *sub;
+
+       ir_node *proj;
+       const ir_edge_t *edge;
+       int min = INT_MAX;
+       int max = INT_MIN;
+       int translation;
+       int pn;
+       int n_projs;
+
+       foreach_out_edge(node, edge) {
+               proj = get_edge_src_irn(edge);
+               assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
+
+               pn = get_Proj_proj(proj);
+
+               min = pn<min ? pn : min;
+               max = pn>max ? pn : max;
+       }
+       translation = min;
+       n_projs = max - translation + 1;
 
-       if (mode == mode_b) {
-               /* an conditional jump */
-               ir_node *cmp_node = get_Proj_pred(selector);
-               ir_node *op1      = get_Cmp_left(cmp_node);
-               ir_node *new_op1  = be_transform_node(op1);
-               ir_node *op2      = get_Cmp_right(cmp_node);
-
-               if (mode_is_float(get_irn_mode(op1))) {
-                       ir_node *new_op2  = be_transform_node(op2);
-                       /* floating point compare */
-                       pn_Cmp pnc = get_Proj_proj(selector);
-
-                       if (pnc & pn_Cmp_Uo) {
-                               /* check for unordered, need cmf */
-                               return new_bd_arm_fpaCmfBra(dbg, block, new_op1, new_op2, pnc);
-                       }
-                       /* Hmm: use need cmfe */
-                       return new_bd_arm_fpaCmfeBra(dbg, block, new_op1, new_op2, pnc);
-               } else if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
-                       /* compare with 0 */
-                       return new_bd_arm_TstBra(dbg, block, new_op1, new_op1, get_Proj_proj(selector));
-               } else {
-                       /* integer compare */
-                       ir_node *new_op2  = be_transform_node(op2);
-                       return new_bd_arm_CmpBra(dbg, block, new_op1, new_op2, get_Proj_proj(selector));
-               }
-       } else {
-               /* SwitchJmp */
-               ir_node *new_op = be_transform_node(selector);
-               ir_node *const_graph;
-               ir_node *sub;
-
-               ir_node *proj;
-               const ir_edge_t *edge;
-               int min = INT_MAX;
-               int max = INT_MIN;
-               int translation;
-               int pn;
-               int n_projs;
-
-               foreach_out_edge(node, edge) {
-                       proj = get_edge_src_irn(edge);
-                       assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
-
-                       pn = get_Proj_proj(proj);
-
-                       min = pn<min ? pn : min;
-                       max = pn>max ? pn : max;
-               }
-               translation = min;
-               n_projs = max - translation + 1;
+       foreach_out_edge(node, edge) {
+               proj = get_edge_src_irn(edge);
+               assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
 
-               foreach_out_edge(node, edge) {
-                       proj = get_edge_src_irn(edge);
-                       assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
+               pn = get_Proj_proj(proj) - translation;
+               set_Proj_proj(proj, pn);
+       }
 
-                       pn = get_Proj_proj(proj) - translation;
-                       set_Proj_proj(proj, pn);
+       const_graph = create_const_graph_value(dbgi, block, translation);
+       sub = new_bd_arm_Sub_reg(dbgi, block, new_op, const_graph);
+       return new_bd_arm_SwitchJmp(dbgi, block, sub, n_projs, get_Cond_default_proj(node) - translation);
+}
+
+static ir_node *gen_Cmp(ir_node *node)
+{
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *op1      = get_Cmp_left(node);
+       ir_node  *op2      = get_Cmp_right(node);
+       ir_mode  *cmp_mode = get_irn_mode(op1);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_node  *new_op1;
+       ir_node  *new_op2;
+       bool      is_unsigned;
+
+       if (mode_is_float(cmp_mode)) {
+               /* TODO: revivie this code */
+               panic("FloatCmp NIY");
+#if 0
+               ir_node *new_op2  = be_transform_node(op2);
+               /* floating point compare */
+               pn_Cmp pnc = get_Proj_proj(selector);
+
+               if (pnc & pn_Cmp_Uo) {
+                       /* check for unordered, need cmf */
+                       return new_bd_arm_fpaCmfBra(dbgi, block, new_op1, new_op2, pnc);
                }
+               /* Hmm: use need cmfe */
+               return new_bd_arm_fpaCmfeBra(dbgi, block, new_op1, new_op2, pnc);
+#endif
+       }
 
-               const_graph = create_const_graph_value(dbg, block, translation);
-               sub = new_bd_arm_Sub(dbg, block, new_op, const_graph, mode, ARM_SHF_NONE, 0);
-               return new_bd_arm_SwitchJmp(dbg, block, sub, n_projs, get_Cond_default_proj(node) - translation);
+       assert(get_irn_mode(op2) == cmp_mode);
+       is_unsigned = !mode_is_signed(cmp_mode);
+
+       /* compare with 0 can be done with Tst */
+       if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
+               new_op1 = be_transform_node(op1);
+               new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
+               return new_bd_arm_Tst_reg(dbgi, block, new_op1, new_op1, false,
+                                         is_unsigned);
+       }
+       if (is_Const(op1) && tarval_is_null(get_Const_tarval(op1))) {
+               new_op2 = be_transform_node(op2);
+               new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
+               return new_bd_arm_Tst_reg(dbgi, block, new_op2, new_op2, true,
+                                         is_unsigned);
        }
+
+       /* integer compare, TODO: use shifer_op in all its combinations */
+       new_op1 = be_transform_node(op1);
+       new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
+       new_op2 = be_transform_node(op2);
+       new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
+       return new_bd_arm_Cmp_reg(dbgi, block, new_op1, new_op2, false,
+                                 is_unsigned);
 }
 
 /**
- * Returns the name of a SymConst.
- * @param symc  the SymConst
- * @return name of the SymConst
+ * Transforms a Cond.
+ *
+ * @return the created ARM Cond node
  */
-static ident *get_sc_ident(ir_node *symc) {
-       ir_entity *ent;
-
-       switch (get_SymConst_kind(symc)) {
-               case symconst_addr_name:
-                       return get_SymConst_name(symc);
-
-               case symconst_addr_ent:
-                       ent = get_SymConst_entity(symc);
-                       set_entity_backend_marked(ent, 1);
-                       return get_entity_ld_ident(ent);
+static ir_node *gen_Cond(ir_node *node)
+{
+       ir_node  *selector = get_Cond_selector(node);
+       ir_mode  *mode     = get_irn_mode(selector);
+       ir_node  *block;
+       ir_node  *flag_node;
+       dbg_info *dbgi;
 
-               default:
-                       assert(0 && "Unsupported SymConst");
+       if (mode != mode_b) {
+               return gen_SwitchJmp(node);
        }
+       assert(is_Proj(selector));
+
+       block     = be_transform_node(get_nodes_block(node));
+       dbgi      = get_irn_dbg_info(node);
+       flag_node = be_transform_node(get_Proj_pred(selector));
 
-       return NULL;
+       return new_bd_arm_B(dbgi, block, flag_node, get_Proj_proj(selector));
 }
 
 static tarval *fpa_imm[3][fpa_max];
 
+#if 0
 /**
  * Check, if a floating point tarval is an fpa immediate, i.e.
  * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
  */
-static int is_fpa_immediate(tarval *tv) {
+static int is_fpa_immediate(tarval *tv)
+{
        ir_mode *mode = get_tarval_mode(tv);
        int i, j, res = 1;
 
@@ -1061,6 +1051,7 @@ static int is_fpa_immediate(tarval *tv) {
        }
        return fpa_max;
 }
+#endif
 
 /**
  * Transforms a Const node.
@@ -1076,6 +1067,7 @@ static ir_node *gen_Const(ir_node *node) {
                env_cg->have_fp_insn = 1;
                if (USE_FPA(env_cg->isa)) {
                        tarval *tv = get_Const_tarval(node);
+#if 0
                        int imm = is_fpa_immediate(tv);
 
                        if (imm != fpa_max) {
@@ -1084,6 +1076,8 @@ static ir_node *gen_Const(ir_node *node) {
                                else
                                        node = new_bd_arm_fpaMnf_i(dbg, block, mode, -imm);
                        } else {
+#endif
+                       {
                                node = new_bd_arm_fpaConst(dbg, block, tv);
                        }
                        be_dep_on_frame(node);
@@ -1105,15 +1099,16 @@ static ir_node *gen_Const(ir_node *node) {
  *
  * @return The transformed ARM node.
  */
-static ir_node *gen_SymConst(ir_node *node) {
-       ir_node  *block = be_transform_node(get_nodes_block(node));
-       ir_mode  *mode  = mode_Iu;
-       dbg_info *dbg   = get_irn_dbg_info(node);
-       ir_node  *res;
+static ir_node *gen_SymConst(ir_node *node)
+{
+       ir_node   *block  = be_transform_node(get_nodes_block(node));
+       ir_entity *entity = get_SymConst_entity(node);
+       dbg_info  *dbgi   = get_irn_dbg_info(node);
+       ir_node   *new_node;
 
-       res = new_bd_arm_SymConst(dbg, block, mode, get_sc_ident(node));
-       be_dep_on_frame(res);
-       return res;
+       new_node = new_bd_arm_SymConst(dbgi, block, entity);
+       be_dep_on_frame(new_node);
+       return new_node;
 }
 
 /**
@@ -1138,104 +1133,26 @@ static ir_node *gen_CopyB(ir_node *node) {
        dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], block, new_dst);
 
        return new_bd_arm_CopyB(dbg, block, dst_copy, src_copy,
-                       new_bd_arm_EmptyReg(dbg, block, mode_Iu),
-                       new_bd_arm_EmptyReg(dbg, block, mode_Iu),
-                       new_bd_arm_EmptyReg(dbg, block, mode_Iu),
+                       new_bd_arm_EmptyReg(dbg, block),
+                       new_bd_arm_EmptyReg(dbg, block),
+                       new_bd_arm_EmptyReg(dbg, block),
                        new_mem, size);
 }
 
-
-/********************************************
- *  _                          _
- * | |                        | |
- * | |__   ___ _ __   ___   __| | ___  ___
- * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
- * | |_) |  __/ | | | (_) | (_| |  __/\__ \
- * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
- *
- ********************************************/
-
-/**
- * Return an expanding stack offset.
- * Note that function is called in the transform phase
- * where the stack offsets are still relative regarding
- * the first (frame allocating) IncSP.
- * However this is exactly what we want because frame
- * access must be done relative the the fist IncSP ...
- */
-static int get_sp_expand_offset(ir_node *inc_sp) {
-       int offset = be_get_IncSP_offset(inc_sp);
-
-       if (offset == BE_STACK_FRAME_SIZE_EXPAND)
-               return 0;
-
-       return offset;
-}
-
-#if 0
-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   *noreg  = ia32_new_NoReg_gp(env->cg);
-       ir_node   *mem    = new_NoMem();
-       ir_node   *ptr    = get_irn_n(irn, 0);
-       ir_entity *ent    = be_get_frame_entity(irn);
-       ir_mode   *mode   = env->mode;
-
-//     /* If the StackParam has only one user ->     */
-//     /* put it in the Block where the user resides */
-//     if (get_irn_n_edges(node) == 1) {
-//             env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
-//     }
-
-       if (mode_is_float(mode)) {
-               if (USE_SSE2(env->cg))
-                       new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
-               else {
-                       env->cg->used_x87 = 1;
-                       new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
-               }
-       }
-       else {
-               new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
-       }
-
-       set_ia32_frame_ent(new_op, ent);
-       set_ia32_use_frame(new_op);
-
-       set_ia32_am_support(new_op, ia32_am_Source);
-       set_ia32_op_type(new_op, ia32_AddrModeS);
-       set_ia32_am_flavour(new_op, ia32_B);
-       set_ia32_ls_mode(new_op, mode);
-
-       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
-
-       return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
-}
-#endif
-
 /**
  * Transforms a FrameAddr into an ARM Add.
  */
-static ir_node *gen_be_FrameAddr(ir_node *node) {
+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);
-       dbg_info  *dbg    = get_irn_dbg_info(node);
-       ir_mode   *mode   = mode_Iu;
-       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(dbg, block, (unsigned)offset);
-       if (is_arm_Mov_i(cnst))
-               return new_bd_arm_Add_i(dbg, block, new_op, mode, get_arm_imm_value(cnst));
-       return new_bd_arm_Add(dbg, block, new_op, cnst, mode, ARM_SHF_NONE, 0);
+       ir_node   *fp     = be_get_FrameAddr_frame(node);
+       ir_node   *new_fp = be_transform_node(fp);
+       dbg_info  *dbgi   = get_irn_dbg_info(node);
+       ir_node   *new_node;
+
+       new_node = new_bd_arm_FrameAddr(dbgi, block, new_fp, ent);
+       return new_node;
 }
 
 /**
@@ -1303,10 +1220,6 @@ static ir_node *gen_Proj_Load(ir_node *node) {
        /* renumber the proj */
        switch (get_arm_irn_opcode(new_load)) {
        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_Ldr_res);
@@ -1363,24 +1276,24 @@ static ir_node *gen_Proj_Quot(ir_node *node) {
 
        switch (proj) {
        case pn_Quot_M:
-               if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
+               if (is_arm_fpaDvf(new_pred)) {
                        return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaDvf_M);
-               } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
+               } else if (is_arm_fpaRdf(new_pred)) {
                        return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaRdf_M);
-               } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
+               } else if (is_arm_fpaFdv(new_pred)) {
                        return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaFdv_M);
-               } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
+               } else if (is_arm_fpaFrd(new_pred)) {
                        return new_rd_Proj(dbgi, block, new_pred, mode_M, pn_arm_fpaFrd_M);
                }
                break;
        case pn_Quot_res:
-               if (is_arm_fpaDvf(new_pred) || is_arm_fpaDvf_i(new_pred)) {
+               if (is_arm_fpaDvf(new_pred)) {
                        return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaDvf_res);
-               } else if (is_arm_fpaRdf(new_pred) || is_arm_fpaRdf_i(new_pred)) {
+               } else if (is_arm_fpaRdf(new_pred)) {
                        return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaRdf_res);
-               } else if (is_arm_fpaFdv(new_pred) || is_arm_fpaFdv_i(new_pred)) {
+               } else if (is_arm_fpaFdv(new_pred)) {
                        return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaFdv_res);
-               } else if (is_arm_fpaFrd(new_pred) || is_arm_fpaFrd_i(new_pred)) {
+               } else if (is_arm_fpaFrd(new_pred)) {
                        return new_rd_Proj(dbgi, block, new_pred, mode, pn_arm_fpaFrd_res);
                }
                break;
@@ -1526,37 +1439,24 @@ static inline ir_node *create_const(ir_node **place,
        return res;
 }
 
-static ir_node *arm_new_Unknown_gp(void) {
-       return create_const(&env_cg->unknown_gp, new_bd_arm_Unknown_GP,
-                           &arm_gp_regs[REG_GP_UKNWN]);
-}
-
-static ir_node *arm_new_Unknown_fpa(void) {
-       return create_const(&env_cg->unknown_fpa, new_bd_arm_Unknown_FPA,
-                           &arm_fpa_regs[REG_FPA_UKNWN]);
-}
+static ir_node *gen_Unknown(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);
 
-/**
- * This function just sets the register for the Unknown node
- * as this is not done during register allocation because Unknown
- * is an "ignore" node.
- */
-static ir_node *gen_Unknown(ir_node *node) {
+       /* just produce a 0 */
        ir_mode *mode = get_irn_mode(node);
        if (mode_is_float(mode)) {
-               if (USE_FPA(env_cg->isa))
-                       return arm_new_Unknown_fpa();
-               else if (USE_VFP(env_cg->isa))
-                       panic("VFP not supported yet");
-               else
-                       panic("Softfloat not supported yet");
+               tarval *tv = get_mode_null(mode);
+               ir_node *node = new_bd_arm_fpaConst(dbgi, new_block, tv);
+               be_dep_on_frame(node);
+               return node;
        } else if (mode_needs_gp_reg(mode)) {
-               return arm_new_Unknown_gp();
-       } else {
-               assert(0 && "unsupported Unknown-Mode");
+               return create_const_graph_value(dbgi, new_block, 0);
        }
 
-       return NULL;
+       panic("Unexpected Unknown mode");
 }
 
 /**
@@ -1595,111 +1495,79 @@ static ir_node *gen_Phi(ir_node *node)
        return phi;
 }
 
-/*********************************************************
- *                  _             _      _
- *                 (_)           | |    (_)
- *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
- * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
- * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
- * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
- *
- *********************************************************/
-
 /**
  * the BAD transformer.
  */
-static ir_node *bad_transform(ir_node *irn) {
+static ir_node *bad_transform(ir_node *irn)
+{
        panic("ARM backend: Not implemented: %+F", irn);
-       return irn;
 }
 
 /**
  * Set a node emitter. Make it a bit more type safe.
  */
-static inline void set_transformer(ir_op *op, be_transform_func arm_transform_func) {
+static 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
  */
-static void arm_register_transformers(void) {
+static void arm_register_transformers(void)
+{
        /* first clear the generic function pointer for all ops */
        clear_irp_opcodes_generic_func();
 
-#define GEN(a)     set_transformer(op_##a, gen_##a)
-#define BAD(a)     set_transformer(op_##a, bad_transform)
-
-       GEN(Add);
-       GEN(Sub);
-       GEN(Mul);
-       BAD(Mulh);      /* unsupported yet */
-       GEN(And);
-       GEN(Or);
-       GEN(Eor);
-
-       GEN(Shl);
-       GEN(Shr);
-       GEN(Shrs);
-       GEN(Rotl);
-
-       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);
-       GEN(Jmp);
-
-       BAD(ASM);       /* unsupported yet */
-       GEN(CopyB);
-       BAD(Mux);       /* unsupported yet */
-       GEN(Proj);
-       GEN(Phi);
-
-       GEN(Const);
-       GEN(SymConst);
-
-       /* we should never see these nodes */
-       BAD(Raise);
-       BAD(Sel);
-       BAD(InstOf);
-       BAD(Cast);
-       BAD(Free);
-       BAD(Tuple);
-       BAD(Id);
-       //BAD(Bad);
-       BAD(Confirm);
-       BAD(Filter);
-       BAD(CallBegin);
-       BAD(EndReg);
-       BAD(EndExcept);
-
-       /* handle builtins */
-       BAD(Builtin);
-
-       /* handle generic backend nodes */
-       GEN(be_FrameAddr);
-       //GEN(be_Call);
-       //GEN(be_Return);
-       GEN(be_AddSP);
-       GEN(be_SubSP);
-       GEN(be_Copy);
-
-       /* set the register for all Unknown nodes */
-       GEN(Unknown);
-
-#undef GEN
-#undef BAD
+       set_transformer(op_Abs,          gen_Abs);
+       set_transformer(op_Add,          gen_Add);
+       set_transformer(op_And,          gen_And);
+       set_transformer(op_be_AddSP,     gen_be_AddSP);
+       set_transformer(op_be_Call,      gen_be_Call);
+       set_transformer(op_be_Copy,      gen_be_Copy);
+       set_transformer(op_be_FrameAddr, gen_be_FrameAddr);
+       set_transformer(op_be_SubSP,     gen_be_SubSP);
+       set_transformer(op_Cmp,          gen_Cmp);
+       set_transformer(op_Cond,         gen_Cond);
+       set_transformer(op_Const,        gen_Const);
+       set_transformer(op_Conv,         gen_Conv);
+       set_transformer(op_CopyB,        gen_CopyB);
+       set_transformer(op_Eor,          gen_Eor);
+       set_transformer(op_Jmp,          gen_Jmp);
+       set_transformer(op_Load,         gen_Load);
+       set_transformer(op_Minus,        gen_Minus);
+       set_transformer(op_Mul,          gen_Mul);
+       set_transformer(op_Not,          gen_Not);
+       set_transformer(op_Or,           gen_Or);
+       set_transformer(op_Phi,          gen_Phi);
+       set_transformer(op_Proj,         gen_Proj);
+       set_transformer(op_Quot,         gen_Quot);
+       set_transformer(op_Rotl,         gen_Rotl);
+       set_transformer(op_Shl,          gen_Shl);
+       set_transformer(op_Shr,          gen_Shr);
+       set_transformer(op_Shrs,         gen_Shrs);
+       set_transformer(op_Store,        gen_Store);
+       set_transformer(op_Sub,          gen_Sub);
+       set_transformer(op_SymConst,     gen_SymConst);
+       set_transformer(op_Unknown,      gen_Unknown);
+
+       set_transformer(op_ASM,       bad_transform);
+       set_transformer(op_Builtin,   bad_transform);
+       set_transformer(op_CallBegin, bad_transform);
+       set_transformer(op_Cast,      bad_transform);
+       set_transformer(op_Confirm,   bad_transform);
+       set_transformer(op_DivMod,    bad_transform);
+       set_transformer(op_EndExcept, bad_transform);
+       set_transformer(op_EndReg,    bad_transform);
+       set_transformer(op_Filter,    bad_transform);
+       set_transformer(op_Free,      bad_transform);
+       set_transformer(op_Id,        bad_transform);
+       set_transformer(op_InstOf,    bad_transform);
+       set_transformer(op_Mulh,      bad_transform);
+       set_transformer(op_Mux,       bad_transform);
+       set_transformer(op_Raise,     bad_transform);
+       set_transformer(op_Sel,       bad_transform);
+       set_transformer(op_Tuple,     bad_transform);
 }
 
 /**
@@ -1716,7 +1584,8 @@ static void arm_pretransform_node(void)
 /**
  * Initialize fpa Immediate support.
  */
-static void arm_init_fpa_immediate(void) {
+static void arm_init_fpa_immediate(void)
+{
        /* 0, 1, 2, 3, 4, 5, 10, or 0.5. */
        fpa_imm[0][fpa_null]  = get_tarval_null(mode_F);
        fpa_imm[0][fpa_one]   = get_tarval_one(mode_F);
@@ -1749,7 +1618,8 @@ static void arm_init_fpa_immediate(void) {
 /**
  * Transform a Firm graph into an ARM graph.
  */
-void arm_transform_graph(arm_code_gen_t *cg) {
+void arm_transform_graph(arm_code_gen_t *cg)
+{
        static int imm_initialized = 0;
 
        if (! imm_initialized) {
@@ -1761,6 +1631,7 @@ void arm_transform_graph(arm_code_gen_t *cg) {
        be_transform_graph(cg->birg, arm_pretransform_node);
 }
 
-void arm_init_transform(void) {
-       // FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
+void arm_init_transform(void)
+{
+       FIRM_DBG_REGISTER(dbg, "firm.be.arm.transform");
 }
index 1add634..fcc5104 100644 (file)
@@ -20,7 +20,7 @@
 /**
  * @file
  * @brief   The main arm backend driver file.
- * @author  Oliver Richter, Tobias Gneist
+ * @author  Matthias Braun, Oliver Richter, Tobias Gneist
  * @version $Id$
  */
 #include "config.h"
@@ -44,7 +44,7 @@
 #include "array_t.h"
 #include "irtools.h"
 
-#include "../bearch.h"                /* the general register allocator interface */
+#include "../bearch.h"
 #include "../benode.h"
 #include "../belower.h"
 #include "../besched.h"
 #include "../bespillslots.h"
 #include "../begnuas.h"
 #include "../belistsched.h"
+#include "../beflags.h"
 
 #include "bearch_arm_t.h"
 
-#include "arm_new_nodes.h"           /* arm nodes interface */
-#include "gen_arm_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
+#include "arm_new_nodes.h"
+#include "gen_arm_regalloc_if.h"
 #include "arm_transform.h"
 #include "arm_optimize.h"
 #include "arm_emitter.h"
 #include "arm_map_regs.h"
 
-#define DEBUG_MODULE "firm.be.arm.isa"
-
-/* TODO: ugly, but we need it to get access to the registers assigned to Phi nodes */
-static set *cur_reg_set = NULL;
-
-/**************************************************
- *                         _ _              _  __
- *                        | | |            (_)/ _|
- *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
- * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
- * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
- * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
- *            __/ |
- *           |___/
- **************************************************/
-
 static arch_irn_class_t arm_classify(const ir_node *irn)
 {
        (void) irn;
        return 0;
 }
 
-static ir_entity *arm_get_frame_entity(const ir_node *irn) {
-       /* we do NOT transform be_Spill or be_Reload nodes, so we never
-          have frame access using ARM nodes. */
-       (void) irn;
+static ir_entity *arm_get_frame_entity(const ir_node *irn)
+{
+       const arm_attr_t *attr = get_arm_attr_const(irn);
+
+       if (is_arm_FrameAddr(irn)) {
+               const arm_SymConst_attr_t *attr = get_irn_generic_attr_const(irn);
+               return attr->entity;
+       }
+       if (attr->is_load_store) {
+               const arm_load_store_attr_t *load_store_attr
+                       = get_arm_load_store_attr_const(irn);
+               if (load_store_attr->is_frame_entity) {
+                       return load_store_attr->entity;
+               }
+       }
        return NULL;
 }
 
-static void arm_set_frame_entity(ir_node *irn, ir_entity *ent) {
+static void arm_set_frame_entity(ir_node *irn, ir_entity *ent)
+{
        (void) irn;
        (void) ent;
        panic("arm_set_frame_entity() called. This should not happen.");
@@ -108,13 +105,20 @@ static void arm_set_frame_entity(ir_node *irn, ir_entity *ent) {
  */
 static void arm_set_stack_bias(ir_node *irn, int bias)
 {
-       (void) irn;
-       (void) bias;
-       /* TODO: correct offset if irn accesses the stack */
+       if (is_arm_FrameAddr(irn)) {
+               arm_SymConst_attr_t *attr = get_irn_generic_attr(irn);
+               attr->fp_offset += bias;
+       } else {
+               arm_load_store_attr_t *attr = get_arm_load_store_attr(irn);
+               assert(attr->base.is_load_store);
+               attr->offset += bias;
+       }
 }
 
 static int arm_get_sp_bias(const ir_node *irn)
 {
+       /* We don't have any nodes changing the stack pointer.
+               TODO: we probably want to support post-/pre increment/decrement later */
        (void) irn;
        return 0;
 }
@@ -134,17 +138,6 @@ static const arch_irn_ops_t arm_irn_ops = {
        NULL,    /* perform_memory_operand  */
 };
 
-/**************************************************
- *                _                         _  __
- *               | |                       (_)/ _|
- *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
- *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
- * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
- *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
- *                        __/ |
- *                       |___/
- **************************************************/
-
 /**
  * Transforms the standard Firm graph into
  * a ARM firm graph.
@@ -179,14 +172,30 @@ static void arm_finish_irg(void *self)
        arm_peephole_optimization(cg);
 }
 
+static ir_node *arm_flags_remat(ir_node *node, ir_node *after)
+{
+       ir_node *block;
+       ir_node *copy;
+
+       if (is_Block(after)) {
+               block = after;
+       } else {
+               block = get_nodes_block(after);
+       }
+       copy = exact_copy(node);
+       set_nodes_block(copy, block);
+       sched_add_after(after, copy);
+       return copy;
+}
 
 static void arm_before_ra(void *self)
 {
-       (void) self;
-       /* Some stuff you need to do immediately after register allocation */
+       arm_code_gen_t *cg = self;
+
+       be_sched_fix_flags(cg->birg, &arm_reg_classes[CLASS_arm_flags],
+                          &arm_flags_remat);
 }
 
-#if 0
 static void transform_Reload(ir_node *node)
 {
        ir_graph  *irg    = get_irn_irg(node);
@@ -194,15 +203,50 @@ static void transform_Reload(ir_node *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_mode   *mode   = get_irn_mode(node);
        ir_entity *entity = be_get_frame_entity(node);
+       const arch_register_t *reg;
+       ir_node   *proj;
        ir_node   *load;
 
        ir_node  *sched_point = sched_prev(node);
 
-       load = new_bd_arm_Ldr(dbgi, block, ptr, mem, entity, false, 0);
+       load = new_bd_arm_Ldr(dbgi, block, ptr, mem, mode, entity, false, 0, true);
+       sched_add_after(sched_point, load);
+       sched_remove(node);
+
+       proj = new_rd_Proj(dbgi, block, load, mode, pn_arm_Ldr_res);
+
+       reg = arch_get_irn_register(node);
+       arch_set_irn_register(proj, reg);
+
+       exchange(node, proj);
+}
+
+static void transform_Spill(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    = new_NoMem();
+       ir_node   *val    = get_irn_n(node, be_pos_Spill_val);
+       ir_mode   *mode   = get_irn_mode(val);
+       ir_entity *entity = be_get_frame_entity(node);
+       ir_node   *sched_point;
+       ir_node   *store;
+
+       sched_point = sched_prev(node);
+       store = new_bd_arm_Str(dbgi, block, ptr, val, mem, mode, entity, false, 0,
+                              true);
+
+       sched_remove(node);
+       sched_add_after(sched_point, store);
+
+       exchange(node, store);
 }
 
-static void after_ra_walker(ir_node *block, void *data)
+static void arm_after_ra_walker(ir_node *block, void *data)
 {
        ir_node *node, *prev;
        (void) data;
@@ -214,17 +258,16 @@ static void after_ra_walker(ir_node *block, void *data)
                        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;
        be_coalesce_spillslots(cg->birg);
+
+       irg_block_walk_graph(cg->irg, NULL, arm_after_ra_walker, NULL);
 }
 
 /**
@@ -237,8 +280,6 @@ static void arm_emit_and_done(void *self) {
 
        arm_gen_routine(cg, irg);
 
-       cur_reg_set = NULL;
-
        /* de-allocate code generator */
        del_set(cg->reg_set);
        free(self);
@@ -253,7 +294,8 @@ static void arm_emit_and_done(void *self) {
  * 2.) A load: simply split into two
  */
 static ir_node *convert_dbl_to_int(ir_node *bl, ir_node *arg, ir_node *mem,
-                                   ir_node **resH, ir_node **resL) {
+                                   ir_node **resH, ir_node **resL)
+{
        if (is_Const(arg)) {
                tarval *tv = get_Const_tarval(arg);
                unsigned v;
@@ -480,8 +522,6 @@ static void *arm_cg_init(be_irg_t *birg) {
 
        FIRM_DBG_REGISTER(cg->mod, "firm.be.arm.cg");
 
-       cur_reg_set = cg->reg_set;
-
        /* enter the current code generator */
        isa->cg = cg;
 
@@ -731,23 +771,14 @@ const arch_register_class_t *arm_get_reg_class_for_mode(const ir_mode *mode) {
  * it will contain the return address and space to store the old base pointer.
  * @return The Firm type modeling the ABI between type.
  */
-static ir_type *arm_get_between_type(void *self) {
+static ir_type *arm_get_between_type(void *self)
+{
        static ir_type *between_type = NULL;
-       static ir_entity *old_bp_ent = NULL;
        (void) self;
 
        if (between_type == NULL) {
-               ir_entity *ret_addr_ent;
-               ir_type *ret_addr_type = new_type_primitive(new_id_from_str("return_addr"), mode_P);
-               ir_type *old_bp_type   = new_type_primitive(new_id_from_str("bp"), mode_P);
-
-               between_type           = new_type_class(new_id_from_str("arm_between_type"));
-               old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
-               ret_addr_ent           = new_entity(between_type, new_id_from_str("old_bp"), ret_addr_type);
-
-               set_entity_offset(old_bp_ent, 0);
-               set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
-               set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
+               between_type = new_type_class(new_id_from_str("arm_between_type"));
+               set_type_size_bytes(between_type, 0);
        }
 
        return between_type;
@@ -823,7 +854,7 @@ static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap *
        *mem = new_r_Proj(block, store, mode_M, pn_arm_StoreStackM4Inc_M);
 
        /* frame pointer is ip-4 (because ip is our old sp value) */
-       fp = new_bd_arm_Sub_i(NULL, block, ip, get_irn_mode(fp), 4);
+       fp = new_bd_arm_Sub_imm(NULL, block, ip, 4, 0);
        arch_set_irn_register(fp, env->arch_env->bp);
 
        /* beware: we change the fp but the StoreStackM4Inc above wants the old
@@ -895,7 +926,8 @@ static const be_abi_callbacks_t arm_abi_callbacks = {
  * @param method_type The type of the method (procedure) in question.
  * @param abi         The abi object to be modified
  */
-void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
+void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi)
+{
        ir_type  *tp;
        ir_mode  *mode;
        int       i;
@@ -956,7 +988,8 @@ void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi
        }
 }
 
-int arm_to_appear_in_schedule(void *block_env, const ir_node *irn) {
+int arm_to_appear_in_schedule(void *block_env, const ir_node *irn)
+{
        (void) block_env;
        if(!is_arm_irn(irn))
                return -1;
@@ -967,7 +1000,8 @@ int arm_to_appear_in_schedule(void *block_env, const ir_node *irn) {
 /**
  * Initializes the code generator interface.
  */
-static const arch_code_generator_if_t *arm_get_code_generator_if(void *self) {
+static const arch_code_generator_if_t *arm_get_code_generator_if(void *self)
+{
        (void) self;
        return &arm_code_gen_if;
 }
@@ -977,7 +1011,8 @@ list_sched_selector_t arm_sched_selector;
 /**
  * Returns the reg_pressure scheduler with to_appear_in_schedule() over\loaded
  */
-static const list_sched_selector_t *arm_get_list_sched_selector(const void *self, list_sched_selector_t *selector) {
+static const list_sched_selector_t *arm_get_list_sched_selector(const void *self, list_sched_selector_t *selector)
+{
        (void) self;
        memcpy(&arm_sched_selector, selector, sizeof(arm_sched_selector));
        /* arm_sched_selector.exectime              = arm_sched_exectime; */
index 00dee8f..b2cf09a 100644 (file)
@@ -329,7 +329,12 @@ static int stack_frame_compute_initial_offset(be_stack_layout_t *frame)
        ir_type  *base = frame->stack_dir < 0 ? frame->between_type : frame->frame_type;
        ir_entity *ent = search_ent_with_offset(base, 0);
 
-       frame->initial_offset = ent ? get_stack_entity_offset(frame, ent, 0) : 0;
+       if (ent == NULL) {
+               frame->initial_offset
+                       = frame->stack_dir < 0 ? get_type_size_bytes(frame->frame_type) : get_type_size_bytes(frame->between_type);
+       } else {
+               frame->initial_offset = get_stack_entity_offset(frame, ent, 0);
+       }
 
        return frame->initial_offset;
 }
index a4cf30b..0a3871a 100644 (file)
@@ -173,8 +173,10 @@ static void rematerialize_or_move(ir_node *flags_needed, ir_node *node,
                        get_nodes_block(node) != get_nodes_block(flags_needed)) {
                int i;
 
-               for (i = get_irn_arity(copy) - 1; i >= 0; --i) {
-                       be_liveness_update(lv, get_irn_n(copy, i));
+               if (lv != NULL) {
+                       for (i = get_irn_arity(copy) - 1; i >= 0; --i) {
+                               be_liveness_update(lv, get_irn_n(copy, i));
+                       }
                }
        }
 }
index 14c9b1b..6265111 100644 (file)
@@ -569,7 +569,8 @@ static void assign_spill_entity(ir_node *node, ir_entity *entity)
                return;
        }
 
-       /* beware: we might have Stores with Memory Proj's, ia32 fisttp for instance */
+       /* beware: we might have Stores with Memory Proj's, ia32 fisttp for
+          instance */
        node = skip_Proj(node);
        assert(arch_get_frame_entity(node) == NULL);
        arch_set_frame_entity(node, entity);
index 3d8d34c..6235db6 100644 (file)
@@ -2239,8 +2239,8 @@ static const lc_opt_table_entry_t ia32_emitter_options[] = {
 /* ==== Experimental binary emitter ==== */
 
 static unsigned char reg_gp_map[N_ia32_gp_REGS];
-static unsigned char reg_mmx_map[N_ia32_mmx_REGS];
-static unsigned char reg_sse_map[N_ia32_xmm_REGS];
+//static unsigned char reg_mmx_map[N_ia32_mmx_REGS];
+//static unsigned char reg_sse_map[N_ia32_xmm_REGS];
 static unsigned char pnc_map_signed[8];
 static unsigned char pnc_map_unsigned[8];
 
diff --git a/ir/be/ia32/ia32_simd_spec.pl b/ir/be/ia32/ia32_simd_spec.pl
deleted file mode 100644 (file)
index 07778a2..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is generated! Do not edit, your changes will be lost!
-#  ___ _____  _____                  _                               _
-# / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___
-# \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|
-#  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \
-# |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/
-
-$nodes{"mov_gp_variant0"} = {
-  reg_req => { "in" => [ "xmm", ], "out" => [ "gp", ] },
-  emit    => ". shl %S2, 15; .movd %S1, %S2",
-  latency => 3,
-};
index 4cad362..5c0ba3f 100644 (file)
@@ -33,7 +33,6 @@ $arch = "ia32";
 #   emit      => "emit code with templates",
 #   attr      => "additional attribute arguments for constructor",
 #   init_attr => "emit attribute initialization template",
-#   rd_constructor => "c source code which constructs an ir_node",
 #   hash_func => "name of the hash function for this operation",
 #   latency   => "latency of this operation (can be float)"
 #   attr_type => "name of the attribute struct",
@@ -225,25 +224,18 @@ $arch = "ia32";
        CMP3  => "${arch}_emit_cmp_suffix_node(node, 3);",
 );
 
-#--------------------------------------------------#
-#                        _                         #
-#                       (_)                        #
-#  _ __   _____      __  _ _ __    ___  _ __  ___  #
-# | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
-# | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
-# |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
-#                                      | |         #
-#                                      |_|         #
-#--------------------------------------------------#
+
+
 
 $default_op_attr_type = "ia32_op_attr_t";
 $default_attr_type    = "ia32_attr_t";
 $default_copy_attr    = "ia32_copy_attr";
 
 sub ia32_custom_init_attr {
-       my $node = shift;
-       my $name = shift;
-       my $res = "";
+       my $constr = shift;
+       my $node   = shift;
+       my $name   = shift;
+       my $res    = "";
 
        if(defined($node->{modified_flags})) {
                $res .= "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n";
@@ -357,19 +349,6 @@ ProduceVal => {
        cmp_attr  => "return 1;",
 },
 
-#-----------------------------------------------------------------#
-#  _       _                                         _            #
-# (_)     | |                                       | |           #
-#  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
-# | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
-# | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
-# |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
-#                   __/ |                                         #
-#                  |___/                                          #
-#-----------------------------------------------------------------#
-
-# commutative operations
-
 Add => {
        irn_flags => "R",
        state     => "exc_pinned",
@@ -506,7 +485,6 @@ And => {
                           out => [ "in_r4 in_r5", "flags", "none" ] },
        ins       => [ "base", "index", "mem", "left", "right" ],
        outs      => [ "res", "flags", "M" ],
-       op_modes  => "commutative | am | immediate | mode_neutral",
        am        => "source,binary",
        emit      => '. and%M %binop',
        units     => [ "GP" ],
@@ -629,8 +607,6 @@ XorMem8Bit => {
        modified_flags => $status_flags
 },
 
-# not commutative operations
-
 Sub => {
        irn_flags => "R",
        state     => "exc_pinned",
@@ -914,8 +890,6 @@ RolMem => {
        modified_flags => $status_flags
 },
 
-# unary operations
-
 Neg => {
        irn_flags => "R",
        reg_req   => { in => [ "gp" ],
@@ -1027,8 +1001,8 @@ NotMem => {
 },
 
 Cmc => {
-       reg_req => { in => [ "flags" ], out => [ "flags" ] },
-       emit    => '.cmc',
+       reg_req   => { in => [ "flags" ], out => [ "flags" ] },
+       emit      => '.cmc',
        units     => [ "GP" ],
        latency   => 1,
        mode      => $mode_flags,
@@ -1036,16 +1010,14 @@ Cmc => {
 },
 
 Stc => {
-       reg_req => { out => [ "flags" ] },
-       emit    => '.stc',
+       reg_req   => { out => [ "flags" ] },
+       emit      => '.stc',
        units     => [ "GP" ],
        latency   => 1,
        mode      => $mode_flags,
        modified_flags => $status_flags
 },
 
-# other operations
-
 Cmp => {
        irn_flags => "R",
        state     => "exc_pinned",
@@ -1752,15 +1724,6 @@ PrefetchW => {
        units     => [ "GP" ],
 },
 
-#-----------------------------------------------------------------------------#
-#   _____ _____ ______    __ _             _                     _            #
-#  / ____/ ____|  ____|  / _| |           | |                   | |           #
-# | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
-#  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
-#  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
-# |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
-#-----------------------------------------------------------------------------#
-
 # produces a 0/+0.0
 xZero => {
        irn_flags => "R",
@@ -1830,8 +1793,6 @@ xMovd  => {
        mode      => $mode_xmm
 },
 
-# commutative operations
-
 xAdd => {
        irn_flags => "R",
        state     => "exc_pinned",
@@ -1930,8 +1891,6 @@ xXor => {
        mode      => $mode_xmm
 },
 
-# not commutative operations
-
 xAndNot => {
        irn_flags => "R",
        state     => "exc_pinned",
@@ -1973,8 +1932,6 @@ xDiv => {
        units     => [ "SSE" ],
 },
 
-# other operations
-
 Ucomi => {
        irn_flags => "R",
        state     => "exc_pinned",
@@ -1992,8 +1949,6 @@ Ucomi => {
        modified_flags => 1,
 },
 
-# Load / Store
-
 xLoad => {
        op_flags  => "L|F",
        state     => "exc_pinned",
@@ -2072,8 +2027,6 @@ l_FloattoLL => {
        reg_req  => { in => [ "none" ], out => [ "none", "none" ] }
 },
 
-# CopyB
-
 CopyB => {
        op_flags  => "F|H",
        state     => "pinned",
@@ -2100,8 +2053,6 @@ CopyB_i => {
 #      modified_flags => [ "DF" ]
 },
 
-# Conversions
-
 Cwtl => {
        state     => "exc_pinned",
        reg_req   => { in => [ "eax" ], out => [ "eax" ] },
@@ -2171,20 +2122,6 @@ Conv_FP2FP => {
        mode      => $mode_xmm,
 },
 
-#----------------------------------------------------------#
-#        _      _               _    __ _             _    #
-#       (_)    | |             | |  / _| |           | |   #
-# __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
-# \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
-#  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
-#   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
-#                 | |                                      #
-#  _ __   ___   __| | ___  ___                             #
-# | '_ \ / _ \ / _` |/ _ \/ __|                            #
-# | | | | (_) | (_| |  __/\__ \                            #
-# |_| |_|\___/ \__,_|\___||___/                            #
-#----------------------------------------------------------#
-
 # rematerialisation disabled for all float nodes for now, because the fpcw
 # handler runs before spilling and we might end up with wrong fpcw then
 
@@ -2264,8 +2201,6 @@ vfchs => {
        attr_type => "ia32_x87_attr_t",
 },
 
-# virtual Load and Store
-
 vfld => {
        irn_flags => "R",
        op_flags  => "L|F",
@@ -2297,8 +2232,6 @@ vfst => {
        attr_type => "ia32_x87_attr_t",
 },
 
-# Conversions
-
 vfild => {
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ],
@@ -2332,9 +2265,6 @@ vfisttp => {
        attr_type => "ia32_x87_attr_t",
 },
 
-
-# constants
-
 vfldz => {
        irn_flags => "R",
        reg_req   => { out => [ "vfp" ] },
@@ -2405,10 +2335,8 @@ vfldl2e => {
        attr_type => "ia32_x87_attr_t",
 },
 
-# other
-
 vFucomFnstsw => {
-# we can't allow to rematerialize this node so we don't have
+# we can't allow to rematerialize this node so we don't
 #  accidently produce Phi(Fucom, Fucom(ins_permuted))
 #      irn_flags => "R",
        reg_req   => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
@@ -2459,245 +2387,208 @@ Sahf => {
        mode      => $mode_flags,
 },
 
-#------------------------------------------------------------------------#
-#       ___ _____    __ _             _                     _            #
-# __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
-# \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
-#  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
-# /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
-#------------------------------------------------------------------------#
-
-# Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
-#       are swapped, we work this around in the emitter...
-
 fadd => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fadd%XM %x87_binop',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 faddp => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. faddp%XM %x87_binop',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fmul => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fmul%XM %x87_binop',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fmulp => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fmulp%XM %x87_binop',,
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fsub => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fsub%XM %x87_binop',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
+# Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
+#       are swapped, we work this around in the emitter...
+
 fsubp => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
 # see note about gas bugs
        emit      => '. fsubrp%XM %x87_binop',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fsubr => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
        irn_flags => "R",
-       reg_req   => { },
        emit      => '. fsubr%XM %x87_binop',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fsubrp => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
        irn_flags => "R",
-       reg_req   => { },
-# see note about gas bugs
+# see note about gas bugs before fsubp
        emit      => '. fsubp%XM %x87_binop',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fprem => {
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fprem1',
        latency   => 20,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 # this node is just here, to keep the simulator running
 # we can omit this when a fprem simulation function exists
 fpremp => {
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fprem1\n'.
                     '. fstp %X0',
        latency   => 20,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fdiv => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fdiv%XM %x87_binop',
        latency   => 20,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fdivp => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
-# see note about gas bugs
+# see note about gas bugs before fsubp
        emit      => '. fdivrp%XM %x87_binop',
        latency   => 20,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fdivr => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fdivr%XM %x87_binop',
        latency   => 20,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fdivrp => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
-# see note about gas bugs
+# see note about gas bugs before fsubp
        emit      => '. fdivp%XM %x87_binop',
        latency   => 20,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fabs => {
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fabs',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
 fchs => {
        op_flags  => "R|K",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fchs',
        latency   => 4,
        attr_type => "ia32_x87_attr_t",
+       constructors => {},
 },
 
-# x87 Load and Store
-
 fld => {
-       rd_constructor => "NONE",
        op_flags  => "R|L|F",
        state     => "exc_pinned",
-       reg_req   => { },
        emit      => '. fld%XM %AM',
        attr_type => "ia32_x87_attr_t",
        latency   => 2,
+       constructors => {},
 },
 
 fst => {
-       rd_constructor => "NONE",
        op_flags  => "R|L|F",
        state     => "exc_pinned",
-       reg_req   => { },
        emit      => '. fst%XM %AM',
        mode      => "mode_M",
        attr_type => "ia32_x87_attr_t",
        latency   => 2,
+       constructors => {},
 },
 
 fstp => {
-       rd_constructor => "NONE",
        op_flags  => "R|L|F",
        state     => "exc_pinned",
-       reg_req   => { },
        emit      => '. fstp%XM %AM',
        mode      => "mode_M",
        attr_type => "ia32_x87_attr_t",
        latency   => 2,
+       constructors => {},
 },
 
-# Conversions
-
 fild => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fild%XM %AM',
        attr_type => "ia32_x87_attr_t",
        latency   => 2,
+       constructors => {},
 },
 
 fist => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fist%XM %AM',
        mode      => "mode_M",
        attr_type => "ia32_x87_attr_t",
        latency   => 2,
+       constructors => {},
 },
 
 fistp => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fistp%XM %AM',
        mode      => "mode_M",
        attr_type => "ia32_x87_attr_t",
        latency   => 2,
+       constructors => {},
 },
 
 # SSE3 fisttp instruction
 fisttp => {
        state     => "exc_pinned",
-       rd_constructor => "NONE",
-       reg_req   => { },
        emit      => '. fisttp%XM %AM',
        mode      => "mode_M",
        attr_type => "ia32_x87_attr_t",
        latency   => 2,
+       constructors => {},
 },
 
-# constants
-
 fldz => {
        op_flags  => "R|c|K",
        irn_flags => "R",
@@ -2833,8 +2724,6 @@ femms => {
        latency   => 3,
 },
 
-# compare
-
 FucomFnstsw => {
        reg_req   => { },
        emit      => ". fucom %X1\n".
@@ -2881,17 +2770,6 @@ FtstFnstsw => {
        latency   => 2,
 },
 
-
-# -------------------------------------------------------------------------------- #
-#  ____ ____  _____                  _                               _             #
-# / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___   #
-# \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|  #
-#  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \  #
-# |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/  #
-#                                                                                  #
-# -------------------------------------------------------------------------------- #
-
-
 # Spilling and reloading of SSE registers, hardcoded, not generated #
 
 xxLoad => {
@@ -2917,14 +2795,6 @@ xxStore => {
 
 ); # end of %nodes
 
-# Include the generated SIMD node specification written by the SIMD optimization
-$my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
-unless ($return = do $my_script_name) {
-       warn "couldn't parse $my_script_name: $@" if $@;
-       warn "couldn't do $my_script_name: $!"    unless defined $return;
-       warn "couldn't run $my_script_name"       unless $return;
-}
-
 # Transform some attributes
 foreach my $op (keys(%nodes)) {
        my $node         = $nodes{$op};
index f5d7d7d..9d1c7f2 100644 (file)
@@ -1,6 +1,5 @@
 # Creation: 2006/02/13
 # $Id$
-# This is a template specification for the Firm-Backend
 
 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
 
index 6f90015..c520fd0 100644 (file)
@@ -1,6 +1,5 @@
 # Creation: 2006/02/13
 # $Id$
-# This is a template specification for the Firm-Backend
 
 # the cpu architecture (ia32, ia64, mips, sparc, ppc32, ...)
 
index 0ea1282..7c1e4c9 100755 (executable)
@@ -114,13 +114,13 @@ my @obst_limit_func;
 my @obst_reg_reqs;
 my @obst_opvar;       # stack for the "ir_op *op_<arch>_<op-name> = NULL;" statements
 my @obst_get_opvar;   # stack for the get_op_<arch>_<op-name>() functions
-my @obst_constructor; # stack for node constructor functions
+my $obst_constructor; # stack for node constructor functions
 my @obst_new_irop;    # stack for the new_ir_op calls
 my @obst_enum_op;     # stack for creating the <arch>_opcode enum
-my @obst_header;      # stack for function prototypes
+my $obst_header;      # stack for function prototypes
 my @obst_is_archirn;  # stack for the is_$arch_irn() function
 my @obst_cmp_attr;    # stack for the compare attribute functions
-my @obst_proj;        # stack for the pn_ numbers
+my $obst_proj = "";   # stack for the pn_ numbers
 my $orig_op;
 my $arity;
 my $cmp_attr_func;
@@ -158,9 +158,317 @@ foreach my $class_name (keys(%reg_classes)) {
 # for registering additional opcodes
 $n_opcodes += $additional_opcodes if (defined($additional_opcodes));
 
-push(@obst_header, "void ".$arch."_create_opcodes(const arch_irn_ops_t *be_ops);\n");
+$obst_header .= "void ${arch}_create_opcodes(const arch_irn_ops_t *be_ops);\n";
 
-push(@obst_enum_op, "typedef enum _$arch\_opcodes {\n");
+sub create_constructor {
+       my $op   = shift;
+       my $name = shift;
+       my $n    = shift;
+       my $on   = shift;
+       my $known_mode;
+
+       my $suffix = "";
+       if ($name ne "") {
+               $suffix = "_${name}";
+       }
+
+       # determine mode
+       if (exists($n->{mode})) {
+               $known_mode = $n->{mode};
+       }
+
+       # determine arity
+       my $arity = 0;
+       if(exists($n->{"arity"})) {
+               $arity = $n->{"arity"};
+       } elsif (exists($n->{"reg_req"}) && exists($n->{"reg_req"}{"in"})) {
+               $arity = scalar(@{ $n->{"reg_req"}{"in"} });
+       } elsif (exists($n->{"ins"})) {
+               $arity = scalar(@{ $n->{"ins"} });
+       }
+       if($arity eq "variable") {
+               $arity = $ARITY_VARIABLE;
+       } elsif($arity eq "dynamic") {
+               $arity = $ARITY_DYNAMIC;
+       }
+
+       # determine out arity
+       my $out_arity = 0;
+       if(exists($n->{"out_arity"})) {
+               $out_arity = $n->{"out_arity"};
+       } elsif (exists($n->{"reg_req"}) && exists($n->{"reg_req"}{"out"})) {
+               $out_arity = scalar(@{ $n->{"reg_req"}{"out"} });
+       } elsif (exists($n->{"outs"})) {
+               $out_arity = scalar(@{ $n->{"outs"} });
+       }
+       if($out_arity eq "variable") {
+               $out_arity = $ARITY_VARIABLE;
+       } elsif($out_arity eq "dynamic") {
+               $out_arity = $ARITY_DYNAMIC;
+       }
+
+
+       my $comment = $n->{"comment"};
+       if(!exists($n->{"comment"})) {
+               $comment = "construct ${orig_op} node";
+       }
+       $comment =
+               "/**\n".
+               " * ${comment}\n".
+               " */\n";
+
+       $obst_constructor .= $comment;
+
+       # create constructor head
+       my $complete_args = "";
+       $temp             = "";
+
+       $temp = "ir_node *new_bd_${arch}_${op}${suffix}(dbg_info *dbgi, ir_node *block";
+       if (!exists($n->{"args"})) { # default args
+               if ($arity == $ARITY_VARIABLE) {
+                       $complete_args = ", int arity, ir_node *in[]";
+               } elsif ($arity == $ARITY_DYNAMIC) {
+                       $complete_args = "";
+               } else {
+                       for (my $i = 0; $i < $arity; $i++) {
+                               my $opname = "op${i}";
+                               if (exists($n->{"ins"})) {
+                                       my @ins = @{ $n->{"ins"} };
+                                       $opname = $ins[$i];
+                               }
+
+                               $complete_args .= ", ir_node *${opname}";
+                       }
+               }
+               if ($out_arity == $ARITY_VARIABLE) {
+                       $complete_args .= ", int n_res";
+               }
+
+               if (!defined($known_mode)) {
+                       $complete_args .= ", ir_mode *mode";
+               }
+       } else { # user defined args
+               for my $href (@{ $n->{"args"} }) {
+                       $href->{"type"} .= " " if ($href->{"type"} !~ / [*]?$/); # put a space between name and type if there is none at the end
+                       $complete_args  .= ", ".$href->{"type"}.$href->{"name"};
+               }
+       }
+
+       # we have additional attribute arguements
+       if (exists($n->{"attr"})) {
+               $complete_args .= ", ".$n->{"attr"};
+       }
+
+       $temp .= "$complete_args)";
+       $obst_constructor .= "${temp}\n{\n";
+
+       $obst_header .= $comment;
+       $obst_header .= "${temp};\n";
+
+       # emit constructor code
+       $temp = <<EOF;
+       ir_node        *res;
+       ir_op          *op      = op_${arch}_${op};
+       int             flags   = 0;
+       backend_info_t *info;
+EOF
+
+       if($arity == $ARITY_DYNAMIC) {
+               $temp .= <<EOF;
+       int             arity   = -1;
+       ir_node       **in      = NULL;
+EOF
+       } elsif($arity == $ARITY_VARIABLE) {
+       } else {
+               $temp .= <<EOF;
+       int             arity   = $arity;
+EOF
+               if($arity > 0) {
+                       $temp .= <<EOF;
+       ir_node        *in[$arity];
+EOF
+               } else {
+                       $temp .= <<EOF;
+       ir_node       **in      = NULL;
+EOF
+               }
+       }
+       if($out_arity == $ARITY_DYNAMIC) {
+               $temp .= <<EOF;
+       int             n_res   = -1;
+EOF
+       } elsif($out_arity == $ARITY_VARIABLE) {
+       } else {
+               $temp .= <<EOF;
+       int             n_res   = ${out_arity};
+EOF
+       }
+
+       if (defined($known_mode)) {
+               $temp .= <<EOF;
+       ir_mode        *mode    = ${known_mode};
+EOF
+       }
+
+       # set up static variables for cpu execution unit assigments
+       if (exists($n->{"units"})) {
+               $temp .= gen_execunit_list_initializer($n->{"units"});
+       } else {
+               $temp .= <<EOF;
+       static const be_execution_unit_t ***exec_units = NULL;
+EOF
+       }
+
+       undef my $in_req_var;
+       undef my $out_req_var;
+
+       my $set_out_reqs = "";
+
+       # set up static variables for requirements and registers
+       if (exists($n->{"reg_req"})) {
+               my %req = %{ $n->{"reg_req"} };
+               my $idx;
+
+               undef my @in;
+               @in = @{ $req{"in"} } if (exists($req{"in"}));
+               undef my @out;
+               @out = @{ $req{"out"} } if exists(($req{"out"}));
+
+               for(my $idx = 0; $idx < $#in; $idx++) {
+                       my $req = $in[$idx];
+                       generate_requirements($req, $n, "${arch}_${op}", $idx, 1);
+               }
+               for(my $idx = 0; $idx < $#out; $idx++) {
+                       my $req = $out[$idx];
+                       generate_requirements($req, $n, "${arch}_${op}", $idx, 0);
+               }
+
+               if (@in) {
+                       if($arity >= 0 && scalar(@in) != $arity) {
+                               die "Fatal error: Arity and number of in requirements don't match for ${op}\n";
+                       }
+
+                       $temp .= "\tstatic const arch_register_req_t *in_reqs[] =\n";
+                       $temp .= "\t{\n";
+                       for ($idx = 0; $idx <= $#in; $idx++) {
+                               my $req = $in[$idx];
+                               my $reqstruct = generate_requirements($req, $n, "${arch}_${op}", $idx, 1);
+                               $temp .= "\t\t& ${reqstruct},\n";
+                       }
+                       $temp .= "\t};\n";
+               } else {
+                       if($arity > 0) {
+                               die "Fatal error: need in requirements for ${op}\n";
+                       }
+                       $temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n";
+               }
+
+               if (@out) {
+                       if($out_arity >= 0 && scalar(@out) != $out_arity) {
+                               die "Fatal error: Out-Arity and number of out requirements don't match for ${op}\n";
+                       }
+
+                       for ($idx = 0; $idx <= $#out; $idx++) {
+                               my $req = $out[$idx];
+                               my $reqstruct = generate_requirements($req, $n, "${arch}_${op}", $idx, 0);
+                               $set_out_reqs .= <<EOF;
+info->out_infos[${idx}].req = &${reqstruct};
+EOF
+                       }
+               } else {
+                       if($out_arity > 0) {
+                               die "Fatal error: need out requirements for ${op}\n";
+                       }
+               }
+       } else {
+               $temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n";
+       }
+       my $attr_type = $on->{attr_type};
+       if(exists($n->{"init_attr"})) {
+               $temp .= "\t${attr_type} *attr;\n";
+       }
+
+       $temp .= "\n";
+
+       if($arity > 0) {
+               $temp .= "\t/* construct in array */\n";
+               for (my $i = 0; $i < $arity; $i++) {
+                       my $opname = "op${i}";
+                       if (exists($n->{"ins"})) {
+                               my @ins = @{ $n->{"ins"} };
+                               $opname = $ins[$i];
+                       }
+
+                       $temp .= "\tin[${i}] = ${opname};\n";
+               }
+               $temp .= "\n";
+       }
+
+       # set flags
+       if (exists($n->{"irn_flags"})) {
+               $temp .= "\t/* flags */\n";
+               foreach my $flag (split(/\|/, $n->{"irn_flags"})) {
+                       if ($flag eq "R") {
+                               $temp .= "\tflags |= arch_irn_flags_rematerializable;\n";
+                       } elsif ($flag eq "N") {
+                               $temp .= "\tflags |= arch_irn_flags_dont_spill;\n";
+                       } elsif ($flag eq "F") {
+                               $temp .= "\tflags |= arch_irn_flags_modify_flags;\n";
+                       } elsif ($flag eq "J") {
+                               $temp .= "\t flags |= arch_irn_flags_simple_jump;\n";
+                       } else {
+                               die "Fatal error: unknown flag $flag for ${op}\n";
+                       }
+               }
+               $temp .= "\n";
+       }
+
+       # lookup init function
+       my $attr_init_code = $init_attr{$attr_type};
+       if(!defined($attr_init_code)) {
+               die "Fatal error: Couldn't find attribute initialisation code for type '${attr_type}'";
+       }
+       my $custominit = "";
+       if(defined($custom_init_attr_func)) {
+               $custominit .= &$custom_init_attr_func($n, $on, "${arch}_${op}");
+       }
+       if(defined($n->{custominit})) {
+               $custominit .= $n->{custominit};
+       }
+
+       $temp .= <<EOF;
+       /* create node */
+       assert(op != NULL);
+       res = new_ir_node(dbgi, current_ir_graph, block, op, mode, arity, in);
+
+       /* init node attributes */
+       ${attr_init_code}
+       ${custominit}
+       info = be_get_info(res);
+       ${set_out_reqs}
+
+EOF
+
+       if (exists($n->{"init_attr"})) {
+               $temp .= "\tattr = get_irn_generic_attr(res);\n";
+               $temp .= "\t".$n->{"init_attr"}."\n";
+       }
+
+       $temp .= <<EOF;
+       /* optimize node */
+       res = optimize_node(res);
+       irn_vrfy_irg(res, current_ir_graph);
+
+       return res;
+EOF
+
+       $obst_constructor .= $temp;
+
+       # close constructor function
+       $obst_constructor .= "}\n\n";
+}
+
+push(@obst_enum_op, "typedef enum _${arch}_opcodes {\n");
 foreach my $op (keys(%nodes)) {
        my %n        = %{ $nodes{"$op"} };
        my $known_mode;
@@ -206,14 +514,14 @@ foreach my $op (keys(%nodes)) {
        if (exists($n{"outs"})) {
                undef my @outs;
 
-               @outs     = @{ $n{"outs"} };
+               @outs = @{ $n{"outs"} };
                if($out_arity >= 0 && scalar(@outs) != $out_arity) {
                        die "Fatal error: Op ${op} has different number of outs and out_arity\n";
                }
 
                $num_outs = $#outs + 1;
 
-               push(@obst_proj, "\nenum pn_$op {\n");
+               $obst_proj .= "\nenum pn_${op} {\n";
 
                for (my $idx = 0; $idx <= $#outs; $idx++) {
                        # check, if we have additional flags annotated to out
@@ -221,12 +529,14 @@ foreach my $op (keys(%nodes)) {
                                push(@out_flags, $1);
                                $outs[$idx] =~ s/:((S|I)(\|(S|I))*)//;
                        }
-                       push(@obst_proj, "\tpn_$op\_".$outs[$idx]." = $idx,\n");
+                       $obst_proj .= "\tpn_${op}_".$outs[$idx]." = ${idx},\n";
                }
 
-               push(@obst_proj, "};\n");
+               $obst_proj .= "};\n";
                # outs have names, it must be a mode_T node
-               $known_mode = "mode_T";
+               if (!defined($n{mode})) {
+                       $n{mode} = "mode_T";
+               }
        }
        if (exists($n{"ins"})) {
                undef my @ins;
@@ -236,33 +546,30 @@ foreach my $op (keys(%nodes)) {
                        die "Fatal error: Op ${op} has different number of ins and arity\n";
                }
 
-               push(@obst_proj, "\nenum n_$op {\n");
-
+               $obst_proj .= "\nenum n_$op {\n";
                for (my $idx = 0; $idx <= $#ins; $idx++) {
-                       push(@obst_proj, "\tn_${op}_".$ins[$idx]." = $idx,\n");
+                       $obst_proj .= "\tn_${op}_".$ins[$idx]." = ${idx},\n";
                }
-
-               push(@obst_proj, "};\n");
-       }
-
-       # determine mode
-       if (exists($n{"mode"})) {
-               $known_mode = $n{"mode"};
+               $obst_proj .= "};\n";
        }
 
+       # Create opcode
        push(@obst_opvar, "ir_op *op_$op = NULL;\n");
        push(@obst_get_opvar, "ir_op *get_op_$op(void)         { return op_$op; }\n");
        push(@obst_get_opvar, "int    is_$op(const ir_node *n) { return get_$arch\_irn_opcode(n) == iro_$op; }\n\n");
 
        push(@obst_is_archirn, "is_$op(node)");
 
-       push(@obst_header, "extern ir_op *op_$op;\n");
-       push(@obst_header, "ir_op *get_op_$op(void);\n");
-       push(@obst_header, "int is_$op(const ir_node *n);\n");
+       $obst_header .= <<EOF;
+extern ir_op *op_${op};
+ir_op *get_op_${op}(void);
+int is_${op}(const ir_node *n);
+EOF
 
-       my $attr_type= $n{"attr_type"};
+       my $attr_type= $n{attr_type};
        if(!defined($attr_type)) {
                $attr_type = $default_attr_type;
+               $n{attr_type} = $attr_type;
        }
 
        # determine hash function
@@ -299,266 +606,294 @@ foreach my $op (keys(%nodes)) {
                }
        }
 
-       if (exists($n{"rd_constructor"}) && $n{"rd_constructor"} =~ /^NONE$/i) {
-               # we explicitly skip the constructor if the specification entry says NONE
+       my %constructors;
+       if (exists($n{constructors})) {
+               %constructors = %{ $n{constructors} };
        } else {
-               my $comment = $n{"comment"};
-               if(!exists($n{"comment"})) {
-                       $comment = "construct ${orig_op} node";
-               }
-               $comment =
-                       "/**\n".
-                       " * ${comment}\n".
-                       " */\n";
-
-               push(@obst_constructor, $comment);
-
-               # create constructor head
-               my $complete_args = "";
-               $temp             = "";
-
-               $temp = "ir_node *new_bd_$op(dbg_info *db, ir_node *block";
-               if (!exists($n{"args"})) { # default args
-                       if ($arity == $ARITY_VARIABLE) {
-                               $complete_args = ", int arity, ir_node *in[]";
-                       } elsif ($arity == $ARITY_DYNAMIC) {
-                               $complete_args = "";
-                       } else {
-                               for (my $i = 0; $i < $arity; $i++) {
-                                       my $opname = "op${i}";
-                                       if (exists($n{"ins"})) {
-                                               my @ins = @{ $n{"ins"} };
-                                               $opname = $ins[$i];
-                                       }
-
-                                       $complete_args .= ", ir_node *${opname}";
-                               }
-                       }
-                       if ($out_arity == $ARITY_VARIABLE) {
-                               $complete_args .= ", int n_res";
+               # Create 1 default constructor
+               my %constructor = ();
+               foreach my $a ("comment", "ins", "outs", "args", "attr", "units",
+                               "reg_req", "init_attr", "irn_flags", "mode", "arity",
+                               "out_arity", "custominit") {
+                       if (defined($n{$a})) {
+                               $constructor{$a} = $n{$a};
                        }
-
-                       if (!defined($known_mode)) {
-                               $complete_args .= ", ir_mode *mode";
-                       }
-               } else { # user defined args
-                       for my $href (@{ $n{"args"} }) {
-                               $href->{"type"} .= " " if ($href->{"type"} !~ / [*]?$/); # put a space between name and type if there is none at the end
-                               $complete_args  .= ", ".$href->{"type"}.$href->{"name"};
-                       }
-               }
-
-               # we have additional attribute arguements
-               if (exists($n{"attr"})) {
-                       $complete_args .= ", ".$n{"attr"};
                }
+               %constructors = ( "" => \%constructor );
+       }
 
-               $temp .= "$complete_args)";
-               push(@obst_constructor, $temp."\n{\n");
-               push(@obst_header, $comment);
-               push(@obst_header, $temp.";\n");
-
-               # emit constructor code
-               if (!exists($n{"rd_constructor"})) { # default constructor
-                       $temp = <<EOF;
-       ir_node        *res;
-       ir_op          *op      = op_${op};
-       int             flags   = 0;
-       backend_info_t *info;
-EOF
-
-                       if($arity == $ARITY_DYNAMIC) {
-                               $temp .= <<EOF;
-       int             arity   = -1;
-       ir_node       **in      = NULL;
-EOF
-                       } elsif($arity == $ARITY_VARIABLE) {
-                       } else {
-                               $temp .= <<EOF;
-       int             arity   = $arity;
-EOF
-                               if($arity > 0) {
-                                       $temp .= <<EOF;
-       ir_node        *in[$arity];
-EOF
-                               } else {
-                                       $temp .= <<EOF;
-       ir_node       **in    = NULL;
-EOF
-                               }
-                       }
-                       if($out_arity == $ARITY_DYNAMIC) {
-                               $temp .= <<EOF;
-       int             n_res   = -1;
-EOF
-                       } elsif($out_arity == $ARITY_VARIABLE) {
-                       } else {
-                               $temp .= <<EOF;
-       int             n_res   = ${out_arity};
-EOF
-                       }
-
-                       if (defined($known_mode)) {
-                               $temp .= <<EOF;
-       ir_mode        *mode    = ${known_mode};
-EOF
-                       }
-
-                       # set up static variables for cpu execution unit assigments
-                       if (exists($n{"units"})) {
-                               $temp .= gen_execunit_list_initializer($n{"units"});
-                       } else {
-                               $temp .= <<EOF;
-       static const be_execution_unit_t ***exec_units = NULL;
-EOF
-                       }
-
-                       undef my $in_req_var;
-                       undef my $out_req_var;
-
-                       my $set_out_reqs = "";
-
-                       # set up static variables for requirements and registers
-                       if (exists($n{"reg_req"})) {
-                               my %req = %{ $n{"reg_req"} };
-                               my $idx;
-
-                               undef my @in;
-                               @in = @{ $req{"in"} } if (exists($req{"in"}));
-                               undef my @out;
-                               @out = @{ $req{"out"} } if exists(($req{"out"}));
-
-                               for(my $idx = 0; $idx < $#in; $idx++) {
-                                       my $req = $in[$idx];
-                                       generate_requirements($req, \%n, $op, $idx, 1);
-                               }
-                               for(my $idx = 0; $idx < $#out; $idx++) {
-                                       my $req = $out[$idx];
-                                       generate_requirements($req, \%n, $op, $idx, 0);
-                               }
-
-                               if (@in) {
-                                       if($arity >= 0 && scalar(@in) != $arity) {
-                                               die "Fatal error: Arity and number of in requirements don't match for ${op}\n";
-                                       }
-
-                                       $temp .= "\tstatic const arch_register_req_t *in_reqs[] =\n";
-                                       $temp .= "\t{\n";
-                                       for ($idx = 0; $idx <= $#in; $idx++) {
-                                               my $req = $in[$idx];
-                                               my $reqstruct = generate_requirements($req, \%n, $op, $idx, 1);
-                                               $temp .= "\t\t& ${reqstruct},\n";
-                                       }
-                                       $temp .= "\t};\n";
-                               } else {
-                                       if($arity > 0) {
-                                               die "Fatal error: need in requirements for ${op}\n";
-                                       }
-                                       $temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n";
-                               }
-
-                               if (@out) {
-                                       if($out_arity >= 0 && scalar(@out) != $out_arity) {
-                                               die "Fatal error: Out-Arity and number of out requirements don't match for ${op}\n";
-                                       }
-
-                                       for ($idx = 0; $idx <= $#out; $idx++) {
-                                               my $req = $out[$idx];
-                                               my $reqstruct = generate_requirements($req, \%n, $op, $idx, 0);
-                                               $set_out_reqs .= <<EOF;
-       info->out_infos[${idx}].req = &${reqstruct};
-EOF
-                                       }
-                               } else {
-                                       if($out_arity > 0) {
-                                               die "Fatal error: need out requirements for ${op}\n";
-                                       }
-                               }
-                       } else {
-                               $temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n";
-                       }
-                       if(exists($n{"init_attr"})) {
-                               $temp .= "\t${attr_type} *attr;\n";
-                       }
-
-                       $temp .= "\n";
-
-                       if($arity > 0) {
-                               $temp .= "\t/* construct in array */\n";
-                               for (my $i = 0; $i < $arity; $i++) {
-                                       my $opname = "op${i}";
-                                       if (exists($n{"ins"})) {
-                                               my @ins = @{ $n{"ins"} };
-                                               $opname = $ins[$i];
-                                       }
-
-                                       $temp .= "\tin[${i}] = ${opname};\n";
-                               }
-                               $temp .= "\n";
-                       }
-
-                       # set flags
-                       if (exists($n{"irn_flags"})) {
-                               $temp .= "\t/* flags */\n";
-                               foreach my $flag (split(/\|/, $n{"irn_flags"})) {
-                                       if ($flag eq "R") {
-                                               $temp .= "\tflags |= arch_irn_flags_rematerializable;\n";
-                                       } elsif ($flag eq "N") {
-                                               $temp .= "\tflags |= arch_irn_flags_dont_spill;\n";
-                                       } elsif ($flag eq "J") {
-                                               $temp .= "\t flags |= arch_irn_flags_simple_jump;\n";
-                                       } else {
-                                               die "Fatal error: unknown flag $flag for ${op}\n";
-                                       }
-                               }
-                               $temp .= "\n";
-                       }
-
-                       # lookup init function
-                       my $attr_init_code = $init_attr{$attr_type};
-                       if(!defined($attr_init_code)) {
-                               die "Fatal error: Couldn't find attribute initialisation code for type '${attr_type}'";
-                       }
-                       my $custominit = "";
-                       if(defined($custom_init_attr_func)) {
-                               $custominit .= &$custom_init_attr_func(\%n, $op);
-                       }
-
-                       $temp .= <<EOF;
-       /* create node */
-       assert(op != NULL);
-       res = new_ir_node(db, current_ir_graph, block, op, mode, arity, in);
-
-       /* init node attributes */
-       ${attr_init_code}
-       ${custominit}
-       info = be_get_info(res);
-       ${set_out_reqs}
-
-EOF
-
-                       if (exists($n{"init_attr"})) {
-                               $temp .= "\tattr = get_irn_generic_attr(res);\n";
-                               $temp .= "\t".$n{"init_attr"}."\n";
+       foreach my $constr (keys(%constructors)) {
+               my %cstr = %{ $constructors{$constr} };
+               # Copy some values from outer node if they don't exists in the constr
+               foreach my $a ("ins", "outs", "irn_flags", "mode", "args", "attr",
+                              "custominit") {
+                       if (!defined($cstr{$a}) && defined($n{$a})) {
+                               $cstr{$a} = $n{$a};
                        }
-
-                       $temp .= <<EOF;
-       /* optimize node */
-       res = optimize_node(res);
-       irn_vrfy_irg(res, current_ir_graph);
-
-       return res;
-EOF
-
-                       push(@obst_constructor, $temp);
-               }
-               else { # user defined constructor
-                       push(@obst_constructor, $n{"rd_constructor"});
                }
+               create_constructor($orig_op, $constr, \%cstr, \%n);
+       }
 
-               # close constructor function
-               push(@obst_constructor, "}\n\n");
-       } # constructor creation
+#      if (exists($n{"rd_constructor"}) && $n{"rd_constructor"} =~ /^NONE$/i) {
+#              # we explicitly skip the constructor if the specification entry says NONE
+#      } else {
+#              my $comment = $n{"comment"};
+#              if(!exists($n{"comment"})) {
+#                      $comment = "construct ${orig_op} node";
+#              }
+#              $comment =
+#                      "/**\n".
+#                      " * ${comment}\n".
+#                      " */\n";
+#
+#              $obst_constructor .= $comment;
+#
+#              # create constructor head
+#              my $complete_args = "";
+#              $temp             = "";
+#
+#              $temp = "ir_node *new_bd_$op(dbg_info *db, ir_node *block";
+#              if (!exists($n{"args"})) { # default args
+#                      if ($arity == $ARITY_VARIABLE) {
+#                              $complete_args = ", int arity, ir_node *in[]";
+#                      } elsif ($arity == $ARITY_DYNAMIC) {
+#                              $complete_args = "";
+#                      } else {
+#                              for (my $i = 0; $i < $arity; $i++) {
+#                                      my $opname = "op${i}";
+#                                      if (exists($n{"ins"})) {
+#                                              my @ins = @{ $n{"ins"} };
+#                                              $opname = $ins[$i];
+#                                      }
+#
+#                                      $complete_args .= ", ir_node *${opname}";
+#                              }
+#                      }
+#                      if ($out_arity == $ARITY_VARIABLE) {
+#                              $complete_args .= ", int n_res";
+#                      }
+#
+#                      if (!defined($known_mode)) {
+#                              $complete_args .= ", ir_mode *mode";
+#                      }
+#              } else { # user defined args
+#                      for my $href (@{ $n{"args"} }) {
+#                              $href->{"type"} .= " " if ($href->{"type"} !~ / [*]?$/); # put a space between name and type if there is none at the end
+#                              $complete_args  .= ", ".$href->{"type"}.$href->{"name"};
+#                      }
+#              }
+#
+#              # we have additional attribute arguements
+#              if (exists($n{"attr"})) {
+#                      $complete_args .= ", ".$n{"attr"};
+#              }
+#
+#              $temp .= "$complete_args)";
+#              $obst_constructor .= "${temp}\n{\n";
+#              $obst_header .= $comment;
+#              $obst_header .= "${temp};\n";
+#
+#              # emit constructor code
+#              if (!exists($n{"rd_constructor"})) { # default constructor
+#                      $temp = <<EOF;
+#      ir_node        *res;
+#      ir_op          *op      = op_${op};
+#      int             flags   = 0;
+#      backend_info_t *info;
+#EOF
+#
+#                      if($arity == $ARITY_DYNAMIC) {
+#                              $temp .= <<EOF;
+#      int             arity   = -1;
+#      ir_node       **in      = NULL;
+#EOF
+#                      } elsif($arity == $ARITY_VARIABLE) {
+#                      } else {
+#                              $temp .= <<EOF;
+#      int             arity   = $arity;
+#EOF
+#                              if($arity > 0) {
+#                                      $temp .= <<EOF;
+#      ir_node        *in[$arity];
+#EOF
+#                              } else {
+#                                      $temp .= <<EOF;
+#      ir_node       **in    = NULL;
+#EOF
+#                              }
+#                      }
+#                      if($out_arity == $ARITY_DYNAMIC) {
+#                              $temp .= <<EOF;
+#      int             n_res   = -1;
+#EOF
+#                      } elsif($out_arity == $ARITY_VARIABLE) {
+#                      } else {
+#                              $temp .= <<EOF;
+#      int             n_res   = ${out_arity};
+#EOF
+#                      }
+#
+#                      if (defined($known_mode)) {
+#                              $temp .= <<EOF;
+#      ir_mode        *mode    = ${known_mode};
+#EOF
+#                      }
+#
+#                      # set up static variables for cpu execution unit assigments
+#                      if (exists($n{"units"})) {
+#                              $temp .= gen_execunit_list_initializer($n{"units"});
+#                      } else {
+#                              $temp .= <<EOF;
+#      static const be_execution_unit_t ***exec_units = NULL;
+#EOF
+#                      }
+#
+#                      undef my $in_req_var;
+#                      undef my $out_req_var;
+#
+#                      my $set_out_reqs = "";
+#
+#                      # set up static variables for requirements and registers
+#                      if (exists($n{"reg_req"})) {
+#                              my %req = %{ $n{"reg_req"} };
+#                              my $idx;
+#
+#                              undef my @in;
+#                              @in = @{ $req{"in"} } if (exists($req{"in"}));
+#                              undef my @out;
+#                              @out = @{ $req{"out"} } if exists(($req{"out"}));
+#
+#                              for(my $idx = 0; $idx < $#in; $idx++) {
+#                                      my $req = $in[$idx];
+#                                      generate_requirements($req, \%n, $op, $idx, 1);
+#                              }
+#                              for(my $idx = 0; $idx < $#out; $idx++) {
+#                                      my $req = $out[$idx];
+#                                      generate_requirements($req, \%n, $op, $idx, 0);
+#                              }
+#
+#                              if (@in) {
+#                                      if($arity >= 0 && scalar(@in) != $arity) {
+#                                              die "Fatal error: Arity and number of in requirements don't match for ${op}\n";
+#                                      }
+#
+#                                      $temp .= "\tstatic const arch_register_req_t *in_reqs[] =\n";
+#                                      $temp .= "\t{\n";
+#                                      for ($idx = 0; $idx <= $#in; $idx++) {
+#                                              my $req = $in[$idx];
+#                                              my $reqstruct = generate_requirements($req, \%n, $op, $idx, 1);
+#                                              $temp .= "\t\t& ${reqstruct},\n";
+#                                      }
+#                                      $temp .= "\t};\n";
+#                              } else {
+#                                      if($arity > 0) {
+#                                              die "Fatal error: need in requirements for ${op}\n";
+#                                      }
+#                                      $temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n";
+#                              }
+#
+#                              if (@out) {
+#                                      if($out_arity >= 0 && scalar(@out) != $out_arity) {
+#                                              die "Fatal error: Out-Arity and number of out requirements don't match for ${op}\n";
+#                                      }
+#
+#                                      for ($idx = 0; $idx <= $#out; $idx++) {
+#                                              my $req = $out[$idx];
+#                                              my $reqstruct = generate_requirements($req, \%n, $op, $idx, 0);
+#                                              $set_out_reqs .= <<EOF;
+#      info->out_infos[${idx}].req = &${reqstruct};
+#EOF
+#                                      }
+#                              } else {
+#                                      if($out_arity > 0) {
+#                                              die "Fatal error: need out requirements for ${op}\n";
+#                                      }
+#                              }
+#                      } else {
+#                              $temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n";
+#                      }
+#                      if(exists($n{"init_attr"})) {
+#                              $temp .= "\t${attr_type} *attr;\n";
+#                      }
+#
+#                      $temp .= "\n";
+#
+#                      if($arity > 0) {
+#                              $temp .= "\t/* construct in array */\n";
+#                              for (my $i = 0; $i < $arity; $i++) {
+#                                      my $opname = "op${i}";
+#                                      if (exists($n{"ins"})) {
+#                                              my @ins = @{ $n{"ins"} };
+#                                              $opname = $ins[$i];
+#                                      }
+#
+#                                      $temp .= "\tin[${i}] = ${opname};\n";
+#                              }
+#                              $temp .= "\n";
+#                      }
+#
+#                      # set flags
+#                      if (exists($n{"irn_flags"})) {
+#                              $temp .= "\t/* flags */\n";
+#                              foreach my $flag (split(/\|/, $n{"irn_flags"})) {
+#                                      if ($flag eq "R") {
+#                                              $temp .= "\tflags |= arch_irn_flags_rematerializable;\n";
+#                                      } elsif ($flag eq "N") {
+#                                              $temp .= "\tflags |= arch_irn_flags_dont_spill;\n";
+#                                      } elsif ($flag eq "J") {
+#                                              $temp .= "\t flags |= arch_irn_flags_simple_jump;\n";
+#                                      } else {
+#                                              die "Fatal error: unknown flag $flag for ${op}\n";
+#                                      }
+#                              }
+#                              $temp .= "\n";
+#                      }
+#
+#                      # lookup init function
+#                      my $attr_init_code = $init_attr{$attr_type};
+#                      if(!defined($attr_init_code)) {
+#                              die "Fatal error: Couldn't find attribute initialisation code for type '${attr_type}'";
+#                      }
+#                      my $custominit = "";
+#                      if(defined($custom_init_attr_func)) {
+#                              $custominit .= &$custom_init_attr_func(\%n, $op);
+#                      }
+#
+#                      $temp .= <<EOF;
+#      /* create node */
+#      assert(op != NULL);
+#      res = new_ir_node(db, current_ir_graph, block, op, mode, arity, in);
+#
+#      /* init node attributes */
+#      ${attr_init_code}
+#      ${custominit}
+#      info = be_get_info(res);
+#      ${set_out_reqs}
+#
+#EOF
+#
+#                      if (exists($n{"init_attr"})) {
+#                              $temp .= "\tattr = get_irn_generic_attr(res);\n";
+#                              $temp .= "\t".$n{"init_attr"}."\n";
+#                      }
+#
+#                      $temp .= <<EOF;
+#      /* optimize node */
+#      res = optimize_node(res);
+#      irn_vrfy_irg(res, current_ir_graph);
+#
+#      return res;
+#EOF
+#
+#                      $obst_constructor .= $temp;
+#              }
+#              else { # user defined constructor
+#                      $obst_constructor .= $n{"rd_constructor"};
+#              }
+#
+#              # close constructor function
+#              $obst_constructor .= "}\n\n";
+#      } # constructor creation
 
        # set default values for state and flags if not given
        $n{"state"}    = "floats" if (! exists($n{"state"}));
@@ -584,10 +919,6 @@ EOF
        }
 
        $n_opcodes++;
-       my $n_res = $out_arity;
-       if($n_res < 0) {
-               $n_res = "20"; # hacky....
-       }
        $temp  = "\top_$op = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", ".$n{"op_flags"};
        $temp .= "|M, ".translate_arity($arity).", 0, sizeof(${attr_type}), &ops);\n";
        push(@obst_new_irop, $temp);
@@ -602,7 +933,7 @@ EOF
 
        push(@obst_enum_op, "\tiro_$op,\n");
 
-       push(@obst_header, "\n");
+       $obst_header .= "\n";
 }
 push(@obst_enum_op, "\tiro_$arch\_last_generated,\n");
 push(@obst_enum_op, "\tiro_$arch\_last = iro_$arch\_last_generated");
@@ -695,9 +1026,9 @@ print OUT "\n";
 print OUT @obst_reg_reqs;
 print OUT "\n";
 
-print OUT @obst_constructor;
-
 print OUT<<ENDOFMAIN;
+$obst_constructor
+
 /**
  * Creates the $arch specific Firm machine operations
  * needed for the assembler irgs.
@@ -774,14 +1105,15 @@ print OUT<<EOF;
 EOF
 
 print OUT @obst_enum_op;
-print OUT "int is_$arch\_irn(const ir_node *node);\n\n";
-print OUT "int get_$arch\_opcode_first(void);\n";
-print OUT "int get_$arch\_opcode_last(void);\n";
-print OUT "int get_$arch\_irn_opcode(const ir_node *node);\n";
-print OUT @obst_header;
-print OUT @obst_proj;
-
 print OUT <<EOF;
+int is_${arch}_irn(const ir_node *node);
+
+int get_${arch}_opcode_first(void);
+int get_${arch}_opcode_last(void);
+int get_${arch}_irn_opcode(const ir_node *node);
+${obst_header}
+${obst_proj}
+
 #endif
 EOF
 
index 20ee73f..b4de6a6 100644 (file)
@@ -38,8 +38,8 @@
  *
  * @param block  the block to test
  */
-static int
-is_Block_unreachable(ir_node *block) {
+static int is_Block_unreachable(ir_node *block)
+{
        return is_Block_dead(block) || get_Block_dom_depth(block) < 0;
 }
 
@@ -62,8 +62,8 @@ is_Block_unreachable(ir_node *block) {
  * @param n         the node to be placed
  * @param worklist  a worklist, predecessors of non-floating nodes are placed here
  */
-static void
-place_floats_early(ir_node *n, waitq *worklist) {
+static void place_floats_early(ir_node *n, waitq *worklist)
+{
        int i, irn_arity;
 
        /* we must not run into an infinite loop */
@@ -96,9 +96,10 @@ place_floats_early(ir_node *n, waitq *worklist) {
 
                                /*
                                 * If the current node is NOT in a dead block, but one of its
-                                * predecessors is, we must move the predecessor to a live block.
-                                * Such thing can happen, if global CSE chose a node from a dead block.
-                                * We move it simply to our block.
+                                * predecessors is, we must move the predecessor to a live
+                                * block.
+                                * Such thing can happen, if global CSE chose a node from a
+                                * dead block. We move it simply to our block.
                                 * Note that neither Phi nor End nodes are floating, so we don't
                                 * need to handle them here.
                                 */
@@ -117,17 +118,18 @@ place_floats_early(ir_node *n, waitq *worklist) {
                        if (in_dead_block)
                                continue;
 
-                       /* Because all loops contain at least one op_pin_state_pinned node, now all
-                          our inputs are either op_pin_state_pinned or place_early() has already
-                          been finished on them.  We do not have any unfinished inputs!  */
+                       /* Because all loops contain at least one op_pin_state_pinned node,
+                          now all our inputs are either op_pin_state_pinned or
+                          place_early() has already been finished on them.
+                          We do not have any unfinished inputs! */
                        pred_block = get_nodes_block(pred);
                        if ((!is_Block_dead(pred_block)) &&
                                (get_Block_dom_depth(pred_block) > depth)) {
                                b = pred_block;
                                depth = get_Block_dom_depth(pred_block);
                        }
-                       /* Avoid that the node is placed in the Start block if we are not in the
-                          backend phase. */
+                       /* Avoid that the node is placed in the Start block if we are not
+                          in the backend phase. */
                        if (depth == 1 &&
                                        get_Block_dom_depth(get_nodes_block(n)) > 1 &&
                                        get_irg_phase_state(current_ir_graph) != phase_backend) {
@@ -142,7 +144,8 @@ place_floats_early(ir_node *n, waitq *worklist) {
 
        /*
         * Add predecessors of non floating nodes and non-floating predecessors
-        * of floating nodes to worklist and fix their blocks if the are in dead block.
+        * of floating nodes to worklist and fix their blocks if the are in dead
+        * block.
         */
        irn_arity = get_irn_arity(n);
 
@@ -220,13 +223,15 @@ place_floats_early(ir_node *n, waitq *worklist) {
 
 /**
  * Floating nodes form subgraphs that begin at nodes as Const, Load,
- * Start, Call and that end at op_pin_state_pinned nodes as Store, Call.  Place_early
- * places all floating nodes reachable from its argument through floating
- * nodes and adds all beginnings at op_pin_state_pinned nodes to the worklist.
+ * Start, Call and that end at op_pin_state_pinned nodes as Store, Call.
+ * Place_early places all floating nodes reachable from its argument through
+ * floating nodes and adds all beginnings at op_pin_state_pinned nodes to the
+ * worklist.
  *
  * @param worklist   a worklist, used for the algorithm, empty on in/output
  */
-static void place_early(waitq *worklist) {
+static void place_early(waitq *worklist)
+{
        assert(worklist);
        inc_irg_visited(current_ir_graph);
 
@@ -251,8 +256,9 @@ static void place_early(waitq *worklist) {
  *
  * @return  the deepest common dominator tree ancestor of block and dca
  */
-static ir_node *calc_dom_dca(ir_node *dca, ir_node *block) {
-       assert(block);
+static ir_node *calc_dom_dca(ir_node *dca, ir_node *block)
+{
+       assert(block != NULL);
 
        /* we do not want to place nodes in dead blocks */
        if (is_Block_dead(block))
@@ -305,7 +311,8 @@ static ir_node *consumer_dom_dca(ir_node *dca, ir_node *consumer, ir_node *produ
        return dca;
 }
 
-static inline int get_block_loop_depth(ir_node *block) {
+static inline int get_block_loop_depth(ir_node *block)
+{
        return get_loop_depth(get_irn_loop(block));
 }
 
@@ -316,7 +323,8 @@ static inline int get_block_loop_depth(ir_node *block) {
  * @param n      the node that should be moved
  * @param early  the earliest block we can n move to
  */
-static void move_out_of_loops(ir_node *n, ir_node *early) {
+static void move_out_of_loops(ir_node *n, ir_node *early)
+{
        ir_node *best, *dca;
        assert(n && early);
 
@@ -348,7 +356,8 @@ static void move_out_of_loops(ir_node *n, ir_node *early) {
  *
  * @return the deepest common dominator ancestor of all blocks of node's users
  */
-static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca) {
+static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca)
+{
        int i;
 
        for (i = get_irn_n_outs(node) - 1; i >= 0; --i) {
@@ -383,7 +392,8 @@ static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca) {
  * @param node   the mode_T node
  * @param block  the block to put the Proj nodes to
  */
-static void set_projs_block(ir_node *node, ir_node *block) {
+static void set_projs_block(ir_node *node, ir_node *block)
+{
        int i;
 
        for (i = get_irn_n_outs(node) - 1; i >= 0; --i) {
@@ -410,7 +420,8 @@ static void set_projs_block(ir_node *node, ir_node *block) {
  * @param worklist  a worklist, all successors of non-floating nodes are
  *                  placed here
  */
-static void place_floats_late(ir_node *n, pdeq *worklist) {
+static void place_floats_late(ir_node *n, pdeq *worklist)
+{
        int i, n_outs;
        ir_node *early_blk;
 
@@ -489,7 +500,8 @@ static void place_floats_late(ir_node *n, pdeq *worklist) {
  *
  * @param worklist   the worklist containing the nodes to place
  */
-static void place_late(waitq *worklist) {
+static void place_late(waitq *worklist)
+{
        assert(worklist);
        inc_irg_visited(current_ir_graph);
 
@@ -505,7 +517,8 @@ static void place_late(waitq *worklist) {
 }
 
 /* Code Placement. */
-void place_code(ir_graph *irg) {
+void place_code(ir_graph *irg)
+{
        waitq *worklist;
        ir_graph *rem = current_ir_graph;
 
@@ -542,13 +555,15 @@ void place_code(ir_graph *irg) {
 /**
  * Wrapper for place_code() inside the place_code pass.
  */
-static void place_code_wrapper(ir_graph *irg) {
+static void place_code_wrapper(ir_graph *irg)
+{
        set_opt_global_cse(1);
        optimize_graph_df(irg);
        place_code(irg);
        set_opt_global_cse(0);
 }
 
-ir_graph_pass_t *place_code_pass(const char *name) {
+ir_graph_pass_t *place_code_pass(const char *name)
+{
        return def_graph_pass(name ? name : "place", place_code_wrapper);
 }