MATCH_SIZE_NEUTRAL = 1 << 1,
} match_flags_t;
-typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
-typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot);
+/**
+ * possible binop constructors.
+ */
+typedef struct arm_binop_factory_t {
+ /** normal reg op reg operation. */
+ ir_node *(*new_binop_reg)(dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
+ /** normal reg op imm operation. */
+ ir_node *(*new_binop_imm)(dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot);
+ /** barrel shifter reg op (reg shift reg operation. */
+ ir_node *(*new_binop_reg_shift_reg)(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right, ir_node *shift, arm_shift_modifier_t shift_modifier);
+ /** barrel shifter reg op (reg shift imm operation. */
+ ir_node *(*new_binop_reg_shift_imm)(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right, arm_shift_modifier_t shift_modifier, unsigned shift_immediate);
+} arm_binop_factory_t;
static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
- new_binop_reg_func new_reg, new_binop_imm_func new_imm)
+ const arm_binop_factory_t *factory)
{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *op1 = get_binop_left(node);
if (try_encode_as_immediate(op2, &imm)) {
ir_node *new_op1 = be_transform_node(op1);
- return new_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
+ return factory->new_binop_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
}
new_op2 = be_transform_node(op2);
if ((flags & MATCH_COMMUTATIVE) && try_encode_as_immediate(op1, &imm)) {
- return new_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
+ return factory->new_binop_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
}
new_op1 = be_transform_node(op1);
- return new_reg(dbgi, block, new_op1, new_op2);
+ /* check if we can fold in a Mov */
+ if (is_arm_Mov(new_op2)) {
+ const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(new_op2);
+
+ switch (attr->shift_modifier) {
+ ir_node *mov_op, *mov_sft;
+
+ case ARM_SHF_IMM:
+ case ARM_SHF_ASR_IMM:
+ case ARM_SHF_LSL_IMM:
+ case ARM_SHF_LSR_IMM:
+ case ARM_SHF_ROR_IMM:
+ if (factory->new_binop_reg_shift_imm) {
+ mov_op = get_irn_n(new_op2, 0);
+ return factory->new_binop_reg_shift_imm(dbgi, block, new_op1, mov_op,
+ attr->shift_modifier, attr->shift_immediate);
+ }
+ break;
+
+ case ARM_SHF_ASR_REG:
+ case ARM_SHF_LSL_REG:
+ case ARM_SHF_LSR_REG:
+ case ARM_SHF_ROR_REG:
+ if (factory->new_binop_reg_shift_reg) {
+ mov_op = get_irn_n(new_op2, 0);
+ mov_sft = get_irn_n(new_op2, 1);
+ return factory->new_binop_reg_shift_reg(dbgi, block, new_op1, mov_op, mov_sft,
+ attr->shift_modifier);
+ }
+ break;
+ }
+ }
+ if ((flags & MATCH_COMMUTATIVE) && is_arm_Mov(new_op1)) {
+ const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(new_op1);
+
+ switch (attr->shift_modifier) {
+ ir_node *mov_op, *mov_sft;
+
+ case ARM_SHF_IMM:
+ case ARM_SHF_ASR_IMM:
+ case ARM_SHF_LSL_IMM:
+ case ARM_SHF_LSR_IMM:
+ case ARM_SHF_ROR_IMM:
+ if (factory->new_binop_reg_shift_imm) {
+ mov_op = get_irn_n(new_op1, 0);
+ return factory->new_binop_reg_shift_imm(dbgi, block, new_op2, mov_op,
+ attr->shift_modifier, attr->shift_immediate);
+ }
+ break;
+
+ case ARM_SHF_ASR_REG:
+ case ARM_SHF_LSL_REG:
+ case ARM_SHF_LSR_REG:
+ case ARM_SHF_ROR_REG:
+ if (factory->new_binop_reg_shift_reg) {
+ mov_op = get_irn_n(new_op1, 0);
+ mov_sft = get_irn_n(new_op1, 1);
+ return factory->new_binop_reg_shift_reg(dbgi, block, new_op2, mov_op, mov_sft,
+ attr->shift_modifier);
+ }
+ break;
+ }
+ }
+ return factory->new_binop_reg(dbgi, block, new_op1, new_op2);
}
/**
*/
static ir_node *gen_Add(ir_node *node)
{
- ir_mode *mode = get_irn_mode(node);
+ static const arm_binop_factory_t add_factory = {
+ new_bd_arm_Add_reg,
+ new_bd_arm_Add_imm,
+ new_bd_arm_Add_reg_shift_reg,
+ new_bd_arm_Add_reg_shift_imm
+ };
+
+ ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
ir_node *block = be_transform_node(get_nodes_block(node));
}
#endif
- return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
- new_bd_arm_Add_reg, new_bd_arm_Add_imm);
+ return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &add_factory);
}
}
static ir_node *gen_And(ir_node *node)
{
- return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
- new_bd_arm_And_reg, new_bd_arm_And_imm);
+ static const arm_binop_factory_t and_factory = {
+ new_bd_arm_And_reg,
+ new_bd_arm_And_imm,
+ new_bd_arm_And_reg_shift_reg,
+ new_bd_arm_And_reg_shift_imm
+ };
+
+ return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &and_factory);
}
static ir_node *gen_Or(ir_node *node)
{
- return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
- new_bd_arm_Or_reg, new_bd_arm_Or_imm);
+ static const arm_binop_factory_t or_factory = {
+ new_bd_arm_Or_reg,
+ new_bd_arm_Or_imm,
+ new_bd_arm_Or_reg_shift_reg,
+ new_bd_arm_Or_reg_shift_imm
+ };
+
+ return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &or_factory);
}
static ir_node *gen_Eor(ir_node *node)
{
- return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
- new_bd_arm_Eor_reg, new_bd_arm_Eor_imm);
+ static const arm_binop_factory_t eor_factory = {
+ new_bd_arm_Eor_reg,
+ new_bd_arm_Eor_imm,
+ new_bd_arm_Eor_reg_shift_reg,
+ new_bd_arm_Eor_reg_shift_imm
+ };
+
+ return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &eor_factory);
}
static ir_node *gen_Sub(ir_node *node)
{
+ static const arm_binop_factory_t sub_factory = {
+ new_bd_arm_Sub_reg,
+ new_bd_arm_Sub_imm,
+ new_bd_arm_Sub_reg_shift_reg,
+ new_bd_arm_Sub_reg_shift_imm
+ };
+
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *op1 = get_Sub_left(node);
ir_node *new_op1 = be_transform_node(op1);
panic("Softfloat not supported yet");
}
} else {
- return gen_int_binop(node, MATCH_SIZE_NEUTRAL,
- new_bd_arm_Sub_reg, new_bd_arm_Sub_imm);
+ return gen_int_binop(node, MATCH_SIZE_NEUTRAL, &sub_factory);
}
}
ir_node *call = get_Proj_pred(get_Proj_pred(node));
ir_node *new_call = be_transform_node(call);
ir_type *function_type = get_Call_type(call);
- calling_convention_t *cconv = decide_calling_convention(function_type);
+ calling_convention_t *cconv = arm_decide_calling_convention(function_type);
const reg_or_stackslot_t *res = &cconv->results[pn];
ir_mode *mode;
int regn;
}
mode = res->reg0->reg_class->mode;
- free_calling_convention(cconv);
+ arm_free_calling_convention(cconv);
return new_r_Proj(new_call, mode, regn);
}
ir_node *new_mem = be_transform_node(mem);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_type *type = get_Call_type(node);
- calling_convention_t *cconv = decide_calling_convention(type);
+ calling_convention_t *cconv = arm_decide_calling_convention(type);
int n_params = get_Call_n_params(node);
int n_param_regs = sizeof(param_regs)/sizeof(param_regs[0]);
/* max inputs: memory, callee, register arguments */
/* copy pinned attribute */
set_irn_pinned(res, get_irn_pinned(node));
- free_calling_convention(cconv);
+ arm_free_calling_convention(cconv);
return res;
}
abihelper = be_abihelper_prepare(irg);
be_collect_stacknodes(abihelper);
assert(cconv == NULL);
- cconv = decide_calling_convention(get_entity_type(entity));
+ cconv = arm_decide_calling_convention(get_entity_type(entity));
create_stacklayout(irg);
be_transform_graph(cg->irg, NULL);
be_abihelper_finish(abihelper);
abihelper = NULL;
- free_calling_convention(cconv);
+ arm_free_calling_convention(cconv);
cconv = NULL;
frame_type = get_irg_frame_type(irg);