mips backend updates:
authorMatthias Braun <matze@braunis.de>
Mon, 7 May 2007 08:36:19 +0000 (08:36 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 7 May 2007 08:36:19 +0000 (08:36 +0000)
- fixed the condition jump nodes
- improvements to transform code
- various bugfixes/updates for new be code

[r13673]

ir/be/mips/bearch_mips.c
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_nodes_attr.h
ir/be/mips/mips_scheduler.c
ir/be/mips/mips_spec.pl
ir/be/mips/mips_transform.c

index 015dbf0..6939655 100644 (file)
@@ -38,6 +38,7 @@
 #include "iredges.h"
 #include "irdump.h"
 #include "irextbb.h"
+#include "error.h"
 
 #include "bitset.h"
 #include "debug.h"
@@ -206,19 +207,18 @@ static arch_irn_flags_t mips_get_flags(const void *self, const ir_node *irn) {
        return 0;
 }
 
-static ir_entity *mips_get_frame_entity(const void *self, const ir_node *irn) {
-       if(is_mips_load_r(irn) || is_mips_store_r(irn)) {
-               mips_attr_t *attr = get_mips_attr(irn);
-
-               return attr->stack_entity;
-       }
+static
+ir_entity *mips_get_frame_entity(const void *self, const ir_node *node) {
+       if(!is_mips_irn(node))
+               return NULL;
 
-       return NULL;
+       mips_attr_t *attr = get_mips_attr(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 *irn, ir_entity *ent) {
        mips_attr_t *attr  = get_mips_attr(irn);
-       assert(is_mips_load_r(irn) || is_mips_store_r(irn));
        attr->stack_entity = ent;
 }
 
@@ -226,11 +226,13 @@ static void mips_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent
  * 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 *irn, int offset)
+{
+       panic("TODO");
+#if 0
        mips_attr_t *attr = get_mips_attr(irn);
-       assert(is_mips_load_r(irn) || is_mips_store_r(irn));
-
        attr->stack_entity_offset = offset;
+#endif
 }
 
 static int mips_get_sp_bias(const void *self, const ir_node *irn) {
@@ -356,6 +358,7 @@ static void mips_create_block_sched(mips_code_gen_t *cg) {
        cg->bl_list = bl_list;
 }
 
+#if 0
 typedef struct _wenv_t {
        ir_node *list;
 } wenv_t;
@@ -371,8 +374,10 @@ static void collect_copyb_nodes(ir_node *node, void *env) {
                wenv->list = node;
        }
 }
+#endif
 
 static void replace_copyb_nodes(mips_code_gen_t *cg) {
+#if 0
        wenv_t env;
        ir_node *copy, *next;
        ir_node *old_bl, *new_bl, *jmp, *new_jmp, *mem;
@@ -410,6 +415,8 @@ static void replace_copyb_nodes(mips_code_gen_t *cg) {
                        }
                }
        }
+#endif
+       (void) cg;
 }
 
 /**
@@ -516,7 +523,6 @@ static void *mips_cg_init(be_irg_t *birg) {
        cg->isa      = isa;
        cg->birg     = birg;
        cg->bl_list  = NULL;
-       FIRM_DBG_REGISTER(cg->mod, "firm.be.mips.cg");
 
        cur_reg_set = cg->reg_set;
 
@@ -565,7 +571,7 @@ static void *mips_init(FILE *file_handle) {
 
        mips_register_init(isa);
        mips_create_opcodes();
-       mips_init_opcode_transforms();
+       // mips_init_opcode_transforms();
 
        /* we mark referenced global entities, so we can only emit those which
         * are actually referenced. (Note: you mustn't use the type visited flag
@@ -682,20 +688,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_store_r(dbg, irg, block, *mem, sp, reg, mode_T);
+               store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg);
                attr = get_mips_attr(store);
-               attr->modes.load_store_mode = mode_Iu;
-               attr->tv = new_tarval_from_long(16, mode_Is);
+               attr->tv = new_tarval_from_long(16, mode_Hs);
 
-               mm[4] = new_r_Proj(irg, block, store, mode_M, pn_Store_M);
+               mm[4] = store;
 
                reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_RA]);
-               store = new_rd_mips_store_r(dbg, irg, block, *mem, sp, reg, mode_T);
+               store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg);
                attr = get_mips_attr(store);
-               attr->modes.load_store_mode = mode_Iu;
-               attr->tv = new_tarval_from_long(20, mode_Is);
+               attr->tv = new_tarval_from_long(20, mode_Hs);
 
-               mm[5] = new_r_Proj(irg, block, store, mode_M, pn_Store_M);
+               mm[5] = store;
 
                // TODO ideally we would route these mem edges directly towards the epilogue
                sync = new_r_Sync(irg, block, 2, mm+4);
@@ -712,12 +716,11 @@ static const arch_register_t *mips_abi_prologue(void *self, ir_node** mem, pmap
                //arch_set_irn_register(mips_get_arg_env(), sp, &mips_gp_regs[REG_SP]);
 
                reg = be_abi_reg_map_get(reg_map, &mips_gp_regs[REG_FP]);
-               store = new_rd_mips_store_r(dbg, irg, block, *mem, sp, reg, mode_T);
+               store = new_rd_mips_sw(dbg, irg, block, *mem, sp, reg);
                attr = get_mips_attr(store);
-               attr->modes.load_store_mode = mode_Iu;
-               attr->tv = new_tarval_from_long(0, mode_Is);
+               attr->tv = new_tarval_from_long(0, mode_Hs);
 
-               *mem = new_r_Proj(irg, block, store, mode_M, pn_Store_M);
+               *mem = store;
        }
 
        // setup framepointer
@@ -751,15 +754,14 @@ static void mips_abi_epilogue(void *self, ir_node *block, ir_node **mem, pmap *r
        //arch_set_irn_register(mips_get_arg_env(), fp, &mips_gp_regs[REG_SP]);
 
        // 1. restore fp
-       load = new_rd_mips_load_r(dbg, irg, block, *mem, sp, mode_T);
+       load = new_rd_mips_lw(dbg, irg, block, *mem, sp);
        attr = get_mips_attr(load);
-       attr->modes.load_store_mode = mode_Iu;
        // 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_Is);
+       attr->tv = new_tarval_from_long(fp_save_offset - initial_frame_size, mode_Hs);
 
-       fp = new_r_Proj(irg, block, load, mode_Iu, pn_Load_res);
-       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]);
+       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);
+       arch_set_irn_register(env->arch_env, fp, &mips_gp_regs[REG_FP]);
 
        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);
index e1f5438..a9a76c5 100644 (file)
@@ -48,7 +48,6 @@ struct mips_code_gen_t {
        const be_irg_t                 *birg;           /**< The be-irg (contains additional information about the irg) */
        ir_node                        **bl_list;               /**< The block schedule list. */
        survive_dce_t                              *bl_list_sdce;       /**< survive dce environment for the block schedule list */
-       DEBUG_ONLY(firm_dbg_module_t   *mod;)           /**< debugging module */
 };
 
 struct mips_isa_t {
@@ -73,9 +72,6 @@ struct mips_transform_env_t {
        ir_node           *irn;      /**< The irn, to be transformed */
        ir_mode           *mode;     /**< The mode of the irn */
        mips_code_gen_t   *cg;       /**< The code generator */
-       DEBUG_ONLY(firm_dbg_module_t *mod;) /**< The firm debugger */
 };
 
-ir_node *mips_new_NoReg(mips_code_gen_t *cg);
-
 #endif
index 7beb5b5..dd0e56a 100644 (file)
@@ -231,10 +231,13 @@ static const char *node_const_to_str(ir_node *n)
 
 void mips_emit_immediate(mips_emit_env_t *env, const ir_node *node)
 {
-       const mips_attr_t *attr;
+       const mips_attr_t *attr = get_mips_attr(node);
 
-       attr = get_mips_attr(node);
-       be_emit_tarval(env->emit, attr->tv);
+       if(attr->tv != NULL) {
+               be_emit_tarval(env->emit, attr->tv);
+       } else {
+               be_emit_cstring(env->emit, "/* TODO */ 0");
+       }
 }
 
 /*
@@ -379,7 +382,7 @@ const char* mips_get_block_label(const ir_node* block)
 static
 void mips_emit_block_label(mips_emit_env_t *env, const ir_node *block)
 {
-       be_emit_irprintf(env->emit, "BLOCK_%ld", get_irn_node_nr(block));
+       be_emit_irprintf(env->emit, "BLOCK_%d", get_irn_node_nr(block));
 }
 
 static void mips_emit_Jump(mips_emit_env_t *env, const ir_node *node)
@@ -392,7 +395,7 @@ static void mips_emit_Jump(mips_emit_env_t *env, const ir_node *node)
        be_emit_finish_line_gas(env->emit, node);
 }
 
-ir_node *mips_get_jump_block(const ir_node* node, int projn)
+ir_node *mips_get_jump_block(const ir_node* node, long projn)
 {
        const ir_edge_t *oute;
        for(oute = get_irn_out_edge_first(node); oute != NULL;
@@ -409,7 +412,8 @@ ir_node *mips_get_jump_block(const ir_node* node, int projn)
        return NULL;
 }
 
-void mips_emit_jump_target_proj(mips_emit_env_t *env, const ir_node *node, int projn)
+void mips_emit_jump_target_proj(mips_emit_env_t *env, const ir_node *node,
+                                long projn)
 {
        ir_node *jumpblock = mips_get_jump_block(node, projn);
        assert(jumpblock != NULL);
@@ -425,6 +429,17 @@ void mips_emit_jump_target(mips_emit_env_t *env, const ir_node *node)
        mips_emit_block_label(env, jumpblock);
 }
 
+void mips_emit_jump_or_fallthrough(mips_emit_env_t *env, const ir_node *node,
+                                   long pn)
+{
+       ir_node *jumpblock = mips_get_jump_block(node, pn);
+       assert(jumpblock != NULL);
+
+       /* TODO: use fallthrough when possible */
+       be_emit_cstring(env->emit, "b ");
+       mips_emit_block_label(env, jumpblock);
+}
+
 /************************************************************************
  *  ____          _ _       _         _                                 *
  * / ___|_      _(_) |_ ___| |__     | |_   _ _ __ ___  _ __            *
@@ -523,7 +538,7 @@ void emit_mips_jump_table(mips_emit_env_t *env, const ir_node *irn) {
 
                for(i2 = lastval + 1; i2 < value; ++i2) {
                        be_emit_cstring(env->emit, "\t.word ");
-                       be_emit_ident(env->emit, attr->symconst_id);
+                       be_emit_ident(env->emit, get_entity_ld_ident(attr->symconst));
                        be_emit_char(env->emit, '\n');
                        be_emit_write_line(env->emit);
                }
@@ -624,6 +639,7 @@ void mips_register_emitters(void) {
        register_emitter(op_Jmp, mips_emit_Jump);
        register_emitter(op_Cmp, mips_emit_this_shouldnt_happen);
        register_emitter(op_Cond, mips_emit_this_shouldnt_happen);
+       register_emitter(op_Phi, mips_emit_nothing);
 }
 
 /**
index d9ff7af..6b11d3b 100644 (file)
@@ -47,10 +47,12 @@ void mips_emit_dest_register(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_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,
-                                int pn);
+                                long pn);
+void mips_emit_jump_or_fallthrough(mips_emit_env_t *env, const ir_node *node,
+                                   long pn);
 
 void mips_register_emitters(void);
-ir_node *mips_get_jump_block(const ir_node* node, int projn);
+ir_node *mips_get_jump_block(const ir_node* node, long projn);
 
 /** returns the label used for a block */
 const char* mips_get_block_label(const ir_node* block);
index 2f8f191..cc095d3 100644 (file)
@@ -198,9 +198,6 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                        }
                        fprintf(F, " (%d)\n", attr->flags);
 
-                       if(attr->modes.load_store_mode != NULL) {
-                               fprintf(F, " load_store_mode %s\n", get_mode_name(attr->modes.load_store_mode));
-                       }
                        if(attr->stack_entity != NULL) {
                                fprintf(F, " stack entity %s\n", get_entity_name(attr->stack_entity));
                        }
@@ -208,8 +205,8 @@ static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
                                tarval_snprintf(buf, sizeof(buf), attr->tv);
                                fprintf(F, " tarval %s\n", buf);
                        }
-                       if(attr->symconst_id != NULL) {
-                               fprintf(F, " symconst '%s'\n", get_id_str(attr->symconst_id));
+                       if(attr->symconst != NULL) {
+                               fprintf(F, " symconst '%s'\n", get_entity_name(attr->symconst));
                        }
 
                        fprintf(F, "=== mips attr end ===\n");
@@ -389,6 +386,25 @@ void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, const arch_regi
        memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0]));
 }
 
+static
+int mips_compare_attr(mips_attr_t *a, mips_attr_t *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(a->n_res != b->n_res)
+               return 1;
+       if(a->switch_default_pn != b->switch_default_pn)
+               return 1;
+
+       return 0;
+}
+
 /************************************************************************
  *  ___ _____     _     _ _
  * |_ _|  ___|__ | | __| (_)_ __   __ _
@@ -398,6 +414,7 @@ void init_mips_attributes(ir_node *node, arch_irn_flags_t flags, const arch_regi
  *                                |___/
  ************************************************************************/
 
+#if 0
 // test if a tarval can be expressed in a 16bit immediate value
 static int is_tarval_16(ir_node* node)
 {
@@ -467,6 +484,7 @@ void mips_init_opcode_transforms(void) {
        op_mips_sr->ops.transform_node  = mips_transform_sr;
        op_mips_slt->ops.transform_node = mips_transform_slt;
 }
+#endif
 
 /***************************************************************************************
  *                  _                            _                   _
index 289473a..5d1a479 100644 (file)
@@ -33,15 +33,11 @@ typedef struct _mips_attr_t {
        arch_irn_flags_t flags;     /**< indicating if spillable, rematerializeable ... etc. */
        int              n_res;     /**< number of results for this node */
 
-       tarval *tv;                                     /**< contains the immediate value (if the node has any) */
-       ident *symconst_id;                     /**< contains the ident (for la operations) */
+       tarval          *tv;        /**< contains the immediate value */
+       ir_entity       *symconst;
 
-       union {
-               ir_mode *load_store_mode;       /**< contains the mode of a load/store */
-               ir_mode *original_mode;         /**< contains the original mode of the node */
-       } modes;
+       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 stack_entity_offset;        /**< contains the real stack offset for the entity */
        int switch_default_pn;          /**< proj number of default case in switch */
 
        const arch_register_req_t **in_req;  /**< register requirements for arguments */
index 635a959..bd8b468 100644 (file)
@@ -201,6 +201,22 @@ static ir_node *mips_scheduler_select(void *block_env, nodeset *ready_set, nodes
 
 #endif
 
+static
+int mips_to_appear_in_schedule(void *block_env, const ir_node *node)
+{
+       ir_fprintf(stderr, "check %+F\n", node);
+       if(!is_mips_irn(node))
+               return -1;
+
+       if(is_mips_zero(node))
+               return 0;
+
+       ir_fprintf(stderr, "Sched: %+F\n", node);
+       return 1;
+}
+
+list_sched_selector_t  mips_selector;
+
 /**
  * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
  */
@@ -216,7 +232,10 @@ const list_sched_selector_t *mips_get_list_sched_selector(const void *self, list
        mips_sched_selector.finish_graph = mips_scheduler_finish_graph;
        //return &mips_sched_selector;
 #endif
-       return selector;
+       memcpy(&mips_selector, selector, sizeof(mips_selector));
+       mips_selector.to_appear_in_schedule = mips_to_appear_in_schedule;
+
+       return &mips_selector;
 }
 
 const ilp_sched_selector_t *mips_get_ilp_sched_selector(const void *self) {
index 31b6333..a96caf6 100644 (file)
@@ -135,6 +135,7 @@ $new_emit_syntax = 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);",
 );
 
 
@@ -149,6 +150,8 @@ $new_emit_syntax = 1;
 #                                      |_|         #
 #--------------------------------------------------#
 
+$default_cmp_attr = "return mips_compare_attr(attr_a, attr_b);";
+
 %nodes = (
 
 #-----------------------------------------------------------------#
@@ -359,23 +362,6 @@ lui => {
        mode      => "mode_Iu",
 },
 
-# load lower immediate
-lli => {
-       op_flags  => "c",
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. ori %D1, %S1, %C',
-       cmp_attr  => 'return attr_a->tv != attr_b->tv;',
-       mode      => "mode_Iu",
-},
-
-la => {
-       op_flags  => "c",
-       reg_req   => { out => [ "gp" ] },
-       emit      => '. la %D1, %C',
-       cmp_attr  => 'return attr_a->symconst_id != attr_b->symconst_id;',
-       mode      => "mode_Iu",
-},
-
 mflo => {
        reg_req   => { in => [ "none" ], out => [ "gp" ] },
        emit      => '. mflo %D1',
@@ -389,6 +375,9 @@ mfhi => {
 },
 
 zero => {
+       state     => "pinned",
+       op_flags  => "c",
+       irn_flags => "I",
        reg_req   => { out => [ "zero" ] },
        emit      => '',
        mode      => "mode_Iu"
@@ -405,128 +394,80 @@ zero => {
 
 slt => {
        reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
-       emit => '
-       if (mode_is_signed(get_irn_mode(node))) {
-               . slt %D1, %S1, %S2
-       }
-       else {
-               . sltu %D1, %S1, %S2
-       }
-',
+       emit    => '. slt %D1, %S1, %S2',
+       mode    => "mode_Iu",
+},
+
+sltu => {
+       reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
+       emit    => '. sltu %D1, %S1, %S2',
        mode    => "mode_Iu",
 },
 
 slti => {
        reg_req => { in => [ "gp" ], out => [ "gp" ] },
-       emit => '
-       if (mode_is_signed(get_irn_mode(node))) {
-               . slti %D1, %S1, %C
-       }
-       else {
-               . sltiu %D1, %S1, %C
-       }
-',
-       cmp_attr => 'return attr_a->tv != attr_b->tv;',
+       emit    => '. slti %D1, %S1, %C',
+       mode    => "mode_Iu",
+},
+
+sltiu => {
+       reg_req => { in => [ "gp" ], out => [ "gp" ] },
+       emit    => '. slti %D1, %S1, %C',
        mode    => "mode_Iu",
 },
 
 beq => {
-       op_flags  => "X|Y",
-       # TxT -> TxX
-       reg_req => { in => [ "gp", "gp" ], out => [ "in_r0", "none" ] },
-       emit => '. beq %S1, %S2, %JumpTarget1'
+       op_flags => "X|Y",
+       reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
+       outs     => [ "false", "true" ],
+       emit     => '. beq %S1, %S2, %JumpTarget1
+                    . %JumpOrFallthrough'
 },
 
 bne => {
-       op_flags  => "X|Y",
-       # TxT -> TxX
-       reg_req => { in => [ "gp", "gp" ], out => [ "in_r0", "none" ] },
-       emit => '. bne %S1, %S2, %JumpTarget1'
+       op_flags => "X|Y",
+       reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
+       outs     => [ "false", "true" ],
+       emit     => '. bne %S1, %S2, %JumpTarget1
+                    . %JumpOrFallthrough'
 },
 
 bgtz => {
-       op_flags  => "X|Y",
-       # TxT -> TxX
-       reg_req => { in => [ "gp" ], out => [ "in_r0", "none" ] },
-       emit => '. bgtz %S1, %JumpTarget1'
+       op_flags => "X|Y",
+       reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
+       outs     => [ "false", "true" ],
+       emit     => '. bgtz %S1, %JumpTarget1
+                    . %JumpOrFallthrough'
 },
 
 blez => {
-       op_flags  => "X|Y",
-       # TxT -> TxX
-       reg_req => { in => [ "gp" ], out => [ "in_r0", "none" ] },
-       emit => '. blez %S1, %JumpTarget1'
-},
-
-j => {
-  op_flags => "X",
-  reg_req => { in => [ "gp" ] },
-  emit => '. j %S1',
+       op_flags => "X|Y",
+       reg_req  => { in => [ "gp" ], out => [ "none", "none" ] },
+       outs     => [ "false", "true" ],
+       emit     => '. blez %S1, %JumpTarget1
+                    . %JumpOrFallthrough'
 },
 
 b => {
        op_flags => "X",
-       # -> X
-       reg_req => { in => [ ], out => [ "none" ] },
-       emit => '. b %JumpTarget'
+       reg_req  => { in => [ ], out => [ "none" ] },
+       emit     => '. b %JumpTarget',
+       mode     => 'mode_X'
 },
 
-fallthrough => {
+jr => {
        op_flags => "X",
-       # -> X
-       reg_req => { in => [ ], out => [ "none" ] },
-       emit => '. /* fallthrough to %JumpTarget */'
+       reg_req  => { in => [ "gp" ], out => [ "none" ] },
+       emit     => '. jr %S1',
+       mode     => 'mode_X'
 },
 
 SwitchJump => {
        op_flags => "X",
-       # -> X,X,...
-       reg_req => { in => [ "gp" ], out => [ "none" ] },
-       emit => '. j %S1'
+       reg_req  => { in => [ "gp" ], out => [ "none" ] },
+       emit     => '. jr %S1'
 },
 
-#  _                    _
-# | |    ___   __ _  __| |
-# | |   / _ \ / _` |/ _` |
-# | |__| (_) | (_| | (_| |
-# |_____\___/ \__,_|\__,_|
-#
-
-load_r => {
-       reg_req => { in => [ "none", "gp" ], out => [ "none", "none", "gp" ] },
-       emit => '
-       mips_attr_t* attr = get_mips_attr(node);
-       ir_mode *mode;
-
-       mode = attr->modes.load_store_mode;
-
-       switch (get_mode_size_bits(mode)) {
-       case 8:
-               if (mode_is_signed(mode)) {
-                       . lb %D3, %C(%S2)
-               } else {
-                       . lbu %D3, %C(%S2)
-               }
-               break;
-       case 16:
-               if (mode_is_signed(mode)) {
-                       . lh %D3, %C(%S2)
-               } else {
-                       . lhu %D3, %C(%S2)
-               }
-               break;
-       case 32:
-               . lw %D3, %C(%S2)
-               break;
-       default:
-               assert(! "Only 8, 16 and 32 bit loads supported");
-               break;
-       }
-',
-       cmp_attr => 'return attr_a->tv != attr_b->tv || attr_a->stack_entity != attr_b->stack_entity;',
-},
-
-
 #  _                    _    ______  _
 # | |    ___   __ _  __| |  / / ___|| |_ ___  _ __ ___
 # | |   / _ \ / _` |/ _` | / /\___ \| __/ _ \| '__/ _ \
@@ -534,73 +475,73 @@ load_r => {
 # |_____\___/ \__,_|\__,_/_/  |____/ \__\___/|_|  \___|
 #
 
-store_r => {
-       reg_req => { in => [ "none", "gp", "gp" ], out => [ "none", "none" ] },
-       emit => '
-       mips_attr_t* attr = get_mips_attr(node);
-       ir_mode* mode;
-
-       mode = attr->modes.load_store_mode;
-
-       switch (get_mode_size_bits(mode)) {
-       case 8:
-               if (mode_is_signed(mode))
-                       . sb %S3, %C(%S2)
-               break;
-       case 16:
-               if (mode_is_signed(mode))
-                       . sh %S3, %C(%S2)
-               break;
-       case 32:
-                       . sw %S3, %C(%S2)
-               break;
-       default:
-               assert(! "Only 8, 16 and 32 bit stores supported");
-               break;
-       }
-',
-       cmp_attr => 'return attr_a->tv != attr_b->tv;',
-},
-
-store_i => {
-       reg_req => { in => [ "none", "none", "gp" ], out => [ "none", "none" ] },
-       emit => '
-       mips_attr_t* attr = get_mips_attr(node);
-       ir_mode *mode;
-
-       mode = attr->modes.load_store_mode;
-
-       switch (get_mode_size_bits(mode)) {
-       case 8:
-               . sb %S3, %C
-               break;
-       case 16:
-               . sh %S3, %C
-               break;
-       case 32:
-               . sw %S3, %C
-               break;
-       default:
-               assert(! "Only 8, 16 and 32 bit stores supported");
-               break;
-       }
-',
-       cmp_attr => 'return attr_a->stack_entity != attr_b->stack_entity;',
+lw => {
+       op_flags => "L|F",
+       state    => "exc_pinned",
+       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
+       outs     => [ "res", "M" ],
+       emit     => '. lw %D1, %C(%S2)',
 },
 
-move => {
-       reg_req  => { in => [ "gp" ], out => [ "gp" ] },
-       emit     => '. move %D1, %S1',
-       mode     => "mode_Iu"
+lh => {
+       op_flags => "L|F",
+       state    => "exc_pinned",
+       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
+       outs     => [ "res", "M" ],
+       emit     => '. lh %D1, %C(%S2)',
 },
 
-#
-# Conversion
-#
+lhu => {
+       op_flags => "L|F",
+       state    => "exc_pinned",
+       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
+       outs     => [ "res", "M" ],
+       emit     => '. lhu %D1, %C(%S2)',
+},
+
+lb => {
+       op_flags => "L|F",
+       state    => "exc_pinned",
+       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
+       outs     => [ "res", "M" ],
+       emit     => '. lb %D1, %C(%S2)',
+},
+
+lbu => {
+       op_flags => "L|F",
+       state    => "exc_pinned",
+       reg_req  => { in => [ "none", "gp" ], out => [ "gp", "none" ] },
+       outs     => [ "res", "M" ],
+       emit     => '. lbu %D1, %C(%S2)',
+},
+
+sw => {
+       op_flags => "L|F",
+       state    => "exc_pinned",
+       reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
+       emit     => '. sw %S3, %C(%S2)',
+       mode     => 'mode_M',
+},
 
-reinterpret_conv => {
-       reg_req  => { in => [ "gp" ], out => [ "in_r1" ] },
-       emit     => '. # reinterpret %S1 -> %D1',
+sh => {
+       op_flags => "L|F",
+       state    => "exc_pinned",
+       reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
+       emit     => '. sh %S3, %C(%S2)',
+       mode     => 'mode_M',
+},
+
+sb => {
+       op_flags => "L|F",
+       state    => "exc_pinned",
+       reg_req  => { in => [ "none", "gp", "gp" ], out => [ "none" ] },
+       emit     => '. sb %S3, %C(%S2)',
+       mode     => 'mode_M',
+},
+
+move => {
+       reg_req  => { in => [ "gp" ], out => [ "gp" ] },
+       emit     => '. move %D1, %S1',
        mode     => "mode_Iu"
 },
 
index 5714e57..58ec798 100644 (file)
@@ -39,6 +39,7 @@
 #include "dbginfo.h"
 #include "iropt_t.h"
 #include "debug.h"
+#include "error.h"
 
 #include "../benode_t.h"
 #include "../beabi.h"
@@ -95,55 +96,48 @@ MIPS_GENBINFUNC(sra)
 
 MIPS_GENUNFUNC(not)
 
-static ir_node* mips_get_reg_node(mips_transform_env_t *env, const arch_register_t *reg) {
-       return be_abi_get_callee_save_irn(env->cg->birg->abi, reg);
-}
-
-static ir_node* gen_zero_node(mips_transform_env_t *env, dbg_info *ebg, ir_graph *irg, ir_node *block)
+static
+ir_node* gen_zero(mips_transform_env_t *env)
 {
-       ir_node *zero = be_abi_get_callee_save_irn(env->cg->birg->abi, &mips_gp_regs[REG_ZERO]);
-       // TODO make zero nodes work
-       //ir_node *unknown = new_rd_mips_zero(dbg, irg, block, mode);
+       ir_graph *irg   = env->irg;
+       ir_node  *block = get_irg_start_block(irg);
+       ir_node  *zero  = new_rd_mips_zero(NULL, irg, block);
+
+       arch_set_irn_register(env->cg->arch_env, zero, &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* gen_node_for_Const(mips_transform_env_t *env, dbg_info *dbg, ir_graph *irg, ir_node *block, ir_node *constant)
 {
        tarval* tv = get_Const_tarval(constant);
-       ir_node *lui;
-       ir_node *lli;
+       ir_node *upper_node;
+       ir_node *lower_node;
        mips_attr_t *attr;
        ir_mode* mode = get_irn_mode(constant);
        unsigned long val, lower, upper;
 
        val = get_tarval_long(tv);
-       if(val == 0)
-               return gen_zero_node(env, dbg, irg, block);
 
        lower = val & 0xffff;
        upper = (val >> 16) & 0xffff;
        if(upper == 0) {
-               ir_node *zero = gen_zero_node(env, dbg, irg, block);
-               ir_node *lli = new_rd_mips_lli(dbg, irg, block, zero);
-               attr = get_mips_attr(lli);
-               attr->tv = new_tarval_from_long(val, mode);
-
-               return lli;
+               upper_node = gen_zero(env);
+       } else {
+               upper_node = new_rd_mips_lui(dbg, irg, block);
+               attr       = get_mips_attr(upper_node);
+               attr->tv   = new_tarval_from_long(val, mode);
        }
 
-       lui = new_rd_mips_lui(dbg, irg, block);
-       attr = get_mips_attr(lui);
-       attr->tv = new_tarval_from_long(val, mode);
-
        if(lower == 0)
-               return lui;
+               return upper_node;
 
-       lli = new_rd_mips_lli(dbg, irg, block, lui);
-       attr = get_mips_attr(lli);
-       attr->tv = new_tarval_from_long(val, mode);
+       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);
 
-       return lli;
+       return lower_node;
 }
 
 static ir_node* exchange_node_for_Const(mips_transform_env_t *env, ir_node* pred, int n) {
@@ -163,95 +157,113 @@ static ir_node* exchange_node_for_Const(mips_transform_env_t *env, ir_node* pred
 }
 
 static ir_node* gen_node_for_SymConst(mips_transform_env_t *env, ir_node* pred, int n) {
-       ir_node *result;
-       symconst_kind kind;
        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_entity *entity;
+       ir_node *lui, *ori;
 
-       if (is_Phi(node)) {
-               ir_node *phipred = get_nodes_block(node);
-               block = get_Block_cfgpred_block(phipred, n);
-       } else {
-               block = get_nodes_block(node);
-       }
+       block = get_nodes_block(pred);
 
-       kind = get_SymConst_kind(pred);
-       if(kind == symconst_addr_ent) {
-               result = new_rd_mips_la(dbg, irg, block);
-               attr = get_mips_attr(result);
-               attr->symconst_id = get_entity_ld_ident(get_SymConst_entity(pred));
-               return result;
-       } else if(kind == symconst_addr_name) {
-               result = new_rd_mips_la(dbg, irg, block);
-               attr = get_mips_attr(result);
-               attr->symconst_id = get_SymConst_name(pred);
-               return result;
+       if(get_SymConst_kind(pred) != symconst_addr_ent) {
+               panic("Only address entity symconsts supported in mips backend");
        }
 
-       // TODO
-       assert(0);
-       return NULL;
+       entity = get_SymConst_entity(pred);
+
+       lui            = new_rd_mips_lui(dbg, irg, block);
+       attr           = get_mips_attr(lui);
+       attr->symconst = entity;
+
+       ori            = new_rd_mips_ori(dbg, irg, block, lui);
+       attr           = get_mips_attr(ori);
+       attr->symconst = entity;
+
+       return ori;
 }
 
+typedef ir_node* (*gen_load_func) (dbg_info *dbg, ir_graph *irg,
+                                   ir_node *block, ir_node *mem, ir_node *ptr);
+
 /**
  * Generates a mips node for a firm Load node
  */
 static ir_node *gen_node_for_Load(mips_transform_env_t *env) {
-       ir_node *node = env->irn;
-       ir_node *result = NULL;
-       ir_mode *mode;
-       ir_node *load_ptr;
-       mips_attr_t *attr;
+       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;
+       gen_load_func func;
 
        ASSERT_NO_FLOAT(get_irn_mode(node));
 
-       mode = get_Load_mode(node);
        assert(mode->vector_elem == 1);
        assert(mode->sort == irms_int_number || mode->sort == irms_reference);
 
-       load_ptr = get_Load_ptr(node);
-       assert(get_mode_sort(mode) == irms_reference || get_mode_sort(mode) == irms_int_number);
-       result = new_rd_mips_load_r(env->dbg, env->irg, env->block,
-                       get_Load_mem(node), load_ptr, get_irn_mode(node));
-
-       attr = get_mips_attr(result);
-       attr->tv = new_tarval_from_long(0, mode_Iu);
-       attr->modes.load_store_mode = mode;
+       switch(get_mode_size_bits(mode)) {
+       case 32:
+               func = new_rd_mips_lw;
+               break;
+       case 16:
+               func = sign ? new_rd_mips_lh : new_rd_mips_lhu;
+               break;
+       case 8:
+               func = sign ? new_rd_mips_lb : new_rd_mips_lbu;
+               break;
+       default:
+               panic("mips backend only support 32, 16, 8 bit loads");
+       }
 
+       result = func(dbg, irg, block, mem, ptr);
        return result;
 }
 
+typedef ir_node* (*gen_store_func) (dbg_info *dbg, ir_graph *irg,
+                                    ir_node *block, ir_node *mem, ir_node *ptr,
+                                    ir_node *val);
+
 /**
  * Generates a mips node for a firm Store node
  */
 static ir_node *gen_node_for_Store(mips_transform_env_t *env) {
-       ir_node *node = env->irn;
-       ir_node *result = NULL;
-       ir_mode *mode;
-       mips_attr_t *attr;
-       ir_node *store_ptr;
-
-       ASSERT_NO_FLOAT(env->mode);
+       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);
+       gen_store_func func;
+       ir_node     *result;
+
+       ASSERT_NO_FLOAT(mode);
 
-       store_ptr = get_Store_ptr(node);
-       mode = get_irn_mode(store_ptr);
        assert(mode->vector_elem == 1);
        assert(mode->sort == irms_int_number || mode->sort == irms_reference);
 
-       if(get_irn_opcode(store_ptr) == iro_SymConst) {
-               result = new_rd_mips_store_i(env->dbg, env->irg, env->block, get_Store_mem(node),
-                       get_Store_ptr(node), get_Store_value(node), env->mode);
-       } else {
-               result = new_rd_mips_store_r(env->dbg, env->irg, env->block, get_Store_mem(node),
-                       get_Store_ptr(node), get_Store_value(node), env->mode);
+       switch(get_mode_size_bits(mode)) {
+       case 32:
+               func = new_rd_mips_sw;
+               break;
+       case 16:
+               func = new_rd_mips_sh;
+               break;
+       case 8:
+               func = new_rd_mips_sb;
+               break;
+       default:
+               panic("store only supported for 32, 16, 8 bit values in mips backend");
        }
-       attr = get_mips_attr(result);
-       attr->tv = new_tarval_from_long(0, mode_Iu);
-       attr->modes.load_store_mode = mode;
 
+       result = func(dbg, irg, block, mem, ptr, val);
        return result;
 }
 
@@ -266,8 +278,8 @@ static ir_node *gen_node_for_div_Proj(mips_transform_env_t *env) {
 
        // set the div mode to the DivMod node
        attr = get_mips_attr(pred);
-       assert(attr->modes.original_mode == NULL || attr->modes.original_mode == env->mode);
-       attr->modes.original_mode = env->mode;
+       assert(attr->original_mode == NULL || attr->original_mode == env->mode);
+       attr->original_mode = env->mode;
 
        // we have to construct a new proj here, to avoid circular refs that
        // happen when we reuse the old one
@@ -283,114 +295,11 @@ static ir_node *gen_node_for_div_Proj(mips_transform_env_t *env) {
        return proj;
 }
 
-static ir_node *make_jmp_or_fallthrough(mips_transform_env_t *env)
-{
-       const ir_edge_t *edge;
-       ir_node *node = env->irn;
-       ir_node *next_block;
-       int our_block_sched_nr = mips_get_block_sched_nr(get_nodes_block(node));
-
-       edge = get_irn_out_edge_first(node);
-       next_block = get_edge_src_irn(edge);
-
-       if(mips_get_sched_block(env->cg, our_block_sched_nr + 1) == next_block) {
-               return new_rd_mips_fallthrough(env->dbg, env->irg, env->block, mode_X);
-       }
-
-       return new_rd_mips_b(env->dbg, env->irg, env->block, mode_X);
-}
-
-static ir_node *gen_node_for_Cond_Proj(mips_transform_env_t *env, ir_node* node, int true_false)
-{
-       // we can't use get_Cond_selector here because the selector is already
-       // replaced by a mips_ compare node
-       ir_node *proj = get_Cond_selector(node);
-       ir_node *original_cmp = get_irn_n(proj, 0);
-       ir_node *cmp;
-       ir_node *condjmp;
-       ir_node *op1, *op2;
-       dbg_info *dbg = env->dbg;
-       ir_graph *irg = env->irg;
-       ir_node *block = env->block;
-       long n;
-
-       n = get_Proj_proj(proj);
-       assert(n < 8 && "Only ordered comps supported");
-
-       assert(get_irn_opcode(original_cmp) == iro_Cmp);
-       op1 = get_Cmp_left(original_cmp);
-       op2 = get_Cmp_right(original_cmp);
-
-       switch(n) {
-       case pn_Cmp_False:
-               if(true_false)
-                       return NULL;
-
-               return make_jmp_or_fallthrough(env);
-
-       case pn_Cmp_Eq:
-               if(!true_false)
-                       return make_jmp_or_fallthrough(env);
-
-               condjmp = new_rd_mips_beq(dbg, irg, block, op1, op2, mode_T);
-               return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
-
-       case pn_Cmp_Lt:
-               if(!true_false)
-                       return make_jmp_or_fallthrough(env);
-
-               cmp = new_rd_mips_slt(dbg, irg, block, op1, op2);
-               condjmp = new_rd_mips_bgtz(dbg, irg, block, cmp, mode_T);
-               return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
-
-       case pn_Cmp_Le:
-               if(!true_false)
-                       return make_jmp_or_fallthrough(env);
-
-               cmp = new_rd_mips_slt(dbg, irg, block, op2, op1);
-               condjmp = new_rd_mips_blez(dbg, irg, block, cmp, mode_T);
-               return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
-
-       case pn_Cmp_Gt:
-               if(!true_false)
-                       return make_jmp_or_fallthrough(env);
-
-               cmp = new_rd_mips_slt(dbg, irg, block, op2, op1);
-               condjmp = new_rd_mips_bgtz(dbg, irg, block, cmp, mode_T);
-               return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
-
-       case pn_Cmp_Ge:
-               if(!true_false)
-                       return make_jmp_or_fallthrough(env);
-
-               cmp = new_rd_mips_slt(dbg, irg, block, op1, op2);
-               condjmp = new_rd_mips_blez(dbg, irg, block, cmp, mode_T);
-               return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
-
-       case pn_Cmp_Lg:
-               if(!true_false)
-                       return make_jmp_or_fallthrough(env);
-
-               condjmp = new_rd_mips_bne(dbg, irg, block, op1, op2, mode_T);
-               return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1);
-
-       case pn_Cmp_Leg:
-               if(!true_false)
-                       return NULL;
-
-               return make_jmp_or_fallthrough(env);
-
-       default:
-               assert(0);
-       }
-
-       return NULL;
-}
-
-static ir_node *gen_node_for_Proj(mips_transform_env_t *env)
+static
+ir_node *gen_node_for_Proj(mips_transform_env_t *env)
 {
        ir_node *proj = env->irn;
-       long n;
+       ir_mode *mode = get_irn_mode(proj);
        ir_node *predecessor = get_Proj_pred(proj);
 
        // all DivMods, Div, Mod should be replaced by now
@@ -401,6 +310,19 @@ static ir_node *gen_node_for_Proj(mips_transform_env_t *env)
        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);
+               }
+       }
+
+#if 0
        if(get_irn_opcode(predecessor) == iro_Cond) {
                ir_node *selector = get_Cond_selector(predecessor);
                ir_mode *mode = get_irn_mode(selector);
@@ -411,11 +333,31 @@ static ir_node *gen_node_for_Proj(mips_transform_env_t *env)
                        return gen_node_for_Cond_Proj(env, predecessor, n == pn_Cond_true);
                }
        }
+#endif
+
+       if(get_mode_sort(mode) == irms_int_number) {
+               set_irn_mode(proj, mode_Iu);
+       }
 
        return proj;
 }
 
-static ir_node *gen_node_for_Cond(mips_transform_env_t *env)
+static
+ir_node *gen_node_for_Phi(mips_transform_env_t *env)
+{
+       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);
+       }
+
+       return node;
+}
+
+#if 0
+static
+ir_node *gen_node_for_SwitchCond(mips_transform_env_t *env)
 {
        ir_node *selector = get_Cond_selector(env->irn);
        ir_mode *selector_mode = get_irn_mode(selector);
@@ -514,46 +456,68 @@ static ir_node *gen_node_for_Cond(mips_transform_env_t *env)
 
        return switchjmp;
 }
+#endif
 
-static ir_node *create_conv_store_load(mips_transform_env_t *env, ir_mode* srcmode, ir_mode* dstmode) {
-       ir_node *nomem, *store, *mem_proj, *value_proj, *load;
-       ir_entity *mem_entity;
-       ir_node *node = env->irn;
-       ir_node *pred = get_Conv_op(node);
-       ir_node *sp;
-       // TODO HACK make this global...
-       ident* id;
-       ir_type *i32type;
-       ir_type *ptr_i32type;
-       mips_attr_t* attr;
-
-       id = new_id_from_str("__conv0");
-       i32type = new_type_primitive(new_id_from_str("ptr32"), mode_Iu);
-       ptr_i32type = new_d_type_pointer(id, i32type, mode_P, env->dbg);
-       mem_entity = new_d_entity(get_irg_frame_type(env->irg), id, ptr_i32type, env->dbg);
-
-       sp = mips_get_reg_node(env, &mips_gp_regs[REG_SP]);
-       nomem = new_ir_node(env->dbg, env->irg, env->block, op_NoMem, mode_M, 0, NULL);
-
-       store = new_rd_mips_store_r(env->dbg, env->irg, env->block, nomem, sp, pred, mode_T);
-       attr = get_mips_attr(store);
-       attr->tv = new_tarval_from_long(0, mode_Iu);
-       attr->modes.load_store_mode = srcmode;
-       attr->stack_entity = mem_entity;
+static
+ir_node *gen_node_for_Cond(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  *sel_proj = get_Cond_selector(node);
+       ir_node  *cmp      = get_Proj_pred(sel_proj);
+       ir_node  *op1, *op2;
+       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) {
+       case pn_Cmp_False:
+       case pn_Cmp_True:
+       case pn_Cmp_Leg:
+               panic("mips backend can't handle unoptimized constant Cond");
 
-       mem_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, mode_M, 1, &store);
-       set_Proj_proj(mem_proj, pn_Store_M);
+       case pn_Cmp_Eq:
+               res = new_rd_mips_beq(dbg, irg, block, op1, op2);
+               break;
 
-       load = new_rd_mips_load_r(env->dbg, env->irg, env->block, mem_proj, sp, mode_T);
-       attr = get_mips_attr(load);
-       attr->tv = new_tarval_from_long(0, mode_Iu);
-       attr->modes.load_store_mode = dstmode;
-       attr->stack_entity = mem_entity;
+       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);
+               break;
 
-       value_proj = new_ir_node(env->dbg, env->irg, env->block, op_Proj, env->mode, 1, &load);
-       set_Proj_proj(value_proj, pn_Load_res);
+       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);
+               break;
 
-       return value_proj;
+       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);
+               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);
+               break;
+
+       case pn_Cmp_Lg:
+               res = new_rd_mips_bne(dbg, irg, block, op1, op2);
+               break;
+
+       default:
+               panic("mips backend doesn't handle unordered compares yet");
+       }
+
+       return res;
 }
 
 static ir_node *create_conv_and(mips_transform_env_t *env, long immediate) {
@@ -584,16 +548,19 @@ static ir_node *gen_node_for_Conv(mips_transform_env_t *env) {
        dst_size = get_mode_size_bits(destmode);
        src_size = get_mode_size_bits(srcmode);
 
+       if(src_size == dst_size) {
+               /* unnecessary conv */
+               return pred;
+       }
+
+#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) {
-               if(srcmode->size == 8) {
-                       return create_conv_store_load(env, mode_Bs, mode_Bs);
-               } else if(srcmode->size == 16) {
-                       return create_conv_store_load(env, mode_Hs, mode_Hs);
-               }
+               /* TODO */
        } else {
                if(src_size == 8) {
                        return create_conv_and(env, 0xff);
@@ -686,17 +653,29 @@ static ir_node *gen_node_for_Mul(mips_transform_env_t *env) {
        return mflo;
 }
 
-static ir_node *gen_node_for_IJmp(mips_transform_env_t *env) {
-       ir_node *node = env->irn;
+static
+ir_node *gen_node_for_IJmp(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  *target = get_IJmp_target(node);
 
-       return new_rd_mips_j(env->dbg, env->irg, env->block, get_IJmp_target(node), node->mode);
+       return new_rd_mips_jr(dbg, irg, block, target);
 }
 
-static ir_node *gen_node_for_Jmp(mips_transform_env_t *env) {
-       return make_jmp_or_fallthrough(env);
+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) {
+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;
@@ -712,7 +691,8 @@ static ir_node *gen_node_for_Abs(mips_transform_env_t *env) {
        return xor;
 }
 
-static ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
+static
+ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
        ir_node *node = env->irn;
        ir_node *subu, *srlv, *sllv, *or;
 
@@ -726,9 +706,10 @@ static ir_node *gen_node_for_Rot(mips_transform_env_t *env) {
 
 static ir_node *gen_node_for_Unknown(mips_transform_env_t *env)
 {
-       return gen_zero_node(env, env->dbg, env->irg, env->block);
+       return gen_zero(env);
 }
 
+#if 0
 /*
  * lower a copyB into standard Firm assembler :-)
  */
@@ -881,11 +862,12 @@ static void mips_fix_CopyB_Proj(mips_transform_env_t* env) {
                set_Proj_proj(node, pn_Store_X_except);
        }
 }
+#endif
 
 static void mips_transform_Spill(mips_transform_env_t* env) {
        ir_node   *node = env->irn;
        ir_node   *sched_point = NULL;
-       ir_node   *store, *proj;
+       ir_node   *store;
        ir_node   *nomem = new_rd_NoMem(env->irg);
        ir_node   *ptr   = get_irn_n(node, 0);
        ir_node   *val   = get_irn_n(node, 1);
@@ -896,21 +878,16 @@ static void mips_transform_Spill(mips_transform_env_t* env) {
                sched_point = sched_prev(node);
        }
 
-       store = new_rd_mips_store_r(env->dbg, env->irg, env->block, nomem, ptr, val, mode_T);
+       store = new_rd_mips_sw(env->dbg, env->irg, env->block, nomem, ptr, val);
        attr = get_mips_attr(store);
        attr->stack_entity = ent;
-       attr->modes.load_store_mode = get_irn_mode(val);
-
-       proj = new_rd_Proj(env->dbg, env->irg, env->block, store, mode_M, pn_Store_M);
 
        if (sched_point) {
                sched_add_after(sched_point, store);
-               sched_add_after(store, proj);
-
                sched_remove(node);
        }
 
-       exchange(node, proj);
+       exchange(node, store);
 }
 
 static void mips_transform_Reload(mips_transform_env_t* env) {
@@ -919,7 +896,6 @@ static void mips_transform_Reload(mips_transform_env_t* env) {
        ir_node   *load, *proj;
        ir_node   *ptr   = get_irn_n(node, 0);
        ir_node   *mem   = get_irn_n(node, 1);
-       ir_mode   *mode  = get_irn_mode(node);
        ir_entity *ent   = be_get_frame_entity(node);
        const arch_register_t* reg;
        mips_attr_t *attr;
@@ -928,12 +904,11 @@ static void mips_transform_Reload(mips_transform_env_t* env) {
                sched_point = sched_prev(node);
        }
 
-       load = new_rd_mips_load_r(env->dbg, env->irg, env->block, mem, ptr, mode_T);
+       load = new_rd_mips_lw(env->dbg, env->irg, env->block, mem, ptr);
        attr = get_mips_attr(load);
        attr->stack_entity = ent;
-       attr->modes.load_store_mode = mode;
 
-       proj = new_rd_Proj(env->dbg, env->irg, env->block, load, mode, pn_Load_res);
+       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);
@@ -949,6 +924,7 @@ static void mips_transform_Reload(mips_transform_env_t* env) {
        exchange(node, proj);
 }
 
+#if 0
 static ir_node *gen_node_for_StackParam(mips_transform_env_t *env)
 {
        ir_node *node = env->irn;
@@ -967,6 +943,7 @@ static ir_node *gen_node_for_StackParam(mips_transform_env_t *env)
 
        return proj;
 }
+#endif
 
 static ir_node *gen_node_for_AddSP(mips_transform_env_t *env)
 {
@@ -1018,7 +995,6 @@ void mips_transform_node(ir_node *node, void *env) {
        tenv.dbg      = get_irn_dbg_info(node);
        tenv.irg      = current_ir_graph;
        tenv.irn      = node;
-       DEBUG_ONLY(tenv.mod      = cgenv->mod;)
        tenv.mode     = get_irn_mode(node);
        tenv.cg           = cgenv;
 
@@ -1027,8 +1003,6 @@ void mips_transform_node(ir_node *node, void *env) {
 #define IGN(a)         case iro_##a: break
 #define BAD(a)         case iro_##a: goto bad
 
-       DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
-
        switch (code) {
                BINOP(Add, addu);
                BINOP(Sub, sub);
@@ -1096,6 +1070,10 @@ void mips_transform_node(ir_node *node, void *env) {
                asm_node = gen_node_for_Cond(&tenv);
                break;
 
+       case iro_Phi:
+               asm_node = gen_node_for_Phi(&tenv);
+               break;
+
                /* TODO: implement these nodes */
                BAD(Mux);
 
@@ -1111,7 +1089,6 @@ void mips_transform_node(ir_node *node, void *env) {
                IGN(Start);
                IGN(End);
                IGN(NoMem);
-               IGN(Phi);
                IGN(Break);
                IGN(Sync);
 
@@ -1134,7 +1111,7 @@ void mips_transform_node(ir_node *node, void *env) {
 
                default:
                        if(be_is_StackParam(node)) {
-                               asm_node = gen_node_for_StackParam(&tenv);
+                               //asm_node = gen_node_for_StackParam(&tenv);
                        } else if(be_is_AddSP(node)) {
                                asm_node = gen_node_for_AddSP(&tenv);
                        }
@@ -1147,9 +1124,6 @@ bad:
 
        if (asm_node != node) {
                exchange(node, asm_node);
-               DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
-       } else {
-               DB((tenv.mod, LEVEL_1, "ignored\n"));
        }
 }
 
@@ -1166,16 +1140,16 @@ void mips_pre_transform_node(ir_node *node, void *env) {
        tenv.dbg      = get_irn_dbg_info(node);
        tenv.irg      = current_ir_graph;
        tenv.irn      = node;
-       DEBUG_ONLY(tenv.mod      = cgenv->mod;)
        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) {
@@ -1205,11 +1179,9 @@ void mips_after_ra_walker(ir_node *node, void *env) {
        tenv.dbg   = get_irn_dbg_info(node);
        tenv.irg   = current_ir_graph;
        tenv.irn   = node;
-       DEBUG_ONLY(tenv.mod   = cg->mod;)
        tenv.mode  = get_irn_mode(node);
        tenv.cg    = cg;
 
-       /* be_is_StackParam(node) || */
        if (be_is_Reload(node)) {
                mips_transform_Reload(&tenv);
        } else if (be_is_Spill(node)) {