reg_req => { out => [ "gp_NOREG" ] },
attr => "ir_entity *symconst, int symconst_sign, long offset",
attr_type => "ia32_immediate_attr_t",
+ latency => 0,
mode => $mode_gp,
},
arity => "variable",
out_arity => "variable",
attr_type => "ia32_asm_attr_t",
+ latency => 100,
+},
+
+ProduceVal => {
+ op_flags => "c",
+ irn_flags => "R",
+ reg_req => { out => [ "gp" ] },
+ emit => "",
+ units => [ ],
+ latency => 0,
+ mode => $mode_gp,
},
#-----------------------------------------------------------------#
Cltd => {
# we should not rematrialize this node. It produces 2 results and has
# very strict constrains
- reg_req => { in => [ "eax" ], out => [ "edx" ] },
- ins => [ "val" ],
+ reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] },
+ ins => [ "val", "globbered" ],
emit => '. cltd',
mode => $mode_gp,
units => [ "GP" ],
arity => 3,
},
-GetST0 => {
- op_flags => "L|F",
- irn_flags => "I",
- state => "pinned",
- reg_req => { in => [ "gp", "gp", "none" ] },
- emit => '. fstp%XM %AM',
- latency => 4,
- units => [ "SSE" ],
- mode => "mode_M",
-},
-
-SetST0 => {
- op_flags => "L|F",
- irn_flags => "I",
- state => "pinned",
- reg_req => { in => [ "gp", "gp", "none" ], out => [ "vf0", "none" ] },
- ins => [ "base", "index", "mem" ],
- emit => '. fld%XM %AM',
- outs => [ "res", "M" ],
- latency => 2,
- units => [ "SSE" ],
-},
-
# CopyB
CopyB => {
if (mode_is_signed(mode)) {
/* in signed mode, we need to sign extend the dividend */
- sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_dividend);
+ ir_node *produceval = new_rd_ia32_ProduceVal(dbgi, irg, block);
+ sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_dividend,
+ produceval);
} else {
sign_extension = new_rd_ia32_Const(dbgi, irg, block);
set_ia32_Immop_tarval(sign_extension, get_tarval_null(mode_Iu));
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *op = left;
ir_node *new_op = be_transform_node(op);
+ ir_node *pval = new_rd_ia32_ProduceVal(dbgi, irg, block);
- return new_rd_ia32_Cltd(dbgi, irg, block, new_op);
+ return new_rd_ia32_Cltd(dbgi, irg, block, new_op, pval);
}
}
}
} else {
ir_node *xor;
- ir_node *sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_op);
+ ir_node *pval = new_rd_ia32_ProduceVal(dbgi, irg, block);
+ ir_node *sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_op,
+ pval);
SET_IA32_ORIG_NODE(sign_extension,
ia32_get_old_node_name(env_cg, node));
noreg = ia32_new_NoReg_gp(env_cg);
/* store xmm0 onto stack */
- sse_store = new_rd_ia32_xStoreSimple(dbgi, irg, block, frame, noreg, new_ret_val, new_ret_mem);
+ sse_store = new_rd_ia32_xStoreSimple(dbgi, irg, block, frame, noreg,
+ 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_flavour(sse_store, ia32_am_B);
- /* load into st0 */
- fld = new_rd_ia32_SetST0(dbgi, irg, block, frame, noreg, sse_store);
- set_ia32_ls_mode(fld, mode);
+ /* load into x87 register */
+ fld = new_rd_ia32_vfld(dbgi, irg, block, frame, noreg, sse_store, mode);
set_ia32_op_type(fld, ia32_AddrModeS);
set_ia32_use_frame(fld);
set_ia32_am_flavour(fld, ia32_am_B);
- mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_SetST0_M);
- fld = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_SetST0_res);
- arch_set_irn_register(env_cg->arch_env, fld, &ia32_vfp_regs[REG_VF0]);
+ mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_vfld_M);
+ fld = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_vfld_res);
/* create a new barrier */
arity = get_irn_arity(barrier);
}
if (call_res_pred == NULL || be_is_Call(call_res_pred)) {
- return new_rd_Proj(dbgi, irg, block, new_call, mode_M, pn_be_Call_M_regular);
+ return new_rd_Proj(dbgi, irg, block, new_call, mode_M,
+ pn_be_Call_M_regular);
} else {
assert(is_ia32_xLoad(call_res_pred));
- return new_rd_Proj(dbgi, irg, block, call_res_pred, mode_M, pn_ia32_xLoad_M);
+ return new_rd_Proj(dbgi, 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 *p;
ir_node *call_mem = be_get_Proj_for_pn(call, pn_be_Call_M_regular);
+ ir_node *call_res;
- /* in case there is no memory output: create one to serialize the copy FPU -> SSE */
- call_mem = new_rd_Proj(dbgi, irg, block, new_call, mode_M, pn_be_Call_M_regular);
+ /* in case there is no memory output: create one to serialize the copy
+ FPU -> SSE */
+ call_mem = new_rd_Proj(dbgi, irg, block, new_call, mode_M,
+ pn_be_Call_M_regular);
+ call_res = new_rd_Proj(dbgi, irg, block, new_call, mode,
+ pn_be_Call_first_res);
/* store st(0) onto stack */
- fstp = new_rd_ia32_GetST0(dbgi, irg, block, frame, noreg, call_mem);
-
- set_ia32_ls_mode(fstp, mode);
+ fstp = new_rd_ia32_vfst(dbgi, irg, block, frame, noreg, call_mem,
+ call_res, mode);
set_ia32_op_type(fstp, ia32_AddrModeD);
set_ia32_use_frame(fstp);
set_ia32_am_flavour(fstp, ia32_am_B);
set_ia32_use_frame(sse_load);
set_ia32_am_flavour(sse_load, ia32_am_B);
- sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm, pn_ia32_xLoad_res);
+ sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm,
+ pn_ia32_xLoad_res);
+#if 0
/* now: create new Keep whith all former ins and one additional in - the result Proj */
/* get a Proj representing a caller save register */
/* 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.");
+#endif
return sse_load;
}
* @return NO_NODE_ADDED
*/
static int sim_Copy(x87_state *state, ir_node *n) {
- x87_simulator *sim;
- ir_node *pred;
- const arch_register_t *out;
- const arch_register_t *op1;
- ir_node *node, *next;
- ia32_x87_attr_t *attr;
- int op1_idx, out_idx;
- unsigned live;
-
- ir_mode *mode = get_irn_mode(n);
-
- if (!mode_is_float(mode))
+ x87_simulator *sim = state->sim;
+ ir_node *pred;
+ const arch_register_t *out;
+ const arch_register_t *op1;
+ const arch_register_class_t *class;
+ ir_node *node, *next;
+ ia32_x87_attr_t *attr;
+ int op1_idx, out_idx;
+ unsigned live;
+
+ class = arch_get_irn_reg_class(sim->arch_env, n, -1);
+ if (class->regs != ia32_vfp_regs)
return 0;
- sim = state->sim;
pred = get_irn_n(n, 0);
- out = x87_get_irn_register(sim, n);
- op1 = x87_get_irn_register(sim, pred);
+ out = x87_get_irn_register(sim, n);
+ op1 = x87_get_irn_register(sim, pred);
live = vfp_live_args_after(sim, n, REGMASK(out));
DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", n,
} /* sim_Copy */
/**
- * Returns the result proj of the call, or NULL if the result is not used
+ * Returns the result proj of the call
*/
static ir_node *get_call_result_proj(ir_node *call) {
const ir_edge_t *edge;
- ir_node *resproj = NULL;
/* search the result proj */
foreach_out_edge(call, edge) {
long pn = get_Proj_proj(proj);
if (pn == pn_be_Call_first_res) {
- resproj = proj;
- break;
- }
- }
- if (resproj == NULL) {
- return NULL;
- }
-
- /* the result proj is connected to a Keep and maybe other nodes */
- foreach_out_edge(resproj, edge) {
- ir_node *pred = get_edge_src_irn(edge);
- if (!be_is_Keep(pred)) {
- return resproj;
+ return proj;
}
}
- /* only be_Keep found, so result is not used */
return NULL;
} /* get_call_result_proj */
const arch_register_t *reg;
(void) arch_env;
+ DB((dbg, LEVEL_1, ">>> %+F\n", n));
+
/* at the begin of a call the x87 state should be empty */
assert(state->depth == 0 && "stack not empty before call");
if (get_method_n_ress(call_tp) <= 0)
- return NO_NODE_ADDED;
+ goto end_call;
/*
* If the called function returns a float, it is returned in st(0).
mode = get_type_mode(res_type);
if (mode == NULL || !mode_is_float(mode))
- return NO_NODE_ADDED;
+ goto end_call;
resproj = get_call_result_proj(n);
- if (resproj == NULL)
- return NO_NODE_ADDED;
+ assert(resproj != NULL);
reg = x87_get_irn_register(state->sim, resproj);
x87_push(state, arch_register_get_index(reg), resproj);
+end_call:
+ DB((dbg, LEVEL_1, "Stack after: "));
+ DEBUG_ONLY(x87_dump_stack(state));
+
return NO_NODE_ADDED;
} /* sim_Call */