{
ir_node *block, *res;
ir_node *startnode;
+ ir_node *in[1];
if(*place != NULL)
return *place;
*place = res;
startnode = get_irg_start(cg->irg);
+ /* make sure we get scheduled very early... */
+ add_irn_dep(startnode, res);
+ /* schedule the node if we already have a schedule program */
if(sched_is_scheduled(startnode)) {
sched_add_before(startnode, res);
}
+ /* keep the node so it isn't accidently removed when unused ... */
+ in[0] = res;
+ be_new_Keep(arch_register_get_class(reg), cg->irg, block, 1, in);
+
return res;
}
return inverse;
}
+static ir_mode *get_spill_mode_mode(const ir_mode *mode)
+{
+ if(mode_is_float(mode))
+ return mode_D;
+
+ return mode_Iu;
+}
+
/**
* Get the mode that should be used for spilling value node
*/
-static ir_mode *get_spill_mode(ia32_code_gen_t *cg, const ir_node *node)
+static ir_mode *get_spill_mode(const ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
- if (mode_is_float(mode)) {
-#if 0
- // super exact spilling...
- if (USE_SSE2(cg))
- return mode_D;
- else
- return mode_E;
-#else
- return mode_D;
-#endif
- }
- else
- return mode_Is;
-
- assert(0);
- return mode;
+ return get_spill_mode_mode(mode);
}
/**
* @return Non-Zero if operand can be loaded
*/
static int ia32_possible_memory_operand(const void *self, const ir_node *irn, unsigned int i) {
- const ia32_irn_ops_t *ops = self;
- ia32_code_gen_t *cg = ops->cg;
ir_node *op = get_irn_n(irn, i);
const ir_mode *mode = get_irn_mode(op);
- const ir_mode *spillmode = get_spill_mode(cg, op);
+ const ir_mode *spillmode = get_spill_mode(op);
if (! is_ia32_irn(irn) || /* must be an ia32 irn */
get_irn_arity(irn) != 5 || /* must be a binary operation */
ir_node *block = get_nodes_block(node);
ir_entity *ent = be_get_frame_entity(node);
ir_mode *mode = get_irn_mode(node);
- ir_mode *spillmode = get_spill_mode(cg, node);
+ ir_mode *spillmode = get_spill_mode(node);
ir_node *noreg = ia32_new_NoReg_gp(cg);
ir_node *sched_point = NULL;
ir_node *ptr = get_irg_frame(irg);
ir_node *block = get_nodes_block(node);
ir_entity *ent = be_get_frame_entity(node);
const ir_node *spillval = get_irn_n(node, be_pos_Spill_val);
- ir_mode *mode = get_spill_mode(cg, spillval);
+ ir_mode *mode = get_spill_mode(spillval);
ir_node *noreg = ia32_new_NoReg_gp(cg);
ir_node *nomem = new_rd_NoMem(irg);
ir_node *ptr = get_irg_frame(irg);
be_fec_env_t *env = data;
if (be_is_Reload(node) && be_get_frame_entity(node) == NULL) {
- const ir_mode *mode = get_irn_mode(node);
+ const ir_mode *mode = get_spill_mode_mode(get_irn_mode(node));
int align = get_mode_size_bytes(mode);
be_node_needs_frame_entity(env, node, mode, align);
} else if(is_ia32_irn(node) && get_ia32_frame_ent(node) == NULL
&& is_ia32_use_frame(node)) {
- if (is_ia32_Load(node)) {
+ if (is_ia32_got_reload(node) || is_ia32_Load(node)) {
const ir_mode *mode = get_ia32_ls_mode(node);
int align = get_mode_size_bytes(mode);
be_node_needs_frame_entity(env, node, mode, align);
ia32_emit_char(env, get_mode_suffix(mode));
}
+void ia32_emit_x87_mode_suffix(ia32_emit_env_t *env, const ir_node *node)
+{
+ ir_mode *mode = get_ia32_ls_mode(node);
+ if(mode != NULL)
+ ia32_emit_mode_suffix(env, mode);
+}
+
void ia32_emit_extend_suffix(ia32_emit_env_t *env, const ir_mode *mode)
{
if(get_mode_size_bits(mode) == 32)
ia32_emit_cstring(env, "\tsahf");
ia32_emit_finish_line(env, node);
- finish_CondJmp(env, node, mode_D, pnc);
+ finish_CondJmp(env, node, mode_E, pnc);
}
static void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos);
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_mode *mode);
+void ia32_emit_x87_mode_suffix(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_extend_suffix(ia32_emit_env_t *env, const ir_mode *mode);
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node);
set_irn_n(irn, idx1, get_irn_n(irn, idx2));
set_irn_n(irn, idx2, tmp);
- set_ia32_pncode(irn, get_negated_pnc(pnc, mode_D));
+ set_ia32_pncode(irn, get_negated_pnc(pnc, mode_E));
}
}
set_ia32_use_frame(fa);
set_ia32_ls_mode(fa, mode_D);
fa_mem = new_r_Proj(irg, block, fa, mode_M, pn_ia32_l_vfild_M);
- fa = new_r_Proj(irg, block, fa, mode_D, pn_ia32_l_vfild_res);
+ fa = new_r_Proj(irg, block, fa, mode_E, pn_ia32_l_vfild_res);
/* store second arg */
store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, b_l, get_irg_no_mem(irg));
set_ia32_use_frame(fb);
set_ia32_ls_mode(fb, mode_D);
fb_mem = new_r_Proj(irg, block, fb, mode_M, pn_ia32_l_vfild_M);
- fb = new_r_Proj(irg, block, fb, mode_D, pn_ia32_l_vfild_res);
+ fb = new_r_Proj(irg, block, fb, mode_E, pn_ia32_l_vfild_res);
op_mem[0] = fa_mem;
op_mem[1] = fb_mem;
switch (dmtp) {
case IA32_INTRINSIC_DIV:
fres = new_rd_ia32_l_vfdiv(dbg, irg, block, fa, fb);
- fres = new_rd_Proj(dbg, irg, block, fres, mode_D, pn_ia32_l_vfdiv_res);
+ fres = new_rd_Proj(dbg, irg, block, fres, mode_E, pn_ia32_l_vfdiv_res);
break;
case IA32_INTRINSIC_MOD:
- fres = new_rd_ia32_l_vfprem(dbg, irg, block, fa, fb, mode_D);
+ fres = new_rd_ia32_l_vfprem(dbg, irg, block, fa, fb, mode_E);
break;
default:
assert(0);
for( ; i >= 0; --i) {
const arch_register_t *spreg;
ir_node *push;
- ir_node *val, *mem;
+ ir_node *val, *mem, *mem_proj;
ir_node *store = stores[i];
ir_node *noreg = ia32_new_NoReg_gp(cg);
arch_set_irn_register(cg->arch_env, curr_sp, spreg);
sched_add_before(irn, curr_sp);
- // rewire users
- edges_reroute(store, push, irg);
+ // create memory proj
+ mem_proj = new_r_Proj(irg, block, push, mode_M, pn_ia32_Push_M);
+ sched_add_before(irn, mem_proj);
+
+ // use the memproj now
+ exchange(store, mem_proj);
// we can remove the store now
- set_irn_n(store, 0, new_Bad());
- set_irn_n(store, 1, new_Bad());
- set_irn_n(store, 2, new_Bad());
- set_irn_n(store, 3, new_Bad());
sched_remove(store);
offset -= 4;
{ "name" => "edi", "type" => 2 },
{ "name" => "ebp", "type" => 2 },
{ "name" => "esp", "type" => 4 },
- { "name" => "gp_NOREG", "type" => 4 | 16 }, # we need a dummy register for NoReg nodes
+ { "name" => "gp_NOREG", "type" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
{ "name" => "gp_UKNWN", "type" => 4 | 8 | 16}, # we need a dummy register for Unknown nodes
{ "mode" => "mode_Iu" }
],
{ "name" => "xmm5", "type" => 1 },
{ "name" => "xmm6", "type" => 1 },
{ "name" => "xmm7", "type" => 1 },
- { "name" => "xmm_NOREG", "type" => 4 | 16 }, # we need a dummy register for NoReg nodes
+ { "name" => "xmm_NOREG", "type" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
{ "name" => "xmm_UKNWN", "type" => 4 | 8 | 16}, # we need a dummy register for Unknown nodes
- { "mode" => "mode_D" }
+ { "mode" => "mode_E" }
],
"vfp" => [
{ "name" => "vf0", "type" => 1 | 16 },
{ "name" => "vf5", "type" => 1 | 16 },
{ "name" => "vf6", "type" => 1 | 16 },
{ "name" => "vf7", "type" => 1 | 16 },
- { "name" => "vfp_NOREG", "type" => 4 | 16 }, # we need a dummy register for NoReg nodes
+ { "name" => "vfp_NOREG", "type" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
{ "name" => "vfp_UKNWN", "type" => 4 | 8 | 16}, # we need a dummy register for Unknown nodes
- { "mode" => "mode_D" }
+ { "mode" => "mode_E" }
],
"st" => [
{ "name" => "st0", "type" => 1 },
"ME" => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
${arch}_emit_mode_suffix(env, get_ia32_ls_mode(node));",
"M" => "${arch}_emit_mode_suffix(env, get_ia32_ls_mode(node));",
+ "XM" => "${arch}_emit_x87_mode_suffix(env, node);",
"AM" => "${arch}_emit_am(env, node);",
"unop" => "${arch}_emit_unop(env, node);",
"binop" => "${arch}_emit_binop(env, node);",
"reg_req" => { "out" => [ "vfp_UKNWN" ] },
"units" => [],
"emit" => "",
- "mode" => "mode_D"
+ "mode" => "mode_E"
},
"Unknown_XMM" => {
"reg_req" => { "out" => [ "xmm_UKNWN" ] },
"units" => [],
"emit" => "",
- "mode" => "mode_D"
+ "mode" => "mode_E"
},
"NoReg_GP" => {
"reg_req" => { "out" => [ "vfp_NOREG" ] },
"units" => [],
"emit" => "",
- "mode" => "mode_D"
+ "mode" => "mode_E"
},
"NoReg_XMM" => {
"reg_req" => { "out" => [ "xmm_NOREG" ] },
"units" => [],
"emit" => "",
- "mode" => "mode_D"
+ "mode" => "mode_E"
},
"ChangeCW" => {
"emit" => '. adds%M %binop',
"latency" => 4,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xMul" => {
"emit" => '. muls%M %binop',
"latency" => 4,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xMax" => {
"emit" => '. maxs%M %binop',
"latency" => 2,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xMin" => {
"emit" => '. mins%M %binop',
"latency" => 2,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xAnd" => {
"emit" => '. andp%M %binop',
"latency" => 3,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xOr" => {
"reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
"emit" => '. orp%M %binop',
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xXor" => {
"emit" => '. xorp%M %binop',
"latency" => 3,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
# not commutative operations
"emit" => '. andnp%M %binop',
"latency" => 3,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xSub" => {
"emit" => '. subs%M %binop',
"latency" => 4,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xDiv" => {
"reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3 !in_r4" ] },
"latency" => 3,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"xCondJmp" => {
"emit" => '. movs%M %D1, $%C',
"latency" => 2,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
# Load / Store
"comment" => "construct Conv Int -> Floating Point",
"latency" => 10,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"Conv_FP2I" => {
"comment" => "construct Conv Floating Point -> Floating Point",
"latency" => 8,
"units" => [ "SSE" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"CmpCMov" => {
"reg_req" => { "in" => [ "vfp", "vfp", "vfp", "vfp" ], "out" => [ "vfp" ] },
"latency" => 10,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
#----------------------------------------------------------#
"reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfmul" => {
"reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"l_vfmul" => {
"reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"l_vfsub" => {
"reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
"latency" => 20,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"l_vfprem" => {
"reg_req" => { "in" => [ "vfp"], "out" => [ "vfp" ] },
"latency" => 2,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfchs" => {
"reg_req" => { "in" => [ "vfp"], "out" => [ "vfp" ] },
"latency" => 2,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfsin" => {
"reg_req" => { "in" => [ "vfp"], "out" => [ "vfp" ] },
"latency" => 150,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfcos" => {
"reg_req" => { "in" => [ "vfp"], "out" => [ "vfp" ] },
"latency" => 150,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfsqrt" => {
"reg_req" => { "in" => [ "vfp"], "out" => [ "vfp" ] },
"latency" => 30,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
# virtual Load and Store
"reg_req" => { "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfld1" => {
"reg_req" => { "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfldpi" => {
"reg_req" => { "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfldln2" => {
"reg_req" => { "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfldlg2" => {
"reg_req" => { "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfldl2t" => {
"reg_req" => { "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfldl2e" => {
"reg_req" => { "out" => [ "vfp" ] },
"latency" => 4,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
"vfConst" => {
"reg_req" => { "out" => [ "vfp" ] },
"latency" => 3,
"units" => [ "VFP" ],
- "mode" => "mode_D",
+ "mode" => "mode_E",
},
# other
"rd_constructor" => "NONE",
"comment" => "x87 Add: Add(a, b) = Add(b, a) = a + b",
"reg_req" => { },
- "emit" => '. fadd %x87_binop',
+ "emit" => '. fadd%XM %x87_binop',
},
"faddp" => {
"rd_constructor" => "NONE",
"comment" => "x87 fp Mul: Mul(a, b) = Mul(b, a) = a + b",
"reg_req" => { },
- "emit" => '. fmul %x87_binop',
+ "emit" => '. fmul%XM %x87_binop',
},
"fmulp" => {
"rd_constructor" => "NONE",
"comment" => "x87 fp Sub: Sub(a, b) = a - b",
"reg_req" => { },
- "emit" => '. fsub %x87_binop',
+ "emit" => '. fsub%XM %x87_binop',
},
"fsubp" => {
"irn_flags" => "R",
"comment" => "x87 fp SubR: SubR(a, b) = b - a",
"reg_req" => { },
- "emit" => '. fsubr %x87_binop',
+ "emit" => '. fsubr%XM %x87_binop',
},
"fsubrp" => {
"rd_constructor" => "NONE",
"comment" => "x87 fp Div: Div(a, b) = a / b",
"reg_req" => { },
- "emit" => '. fdiv %x87_binop',
+ "emit" => '. fdiv%XM %x87_binop',
},
"fdivp" => {
"rd_constructor" => "NONE",
"comment" => "x87 fp DivR: DivR(a, b) = b / a",
"reg_req" => { },
- "emit" => '. fdivr %x87_binop',
+ "emit" => '. fdivr%XM %x87_binop',
},
"fdivrp" => {
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;
/* 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;
}
assert(get_method_n_ress(tp) == 1);
- mode = mode_D;
+ mode = mode_E;
pn_ret_val = get_Proj_proj(ret_val);
pn_ret_mem = get_Proj_proj(ret_mem);
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;
}
}
} 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);
}
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);
}