Commit 90ffdc64 authored by Matthias Braun's avatar Matthias Braun
Browse files

amd64: fix Div/IDiv missing memory input

This should fix firm-testsuite/fehler242.c
parent 511aff19
...@@ -157,7 +157,9 @@ Div => { ...@@ -157,7 +157,9 @@ Div => {
arity => "variable", arity => "variable",
outs => [ "res_div", "flags", "M", "res_mod" ], outs => [ "res_div", "flags", "M", "res_mod" ],
attr_type => "amd64_addr_attr_t", attr_type => "amd64_addr_attr_t",
attr => "amd64_insn_mode_t insn_mode, amd64_op_mode_t op_mode, amd64_addr_t addr", fixed => "amd64_addr_t addr = { { NULL, 0 }, NO_INPUT, NO_INPUT, NO_INPUT, 0, AMD64_SEGMENT_DEFAULT };\n"
."amd64_op_mode_t op_mode = AMD64_OP_RAX_REG;\n",
attr => "amd64_insn_mode_t insn_mode",
emit => "div%M %AM", emit => "div%M %AM",
modified_flags => $status_flags, modified_flags => $status_flags,
}, },
...@@ -168,7 +170,9 @@ IDiv => { ...@@ -168,7 +170,9 @@ IDiv => {
arity => "variable", arity => "variable",
outs => [ "res_div", "flags", "M", "res_mod" ], outs => [ "res_div", "flags", "M", "res_mod" ],
attr_type => "amd64_addr_attr_t", attr_type => "amd64_addr_attr_t",
attr => "amd64_insn_mode_t insn_mode, amd64_op_mode_t op_mode, amd64_addr_t addr", fixed => "amd64_addr_t addr = { { NULL, 0 }, NO_INPUT, NO_INPUT, NO_INPUT, 0, AMD64_SEGMENT_DEFAULT };\n"
."amd64_op_mode_t op_mode = AMD64_OP_RAX_REG;\n",
attr => "amd64_insn_mode_t insn_mode",
emit => "idiv%M %AM", emit => "idiv%M %AM",
modified_flags => $status_flags, modified_flags => $status_flags,
}, },
......
...@@ -199,10 +199,11 @@ static const arch_register_req_t *rax_reg_reqs[] = { ...@@ -199,10 +199,11 @@ static const arch_register_req_t *rax_reg_reqs[] = {
&amd64_requirement_gp, &amd64_requirement_gp,
}; };
static const arch_register_req_t *rax_reg_rdx_reqs[] = { static const arch_register_req_t *rax_reg_rdx_mem_reqs[] = {
&amd64_requirement_rax, &amd64_requirement_rax,
&amd64_requirement_gp, &amd64_requirement_gp,
&amd64_requirement_rdx, &amd64_requirement_rdx,
&arch_no_requirement,
}; };
static const arch_register_req_t *reg_reqs[] = { static const arch_register_req_t *reg_reqs[] = {
...@@ -684,17 +685,6 @@ static ir_node *gen_binop_am(ir_node *node, ir_node *op1, ir_node *op2, ...@@ -684,17 +685,6 @@ static ir_node *gen_binop_am(ir_node *node, ir_node *op1, ir_node *op2,
} }
} }
/* Transform arguments for a binop using RAX and register as input */
static void gen_binop_rax_reg(ir_node *op1, ir_node *op2, ir_node **in,
int *arity, amd64_op_mode_t *op_mode,
const arch_register_req_t ***reqs)
{
in[(*arity)++] = be_transform_node(op1);
in[(*arity)++] = be_transform_node(op2);
*reqs = rax_reg_reqs;
*op_mode = AMD64_OP_RAX_REG;
}
static ir_node *gen_binop_rax(ir_node *node, ir_node *op1, ir_node *op2, static ir_node *gen_binop_rax(ir_node *node, ir_node *op1, ir_node *op2,
construct_rax_binop_func make_node, construct_rax_binop_func make_node,
match_flags_t flags) match_flags_t flags)
...@@ -752,7 +742,10 @@ static ir_node *gen_binop_rax(ir_node *node, ir_node *op1, ir_node *op2, ...@@ -752,7 +742,10 @@ static ir_node *gen_binop_rax(ir_node *node, ir_node *op1, ir_node *op2,
op_mode = AMD64_OP_RAX_ADDR; op_mode = AMD64_OP_RAX_ADDR;
} else { } else {
/* simply transform the arguments */ /* simply transform the arguments */
gen_binop_rax_reg(op1, op2, in, &arity, &op_mode, &reqs); in[arity++] = be_transform_node(op1);
in[arity++] = be_transform_node(op2);
reqs = rax_reg_reqs;
op_mode = AMD64_OP_RAX_REG;
} }
assert((size_t)arity <= ARRAY_SIZE(in)); assert((size_t)arity <= ARRAY_SIZE(in));
...@@ -1004,7 +997,8 @@ static ir_node *gen_Shrs(ir_node *const node) ...@@ -1004,7 +997,8 @@ static ir_node *gen_Shrs(ir_node *const node)
} }
static ir_node *create_div(ir_node *const node, ir_mode *const mode, static ir_node *create_div(ir_node *const node, ir_mode *const mode,
ir_node *const op1, ir_node *const op2) ir_node *const op1, ir_node *const op2,
ir_node *const mem)
{ {
dbg_info *const dbgi = get_irn_dbg_info(node); dbg_info *const dbgi = get_irn_dbg_info(node);
ir_node *const block = get_nodes_block(node); ir_node *const block = get_nodes_block(node);
...@@ -1012,33 +1006,22 @@ static ir_node *create_div(ir_node *const node, ir_mode *const mode, ...@@ -1012,33 +1006,22 @@ static ir_node *create_div(ir_node *const node, ir_mode *const mode,
amd64_insn_mode_t insn_mode amd64_insn_mode_t insn_mode
= get_mode_size_bits(mode) > 32 ? INSN_MODE_64 : INSN_MODE_32; = get_mode_size_bits(mode) > 32 ? INSN_MODE_64 : INSN_MODE_32;
ir_node *res; ir_node *new_op1 = be_transform_node(op1);
ir_node *in[3]; ir_node *new_op2 = be_transform_node(op2);
int arity = 0; ir_node *new_mem = be_transform_node(mem);
const arch_register_req_t **reqs; ir_node *upper_value;
ir_node *(*constructor)(dbg_info*,ir_node*,int,ir_node**,amd64_insn_mode_t);
amd64_op_mode_t op_mode;
amd64_addr_t addr;
memset(&addr, 0, sizeof(addr));
gen_binop_rax_reg(op1, op2, in, &arity, &op_mode, &reqs);
reqs = rax_reg_rdx_reqs;
if (mode_is_signed(mode)) { if (mode_is_signed(mode)) {
/* Sign extend RAX to RDX */ upper_value = create_sext(block, op1, mode);
in[arity++] = create_sext(block, op1, mode); constructor = new_bd_amd64_IDiv;
res = new_bd_amd64_IDiv(dbgi, new_block, arity, in, insn_mode,
op_mode, addr);
} else { } else {
/* Zero extend to register RDX */ upper_value = create_zext(block, node);
in[arity++] = create_zext(block, node); constructor = new_bd_amd64_Div;
res = new_bd_amd64_Div(dbgi, new_block, arity, in, insn_mode,
op_mode, addr);
} }
arch_set_irn_register_reqs_in(res, reqs); ir_node *in[] = { new_op1, new_op2, upper_value, new_mem };
ir_node *res = constructor(dbgi, new_block, ARRAY_SIZE(in), in, insn_mode);
arch_set_irn_register_reqs_in(res, rax_reg_rdx_mem_reqs);
return res; return res;
} }
...@@ -1066,13 +1049,14 @@ static ir_node *create_sse_div(ir_node *const node, ir_mode *const mode, ...@@ -1066,13 +1049,14 @@ static ir_node *create_sse_div(ir_node *const node, ir_mode *const mode,
static ir_node *gen_Div(ir_node *const node) static ir_node *gen_Div(ir_node *const node)
{ {
ir_mode *const mode = get_Div_resmode(node); ir_mode *const mode = get_Div_resmode(node);
ir_node *const op1 = get_Div_left(node); ir_node *const op1 = get_Div_left(node);
ir_node *const op2 = get_Div_right(node); ir_node *const op2 = get_Div_right(node);
ir_node *const mem = get_Div_mem(node);
if (mode_is_float(mode)) if (mode_is_float(mode))
return create_sse_div(node, mode, op1, op2); return create_sse_div(node, mode, op1, op2);
else else
return create_div(node, mode, op1, op2); return create_div(node, mode, op1, op2, mem);
} }
static ir_node *gen_Proj_Div(ir_node *const node) static ir_node *gen_Proj_Div(ir_node *const node)
...@@ -1109,8 +1093,9 @@ static ir_node *gen_Mod(ir_node *const node) ...@@ -1109,8 +1093,9 @@ static ir_node *gen_Mod(ir_node *const node)
ir_mode *const mode = get_Mod_resmode(node); ir_mode *const mode = get_Mod_resmode(node);
ir_node *const op1 = get_Mod_left(node); ir_node *const op1 = get_Mod_left(node);
ir_node *const op2 = get_Mod_right(node); ir_node *const op2 = get_Mod_right(node);
ir_node *const mem = get_Mod_mem(node);
assert(mode_needs_gp_reg(mode)); assert(mode_needs_gp_reg(mode));
return create_div(node, mode, op1, op2); return create_div(node, mode, op1, op2, mem);
} }
static ir_node *gen_Proj_Mod(ir_node *const node) static ir_node *gen_Proj_Mod(ir_node *const node)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment