2 * This file implements the IR transformation from firm into ia32-Firm.
3 * @author Christian Wuerdig
15 #include "irgraph_t.h"
20 #include "iredges_t.h"
28 #include "archop.h" /* we need this for Min and Max nodes */
30 #include "../benode_t.h"
31 #include "../besched.h"
34 #include "bearch_ia32_t.h"
35 #include "ia32_nodes_attr.h"
36 #include "ia32_transform.h"
37 #include "ia32_new_nodes.h"
38 #include "ia32_map_regs.h"
39 #include "ia32_dbg_stat.h"
40 #include "ia32_optimize.h"
41 #include "ia32_util.h"
43 #include "gen_ia32_regalloc_if.h"
45 #define SFP_SIGN "0x80000000"
46 #define DFP_SIGN "0x8000000000000000"
47 #define SFP_ABS "0x7FFFFFFF"
48 #define DFP_ABS "0x7FFFFFFFFFFFFFFF"
50 #define TP_SFP_SIGN "ia32_sfp_sign"
51 #define TP_DFP_SIGN "ia32_dfp_sign"
52 #define TP_SFP_ABS "ia32_sfp_abs"
53 #define TP_DFP_ABS "ia32_dfp_abs"
55 #define ENT_SFP_SIGN "IA32_SFP_SIGN"
56 #define ENT_DFP_SIGN "IA32_DFP_SIGN"
57 #define ENT_SFP_ABS "IA32_SFP_ABS"
58 #define ENT_DFP_ABS "IA32_DFP_ABS"
60 extern ir_op *get_op_Mulh(void);
62 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
63 ir_node *op1, ir_node *op2, ir_node *mem);
65 typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
66 ir_node *op, ir_node *mem);
69 ia32_SSIGN, ia32_DSIGN, ia32_SABS, ia32_DABS, ia32_known_const_max
72 /****************************************************************************************************
74 * | | | | / _| | | (_)
75 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
76 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
77 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
78 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
80 ****************************************************************************************************/
83 * Returns 1 if irn is a Const representing 0, 0 otherwise
85 static INLINE int is_ia32_Const_0(ir_node *irn) {
86 return (is_ia32_irn(irn) && get_ia32_op_type(irn) == ia32_Const) ?
87 classify_tarval(get_ia32_Immop_tarval(irn)) == TV_CLASSIFY_NULL : 0;
91 * Returns 1 if irn is a Const representing 1, 0 otherwise
93 static INLINE int is_ia32_Const_1(ir_node *irn) {
94 return (is_ia32_irn(irn) && get_ia32_op_type(irn) == ia32_Const) ?
95 classify_tarval(get_ia32_Immop_tarval(irn)) == TV_CLASSIFY_ONE : 0;
99 * Returns the Proj representing the UNKNOWN register for given mode.
101 static ir_node *be_get_unknown_for_mode(ia32_code_gen_t *cg, ir_mode *mode) {
102 be_abi_irg_t *babi = cg->birg->abi;
103 const arch_register_t *unknwn_reg = NULL;
105 if (mode_is_float(mode)) {
106 unknwn_reg = USE_SSE2(cg) ? &ia32_xmm_regs[REG_XMM_UKNWN] : &ia32_vfp_regs[REG_VFP_UKNWN];
109 unknwn_reg = &ia32_gp_regs[REG_GP_UKNWN];
112 return be_abi_get_callee_save_irn(babi, unknwn_reg);
116 * Gets the Proj with number pn from irn.
118 static ir_node *get_proj_for_pn(const ir_node *irn, long pn) {
119 const ir_edge_t *edge;
121 assert(get_irn_mode(irn) == mode_T && "need mode_T");
123 foreach_out_edge(irn, edge) {
124 proj = get_edge_src_irn(edge);
126 if (get_Proj_proj(proj) == pn)
134 * SSE convert of an integer node into a floating point node.
136 static ir_node *gen_sse_conv_int2float(ia32_code_gen_t *cg, dbg_info *dbg, ir_graph *irg, ir_node *block,
137 ir_node *in, ir_node *old_node, ir_mode *tgt_mode)
139 ir_node *noreg = ia32_new_NoReg_gp(cg);
140 ir_node *nomem = new_rd_NoMem(irg);
142 ir_node *conv = new_rd_ia32_Conv_I2FP(dbg, irg, block, noreg, noreg, in, nomem);
143 set_ia32_src_mode(conv, get_irn_mode(in));
144 set_ia32_tgt_mode(conv, tgt_mode);
145 set_ia32_am_support(conv, ia32_am_Source);
146 SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node));
148 return new_rd_Proj(dbg, irg, block, conv, tgt_mode, pn_ia32_Conv_I2FP_res);
151 /* Generates an entity for a known FP const (used for FP Neg + Abs) */
152 static ident *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) {
153 static const struct {
155 const char *ent_name;
156 const char *cnst_str;
157 } names [ia32_known_const_max] = {
158 { TP_SFP_SIGN, ENT_SFP_SIGN, SFP_SIGN }, /* ia32_SSIGN */
159 { TP_DFP_SIGN, ENT_DFP_SIGN, DFP_SIGN }, /* ia32_DSIGN */
160 { TP_SFP_ABS, ENT_SFP_ABS, SFP_ABS }, /* ia32_SABS */
161 { TP_DFP_ABS, ENT_DFP_ABS, DFP_ABS } /* ia32_DABS */
163 static struct entity *ent_cache[ia32_known_const_max];
165 const char *tp_name, *ent_name, *cnst_str;
172 ent_name = names[kct].ent_name;
173 if (! ent_cache[kct]) {
174 tp_name = names[kct].tp_name;
175 cnst_str = names[kct].cnst_str;
177 tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
178 tp = new_type_primitive(new_id_from_str(tp_name), mode);
179 ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);
181 set_entity_ld_ident(ent, get_entity_ident(ent));
182 set_entity_visibility(ent, visibility_local);
183 set_entity_variability(ent, variability_constant);
184 set_entity_allocation(ent, allocation_static);
186 /* we create a new entity here: It's initialization must resist on the
188 rem = current_ir_graph;
189 current_ir_graph = get_const_code_irg();
190 cnst = new_Const(mode, tv);
191 current_ir_graph = rem;
193 set_atomic_ent_value(ent, cnst);
195 /* cache the entry */
196 ent_cache[kct] = ent;
199 return get_entity_ident(ent_cache[kct]);
204 * Prints the old node name on cg obst and returns a pointer to it.
206 const char *ia32_get_old_node_name(ia32_code_gen_t *cg, ir_node *irn) {
207 ia32_isa_t *isa = (ia32_isa_t *)cg->arch_env->isa;
209 lc_eoprintf(firm_get_arg_env(), isa->name_obst, "%+F", irn);
210 obstack_1grow(isa->name_obst, 0);
211 isa->name_obst_size += obstack_object_size(isa->name_obst);
212 return obstack_finish(isa->name_obst);
216 /* determine if one operator is an Imm */
217 static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
219 return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL);
220 else return is_ia32_Cnst(op2) ? op2 : NULL;
223 /* determine if one operator is not an Imm */
224 static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
225 return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL);
230 * Construct a standard binary operation, set AM and immediate if required.
232 * @param env The transformation environment
233 * @param op1 The first operand
234 * @param op2 The second operand
235 * @param func The node constructor function
236 * @return The constructed ia32 node.
238 static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
239 ir_node *new_op = NULL;
240 ir_mode *mode = env->mode;
241 dbg_info *dbg = env->dbg;
242 ir_graph *irg = env->irg;
243 ir_node *block = env->block;
244 ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg);
245 ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg);
246 ir_node *nomem = new_NoMem();
248 ir_node *expr_op, *imm_op;
249 DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
251 /* Check if immediate optimization is on and */
252 /* if it's an operation with immediate. */
253 /* Mul/MulS/Mulh don't support immediates */
254 if (! (env->cg->opt & IA32_OPT_IMMOPS) ||
255 func == new_rd_ia32_Mul ||
256 func == new_rd_ia32_Mulh ||
257 func == new_rd_ia32_MulS)
261 /* immediate operations are requested, but we are here: it a mul */
262 if (env->cg->opt & IA32_OPT_IMMOPS)
265 else if (is_op_commutative(get_irn_op(env->irn))) {
266 imm_op = get_immediate_op(op1, op2);
267 expr_op = get_expr_op(op1, op2);
270 imm_op = get_immediate_op(NULL, op2);
271 expr_op = get_expr_op(op1, op2);
274 assert((expr_op || imm_op) && "invalid operands");
277 /* We have two consts here: not yet supported */
281 if (mode_is_float(mode)) {
282 /* floating point operations */
284 DB((mod, LEVEL_1, "FP with immediate ..."));
285 new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_fp, nomem);
286 set_ia32_Immop_attr(new_op, imm_op);
287 set_ia32_am_support(new_op, ia32_am_None);
290 DB((mod, LEVEL_1, "FP binop ..."));
291 new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem);
292 set_ia32_am_support(new_op, ia32_am_Source);
294 set_ia32_ls_mode(new_op, mode);
297 /* integer operations */
299 /* This is expr + const */
300 DB((mod, LEVEL_1, "INT with immediate ..."));
301 new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_gp, nomem);
302 set_ia32_Immop_attr(new_op, imm_op);
305 set_ia32_am_support(new_op, ia32_am_Dest);
308 DB((mod, LEVEL_1, "INT binop ..."));
309 /* This is a normal operation */
310 new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem);
313 set_ia32_am_support(new_op, ia32_am_Full);
316 /* Muls can only have AM source */
318 set_ia32_am_support(new_op, ia32_am_Source);
321 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
323 set_ia32_res_mode(new_op, mode);
325 if (is_op_commutative(get_irn_op(env->irn))) {
326 set_ia32_commutative(new_op);
329 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
335 * Construct a shift/rotate binary operation, sets AM and immediate if required.
337 * @param env The transformation environment
338 * @param op1 The first operand
339 * @param op2 The second operand
340 * @param func The node constructor function
341 * @return The constructed ia32 node.
343 static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
344 ir_node *new_op = NULL;
345 ir_mode *mode = env->mode;
346 dbg_info *dbg = env->dbg;
347 ir_graph *irg = env->irg;
348 ir_node *block = env->block;
349 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
350 ir_node *nomem = new_NoMem();
351 ir_node *expr_op, *imm_op;
353 DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
355 assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
357 /* Check if immediate optimization is on and */
358 /* if it's an operation with immediate. */
359 imm_op = (env->cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(NULL, op2) : NULL;
360 expr_op = get_expr_op(op1, op2);
362 assert((expr_op || imm_op) && "invalid operands");
365 /* We have two consts here: not yet supported */
369 /* Limit imm_op within range imm8 */
371 tv = get_ia32_Immop_tarval(imm_op);
374 tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
375 set_ia32_Immop_tarval(imm_op, tv);
382 /* integer operations */
384 /* This is shift/rot with const */
385 DB((mod, LEVEL_1, "Shift/Rot with immediate ..."));
387 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem);
388 set_ia32_Immop_attr(new_op, imm_op);
391 /* This is a normal shift/rot */
392 DB((mod, LEVEL_1, "Shift/Rot binop ..."));
393 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem);
397 set_ia32_am_support(new_op, ia32_am_Dest);
399 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
401 set_ia32_res_mode(new_op, mode);
402 set_ia32_emit_cl(new_op);
404 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
409 * Construct a standard unary operation, set AM and immediate if required.
411 * @param env The transformation environment
412 * @param op The operand
413 * @param func The node constructor function
414 * @return The constructed ia32 node.
416 static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) {
417 ir_node *new_op = NULL;
418 ir_mode *mode = env->mode;
419 dbg_info *dbg = env->dbg;
420 ir_graph *irg = env->irg;
421 ir_node *block = env->block;
422 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
423 ir_node *nomem = new_NoMem();
424 DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
426 new_op = func(dbg, irg, block, noreg, noreg, op, nomem);
428 if (mode_is_float(mode)) {
429 DB((mod, LEVEL_1, "FP unop ..."));
430 /* floating point operations don't support implicit store */
431 set_ia32_am_support(new_op, ia32_am_None);
434 DB((mod, LEVEL_1, "INT unop ..."));
435 set_ia32_am_support(new_op, ia32_am_Dest);
438 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
440 set_ia32_res_mode(new_op, mode);
442 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
448 * Creates an ia32 Add with immediate.
450 * @param env The transformation environment
451 * @param expr_op The expression operator
452 * @param const_op The constant
453 * @return the created ia32 Add node
455 static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
456 ir_node *new_op = NULL;
457 tarval *tv = get_ia32_Immop_tarval(const_op);
458 dbg_info *dbg = env->dbg;
459 ir_graph *irg = env->irg;
460 ir_node *block = env->block;
461 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
462 ir_node *nomem = new_NoMem();
464 tarval_classification_t class_tv, class_negtv;
465 DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
467 /* try to optimize to inc/dec */
468 if ((env->cg->opt & IA32_OPT_INCDEC) && (get_ia32_op_type(const_op) == ia32_Const)) {
469 /* optimize tarvals */
470 class_tv = classify_tarval(tv);
471 class_negtv = classify_tarval(tarval_neg(tv));
473 if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
474 DB((env->mod, LEVEL_2, "Add(1) to Inc ... "));
475 new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem);
478 else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
479 DB((mod, LEVEL_2, "Add(-1) to Dec ... "));
480 new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem);
486 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem);
487 set_ia32_Immop_attr(new_op, const_op);
488 set_ia32_commutative(new_op);
495 * Creates an ia32 Add.
497 * @param env The transformation environment
498 * @return the created ia32 Add node
500 static ir_node *gen_Add(ia32_transform_env_t *env) {
501 ir_node *new_op = NULL;
502 dbg_info *dbg = env->dbg;
503 ir_mode *mode = env->mode;
504 ir_graph *irg = env->irg;
505 ir_node *block = env->block;
506 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
507 ir_node *nomem = new_NoMem();
508 ir_node *expr_op, *imm_op;
509 ir_node *op1 = get_Add_left(env->irn);
510 ir_node *op2 = get_Add_right(env->irn);
512 /* Check if immediate optimization is on and */
513 /* if it's an operation with immediate. */
514 imm_op = (env->cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(op1, op2) : NULL;
515 expr_op = get_expr_op(op1, op2);
517 assert((expr_op || imm_op) && "invalid operands");
519 if (mode_is_float(mode)) {
521 if (USE_SSE2(env->cg))
522 return gen_binop(env, op1, op2, new_rd_ia32_xAdd);
524 return gen_binop(env, op1, op2, new_rd_ia32_vfadd);
529 /* No expr_op means, that we have two const - one symconst and */
530 /* one tarval or another symconst - because this case is not */
531 /* covered by constant folding */
532 /* We need to check for: */
533 /* 1) symconst + const -> becomes a LEA */
534 /* 2) symconst + symconst -> becomes a const + LEA as the elf */
535 /* linker doesn't support two symconsts */
537 if (get_ia32_op_type(op1) == ia32_SymConst && get_ia32_op_type(op2) == ia32_SymConst) {
538 /* this is the 2nd case */
539 new_op = new_rd_ia32_Lea(dbg, irg, block, op1, noreg, mode);
540 set_ia32_am_sc(new_op, get_ia32_id_cnst(op2));
541 set_ia32_am_flavour(new_op, ia32_am_OB);
543 DBG_OPT_LEA3(op1, op2, env->irn, new_op);
546 /* this is the 1st case */
547 new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
549 DBG_OPT_LEA3(op1, op2, env->irn, new_op);
551 if (get_ia32_op_type(op1) == ia32_SymConst) {
552 set_ia32_am_sc(new_op, get_ia32_id_cnst(op1));
553 add_ia32_am_offs(new_op, get_ia32_cnst(op2));
556 add_ia32_am_offs(new_op, get_ia32_cnst(op1));
557 set_ia32_am_sc(new_op, get_ia32_id_cnst(op2));
559 set_ia32_am_flavour(new_op, ia32_am_O);
563 set_ia32_am_support(new_op, ia32_am_Source);
564 set_ia32_op_type(new_op, ia32_AddrModeS);
566 /* Lea doesn't need a Proj */
570 /* This is expr + const */
571 new_op = gen_imm_Add(env, expr_op, imm_op);
574 set_ia32_am_support(new_op, ia32_am_Dest);
577 /* This is a normal add */
578 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem);
581 set_ia32_am_support(new_op, ia32_am_Full);
582 set_ia32_commutative(new_op);
586 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
588 set_ia32_res_mode(new_op, mode);
590 return new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_Add_res);
596 * Creates an ia32 Mul.
598 * @param env The transformation environment
599 * @return the created ia32 Mul node
601 static ir_node *gen_Mul(ia32_transform_env_t *env) {
602 ir_node *op1 = get_Mul_left(env->irn);
603 ir_node *op2 = get_Mul_right(env->irn);
606 if (mode_is_float(env->mode)) {
608 if (USE_SSE2(env->cg))
609 new_op = gen_binop(env, op1, op2, new_rd_ia32_xMul);
611 new_op = gen_binop(env, op1, op2, new_rd_ia32_vfmul);
614 new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
623 * Creates an ia32 Mulh.
624 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
625 * this result while Mul returns the lower 32 bit.
627 * @param env The transformation environment
628 * @return the created ia32 Mulh node
630 static ir_node *gen_Mulh(ia32_transform_env_t *env) {
631 ir_node *op1 = get_irn_n(env->irn, 0);
632 ir_node *op2 = get_irn_n(env->irn, 1);
633 ir_node *proj_EAX, *proj_EDX, *mulh;
636 assert(!mode_is_float(env->mode) && "Mulh with float not supported");
637 proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh);
638 mulh = get_Proj_pred(proj_EAX);
639 proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX);
641 /* to be on the save side */
642 set_Proj_proj(proj_EAX, pn_EAX);
644 if (is_ia32_ImmConst(mulh) || is_ia32_ImmSymConst(mulh)) {
645 /* Mulh with const cannot have AM */
646 set_ia32_am_support(mulh, ia32_am_None);
649 /* Mulh cannot have AM for destination */
650 set_ia32_am_support(mulh, ia32_am_Source);
656 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);
664 * Creates an ia32 And.
666 * @param env The transformation environment
667 * @return The created ia32 And node
669 static ir_node *gen_And(ia32_transform_env_t *env) {
670 ir_node *op1 = get_And_left(env->irn);
671 ir_node *op2 = get_And_right(env->irn);
673 assert (! mode_is_float(env->mode));
674 return gen_binop(env, op1, op2, new_rd_ia32_And);
680 * Creates an ia32 Or.
682 * @param env The transformation environment
683 * @return The created ia32 Or node
685 static ir_node *gen_Or(ia32_transform_env_t *env) {
686 ir_node *op1 = get_Or_left(env->irn);
687 ir_node *op2 = get_Or_right(env->irn);
689 assert (! mode_is_float(env->mode));
690 return gen_binop(env, op1, op2, new_rd_ia32_Or);
696 * Creates an ia32 Eor.
698 * @param env The transformation environment
699 * @return The created ia32 Eor node
701 static ir_node *gen_Eor(ia32_transform_env_t *env) {
702 ir_node *op1 = get_Eor_left(env->irn);
703 ir_node *op2 = get_Eor_right(env->irn);
705 assert(! mode_is_float(env->mode));
706 return gen_binop(env, op1, op2, new_rd_ia32_Eor);
712 * Creates an ia32 Max.
714 * @param env The transformation environment
715 * @return the created ia32 Max node
717 static ir_node *gen_Max(ia32_transform_env_t *env) {
718 ir_node *op1 = get_irn_n(env->irn, 0);
719 ir_node *op2 = get_irn_n(env->irn, 1);
722 if (mode_is_float(env->mode)) {
724 if (USE_SSE2(env->cg))
725 new_op = gen_binop(env, op1, op2, new_rd_ia32_xMax);
731 new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
732 set_ia32_am_support(new_op, ia32_am_None);
733 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
742 * Creates an ia32 Min.
744 * @param env The transformation environment
745 * @return the created ia32 Min node
747 static ir_node *gen_Min(ia32_transform_env_t *env) {
748 ir_node *op1 = get_irn_n(env->irn, 0);
749 ir_node *op2 = get_irn_n(env->irn, 1);
752 if (mode_is_float(env->mode)) {
754 if (USE_SSE2(env->cg))
755 new_op = gen_binop(env, op1, op2, new_rd_ia32_xMin);
761 new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
762 set_ia32_am_support(new_op, ia32_am_None);
763 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
772 * Creates an ia32 Sub with immediate.
774 * @param env The transformation environment
775 * @param expr_op The first operator
776 * @param const_op The constant operator
777 * @return The created ia32 Sub node
779 static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
780 ir_node *new_op = NULL;
781 tarval *tv = get_ia32_Immop_tarval(const_op);
782 dbg_info *dbg = env->dbg;
783 ir_graph *irg = env->irg;
784 ir_node *block = env->block;
785 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
786 ir_node *nomem = new_NoMem();
788 tarval_classification_t class_tv, class_negtv;
789 DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
791 /* try to optimize to inc/dec */
792 if ((env->cg->opt & IA32_OPT_INCDEC) && tv) {
793 /* optimize tarvals */
794 class_tv = classify_tarval(tv);
795 class_negtv = classify_tarval(tarval_neg(tv));
797 if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
798 DB((mod, LEVEL_2, "Sub(1) to Dec ... "));
799 new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem);
802 else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
803 DB((mod, LEVEL_2, "Sub(-1) to Inc ... "));
804 new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem);
810 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem);
811 set_ia32_Immop_attr(new_op, const_op);
818 * Creates an ia32 Sub.
820 * @param env The transformation environment
821 * @return The created ia32 Sub node
823 static ir_node *gen_Sub(ia32_transform_env_t *env) {
824 ir_node *new_op = NULL;
825 dbg_info *dbg = env->dbg;
826 ir_mode *mode = env->mode;
827 ir_graph *irg = env->irg;
828 ir_node *block = env->block;
829 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
830 ir_node *nomem = new_NoMem();
831 ir_node *op1 = get_Sub_left(env->irn);
832 ir_node *op2 = get_Sub_right(env->irn);
833 ir_node *expr_op, *imm_op;
835 /* Check if immediate optimization is on and */
836 /* if it's an operation with immediate. */
837 imm_op = (env->cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(NULL, op2) : NULL;
838 expr_op = get_expr_op(op1, op2);
840 assert((expr_op || imm_op) && "invalid operands");
842 if (mode_is_float(mode)) {
844 if (USE_SSE2(env->cg))
845 return gen_binop(env, op1, op2, new_rd_ia32_xSub);
847 return gen_binop(env, op1, op2, new_rd_ia32_vfsub);
852 /* No expr_op means, that we have two const - one symconst and */
853 /* one tarval or another symconst - because this case is not */
854 /* covered by constant folding */
855 /* We need to check for: */
856 /* 1) symconst - const -> becomes a LEA */
857 /* 2) symconst - symconst -> becomes a const - LEA as the elf */
858 /* linker doesn't support two symconsts */
860 if (get_ia32_op_type(op1) == ia32_SymConst && get_ia32_op_type(op2) == ia32_SymConst) {
861 /* this is the 2nd case */
862 new_op = new_rd_ia32_Lea(dbg, irg, block, op1, noreg, mode);
863 set_ia32_am_sc(new_op, get_ia32_id_cnst(op2));
864 set_ia32_am_sc_sign(new_op);
865 set_ia32_am_flavour(new_op, ia32_am_OB);
867 DBG_OPT_LEA3(op1, op2, env->irn, new_op);
870 /* this is the 1st case */
871 new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
873 DBG_OPT_LEA3(op1, op2, env->irn, new_op);
875 if (get_ia32_op_type(op1) == ia32_SymConst) {
876 set_ia32_am_sc(new_op, get_ia32_id_cnst(op1));
877 sub_ia32_am_offs(new_op, get_ia32_cnst(op2));
880 add_ia32_am_offs(new_op, get_ia32_cnst(op1));
881 set_ia32_am_sc(new_op, get_ia32_id_cnst(op2));
882 set_ia32_am_sc_sign(new_op);
884 set_ia32_am_flavour(new_op, ia32_am_O);
888 set_ia32_am_support(new_op, ia32_am_Source);
889 set_ia32_op_type(new_op, ia32_AddrModeS);
891 /* Lea doesn't need a Proj */
895 /* This is expr - const */
896 new_op = gen_imm_Sub(env, expr_op, imm_op);
899 set_ia32_am_support(new_op, ia32_am_Dest);
902 /* This is a normal sub */
903 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem);
906 set_ia32_am_support(new_op, ia32_am_Full);
910 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
912 set_ia32_res_mode(new_op, mode);
914 return new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_Sub_res);
920 * Generates an ia32 DivMod with additional infrastructure for the
921 * register allocator if needed.
923 * @param env The transformation environment
924 * @param dividend -no comment- :)
925 * @param divisor -no comment- :)
926 * @param dm_flav flavour_Div/Mod/DivMod
927 * @return The created ia32 DivMod node
929 static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
931 ir_node *edx_node, *cltd;
933 dbg_info *dbg = env->dbg;
934 ir_graph *irg = env->irg;
935 ir_node *block = env->block;
936 ir_mode *mode = env->mode;
937 ir_node *irn = env->irn;
943 mem = get_Div_mem(irn);
944 mode = get_irn_mode(get_proj_for_pn(irn, pn_Div_res));
947 mem = get_Mod_mem(irn);
948 mode = get_irn_mode(get_proj_for_pn(irn, pn_Mod_res));
951 mem = get_DivMod_mem(irn);
952 mode = get_irn_mode(get_proj_for_pn(irn, pn_DivMod_res_div));
958 if (mode_is_signed(mode)) {
959 /* in signed mode, we need to sign extend the dividend */
960 cltd = new_rd_ia32_Cdq(dbg, irg, block, dividend);
961 dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_ia32_Cdq_EAX);
962 edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_ia32_Cdq_EDX);
965 edx_node = new_rd_ia32_Const(dbg, irg, block, get_irg_no_mem(irg), mode_Iu);
966 set_ia32_Const_type(edx_node, ia32_Const);
967 set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
970 res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, dm_flav);
972 set_ia32_n_res(res, 2);
974 /* Only one proj is used -> We must add a second proj and */
975 /* connect this one to a Keep node to eat up the second */
976 /* destroyed register. */
977 n = get_irn_n_edges(irn);
980 proj = ia32_get_proj_for_mode(irn, mode_M);
982 /* in case of two projs, one must be the memory proj */
983 if (n == 1 || (n == 2 && proj)) {
984 proj = ia32_get_res_proj(irn);
985 assert(proj && "Result proj expected");
987 if (get_irn_op(irn) == op_Div) {
988 set_Proj_proj(proj, pn_DivMod_res_div);
989 in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode, pn_DivMod_res_mod);
992 set_Proj_proj(proj, pn_DivMod_res_mod);
993 in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode, pn_DivMod_res_div);
996 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
999 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1001 set_ia32_res_mode(res, mode);
1008 * Wrapper for generate_DivMod. Sets flavour_Mod.
1010 * @param env The transformation environment
1012 static ir_node *gen_Mod(ia32_transform_env_t *env) {
1013 return generate_DivMod(env, get_Mod_left(env->irn), get_Mod_right(env->irn), flavour_Mod);
1017 * Wrapper for generate_DivMod. Sets flavour_Div.
1019 * @param env The transformation environment
1021 static ir_node *gen_Div(ia32_transform_env_t *env) {
1022 return generate_DivMod(env, get_Div_left(env->irn), get_Div_right(env->irn), flavour_Div);
1026 * Wrapper for generate_DivMod. Sets flavour_DivMod.
1028 static ir_node *gen_DivMod(ia32_transform_env_t *env) {
1029 return generate_DivMod(env, get_DivMod_left(env->irn), get_DivMod_right(env->irn), flavour_DivMod);
1035 * Creates an ia32 floating Div.
1037 * @param env The transformation environment
1038 * @return The created ia32 xDiv node
1040 static ir_node *gen_Quot(ia32_transform_env_t *env) {
1041 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1043 ir_node *nomem = new_rd_NoMem(env->irg);
1044 ir_node *op1 = get_Quot_left(env->irn);
1045 ir_node *op2 = get_Quot_right(env->irn);
1048 if (USE_SSE2(env->cg)) {
1049 if (is_ia32_xConst(op2)) {
1050 new_op = new_rd_ia32_xDiv(env->dbg, env->irg, env->block, noreg, noreg, op1, noreg, nomem);
1051 set_ia32_am_support(new_op, ia32_am_None);
1052 set_ia32_Immop_attr(new_op, op2);
1055 new_op = new_rd_ia32_xDiv(env->dbg, env->irg, env->block, noreg, noreg, op1, op2, nomem);
1056 set_ia32_am_support(new_op, ia32_am_Source);
1060 new_op = new_rd_ia32_vfdiv(env->dbg, env->irg, env->block, noreg, noreg, op1, op2, nomem);
1061 set_ia32_am_support(new_op, ia32_am_Source);
1063 set_ia32_res_mode(new_op, get_irn_mode(get_proj_for_pn(env->irn, pn_Quot_res)));
1064 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1072 * Creates an ia32 Shl.
1074 * @param env The transformation environment
1075 * @return The created ia32 Shl node
1077 static ir_node *gen_Shl(ia32_transform_env_t *env) {
1078 return gen_shift_binop(env, get_Shl_left(env->irn), get_Shl_right(env->irn), new_rd_ia32_Shl);
1084 * Creates an ia32 Shr.
1086 * @param env The transformation environment
1087 * @return The created ia32 Shr node
1089 static ir_node *gen_Shr(ia32_transform_env_t *env) {
1090 return gen_shift_binop(env, get_Shr_left(env->irn), get_Shr_right(env->irn), new_rd_ia32_Shr);
1096 * Creates an ia32 Shrs.
1098 * @param env The transformation environment
1099 * @return The created ia32 Shrs node
1101 static ir_node *gen_Shrs(ia32_transform_env_t *env) {
1102 return gen_shift_binop(env, get_Shrs_left(env->irn), get_Shrs_right(env->irn), new_rd_ia32_Shrs);
1108 * Creates an ia32 RotL.
1110 * @param env The transformation environment
1111 * @param op1 The first operator
1112 * @param op2 The second operator
1113 * @return The created ia32 RotL node
1115 static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
1116 return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL);
1122 * Creates an ia32 RotR.
1123 * NOTE: There is no RotR with immediate because this would always be a RotL
1124 * "imm-mode_size_bits" which can be pre-calculated.
1126 * @param env The transformation environment
1127 * @param op1 The first operator
1128 * @param op2 The second operator
1129 * @return The created ia32 RotR node
1131 static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
1132 return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR);
1138 * Creates an ia32 RotR or RotL (depending on the found pattern).
1140 * @param env The transformation environment
1141 * @return The created ia32 RotL or RotR node
1143 static ir_node *gen_Rot(ia32_transform_env_t *env) {
1144 ir_node *rotate = NULL;
1145 ir_node *op1 = get_Rot_left(env->irn);
1146 ir_node *op2 = get_Rot_right(env->irn);
1148 /* Firm has only Rot (which is a RotL), so we are looking for a right (op2)
1149 operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
1150 that means we can create a RotR instead of an Add and a RotL */
1153 ir_node *pred = get_Proj_pred(op2);
1155 if (is_ia32_Add(pred)) {
1156 ir_node *pred_pred = get_irn_n(pred, 2);
1157 tarval *tv = get_ia32_Immop_tarval(pred);
1158 long bits = get_mode_size_bits(env->mode);
1160 if (is_Proj(pred_pred)) {
1161 pred_pred = get_Proj_pred(pred_pred);
1164 if (is_ia32_Minus(pred_pred) &&
1165 tarval_is_long(tv) &&
1166 get_tarval_long(tv) == bits)
1168 DB((env->mod, LEVEL_1, "RotL into RotR ... "));
1169 rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
1176 rotate = gen_RotL(env, op1, op2);
1185 * Transforms a Minus node.
1187 * @param env The transformation environment
1188 * @param op The Minus operand
1189 * @return The created ia32 Minus node
1191 ir_node *gen_Minus_ex(ia32_transform_env_t *env, ir_node *op) {
1196 if (mode_is_float(env->mode)) {
1198 if (USE_SSE2(env->cg)) {
1199 ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg);
1200 ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg);
1201 ir_node *nomem = new_rd_NoMem(env->irg);
1203 new_op = new_rd_ia32_xEor(env->dbg, env->irg, env->block, noreg_gp, noreg_gp, op, noreg_fp, nomem);
1205 size = get_mode_size_bits(env->mode);
1206 name = gen_fp_known_const(env->mode, size == 32 ? ia32_SSIGN : ia32_DSIGN);
1208 set_ia32_am_sc(new_op, name);
1210 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1212 set_ia32_res_mode(new_op, env->mode);
1213 set_ia32_op_type(new_op, ia32_AddrModeS);
1214 set_ia32_ls_mode(new_op, env->mode);
1216 new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, pn_ia32_xEor_res);
1219 new_op = new_rd_ia32_vfchs(env->dbg, env->irg, env->block, op, env->mode);
1220 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1224 new_op = gen_unop(env, op, new_rd_ia32_Minus);
1231 * Transforms a Minus node.
1233 * @param env The transformation environment
1234 * @return The created ia32 Minus node
1236 static ir_node *gen_Minus(ia32_transform_env_t *env) {
1237 return gen_Minus_ex(env, get_Minus_op(env->irn));
1242 * Transforms a Not node.
1244 * @param env The transformation environment
1245 * @return The created ia32 Not node
1247 static ir_node *gen_Not(ia32_transform_env_t *env) {
1248 assert (! mode_is_float(env->mode));
1249 return gen_unop(env, get_Not_op(env->irn), new_rd_ia32_Not);
1255 * Transforms an Abs node.
1257 * @param env The transformation environment
1258 * @return The created ia32 Abs node
1260 static ir_node *gen_Abs(ia32_transform_env_t *env) {
1261 ir_node *res, *p_eax, *p_edx;
1262 dbg_info *dbg = env->dbg;
1263 ir_mode *mode = env->mode;
1264 ir_graph *irg = env->irg;
1265 ir_node *block = env->block;
1266 ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg);
1267 ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg);
1268 ir_node *nomem = new_NoMem();
1269 ir_node *op = get_Abs_op(env->irn);
1273 if (mode_is_float(mode)) {
1275 if (USE_SSE2(env->cg)) {
1276 res = new_rd_ia32_xAnd(dbg,irg, block, noreg_gp, noreg_gp, op, noreg_fp, nomem);
1278 size = get_mode_size_bits(mode);
1279 name = gen_fp_known_const(mode, size == 32 ? ia32_SABS : ia32_DABS);
1281 set_ia32_am_sc(res, name);
1283 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1285 set_ia32_res_mode(res, mode);
1286 set_ia32_op_type(res, ia32_AddrModeS);
1287 set_ia32_ls_mode(res, env->mode);
1289 res = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_xAnd_res);
1292 res = new_rd_ia32_vfabs(dbg, irg, block, op, mode);
1293 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1297 res = new_rd_ia32_Cdq(dbg, irg, block, op);
1298 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1299 set_ia32_res_mode(res, mode);
1301 p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_Cdq_EAX);
1302 p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_Cdq_EDX);
1304 res = new_rd_ia32_Eor(dbg, irg, block, noreg_gp, noreg_gp, p_eax, p_edx, nomem);
1305 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1306 set_ia32_res_mode(res, mode);
1308 res = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_Eor_res);
1310 res = new_rd_ia32_Sub(dbg, irg, block, noreg_gp, noreg_gp, res, p_edx, nomem);
1311 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1312 set_ia32_res_mode(res, mode);
1314 res = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_Sub_res);
1323 * Transforms a Load.
1325 * @param env The transformation environment
1326 * @return the created ia32 Load node
1328 static ir_node *gen_Load(ia32_transform_env_t *env) {
1329 ir_node *node = env->irn;
1330 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1331 ir_node *ptr = get_Load_ptr(node);
1332 ir_node *lptr = ptr;
1333 ir_mode *mode = get_Load_mode(node);
1336 ia32_am_flavour_t am_flav = ia32_am_B;
1338 /* address might be a constant (symconst or absolute address) */
1339 if (is_ia32_Const(ptr)) {
1344 if (mode_is_float(mode)) {
1346 if (USE_SSE2(env->cg))
1347 new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, lptr, noreg, get_Load_mem(node));
1349 new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, lptr, noreg, get_Load_mem(node));
1352 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, lptr, noreg, get_Load_mem(node));
1355 /* base is an constant address */
1357 if (get_ia32_op_type(ptr) == ia32_SymConst) {
1358 set_ia32_am_sc(new_op, get_ia32_id_cnst(ptr));
1359 am_flav = ia32_am_N;
1362 add_ia32_am_offs(new_op, get_ia32_cnst(ptr));
1363 am_flav = ia32_am_O;
1367 set_ia32_am_support(new_op, ia32_am_Source);
1368 set_ia32_op_type(new_op, ia32_AddrModeS);
1369 set_ia32_am_flavour(new_op, am_flav);
1370 set_ia32_ls_mode(new_op, mode);
1373 check for special case: the loaded value might not be used (optimized, volatile, ...)
1374 we add a Proj + Keep for volatile loads and ignore all other cases
1376 if (! get_proj_for_pn(node, pn_Load_res) && get_Load_volatility(node) == volatility_is_volatile) {
1377 /* add a result proj and a Keep to produce a pseudo use */
1378 ir_node *proj = new_r_Proj(env->irg, env->block, new_op, mode, pn_ia32_Load_res);
1379 be_new_Keep(arch_get_irn_reg_class(env->cg->arch_env, proj, -1), env->irg, env->block, 1, &proj);
1382 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1390 * Transforms a Store.
1392 * @param env The transformation environment
1393 * @return the created ia32 Store node
1395 static ir_node *gen_Store(ia32_transform_env_t *env) {
1396 ir_node *node = env->irn;
1397 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1398 ir_node *val = get_Store_value(node);
1399 ir_node *ptr = get_Store_ptr(node);
1400 ir_node *sptr = ptr;
1401 ir_node *mem = get_Store_mem(node);
1402 ir_mode *mode = get_irn_link(node);
1403 ir_node *sval = val;
1406 ia32_am_flavour_t am_flav = ia32_am_B;
1407 ia32_immop_type_t immop = ia32_ImmNone;
1409 if (! mode_is_float(mode)) {
1410 /* in case of storing a const (but not a symconst) -> make it an attribute */
1411 if (is_ia32_Cnst(val)) {
1412 switch (get_ia32_op_type(val)) {
1414 immop = ia32_ImmConst;
1417 immop = ia32_ImmSymConst;
1420 assert(0 && "unsupported Const type");
1426 /* address might be a constant (symconst or absolute address) */
1427 if (is_ia32_Const(ptr)) {
1432 if (mode_is_float(mode)) {
1434 if (USE_SSE2(env->cg))
1435 new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, sptr, noreg, sval, mem);
1437 new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, sptr, noreg, sval, mem);
1439 else if (get_mode_size_bits(mode) == 8) {
1440 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, sptr, noreg, sval, mem);
1443 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, sptr, noreg, sval, mem);
1446 /* stored const is an attribute (saves a register) */
1447 if (! mode_is_float(mode) && is_ia32_Cnst(val)) {
1448 set_ia32_Immop_attr(new_op, val);
1451 /* base is an constant address */
1453 if (get_ia32_immop_type(ptr) == ia32_ImmSymConst) {
1454 set_ia32_am_sc(new_op, get_ia32_id_cnst(ptr));
1455 am_flav = ia32_am_N;
1458 add_ia32_am_offs(new_op, get_ia32_cnst(ptr));
1459 am_flav = ia32_am_O;
1463 set_ia32_am_support(new_op, ia32_am_Dest);
1464 set_ia32_op_type(new_op, ia32_AddrModeD);
1465 set_ia32_am_flavour(new_op, am_flav);
1466 set_ia32_ls_mode(new_op, mode);
1467 set_ia32_immop_type(new_op, immop);
1469 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1477 * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp, CondJmp_i or TestJmp
1479 * @param env The transformation environment
1480 * @return The transformed node.
1482 static ir_node *gen_Cond(ia32_transform_env_t *env) {
1483 dbg_info *dbg = env->dbg;
1484 ir_graph *irg = env->irg;
1485 ir_node *block = env->block;
1486 ir_node *node = env->irn;
1487 ir_node *sel = get_Cond_selector(node);
1488 ir_mode *sel_mode = get_irn_mode(sel);
1489 ir_node *res = NULL;
1490 ir_node *pred = NULL;
1491 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1492 ir_node *cmp_a, *cmp_b, *cnst, *expr;
1494 if (is_Proj(sel) && sel_mode == mode_b) {
1495 ir_node *nomem = new_NoMem();
1497 pred = get_Proj_pred(sel);
1499 /* get both compare operators */
1500 cmp_a = get_Cmp_left(pred);
1501 cmp_b = get_Cmp_right(pred);
1503 /* check if we can use a CondJmp with immediate */
1504 cnst = (env->cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(cmp_a, cmp_b) : NULL;
1505 expr = get_expr_op(cmp_a, cmp_b);
1508 pn_Cmp pnc = get_Proj_proj(sel);
1510 if ((pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) && mode_is_int(get_irn_mode(expr))) {
1511 if (get_ia32_op_type(cnst) == ia32_Const &&
1512 classify_tarval(get_ia32_Immop_tarval(cnst)) == TV_CLASSIFY_NULL)
1514 /* a Cmp A =/!= 0 */
1515 ir_node *op1 = expr;
1516 ir_node *op2 = expr;
1517 ir_node *and = skip_Proj(expr);
1518 const char *cnst = NULL;
1520 /* check, if expr is an only once used And operation */
1521 if (get_irn_n_edges(expr) == 1 && is_ia32_And(and)) {
1522 op1 = get_irn_n(and, 2);
1523 op2 = get_irn_n(and, 3);
1525 cnst = (is_ia32_ImmConst(and) || is_ia32_ImmSymConst(and)) ? get_ia32_cnst(and) : NULL;
1527 res = new_rd_ia32_TestJmp(dbg, irg, block, op1, op2);
1528 set_ia32_pncode(res, get_Proj_proj(sel));
1529 set_ia32_res_mode(res, get_irn_mode(op1));
1532 copy_ia32_Immop_attr(res, and);
1535 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1540 if (mode_is_float(get_irn_mode(expr))) {
1542 if (USE_SSE2(env->cg))
1543 res = new_rd_ia32_xCondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem);
1549 res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem);
1551 set_ia32_Immop_attr(res, cnst);
1552 set_ia32_res_mode(res, get_irn_mode(expr));
1555 if (mode_is_float(get_irn_mode(cmp_a))) {
1557 if (USE_SSE2(env->cg))
1558 res = new_rd_ia32_xCondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);
1561 res = new_rd_ia32_vfCondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);
1562 proj_eax = new_r_Proj(irg, block, res, mode_Is, pn_ia32_vfCondJmp_temp_reg_eax);
1563 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, &proj_eax);
1567 res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);
1568 set_ia32_commutative(res);
1570 set_ia32_res_mode(res, get_irn_mode(cmp_a));
1573 set_ia32_pncode(res, get_Proj_proj(sel));
1574 //set_ia32_am_support(res, ia32_am_Source);
1577 /* determine the smallest switch case value */
1578 int switch_min = INT_MAX;
1579 const ir_edge_t *edge;
1582 foreach_out_edge(node, edge) {
1583 int pn = get_Proj_proj(get_edge_src_irn(edge));
1584 switch_min = pn < switch_min ? pn : switch_min;
1588 /* if smallest switch case is not 0 we need an additional sub */
1589 snprintf(buf, sizeof(buf), "%d", switch_min);
1590 res = new_rd_ia32_Lea(dbg, irg, block, sel, noreg, mode_Is);
1591 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1592 sub_ia32_am_offs(res, buf);
1593 set_ia32_am_flavour(res, ia32_am_OB);
1594 set_ia32_am_support(res, ia32_am_Source);
1595 set_ia32_op_type(res, ia32_AddrModeS);
1598 res = new_rd_ia32_SwitchJmp(dbg, irg, block, switch_min ? res : sel, mode_T);
1599 set_ia32_pncode(res, get_Cond_defaultProj(node));
1600 set_ia32_res_mode(res, get_irn_mode(sel));
1603 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1610 * Transforms a CopyB node.
1612 * @param env The transformation environment
1613 * @return The transformed node.
1615 static ir_node *gen_CopyB(ia32_transform_env_t *env) {
1616 ir_node *res = NULL;
1617 dbg_info *dbg = env->dbg;
1618 ir_graph *irg = env->irg;
1619 ir_node *block = env->block;
1620 ir_node *node = env->irn;
1621 ir_node *src = get_CopyB_src(node);
1622 ir_node *dst = get_CopyB_dst(node);
1623 ir_node *mem = get_CopyB_mem(node);
1624 int size = get_type_size_bytes(get_CopyB_type(node));
1625 ir_mode *dst_mode = get_irn_mode(dst);
1626 ir_mode *src_mode = get_irn_mode(src);
1628 ir_node *in[3], *tmp;
1630 /* If we have to copy more than 16 bytes, we use REP MOVSx and */
1631 /* then we need the size explicitly in ECX. */
1632 if (size >= 16 * 4) {
1633 rem = size & 0x3; /* size % 4 */
1636 res = new_rd_ia32_Const(dbg, irg, block, get_irg_no_mem(irg), mode_Is);
1637 set_ia32_op_type(res, ia32_Const);
1638 set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
1640 res = new_rd_ia32_CopyB(dbg, irg, block, dst, src, res, mem);
1641 set_ia32_Immop_tarval(res, new_tarval_from_long(rem, mode_Is));
1643 /* ok: now attach Proj's because rep movsd will destroy esi, edi and ecx */
1644 in[0] = new_r_Proj(irg, block, res, dst_mode, pn_ia32_CopyB_DST);
1645 in[1] = new_r_Proj(irg, block, res, src_mode, pn_ia32_CopyB_SRC);
1646 in[2] = new_r_Proj(irg, block, res, mode_Is, pn_ia32_CopyB_CNT);
1647 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 3, in);
1649 tmp = ia32_get_proj_for_mode(node, mode_M);
1650 set_Proj_proj(tmp, pn_ia32_CopyB_M);
1653 res = new_rd_ia32_CopyB_i(dbg, irg, block, dst, src, mem);
1654 set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
1655 set_ia32_immop_type(res, ia32_ImmConst);
1657 /* ok: now attach Proj's because movsd will destroy esi and edi */
1658 in[0] = new_r_Proj(irg, block, res, dst_mode, pn_ia32_CopyB_i_DST);
1659 in[1] = new_r_Proj(irg, block, res, src_mode, pn_ia32_CopyB_i_SRC);
1660 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 2, in);
1662 tmp = ia32_get_proj_for_mode(node, mode_M);
1663 set_Proj_proj(tmp, pn_ia32_CopyB_i_M);
1666 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
1674 * Transforms a Mux node into CMov.
1676 * @param env The transformation environment
1677 * @return The transformed node.
1679 static ir_node *gen_Mux(ia32_transform_env_t *env) {
1681 ir_node *node = env->irn;
1682 ir_node *new_op = new_rd_ia32_CMov(env->dbg, env->irg, env->block, \
1683 get_Mux_sel(node), get_Mux_false(node), get_Mux_true(node), env->mode);
1685 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
1692 typedef ir_node *cmov_func_t(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *cmp_a, ir_node *cmp_b, \
1693 ir_node *psi_true, ir_node *psi_default, ir_mode *mode);
1696 * Transforms a Psi node into CMov.
1698 * @param env The transformation environment
1699 * @return The transformed node.
1701 static ir_node *gen_Psi(ia32_transform_env_t *env) {
1702 ia32_code_gen_t *cg = env->cg;
1703 dbg_info *dbg = env->dbg;
1704 ir_graph *irg = env->irg;
1705 ir_mode *mode = env->mode;
1706 ir_node *block = env->block;
1707 ir_node *node = env->irn;
1708 ir_node *cmp_proj = get_Mux_sel(node);
1709 ir_node *psi_true = get_Psi_val(node, 0);
1710 ir_node *psi_default = get_Psi_default(node);
1711 ir_node *noreg = ia32_new_NoReg_gp(cg);
1712 ir_node *nomem = new_rd_NoMem(irg);
1713 ir_node *cmp, *cmp_a, *cmp_b, *and1, *and2, *new_op = NULL;
1716 assert(get_irn_mode(cmp_proj) == mode_b && "Condition for Psi must have mode_b");
1718 cmp = get_Proj_pred(cmp_proj);
1719 cmp_a = get_Cmp_left(cmp);
1720 cmp_b = get_Cmp_right(cmp);
1721 pnc = get_Proj_proj(cmp_proj);
1723 if (mode_is_float(mode)) {
1724 /* floating point psi */
1727 /* 1st case: compare operands are float too */
1729 /* psi(cmp(a, b), t, f) can be done as: */
1730 /* tmp = cmp a, b */
1731 /* tmp2 = t and tmp */
1732 /* tmp3 = f and not tmp */
1733 /* res = tmp2 or tmp3 */
1735 /* in case the compare operands are int, we move them into xmm register */
1736 if (! mode_is_float(get_irn_mode(cmp_a))) {
1737 cmp_a = gen_sse_conv_int2float(cg, dbg, irg, block, cmp_a, node, mode_D);
1738 cmp_b = gen_sse_conv_int2float(cg, dbg, irg, block, cmp_b, node, mode_D);
1740 pnc |= 8; /* transform integer compare to fp compare */
1743 new_op = new_rd_ia32_xCmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);
1744 set_ia32_pncode(new_op, pnc);
1745 set_ia32_am_support(new_op, ia32_am_Source);
1746 set_ia32_res_mode(new_op, mode);
1747 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node));
1748 new_op = new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_xCmp_res);
1750 and1 = new_rd_ia32_xAnd(dbg, irg, block, noreg, noreg, psi_true, new_op, nomem);
1751 set_ia32_am_support(and1, ia32_am_None);
1752 set_ia32_res_mode(and1, mode);
1753 SET_IA32_ORIG_NODE(and1, ia32_get_old_node_name(cg, node));
1754 and1 = new_rd_Proj(dbg, irg, block, and1, mode, pn_ia32_xAnd_res);
1756 and2 = new_rd_ia32_xAndNot(dbg, irg, block, noreg, noreg, new_op, psi_default, nomem);
1757 set_ia32_am_support(and2, ia32_am_None);
1758 set_ia32_res_mode(and2, mode);
1759 SET_IA32_ORIG_NODE(and2, ia32_get_old_node_name(cg, node));
1760 and2 = new_rd_Proj(dbg, irg, block, and2, mode, pn_ia32_xAndNot_res);
1762 new_op = new_rd_ia32_xOr(dbg, irg, block, noreg, noreg, and1, and2, nomem);
1763 set_ia32_am_support(new_op, ia32_am_None);
1764 set_ia32_res_mode(new_op, mode);
1765 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node));
1766 new_op = new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_xOr_res);
1770 new_op = new_rd_ia32_vfCMov(dbg, irg, block, cmp_a, cmp_b, psi_true, psi_default, mode);
1771 set_ia32_pncode(new_op, pnc);
1772 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, node));
1777 construct_binop_func *set_func = NULL;
1778 cmov_func_t *cmov_func = NULL;
1780 if (mode_is_float(get_irn_mode(cmp_a))) {
1781 /* 1st case: compare operands are floats */
1786 set_func = new_rd_ia32_xCmpSet;
1787 cmov_func = new_rd_ia32_xCmpCMov;
1791 set_func = new_rd_ia32_vfCmpSet;
1792 cmov_func = new_rd_ia32_vfCmpCMov;
1795 pnc &= 7; /* fp compare -> int compare */
1798 /* 2nd case: compare operand are integer too */
1799 set_func = new_rd_ia32_CmpSet;
1800 cmov_func = new_rd_ia32_CmpCMov;
1803 /* create the nodes */
1805 /* check for special case first: And/Or -- Cmp with 0 -- Psi */
1806 if (is_ia32_Const_0(cmp_b) && is_Proj(cmp_a) && (is_ia32_And(get_Proj_pred(cmp_a)) || is_ia32_Or(get_Proj_pred(cmp_a)))) {
1807 if (is_ia32_Const_1(psi_true) && is_ia32_Const_0(psi_default)) {
1808 /* first case for SETcc: default is 0, set to 1 iff condition is true */
1809 new_op = new_rd_ia32_PsiCondSet(dbg, irg, block, cmp_a, mode);
1810 set_ia32_pncode(new_op, pnc);
1812 else if (is_ia32_Const_0(psi_true) && is_ia32_Const_1(psi_default)) {
1813 /* second case for SETcc: default is 1, set to 0 iff condition is true: */
1814 /* we invert condition and set default to 0 */
1815 new_op = new_rd_ia32_PsiCondSet(dbg, irg, block, cmp_a, mode);
1816 set_ia32_pncode(new_op, get_inversed_pnc(pnc));
1819 /* otherwise: use CMOVcc */
1820 new_op = new_rd_ia32_PsiCondCMov(dbg, irg, block, cmp_a, psi_true, psi_default, mode);
1821 set_ia32_pncode(new_op, pnc);
1824 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node));
1828 if (is_ia32_Const_1(psi_true) && is_ia32_Const_0(psi_default)) {
1829 /* first case for SETcc: default is 0, set to 1 iff condition is true */
1830 new_op = gen_binop(env, cmp_a, cmp_b, set_func);
1831 set_ia32_pncode(get_Proj_pred(new_op), pnc);
1832 set_ia32_am_support(get_Proj_pred(new_op), ia32_am_Source);
1834 else if (is_ia32_Const_0(psi_true) && is_ia32_Const_1(psi_default)) {
1835 /* second case for SETcc: default is 1, set to 0 iff condition is true: */
1836 /* we invert condition and set default to 0 */
1837 new_op = gen_binop(env, cmp_a, cmp_b, set_func);
1838 set_ia32_pncode(get_Proj_pred(new_op), get_inversed_pnc(pnc));
1839 set_ia32_am_support(get_Proj_pred(new_op), ia32_am_Source);
1842 /* otherwise: use CMOVcc */
1843 new_op = cmov_func(dbg, irg, block, cmp_a, cmp_b, psi_true, psi_default, mode);
1844 set_ia32_pncode(new_op, pnc);
1845 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node));
1855 * Following conversion rules apply:
1859 * 1) n bit -> m bit n > m (downscale)
1860 * a) target is signed: movsx
1861 * b) target is unsigned: and with lower bits sets
1862 * 2) n bit -> m bit n == m (sign change)
1864 * 3) n bit -> m bit n < m (upscale)
1865 * a) source is signed: movsx
1866 * b) source is unsigned: and with lower bits sets
1870 * SSE(1/2) convert to float or double (cvtsi2ss/sd)
1874 * SSE(1/2) convert from float or double to 32bit int (cvtss/sd2si)
1875 * if target mode < 32bit: additional INT -> INT conversion (see above)
1879 * SSE(1/2) convert from float or double to double or float (cvtss/sd2sd/ss)
1880 * x87 is mode_E internally, conversions happen only at load and store
1881 * in non-strict semantic
1885 * Create a conversion from x87 state register to general purpose.
1887 static ir_node *gen_x87_fp_to_gp(ia32_transform_env_t *env, ir_mode *tgt_mode) {
1888 ia32_code_gen_t *cg = env->cg;
1889 entity *ent = cg->fp_to_gp;
1890 ir_graph *irg = env->irg;
1891 ir_node *block = env->block;
1892 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1893 ir_node *op = get_Conv_op(env->irn);
1894 ir_node *fist, *mem, *load;
1897 int size = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_vfp].mode);
1898 ent = cg->fp_to_gp =
1899 frame_alloc_area(get_irg_frame_type(env->irg), size, 16, 0);
1903 fist = new_rd_ia32_vfist(env->dbg, irg, block, get_irg_frame(irg), noreg, op, get_irg_no_mem(irg));
1905 set_ia32_frame_ent(fist, ent);
1906 set_ia32_use_frame(fist);
1907 set_ia32_am_support(fist, ia32_am_Dest);
1908 set_ia32_op_type(fist, ia32_AddrModeD);
1909 set_ia32_am_flavour(fist, ia32_B);
1910 set_ia32_ls_mode(fist, mode_F);
1912 mem = new_r_Proj(irg, block, fist, mode_M, pn_ia32_vfist_M);
1915 load = new_rd_ia32_Load(env->dbg, irg, block, get_irg_frame(irg), noreg, mem);
1917 set_ia32_frame_ent(load, ent);
1918 set_ia32_use_frame(load);
1919 set_ia32_am_support(load, ia32_am_Source);
1920 set_ia32_op_type(load, ia32_AddrModeS);
1921 set_ia32_am_flavour(load, ia32_B);
1922 set_ia32_ls_mode(load, tgt_mode);
1924 return new_r_Proj(irg, block, load, tgt_mode, pn_ia32_Load_res);
1928 * Create a conversion from x87 state register to general purpose.
1930 static ir_node *gen_x87_gp_to_fp(ia32_transform_env_t *env, ir_mode *src_mode) {
1931 ia32_code_gen_t *cg = env->cg;
1932 entity *ent = cg->gp_to_fp;
1933 ir_graph *irg = env->irg;
1934 ir_node *block = env->block;
1935 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1936 ir_node *nomem = get_irg_no_mem(irg);
1937 ir_node *op = get_Conv_op(env->irn);
1938 ir_node *fild, *store, *mem;
1942 int size = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode);
1943 ent = cg->gp_to_fp =
1944 frame_alloc_area(get_irg_frame_type(env->irg), size, size, 0);
1947 /* first convert to 32 bit */
1948 src_bits = get_mode_size_bits(src_mode);
1949 if (src_bits == 8) {
1950 op = new_rd_ia32_Conv_I2I8Bit(env->dbg, irg, block, noreg, noreg, op, nomem);
1951 op = new_r_Proj(irg, block, op, mode_Is, 0);
1953 else if (src_bits < 32) {
1954 op = new_rd_ia32_Conv_I2I(env->dbg, irg, block, noreg, noreg, op, nomem);
1955 op = new_r_Proj(irg, block, op, mode_Is, 0);
1959 store = new_rd_ia32_Store(env->dbg, irg, block, get_irg_frame(irg), noreg, op, nomem);
1961 set_ia32_frame_ent(store, ent);
1962 set_ia32_use_frame(store);
1964 set_ia32_am_support(store, ia32_am_Dest);
1965 set_ia32_op_type(store, ia32_AddrModeD);
1966 set_ia32_am_flavour(store, ia32_B);
1967 set_ia32_ls_mode(store, mode_Is);
1969 mem = new_r_Proj(irg, block, store, mode_M, 0);
1972 fild = new_rd_ia32_vfild(env->dbg, irg, block, get_irg_frame(irg), noreg, mem);
1974 set_ia32_frame_ent(fild, ent);
1975 set_ia32_use_frame(fild);
1976 set_ia32_am_support(fild, ia32_am_Source);
1977 set_ia32_op_type(fild, ia32_AddrModeS);
1978 set_ia32_am_flavour(fild, ia32_B);
1979 set_ia32_ls_mode(fild, mode_F);
1981 return new_r_Proj(irg, block, fild, mode_F, 0);
1985 * Transforms a Conv node.
1987 * @param env The transformation environment
1988 * @return The created ia32 Conv node
1990 static ir_node *gen_Conv(ia32_transform_env_t *env) {
1991 dbg_info *dbg = env->dbg;
1992 ir_graph *irg = env->irg;
1993 ir_node *op = get_Conv_op(env->irn);
1994 ir_mode *src_mode = get_irn_mode(op);
1995 ir_mode *tgt_mode = env->mode;
1996 int src_bits = get_mode_size_bits(src_mode);
1997 int tgt_bits = get_mode_size_bits(tgt_mode);
1999 ir_node *block = env->block;
2000 ir_node *new_op = NULL;
2001 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
2002 ir_node *nomem = new_rd_NoMem(irg);
2004 DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
2006 if (src_mode == tgt_mode) {
2007 /* this can happen when changing mode_P to mode_Is */
2008 DB((mod, LEVEL_1, "killed Conv(mode, mode) ..."));
2009 edges_reroute(env->irn, op, irg);
2011 else if (mode_is_float(src_mode)) {
2012 /* we convert from float ... */
2013 if (mode_is_float(tgt_mode)) {
2015 if (USE_SSE2(env->cg)) {
2016 DB((mod, LEVEL_1, "create Conv(float, float) ..."));
2017 new_op = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, op, nomem);
2018 pn = pn_ia32_Conv_FP2FP_res;
2021 DB((mod, LEVEL_1, "killed Conv(float, float) ..."));
2022 edges_reroute(env->irn, op, irg);
2027 DB((mod, LEVEL_1, "create Conv(float, int) ..."));
2028 if (USE_SSE2(env->cg)) {
2029 new_op = new_rd_ia32_Conv_FP2I(dbg, irg, block, noreg, noreg, op, nomem);
2030 pn = pn_ia32_Conv_FP2I_res;
2033 return gen_x87_fp_to_gp(env, tgt_mode);
2035 /* if target mode is not int: add an additional downscale convert */
2036 if (tgt_bits < 32) {
2037 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
2038 set_ia32_am_support(new_op, ia32_am_Source);
2039 set_ia32_tgt_mode(new_op, tgt_mode);
2040 set_ia32_src_mode(new_op, src_mode);
2042 proj = new_rd_Proj(dbg, irg, block, new_op, mode_Is, pn_ia32_Conv_FP2I_res);
2044 if (tgt_bits == 8 || src_bits == 8) {
2045 new_op = new_rd_ia32_Conv_I2I8Bit(dbg, irg, block, noreg, noreg, proj, nomem);
2046 pn = pn_ia32_Conv_I2I8Bit_res;
2049 new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, proj, nomem);
2050 pn = pn_ia32_Conv_I2I_res;
2056 /* we convert from int ... */
2057 if (mode_is_float(tgt_mode)) {
2060 DB((mod, LEVEL_1, "create Conv(int, float) ..."));
2061 if (USE_SSE2(env->cg)) {
2062 new_op = new_rd_ia32_Conv_I2FP(dbg, irg, block, noreg, noreg, op, nomem);
2063 pn = pn_ia32_Conv_I2FP_res;
2066 return gen_x87_gp_to_fp(env, src_mode);
2070 if (get_mode_size_bits(src_mode) == tgt_bits) {
2071 DB((mod, LEVEL_1, "omitting equal size Conv(%+F, %+F) ...", src_mode, tgt_mode));
2072 edges_reroute(env->irn, op, irg);
2075 DB((mod, LEVEL_1, "create Conv(int, int) ...", src_mode, tgt_mode));
2076 if (tgt_bits == 8 || src_bits == 8) {
2077 new_op = new_rd_ia32_Conv_I2I8Bit(dbg, irg, block, noreg, noreg, op, nomem);
2078 pn = pn_ia32_Conv_I2I8Bit_res;
2081 new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, op, nomem);
2082 pn = pn_ia32_Conv_I2I_res;
2089 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
2090 set_ia32_tgt_mode(new_op, tgt_mode);
2091 set_ia32_src_mode(new_op, src_mode);
2093 set_ia32_am_support(new_op, ia32_am_Source);
2095 new_op = new_rd_Proj(dbg, irg, block, new_op, tgt_mode, pn);
2103 /********************************************
2106 * | |__ ___ _ __ ___ __| | ___ ___
2107 * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
2108 * | |_) | __/ | | | (_) | (_| | __/\__ \
2109 * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
2111 ********************************************/
2114 * Decides in which block the transformed StackParam should be placed.
2115 * If the StackParam has more than one user, the dominator block of
2116 * the users will be returned. In case of only one user, this is either
2117 * the user block or, in case of a Phi, the predecessor block of the Phi.
2119 static ir_node *get_block_transformed_stack_param(ir_node *irn) {
2120 ir_node *dom_bl = NULL;
2122 if (get_irn_n_edges(irn) == 1) {
2123 ir_node *src = get_edge_src_irn(get_irn_out_edge_first(irn));
2125 if (! is_Phi(src)) {
2126 dom_bl = get_nodes_block(src);
2129 /* Determine on which in position of the Phi the irn is */
2130 /* and get the corresponding cfg predecessor block. */
2132 int i = get_irn_pred_pos(src, irn);
2133 assert(i >= 0 && "kaputt");
2134 dom_bl = get_Block_cfgpred_block(get_nodes_block(src), i);
2138 dom_bl = node_users_smallest_common_dominator(irn, 1);
2141 assert(dom_bl && "dominator block not found");
2146 static ir_node *gen_be_StackParam(ia32_transform_env_t *env) {
2147 ir_node *new_op = NULL;
2148 ir_node *node = env->irn;
2149 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
2150 ir_node *mem = new_rd_NoMem(env->irg);
2151 ir_node *ptr = get_irn_n(node, 0);
2152 entity *ent = be_get_frame_entity(node);
2153 ir_mode *mode = env->mode;
2155 /* choose the block where to place the load */
2156 env->block = get_block_transformed_stack_param(node);
2158 if (mode_is_float(mode)) {
2160 if (USE_SSE2(env->cg))
2161 new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, mem);
2163 new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
2166 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem);
2169 set_ia32_frame_ent(new_op, ent);
2170 set_ia32_use_frame(new_op);
2172 set_ia32_am_support(new_op, ia32_am_Source);
2173 set_ia32_op_type(new_op, ia32_AddrModeS);
2174 set_ia32_am_flavour(new_op, ia32_B);
2175 set_ia32_ls_mode(new_op, mode);
2177 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
2179 return new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, pn_ia32_Load_res);
2183 * Transforms a FrameAddr into an ia32 Add.
2185 static ir_node *gen_be_FrameAddr(ia32_transform_env_t *env) {
2186 ir_node *new_op = NULL;
2187 ir_node *node = env->irn;
2188 ir_node *op = get_irn_n(node, 0);
2189 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
2190 ir_node *nomem = new_rd_NoMem(env->irg);
2192 new_op = new_rd_ia32_Add(env->dbg, env->irg, env->block, noreg, noreg, op, noreg, nomem);
2193 set_ia32_frame_ent(new_op, be_get_frame_entity(node));
2194 set_ia32_am_support(new_op, ia32_am_Full);
2195 set_ia32_use_frame(new_op);
2196 set_ia32_immop_type(new_op, ia32_ImmConst);
2197 set_ia32_commutative(new_op);
2199 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
2201 return new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, pn_ia32_Add_res);
2205 * Transforms a FrameLoad into an ia32 Load.
2207 static ir_node *gen_be_FrameLoad(ia32_transform_env_t *env) {
2208 ir_node *new_op = NULL;
2209 ir_node *node = env->irn;
2210 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
2211 ir_node *mem = get_irn_n(node, 0);
2212 ir_node *ptr = get_irn_n(node, 1);
2213 entity *ent = be_get_frame_entity(node);
2214 ir_mode *mode = get_type_mode(get_entity_type(ent));
2216 if (mode_is_float(mode)) {
2218 if (USE_SSE2(env->cg))
2219 new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, mem);
2221 new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
2224 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem);
2226 set_ia32_frame_ent(new_op, ent);
2227 set_ia32_use_frame(new_op);
2229 set_ia32_am_support(new_op, ia32_am_Source);
2230 set_ia32_op_type(new_op, ia32_AddrModeS);
2231 set_ia32_am_flavour(new_op, ia32_B);
2232 set_ia32_ls_mode(new_op, mode);
2234 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
2241 * Transforms a FrameStore into an ia32 Store.
2243 static ir_node *gen_be_FrameStore(ia32_transform_env_t *env) {
2244 ir_node *new_op = NULL;
2245 ir_node *node = env->irn;
2246 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
2247 ir_node *mem = get_irn_n(node, 0);
2248 ir_node *ptr = get_irn_n(node, 1);
2249 ir_node *val = get_irn_n(node, 2);
2250 entity *ent = be_get_frame_entity(node);
2251 ir_mode *mode = get_irn_mode(val);
2253 if (mode_is_float(mode)) {
2255 if (USE_SSE2(env->cg))
2256 new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem);
2258 new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem);
2260 else if (get_mode_size_bits(mode) == 8) {
2261 new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem);
2264 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem);
2267 set_ia32_frame_ent(new_op, ent);
2268 set_ia32_use_frame(new_op);
2270 set_ia32_am_support(new_op, ia32_am_Dest);
2271 set_ia32_op_type(new_op, ia32_AddrModeD);
2272 set_ia32_am_flavour(new_op, ia32_B);
2273 set_ia32_ls_mode(new_op, mode);
2275 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
2281 * In case SSE is used we need to copy the result from FPU TOS.
2283 static ir_node *gen_be_Call(ia32_transform_env_t *env) {
2284 ir_node *call_res = get_proj_for_pn(env->irn, pn_be_Call_first_res);
2285 ir_node *call_mem = get_proj_for_pn(env->irn, pn_be_Call_M_regular);
2288 if (! call_res || ! USE_SSE2(env->cg))
2291 mode = get_irn_mode(call_res);
2293 if (mode_is_float(mode)) {
2294 /* store st(0) onto stack */
2295 ir_node *frame = get_irg_frame(env->irg);
2296 ir_node *fstp = new_rd_ia32_GetST0(env->dbg, env->irg, env->block, frame, call_mem);
2297 ir_node *mproj = new_r_Proj(env->irg, env->block, fstp, mode_M, pn_ia32_GetST0_M);
2298 entity *ent = frame_alloc_area(get_irg_frame_type(env->irg), get_mode_size_bytes(mode), 16, 0);
2301 set_ia32_ls_mode(fstp, mode);
2302 set_ia32_op_type(fstp, ia32_AddrModeD);
2303 set_ia32_use_frame(fstp);
2304 set_ia32_frame_ent(fstp, ent);
2305 set_ia32_am_flavour(fstp, ia32_B);
2306 set_ia32_am_support(fstp, ia32_am_Dest);
2308 /* load into SSE register */
2309 sse_load = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, frame, ia32_new_NoReg_gp(env->cg), mproj);
2310 set_ia32_ls_mode(sse_load, mode);
2311 set_ia32_op_type(sse_load, ia32_AddrModeS);
2312 set_ia32_use_frame(sse_load);
2313 set_ia32_frame_ent(sse_load, ent);
2314 set_ia32_am_flavour(sse_load, ia32_B);
2315 set_ia32_am_support(sse_load, ia32_am_Source);
2316 sse_load = new_r_Proj(env->irg, env->block, sse_load, mode, pn_ia32_xLoad_res);
2318 /* reroute all users of the result proj to the sse load */
2319 edges_reroute(call_res, sse_load, env->irg);
2326 * In case SSE is used we need to copy the result from XMM0 to FPU TOS before return.
2328 static ir_node *gen_be_Return(ia32_transform_env_t *env) {
2329 ir_node *ret_val = get_irn_n(env->irn, be_pos_Return_val);
2330 ir_node *ret_mem = get_irn_n(env->irn, be_pos_Return_mem);
2333 if (! ret_val || ! USE_SSE2(env->cg))
2336 mode = get_irn_mode(ret_val);
2338 if (mode_is_float(mode)) {
2339 ir_node *frame = get_irg_frame(env->irg);
2340 entity *ent = frame_alloc_area(get_irg_frame_type(env->irg), get_mode_size_bytes(mode), 16, 0);
2341 ir_node *sse_store, *fld, *mproj;
2343 /* store xmm0 onto stack */
2344 sse_store = new_rd_ia32_xStoreSimple(env->dbg, env->irg, env->block, frame, ret_val, ret_mem);
2345 set_ia32_ls_mode(sse_store, mode);
2346 set_ia32_op_type(sse_store, ia32_AddrModeD);
2347 set_ia32_use_frame(sse_store);
2348 set_ia32_frame_ent(sse_store, ent);
2349 set_ia32_am_flavour(sse_store, ia32_B);
2350 set_ia32_am_support(sse_store, ia32_am_Dest);
2351 sse_store = new_r_Proj(env->irg, env->block, sse_store, mode_M, pn_ia32_xStore_M);
2354 fld = new_rd_ia32_SetST0(env->dbg, env->irg, env->block, frame, sse_store);
2355 set_ia32_ls_mode(fld, mode);
2356 set_ia32_op_type(fld, ia32_AddrModeS);
2357 set_ia32_use_frame(fld);
2358 set_ia32_frame_ent(fld, ent);
2359 set_ia32_am_flavour(fld, ia32_B);
2360 set_ia32_am_support(fld, ia32_am_Source);
2361 mproj = new_r_Proj(env->irg, env->block, fld, mode_M, pn_ia32_SetST0_M);
2362 fld = new_r_Proj(env->irg, env->block, fld, mode, pn_ia32_SetST0_res);
2364 /* set new return value */
2365 set_irn_n(env->irn, be_pos_Return_val, fld);
2366 set_irn_n(env->irn, be_pos_Return_mem, mproj);
2374 * This function just sets the register for the Unknown node
2375 * as this is not done during register allocation because Unknown
2376 * is an "ignore" node.
2378 static ir_node *gen_Unknown(ia32_transform_env_t *env) {
2379 ir_mode *mode = env->mode;
2380 ir_node *irn = env->irn;
2382 if (mode_is_float(mode)) {
2383 if (USE_SSE2(env->cg))
2384 arch_set_irn_register(env->cg->arch_env, irn, &ia32_xmm_regs[REG_XMM_UKNWN]);
2386 arch_set_irn_register(env->cg->arch_env, irn, &ia32_vfp_regs[REG_VFP_UKNWN]);
2388 else if (mode_is_int(mode) || mode_is_reference(mode)) {
2389 arch_set_irn_register(env->cg->arch_env, irn, &ia32_gp_regs[REG_GP_UKNWN]);
2392 assert(0 && "unsupported Unknown-Mode");
2398 /**********************************************************************
2401 * | | _____ _____ _ __ ___ __| | _ __ ___ __| | ___ ___
2402 * | |/ _ \ \ /\ / / _ \ '__/ _ \/ _` | | '_ \ / _ \ / _` |/ _ \/ __|
2403 * | | (_) \ V V / __/ | | __/ (_| | | | | | (_) | (_| | __/\__ \
2404 * |_|\___/ \_/\_/ \___|_| \___|\__,_| |_| |_|\___/ \__,_|\___||___/
2406 **********************************************************************/
2408 /* These nodes are created in intrinsic lowering (64bit -> 32bit) */
2410 typedef ir_node *construct_load_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
2413 typedef ir_node *construct_store_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
2414 ir_node *val, ir_node *mem);
2417 * Transforms a lowered Load into a "real" one.
2419 static ir_node *gen_lowered_Load(ia32_transform_env_t *env, construct_load_func func, char fp_unit) {
2420 ir_node *node = env->irn;
2421 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
2422 ir_mode *mode = get_ia32_ls_mode(node);
2425 ia32_am_flavour_t am_flav = ia32_B;
2428 Could be that we have SSE2 unit, but due to 64Bit Div/Conv
2429 lowering we have x87 nodes, so we need to enforce simulation.
2431 if (mode_is_float(mode)) {
2433 if (fp_unit == fp_x87)
2437 new_op = func(env->dbg, env->irg, env->block, get_irn_n(node, 0), noreg, get_irn_n(node, 1));
2438 am_offs = get_ia32_am_offs(node);
2442 add_ia32_am_offs(new_op, am_offs);
2445 set_ia32_am_support(new_op, ia32_am_Source);
2446 set_ia32_op_type(new_op, ia32_AddrModeS);
2447 set_ia32_am_flavour(new_op, am_flav);
2448 set_ia32_ls_mode(new_op, mode);
2449 set_ia32_frame_ent(new_op, get_ia32_frame_ent(node));
2450 set_ia32_use_frame(new_op);
2452 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, node));
2458 * Transforms a lowered Store into a "real" one.
2460 static ir_node *gen_lowered_Store(ia32_transform_env_t *env, construct_store_func func, char fp_unit) {
2461 ir_node *node = env->irn;
2462 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
2463 ir_mode *mode = get_ia32_ls_mode(node);
2466 ia32_am_flavour_t am_flav = ia32_B;
2469 Could be that we have SSE2 unit, but due to 64Bit Div/Conv
2470 lowering we have x87 nodes, so we need to enforce simulation.
2472 if (mode_is_float(mode)) {
2474 if (fp_unit == fp_x87)
2478 new_op = func(env->dbg, env->irg, env->block, get_irn_n(node, 0), noreg, get_irn_n(node, 1), get_irn_n(node, 2));
2480 if ((am_offs = get_ia32_am_offs(node)) != NULL) {
2482 add_ia32_am_offs(new_op, am_offs);
2485 set_ia32_am_support(new_op, ia32_am_Dest);
2486 set_ia32_op_type(new_op, ia32_AddrModeD);
2487 set_ia32_am_flavour(new_op, am_flav);
2488 set_ia32_ls_mode(new_op, mode);
2489 set_ia32_frame_ent(new_op, get_ia32_frame_ent(node));
2490 set_ia32_use_frame(new_op);
2492 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, node));
2499 * Transforms an ia32_l_XXX into a "real" XXX node
2501 * @param env The transformation environment
2502 * @return the created ia32 XXX node
2504 #define GEN_LOWERED_OP(op) \
2505 static ir_node *gen_ia32_l_##op(ia32_transform_env_t *env) { \
2506 if (mode_is_float(env->mode)) \
2508 return gen_binop(env, get_binop_left(env->irn), get_binop_right(env->irn), new_rd_ia32_##op); \
2511 #define GEN_LOWERED_x87_OP(op) \
2512 static ir_node *gen_ia32_l_##op(ia32_transform_env_t *env) { \
2514 FORCE_x87(env->cg); \
2515 new_op = gen_binop(env, get_binop_left(env->irn), get_binop_right(env->irn), new_rd_ia32_##op); \
2516 set_ia32_am_support(get_Proj_pred(new_op), ia32_am_None); \
2520 #define GEN_LOWERED_UNOP(op) \
2521 static ir_node *gen_ia32_l_##op(ia32_transform_env_t *env) { \
2522 return gen_unop(env, get_unop_op(env->irn), new_rd_ia32_##op); \
2525 #define GEN_LOWERED_SHIFT_OP(op) \
2526 static ir_node *gen_ia32_l_##op(ia32_transform_env_t *env) { \
2527 return gen_shift_binop(env, get_binop_left(env->irn), get_binop_right(env->irn), new_rd_ia32_##op); \
2530 #define GEN_LOWERED_LOAD(op, fp_unit) \
2531 static ir_node *gen_ia32_l_##op(ia32_transform_env_t *env) { \
2532 return gen_lowered_Load(env, new_rd_ia32_##op, fp_unit); \
2535 #define GEN_LOWERED_STORE(op, fp_unit) \
2536 static ir_node *gen_ia32_l_##op(ia32_transform_env_t *env) { \
2537 return gen_lowered_Store(env, new_rd_ia32_##op, fp_unit); \
2540 GEN_LOWERED_OP(AddC)
2542 GEN_LOWERED_OP(SubC)
2546 GEN_LOWERED_x87_OP(vfdiv)
2547 GEN_LOWERED_x87_OP(vfmul)
2548 GEN_LOWERED_x87_OP(vfsub)
2550 GEN_LOWERED_UNOP(Minus)
2552 GEN_LOWERED_LOAD(vfild, fp_x87)
2553 GEN_LOWERED_LOAD(Load, fp_none)
2554 GEN_LOWERED_STORE(vfist, fp_x87)
2555 GEN_LOWERED_STORE(Store, fp_none)
2558 * Transforms a l_MulS into a "real" MulS node.
2560 * @param env The transformation environment
2561 * @return the created ia32 MulS node
2563 static ir_node *gen_ia32_l_MulS(ia32_transform_env_t *env) {
2565 /* l_MulS is already a mode_T node, so we create the MulS in the normal way */
2566 /* and then skip the result Proj, because all needed Projs are already there. */
2568 ir_node *new_op = gen_binop(env, get_binop_left(env->irn), get_binop_right(env->irn), new_rd_ia32_MulS);
2569 ir_node *muls = get_Proj_pred(new_op);
2571 /* MulS cannot have AM for destination */
2572 if (get_ia32_am_support(muls) != ia32_am_None)
2573 set_ia32_am_support(muls, ia32_am_Source);
2578 GEN_LOWERED_SHIFT_OP(Shl)
2579 GEN_LOWERED_SHIFT_OP(Shr)
2580 GEN_LOWERED_SHIFT_OP(Shrs)
2583 * Transforms a l_ShlD/l_ShrD into a ShlD/ShrD. Those nodes have 3 data inputs:
2584 * op1 - target to be shifted
2585 * op2 - contains bits to be shifted into target
2587 * Only op3 can be an immediate.
2589 static ir_node *gen_lowered_64bit_shifts(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, ir_node *count) {
2590 ir_node *new_op = NULL;
2591 ir_mode *mode = env->mode;
2592 dbg_info *dbg = env->dbg;
2593 ir_graph *irg = env->irg;
2594 ir_node *block = env->block;
2595 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
2596 ir_node *nomem = new_NoMem();
2599 DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
2601 assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
2603 /* Check if immediate optimization is on and */
2604 /* if it's an operation with immediate. */
2605 imm_op = (env->cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(NULL, count) : NULL;
2607 /* Limit imm_op within range imm8 */
2609 tv = get_ia32_Immop_tarval(imm_op);
2612 tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
2613 set_ia32_Immop_tarval(imm_op, tv);
2620 /* integer operations */
2622 /* This is ShiftD with const */
2623 DB((mod, LEVEL_1, "ShiftD with immediate ..."));
2625 if (is_ia32_l_ShlD(env->irn))
2626 new_op = new_rd_ia32_ShlD(dbg, irg, block, noreg, noreg, op1, op2, noreg, nomem);
2628 new_op = new_rd_ia32_ShrD(dbg, irg, block, noreg, noreg, op1, op2, noreg, nomem);
2629 set_ia32_Immop_attr(new_op, imm_op);
2632 /* This is a normal ShiftD */
2633 DB((mod, LEVEL_1, "ShiftD binop ..."));
2634 if (is_ia32_l_ShlD(env->irn))
2635 new_op = new_rd_ia32_ShlD(dbg, irg, block, noreg, noreg, op1, op2, count, nomem);
2637 new_op = new_rd_ia32_ShrD(dbg, irg, block, noreg, noreg, op1, op2, count, nomem);
2640 /* set AM support */
2641 set_ia32_am_support(new_op, ia32_am_Dest);
2643 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));
2645 set_ia32_res_mode(new_op, mode);
2646 set_ia32_emit_cl(new_op);
2648 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
2651 static ir_node *gen_ia32_l_ShlD(ia32_transform_env_t *env) {
2652 return gen_lowered_64bit_shifts(env, get_irn_n(env->irn, 0), get_irn_n(env->irn, 1), get_irn_n(env->irn, 2));
2655 static ir_node *gen_ia32_l_ShrD(ia32_transform_env_t *env) {
2656 return gen_lowered_64bit_shifts(env, get_irn_n(env->irn, 0), get_irn_n(env->irn, 1), get_irn_n(env->irn, 2));
2660 * In case SSE Unit is used, the node is transformed into a vfst + xLoad.
2662 static ir_node *gen_ia32_l_X87toSSE(ia32_transform_env_t *env) {
2663 ia32_code_gen_t *cg = env->cg;
2664 ir_node *res = NULL;
2665 ir_node *ptr = get_irn_n(env->irn, 0);
2666 ir_node *val = get_irn_n(env->irn, 1);
2667 ir_node *mem = get_irn_n(env->irn, 2);
2670 ir_node *noreg = ia32_new_NoReg_gp(cg);
2672 /* Store x87 -> MEM */
2673 res = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem);
2674 set_ia32_frame_ent(res, get_ia32_frame_ent(env->irn));
2675 set_ia32_use_frame(res);
2676 set_ia32_ls_mode(res, get_ia32_ls_mode(env->irn));
2677 set_ia32_am_support(res, ia32_am_Dest);
2678 set_ia32_am_flavour(res, ia32_B);
2679 res = new_rd_Proj(env->dbg, env->irg, env->block, res, mode_M, pn_ia32_vfst_M);
2681 /* Load MEM -> SSE */
2682 res = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, res);
2683 set_ia32_frame_ent(res, get_ia32_frame_ent(env->irn));
2684 set_ia32_use_frame(res);
2685 set_ia32_ls_mode(res, get_ia32_ls_mode(env->irn));
2686 set_ia32_am_support(res, ia32_am_Source);
2687 set_ia32_am_flavour(res, ia32_B);
2688 res = new_rd_Proj(env->dbg, env->irg, env->block, res, get_ia32_ls_mode(env->irn), pn_ia32_xLoad_res);
2691 /* SSE unit is not used -> skip this node. */
2694 edges_reroute(env->irn, val, env->irg);
2695 for (i = get_irn_arity(env->irn) - 1; i >= 0; i--)
2696 set_irn_n(env->irn, i, get_irg_bad(env->irg));
2703 * In case SSE Unit is used, the node is transformed into a xStore + vfld.
2705 static ir_node *gen_ia32_l_SSEtoX87(ia32_transform_env_t *env) {
2706 ia32_code_gen_t *cg = env->cg;
2707 ir_node *res = NULL;
2708 ir_node *ptr = get_irn_n(env->irn, 0);
2709 ir_node *val = get_irn_n(env->irn, 1);
2710 ir_node *mem = get_irn_n(env->irn, 2);
2713 ir_node *noreg = ia32_new_NoReg_gp(cg);
2715 /* Store SSE -> MEM */
2716 res = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem);
2717 set_ia32_frame_ent(res, get_ia32_frame_ent(env->irn));
2718 set_ia32_use_frame(res);
2719 set_ia32_ls_mode(res, get_ia32_ls_mode(env->irn));
2720 set_ia32_am_support(res, ia32_am_Dest);
2721 set_ia32_am_flavour(res, ia32_B);
2722 res = new_rd_Proj(env->dbg, env->irg, env->block, res, mode_M, pn_ia32_xStore_M);
2724 /* Load MEM -> x87 */
2725 res = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem);
2726 set_ia32_frame_ent(res, get_ia32_frame_ent(env->irn));
2727 set_ia32_use_frame(res);
2728 set_ia32_ls_mode(res, get_ia32_ls_mode(env->irn));
2729 set_ia32_am_support(res, ia32_am_Source);
2730 set_ia32_am_flavour(res, ia32_B);
2731 res = new_rd_Proj(env->dbg, env->irg, env->block, res, get_ia32_ls_mode(env->irn), pn_ia32_vfld_res);
2734 /* SSE unit is not used -> skip this node. */
2737 edges_reroute(env->irn, val, env->irg);
2738 for (i = get_irn_arity(env->irn) - 1; i >= 0; i--)
2739 set_irn_n(env->irn, i, get_irg_bad(env->irg));
2745 /*********************************************************
2748 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
2749 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
2750 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
2751 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
2753 *********************************************************/
2756 * the BAD transformer.
2758 static ir_node *bad_transform(ia32_transform_env_t *env) {
2759 ir_fprintf(stderr, "Not implemented: %+F\n", env->irn);
2765 * Enters all transform functions into the generic pointer
2767 void ia32_register_transformers(void) {
2768 ir_op *op_Max, *op_Min, *op_Mulh;
2770 /* first clear the generic function pointer for all ops */
2771 clear_irp_opcodes_generic_func();
2773 #define GEN(a) op_##a->ops.generic = (op_func)gen_##a
2774 #define BAD(a) op_##a->ops.generic = (op_func)bad_transform
2808 /* transform ops from intrinsic lowering */
2829 GEN(ia32_l_X87toSSE);
2830 GEN(ia32_l_SSEtoX87);
2845 /* constant transformation happens earlier */
2850 /* we should never see these nodes */
2865 /* handle generic backend nodes */
2873 /* set the register for all Unknown nodes */
2876 op_Max = get_op_Max();
2879 op_Min = get_op_Min();
2882 op_Mulh = get_op_Mulh();
2891 typedef ir_node *(transform_func)(ia32_transform_env_t *env);
2894 * Transforms the given firm node (and maybe some other related nodes)
2895 * into one or more assembler nodes.
2897 * @param node the firm node
2898 * @param env the debug module
2900 void ia32_transform_node(ir_node *node, void *env) {
2901 ia32_code_gen_t *cg = (ia32_code_gen_t *)env;
2902 ir_op *op = get_irn_op(node);
2903 ir_node *asm_node = NULL;
2909 /* link arguments pointing to Unknown to the UNKNOWN Proj */
2910 for (i = get_irn_arity(node) - 1; i >= 0; i--) {
2911 if (is_Unknown(get_irn_n(node, i)))
2912 set_irn_n(node, i, be_get_unknown_for_mode(cg, get_irn_mode(get_irn_n(node, i))));
2915 DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
2916 if (op->ops.generic) {
2917 ia32_transform_env_t tenv;
2918 transform_func *transform = (transform_func *)op->ops.generic;
2920 tenv.block = get_nodes_block(node);
2921 tenv.dbg = get_irn_dbg_info(node);
2922 tenv.irg = current_ir_graph;
2924 tenv.mode = get_irn_mode(node);
2926 DEBUG_ONLY(tenv.mod = cg->mod;)
2928 asm_node = (*transform)(&tenv);
2931 /* exchange nodes if a new one was generated */
2933 exchange(node, asm_node);
2934 DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
2937 DB((cg->mod, LEVEL_1, "ignored\n"));
2942 * Transforms a psi condition.
2944 static void transform_psi_cond(ir_node *cond, ir_mode *mode, ia32_code_gen_t *cg) {
2947 /* if the mode is target mode, we have already seen this part of the tree */
2948 if (get_irn_mode(cond) == mode)
2951 assert(get_irn_mode(cond) == mode_b && "logical operator for condition must be mode_b");
2953 set_irn_mode(cond, mode);
2955 for (i = get_irn_arity(cond) - 1; i >= 0; i--) {
2956 ir_node *in = get_irn_n(cond, i);
2958 /* if in is a compare: transform into Set/xCmp */
2960 ir_node *new_op = NULL;
2961 ir_node *cmp = get_Proj_pred(in);
2962 ir_node *cmp_a = get_Cmp_left(cmp);
2963 ir_node *cmp_b = get_Cmp_right(cmp);
2964 dbg_info *dbg = get_irn_dbg_info(cmp);
2965 ir_graph *irg = get_irn_irg(cmp);
2966 ir_node *block = get_nodes_block(cmp);
2967 ir_node *noreg = ia32_new_NoReg_gp(cg);
2968 ir_node *nomem = new_rd_NoMem(irg);
2969 int pnc = get_Proj_proj(in);
2971 /* this is a compare */
2972 if (mode_is_float(mode)) {
2973 /* Psi is float, we need a floating point compare */
2977 if (! mode_is_float(get_irn_mode(cmp_a))) {
2978 cmp_a = gen_sse_conv_int2float(cg, dbg, irg, block, cmp_a, cmp_a, mode);
2979 cmp_b = gen_sse_conv_int2float(cg, dbg, irg, block, cmp_b, cmp_b, mode);
2983 new_op = new_rd_ia32_xCmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem);
2984 set_ia32_pncode(new_op, pnc);
2985 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, cmp));
2994 ia32_transform_env_t tenv;
2995 construct_binop_func *set_func = NULL;
2997 if (mode_is_float(get_irn_mode(cmp_a))) {
2998 /* 1st case: compare operands are floats */
3003 set_func = new_rd_ia32_xCmpSet;
3007 set_func = new_rd_ia32_vfCmpSet;
3010 pnc &= 7; /* fp compare -> int compare */
3013 /* 2nd case: compare operand are integer too */
3014 set_func = new_rd_ia32_CmpSet;
3025 new_op = gen_binop(&tenv, cmp_a, cmp_b, set_func);
3026 set_ia32_pncode(get_Proj_pred(new_op), pnc);
3027 set_ia32_am_support(get_Proj_pred(new_op), ia32_am_Source);
3030 /* the the new compare as in */
3031 set_irn_n(cond, i, new_op);
3034 /* another complex condition */
3035 transform_psi_cond(in, mode, cg);
3041 * The Psi selector can be a tree of compares combined with "And"s and "Or"s.
3042 * We create a Set node, respectively a xCmp in case the Psi is a float, for each
3043 * compare, which causes the compare result to be stores in a register. The
3044 * "And"s and "Or"s are transformed later, we just have to set their mode right.
3046 void ia32_transform_psi_cond_tree(ir_node *node, void *env) {
3047 ia32_code_gen_t *cg = env;
3048 ir_node *psi_sel, *new_cmp, *block;
3053 if (get_irn_opcode(node) != iro_Psi)
3056 psi_sel = get_Psi_cond(node, 0);
3058 /* if psi_cond is a cmp: do nothing, this case is covered by gen_Psi */
3059 if (is_Proj(psi_sel))
3062 mode = get_irn_mode(node);
3064 transform_psi_cond(psi_sel, mode, cg);
3066 irg = get_irn_irg(node);
3067 block = get_nodes_block(node);
3069 /* we need to compare the evaluated condition tree with 0 */
3071 /* BEWARE: new_r_Const_long works for floating point as well */
3072 new_cmp = new_r_Cmp(irg, block, psi_sel, new_r_Const_long(irg, block, mode, 0));
3073 new_cmp = new_r_Proj(irg, block, new_cmp, mode_b, pn_Cmp_Ne + (mode_is_float(mode) ? pn_Cmp_Uo : 0));
3075 set_Psi_cond(node, 0, new_cmp);