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