set_ia32_op_type(load, ia32_AddrModeS);
set_ia32_am_flavour(load, ia32_am_N);
set_ia32_am_sc(load, ia32_get_ent_ident(floatent));
- res = new_r_Proj(irg, block, load, mode_D, pn_ia32_vfld_res);
+ res = new_r_Proj(irg, block, load, mode_E, pn_ia32_vfld_res);
}
} else {
floatent = get_entity_for_tv(env->cg, node);
set_ia32_op_type(load, ia32_AddrModeS);
set_ia32_am_flavour(load, ia32_am_N);
set_ia32_am_sc(load, ia32_get_ent_ident(floatent));
- res = new_r_Proj(irg, block, load, mode_D, pn_ia32_xLoad_res);
+ res = new_r_Proj(irg, block, load, mode_E, pn_ia32_xLoad_res);
}
set_ia32_ls_mode(load, mode);
ir_node *conv = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, in, nomem);
set_ia32_am_support(conv, ia32_am_Source);
- set_ia32_ls_mode(conv, mode_D);
+ set_ia32_ls_mode(conv, mode_E);
SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node));
return conv;
tp_name = names[kct].tp_name;
cnst_str = names[kct].cnst_str;
- mode = kct == ia32_SSIGN || kct == ia32_SABS ? mode_Iu : mode_Lu;
+ //mode = kct == ia32_SSIGN || kct == ia32_SABS ? mode_Iu : mode_Lu;
+ mode = mode_LLu;
tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
tp = new_type_primitive(new_id_from_str(tp_name), mode);
ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);
ir_node *new_op2 = transform_node(env, op2);
new_node = func(dbg, irg, block, noreg_gp, noreg_gp, new_op1, new_op2, nomem);
- if(func == new_rd_ia32_Mul) {
+ if(func == new_rd_ia32_IMul) {
set_ia32_am_support(new_node, ia32_am_Source);
} else {
set_ia32_am_support(new_node, ia32_am_Full);
ir_node *new_op1 = transform_node(env, op1);
ir_node *new_op2 = transform_node(env, op2);
ir_node *noreg = ia32_new_NoReg_gp(env->cg);
- ir_node *proj_EAX, *proj_EDX, *mulh;
+ ir_node *proj_EAX, *proj_EDX, *res;
ir_mode *mode = get_irn_mode(node);
ir_node *in[1];
assert(!mode_is_float(mode) && "Mulh with float not supported");
- mulh = new_rd_ia32_Mulh(dbg, irg, block, noreg, noreg, new_op1, new_op2, new_NoMem());
- set_ia32_commutative(mulh);
- set_ia32_am_support(mulh, ia32_am_Source);
+ if(mode_is_signed(mode)) {
+ res = new_rd_ia32_IMul1OP(dbg, irg, block, noreg, noreg, new_op1, new_op2, new_NoMem());
+ } else {
+ res = new_rd_ia32_Mul(dbg, irg, block, noreg, noreg, new_op1, new_op2, new_NoMem());
+ }
- /* imediates are not supported, so no fold_immediate */
- proj_EAX = new_rd_Proj(dbg, irg, block, mulh, mode_Iu, pn_EAX);
- proj_EDX = new_rd_Proj(dbg, irg, block, mulh, mode_Iu, pn_EDX);
+ set_ia32_commutative(res);
+ set_ia32_am_support(res, ia32_am_Source);
+
+ set_ia32_am_support(res, ia32_am_Source);
+
+ proj_EAX = new_rd_Proj(dbg, irg, block, res, mode_Iu, pn_EAX);
+ proj_EDX = new_rd_Proj(dbg, irg, block, res, mode_Iu, pn_EDX);
/* keep EAX */
in[0] = proj_EAX;
ir_node *in_keep[1];
ir_node *mem, *new_mem;
ir_node *projs[pn_DivMod_max];
+ ir_node *noreg = ia32_new_NoReg_gp(env->cg);
ir_node *new_dividend = transform_node(env, dividend);
ir_node *new_divisor = transform_node(env, divisor);
}
if(mode_is_signed(mode)) {
- res = new_rd_ia32_IDiv(dbg, irg, block, new_dividend, new_divisor, edx_node, new_mem, dm_flav);
+ res = new_rd_ia32_IDiv(dbg, irg, block, noreg, noreg, new_dividend, edx_node, new_divisor, new_mem, dm_flav);
} else {
- res = new_rd_ia32_Div(dbg, irg, block, new_dividend, new_divisor, edx_node, new_mem, dm_flav);
+ res = new_rd_ia32_Div(dbg, irg, block, noreg, noreg, new_dividend, edx_node, new_divisor, new_mem, dm_flav);
}
+
+ /* Matze: code can't handle this at the moment... */
+#if 0
+ /* set AM support */
+ set_ia32_am_support(res, ia32_am_Source);
+#endif
+
set_ia32_n_res(res, 2);
/* Only one proj is used -> We must add a second proj and */
/* in case the compare operands are int, we move them into xmm register */
if (! mode_is_float(get_irn_mode(cmp_a))) {
- new_cmp_a = gen_sse_conv_int2float(cg, dbg, irg, block, new_cmp_a, node, mode_D);
- new_cmp_b = gen_sse_conv_int2float(cg, dbg, irg, block, new_cmp_b, node, mode_D);
+ new_cmp_a = gen_sse_conv_int2float(cg, dbg, irg, block, new_cmp_a, node, mode_E);
+ new_cmp_b = gen_sse_conv_int2float(cg, dbg, irg, block, new_cmp_b, node, mode_E);
pnc |= 8; /* transform integer compare to fp compare */
}
pn_res = pn_ia32_vfld_res;
}
- proj_mode = mode_D;
+ proj_mode = mode_E;
} else {
new_op = new_rd_ia32_Load(dbg, irg, block, new_ptr, noreg, nomem);
proj_mode = mode_Iu;
return new_op;
}
-/**
- * In case SSE is used we need to copy the result from FPU TOS.
- */
-static ir_node *gen_be_Call(ia32_transform_env_t *env, ir_node *node) {
- ir_graph *irg = env->irg;
- dbg_info *dbg = get_irn_dbg_info(node);
- ir_node *block = transform_node(env, get_nodes_block(node));
- ir_node *call_res = be_get_Proj_for_pn(node, pn_be_Call_first_res);
- ir_node *call_mem = be_get_Proj_for_pn(node, pn_be_Call_M_regular);
- ir_mode *mode;
- ir_node *nomem = new_NoMem();
- ir_node *noreg = ia32_new_NoReg_gp(env->cg);
-
- if (! call_res || ! USE_SSE2(env->cg)) {
- return duplicate_node(env, node);
- }
-
- mode = get_irn_mode(call_res);
-
- /* in case there is no memory output: create one to serialize the copy FPU -> SSE */
- if (call_mem == NULL)
- call_mem = new_rd_Proj(dbg, irg, block, node, mode_M, pn_be_Call_M_regular);
-
- if (mode_is_float(mode)) {
- /* store st(0) onto stack */
- ir_node *frame = get_irg_frame(irg);
- ir_node *fstp = new_rd_ia32_GetST0(dbg, irg, block, frame, noreg, nomem);
- ir_entity *ent = frame_alloc_area(get_irg_frame_type(irg), get_mode_size_bytes(mode), 16, 0);
- ir_node *sse_load, *p, *bad, *keep;
- ir_node *mproj;
- ir_node **in_keep;
- int keep_arity, i;
-
- // Matze: TODO, fix this for new transform code...
- assert(0);
-
- set_ia32_ls_mode(fstp, mode);
- set_ia32_op_type(fstp, ia32_AddrModeD);
- set_ia32_use_frame(fstp);
- set_ia32_frame_ent(fstp, ent);
- set_ia32_am_flavour(fstp, ia32_am_B);
- set_ia32_am_support(fstp, ia32_am_Dest);
-
- /* load into SSE register */
- sse_load = new_rd_ia32_xLoad(dbg, irg, block, frame, ia32_new_NoReg_gp(env->cg), fstp);
- set_ia32_ls_mode(sse_load, mode);
- set_ia32_op_type(sse_load, ia32_AddrModeS);
- set_ia32_use_frame(sse_load);
- set_ia32_frame_ent(sse_load, ent);
- set_ia32_am_flavour(sse_load, ia32_am_B);
- set_ia32_am_support(sse_load, ia32_am_Source);
- mproj = new_rd_Proj(dbg, irg, block, sse_load, mode_M, pn_ia32_xLoad_M);
- sse_load = new_rd_Proj(dbg, irg, block, sse_load, mode, pn_ia32_xLoad_res);
-
- /* reroute all users of the result proj to the sse load */
- edges_reroute(call_res, sse_load, irg);
- edges_reroute_kind(call_res, sse_load, EDGE_KIND_DEP, irg);
-
- /* reroute all users of the old call memory to the sse load memory */
- edges_reroute(call_mem, mproj, irg);
- edges_reroute_kind(call_mem, mproj, EDGE_KIND_DEP, irg);
-
- /* now, we can set the old call mem as input of GetST0 */
- set_irn_n(fstp, 1, call_mem);
-
- /* now: create new Keep whith all former ins and one additional in - the result Proj */
-
- /* get a Proj representing a caller save register */
- p = be_get_Proj_for_pn(node, pn_be_Call_first_res + 1);
- assert(is_Proj(p) && "Proj expected.");
-
- /* user of the the proj is the Keep */
- p = get_edge_src_irn(get_irn_out_edge_first(p));
- assert(be_is_Keep(p) && "Keep expected.");
-
- /* copy in array of the old keep and set the result proj as additional in */
- keep_arity = get_irn_arity(p) + 1;
- NEW_ARR_A(ir_node *, in_keep, keep_arity);
- in_keep[keep_arity - 1] = call_res;
- for (i = 0; i < keep_arity - 1; ++i)
- in_keep[i] = get_irn_n(p, i);
-
- /* create new keep and set the in class requirements properly */
- keep = be_new_Keep(NULL, irg, block, keep_arity, in_keep);
- for(i = 0; i < keep_arity; ++i) {
- const arch_register_class_t *cls = arch_get_irn_reg_class(env->cg->arch_env, in_keep[i], -1);
- be_node_set_reg_class(keep, i, cls);
- }
-
- /* kill the old keep */
- bad = get_irg_bad(irg);
- for (i = 0; i < keep_arity - 1; i++)
- set_irn_n(p, i, bad);
- remove_End_keepalive(get_irg_end(irg), p);
- }
-
- return duplicate_node(env, node);
-}
-
/**
* In case SSE is used we need to copy the result from XMM0 to FPU TOS before return.
*/
ir_type *res_type;
ir_mode *mode;
ir_node *frame, *sse_store, *fld, *mproj, *barrier;
- ir_node *new_barrier, *new_frame, *new_ret_val, *new_ret_mem;
+ ir_node *new_barrier, *new_ret_val, *new_ret_mem;
ir_node **in;
int pn_ret_val, pn_ret_mem, arity, i;
}
assert(get_method_n_ress(tp) == 1);
- mode = mode_D;
pn_ret_val = get_Proj_proj(ret_val);
pn_ret_mem = get_Proj_proj(ret_mem);
new_ret_mem = transform_node(env, ret_mem);
frame = get_irg_frame(irg);
- new_frame = transform_node(env, frame);
dbg = get_irn_dbg_info(barrier);
block = transform_node(env, get_nodes_block(barrier));
/* store xmm0 onto stack */
- sse_store = new_rd_ia32_xStoreSimple(dbg, irg, block, new_frame, new_ret_val, new_ret_mem);
+ sse_store = new_rd_ia32_xStoreSimple(dbg, irg, block, frame, new_ret_val, new_ret_mem);
set_ia32_ls_mode(sse_store, mode);
set_ia32_op_type(sse_store, ia32_AddrModeD);
set_ia32_use_frame(sse_store);
set_ia32_am_support(sse_store, ia32_am_Dest);
/* load into st0 */
- fld = new_rd_ia32_SetST0(dbg, irg, block, new_frame, sse_store);
+ fld = new_rd_ia32_SetST0(dbg, irg, block, frame, sse_store);
set_ia32_ls_mode(fld, mode);
set_ia32_op_type(fld, ia32_AddrModeS);
set_ia32_use_frame(fld);
set_ia32_am_support(fld, ia32_am_Source);
mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_SetST0_M);
- fld = new_r_Proj(irg, block, fld, mode_D, pn_ia32_SetST0_res);
+ fld = new_r_Proj(irg, block, fld, mode_E, pn_ia32_SetST0_res);
arch_set_irn_register(env->cg->arch_env, fld, &ia32_vfp_regs[REG_VF0]);
/* create a new barrier */
mode = mode_Iu;
} else if(mode_is_float(mode)) {
assert(mode == mode_D || mode == mode_F);
- // all float operations are on mode_D registers
- mode = mode_D;
+ // all float operations are on mode_E registers
+ mode = mode_E;
}
/* phi nodes allow loops, so we use the old arguments for now
set_ia32_am_support(res, ia32_am_Source);
set_ia32_am_flavour(res, ia32_B);
set_ia32_op_type(res, ia32_AddrModeS);
- res = new_rd_Proj(dbg, irg, block, res, mode_D, pn_ia32_xLoad_res);
+ res = new_rd_Proj(dbg, irg, block, res, mode_E, pn_ia32_xLoad_res);
return res;
}
dbg_info *dbg = get_irn_dbg_info(node);
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = transform_node(env, pred);
- int proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
if(proj == pn_be_AddSP_res) {
ir_node *res = new_rd_Proj(dbg, irg, block, new_pred, mode_Iu, pn_ia32_AddSP_stack);
dbg_info *dbg = get_irn_dbg_info(node);
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = transform_node(env, pred);
- int proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
if(proj == pn_be_SubSP_res) {
ir_node *res = new_rd_Proj(dbg, irg, block, new_pred, mode_Iu, pn_ia32_AddSP_stack);
dbg_info *dbg = get_irn_dbg_info(node);
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = transform_node(env, pred);
- int proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
/* renumber the proj */
if(is_ia32_Load(new_pred)) {
}
} else if(is_ia32_xLoad(new_pred)) {
if(proj == pn_Load_res) {
- return new_rd_Proj(dbg, irg, block, new_pred, mode_D, pn_ia32_xLoad_res);
+ return new_rd_Proj(dbg, irg, block, new_pred, mode_E, pn_ia32_xLoad_res);
} else if(proj == pn_Load_M) {
return new_rd_Proj(dbg, irg, block, new_pred, mode_M, pn_ia32_xLoad_M);
}
} else if(is_ia32_vfld(new_pred)) {
if(proj == pn_Load_res) {
- return new_rd_Proj(dbg, irg, block, new_pred, mode_D, pn_ia32_vfld_res);
+ return new_rd_Proj(dbg, irg, block, new_pred, mode_E, pn_ia32_vfld_res);
} else if(proj == pn_Load_M) {
return new_rd_Proj(dbg, irg, block, new_pred, mode_M, pn_ia32_vfld_M);
}
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = transform_node(env, pred);
- int proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
assert(is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred));
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = transform_node(env, pred);
- int proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
switch(proj) {
case pn_CopyB_M_regular:
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = transform_node(env, pred);
- int proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
switch(proj) {
case pn_ia32_l_vfdiv_M:
return new_rd_Proj(dbg, irg, block, new_pred, mode_M, pn_ia32_vfdiv_M);
case pn_ia32_l_vfdiv_res:
- return new_rd_Proj(dbg, irg, block, new_pred, mode_D, pn_ia32_vfdiv_res);
+ return new_rd_Proj(dbg, irg, block, new_pred, mode_E, pn_ia32_vfdiv_res);
default:
assert(0);
}
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = transform_node(env, pred);
- int proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
switch(proj) {
case pn_Quot_M:
break;
case pn_Quot_res:
if(is_ia32_xDiv(new_pred)) {
- return new_rd_Proj(dbg, irg, block, new_pred, mode,
+ return new_rd_Proj(dbg, irg, block, new_pred, mode_E,
pn_ia32_xDiv_res);
} else if(is_ia32_vfdiv(new_pred)) {
- return new_rd_Proj(dbg, irg, block, new_pred, mode,
+ return new_rd_Proj(dbg, irg, block, new_pred, mode_E,
pn_ia32_vfdiv_res);
}
break;
static ir_node *gen_Proj_tls(ia32_transform_env_t *env, ir_node *node) {
ir_graph *irg = env->irg;
- dbg_info *dbg = get_irn_dbg_info(node);
+ //dbg_info *dbg = get_irn_dbg_info(node);
+ dbg_info *dbg = NULL;
ir_node *block = transform_node(env, get_nodes_block(node));
ir_node *res = new_rd_ia32_LdTls(dbg, irg, block, mode_Iu);
return res;
}
+static ir_node *gen_Proj_be_Call(ia32_transform_env_t *env, ir_node *node) {
+ ir_graph *irg = env->irg;
+ dbg_info *dbg = get_irn_dbg_info(node);
+ long proj = get_Proj_proj(node);
+ ir_mode *mode = get_irn_mode(node);
+ ir_node *block = transform_node(env, get_nodes_block(node));
+ ir_node *sse_load;
+ ir_node *call = get_Proj_pred(node);
+ ir_node *new_call = transform_node(env, call);
+
+ /* The following is kinda tricky: If we're using SSE, then we have to
+ * move the result value of the call in floating point registers to an
+ * xmm register, we therefore construct a GetST0 -> xLoad sequence
+ * after the call, we have to make sure to correctly make the
+ * MemProj and the result Proj use these 2 nodes
+ */
+ if(proj == pn_be_Call_M_regular) {
+ // get new node for result, are we doing the sse load/store hack?
+ ir_node *call_res = be_get_Proj_for_pn(call, pn_be_Call_first_res);
+ ir_node *call_res_new;
+ ir_node *call_res_pred = NULL;
+
+ if(call_res != NULL) {
+ call_res_new = transform_node(env, call_res);
+ call_res_pred = get_Proj_pred(call_res_new);
+ }
+
+ if(call_res_pred == NULL || be_is_Call(call_res_pred)) {
+ return new_rd_Proj(dbg, irg, block, new_call, mode_M, pn_be_Call_M_regular);
+ } else {
+ assert(is_ia32_xLoad(call_res_pred));
+ return new_rd_Proj(dbg, irg, block, call_res_pred, mode_M, pn_ia32_xLoad_M);
+ }
+ }
+ if(proj == pn_be_Call_first_res && mode_is_float(mode)
+ && USE_SSE2(env->cg)) {
+ ir_node *fstp;
+ ir_node *frame = get_irg_frame(irg);
+ ir_node *noreg = ia32_new_NoReg_gp(env->cg);
+ ir_node *p;
+ ir_node *call_mem = be_get_Proj_for_pn(call, pn_be_Call_M_regular);
+ ir_node *keepin[1];
+ const arch_register_class_t *cls;
+
+ /* in case there is no memory output: create one to serialize the copy FPU -> SSE */
+ call_mem = new_rd_Proj(dbg, irg, block, new_call, mode_M, pn_be_Call_M_regular);
+
+ /* store st(0) onto stack */
+ fstp = new_rd_ia32_GetST0(dbg, irg, block, frame, noreg, call_mem);
+
+ set_ia32_ls_mode(fstp, mode);
+ set_ia32_op_type(fstp, ia32_AddrModeD);
+ set_ia32_use_frame(fstp);
+ set_ia32_am_flavour(fstp, ia32_am_B);
+ set_ia32_am_support(fstp, ia32_am_Dest);
+
+ /* load into SSE register */
+ sse_load = new_rd_ia32_xLoad(dbg, irg, block, frame, noreg, fstp);
+ set_ia32_ls_mode(sse_load, mode);
+ set_ia32_op_type(sse_load, ia32_AddrModeS);
+ set_ia32_use_frame(sse_load);
+ set_ia32_am_flavour(sse_load, ia32_am_B);
+ set_ia32_am_support(sse_load, ia32_am_Source);
+
+ //mproj = new_rd_Proj(dbg, irg, block, sse_load, mode_M, pn_ia32_xLoad_M);
+ sse_load = new_rd_Proj(dbg, irg, block, sse_load, mode_E, pn_ia32_xLoad_res);
+
+ /* now: create new Keep whith all former ins and one additional in - the result Proj */
+
+ /* get a Proj representing a caller save register */
+ p = be_get_Proj_for_pn(call, pn_be_Call_first_res + 1);
+ assert(is_Proj(p) && "Proj expected.");
+
+ /* user of the the proj is the Keep */
+ p = get_edge_src_irn(get_irn_out_edge_first(p));
+ assert(be_is_Keep(p) && "Keep expected.");
+
+ /* keep the result */
+ cls = arch_get_irn_reg_class(env->cg->arch_env, sse_load, -1);
+ keepin[0] = sse_load;
+ be_new_Keep(cls, irg, block, 1, keepin);
+
+ return sse_load;
+ }
+
+ /* transform call modes to the mode_Iu or mode_E */
+ if(mode_is_float(mode)) {
+ mode = mode_E;
+ } else if(mode != mode_M) {
+ mode = mode_Iu;
+ }
+
+ return new_rd_Proj(dbg, irg, block, new_call, mode, proj);
+}
+
static ir_node *gen_Proj(ia32_transform_env_t *env, ir_node *node) {
ir_graph *irg = env->irg;
dbg_info *dbg = get_irn_dbg_info(node);
ir_node *pred = get_Proj_pred(node);
- int proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
if(is_Store(pred) || be_is_FrameStore(pred)) {
if(proj == pn_Store_M) {
return gen_Proj_be_SubSP(env, node);
} else if(be_is_AddSP(pred)) {
return gen_Proj_be_AddSP(env, node);
+ } else if(be_is_Call(pred)) {
+ return gen_Proj_be_Call(env, node);
} else if(get_irn_op(pred) == op_Start) {
if(proj == pn_Start_X_initial_exec) {
ir_node *block = get_nodes_block(pred);
/* handle generic backend nodes */
GEN(be_FrameAddr);
- GEN(be_Call);
+ //GEN(be_Call);
GEN(be_Return);
GEN(be_FrameLoad);
GEN(be_FrameStore);
ir_node *block;
ir_node *new_node;
int i, arity;
- ir_node **ins;
block = transform_node(env, get_nodes_block(node));
arity = get_irn_arity(node);
- ins = alloca(arity * sizeof(ins[0]));
- for(i = 0; i < arity; ++i) {
- ir_node *in = get_irn_n(node, i);
- ins[i] = transform_node(env, in);
+ if(op->opar == oparity_dynamic) {
+ new_node = new_ir_node(dbg, irg, block, op, mode, -1, NULL);
+ for(i = 0; i < arity; ++i) {
+ ir_node *in = get_irn_n(node, i);
+ in = transform_node(env, in);
+ add_irn_n(new_node, in);
+ }
+ } else {
+ ir_node **ins = alloca(arity * sizeof(ins[0]));
+ for(i = 0; i < arity; ++i) {
+ ir_node *in = get_irn_n(node, i);
+ ins[i] = transform_node(env, in);
+ }
+
+ new_node = new_ir_node(dbg, irg, block, op, mode, arity, ins);
}
- new_node = new_ir_node(dbg, irg, block,
- op, mode, arity, ins);
copy_node_attr(node, new_node);
duplicate_deps(env, node, new_node);