Commit 9f4312e1 authored by Matthias Braun's avatar Matthias Braun
Browse files

reimplement the long long -> double, conversion. Removed broken double -> long long conv for now

[r17007]
parent 6638a5dd
......@@ -682,6 +682,8 @@ static int map_Conv(ir_node *call, void *ctx) {
ir_node *op_mem[2], *mem;
if (n == 1) {
ir_node *float_to_ll;
/* We have a Conv float -> long long here */
ir_node *a_f = params[0];
ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
......@@ -689,60 +691,18 @@ static int map_Conv(ir_node *call, void *ctx) {
assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
/* allocate memory on frame to store args */
ent = env->irg == irg ? env->d_ll_conv : NULL;
if (! ent) {
ent = env->d_ll_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
env->irg = irg;
}
float_to_ll = new_rd_ia32_l_FloattoLL(dbg, irg, block, a_f);
/* Store arg */
frame = get_irg_frame(irg);
/*
Now we create a node to move the value from a XMM register into
x87 FPU because it is unknown here, which FPU is used.
This node is killed in transformation phase when not needed.
Otherwise it is split up into a movsd + fld
*/
a_f = new_rd_ia32_l_SSEtoX87(dbg, irg, block, frame, a_f, get_irg_no_mem(irg), mode_D);
set_ia32_frame_ent(a_f, ent);
set_ia32_use_frame(a_f);
set_ia32_ls_mode(a_f, mode_D);
if (mode_is_signed(h_res_mode)) {
/* a float to signed conv, the simple case */
/* store from FPU as Int */
a_f = new_rd_ia32_l_vfist(dbg, irg, block, frame, a_f, get_irg_no_mem(irg));
set_ia32_frame_ent(a_f, ent);
set_ia32_use_frame(a_f);
set_ia32_ls_mode(a_f, mode_Ls);
mem = a_f;
/* load low part of the result */
l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
set_ia32_frame_ent(l_res, ent);
set_ia32_use_frame(l_res);
set_ia32_ls_mode(l_res, l_res_mode);
l_res = new_r_Proj(irg, block, l_res, l_res_mode, pn_ia32_l_Load_res);
/* load hight part of the result */
h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
set_ia32_frame_ent(h_res, ent);
add_ia32_am_offs_int(h_res, gp_bytes);
set_ia32_use_frame(h_res);
set_ia32_ls_mode(h_res, h_res_mode);
h_res = new_r_Proj(irg, block, h_res, h_res_mode, pn_ia32_l_Load_res);
} else {
/* a float to unsigned conv, more complicated */
panic("Float->unsigned64 NYI\n");
}
l_res = new_r_Proj(irg, block, float_to_ll, l_res_mode,
pn_ia32_l_FloattoLL_res_low);
h_res = new_r_Proj(irg, block, float_to_ll, h_res_mode,
pn_ia32_l_FloattoLL_res_high);
/* lower the call */
resolve_call(call, l_res, h_res, irg, block);
}
else if (n == 2) {
} else if (n == 2) {
ir_node *ll_to_float;
/* We have a Conv long long -> float here */
ir_node *a_l = params[BINOP_Left_Low];
ir_node *a_h = params[BINOP_Left_High];
......@@ -751,57 +711,13 @@ static int map_Conv(ir_node *call, void *ctx) {
assert(! mode_is_float(get_irn_mode(a_l))
&& ! mode_is_float(get_irn_mode(a_h)));
/* allocate memory on frame to store args */
ent = env->irg == irg ? env->ll_d_conv : NULL;
if (! ent) {
ent = env->ll_d_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
env->irg = irg;
}
/* Store arg */
frame = get_irg_frame(irg);
/* store first arg (low part) */
store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, a_l, get_irg_no_mem(irg));
set_ia32_frame_ent(store_l, ent);
set_ia32_use_frame(store_l);
set_ia32_ls_mode(store_l, get_irn_mode(a_l));
op_mem[0] = store_l;
/* store second arg (high part) */
store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg));
set_ia32_frame_ent(store_h, ent);
add_ia32_am_offs_int(store_h, gp_bytes);
set_ia32_use_frame(store_h);
set_ia32_ls_mode(store_h, get_irn_mode(a_h));
op_mem[1] = store_h;
mem = new_r_Sync(irg, block, 2, op_mem);
/* Load arg into x87 FPU (implicit convert) */
fres = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem);
set_ia32_frame_ent(fres, ent);
set_ia32_use_frame(fres);
set_ia32_ls_mode(fres, mode_D);
mem = new_r_Proj(irg, block, fres, mode_M, pn_ia32_l_vfild_M);
fres = new_r_Proj(irg, block, fres, fres_mode, pn_ia32_l_vfild_res);
/*
Now we create a node to move the loaded value into a XMM
register because it is unknown here, which FPU is used.
This node is killed in transformation phase when not needed.
Otherwise it is split up into a fst + movsd
*/
fres = new_rd_ia32_l_X87toSSE(dbg, irg, block, frame, fres, mem, fres_mode);
set_ia32_frame_ent(fres, ent);
set_ia32_use_frame(fres);
set_ia32_ls_mode(fres, fres_mode);
ll_to_float = new_rd_ia32_l_LLtoFloat(dbg, irg, block, a_h, a_l,
fres_mode);
/* lower the call */
resolve_call(call, fres, NULL, irg, block);
}
else {
assert(0 && "unexpected Conv call");
resolve_call(call, ll_to_float, NULL, irg, block);
} else {
panic("unexpected Conv call %+F", call);
}
return 1;
......
......@@ -1637,16 +1637,17 @@ CvtSI2SD => {
},
l_X87toSSE => {
l_LLtoFloat => {
op_flags => "L|F",
cmp_attr => "return 1;",
arity => 3,
ins => [ "val_high", "val_low" ],
},
l_SSEtoX87 => {
l_FloattoLL => {
op_flags => "L|F",
cmp_attr => "return 1;",
arity => 3,
ins => [ "val" ],
outs => [ "res_high", "res_low" ],
},
# CopyB
......
......@@ -4169,104 +4169,63 @@ static ir_node *gen_ia32_l_ShrD(ir_node *node)
return gen_lowered_64bit_shifts(node, high, low, count);
}
/**
* In case SSE Unit is used, the node is transformed into a vfst + xLoad.
*/
static ir_node *gen_ia32_l_X87toSSE(ir_node *node) {
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *val = get_irn_n(node, 1);
ir_node *new_val = be_transform_node(val);
ir_node *res = NULL;
ir_graph *irg = current_ir_graph;
dbg_info *dbgi;
ir_node *noreg, *new_ptr, *new_mem;
ir_node *ptr, *mem;
static ir_node *gen_ia32_l_LLtoFloat(ir_node *node) {
ir_node *src_block = get_nodes_block(node);
ir_node *block = be_transform_node(src_block);
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *frame = get_irg_frame(irg);
ir_node *noreg = ia32_new_NoReg_gp(env_cg);
ir_node *nomem = new_NoMem();
ir_node *val_low = get_irn_n(node, n_ia32_l_LLtoFloat_val_low);
ir_node *val_high = get_irn_n(node, n_ia32_l_LLtoFloat_val_high);
ir_node *new_val_low = be_transform_node(val_low);
ir_node *new_val_high = be_transform_node(val_high);
ir_node *in[2];
ir_node *sync;
ir_node *fild;
ir_node *store_low;
ir_node *store_high;
if (ia32_cg_config.use_sse2) {
return new_val;
if(!mode_is_signed(get_irn_mode(val_high))) {
panic("unsigned long long -> float not supported yet (%+F)", node);
}
mem = get_irn_n(node, 2);
new_mem = be_transform_node(mem);
ptr = get_irn_n(node, 0);
new_ptr = be_transform_node(ptr);
noreg = ia32_new_NoReg_gp(env_cg);
dbgi = get_irn_dbg_info(node);
/* Store x87 -> MEM */
res = new_rd_ia32_vfst(dbgi, irg, block, new_ptr, noreg, new_mem, new_val,
get_ia32_ls_mode(node));
set_ia32_frame_ent(res, get_ia32_frame_ent(node));
set_ia32_use_frame(res);
set_ia32_ls_mode(res, get_ia32_ls_mode(node));
set_ia32_op_type(res, ia32_AddrModeD);
/* Load MEM -> SSE */
res = new_rd_ia32_xLoad(dbgi, irg, block, new_ptr, noreg, res,
get_ia32_ls_mode(node));
set_ia32_frame_ent(res, get_ia32_frame_ent(node));
set_ia32_use_frame(res);
set_ia32_op_type(res, ia32_AddrModeS);
res = new_rd_Proj(dbgi, irg, block, res, mode_xmm, pn_ia32_xLoad_res);
/* do a store */
store_low = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem,
new_val_low);
store_high = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem,
new_val_high);
SET_IA32_ORIG_NODE(store_low, ia32_get_old_node_name(env_cg, node));
SET_IA32_ORIG_NODE(store_high, ia32_get_old_node_name(env_cg, node));
set_ia32_use_frame(store_low);
set_ia32_use_frame(store_high);
set_ia32_op_type(store_low, ia32_AddrModeD);
set_ia32_op_type(store_high, ia32_AddrModeD);
set_ia32_ls_mode(store_low, mode_Iu);
set_ia32_ls_mode(store_high, mode_Is);
add_ia32_am_offs_int(store_high, 4);
in[0] = store_low;
in[1] = store_high;
sync = new_rd_Sync(dbgi, irg, block, 2, in);
return res;
}
/* do a fild */
fild = new_rd_ia32_vfild(dbgi, irg, block, frame, noreg, sync);
/**
* In case SSE Unit is used, the node is transformed into a xStore + vfld.
*/
static ir_node *gen_ia32_l_SSEtoX87(ir_node *node) {
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *val = get_irn_n(node, 1);
ir_node *new_val = be_transform_node(val);
ir_graph *irg = current_ir_graph;
ir_node *res = NULL;
ir_entity *fent = get_ia32_frame_ent(node);
ir_mode *lsmode = get_ia32_ls_mode(node);
int offs = 0;
ir_node *noreg, *new_ptr, *new_mem;
ir_node *ptr, *mem;
dbg_info *dbgi;
if (! ia32_cg_config.use_sse2) {
/* SSE unit is not used -> skip this node. */
return new_val;
}
set_ia32_use_frame(fild);
set_ia32_op_type(fild, ia32_AddrModeS);
set_ia32_ls_mode(fild, mode_Ls);
ptr = get_irn_n(node, 0);
new_ptr = be_transform_node(ptr);
mem = get_irn_n(node, 2);
new_mem = be_transform_node(mem);
noreg = ia32_new_NoReg_gp(env_cg);
dbgi = get_irn_dbg_info(node);
/* Store SSE -> MEM */
if (is_ia32_xLoad(skip_Proj(new_val))) {
ir_node *ld = skip_Proj(new_val);
/* we can vfld the value directly into the fpu */
fent = get_ia32_frame_ent(ld);
ptr = get_irn_n(ld, 0);
offs = get_ia32_am_offs_int(ld);
} else {
res = new_rd_ia32_xStore(dbgi, irg, block, new_ptr, noreg, new_mem,
new_val);
set_ia32_frame_ent(res, fent);
set_ia32_use_frame(res);
set_ia32_ls_mode(res, lsmode);
set_ia32_op_type(res, ia32_AddrModeD);
mem = res;
}
SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node));
/* Load MEM -> x87 */
res = new_rd_ia32_vfld(dbgi, irg, block, new_ptr, noreg, new_mem, lsmode);
set_ia32_frame_ent(res, fent);
set_ia32_use_frame(res);
add_ia32_am_offs_int(res, offs);
set_ia32_op_type(res, ia32_AddrModeS);
res = new_rd_Proj(dbgi, irg, block, res, mode_vfp, pn_ia32_vfld_res);
return new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
}
return res;
static ir_node *gen_ia32_l_FloattoLL(ir_node *node) {
(void) node;
panic("LLtoFloat NIY");
}
/**
......@@ -4779,8 +4738,8 @@ static void register_transformers(void)
GEN(ia32_l_Load);
GEN(ia32_l_vfist);
GEN(ia32_l_Store);
GEN(ia32_l_X87toSSE);
GEN(ia32_l_SSEtoX87);
GEN(ia32_l_LLtoFloat);
GEN(ia32_l_FloattoLL);
GEN(Const);
GEN(SymConst);
......
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