adapt mips backend to new transform logic, use Immediate nodes, fixes
authorMatthias Braun <matze@braunis.de>
Mon, 25 Jun 2007 23:11:31 +0000 (23:11 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 25 Jun 2007 23:11:31 +0000 (23:11 +0000)
[r14762]

12 files changed:
ir/be/mips/bearch_mips.c
ir/be/mips/bearch_mips.h
ir/be/mips/bearch_mips_t.h
ir/be/mips/mips_emitter.c
ir/be/mips/mips_emitter.h
ir/be/mips/mips_new_nodes.c
ir/be/mips/mips_new_nodes.h
ir/be/mips/mips_nodes_attr.h
ir/be/mips/mips_scheduler.c
ir/be/mips/mips_spec.pl
ir/be/mips/mips_transform.c
ir/be/mips/mips_transform.h

index f32a49a..3fb2506 100644 (file)
@@ -154,8 +154,7 @@ static void mips_set_irn_reg(const void *self, ir_node *irn,
 
                slots      = get_mips_slots(irn);
                slots[pos] = reg;
-       }
-       else {
+       } else {
                /* here we set the registers for the Phi nodes */
                mips_set_firm_reg(irn, reg, cur_reg_set);
        }
@@ -209,51 +208,76 @@ static arch_irn_flags_t mips_get_flags(const void *self, const ir_node *irn)
        (void) self;
        irn = skip_Proj_const(irn);
 
-       if (is_mips_irn(irn)) {
-               return get_mips_flags(irn);
-       }
-       else if (is_Unknown(irn)) {
-               return arch_irn_flags_ignore;
-       }
+       if (!is_mips_irn(irn))
+               return 0;
 
-       return 0;
+       return get_mips_flags(irn);
+}
+
+int mips_is_Load(const ir_node *node)
+{
+       return is_mips_lw(node) || is_mips_lh(node) || is_mips_lhu(node) ||
+               is_mips_lb(node) || is_mips_lbu(node);
+}
+
+int mips_is_Store(const ir_node *node)
+{
+       return is_mips_sw(node) || is_mips_sh(node) || is_mips_sb(node);
 }
 
-static
-ir_entity *mips_get_frame_entity(const void *self, const ir_node *node)
+static ir_entity *mips_get_frame_entity(const void *self, const ir_node *node)
 {
-       const mips_attr_t *attr;
+       const mips_load_store_attr_t *attr;
        (void) self;
 
        if(!is_mips_irn(node))
                return NULL;
+       if(!mips_is_Load(node) && !mips_is_Store(node))
+               return NULL;
 
-       attr = get_mips_attr_const(node);
+       attr = get_mips_load_store_attr_const(node);
        return attr->stack_entity;
 }
 
-static
-void mips_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent)
+static void mips_set_frame_entity(const void *self, ir_node *node,
+                                  ir_entity *entity)
 {
-       mips_attr_t *attr  = get_mips_attr(irn);
+       mips_load_store_attr_t *attr;
        (void) self;
-       attr->stack_entity = ent;
+
+       if(!is_mips_irn(node)) {
+               panic("trying to set frame entity on non load/store node %+F\n", node);
+       }
+       if(!mips_is_Load(node) && !mips_is_Store(node)) {
+               panic("trying to set frame entity on non load/store node %+F\n", node);
+       }
+
+       attr = get_irn_generic_attr(node);
+       attr->stack_entity = entity;
 }
 
 /**
  * This function is called by the generic backend to correct offsets for
  * nodes accessing the stack.
  */
-static void mips_set_frame_offset(const void *self, ir_node *irn, int offset)
+static void mips_set_frame_offset(const void *self, ir_node *node, int offset)
 {
+       mips_load_store_attr_t *attr;
        (void) self;
-       (void) irn;
-       (void) offset;
-       panic("TODO");
-#if 0
-       mips_attr_t *attr = get_mips_attr(irn);
-       attr->stack_entity_offset = offset;
-#endif
+
+       if(!is_mips_irn(node)) {
+               panic("trying to set frame offset on non load/store node %+F\n", node);
+       }
+       if(!mips_is_Load(node) && !mips_is_Store(node)) {
+               panic("trying to set frame offset on non load/store node %+F\n", node);
+       }
+
+       attr = get_irn_generic_attr(node);
+       attr->offset += offset;
+
+       if(attr->offset < -32768 || attr->offset > 32767) {
+               panic("Out of stack space! (mips supports only 16bit offsets)");
+       }
 }
 
 static int mips_get_sp_bias(const void *self, const ir_node *irn)
@@ -465,8 +489,7 @@ static void mips_prepare_graph(void *self) {
        }
 
        // walk the graph and transform firm nodes into mips nodes where possible
-       irg_walk_blkwise_graph(cg->irg, mips_pre_transform_node, mips_transform_node, cg);
-
+       mips_transform_graph(cg);
        dump_ir_block_graph_sched(cg->irg, "-transformed");
 }
 
@@ -559,6 +582,8 @@ static void *mips_cg_init(be_irg_t *birg)
 
        mips_irn_ops.cg = cg;
 
+       isa->cg = cg;
+
        return (arch_code_generator_t *)cg;
 }
 
@@ -584,6 +609,7 @@ static mips_isa_t mips_isa_template = {
                5,      /* reload costs */
        },
        NULL_EMITTER,  /* emitter environment */
+       NULL,          /* cg */
 };
 
 /**
@@ -690,9 +716,7 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
 {
        mips_abi_env_t *env = self;
        ir_graph *irg = env->irg;
-       dbg_info *dbg = NULL; // TODO where can I get this from?
        ir_node *block = get_irg_start_block(env->irg);
-       mips_attr_t *attr;
        ir_node *sp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_SP]);
        ir_node *fp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
        int initialstackframesize;
@@ -709,11 +733,10 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
                initialstackframesize = 24;
 
                // - setup first part of stackframe
-               sp = new_rd_mips_addiu(dbg, irg, block, sp);
-               attr = get_mips_attr(sp);
-               attr->tv = new_tarval_from_long(-initialstackframesize, mode_Is);
+               sp = new_rd_mips_addu(NULL, irg, block, sp,
+                                     mips_create_Immediate(initialstackframesize));
                mips_set_irn_reg(NULL, sp, &mips_gp_regs[REG_SP]);
-               //arch_set_irn_register(mips_get_arg_env(), sp, &mips_gp_regs[REG_SP]);
+               set_mips_flags(sp, arch_irn_flags_ignore);
 
                /* TODO: where to get an edge with a0-a3
                int i;
@@ -729,20 +752,18 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
                */
 
                reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
-               store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg);
-               attr = get_mips_attr(store);
-               attr->tv = new_tarval_from_long(16, mode_Hs);
+               store = new_rd_mips_sw(NULL, irg, block, sp, reg, *mem, NULL, 16);
 
                mm[4] = store;
 
                reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_RA]);
-               store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg);
-               attr = get_mips_attr(store);
-               attr->tv = new_tarval_from_long(20, mode_Hs);
+               store = new_rd_mips_sw(NULL, irg, block, sp, reg, *mem, NULL, 20);
 
                mm[5] = store;
 
-               // TODO ideally we would route these mem edges directly towards the epilogue
+               /* Note: ideally we would route these mem edges directly towards the
+                * epilogue, but this is currently not supported so we sync all mems
+                * together */
                sync = new_r_Sync(irg, block, 2, mm+4);
                *mem = sync;
        } else {
@@ -750,26 +771,22 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
                initialstackframesize = 4;
 
                // save old framepointer
-               sp = new_rd_mips_addiu(dbg, irg, block, sp);
-               attr = get_mips_attr(sp);
-               attr->tv = new_tarval_from_long(-initialstackframesize, mode_Is);
+               sp = new_rd_mips_addu(NULL, irg, block, sp,
+                                     mips_create_Immediate(-initialstackframesize));
                mips_set_irn_reg(NULL, sp, &mips_gp_regs[REG_SP]);
-               //arch_set_irn_register(mips_get_arg_env(), sp, &mips_gp_regs[REG_SP]);
+               set_mips_flags(sp, arch_irn_flags_ignore);
 
                reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
-               store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg);
-               attr = get_mips_attr(store);
-               attr->tv = new_tarval_from_long(0, mode_Hs);
+               store = new_rd_mips_sw(NULL, irg, block, sp, reg, *mem, NULL, 0);
 
                *mem = store;
        }
 
        // setup framepointer
-       fp = new_rd_mips_addiu(dbg, irg, block, sp);
-       attr = get_mips_attr(fp);
-       attr->tv = new_tarval_from_long(initialstackframesize, mode_Is);
+       fp = new_rd_mips_addu(NULL, irg, block, sp,
+                             mips_create_Immediate(-initialstackframesize));
        mips_set_irn_reg(NULL, fp, &mips_gp_regs[REG_FP]);
-       //arch_set_irn_register(mips_get_arg_env(), fp, &mips_gp_regs[REG_FP]);
+       set_mips_flags(fp, arch_irn_flags_ignore);
 
        be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_FP], fp);
        be_abi_reg_map_set(reg_map, &mips_gp_regs[REG_SP], sp);
@@ -779,10 +796,9 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
 
 static void mips_abi_epilogue(void *self, ir_node *block, ir_node **mem, pmap *reg_map)
 {
-       mips_abi_env_t *env = self;
+       mips_abi_env_t   *env = self;
+
        ir_graph *irg = env->irg;
-       dbg_info *dbg = NULL; // TODO where can I get this from?
-       mips_attr_t *attr;
        ir_node *sp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_SP]);
        ir_node *fp = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
        ir_node *load;
@@ -790,15 +806,14 @@ static void mips_abi_epilogue(void *self, ir_node *block, ir_node **mem, pmap *r
        int fp_save_offset = env->debug ? 16 : 0;
 
        // copy fp to sp
-       sp = new_rd_mips_move(dbg, irg, block, fp);
+       sp = new_rd_mips_or(NULL, irg, block, fp, mips_create_zero());
        mips_set_irn_reg(NULL, sp, &mips_gp_regs[REG_SP]);
-       //arch_set_irn_register(mips_get_arg_env(), fp, &mips_gp_regs[REG_SP]);
+       set_mips_flags(sp, arch_irn_flags_ignore);
 
        // 1. restore fp
-       load = new_rd_mips_lw(dbg, irg, block, *mem, sp);
-       attr = get_mips_attr(load);
-       // sp is at the fp address already, so we have to do fp_save_offset - initial_frame_size
-       attr->tv = new_tarval_from_long(fp_save_offset - initial_frame_size, mode_Hs);
+       load = new_rd_mips_lw(NULL, irg, block, sp, *mem, NULL,
+                             fp_save_offset - initial_frame_size);
+       set_mips_flags(load, arch_irn_flags_ignore);
 
        fp = new_r_Proj(irg, block, load, mode_Iu, pn_mips_lw_res);
        *mem = new_r_Proj(irg, block, load, mode_Iu, pn_mips_lw_M);
index 5496dbb..b863ce9 100644 (file)
@@ -44,4 +44,7 @@ void mips_set_block_sched_nr(ir_node *block, int nr);
 /** get a block schedule number */
 int mips_get_block_sched_nr(ir_node *block);
 
+int mips_is_Load(const ir_node *node);
+int mips_is_Store(const ir_node *node);
+
 #endif
index edf83f7..afd85ab 100644 (file)
@@ -52,6 +52,7 @@ struct mips_code_gen_t {
 struct mips_isa_t {
        arch_isa_t             arch_isa;    /**< must be derived from arch_isa_t */
        be_emit_env_t          emit;        /**< An emitter environment for the GAS emitter. */
+       mips_code_gen_t       *cg;
 };
 
 struct mips_irn_ops_t {
index 6a1ea25..158df07 100644 (file)
@@ -229,27 +229,78 @@ static const char *node_const_to_str(ir_node *n)
 }
 #endif
 
+void mips_emit_load_store_address(mips_emit_env_t *env, const ir_node *node,
+                                  int pos)
+{
+       const mips_load_store_attr_t *attr = get_mips_load_store_attr_const(node);
+
+       be_emit_irprintf(env->emit, "%d(", attr->offset);
+       mips_emit_source_register(env, node, pos);
+       be_emit_char(env->emit, ')');
+}
+
+void mips_emit_immediate_suffix(mips_emit_env_t *env, const ir_node *node,
+                                int pos)
+{
+       ir_node *op = get_irn_n(node, pos);
+       if(is_mips_Immediate(op))
+               be_emit_char(env->emit, 'i');
+}
+
 void mips_emit_immediate(mips_emit_env_t *env, const ir_node *node)
 {
-       const mips_attr_t *attr = get_mips_attr_const(node);
+       const mips_immediate_attr_t *attr = get_mips_immediate_attr_const(node);
+
+       switch(attr->imm_type) {
+       case MIPS_IMM_CONST:
+               be_emit_irprintf(env->emit, "%d", attr->val);
+               break;
+       case MIPS_IMM_SYMCONST_LO:
+               be_emit_cstring(env->emit, "%lo($");
+               be_emit_ident(env->emit, get_entity_ld_ident(attr->entity));
+               if(attr->val != 0) {
+                       be_emit_irprintf(env->emit, "%+d", attr->val);
+               }
+               be_emit_char(env->emit, ')');
+               break;
+       case MIPS_IMM_SYMCONST_HI:
+               be_emit_cstring(env->emit, "%hi($");
+               be_emit_ident(env->emit, get_entity_ld_ident(attr->entity));
+               if(attr->val != 0) {
+                       be_emit_irprintf(env->emit, "%+d", attr->val);
+               }
+               be_emit_char(env->emit, ')');
+               break;
+       default:
+               panic("invalid immediate type found");
+       }
+}
 
-       if(attr->tv != NULL) {
-               be_emit_tarval(env->emit, attr->tv);
+/**
+ * Emit the name of the destination register at given output position.
+ */
+void mips_emit_source_register_or_immediate(mips_emit_env_t *env,
+                                            const ir_node *node, int pos)
+{
+       const ir_node *op = get_irn_n(node, pos);
+       if(is_mips_Immediate(op)) {
+               mips_emit_immediate(env, op);
        } else {
-               be_emit_cstring(env->emit, "/* TODO */ 0");
+               mips_emit_source_register(env, node, pos);
        }
 }
 
+#if 0
 /*
  * Add a number to a prefix. This number will not be used a second time.
  */
-static
-char *get_unique_label(char *buf, size_t buflen, const char *prefix)
+static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
 {
        static unsigned long id = 0;
        snprintf(buf, buflen, "%s%lu", prefix, ++id);
        return buf;
 }
+#endif
 
 /************************************************************************/
 /* ABI Handling                                                         */
@@ -450,6 +501,7 @@ void mips_emit_jump_or_fallthrough(mips_emit_env_t *env, const ir_node *node,
  *                                                                      *
  ************************************************************************/
 
+#if 0
 /* jump table entry (target and corresponding number) */
 typedef struct _branch_t {
        ir_node *target;
@@ -469,7 +521,8 @@ typedef struct _jmp_tbl_t {
 /**
  * Compare two variables of type branch_t. Used to sort all switch cases
  */
-static int mips_cmp_branch_t(const void *a, const void *b) {
+static int mips_cmp_branch_t(const void *a, const void *b)
+{
        branch_t *b1 = (branch_t *)a;
        branch_t *b2 = (branch_t *)b;
 
@@ -573,6 +626,7 @@ void dump_jump_tables(ir_node* node, void *data)
                be_emit_write_line(env->emit);
        }
 }
+#endif
 
 /***********************************************************************************
  *                  _          __                                             _
@@ -689,7 +743,7 @@ void mips_emit_func_prolog(mips_emit_env_t *env, ir_graph *irg)
        be_emit_env_t *eenv = env->emit;
 
        // dump jump tables
-       irg_walk_graph(irg, NULL, dump_jump_tables, env);
+       //irg_walk_graph(irg, NULL, dump_jump_tables, env);
 
        be_emit_write_line(eenv);
        be_gas_emit_switch_section(eenv, GAS_SECTION_TEXT);
index 6b11d3b..7b65f01 100644 (file)
@@ -42,9 +42,17 @@ struct mips_emit_env_t {
        mips_isa_t            *isa;
 };
 
-void mips_emit_source_register(mips_emit_env_t *env, const ir_node *node, int pos);
-void mips_emit_dest_register(mips_emit_env_t *env, const ir_node *node, int pos);
+void mips_emit_source_register(mips_emit_env_t *env, const ir_node *node,
+                               int pos);
+void mips_emit_dest_register(mips_emit_env_t *env, const ir_node *node,
+                             int pos);
+void mips_emit_source_register_or_immediate(mips_emit_env_t *env,
+                                            const ir_node *node, int pos);
 void mips_emit_immediate(mips_emit_env_t *env, const ir_node *node);
+void mips_emit_immediate_suffix(mips_emit_env_t *env, const ir_node *node,
+                                int pos);
+void mips_emit_load_store_address(mips_emit_env_t *env, const ir_node *node,
+                                  int pos);
 void mips_emit_jump_target(mips_emit_env_t *env, const ir_node *node);
 void mips_emit_jump_target_proj(mips_emit_env_t *env, const ir_node *node,
                                 long pn);
index 3683fa4..126aea2 100644 (file)
 /**
  * Dumps the register requirements for either in or out.
  */
-static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs, int inout) {
+static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
+                         int inout)
+{
+       const mips_attr_t *attr = get_mips_attr_const(n);
        char *dir = inout ? "out" : "in";
-       int   max = inout ? get_mips_n_res(n) : get_irn_arity(n);
+       int   max = inout ? ARR_LEN(attr->slots) : get_irn_arity(n);
        char  buf[1024];
        int   i;
 
@@ -116,11 +119,9 @@ static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
  * @return 0 on success or != 0 on failure
  */
 static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
-       ir_mode     *mode = NULL;
        int          bad  = 0;
        int          i;
-       mips_attr_t *attr;
-       char buf[64];
+       const mips_attr_t *attr = get_mips_attr_const(n);
        const arch_register_req_t **reqs;
        const arch_register_t     **slots;
 
@@ -130,20 +131,15 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                        break;
 
                case dump_node_mode_txt:
-                       mode = get_irn_mode(n);
-
-                       if (mode) {
-                               fprintf(F, "[%s]", get_mode_name(mode));
-                       }
-                       else {
-                               fprintf(F, "[?NOMODE?]");
-                       }
                        break;
 
                case dump_node_nodeattr_txt:
 
-                       /* TODO: dump some attributes which should show up */
-                       /* in node name in dump (e.g. consts or the like)  */
+                       if(is_mips_Immediate(n)) {
+                               const mips_immediate_attr_t *attr
+                                       = get_mips_immediate_attr_const(n);
+                               fprintf(F, " %ld", attr->val);
+                       }
 
                        break;
 
@@ -178,7 +174,7 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                        fprintf(F, "\n");
 
                        /* dump n_res */
-                       fprintf(F, "n_res = %d\n", get_mips_n_res(n));
+                       fprintf(F, "n_res = %d\n", ARR_LEN(attr->slots));
 
                        /* dump flags */
                        fprintf(F, "flags =");
@@ -198,17 +194,6 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                        }
                        fprintf(F, " (%d)\n", attr->flags);
 
-                       if(attr->stack_entity != NULL) {
-                               fprintf(F, " stack entity %s\n", get_entity_name(attr->stack_entity));
-                       }
-                       if(attr->tv != NULL) {
-                               tarval_snprintf(buf, sizeof(buf), attr->tv);
-                               fprintf(F, " tarval %s\n", buf);
-                       }
-                       if(attr->symconst != NULL) {
-                               fprintf(F, " symconst '%s'\n", get_entity_name(attr->symconst));
-                       }
-
                        fprintf(F, "=== mips attr end ===\n");
                        /* end of: case dump_node_info_txt */
                        break;
@@ -231,12 +216,27 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
  *                                       |___/
  ***************************************************************************************************/
 
-mips_attr_t *get_mips_attr(ir_node *node) {
+mips_attr_t *get_mips_attr(ir_node *node)
+{
        assert(is_mips_irn(node) && "need mips node to get attributes");
        return (mips_attr_t *) get_irn_generic_attr(node);
 }
 
-const mips_attr_t *get_mips_attr_const(const ir_node *node) {
+const mips_attr_t *get_mips_attr_const(const ir_node *node)
+{
+       assert(is_mips_irn(node) && "need mips node to get attributes");
+       return get_irn_generic_attr_const(node);
+}
+
+const mips_immediate_attr_t *get_mips_immediate_attr_const(const ir_node *node)
+{
+       assert(is_mips_irn(node) && "need mips node to get attributes");
+       return get_irn_generic_attr_const(node);
+}
+
+const mips_load_store_attr_t *get_mips_load_store_attr_const(
+               const ir_node *node)
+{
        assert(is_mips_irn(node) && "need mips node to get attributes");
        return get_irn_generic_attr_const(node);
 }
@@ -244,7 +244,8 @@ const mips_attr_t *get_mips_attr_const(const ir_node *node) {
 /**
  * Returns the argument register requirements of a mips node.
  */
-const arch_register_req_t **get_mips_in_req_all(const ir_node *node) {
+const arch_register_req_t **get_mips_in_req_all(const ir_node *node)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
        return attr->in_req;
 }
@@ -252,7 +253,8 @@ const arch_register_req_t **get_mips_in_req_all(const ir_node *node) {
 /**
  * Returns the result register requirements of an mips node.
  */
-const arch_register_req_t **get_mips_out_req_all(const ir_node *node) {
+const arch_register_req_t **get_mips_out_req_all(const ir_node *node)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
        return attr->out_req;
 }
@@ -260,7 +262,8 @@ const arch_register_req_t **get_mips_out_req_all(const ir_node *node) {
 /**
  * Returns the argument register requirement at position pos of an mips node.
  */
-const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
        return attr->in_req[pos];
 }
@@ -268,7 +271,8 @@ const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos) {
 /**
  * Returns the result register requirement at position pos of an mips node.
  */
-const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
        return attr->out_req[pos];
 }
@@ -276,7 +280,8 @@ const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos) {
 /**
  * Sets the OUT register requirements at position pos.
  */
-void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
+void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos)
+{
        mips_attr_t *attr   = get_mips_attr(node);
        attr->out_req[pos] = req;
 }
@@ -284,7 +289,8 @@ void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
 /**
  * Sets the IN register requirements at position pos.
  */
-void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
+void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos)
+{
        mips_attr_t *attr  = get_mips_attr(node);
        attr->in_req[pos] = req;
 }
@@ -292,7 +298,8 @@ void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
 /**
  * Returns the register flag of an mips node.
  */
-arch_irn_flags_t get_mips_flags(const ir_node *node) {
+arch_irn_flags_t get_mips_flags(const ir_node *node)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
        return attr->flags;
 }
@@ -300,7 +307,8 @@ arch_irn_flags_t get_mips_flags(const ir_node *node) {
 /**
  * Sets the register flag of an mips node.
  */
-void set_mips_flags(ir_node *node, arch_irn_flags_t flags) {
+void set_mips_flags(ir_node *node, arch_irn_flags_t flags)
+{
        mips_attr_t *attr = get_mips_attr(node);
        attr->flags      = flags;
 }
@@ -308,7 +316,8 @@ void set_mips_flags(ir_node *node, arch_irn_flags_t flags) {
 /**
  * Returns the result register slots of an mips node.
  */
-const arch_register_t **get_mips_slots(const ir_node *node) {
+const arch_register_t **get_mips_slots(const ir_node *node)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
        return attr->slots;
 }
@@ -316,7 +325,8 @@ const arch_register_t **get_mips_slots(const ir_node *node) {
 /**
  * Returns the name of the OUT register at position pos.
  */
-const char *get_mips_out_reg_name(const ir_node *node, int pos) {
+const char *get_mips_out_reg_name(const ir_node *node, int pos)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
 
        assert(is_mips_irn(node) && "Not an mips node.");
@@ -329,7 +339,8 @@ const char *get_mips_out_reg_name(const ir_node *node, int pos) {
 /**
  * Returns the index of the OUT register at position pos within its register class.
  */
-int get_mips_out_regnr(const ir_node *node, int pos) {
+int get_mips_out_regnr(const ir_node *node, int pos)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
 
        assert(is_mips_irn(node) && "Not an mips node.");
@@ -342,7 +353,8 @@ int get_mips_out_regnr(const ir_node *node, int pos) {
 /**
  * Returns the OUT register at position pos.
  */
-const arch_register_t *get_mips_out_reg(const ir_node *node, int pos) {
+const arch_register_t *get_mips_out_reg(const ir_node *node, int pos)
+{
        const mips_attr_t *attr = get_mips_attr_const(node);
 
        assert(is_mips_irn(node) && "Not an mips node.");
@@ -352,22 +364,14 @@ const arch_register_t *get_mips_out_reg(const ir_node *node, int pos) {
        return attr->slots[pos];
 }
 
-/**
- * Returns the number of results.
- */
-int get_mips_n_res(const ir_node *node) {
-       const mips_attr_t *attr = get_mips_attr_const(node);
-       return ARR_LEN(attr->slots);
-}
-
 /**
  * Initializes the nodes attributes.
  */
-void init_mips_attributes(ir_node *node, arch_irn_flags_t flags,
-                          const arch_register_req_t **in_reqs,
-                          const arch_register_req_t **out_reqs,
-                          const be_execution_unit_t ***execution_units,
-                          int n_res, unsigned latency)
+static void init_mips_attributes(ir_node *node, arch_irn_flags_t flags,
+                                 const arch_register_req_t **in_reqs,
+                                 const arch_register_req_t **out_reqs,
+                                 const be_execution_unit_t ***execution_units,
+                                 int n_res, unsigned latency)
 {
        ir_graph       *irg  = get_irn_irg(node);
        struct obstack *obst = get_irg_obstack(irg);
@@ -383,18 +387,30 @@ void init_mips_attributes(ir_node *node, arch_irn_flags_t flags,
        memset(attr->slots, 0, n_res * sizeof(attr->slots[0]));
 }
 
-static
-int mips_compare_attr(ir_node *node_a, ir_node *node_b)
+static void init_mips_immediate_attributes(ir_node *node,
+                                           mips_immediate_type_t type,
+                                           ir_entity *entity, long val)
+{
+       mips_immediate_attr_t *attr = get_irn_generic_attr(node);
+
+       attr->imm_type = type;
+       attr->entity   = entity;
+       attr->val      = val;
+}
+
+static void init_mips_load_store_attributes(ir_node *node, ir_entity *entity,
+                                            long offset)
+{
+       mips_load_store_attr_t *attr = get_irn_generic_attr(node);
+       attr->stack_entity = entity;
+       attr->offset       = offset;
+}
+
+static int mips_compare_nodes_attr(ir_node *node_a, ir_node *node_b)
 {
        const mips_attr_t *a = get_mips_attr_const(node_a);
        const mips_attr_t *b = get_mips_attr_const(node_b);
 
-       if(a->tv != b->tv)
-               return 1;
-       if(a->symconst != b->symconst)
-               return 1;
-       if(a->stack_entity != b->stack_entity)
-               return 1;
        if(a->flags != b->flags)
                return 1;
        if(ARR_LEN(a->slots) != ARR_LEN(b->slots))
@@ -405,86 +421,47 @@ int mips_compare_attr(ir_node *node_a, ir_node *node_b)
        return 0;
 }
 
-/************************************************************************
- *  ___ _____     _     _ _
- * |_ _|  ___|__ | | __| (_)_ __   __ _
- *  | || |_ / _ \| |/ _` | | '_ \ / _` |
- *  | ||  _| (_) | | (_| | | | | | (_| |
- * |___|_|  \___/|_|\__,_|_|_| |_|\__, |
- *                                |___/
- ************************************************************************/
-
-#if 0
-// test if a tarval can be expressed in a 16bit immediate value
-static int is_tarval_16(ir_node* node)
+static int mips_compare_immediate_attr(ir_node *node_a, ir_node *node_b)
 {
-       mips_attr_t *attr = get_mips_attr(node);
-       tarval* tv = attr->tv;
-       long val = get_tarval_long(tv);
-       if(get_mode_sign(get_irn_mode(node))) {
-               if(val < -32768 || val > 32767)
-                       return 0;
-       } else {
-               unsigned long uval = (unsigned long) val;
-               if(uval > 65536)
-                       return 0;
-       }
+       const mips_immediate_attr_t *a = get_mips_immediate_attr_const(node_a);
+       const mips_immediate_attr_t *b = get_mips_immediate_attr_const(node_b);
 
-       return 1;
+       if(a->attr.flags != b->attr.flags)
+               return 1;
+       if(a->val != b->val)
+               return 1;
+
+       return 0;
 }
 
-#define MIPS_MAKE_IFOLDING_TRANSFORM(srcnode, inode, commutative)      \
-ir_node *mips_transform_##srcnode(ir_node* node)                               \
-{                                                                                                                              \
-       ir_node* op1 = get_irn_n(node, 0);                                                      \
-       ir_node* op2 = get_irn_n(node, 1);                                                      \
-       ir_node* result;                                                                                        \
-       if(op1 == NULL || op2 == NULL)                                                          \
-               return node;                                                                                    \
-                                                                                                                               \
-       if((is_mips_lli(op2) || is_mips_lui(op2)) && is_tarval_16(op2)) {       \
-               mips_attr_t *attr, *op_attr = get_mips_attr(op2);               \
-               long val = get_tarval_long(op_attr->tv);                                \
-               result = new_rd_mips_##inode(get_irn_dbg_info(node), get_irn_irg(node), get_nodes_block(node),  \
-                       op1);                                                                       \
-               attr = get_mips_attr(result);                                                   \
-               attr->tv = new_tarval_from_long(val, get_mode_sign(get_irn_mode(node)) ? mode_Hs : mode_Hu);    \
-               return result;                                                                                  \
-       }                                                                                                                       \
-                                                                                                                               \
-       if(commutative && (is_mips_lli(op1) || is_mips_lui(op1)) && is_tarval_16(op1)) {        \
-               mips_attr_t *attr, *op_attr = get_mips_attr(op1);       \
-               long val = get_tarval_long(op_attr->tv);                                \
-               result = new_rd_mips_##inode(get_irn_dbg_info(node), get_irn_irg(node), get_nodes_block(node),  \
-                       op2);                                                                       \
-               attr = get_mips_attr(result);                                                   \
-               attr->tv = new_tarval_from_long(val, get_mode_sign(get_irn_mode(node)) ? mode_Hs : mode_Hu);    \
-               return result;                                                                                  \
-       }                                                                                                                       \
-                                                                                                                               \
-       return node;                                                                                            \
+static int mips_compare_load_store_attr(ir_node *node_a, ir_node *node_b)
+{
+       const mips_load_store_attr_t *a = get_mips_load_store_attr_const(node_a);
+       const mips_load_store_attr_t *b = get_mips_load_store_attr_const(node_b);
+
+       if(mips_compare_nodes_attr(node_a, node_b))
+               return 1;
+       if(a->stack_entity != b->stack_entity)
+               return 1;
+       if(a->offset != b->offset)
+               return 1;
+
+       return 0;
 }
 
-MIPS_MAKE_IFOLDING_TRANSFORM(addu, addiu, 1)
-MIPS_MAKE_IFOLDING_TRANSFORM(and, andi, 1)
-MIPS_MAKE_IFOLDING_TRANSFORM(or, ori, 1)
-MIPS_MAKE_IFOLDING_TRANSFORM(sra, srai, 0)
-MIPS_MAKE_IFOLDING_TRANSFORM(xor, xori, 1)
-MIPS_MAKE_IFOLDING_TRANSFORM(sl, sli, 0)
-MIPS_MAKE_IFOLDING_TRANSFORM(sr, sri, 0)
-MIPS_MAKE_IFOLDING_TRANSFORM(slt, slti, 0)
-
-void mips_init_opcode_transforms(void) {
-       op_mips_addu->ops.transform_node = mips_transform_addu;
-       op_mips_and->ops.transform_node = mips_transform_and;
-       op_mips_or->ops.transform_node  = mips_transform_or;
-       op_mips_sra->ops.transform_node = mips_transform_sra;
-       op_mips_xor->ops.transform_node = mips_transform_xor;
-       op_mips_sl->ops.transform_node  = mips_transform_sl;
-       op_mips_sr->ops.transform_node  = mips_transform_sr;
-       op_mips_slt->ops.transform_node = mips_transform_slt;
+static void mips_copy_attr(const ir_node *old_node , ir_node *new_node)
+{
+       ir_graph          *irg      = get_irn_irg(new_node);
+       struct obstack    *obst     = get_irg_obstack(irg);
+       const mips_attr_t *attr_old = get_mips_attr_const(old_node);
+       mips_attr_t       *attr_new = get_mips_attr(new_node);
+
+       /* copy the attributes */
+       memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
+
+       /* copy register assignments */
+       attr_new->slots = DUP_ARR_D(arch_register_t*, obst, attr_old->slots);
 }
-#endif
 
 /***************************************************************************************
  *                  _                            _                   _
index 91497f6..ef7c7b3 100644 (file)
  */
 mips_attr_t *get_mips_attr(ir_node *node);
 const mips_attr_t *get_mips_attr_const(const ir_node *node);
+const mips_immediate_attr_t *get_mips_immediate_attr_const(const ir_node *node);
+const mips_load_store_attr_t *get_mips_load_store_attr_const(
+               const ir_node *node);
+
 /**
  * Returns the argument register requirements of an mips node.
  */
@@ -104,24 +108,6 @@ int get_mips_out_regnr(const ir_node *node, int pos);
  */
 const arch_register_t *get_mips_out_reg(const ir_node *node, int pos);
 
-/**
- * Returns the number of results.
- */
-int get_mips_n_res(const ir_node *node);
-
-
-/**
- * Initializes the nodes attributes.
- */
-void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, const arch_register_req_t **in_reqs,
-        const arch_register_req_t **out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency);
-
-/**
- * Initialize transform ops for the mips opcodes
- */
-void mips_init_opcode_transforms(void);
-
-
 /* Include the generated headers */
 #include "gen_mips_new_nodes.h"
 
index eae48cd..37f78a7 100644 (file)
 
 #include "../bearch_t.h"
 #include "irmode_t.h"
+#include "irnode_t.h"
 
-typedef struct _mips_attr_t {
+typedef struct mips_attr_t {
+       except_attr  exc;               /**< the exception attribute. MUST be the first one. */
        arch_irn_flags_t flags;     /**< indicating if spillable, rematerializeable ... etc. */
 
-       tarval          *tv;        /**< contains the immediate value */
-       ir_entity       *symconst;
-
-       ir_mode *original_mode;         /**< contains the original mode of the node */
-       ir_entity *stack_entity;        /**< contains the entity on the stack for a load/store mode */
        int switch_default_pn;          /**< proj number of default case in switch */
 
        const arch_register_req_t **in_req;  /**< register requirements for arguments */
@@ -45,4 +42,23 @@ typedef struct _mips_attr_t {
        const arch_register_t **slots;     /**< register slots for assigned registers */
 } mips_attr_t;
 
+typedef enum mips_immediate_type_t {
+       MIPS_IMM_CONST,
+       MIPS_IMM_SYMCONST_LO,
+       MIPS_IMM_SYMCONST_HI
+} mips_immediate_type_t;
+
+typedef struct mips_immediate_attr_t {
+       mips_attr_t            attr;
+       mips_immediate_type_t  imm_type;
+       ir_entity             *entity;
+       long                   val;
+} mips_immediate_attr_t;
+
+typedef struct mips_load_store_attr_t {
+       mips_attr_t  attr;
+       ir_entity   *stack_entity;
+       long         offset;
+} mips_load_store_attr_t;
+
 #endif
index 645bea1..5ab8ca6 100644 (file)
@@ -208,8 +208,7 @@ int mips_to_appear_in_schedule(void *block_env, const ir_node *node)
 
        if(!is_mips_irn(node))
                return -1;
-
-       if(is_mips_zero(node))
+       if(is_mips_zero(node) || is_mips_Immediate(node))
                return 0;
 
        return 1;
index 61664c4..e93e2be 100644 (file)
@@ -121,23 +121,47 @@ $new_emit_syntax = 1;
                { name => "sp", type => 4 }, # stack pointer
                { name => "fp", type => 4 }, # frame pointer
                { name => "ra", type => 2+1 }, # return address
+               { name => "gp_NOREG", realname => "!NOREG_INVALID!", type => 4 | 8 | 16 }, #dummy register for immediate nodes
                { mode => "mode_Iu" }
        ],
 ); # %reg_classes
 
 %emit_templates = (
-    S0 => "${arch}_emit_source_register(env, node, 0);",
-    S1 => "${arch}_emit_source_register(env, node, 1);",
-    S2 => "${arch}_emit_source_register(env, node, 2);",
-    D0 => "${arch}_emit_dest_register(env, node, 0);",
-    D1 => "${arch}_emit_dest_register(env, node, 1);",
-    D2 => "${arch}_emit_dest_register(env, node, 2);",
-       C  => "${arch}_emit_immediate(env, node);",
+    S0  => "${arch}_emit_source_register(env, node, 0);",
+    S1  => "${arch}_emit_source_register(env, node, 1);",
+    S2  => "${arch}_emit_source_register(env, node, 2);",
+       SI1 => "${arch}_emit_source_register_or_immediate(env, node, 1);",
+    D0  => "${arch}_emit_dest_register(env, node, 0);",
+    D1  => "${arch}_emit_dest_register(env, node, 1);",
+    D2  => "${arch}_emit_dest_register(env, node, 2);",
+       A0  => "${arch}_emit_load_store_address(env, node, 0);",
+       I   => "${arch}_emit_immediate_suffix(env, node, 1);",
+       C   => "${arch}_emit_immediate(env, node);",
        JumpTarget => "${arch}_emit_jump_target(env, node);",
        JumpTarget1 => "${arch}_emit_jump_target_proj(env, node, 1);",
        JumpOrFallthrough => "${arch}_emit_jump_or_fallthrough(env, node, 0);",
 );
 
+$default_attr_type = "mips_attr_t";
+$default_copy_attr = "mips_copy_attr";
+
+$mode_gp = "mode_Iu";
+
+%init_attr = (
+       mips_attr_t            => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
+
+       mips_immediate_attr_t  => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
+                                "\tinit_mips_immediate_attributes(res, imm_type, entity, val);",
+
+       mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
+                                "\tinit_mips_load_store_attributes(res, entity, offset);",
+);
+
+%compare_attr = (
+       mips_attr_t            => "mips_compare_nodes_attr",
+       mips_immediate_attr_t  => "mips_compare_immediate_attr",
+       mips_load_store_attr_t => "mips_compare_load_store_attr",
+);
 
 #--------------------------------------------------#
 #                        _                         #
@@ -152,6 +176,16 @@ $new_emit_syntax = 1;
 
 %nodes = (
 
+Immediate => {
+       state     => "pinned",
+       op_flags  => "c",
+       irn_flags => "I",
+       reg_req   => { out => [ "gp_NOREG" ] },
+       attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
+       attr_type => "mips_immediate_attr_t",
+       mode      => $mode_gp,
+},
+
 #-----------------------------------------------------------------#
 #  _       _                                         _            #
 # (_)     | |                                       | |           #
@@ -166,210 +200,146 @@ $new_emit_syntax = 1;
 # commutative operations
 
 addu => {
-       op_flags  => "C",
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '. addu %D0, %S0, %S1',
-       mode      => "mode_Iu",
-},
-
-addiu => {
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. addiu %D0, %S0, %C',
-       cmp_attr  => 'return attr_a->tv != attr_b->tv;',
-       mode      => "mode_Iu",
+       ins       => [ "left", "right" ],
+       emit      => '. add%I%.u %D0, %S0, %SI1',
+       mode      => $mode_gp,
 },
 
 and => {
-       op_flags  => "C",
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '. and %D0, %S0, %S1',
-       mode      => "mode_Iu",
-},
-
-andi => {
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. andi %D0, %S0, %C',
-       cmp_attr  => 'return attr_a->tv != attr_b->tv;',
-       mode      => "mode_Iu",
+       ins       => [ "left", "right" ],
+       emit      => '. and%I %D0, %S0, %SI1',
+       mode      => $mode_gp,
 },
 
 div => {
-       reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
+       reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
+       ins       => [ "left", "right" ],
+       outs      => [ "lohi", "M" ],
        emit      => '. div %S0, %S1',
        mode      => "mode_M",
 },
 
 divu => {
-       reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
+       reg_req   => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
+       ins       => [ "left", "right" ],
+       outs      => [ "lohi", "M" ],
        emit      => '. divu %S0, %S1',
        mode      => "mode_M",
 },
 
 mult => {
-       op_flags  => "C",
        reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
+       ins       => [ "left", "right" ],
        emit      => '. mult %S0, %S1',
        mode      => "mode_M"
 },
 
 multu => {
-       op_flags  => "C",
        reg_req   => { in => [ "gp", "gp" ], out => [ "none" ] },
+       ins       => [ "left", "right" ],
        emit      => '. multu %S0, %S1',
        mode      => "mode_M",
 },
 
 nor => {
-       op_flags  => "C",
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '. nor %D0, %S0, %S1',
-       mode      => "mode_Iu"
-},
-
-not => {
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. nor %D0, %S0, $zero',
-       mode      => "mode_Iu"
+       emit      => '. nor%I %D0, %S0, %SI1',
+       mode      => $mode_gp
 },
 
 or => {
-       op_flags  => "C",
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '. or %D0, %S0, %S1',
-       mode      => "mode_Iu"
-},
-
-ori => {
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. ori %D0, %S0, %C',
-       cmp_attr  => 'return attr_a->tv != attr_b->tv;',
-       mode      => "mode_Iu"
+       ins       => [ "left", "right" ],
+       emit      => '. or%I %D0, %S0, %SI1',
+       mode      => $mode_gp
 },
 
-sl => {
+sll => {
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '
-       if (mode_is_signed(get_irn_mode(node))) {
-               . sal %D0, %S0, %S1
-       } else {
-               . sll %D0, %S0, %S1
-       }
-',
-       mode      => "mode_Iu",
-},
-
-sli => {
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '
-       if (mode_is_signed(get_irn_mode(node))) {
-               . sal %D0, %S0, %C
-       } else {
-               . sll %D0, %S0, %C
-       }
-',
-       mode      => "mode_Iu",
+       ins       => [ "left", "right" ],
+       emit      => '. sll %D0, %S0, %SI1',
+       mode      => $mode_gp,
 },
 
 sra => {
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '. sra %D0, %S0, %S1',
-       mode      => "mode_Iu"
-},
-
-srai => {
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. sra %D0, %S0, %C',
-       cmp_attr  => 'return attr_a->tv != attr_b->tv;',
-       mode      => "mode_Iu",
-},
-
-sr => {
-       reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '
-       if (mode_is_signed(get_irn_mode(node))) {
-               . sra %D0, %S0, %S1
-       } else {
-               . srl %D0, %S0, %S1
-       }
-',
-       mode      => "mode_Iu",
-},
-
-sri => {
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '
-       if (mode_is_signed(get_irn_mode(node))) {
-               . sra %D0, %S0, %C
-       } else {
-               . srl %D0, %S0, %C
-       }
-',
-       mode      => "mode_Iu"
-},
-
-srlv => {
-       reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '. srlv %D0, %S0, %S1',
-       mode      => "mode_Iu"
+       ins       => [ "left", "right" ],
+       emit      => '. sra %D0, %S0, %SI1',
+       mode      => $mode_gp
 },
 
-sllv => {
+srl => {
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '. sllv %D0, %S0, %S1',
-       mode      => "mode_Iu"
+       ins       => [ "left", "right" ],
+       emit      => '. srl %D0, %S0, %SI1',
+       mode      => $mode_gp,
 },
 
-sub => {
+subu => {
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+       ins       => [ "left", "right" ],
        emit      => '. subu %D0, %S0, %S1',
-       mode      => "mode_Iu"
-},
-
-subuzero => {
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. subu %D0, $zero, %S0',
-       mode      => "mode_Iu",
+       mode      => $mode_gp
 },
 
 xor => {
+       op_flags  => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit      => '. xor %D0, %S0, %S1',
-       mode      => "mode_Iu",
+       ins       => [ "left", "right" ],
+       emit      => '. xor%I %D0, %S0, %SI1',
+       mode      => $mode_gp,
 },
 
-xori => {
+seb => {
+       op_flags  => "R",
        reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. xori %D0, %S0, %C',
-       cmp_attr  => 'return attr_a->tv != attr_b->tv;',
-       mode      => "mode_Iu",
+       ins       => [ "val" ],
+       emit      => '.seb %D0, %S0',
+       mode      => $mode_gp,
 },
 
-#   ____                _              _
-#  / ___|___  _ __  ___| |_ __ _ _ __ | |_ ___
-# | |   / _ \| '_ \/ __| __/ _` | '_ \| __/ __|
-# | |__| (_) | | | \__ \ || (_| | | | | |_\__ \
-#  \____\___/|_| |_|___/\__\__,_|_| |_|\__|___/
-#
+seh => {
+       op_flags  => "R",
+       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
+       ins       => [ "val" ],
+       emit      => '.seh %D0, %S0',
+       mode      => $mode_gp,
+},
 
-# load upper imediate
 lui => {
        op_flags  => "c",
+       irn_flags => "R",
        reg_req   => { out => [ "gp" ] },
-       emit      => '. lui %D0, %C',
-       cmp_attr  => 'return attr_a->tv != attr_b->tv;',
-       mode      => "mode_Iu",
+       emit      => '.lui %D0, %C',
+       attr_type => "mips_immediate_attr_t",
+       attr      => "mips_immediate_type_t imm_type, ir_entity *entity, long val",
+       mode      => $mode_gp,
 },
 
 mflo => {
+       irn_flags => "R",
        reg_req   => { in => [ "none" ], out => [ "gp" ] },
+       ins       => [ "lohi" ],
        emit      => '. mflo %D0',
-       mode      => "mode_Iu"
+       mode      => $mode_gp
 },
 
 mfhi => {
+       irn_flags => "R",
        reg_req   => { in => [ "none" ], out => [ "gp" ] },
+       ins       => [ "lohi" ],
        emit      => '. mfhi %D0',
-       mode      => "mode_Iu"
+       mode      => $mode_gp
 },
 
 zero => {
@@ -378,7 +348,7 @@ zero => {
        irn_flags => "I",
        reg_req   => { out => [ "zero" ] },
        emit      => '',
-       mode      => "mode_Iu"
+       mode      => $mode_gp
 },
 
 #
@@ -391,27 +361,17 @@ zero => {
 #
 
 slt => {
+       op_flags => "R",
        reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit    => '. slt %D0, %S0, %S1',
-       mode    => "mode_Iu",
+       emit    => '. slt%I %D0, %S0, %SI1',
+       mode    => $mode_gp,
 },
 
 sltu => {
-       reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit    => '. sltu %D0, %S0, %S1',
-       mode    => "mode_Iu",
-},
-
-slti => {
-       reg_req => { in => [ "gp" ], out => [ "gp" ] },
-       emit    => '. slti %D0, %S0, %C',
-       mode    => "mode_Iu",
-},
-
-sltiu => {
-       reg_req => { in => [ "gp" ], out => [ "gp" ] },
-       emit    => '. slti %D0, %S0, %C',
-       mode    => "mode_Iu",
+       op_flags => "R",
+       reg_req  => { in => [ "gp", "gp" ], out => [ "gp" ] },
+       emit     => '. slt%I%.u %D0, %S0, %SI1',
+       mode     => $mode_gp,
 },
 
 beq => {
@@ -474,73 +434,91 @@ SwitchJump => {
 #
 
 lw => {
-       op_flags => "L|F",
-       state    => "exc_pinned",
-       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
-       outs     => [ "res", "M" ],
-       emit     => '. lw %D0, %C(%S1)',
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
+       emit      => '. lw %D0, %A0',
+       attr_type => "mips_load_store_attr_t",
+       attr      => "ir_entity *entity, long offset",
 },
 
 lh => {
-       op_flags => "L|F",
-       state    => "exc_pinned",
-       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
-       outs     => [ "res", "M" ],
-       emit     => '. lh %D0, %C(%S1)',
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
+       emit      => '. lh %D0, %A0',
+       attr_type => "mips_load_store_attr_t",
+       attr      => "ir_entity *entity, long offset",
 },
 
 lhu => {
-       op_flags => "L|F",
-       state    => "exc_pinned",
-       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
-       outs     => [ "res", "M" ],
-       emit     => '. lhu %D0, %C(%S1)',
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
+       emit      => '. lhu %D0, %A0',
+       attr_type => "mips_load_store_attr_t",
+       attr      => "ir_entity *entity, long offset",
 },
 
 lb => {
-       op_flags => "L|F",
-       state    => "exc_pinned",
-       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
-       outs     => [ "res", "M" ],
-       emit     => '. lb %D0, %C(%S1)',
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
+       emit      => '. lb %D0, %A0',
+       attr_type => "mips_load_store_attr_t",
+       attr      => "ir_entity *entity, long offset",
 },
 
 lbu => {
-       op_flags => "L|F",
-       state    => "exc_pinned",
-       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
-       outs     => [ "res", "M" ],
-       emit     => '. lbu %D0, %C(%S1)',
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
+       ins       => [ "ptr", "mem" ],
+       outs      => [ "res", "M" ],
+       emit      => '. lbu %D0, %A0',
+       attr_type => "mips_load_store_attr_t",
+       attr      => "ir_entity *entity, long offset",
 },
 
 sw => {
-       op_flags => "L|F",
-       state    => "exc_pinned",
-       reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
-       emit     => '. sw %S2, %C(%S1)',
-       mode     => 'mode_M',
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       ins       => [ "ptr", "val", "mem" ],
+       emit      => '. sw %S1, %A0',
+       mode      => 'mode_M',
+       attr_type => "mips_load_store_attr_t",
+       attr      => "ir_entity *entity, long offset",
 },
 
 sh => {
-       op_flags => "L|F",
-       state    => "exc_pinned",
-       reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
-       emit     => '. sh %S2, %C(%S1)',
-       mode     => 'mode_M',
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       ins       => [ "ptr", "val", "mem" ],
+       emit      => '. sh %S1, %A0',
+       mode      => 'mode_M',
+       attr_type => "mips_load_store_attr_t",
+       attr      => "ir_entity *entity, long offset",
 },
 
 sb => {
-       op_flags => "L|F",
-       state    => "exc_pinned",
-       reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
-       emit     => '. sb %S2, %C(%S1)',
-       mode     => 'mode_M',
-},
-
-move => {
-       reg_req  => { in => [ "gp" ], out => [ "gp" ] },
-       emit     => '. move %D0, %S0',
-       mode     => "mode_Iu"
+       op_flags  => "L|F",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       ins       => [ "ptr", "val", "mem" ],
+       emit      => '. sb %S1, %A0',
+       mode      => 'mode_M',
+       attr_type => "mips_load_store_attr_t",
+       attr      => "ir_entity *entity, long offset",
 },
 
 #
index 4db5dd9..7c8b9eb 100644 (file)
@@ -36,6 +36,8 @@
 #include "iredges.h"
 #include "irvrfy.h"
 #include "ircons.h"
+#include "irprintf.h"
+#include "irop.h"
 #include "dbginfo.h"
 #include "iropt_t.h"
 #include "debug.h"
@@ -46,6 +48,7 @@
 #include "../besched.h"
 #include "../besched_t.h"
 #include "../beirg_t.h"
+#include "../betranshlp.h"
 #include "bearch_mips_t.h"
 
 #include "mips_nodes_attr.h"
@@ -58,6 +61,9 @@
 
 #include "gen_mips_regalloc_if.h"
 
+/** hold the current code generator during transformation */
+static mips_code_gen_t *env_cg = NULL;
+
 /****************************************************************************************************
  *                  _        _                        __                           _   _
  *                 | |      | |                      / _|                         | | (_)
  *
  ****************************************************************************************************/
 
-#define MIPS_GENBINFUNC(mips_nodetype)                                                                                                                 \
-       static ir_node* mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op1, ir_node *op2) {\
-               ASSERT_NO_FLOAT(env->mode);                                                                                                                             \
-               /*assert(get_irn_mode(op1) == get_irn_mode(op2));*/                                                                             \
-               /*assert(get_irn_mode(op1) == env->mode);*/                                                                                             \
-               assert(get_mode_size_bits(env->mode) == 32);                                                                                    \
-               return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op1, op2);           \
-       }
+typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
+       ir_node *block, ir_node *left, ir_node *right);
 
-MIPS_GENBINFUNC(addu)
-MIPS_GENBINFUNC(sub)
-MIPS_GENBINFUNC(and)
-MIPS_GENBINFUNC(or)
-MIPS_GENBINFUNC(xor)
-MIPS_GENBINFUNC(sl)
-MIPS_GENBINFUNC(sr)
-MIPS_GENBINFUNC(sra)
-
-#define MIPS_GENUNFUNC(mips_nodetype)                                                                                                                  \
-       static ir_node *mips_gen_##mips_nodetype(mips_transform_env_t *env, ir_node *op) {                      \
-               ASSERT_NO_FLOAT(env->mode);                                                                                                                             \
-               assert(get_irn_mode(op) == env->mode);                                                                                                  \
-               assert(get_mode_size_bits(env->mode) == 32);                                                                                    \
-               return new_rd_mips_##mips_nodetype(env->dbg, env->irg, env->block, op);                     \
-       }
+static INLINE int mode_needs_gp_reg(ir_mode *mode) {
+       return mode_is_int(mode) || mode_is_character(mode)
+               || mode_is_reference(mode);
+}
 
-MIPS_GENUNFUNC(not)
+ir_node *mips_create_Immediate(long val)
+{
+       ir_graph *irg   = current_ir_graph;
+       ir_node  *block = get_irg_start_block(irg);
+       const arch_register_t **slots;
+       ir_node  *res;
 
-static
-ir_node* gen_zero(mips_transform_env_t *env)
+       assert(val >=  -32768 && val <= 32767);
+       res      = new_rd_mips_Immediate(NULL, irg, block, MIPS_IMM_CONST, NULL,
+                                        val);
+       slots    = get_mips_slots(res);
+       slots[0] = &mips_gp_regs[REG_GP_NOREG];
+
+       return res;
+}
+
+ir_node* mips_create_zero(void)
 {
-       ir_graph *irg   = env->irg;
+       ir_graph *irg   = current_ir_graph;
        ir_node  *block = get_irg_start_block(irg);
        ir_node  *zero  = new_rd_mips_zero(NULL, irg, block);
+       const arch_register_t **slots = get_mips_slots(zero);
 
-       arch_set_irn_register(env->cg->arch_env, zero, &mips_gp_regs[REG_ZERO]);
+       slots[0] = &mips_gp_regs[REG_ZERO];
 
        return zero;
 }
 
-static
-ir_node* gen_node_for_Const(mips_transform_env_t *env, dbg_info *dbg, ir_graph *irg, ir_node *block, ir_node *constant)
+static ir_node *try_create_Immediate(ir_node *node)
 {
-       tarval* tv = get_Const_tarval(constant);
-       ir_node *upper_node;
-       ir_node *lower_node;
-       mips_attr_t *attr;
-       ir_mode* mode = get_irn_mode(constant);
+       tarval   *tv;
+       long      val;
+       ir_mode  *mode;
+
+       if(!is_Const(node))
+               return NULL;
+
+       mode = get_irn_mode(node);
+       if(!mode_needs_gp_reg(mode))
+               return NULL;
+
+       tv = get_Const_tarval(node);
+       if(tarval_is_long(tv)) {
+               val = get_tarval_long(tv);
+       } else if(tarval_is_null(tv)) {
+               val = 0;
+       } else {
+               ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n",
+                          node);
+               return NULL;
+       }
+
+       if(val < -32768 || val > 32767)
+               return NULL;
+
+       return mips_create_Immediate(val);
+}
+
+static void create_binop_operands(ir_node **new_left, ir_node **new_right,
+                                  ir_node *left, ir_node *right,
+                                  int is_commutative)
+{
+       *new_right = try_create_Immediate(right);
+       if(*new_right != NULL) {
+               *new_left = be_transform_node(left);
+               return;
+       }
+       if(is_commutative) {
+               *new_right = try_create_Immediate(left);
+               if(*new_right != NULL) {
+                       *new_left = be_transform_node(right);
+                       return;
+               }
+       }
+
+       *new_left  = be_transform_node(left);
+       *new_right = be_transform_node(right);
+}
+
+static ir_node *gen_binop(ir_node *node, ir_node *left, ir_node *right,
+                          construct_binop_func func, int supports_immediate)
+{
+       ir_graph *irg   = current_ir_graph;
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_node  *block = be_transform_node(get_nodes_block(node));
+       ir_node  *res;
+       ir_node  *new_left, *new_right;
+
+       assert(mode_needs_gp_reg(get_irn_mode(node)));
+
+       if(supports_immediate) {
+               int is_commutative = is_op_commutative(get_irn_op(node));
+               create_binop_operands(&new_left, &new_right, left, right,
+                                     is_commutative);
+       } else {
+               new_left  = be_transform_node(left);
+               new_right = be_transform_node(right);
+       }
+
+       res = func(dbgi, irg, block, new_left, new_right);
+
+       return res;
+}
+
+static ir_node *gen_Add(ir_node *node)
+{
+       /* TODO: match add(symconst, const) */
+       return gen_binop(node, get_Add_left(node), get_Add_right(node),
+                        new_rd_mips_addu, 1);
+}
+
+static ir_node *gen_Sub(ir_node *node)
+{
+       return gen_binop(node, get_Sub_left(node), get_Sub_right(node),
+                        new_rd_mips_addu, 0);
+}
+
+static ir_node *gen_And(ir_node *node)
+{
+       return gen_binop(node, get_Add_left(node), get_Add_right(node),
+                        new_rd_mips_and, 1);
+}
+
+static ir_node *gen_Or(ir_node *node)
+{
+       return gen_binop(node, get_Add_left(node), get_Add_right(node),
+                        new_rd_mips_or, 1);
+}
+
+static ir_node *gen_Eor(ir_node *node)
+{
+       return gen_binop(node, get_Add_left(node), get_Add_right(node),
+                        new_rd_mips_xor, 1);
+}
+
+static ir_node *gen_Shl(ir_node *node)
+{
+       return gen_binop(node, get_Add_left(node), get_Add_right(node),
+                        new_rd_mips_sll, 1);
+}
+
+static ir_node *gen_Shr(ir_node *node)
+{
+       return gen_binop(node, get_Add_left(node), get_Add_right(node),
+                        new_rd_mips_srl, 1);
+}
+
+static ir_node *gen_Shrs(ir_node *node)
+{
+       return gen_binop(node, get_Add_left(node), get_Add_right(node),
+                        new_rd_mips_sra, 1);
+}
+
+static ir_node *gen_Not(ir_node *node)
+{
+       ir_graph *irg   = current_ir_graph;
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_node  *block = be_transform_node(get_nodes_block(node));
+       ir_node  *op    = get_Not_op(node);
+       ir_node  *new_op;
+       ir_node  *res;
+       ir_node  *one;
+
+       /* we can transform not->or to nor */
+       if(is_Or(op)) {
+               return gen_binop(op, get_Or_left(op), get_Or_right(op),
+                                new_rd_mips_nor, 1);
+       }
+
+       /* construct (op < 1) */
+       one    = mips_create_Immediate(1);
+       new_op = be_transform_node(op);
+       res    = new_rd_mips_sltu(dbgi, irg, block, new_op, one);
+
+       return res;
+}
+
+static ir_node *gen_Minus(ir_node *node)
+{
+       ir_graph *irg    = current_ir_graph;
+       dbg_info *dbgi   = get_irn_dbg_info(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);
+       ir_node  *res;
+       ir_node  *zero;
+
+       /* construct (0 - op) */
+       zero = mips_create_zero();
+       res  = new_rd_mips_subu(dbgi, irg, block, zero, new_op);
+
+       return res;
+}
+
+static ir_node *gen_Abs(ir_node *node)
+{
+       ir_graph *irg    = current_ir_graph;
+       dbg_info *dbgi   = get_irn_dbg_info(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);
+       ir_node  *sra_const, *sra, *add, *xor;
+
+       /* TODO: support other bit sizes... */
+       assert(get_mode_size_bits(get_irn_mode(node)) == 32);
+       sra_const = mips_create_Immediate(31);
+       sra       = new_rd_mips_sra(dbgi, irg, block, new_op, sra_const);
+       add       = new_rd_mips_addu(dbgi, irg, block, new_op, sra);
+       xor       = new_rd_mips_xor(dbgi, irg, block, sra, add);
+
+       return xor;
+}
+
+static ir_node* gen_Const(ir_node *node)
+{
+       ir_graph *irg   = current_ir_graph;
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_node  *block = be_transform_node(get_nodes_block(node));
+       tarval   *tv    = get_Const_tarval(node);
+       ir_node  *upper_node;
+       ir_node  *lower_node;
+       ir_node  *or_const;
        unsigned long val, lower, upper;
 
+       if(tarval_is_long(tv)) {
+               val = get_tarval_long(tv);
+       } else if(tarval_is_null(tv)) {
+               val = 0;
+       } else {
+               panic("Can't get value of tarval %+F\n", node);
+       }
+
        val = get_tarval_long(tv);
 
        lower = val & 0xffff;
        upper = (val >> 16) & 0xffff;
        if(upper == 0) {
-               upper_node = gen_zero(env);
+               upper_node = mips_create_zero();
        } else {
-               upper_node = new_rd_mips_lui(dbg, irg, block);
-               attr       = get_mips_attr(upper_node);
-               attr->tv   = new_tarval_from_long(val, mode);
+               upper_node = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_CONST, NULL,
+                                            upper);
        }
 
        if(lower == 0)
                return upper_node;
 
-       lower_node = new_rd_mips_ori(dbg, irg, block, upper_node);
-       attr       = get_mips_attr(lower_node);
-       attr->tv   = new_tarval_from_long(lower, mode);
+       or_const   = mips_create_Immediate(lower);
+       lower_node = new_rd_mips_or(dbgi, irg, block, upper_node, or_const);
 
        return lower_node;
 }
 
-static ir_node* exchange_node_for_Const(mips_transform_env_t *env, ir_node* pred, int n) {
-       ir_node *node = env->irn;
-       dbg_info *dbg = get_irn_dbg_info(pred);
-       ir_graph *irg = get_irn_irg(node);
-       ir_node *block;
-
-       if(get_irn_opcode(node) == iro_Phi) {
-               ir_node *phipred = get_nodes_block(node);
-               block = get_Block_cfgpred_block(phipred, n);
-       } else {
-               block = get_nodes_block(node);
-       }
-
-       return gen_node_for_Const(env, dbg, irg, block, pred);
-}
-
-static ir_node* gen_node_for_SymConst(mips_transform_env_t *env, ir_node* pred)
+static ir_node* gen_SymConst(ir_node *node)
 {
-       mips_attr_t *attr;
-       ir_node *node = env->irn;
-       dbg_info *dbg = get_irn_dbg_info(pred);
-       ir_graph *irg = get_irn_irg(node);
-       ir_node *block;
+       ir_graph *irg   = current_ir_graph;
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_node  *block = be_transform_node(get_nodes_block(node));
        ir_entity *entity;
-       ir_node *lui, *ori;
+       ir_node *lui, *or_const, *or;
 
-       block = get_nodes_block(pred);
-
-       if(get_SymConst_kind(pred) != symconst_addr_ent) {
+       if(get_SymConst_kind(node) != symconst_addr_ent) {
                panic("Only address entity symconsts supported in mips backend");
        }
 
-       entity = get_SymConst_entity(pred);
-
-       lui            = new_rd_mips_lui(dbg, irg, block);
-       attr           = get_mips_attr(lui);
-       attr->symconst = entity;
+       entity = get_SymConst_entity(node);
 
-       ori            = new_rd_mips_ori(dbg, irg, block, lui);
-       attr           = get_mips_attr(ori);
-       attr->symconst = entity;
+       lui            = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_SYMCONST_HI,
+                                        entity, 0);
+       or_const       = new_rd_mips_Immediate(dbgi, irg, block,
+                                              MIPS_IMM_SYMCONST_LO, entity, 0);
+       or             = new_rd_mips_or(dbgi, irg, block, lui, or_const);
 
-       return ori;
+       return or;
 }
 
 typedef ir_node* (*gen_load_func) (dbg_info *dbg, ir_graph *irg,
-                                   ir_node *block, ir_node *mem, ir_node *ptr);
+                                   ir_node *block, ir_node *ptr, ir_node *mem,
+                                   ir_entity *entity, long offset);
 
 /**
  * Generates a mips node for a firm Load node
  */
-static ir_node *gen_node_for_Load(mips_transform_env_t *env) {
-       ir_graph *irg    = env->irg;
-       ir_node  *node   = env->irn;
-       dbg_info *dbg    = get_irn_dbg_info(node);
-       ir_node  *block  = get_nodes_block(node);
-       ir_node  *mem    = get_Load_mem(node);
-       ir_node  *ptr    = get_Load_ptr(node);
-       ir_mode  *mode   = get_Load_mode(node);
-       int       sign   = get_mode_sign(mode);
-       ir_node  *result;
+static ir_node *gen_Load(ir_node *node)
+{
+       ir_graph *irg     = current_ir_graph;
+       dbg_info *dbgi    = get_irn_dbg_info(node);
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *mem     = get_Load_mem(node);
+       ir_node  *new_mem = be_transform_node(mem);
+       ir_node  *ptr     = get_Load_ptr(node);
+       ir_node  *new_ptr = be_transform_node(ptr);
+       ir_mode  *mode    = get_Load_mode(node);
+       int       sign    = get_mode_sign(mode);
+       ir_node  *res;
        gen_load_func func;
 
-       ASSERT_NO_FLOAT(get_irn_mode(node));
+       ASSERT_NO_FLOAT(mode);
+       assert(mode_needs_gp_reg(mode));
 
-       assert(mode->vector_elem == 1);
-       assert(mode->sort == irms_int_number || mode->sort == irms_reference);
+       /* TODO: make use of offset in ptrs */
 
        switch(get_mode_size_bits(mode)) {
        case 32:
@@ -222,33 +397,35 @@ static ir_node *gen_node_for_Load(mips_transform_env_t *env) {
                panic("mips backend only support 32, 16, 8 bit loads");
        }
 
-       result = func(dbg, irg, block, mem, ptr);
-       return result;
+       res = func(dbgi, irg, block, new_ptr, new_mem, NULL, 0);
+       set_irn_pinned(res, get_irn_pinned(node));
+
+       return res;
 }
 
 typedef ir_node* (*gen_store_func) (dbg_info *dbg, ir_graph *irg,
-                                    ir_node *block, ir_node *mem, ir_node *ptr,
-                                    ir_node *val);
+                                    ir_node *block, ir_node *ptr, ir_node *val,
+                                    ir_node *mem, ir_entity *ent, long offset);
 
 /**
  * Generates a mips node for a firm Store node
  */
-static ir_node *gen_node_for_Store(mips_transform_env_t *env) {
-       ir_graph    *irg   = env->irg;
-       ir_node     *node  = env->irn;
-       dbg_info    *dbg   = get_irn_dbg_info(node);
-       ir_node     *block = get_nodes_block(node);
-       ir_node     *mem   = get_Store_mem(node);
-       ir_node     *ptr   = get_Store_ptr(node);
-       ir_node     *val   = get_Store_value(node);
-       ir_mode     *mode  = get_irn_mode(val);
+static ir_node *gen_Store(ir_node *node)
+{
+       ir_graph    *irg     = current_ir_graph;
+       dbg_info    *dbgi    = get_irn_dbg_info(node);
+       ir_node     *block   = be_transform_node(get_nodes_block(node));
+       ir_node     *mem     = get_Store_mem(node);
+       ir_node     *new_mem = be_transform_node(mem);
+       ir_node     *ptr     = get_Store_ptr(node);
+       ir_node     *new_ptr = be_transform_node(ptr);
+       ir_node     *val     = get_Store_value(node);
+       ir_node     *new_val = be_transform_node(val);
+       ir_mode     *mode    = get_irn_mode(val);
        gen_store_func func;
-       ir_node     *result;
-
-       ASSERT_NO_FLOAT(mode);
+       ir_node     *res;
 
-       assert(mode->vector_elem == 1);
-       assert(mode->sort == irms_int_number || mode->sort == irms_reference);
+       assert(mode_needs_gp_reg(mode));
 
        switch(get_mode_size_bits(mode)) {
        case 32:
@@ -264,96 +441,150 @@ static ir_node *gen_node_for_Store(mips_transform_env_t *env) {
                panic("store only supported for 32, 16, 8 bit values in mips backend");
        }
 
-       result = func(dbg, irg, block, mem, ptr, val);
-       return result;
-}
+       res = func(dbgi, irg, block, new_ptr, new_val, new_mem, NULL, 0);
+       set_irn_pinned(res, get_irn_pinned(node));
 
-static ir_node *gen_node_for_div_Proj(mips_transform_env_t *env) {
-       ir_node *proj = env->irn;
-       ir_node *new_proj;
-       ir_node *pred = get_irn_n(proj, 0);
-       mips_attr_t *attr;
-       long n;
+       return res;
+}
 
-       n = get_Proj_proj(proj);
+static ir_node *gen_Proj_DivMod(ir_node *node)
+{
+       ir_graph *irg     = current_ir_graph;
+       dbg_info *dbgi    = get_irn_dbg_info(node);
+       ir_node  *block   = be_transform_node(get_nodes_block(node));
+       ir_node  *divmod  = get_Proj_pred(node);
+       ir_node  *new_div = be_transform_node(divmod);
+       long      pn      = get_Proj_proj(node);
+       ir_node  *proj;
 
-       // set the div mode to the DivMod node
-       attr = get_mips_attr(pred);
-       assert(attr->original_mode == NULL || attr->original_mode == env->mode);
-       attr->original_mode = env->mode;
+       assert(is_mips_div(new_div) || is_mips_divu(new_div));
 
-       // we have to construct a new proj here, to avoid circular refs that
-       // happen when we reuse the old one
-       new_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, mode_ANY, 1, &pred);
-       set_Proj_proj(new_proj, n);
+       switch(get_irn_opcode(divmod)) {
+       case iro_Div:
+               switch(pn) {
+               case pn_Div_M:
+                       return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
+                                          pn_mips_div_M);
+               case pn_Div_res:
+                       proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
+                                          pn_mips_div_lohi);
+                       return new_rd_mips_mflo(dbgi, irg, block, proj);
+               default:
+                       break;
+               }
+       case iro_Mod:
+               switch(pn) {
+               case pn_Mod_M:
+                       return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
+                                          pn_mips_div_M);
+               case pn_Mod_res:
+                       proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
+                                          pn_mips_div_lohi);
+                       return new_rd_mips_mfhi(dbgi, irg, block, proj);
+               default:
+                       break;
+               }
 
-       if(n == pn_DivMod_res_div) {
-               return new_rd_mips_mflo(env->dbg, env->irg, env->block, new_proj);
-       } else if(n == pn_DivMod_res_mod) {
-               return new_rd_mips_mfhi(env->dbg, env->irg, env->block, new_proj);
+       case iro_DivMod:
+               switch(pn) {
+               case pn_Div_M:
+                       return new_rd_Proj(dbgi, irg, block, new_div, mode_M,
+                                          pn_mips_div_M);
+               case pn_DivMod_res_div:
+                       proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
+                                          pn_mips_div_lohi);
+                       return new_rd_mips_mflo(dbgi, irg, block, proj);
+               case pn_DivMod_res_mod:
+                       proj = new_rd_Proj(dbgi, irg, block, new_div, mode_M,
+                                          pn_mips_div_lohi);
+                       return new_rd_mips_mfhi(dbgi, irg, block, proj);
+               default:
+                       break;
+               }
+       default:
+               break;
        }
 
-       return proj;
+       panic("invalid proj attached to %+F\n", divmod);
 }
 
-static
-ir_node *gen_node_for_Proj(mips_transform_env_t *env)
+static ir_node *gen_Proj_Start(ir_node *node)
 {
-       ir_node *proj = env->irn;
-       ir_mode *mode = get_irn_mode(proj);
-       ir_node *predecessor = get_Proj_pred(proj);
-
-       // all DivMods, Div, Mod should be replaced by now
-       assert(get_irn_opcode(predecessor) != iro_DivMod);
-       assert(get_irn_opcode(predecessor) != iro_Div);
-       assert(get_irn_opcode(predecessor) != iro_Mod);
-
-       if(is_mips_div(predecessor))
-               return gen_node_for_div_Proj(env);
-
-       if(is_mips_lw(predecessor) || is_mips_lh(predecessor)
-                       || is_mips_lhu(predecessor) || is_mips_lb(predecessor)
-                       || is_mips_lbu(predecessor)) {
-
-               long pn = get_Proj_proj(proj);
-               if(pn == pn_Load_M) {
-                       set_Proj_proj(proj, pn_mips_lw_M);
-               } else if(pn == pn_Load_res) {
-                       set_Proj_proj(proj, pn_mips_lw_res);
-               }
+       ir_graph *irg   = current_ir_graph;
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_node  *block = be_transform_node(get_nodes_block(node));
+       long      pn    = get_Proj_proj(node);
+
+       if(pn == pn_Start_X_initial_exec) {
+               /* we exchange the projx with a jump */
+               ir_node *jump = new_rd_Jmp(dbgi, irg, block);
+               return jump;
        }
-
-#if 0
-       if(get_irn_opcode(predecessor) == iro_Cond) {
-               ir_node *selector = get_Cond_selector(predecessor);
-               ir_mode *mode = get_irn_mode(selector);
-               n = get_Proj_proj(proj);
-
-               if(get_mode_sort(mode) == irms_internal_boolean) {
-                       assert(n == pn_Cond_true || n == pn_Cond_false);
-                       return gen_node_for_Cond_Proj(env, predecessor, n == pn_Cond_true);
-               }
+       if(node == be_get_old_anchor(anchor_tls)) {
+               /* TODO... */
+               return be_duplicate_node(node);
        }
-#endif
+       return be_duplicate_node(node);
+}
+
+static ir_node *gen_Proj(ir_node *node)
+{
+       ir_graph *irg  = current_ir_graph;
+       dbg_info *dbgi = get_irn_dbg_info(node);
+       ir_node  *pred = get_Proj_pred(node);
 
-       if(get_mode_sort(mode) == irms_int_number) {
-               set_irn_mode(proj, mode_Iu);
+       switch(get_irn_opcode(pred)) {
+       case iro_Load:
+               break;
+       case iro_Store:
+               break;
+       case iro_Div:
+       case iro_Mod:
+       case iro_DivMod:
+               return gen_Proj_DivMod(node);
+
+       case iro_Start:
+               return gen_Proj_Start(node);
+
+       default:
+               assert(get_irn_mode(node) != mode_T);
+               if(mode_needs_gp_reg(get_irn_mode(node))) {
+                       ir_node *new_pred = be_transform_node(pred);
+                       ir_node *block    = be_transform_node(get_nodes_block(node));
+                       long     pn       = get_Proj_proj(node);
+
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn);
+               }
+               break;
        }
 
-       return proj;
+       return be_duplicate_node(node);
 }
 
-static
-ir_node *gen_node_for_Phi(mips_transform_env_t *env)
+static ir_node *gen_Phi(ir_node *node)
 {
-       ir_node *node = env->irn;
-       ir_mode *mode = get_irn_mode(node);
-
-       if(get_mode_sort(mode) == irms_int_number) {
-               set_irn_mode(node, mode_Iu);
+       ir_graph *irg   = current_ir_graph;
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_node  *block = be_transform_node(get_nodes_block(node));
+       ir_mode  *mode  = get_irn_mode(node);
+       ir_node  *phi;
+
+       if(mode_needs_gp_reg(mode)) {
+               assert(get_mode_size_bits(mode) <= 32);
+               mode = mode_Iu;
        }
 
-       return node;
+       /* phi nodes allow loops, so we use the old arguments for now
+        * and fix this later */
+       phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
+                         get_irn_in(node) + 1);
+       copy_node_attr(node, phi);
+       be_duplicate_deps(node, phi);
+
+       be_set_transformed_node(node, phi);
+       be_enqueue_preds(node);
+
+       return phi;
 }
 
 #if 0
@@ -459,59 +690,60 @@ ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env)
 }
 #endif
 
-static
-ir_node *gen_node_for_Cond(mips_transform_env_t *env)
+static ir_node *gen_Cond(ir_node *node)
 {
-       ir_graph *irg      = env->irg;
-       ir_node  *node     = env->irn;
-       dbg_info *dbg      = get_irn_dbg_info(node);
-       ir_node  *block    = get_nodes_block(node);
-       ir_node  *sel_proj = get_Cond_selector(node);
-       ir_node  *cmp      = get_Proj_pred(sel_proj);
-       ir_node  *op1, *op2;
+       ir_graph *irg       = current_ir_graph;
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *block     = get_nodes_block(node);
+       ir_node  *sel_proj  = get_Cond_selector(node);
+       ir_node  *cmp       = get_Proj_pred(sel_proj);
+       ir_node  *left      = get_Cmp_left(cmp);
+       ir_node  *new_left  = be_transform_node(left);
+       ir_node  *right     = get_Cmp_right(cmp);
+       ir_node  *new_right = be_transform_node(right);
+       long      pnc       = get_Proj_proj(sel_proj);
        ir_node  *res;
        ir_node  *slt;
        ir_node  *zero;
-       long      pn       = get_Proj_proj(sel_proj);
 
-       op1 = get_Cmp_left(cmp);
-       op2 = get_Cmp_right(cmp);
-       switch(pn) {
+       /* TODO: use blez & co. when possible */
+
+       switch(pnc) {
        case pn_Cmp_False:
        case pn_Cmp_True:
        case pn_Cmp_Leg:
                panic("mips backend can't handle unoptimized constant Cond");
 
        case pn_Cmp_Eq:
-               res = new_rd_mips_beq(dbg, irg, block, op1, op2);
+               res = new_rd_mips_beq(dbgi, irg, block, new_left, new_right);
                break;
 
        case pn_Cmp_Lt:
-               zero = gen_zero(env);
-               slt  = new_rd_mips_slt(dbg, irg, block, op1, op2);
-               res  = new_rd_mips_bne(dbg, irg, block, slt, zero);
+               zero = mips_create_zero();
+               slt  = new_rd_mips_slt(dbgi, irg, block, new_left, new_right);
+               res  = new_rd_mips_bne(dbgi, irg, block, slt, zero);
                break;
 
        case pn_Cmp_Le:
-               zero = gen_zero(env);
-               slt  = new_rd_mips_slt(dbg, irg, block, op2, op1);
-               res  = new_rd_mips_beq(dbg, irg, block, slt, zero);
+               zero = mips_create_zero();
+               slt  = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
+               res  = new_rd_mips_beq(dbgi, irg, block, slt, zero);
                break;
 
        case pn_Cmp_Gt:
-               zero = gen_zero(env);
-               slt  = new_rd_mips_slt(dbg, irg, block, op2, op1);
-               res  = new_rd_mips_bne(dbg, irg, block, slt, zero);
+               zero = mips_create_zero();
+               slt  = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
+               res  = new_rd_mips_bne(dbgi, irg, block, slt, zero);
                break;
 
        case pn_Cmp_Ge:
-               zero = gen_zero(env);
-               slt  = new_rd_mips_slt(dbg, irg, block, op2, op1);
-               res  = new_rd_mips_bne(dbg, irg, block, slt, zero);
+               zero = mips_create_zero();
+               slt  = new_rd_mips_slt(dbgi, irg, block, new_right, new_left);
+               res  = new_rd_mips_bne(dbgi, irg, block, slt, zero);
                break;
 
        case pn_Cmp_Lg:
-               res = new_rd_mips_bne(dbg, irg, block, op1, op2);
+               res = new_rd_mips_bne(dbgi, irg, block, new_left, new_right);
                break;
 
        default:
@@ -521,115 +753,92 @@ ir_node *gen_node_for_Cond(mips_transform_env_t *env)
        return res;
 }
 
-static ir_node *create_conv_and(mips_transform_env_t *env, long immediate) {
-       ir_node *node = env->irn;
-       ir_node *pred;
-       ir_node *result;
-       mips_attr_t *attr;
-
-       pred = get_Conv_op(node);
-       result = new_rd_mips_andi(env->dbg, env->irg, env->block, pred);
-       attr = get_mips_attr(result);
-       attr->tv = new_tarval_from_long(immediate, mode_Iu);
-
-       return result;
-}
-
-static ir_node *gen_node_for_Conv(mips_transform_env_t *env) {
-       ir_node *node = env->irn;
-       ir_node *pred;
-       ir_mode *srcmode;
-       ir_mode *destmode;
-       int dst_size, src_size;
-
-       pred = get_Conv_op(node);
-       srcmode = get_irn_mode(pred);
-       destmode = get_irn_mode(node);
+static ir_node *gen_Conv(ir_node *node)
+{
+       ir_graph *irg      = current_ir_graph;
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *op       = get_Conv_op(node);
+       ir_node  *new_op   = be_transform_node(op);
+       ir_mode  *src_mode = get_irn_mode(op);
+       ir_mode  *dst_mode = get_irn_mode(node);
+       int       src_size = get_mode_size_bits(src_mode);
+       int       dst_size = get_mode_size_bits(dst_mode);
+       ir_node  *res;
 
-       dst_size = get_mode_size_bits(destmode);
-       src_size = get_mode_size_bits(srcmode);
+       assert(mode_needs_gp_reg(src_mode));
+       assert(mode_needs_gp_reg(dst_mode));
 
-       if(src_size == dst_size) {
+       /* we only need to do something on upconvs */
+       if(src_size >= dst_size) {
                /* unnecessary conv */
-               return pred;
+               return new_op;
        }
 
-#if 0
-       if(srcmode->size >= destmode->size) {
-               assert(srcmode->size > destmode->size || srcmode->sign != destmode->sign);
-               return new_rd_mips_reinterpret_conv(env->dbg, env->irg, env->block, pred);
-       }
-#endif
-       if(srcmode->sign) {
-               /* TODO */
+       if(mode_is_signed(src_mode)) {
+               if(src_size == 8) {
+                       res = new_rd_mips_seb(dbgi, irg, block, new_op);
+               } else if(src_size == 16) {
+                       res = new_rd_mips_seh(dbgi, irg, block, new_op);
+               } else {
+                       panic("invalid conv %+F\n", node);
+               }
        } else {
+               ir_node *and_const;
+
                if(src_size == 8) {
-                       return create_conv_and(env, 0xff);
+                       and_const = mips_create_Immediate(0xff);
                } else if(src_size == 16) {
-                       return create_conv_and(env, 0xffff);
+                       and_const = mips_create_Immediate(0xffff);
+               } else {
+                       panic("invalid conv %+F\n", node);
                }
+               res = new_rd_mips_and(dbgi, irg, block, new_op, and_const);
        }
 
-       assert(0);
-       return NULL;
+       return res;
 }
 
-static ir_node *gen_node_mips_div(mips_transform_env_t *env, ir_node* op1, ir_node* op2, long p_div, long p_mod,
-                                                                 long p_m, long p_x)
+static ir_node *create_div(ir_node *node, ir_node *left, ir_node *right,
+                           ir_mode *mode)
 {
-       ir_node *node = env->irn;
-       ir_node *div;
-       const ir_edge_t *edge;
-       ir_mode *mode = get_irn_mode(node);
+       ir_graph *irg       = current_ir_graph;
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *block     = be_transform_node(get_nodes_block(node));
+       ir_node  *new_left  = be_transform_node(left);
+       ir_node  *new_right = be_transform_node(right);
+       ir_node  *res;
 
        if(mode_is_signed(mode)) {
-               div = new_rd_mips_div(env->dbg, env->irg, env->block, op1, op2);
+               res = new_rd_mips_div(dbgi, irg, block, new_left, new_right);
        } else {
-               div = new_rd_mips_divu(env->dbg, env->irg, env->block, op1, op2);
+               res = new_rd_mips_divu(dbgi, irg, block, new_left, new_right);
        }
 
-       // Adjust div projs
-       foreach_out_edge(node, edge) {
-               ir_node *proj = get_edge_src_irn(edge);
-               long n = get_Proj_proj(proj);
-               assert(is_Proj(proj) && "non-Proj from Mod node");
-               if (n == p_div) {
-                       set_Proj_proj(proj, pn_DivMod_res_div);
-               } else if (n == p_mod) {
-                       set_Proj_proj(proj, pn_DivMod_res_mod);
-               } else if(n == p_m) {
-                       set_Proj_proj(proj, pn_DivMod_M);
-               } else if(n == p_x) {
-                       set_Proj_proj(proj, pn_DivMod_X_except);
-               } else {
-                       assert(!"invalid proj");
-               }
-       }
+       set_irn_pinned(res, get_irn_pinned(node));
 
-       return div;
+       return res;
 }
 
-static ir_node *gen_node_for_DivMod(mips_transform_env_t *env) {
-       ir_node *node = env->irn;
-
-       return gen_node_mips_div(env, get_DivMod_left(node), get_DivMod_right(node), pn_DivMod_res_div,
-                                                        pn_DivMod_res_mod, pn_DivMod_M, pn_DivMod_X_except);
+static ir_node *gen_DivMod(ir_node *node)
+{
+       return create_div(node, get_DivMod_left(node), get_DivMod_right(node),
+                         get_DivMod_resmode(node));
 }
 
-static ir_node *gen_node_for_Div(mips_transform_env_t *env) {
-       ir_node *node = env->irn;
-
-       return gen_node_mips_div(env, get_Div_left(node), get_Div_right(node), pn_Div_res, -1,
-                                                        pn_Div_M, pn_Div_X_except);
+static ir_node *gen_Div(ir_node *node)
+{
+       return create_div(node, get_Div_left(node), get_Div_right(node),
+                         get_Div_resmode(node));
 }
 
-static ir_node *gen_node_for_Mod(mips_transform_env_t *env) {
-       ir_node *node = env->irn;
-
-       return gen_node_mips_div(env, get_Mod_left(node), get_Mod_right(node), -1, pn_Mod_res,
-                                                        pn_Mod_M, pn_Mod_X_except);
+static ir_node *gen_Mod(ir_node *node)
+{
+       return create_div(node, get_Mod_left(node), get_Mod_right(node),
+                         get_Mod_resmode(node));
 }
 
+#if 0
 static ir_node *gen_node_for_Mul(mips_transform_env_t *env) {
        ir_node *node = env->irn;
        ir_node *mul;
@@ -665,33 +874,6 @@ ir_node *gen_node_for_IJmp(mips_transform_env_t *env) {
        return new_rd_mips_jr(dbg, irg, block, target);
 }
 
-static
-ir_node *gen_node_for_Jmp(mips_transform_env_t *env) {
-       ir_graph *irg    = env->irg;
-       ir_node  *node   = env->irn;
-       dbg_info *dbg    = get_irn_dbg_info(node);
-       ir_node  *block  = get_nodes_block(node);
-
-       return new_rd_mips_b(dbg, irg, block);
-}
-
-static
-ir_node *gen_node_for_Abs(mips_transform_env_t *env) {
-       ir_node *node = env->irn;
-       ir_node *sra, *add, *xor;
-       mips_attr_t *attr;
-
-       // TODO for other bit sizes...
-       assert(get_mode_size_bits(env->mode) == 32);
-       sra = new_rd_mips_srai(env->dbg, env->irg, env->block, get_Abs_op(node));
-       attr = get_mips_attr(sra);
-       attr->tv = new_tarval_from_long(31, mode_Iu);
-       add = new_rd_mips_addu(env->dbg, env->irg, env->block, get_Abs_op(node), sra);
-       xor = new_rd_mips_xor(env->dbg, env->irg, env->block, sra, add);
-
-       return xor;
-}
-
 static
 ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
        ir_node *node = env->irn;
@@ -704,10 +886,13 @@ ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
 
        return or;
 }
+#endif
 
-static ir_node *gen_node_for_Unknown(mips_transform_env_t *env)
+static ir_node *gen_Unknown(ir_node *node)
 {
-       return gen_zero(env);
+       (void) node;
+       assert(mode_needs_gp_reg(get_irn_mode(node)));
+       return mips_create_zero();
 }
 
 #if 0
@@ -873,15 +1058,13 @@ static void mips_transform_Spill(mips_transform_env_t* env) {
        ir_node   *ptr   = get_irn_n(node, 0);
        ir_node   *val   = get_irn_n(node, 1);
        ir_entity *ent   = be_get_frame_entity(node);
-       mips_attr_t *attr;
 
        if(sched_is_scheduled(node)) {
                sched_point = sched_prev(node);
        }
 
-       store = new_rd_mips_sw(env->dbg, env->irg, env->block, nomem, ptr, val);
-       attr = get_mips_attr(store);
-       attr->stack_entity = ent;
+       store = new_rd_mips_sw(env->dbg, env->irg, env->block, ptr, val, nomem,
+                              ent, 0);
 
        if (sched_point) {
                sched_add_after(sched_point, store);
@@ -899,21 +1082,17 @@ static void mips_transform_Reload(mips_transform_env_t* env) {
        ir_node   *mem   = get_irn_n(node, 1);
        ir_entity *ent   = be_get_frame_entity(node);
        const arch_register_t* reg;
-       mips_attr_t *attr;
 
        if(sched_is_scheduled(node)) {
                sched_point = sched_prev(node);
        }
 
-       load = new_rd_mips_lw(env->dbg, env->irg, env->block, mem, ptr);
-       attr = get_mips_attr(load);
-       attr->stack_entity = ent;
+       load = new_rd_mips_lw(env->dbg, env->irg, env->block, ptr, mem, ent, 0);
 
        proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode_Iu, pn_mips_lw_res);
 
        if (sched_point) {
                sched_add_after(sched_point, load);
-               sched_add_after(load, proj);
 
                sched_remove(node);
        }
@@ -946,7 +1125,8 @@ static ir_node *gen_node_for_StackParam(mips_transform_env_t *env)
 }
 #endif
 
-static ir_node *gen_node_for_AddSP(mips_transform_env_t *env)
+#if 0
+static ir_node *gen_AddSP(ir_node *node)
 {
        ir_node *node = env->irn;
        ir_node *op1, *op2;
@@ -964,6 +1144,7 @@ static ir_node *gen_node_for_AddSP(mips_transform_env_t *env)
 
        return add;
 }
+#endif
 
 /*********************************************************
  *                  _             _      _
@@ -975,7 +1156,55 @@ static ir_node *gen_node_for_AddSP(mips_transform_env_t *env)
  *
  *********************************************************/
 
+static ir_node *gen_Bad(ir_node *node)
+{
+       panic("Unexpected node %+F found in mips transform phase.\n", node);
+       return NULL;
+}
+
+static void register_transformers(void)
+{
+       clear_irp_opcodes_generic_func();
+
+       op_Add->ops.generic      = (op_func) gen_Add;
+       op_Sub->ops.generic      = (op_func) gen_Sub;
+       op_And->ops.generic      = (op_func) gen_And;
+       op_Or->ops.generic       = (op_func) gen_Or;
+       op_Eor->ops.generic      = (op_func) gen_Eor;
+       op_Shl->ops.generic      = (op_func) gen_Shl;
+       op_Shr->ops.generic      = (op_func) gen_Shr;
+       op_Shrs->ops.generic     = (op_func) gen_Shrs;
+       op_Not->ops.generic      = (op_func) gen_Not;
+       op_Minus->ops.generic    = (op_func) gen_Minus;
+       op_Div->ops.generic      = (op_func) gen_Div;
+       op_Mod->ops.generic      = (op_func) gen_Mod;
+       op_DivMod->ops.generic   = (op_func) gen_DivMod;
+       op_Abs->ops.generic      = (op_func) gen_Abs;
+       op_Load->ops.generic     = (op_func) gen_Load;
+       op_Store->ops.generic    = (op_func) gen_Store;
+       op_Cond->ops.generic     = (op_func) gen_Cond;
+       op_Conv->ops.generic     = (op_func) gen_Conv;
+       op_Const->ops.generic    = (op_func) gen_Const;
+       op_SymConst->ops.generic = (op_func) gen_SymConst;
+       op_Unknown->ops.generic  = (op_func) gen_Unknown;
+       op_Proj->ops.generic     = (op_func) gen_Proj;
+       op_Phi->ops.generic      = (op_func) gen_Phi;
+
+       op_Raise->ops.generic     = (op_func) gen_Bad;
+       op_Sel->ops.generic       = (op_func) gen_Bad;
+       op_InstOf->ops.generic    = (op_func) gen_Bad;
+       op_Cast->ops.generic      = (op_func) gen_Bad;
+       op_Free->ops.generic      = (op_func) gen_Bad;
+       op_Tuple->ops.generic     = (op_func) gen_Bad;
+       op_Id->ops.generic        = (op_func) gen_Bad;
+       op_Confirm->ops.generic   = (op_func) gen_Bad;
+       op_Filter->ops.generic    = (op_func) gen_Bad;
+       op_CallBegin->ops.generic = (op_func) gen_Bad;
+       op_EndReg->ops.generic    = (op_func) gen_Bad;
+       op_EndExcept->ops.generic = (op_func) gen_Bad;
+}
 
+#if 0
 /**
  * Transforms the given firm node (and maybe some other related nodes)
  * into one or more assembler nodes.
@@ -1127,43 +1356,13 @@ bad:
                exchange(node, asm_node);
        }
 }
-
-void mips_pre_transform_node(ir_node *node, void *env) {
-       mips_code_gen_t *cgenv = (mips_code_gen_t *)env;
-       int i;
-
-       mips_transform_env_t tenv;
-
-       if (is_Block(node))
-               return;
-
-       tenv.block    = get_nodes_block(node);
-       tenv.dbg      = get_irn_dbg_info(node);
-       tenv.irg      = current_ir_graph;
-       tenv.irn      = node;
-       tenv.mode     = get_irn_mode(node);
-       tenv.cg           = cgenv;
-
-       if(is_Proj(node)) {
-#if 0
-               ir_node* pred = get_Proj_pred(node);
-               if(get_irn_opcode(pred) == iro_CopyB) {
-                       mips_fix_CopyB_Proj(&tenv);
-               }
 #endif
-       }
 
-       for(i = 0; i < get_irn_arity(node); ++i) {
-               ir_node* pred = get_irn_n(node, i);
-
-               if (is_Const(pred)) {
-                       ir_node* constnode = exchange_node_for_Const(&tenv, pred, i);
-                       set_irn_n(node, i, constnode);
-               } else if (get_irn_op(pred) == op_SymConst) {
-                       ir_node* constnode = gen_node_for_SymConst(&tenv, pred);
-                       set_irn_n(node, i, constnode);
-               }
-       }
+void mips_transform_graph(mips_code_gen_t *cg)
+{
+       env_cg = cg;
+       register_transformers();
+       be_transform_graph(cg->birg, NULL, cg);
 }
 
 /**
index fa9b8f3..342f60c 100644 (file)
  */
 ir_node *gen_code_for_CopyB(ir_node *blk, ir_node *node);
 
-void mips_pre_transform_node(ir_node *node, void *env);
-void mips_transform_node(ir_node *node, void *env);
+ir_node *mips_create_Immediate(long offset);
+ir_node *mips_create_zero(void);
+
+void mips_transform_graph(mips_code_gen_t *cg);
 void mips_after_ra_walker(ir_node *node, void *env);
 
 #endif