}
#endif /* NDEBUG */
-static int use_source_address_mode(ir_node *block, ir_node *node,
- ir_node *other)
+int use_source_address_mode(ir_node *block, ir_node *node, ir_node *other)
{
ir_mode *mode;
ir_node *load;
match_commutative = 1 << 0,
match_am_and_immediates = 1 << 1,
match_no_am = 1 << 2,
- match_8_16_bit_am = 1 << 3
+ match_8_16_bit_am = 1 << 3,
+ match_no_immediate = 1 << 4
} match_flags_t;
static void match_arguments(ia32_address_mode_t *am, ir_node *block,
int use_am;
int commutative;
int use_am_and_immediates;
+ int use_immediate;
memset(am, 0, sizeof(am[0]));
commutative = (flags & match_commutative) != 0;
use_am_and_immediates = (flags & match_am_and_immediates) != 0;
use_am = ! (flags & match_no_am);
+ use_immediate = !(flags & match_no_immediate);
+
+ assert(op2 != NULL);
+ assert(!commutative || op1 != NULL);
+
if(!(flags & match_8_16_bit_am)
+ && op1 != NULL
&& get_mode_size_bits(get_irn_mode(op1)) < 32)
use_am = 0;
- new_op2 = try_create_Immediate(op2, 0);
+ new_op2 = (use_immediate ? try_create_Immediate(op2, 0) : NULL);
if(new_op2 == NULL && use_am && use_source_address_mode(block, op2, op1)) {
build_address(am, op2);
- new_op1 = be_transform_node(op1);
+ new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
new_op2 = noreg_gp;
am->op_type = ia32_AddrModeS;
} else if(commutative && (new_op2 == NULL || use_am_and_immediates) &&
}
am->op_type = ia32_AddrModeS;
} else {
- new_op1 = be_transform_node(op1);
+ new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
if(new_op2 == NULL)
new_op2 = be_transform_node(op2);
am->op_type = ia32_Normal;
/* create a conv node with address mode for smaller modes */
if(get_mode_size_bits(mode) < 32) {
- new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index, new_mem,
- noreg, mode);
+ new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index,
+ new_mem, noreg, mode);
} else {
new_op = new_rd_ia32_Load(dbgi, irg, block, base, index, new_mem);
}
if(!is_Const_0(cmp_right))
return NULL;
- if(is_And(cmp_left) && can_fold_test_and(node)) {
+ if(is_And(cmp_left) && get_irn_n_edges(cmp_left) == 1 &&
+ can_fold_test_and(node)) {
ir_node *and_left = get_And_left(cmp_left);
ir_node *and_right = get_And_right(cmp_left);
* Create a conversion from general purpose to x87 register
*/
static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
- 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_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *noreg = ia32_new_NoReg_gp(env_cg);
- ir_node *nomem = new_NoMem();
- ir_mode *mode = get_irn_mode(op);
- ir_mode *store_mode;
- ir_node *fild, *store;
- ir_node *res;
- int src_bits;
+ ir_node *src_block = get_nodes_block(node);
+ ir_node *block = be_transform_node(src_block);
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *op = get_Conv_op(node);
+ ir_node *new_op;
+ ir_node *noreg;
+ ir_node *nomem;
+ ir_mode *mode;
+ ir_mode *store_mode;
+ ir_node *fild;
+ ir_node *store;
+ ir_node *res;
+ int src_bits;
+
+ /* fild can use source AM if the operand is a signed 32bit integer */
+ if (src_mode == mode_Is) {
+ ia32_address_mode_t am;
+
+ match_arguments(&am, src_block, NULL, op, match_no_immediate);
+ if (am.op_type == ia32_AddrModeS) {
+ ia32_address_t *addr = &am.addr;
+
+ fild = new_rd_ia32_vfild(dbgi, irg, block, addr->base, addr->index, addr->mem);
+ res = new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
+
+ set_am_attributes(fild, &am);
+ SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node));
+
+ fix_mem_proj(fild, &am);
+
+ return res;
+ }
+ new_op = am.new_op2;
+ } else {
+ new_op = be_transform_node(op);
+ }
+
+ noreg = ia32_new_NoReg_gp(env_cg);
+ nomem = new_NoMem();
+ mode = get_irn_mode(op);
/* first convert to 32 bit signed if necessary */
src_bits = get_mode_size_bits(src_mode);
new_op = noreg;
am.op_type = ia32_AddrModeS;
} else {
- new_op = be_transform_node(op);
+ new_op = be_transform_node(op);
am.op_type = ia32_Normal;
}
if(addr->base == NULL)
case 'y': /* we don't support mmx registers yet */
case 'Z': /* not available in 32 bit mode */
case 'e': /* not available in 32 bit mode */
- assert(0 && "asm constraint not supported");
+ panic("unsupported asm constraint '%c' found in (%+F)",
+ *c, current_ir_graph);
break;
default:
- assert(0 && "unknown asm constraint found");
+ panic("unknown asm constraint '%c' found in (%+F)", *c,
+ current_ir_graph);
break;
}
++c;
req->cls = other_constr->cls;
req->type = arch_register_req_type_should_be_same;
req->limited = NULL;
- req->other_same = pos;
+ req->other_same[0] = pos;
+ req->other_same[1] = -1;
req->other_different = -1;
/* switch constraints. This is because in firm we have same_as
return muls;
}
-static ir_node *gen_ia32_Add64Bit(ir_node *node)
-{
- ir_node *a_l = be_transform_node(get_irn_n(node, 0));
- ir_node *a_h = be_transform_node(get_irn_n(node, 1));
- ir_node *b_l = create_immediate_or_transform(get_irn_n(node, 2), 0);
- ir_node *b_h = create_immediate_or_transform(get_irn_n(node, 3), 0);
- ir_node *block = be_transform_node(get_nodes_block(node));
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_graph *irg = current_ir_graph;
- ir_node *new_op = new_rd_ia32_Add64Bit(dbgi, irg, block, a_l, a_h, b_l, b_h);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
- return new_op;
+static ir_node *gen_ia32_l_Sub(ir_node *node) {
+ ir_node *left = get_irn_n(node, n_ia32_l_Sub_left);
+ ir_node *right = get_irn_n(node, n_ia32_l_Sub_right);
+ ir_node *lowered = gen_binop(node, left, right, new_rd_ia32_Sub, 0);
+
+ if(is_Proj(lowered)) {
+ lowered = get_Proj_pred(lowered);
+ } else {
+ assert(is_ia32_Sub(lowered));
+ set_irn_mode(lowered, mode_T);
+ }
+
+ return lowered;
}
-static ir_node *gen_ia32_Sub64Bit(ir_node *node)
-{
- ir_node *a_l = be_transform_node(get_irn_n(node, 0));
- ir_node *a_h = be_transform_node(get_irn_n(node, 1));
- ir_node *b_l = create_immediate_or_transform(get_irn_n(node, 2), 0);
- ir_node *b_h = create_immediate_or_transform(get_irn_n(node, 3), 0);
- ir_node *block = be_transform_node(get_nodes_block(node));
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_graph *irg = current_ir_graph;
- ir_node *new_op = new_rd_ia32_Sub64Bit(dbgi, irg, block, a_l, a_h, b_l, b_h);
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
- return new_op;
+static ir_node *gen_ia32_l_Sbb(ir_node *node) {
+ ir_node *src_block = get_nodes_block(node);
+ ir_node *block = be_transform_node(src_block);
+ ir_node *op1 = get_irn_n(node, n_ia32_l_Sbb_left);
+ ir_node *op2 = get_irn_n(node, n_ia32_l_Sbb_right);
+ ir_node *flags = get_irn_n(node, n_ia32_l_Sbb_eflags);
+ ir_node *new_flags = be_transform_node(flags);
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *new_node;
+ ia32_address_mode_t am;
+ ia32_address_t *addr = &am.addr;
+
+ match_arguments(&am, src_block, op1, op2, match_commutative);
+
+ new_node = new_rd_ia32_Sbb(dbgi, irg, block, addr->base, addr->index,
+ addr->mem, am.new_op1, am.new_op2, new_flags);
+ set_am_attributes(new_node, &am);
+ /* we can't use source address mode anymore when using immediates */
+ if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
+ set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
+ SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+
+ new_node = fix_mem_proj(new_node, &am);
+
+ return new_node;
}
/**
GEN(IJmp);
/* transform ops from intrinsic lowering */
- GEN(ia32_Add64Bit);
- GEN(ia32_Sub64Bit);
GEN(ia32_l_Add);
GEN(ia32_l_Adc);
GEN(ia32_l_Neg);
GEN(ia32_l_SarDep);
GEN(ia32_l_ShlD);
GEN(ia32_l_ShrD);
+ GEN(ia32_l_Sub);
+ GEN(ia32_l_Sbb);
GEN(ia32_l_vfdiv);
GEN(ia32_l_vfprem);
GEN(ia32_l_vfmul);
/* do the transformation */
void ia32_transform_graph(ia32_code_gen_t *cg) {
+ ir_graph *irg = cg->irg;
+
register_transformers();
env_cg = cg;
initial_fpcw = NULL;
- heights = heights_new(cg->irg);
+ heights = heights_new(irg);
+ calculate_non_address_mode_nodes(irg);
be_transform_graph(cg->birg, ia32_pretransform_node, cg);
+ free_non_address_mode_nodes();
heights_free(heights);
heights = NULL;
}