Commit b6825341 authored by Matthias Braun's avatar Matthias Braun
Browse files

amd64: Implement x87 fadd,fsub,fmul,fdiv

parent 097827ee
......@@ -469,6 +469,14 @@ end_of_mods:
case 'A':
switch (*fmt++) {
case 'F': {
x87_attr_t const *const attr
= amd64_get_x87_attr_const(node);
char const *const fmt
= attr->res_in_reg ? "%%st, %%%s" : "%%%s, %%st";
be_emit_irprintf(fmt, attr->reg->name);
break;
}
case 'M':
amd64_emit_am(node, mod & EMIT_INDIRECT_STAR);
break;
......@@ -518,13 +526,15 @@ end_of_mods:
= amd64_get_x87_attr_const(node);
be_emit_char('%');
be_emit_string(attr->reg->name);
} else {
} else if (*fmt == 'R') {
++fmt;
x87_attr_t const *const attr
= amd64_get_x87_attr_const(node);
char const *const fmt
= attr->res_in_reg ? "%%st, %%%s" : "%%%s, %%st";
be_emit_irprintf(fmt, attr->reg->name);
}
/** see also ia32_emitter comment */
if (attr->reverse)
be_emit_char('r');
} else
goto unknown;
break;
}
......
......@@ -240,7 +240,17 @@ my $x87unop = {
in_reqs => [ "x87" ],
out_reqs => [ "x87" ],
ins => [ "value" ],
fixed => "amd64_op_mode_t op_mode = AMD64_OP_X87;\n",
attr_type => "amd64_x87_attr_t",
mode => $mode_x87,
};
my $x87binop = {
# TODO: AM variants
irn_flags => [ "rematerializable" ],
in_reqs => [ "x87", "x87" ],
out_reqs => [ "x87" ],
ins => [ "left", "right" ],
attr_type => "amd64_x87_attr_t",
mode => $mode_x87,
};
......@@ -782,6 +792,29 @@ fstp => {
emit => "fstp%FM %AM",
},
fadd => {
template => $x87binop,
emit => "fadd%FP %AF",
},
fdiv => {
template => $x87binop,
emit => "fdiv%FR%FP %AF",
outs => [ "res", "flags", "M" ],
out_reqs => [ "x87", "flags", "mem" ],
mode => "mode_T",
},
fmul => {
template => $x87binop,
emit => "fmul%FP %AF",
},
fsub => {
template => $x87binop,
emit => "fadd%FR%FP %AF",
},
fchs => {
template => $x87unop,
emit => "fchs",
......
......@@ -932,6 +932,21 @@ static ir_node *gen_binop_xmm(ir_node *node, ir_node *op0, ir_node *op1,
return be_new_Proj(new_node, pn_amd64_subs_res);
}
typedef ir_node *(*construct_x87_binop_func)(
dbg_info *dbgi, ir_node *block, ir_node *op0, ir_node *op1);
static ir_node *gen_binop_x87(ir_node *const node, ir_node *const op0,
ir_node *const op1, construct_x87_binop_func cons)
{
dbg_info *const dbgi = get_irn_dbg_info(node);
ir_node *const new_block = be_transform_node(get_nodes_block(node));
ir_node *const new_op0 = be_transform_node(op0);
ir_node *const new_op1 = be_transform_node(op1);
ir_node *const res = cons(dbgi, new_block, new_op0, new_op1);
/* TODO: address modes */
return res;
}
typedef ir_node *(*construct_shift_func)(dbg_info *dbgi, ir_node *block, int arity, ir_node *const *in, arch_register_req_t const **in_reqs, amd64_shift_attr_t const *attr_init);
static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
......@@ -1029,6 +1044,8 @@ static ir_node *gen_Add(ir_node *const node)
ir_node *const block = get_nodes_block(node);
if (mode_is_float(mode)) {
if (mode == x86_mode_E)
return gen_binop_x87(node, op1, op2, new_bd_amd64_fadd);
return gen_binop_am(node, op1, op2, new_bd_amd64_adds,
pn_amd64_adds_res, match_commutative | match_am);
}
......@@ -1058,6 +1075,8 @@ static ir_node *gen_Sub(ir_node *const node)
ir_mode *const mode = get_irn_mode(node);
if (mode_is_float(mode)) {
if (mode == x86_mode_E)
return gen_binop_x87(node, op1, op2, new_bd_amd64_fsub);
return gen_binop_am(node, op1, op2, new_bd_amd64_subs,
pn_amd64_subs_res, match_am);
} else {
......@@ -1108,6 +1127,8 @@ static ir_node *gen_Mul(ir_node *const node)
match_mode_neutral | match_commutative);
return be_new_Proj(new_node, pn_amd64_imul_1op_res_low);
} else if (mode_is_float(mode)) {
if (mode == x86_mode_E)
return gen_binop_x87(node, op1, op2, new_bd_amd64_fmul);
return gen_binop_am(node, op1, op2, new_bd_amd64_muls,
pn_amd64_muls_res, match_commutative | match_am);
} else {
......@@ -1227,10 +1248,13 @@ static ir_node *gen_Div(ir_node *const 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)) {
if (mode == x86_mode_E)
return gen_binop_x87(node, op1, op2, new_bd_amd64_fdiv);
return create_sse_div(node, mode, op1, op2);
else
} else {
return create_div(node, mode, op1, op2, mem);
}
}
static ir_node *gen_Proj_Div(ir_node *const node)
......
......@@ -51,16 +51,44 @@ static void sim_amd64_call(x87_state *const state, ir_node *const node)
}
}
static void sim_amd64_fadd(x87_state *const state, ir_node *const node)
{
arch_register_t const *const out = arch_get_irn_register_out(node, 0);
x86_sim_x87_binop(state, node, n_amd64_fadd_left, n_amd64_fadd_right, out);
}
static void sim_amd64_fsub(x87_state *const state, ir_node *const node)
{
arch_register_t const *const out = arch_get_irn_register_out(node, 0);
x86_sim_x87_binop(state, node, n_amd64_fsub_left, n_amd64_fsub_right, out);
}
static void sim_amd64_fmul(x87_state *const state, ir_node *const node)
{
arch_register_t const *const out = arch_get_irn_register_out(node, 0);
x86_sim_x87_binop(state, node, n_amd64_fmul_left, n_amd64_fmul_right, out);
}
static void sim_amd64_fdiv(x87_state *const state, ir_node *const node)
{
arch_register_t const *const out = arch_get_irn_register_out(node, 0);
x86_sim_x87_binop(state, node, n_amd64_fdiv_left, n_amd64_fdiv_right, out);
}
static void prepare_callbacks(void)
{
x86_prepare_x87_callbacks();
x86_register_x87_sim(op_amd64_call, sim_amd64_call);
x86_register_x87_sim(op_amd64_fadd, sim_amd64_fadd);
x86_register_x87_sim(op_amd64_fchs, x86_sim_x87_unop);
x86_register_x87_sim(op_amd64_fdiv, sim_amd64_fdiv);
x86_register_x87_sim(op_amd64_fld, sim_amd64_fld);
x86_register_x87_sim(op_amd64_fld1, x86_x87_push);
x86_register_x87_sim(op_amd64_fldz, x86_x87_push);
x86_register_x87_sim(op_amd64_fchs, x86_sim_x87_unop);
x86_register_x87_sim(op_amd64_fmul, sim_amd64_fmul);
x86_register_x87_sim(op_amd64_fst, sim_amd64_fst);
x86_register_x87_sim(op_amd64_fstp, sim_amd64_fstp);
x86_register_x87_sim(op_amd64_fsub, sim_amd64_fsub);
x86_register_x87_sim(op_amd64_ret, x86_sim_x87_ret);
}
......
Markdown is supported
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