{ "name" => "ebp", "type" => 2 },
{ "name" => "esp", "type" => 4 },
{ "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
+ { "name" => "gp_UKNWN", "type" => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
{ "mode" => "mode_Iu" }
],
"xmm" => [
{ "name" => "xmm6", "type" => 1 },
{ "name" => "xmm7", "type" => 1 },
{ "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
+ { "name" => "xmm_UKNWN", "type" => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
{ "mode" => "mode_E" }
],
"vfp" => [
{ "name" => "vf6", "type" => 1 | 16 },
{ "name" => "vf7", "type" => 1 | 16 },
{ "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
+ { "name" => "vfp_UKNWN", "type" => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
{ "mode" => "mode_E" }
],
"st" => [
"mode" => "mode_Iu",
},
+"IMul1OP" => {
+ "irn_flags" => "R",
+ "comment" => "construct Mul (1 operand format): Mul(a, b) = Mul(b, a) = a * b",
+ "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
+ "emit" => '. imull %unop',
+ "outs" => [ "EAX", "EDX", "M" ],
+ "latency" => 5,
+ "units" => [ "GP" ],
+},
+
"l_IMul" => {
"op_flags" => "C",
"cmp_attr" => "return 1;",
"arity" => 2
},
-# Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX
-# Matze: It's not clear to me why we have a separate Mulh node and not just use
-# the IMul node...
-"Mulh" => {
- # we should not rematrialize this node. It produces 2 results and has
- # very strict constrains
- "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
- "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] },
- "emit" => '. imull %unop',
- "outs" => [ "EAX", "EDX", "M" ],
- "latency" => 5,
- "units" => [ "GP" ],
-},
-
"And" => {
"irn_flags" => "R",
"comment" => "construct And: And(a, b) = And(b, a) = a AND b",
"IDiv" => {
"op_flags" => "F|L",
"state" => "exc_pinned",
- "reg_req" => { "in" => [ "eax", "gp", "edx", "none" ], "out" => [ "eax", "edx", "none" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "eax", "edx", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
"attr" => "ia32_op_flavour_t dm_flav",
"init_attr" => "attr->data.op_flav = dm_flav;",
"emit" => ". idivl %unop",
"Div" => {
"op_flags" => "F|L",
"state" => "exc_pinned",
- "reg_req" => { "in" => [ "eax", "gp", "edx", "none" ], "out" => [ "eax", "edx", "none" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "eax", "edx", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
"attr" => "ia32_op_flavour_t dm_flav",
"init_attr" => "attr->data.op_flav = dm_flav;",
"emit" => ". divl %unop",
"state" => "exc_pinned",
"comment" => "store ST0 onto stack",
"reg_req" => { "in" => [ "gp", "gp", "none" ] },
- "emit" => '. fstp%M %AM',
+ "emit" => '. fstp%XM %AM',
"latency" => 4,
"units" => [ "SSE" ],
"mode" => "mode_M",
"state" => "exc_pinned",
"comment" => "x87 fp Load: Load(ptr, mem) = LD ptr -> reg",
"reg_req" => { },
- "emit" => '. fld%M %AM',
+ "emit" => '. fld%XM %AM',
},
"fst" => {
"state" => "exc_pinned",
"comment" => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val",
"reg_req" => { },
- "emit" => '. fst%M %AM',
+ "emit" => '. fst%XM %AM',
"mode" => "mode_M",
},
"state" => "exc_pinned",
"comment" => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val",
"reg_req" => { },
- "emit" => '. fstp%M %AM',
+ "emit" => '. fstp%XM %AM',
"mode" => "mode_M",
},
"rd_constructor" => "NONE",
"comment" => "x87 fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
"reg_req" => { },
- "emit" => '. fild%M %AM',
+ "emit" => '. fild%XM %AM',
},
"fist" => {
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 */
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)) {
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:
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:
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);
+ ir_node *pred = get_Proj_pred(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 *new_pred = transform_node(env, pred);
+
+ /* 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_pred, 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);