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

amd64: Implement most x87->int conversions

parent 6109afee
......@@ -256,6 +256,17 @@ my $x87binop = {
mode => $mode_x87,
};
my $x87store = {
op_flags => [ "uses_memory" ],
state => "exc_pinned",
in_reqs => "...",
out_reqs => [ "mem" ],
outs => [ "M" ],
attr_type => "amd64_x87_binop_addr_attr_t",
attr => "const amd64_binop_addr_attr_t *attr_init",
mode => "mode_M",
};
%nodes = (
push_am => {
op_flags => [ "uses_memory" ],
......@@ -779,30 +790,21 @@ fild => {
outs => [ "res", "unused", "M" ],
attr_type => "amd64_x87_addr_attr_t",
attr => "amd64_insn_mode_t insn_mode, amd64_op_mode_t op_mode, amd64_addr_t addr",
emit => "fild%FM %AM",
emit => "fild%M %AM",
},
fisttp => {
template => $x87store,
emit => "fisttp%M %AM",
},
fst => {
op_flags => [ "uses_memory" ],
state => "exc_pinned",
in_reqs => "...",
out_reqs => [ "mem" ],
outs => [ "M" ],
attr_type => "amd64_x87_binop_addr_attr_t",
attr => "const amd64_binop_addr_attr_t *attr_init",
mode => "mode_M",
template => $x87store,
emit => "fst%FP%FM %AM",
},
fstp => {
op_flags => [ "uses_memory" ],
state => "exc_pinned",
in_reqs => "...",
out_reqs => [ "mem" ],
outs => [ "M" ],
attr_type => "amd64_x87_binop_addr_attr_t",
attr => "const amd64_binop_addr_attr_t *attr_init",
mode => "mode_M",
template => $x87store,
emit => "fstp%FM %AM",
},
......@@ -865,6 +867,7 @@ fxch => {
fpop => {
op_flags => [ "keep" ],
out_reqs => [ "none" ],
attrs_equal => "attrs_equal_false",
attr_type => "amd64_x87_attr_t",
attr => "const arch_register_t *reg",
init => "attr->x87.reg = reg;",
......
......@@ -2261,10 +2261,29 @@ static ir_node *conv_sse_to_x87(dbg_info *dbgi, ir_node *block, ir_node *op)
return be_new_Proj(load, pn_amd64_fld_res);
}
static ir_node *conv_int_to_x87(dbg_info *dbgi, ir_node *block, ir_node *op)
static ir_node *conv_x87_to_sse(dbg_info *dbgi, ir_node *block, ir_node *op,
ir_mode *dst_mode)
{
ir_mode *const mode = get_irn_mode(op);
ir_node *const new_op = extend_if_necessary(dbgi, block, op);
amd64_insn_mode_t const insn_mode = get_insn_mode_from_mode(dst_mode);
ir_node *const new_op = be_transform_node(op);
ir_node *in[5];
int n_in = 0;
amd64_addr_t addr;
assert(get_mode_size_bits(dst_mode) <= 64);
store_to_temp(new_bd_amd64_fst, x87_reg_mem_reqs, &addr, dbgi, block, in,
&n_in, new_op, insn_mode);
assert(n_in < (int)ARRAY_SIZE(in));
ir_node *load = new_bd_amd64_movs_xmm(dbgi, block, n_in, in, reg_mem_reqs,
insn_mode, AMD64_OP_ADDR, addr);
set_irn_pinned(load, false);
return be_new_Proj(load, pn_amd64_fld_res);
}
static ir_node *conv_int_to_x87(dbg_info *dbgi, ir_node *block, ir_node *val)
{
ir_mode *const mode = get_irn_mode(val);
ir_node *const new_val = extend_if_necessary(dbgi, block, val);
amd64_insn_mode_t insn_mode = get_insn_mode_from_mode(mode);
if (insn_mode < INSN_MODE_32)
insn_mode = INSN_MODE_32;
......@@ -2276,32 +2295,38 @@ static ir_node *conv_int_to_x87(dbg_info *dbgi, ir_node *block, ir_node *op)
int n_in = 0;
amd64_addr_t addr;
store_to_temp(new_bd_amd64_mov_store, reg_reg_mem_reqs, &addr, dbgi, block,
in, &n_in, new_op, insn_mode);
in, &n_in, new_val, insn_mode);
assert(n_in < (int)ARRAY_SIZE(in));
ir_node *load = new_bd_amd64_fild(dbgi, block, n_in, in, reg_mem_reqs,
INSN_MODE_32, AMD64_OP_ADDR, addr);
insn_mode, AMD64_OP_ADDR, addr);
set_irn_pinned(load, false);
return be_new_Proj(load, pn_amd64_fild_res);
}
static ir_node *conv_x87_to_sse(dbg_info *dbgi, ir_node *block, ir_node *op,
ir_mode *dst_mode)
static ir_node *conv_x87_to_int(dbg_info *const dbgi, ir_node *const block,
ir_node *const val, ir_mode *const dest_mode)
{
amd64_insn_mode_t const insn_mode = get_insn_mode_from_mode(dst_mode);
ir_node *const new_op = be_transform_node(op);
ir_node *const new_val = be_transform_node(val);
amd64_insn_mode_t const insn_mode_dest = get_insn_mode_from_mode(dest_mode);
amd64_insn_mode_t const insn_mode_src = insn_mode_dest > INSN_MODE_32
? INSN_MODE_64 : INSN_MODE_32;
ir_node *in[5];
int n_in = 0;
amd64_addr_t addr;
assert(get_mode_size_bits(dst_mode) <= 64);
store_to_temp(new_bd_amd64_fst, x87_reg_mem_reqs, &addr, dbgi, block, in,
&n_in, new_op, insn_mode);
store_to_temp(new_bd_amd64_fisttp, x87K_reg_mem_reqs, &addr, dbgi, block,
in, &n_in, new_val, insn_mode_src);
assert(n_in < (int)ARRAY_SIZE(in));
ir_node *load = new_bd_amd64_movs_xmm(dbgi, block, n_in, in, reg_mem_reqs,
insn_mode, AMD64_OP_ADDR, addr);
create_mov_func new_mov = insn_mode_dest < INSN_MODE_64
? new_bd_amd64_movs : new_bd_amd64_mov_gp;
ir_node *load = new_mov(dbgi, block, n_in, in, reg_mem_reqs, insn_mode_dest,
AMD64_OP_ADDR, addr);
set_irn_pinned(load, false);
return be_new_Proj(load, pn_amd64_fld_res);
return be_new_Proj(load, pn_amd64_movs_res);
}
static ir_node *gen_Conv(ir_node *const node)
......@@ -2360,11 +2385,11 @@ static ir_node *gen_Conv(ir_node *const node)
min_mode = src_mode;
} else if (src_bits > dst_bits) {
min_mode = dst_mode;
} else if ((src_float && dst_float) || is_gp) {
} else {
assert(src_bits == dst_bits);
/* skip unnecessary conv */
if ((src_float && dst_float) || is_gp)
return be_transform_node(op);
} else {
/* src_bits == dst_bits, but one is float the other integer*/
min_mode = src_mode;
}
......@@ -2400,7 +2425,7 @@ static ir_node *gen_Conv(ir_node *const node)
return conv_sse_to_x87(dbgi, block, op);
} else if (src_mode == x86_mode_E) {
if (!dst_float)
panic("amd64: int -> mode_E NIY");
return conv_x87_to_int(dbgi, block, op, dst_mode);
return conv_x87_to_sse(dbgi, block, op, dst_mode);
}
......
......@@ -43,6 +43,11 @@ static void sim_amd64_fild(x87_state *const state, ir_node *const node)
x86_sim_x87_load(state, node, value);
}
static void sim_amd64_fisttp(x87_state *const state, ir_node *const node)
{
x86_sim_x87_store_pop(state, node, 0);
}
static void sim_amd64_call(x87_state *const state, ir_node *const node)
{
/** push fp results onto x87 stack */
......@@ -99,6 +104,7 @@ static void prepare_callbacks(void)
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_fild, sim_amd64_fild);
x86_register_x87_sim(op_amd64_fisttp, sim_amd64_fisttp);
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);
......
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