X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fmips%2Fmips_transform.c;h=190d26a4de15a8abb15f7f036fec2aa49ca76b5d;hb=29bb6875dc277a493d3764d1ef69d05100de03c0;hp=10c38c3f2f5c38b754b1b0d1d048de11b670a5ff;hpb=4d5c3365a58cba59993045a9e08e686d8ae079a7;p=libfirm diff --git a/ir/be/mips/mips_transform.c b/ir/be/mips/mips_transform.c index 10c38c3f2..190d26a4d 100644 --- a/ir/be/mips/mips_transform.c +++ b/ir/be/mips/mips_transform.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -17,9 +17,12 @@ * PURPOSE. */ -/* The codegenrator (transform FIRM into mips FIRM */ -/* $Id$ */ - +/** + * @file + * @brief The codegenrator (transform FIRM into mips FIRM + * @author Matthias Braun, Mehdi + * @version $Id$ + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -33,19 +36,22 @@ #include "iredges.h" #include "irvrfy.h" #include "ircons.h" -#include "dbginfo.h" +#include "irprintf.h" +#include "irop.h" #include "iropt_t.h" #include "debug.h" +#include "error.h" #include "../benode_t.h" #include "../beabi.h" #include "../besched.h" #include "../besched_t.h" #include "../beirg_t.h" +#include "../betranshlp.h" #include "bearch_mips_t.h" #include "mips_nodes_attr.h" -#include "../arch/archop.h" /* we need this for Min and Max nodes */ +#include "archop.h" #include "mips_transform.h" #include "mips_new_nodes.h" #include "mips_map_regs.h" @@ -54,6 +60,9 @@ #include "gen_mips_regalloc_if.h" +/** hold the current code generator during transformation */ +static mips_code_gen_t *env_cg = NULL; + /**************************************************************************************************** * _ _ __ _ _ * | | | | / _| | | (_) @@ -64,355 +73,517 @@ * ****************************************************************************************************/ -#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); \ - } - -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); \ - } +typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, + ir_node *block, ir_node *left, ir_node *right); -MIPS_GENUNFUNC(not) +static INLINE int mode_needs_gp_reg(ir_mode *mode) { + return mode_is_int(mode) || mode_is_reference(mode); +} -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); +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; + + 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; } -static ir_node* gen_zero_node(mips_transform_env_t *env, dbg_info *ebg, ir_graph *irg, ir_node *block) +ir_node* mips_create_zero(void) { - 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 = 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); + + 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 *lui; - ir_node *lli; - mips_attr_t *attr; - ir_mode* mode = get_irn_mode(constant); - unsigned long val, lower, upper; + tarval *tv; + long val; + ir_mode *mode; - val = get_tarval_long(tv); - if(val == 0) - return gen_zero_node(env, dbg, irg, block); + if(!is_Const(node)) + return NULL; - 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); + mode = get_irn_mode(node); + if(!mode_needs_gp_reg(mode)) + return NULL; - return lli; + tv = get_Const_tarval(node); + if(tarval_is_long(tv)) { + val = get_tarval_long(tv); + } else { + ir_fprintf(stderr, "Optimisation Warning: tarval %+F is not a long?\n", + node); + return NULL; } - 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; - - lli = new_rd_mips_lli(dbg, irg, block, lui); - attr = get_mips_attr(lli); - attr->tv = new_tarval_from_long(val, mode); + if(val < -32768 || val > 32767) + return NULL; - return lli; + return mips_create_Immediate(val); } -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); +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; + } } - return gen_node_for_Const(env, dbg, irg, block, pred); + *new_left = be_transform_node(left); + *new_right = be_transform_node(right); } -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; - - if (is_Phi(node)) { - ir_node *phipred = get_nodes_block(node); - block = get_Block_cfgpred_block(phipred, n); +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 { - block = get_nodes_block(node); + new_left = be_transform_node(left); + new_right = be_transform_node(right); } - 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; - } + res = func(dbgi, irg, block, new_left, new_right); - // TODO - assert(0); - return NULL; + return res; } -/** - * 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; - - ASSERT_NO_FLOAT(get_irn_mode(node)); +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); +} - mode = get_Load_mode(node); - assert(mode->vector_elem == 1); - assert(mode->sort == irms_int_number || mode->sort == irms_reference); +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); +} - 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)); +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); +} - attr = get_mips_attr(result); - attr->tv = new_tarval_from_long(0, mode_Iu); - attr->modes.load_store_mode = mode; +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); +} - return result; +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); } -/** - * 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; +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); +} - ASSERT_NO_FLOAT(env->mode); +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); +} - 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); +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); +} - 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); +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); } - attr = get_mips_attr(result); - attr->tv = new_tarval_from_long(0, mode_Iu); - attr->modes.load_store_mode = mode; - return result; + /* 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_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; +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; +} - n = get_Proj_proj(proj); +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); - // 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; + return xor; +} - // 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); +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(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); + if(tarval_is_long(tv)) { + val = get_tarval_long(tv); + } else { + panic("Can't get value of tarval %+F\n", node); } - return proj; -} + val = get_tarval_long(tv); -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)); + lower = val & 0xffff; + upper = (val >> 16) & 0xffff; + if(upper == 0) { + upper_node = mips_create_zero(); + } else { + upper_node = new_rd_mips_lui(dbgi, irg, block, MIPS_IMM_CONST, NULL, + upper); + } - edge = get_irn_out_edge_first(node); - next_block = get_edge_src_irn(edge); + if(lower == 0) + return upper_node; - 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); - } + or_const = mips_create_Immediate(lower); + lower_node = new_rd_mips_or(dbgi, irg, block, upper_node, or_const); - return new_rd_mips_b(env->dbg, env->irg, env->block, mode_X); + return lower_node; } -static ir_node *gen_node_for_Cond_Proj(mips_transform_env_t *env, ir_node* node, int true_false) +static ir_node* gen_SymConst(ir_node *node) { - // 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; + 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, *or_const, *or; + + if(get_SymConst_kind(node) != symconst_addr_ent) { + panic("Only address entity symconsts supported in mips backend"); + } - n = get_Proj_proj(proj); - assert(n < 8 && "Only ordered comps supported"); + entity = get_SymConst_entity(node); - assert(get_irn_opcode(original_cmp) == iro_Cmp); - op1 = get_Cmp_left(original_cmp); - op2 = get_Cmp_right(original_cmp); + 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); - switch(n) { - case pn_Cmp_False: - if(true_false) - return NULL; + return or; +} - return make_jmp_or_fallthrough(env); +typedef ir_node* (*gen_load_func) (dbg_info *dbg, ir_graph *irg, + ir_node *block, ir_node *ptr, ir_node *mem, + ir_entity *entity, long offset); - case pn_Cmp_Eq: - if(!true_false) - return make_jmp_or_fallthrough(env); +/** + * Generates a mips node for a firm Load node + */ +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(mode); + assert(mode_needs_gp_reg(mode)); + + /* TODO: make use of offset in ptrs */ + + 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"); + } - condjmp = new_rd_mips_beq(dbg, irg, block, op1, op2, mode_T); - return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1); + res = func(dbgi, irg, block, new_ptr, new_mem, NULL, 0); + set_irn_pinned(res, get_irn_pinned(node)); - case pn_Cmp_Lt: - if(!true_false) - return make_jmp_or_fallthrough(env); + return res; +} - 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); +typedef ir_node* (*gen_store_func) (dbg_info *dbg, ir_graph *irg, + ir_node *block, ir_node *ptr, ir_node *val, + ir_node *mem, ir_entity *ent, long offset); - case pn_Cmp_Le: - if(!true_false) - return make_jmp_or_fallthrough(env); +/** + * Generates a mips node for a firm Store node + */ +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 *res; + + assert(mode_needs_gp_reg(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"); + } - 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); + res = func(dbgi, irg, block, new_ptr, new_val, new_mem, NULL, 0); + set_irn_pinned(res, get_irn_pinned(node)); - case pn_Cmp_Gt: - if(!true_false) - return make_jmp_or_fallthrough(env); + return res; +} - 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); +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; - case pn_Cmp_Ge: - if(!true_false) - return make_jmp_or_fallthrough(env); + assert(is_mips_div(new_div) || is_mips_divu(new_div)); - 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); + 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; + } - case pn_Cmp_Lg: - if(!true_false) - return make_jmp_or_fallthrough(env); + 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; + } - condjmp = new_rd_mips_bne(dbg, irg, block, op1, op2, mode_T); - return new_rd_Proj(dbg, irg, block, condjmp, mode_X, 1); + panic("invalid proj attached to %+F\n", divmod); +} - case pn_Cmp_Leg: - if(!true_false) - return NULL; +static ir_node *gen_Proj_Start(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)); + 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(node == get_irg_anchor(irg, anchor_tls)) { + /* TODO... */ + return be_duplicate_node(node); + } + return be_duplicate_node(node); +} - return make_jmp_or_fallthrough(env); +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); + + 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(0); + 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 NULL; + return be_duplicate_node(node); } -static ir_node *gen_node_for_Proj(mips_transform_env_t *env) +static ir_node *gen_Phi(ir_node *node) { - ir_node *proj = env->irn; - long n; - 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(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); - } + 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 proj; + /* 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; } -static ir_node *gen_node_for_Cond(mips_transform_env_t *env) +#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); @@ -511,154 +682,157 @@ 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; - - 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); - - 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; +static ir_node *gen_Cond(ir_node *node) +{ + 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; + + /* 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"); - 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_Eq: + res = new_rd_mips_beq(dbgi, irg, block, new_left, new_right); + break; - return value_proj; -} + case pn_Cmp_Lt: + 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; -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; + case pn_Cmp_Le: + 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; - 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); + case pn_Cmp_Gt: + 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; - return result; -} + case pn_Cmp_Ge: + 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; -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; + case pn_Cmp_Lg: + res = new_rd_mips_bne(dbgi, irg, block, new_left, new_right); + break; - pred = get_Conv_op(node); - srcmode = get_irn_mode(pred); - destmode = get_irn_mode(node); + default: + panic("mips backend doesn't handle unordered compares yet"); + } - dst_size = get_mode_size_bits(destmode); - src_size = get_mode_size_bits(srcmode); + return res; +} - 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); +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; + + assert(mode_needs_gp_reg(src_mode)); + assert(mode_needs_gp_reg(dst_mode)); + + /* we only need to do something on upconvs */ + if(src_size >= dst_size) { + /* unnecessary conv */ + return new_op; } - 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); + + 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; @@ -683,33 +857,19 @@ 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; - - return new_rd_mips_j(env->dbg, env->irg, env->block, get_IJmp_target(node), node->mode); -} +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); -static ir_node *gen_node_for_Jmp(mips_transform_env_t *env) { - return make_jmp_or_fallthrough(env); + return new_rd_mips_jr(dbg, irg, block, target); } -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) { +static +ir_node *gen_node_for_Rot(mips_transform_env_t *env) { ir_node *node = env->irn; ir_node *subu, *srlv, *sllv, *or; @@ -720,12 +880,16 @@ static 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_node(env, env->dbg, env->irg, env->block); + (void) node; + assert(mode_needs_gp_reg(get_irn_mode(node))); + return mips_create_zero(); } +#if 0 /* * lower a copyB into standard Firm assembler :-) */ @@ -878,36 +1042,30 @@ 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); 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_store_r(env->dbg, env->irg, env->block, nomem, ptr, val, mode_T); - 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); + 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); - sched_add_after(store, proj); - sched_remove(node); } - exchange(node, proj); + exchange(node, store); } static void mips_transform_Reload(mips_transform_env_t* env) { @@ -916,25 +1074,19 @@ 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; if(sched_is_scheduled(node)) { sched_point = sched_prev(node); } - load = new_rd_mips_load_r(env->dbg, env->irg, env->block, mem, ptr, mode_T); - attr = get_mips_attr(load); - attr->stack_entity = ent; - attr->modes.load_store_mode = mode; + 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, 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); - sched_add_after(load, proj); sched_remove(node); } @@ -946,26 +1098,8 @@ static void mips_transform_Reload(mips_transform_env_t* env) { exchange(node, proj); } -static ir_node *gen_node_for_StackParam(mips_transform_env_t *env) -{ - ir_node *node = env->irn; - ir_node *sp = get_irn_n(node, 0); - ir_node *load; - ir_node *nomem = new_rd_NoMem(env->irg); - ir_node *proj; - mips_attr_t *attr; - - load = new_rd_mips_load_r(env->dbg, env->irg, env->block, nomem, sp, mode_T); - attr = get_mips_attr(load); - attr->stack_entity = be_get_frame_entity(node); - attr->modes.load_store_mode = env->mode; - - proj = new_rd_Proj(env->dbg, env->irg, env->block, load, env->mode, pn_Load_res); - - return proj; -} - -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; @@ -983,6 +1117,7 @@ static ir_node *gen_node_for_AddSP(mips_transform_env_t *env) return add; } +#endif /********************************************************* * _ _ _ @@ -994,198 +1129,59 @@ static ir_node *gen_node_for_AddSP(mips_transform_env_t *env) * *********************************************************/ - -/** - * Transforms the given firm node (and maybe some other related nodes) - * into one or more assembler nodes. - * - * @param node the firm node - * @param env the debug module - */ -void mips_transform_node(ir_node *node, void *env) { - mips_code_gen_t *cgenv = (mips_code_gen_t *)env; - ir_opcode code = get_irn_opcode(node); - ir_node *asm_node = node; - 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; - DEBUG_ONLY(tenv.mod = cgenv->mod;) - tenv.mode = get_irn_mode(node); - tenv.cg = cgenv; - -#define UNOP(firm_opcode, mips_nodetype) case iro_##firm_opcode: asm_node = mips_gen_##mips_nodetype(&tenv, get_##firm_opcode##_op(node)); break -#define BINOP(firm_opcode, mips_nodetype) case iro_##firm_opcode: asm_node = mips_gen_##mips_nodetype(&tenv, get_##firm_opcode##_left(node), get_##firm_opcode##_right(node)); break -#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); - BINOP(And, and); - BINOP(Or, or); - BINOP(Eor, xor); - UNOP(Not, not); - BINOP(Shl, sl); - BINOP(Shr, sr); - BINOP(Shrs, sra); - - case iro_Abs: - asm_node = gen_node_for_Abs(&tenv); - break; - - case iro_Rot: - asm_node = gen_node_for_Rot(&tenv); - break; - - case iro_Div: - asm_node = gen_node_for_Div(&tenv); - break; - - case iro_Mod: - asm_node = gen_node_for_Mod(&tenv); - break; - - case iro_Load: - asm_node = gen_node_for_Load(&tenv); - break; - - case iro_Store: - asm_node = gen_node_for_Store(&tenv); - break; - - case iro_Proj: - asm_node = gen_node_for_Proj(&tenv); - break; - - case iro_Conv: - asm_node = gen_node_for_Conv(&tenv); - break; - - case iro_DivMod: - asm_node = gen_node_for_DivMod(&tenv); - break; - - case iro_Mul: - asm_node = gen_node_for_Mul(&tenv); - break; - - case iro_Jmp: - asm_node = gen_node_for_Jmp(&tenv); - break; - - case iro_IJmp: - asm_node = gen_node_for_IJmp(&tenv); - break; - - case iro_Unknown: - asm_node = gen_node_for_Unknown(&tenv); - break; - - case iro_Cond: - asm_node = gen_node_for_Cond(&tenv); - break; - - /* TODO: implement these nodes */ - BAD(Mux); - - /* You probably don't need to handle the following nodes */ - - // call is handled in the emit phase - IGN(Call); - // Cmp is handled together with Cond - IGN(Cmp); - IGN(Alloc); - - IGN(Block); - IGN(Start); - IGN(End); - IGN(NoMem); - IGN(Phi); - IGN(Break); - IGN(Sync); - - IGN(Const); - IGN(SymConst); - - BAD(Raise); - BAD(Sel); - BAD(InstOf); - BAD(Cast); - BAD(Free); - BAD(Tuple); - BAD(Id); - BAD(Bad); - BAD(Confirm); - BAD(Filter); - BAD(CallBegin); - BAD(EndReg); - BAD(EndExcept); - - default: - if(be_is_StackParam(node)) { - asm_node = gen_node_for_StackParam(&tenv); - } else if(be_is_AddSP(node)) { - asm_node = gen_node_for_AddSP(&tenv); - } - break; - -bad: - fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node)); - assert(0); - } - - 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")); - } +static ir_node *gen_Bad(ir_node *node) +{ + panic("Unexpected node %+F found in mips transform phase.\n", node); + return NULL; } -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; - DEBUG_ONLY(tenv.mod = cgenv->mod;) - tenv.mode = get_irn_mode(node); - tenv.cg = cgenv; - - if(is_Proj(node)) { - ir_node* pred = get_Proj_pred(node); - - if(get_irn_opcode(pred) == iro_CopyB) { - mips_fix_CopyB_Proj(&tenv); - } - } - - for(i = 0; i < get_irn_arity(node); ++i) { - ir_node* pred = get_irn_n(node, i); +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 (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, i); - 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); } /** @@ -1202,11 +1198,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)) {