* @return The constructed ia32 node.
*/
static ir_node *gen_binop_x87_float(ir_node *node, ir_node *op1, ir_node *op2,
- construct_binop_float_func *func,
- match_flags_t flags)
+ construct_binop_float_func *func)
{
ir_mode *mode = get_irn_mode(node);
dbg_info *dbgi;
ir_node *block, *new_block, *new_node;
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
+ ia32_x87_attr_t *attr;
+ /* All operations are considered commutative, because there are reverse
+ * variants */
+ match_flags_t flags = match_commutative;
/* cannot use address mode with long double on x87 */
- if (get_mode_size_bits(mode) > 64)
- flags &= ~match_am;
+ if (get_mode_size_bits(mode) <= 64)
+ flags |= match_am;
block = get_nodes_block(node);
match_arguments(&am, block, op1, op2, NULL, flags);
am.new_op1, am.new_op2, get_fpcw());
set_am_attributes(new_node, &am);
+ attr = get_ia32_x87_attr(new_node);
+ attr->attr.data.ins_permuted = am.ins_permuted;
+
SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
new_node = fix_mem_proj(new_node, &am);
return gen_binop(node, op1, op2, new_rd_ia32_xAdd,
match_commutative | match_am);
else
- return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd,
- match_commutative | match_am);
+ return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd);
}
ia32_mark_non_am(node);
return gen_binop(node, op1, op2, new_rd_ia32_xMul,
match_commutative | match_am);
else
- return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul,
- match_commutative | match_am);
+ return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul);
}
return gen_binop(node, op1, op2, new_rd_ia32_IMul,
match_commutative | match_am | match_mode_neutral |
if (ia32_cg_config.use_sse2)
return gen_binop(node, op1, op2, new_rd_ia32_xSub, match_am);
else
- return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfsub,
- match_am);
+ return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfsub);
}
if (is_Const(op2)) {
if (ia32_cg_config.use_sse2) {
return gen_binop(node, op1, op2, new_rd_ia32_xDiv, match_am);
} else {
- return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfdiv, match_am);
+ return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfdiv);
}
}
int op2_idx = 0, op1_idx;
int out_idx, do_pop = 0;
ia32_x87_attr_t *attr;
+ int permuted;
ir_node *patched_insn;
ir_op *dst;
x87_simulator *sim = state->sim;
op1_live_after = is_vfp_live(arch_register_get_index(op1_reg), live);
}
+ attr = get_ia32_x87_attr(n);
+ permuted = attr->attr.data.ins_permuted;
+
if (reg_index_2 != REG_VFP_NOREG) {
+ assert(!permuted);
+
if(reg_index_2 == REG_VFP_UKNWN) {
op2_idx = 0;
op2_live_after = 1;
/* first operand is live: push it here */
x87_create_fpush(state, n, op1_idx, n_ia32_binary_left);
op1_idx = 0;
- /* use fxxx (tos = tos X mem) */
- dst = tmpl->normal_op;
- out_idx = 0;
} else {
/* first operand is dead: bring it to tos */
if (op1_idx != 0) {
x87_create_fxch(state, n, op1_idx);
op1_idx = 0;
}
-
- /* use fxxxp (tos = tos X mem) */
- dst = tmpl->normal_op;
- out_idx = 0;
}
+
+ /* use fxxx (tos = tos X mem) */
+ dst = permuted ? tmpl->reverse_op : tmpl->normal_op;
+ out_idx = 0;
}
patched_insn = x87_patch_insn(n, dst);
}
/* patch the operation */
- attr = get_ia32_x87_attr(n);
attr->x87[0] = op1_reg = &ia32_st_regs[op1_idx];
if (reg_index_2 != REG_VFP_NOREG) {
attr->x87[1] = op2_reg = &ia32_st_regs[op2_idx];