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