16 #include "../benode_t.h"
17 #include "bearch_ia32_t.h"
19 #include "ia32_nodes_attr.h"
20 #include "../arch/archop.h" /* we need this for Min and Max nodes */
21 #include "ia32_transform.h"
22 #include "ia32_new_nodes.h"
23 #include "ia32_map_regs.h"
25 #include "gen_ia32_regalloc_if.h"
27 extern ir_op *get_op_Mulh(void);
29 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
30 ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode);
32 typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
33 ir_node *op, ir_node *mem, ir_mode *mode);
35 /* TEMPORARY WORKAROUND */
36 ir_node *be_new_NoReg(ir_graph *irg) {
40 /****************************************************************************************************
42 * | | | | / _| | | (_)
43 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
44 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
45 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
46 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
48 ****************************************************************************************************/
51 #define is_cnst(op) (is_ia32_Const(op) || is_ia32_fConst(op))
53 /* determine if one operator is an Imm */
54 static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
56 return is_cnst(op1) ? op1 : (is_cnst(op2) ? op2 : NULL);
57 else return is_cnst(op2) ? op2 : NULL;
60 /* determine if one operator is not an Imm */
61 static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
62 return !is_cnst(op1) ? op1 : (!is_cnst(op2) ? op2 : NULL);
67 * Construct a standard binary operation, set AM and immediate if required.
69 * @param env The transformation environment
70 * @param op1 The first operand
71 * @param op2 The second operand
72 * @param func The node constructor function
73 * @return The constructed ia32 node.
75 static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
76 ir_node *new_op = NULL;
77 ir_mode *mode = env->mode;
78 dbg_info *dbg = env->dbg;
79 ir_graph *irg = env->irg;
80 ir_node *block = env->block;
81 firm_dbg_module_t *mod = env->mod;
82 ir_node *noreg = be_new_NoReg(irg);
83 ir_node *nomem = new_NoMem();
84 ir_node *expr_op, *imm_op;
87 /* check if it's an operation with immediate */
88 if (is_op_commutative(get_irn_op(env->irn))) {
89 imm_op = get_immediate_op(op1, op2);
90 expr_op = get_expr_op(op1, op2);
93 imm_op = get_immediate_op(NULL, op2);
94 expr_op = get_expr_op(op1, op2);
97 assert((expr_op || imm_op) && "invalid operands");
100 /* We have two consts here: not yet supported */
104 if (mode_is_float(mode)) {
105 /* floating point operations */
108 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
109 set_ia32_Immop_attr(new_op, imm_op);
110 set_ia32_am_support(new_op, ia32_am_None);
113 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
114 set_ia32_am_support(new_op, ia32_am_Source);
118 /* integer operations */
120 /* This is expr + const */
121 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
122 set_ia32_Immop_attr(new_op, imm_op);
125 set_ia32_am_support(new_op, ia32_am_Dest);
128 /* This is a normal operation */
129 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
132 set_ia32_am_support(new_op, ia32_am_Full);
136 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
142 * Construct a shift/rotate binary operation, sets AM and immediate if required.
144 * @param env The transformation environment
145 * @param op1 The first operand
146 * @param op2 The second operand
147 * @param func The node constructor function
148 * @return The constructed ia32 node.
150 static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
151 ir_node *new_op = NULL;
152 ir_mode *mode = env->mode;
153 dbg_info *dbg = env->dbg;
154 ir_graph *irg = env->irg;
155 ir_node *block = env->block;
156 firm_dbg_module_t *mod = env->mod;
157 ir_node *noreg = be_new_NoReg(irg);
158 ir_node *nomem = new_NoMem();
159 ir_node *expr_op, *imm_op;
162 assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
164 imm_op = get_immediate_op(NULL, op2);
165 expr_op = get_expr_op(op1, op2);
167 assert((expr_op || imm_op) && "invalid operands");
170 /* We have two consts here: not yet supported */
174 /* Limit imm_op within range imm8 */
176 tv = get_ia32_Immop_tarval(imm_op);
179 tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
186 /* integer operations */
188 /* This is shift/rot with const */
190 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
191 set_ia32_Immop_attr(new_op, imm_op);
194 /* This is a normal shift/rot */
195 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
199 set_ia32_am_support(new_op, ia32_am_Dest);
201 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
206 * Construct a standard unary operation, set AM and immediate if required.
208 * @param env The transformation environment
209 * @param op The operand
210 * @param func The node constructor function
211 * @return The constructed ia32 node.
213 static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) {
214 ir_node *new_op = NULL;
215 ir_mode *mode = env->mode;
216 dbg_info *dbg = env->dbg;
217 ir_graph *irg = env->irg;
218 ir_node *block = env->block;
219 ir_node *noreg = be_new_NoReg(irg);
220 ir_node *nomem = new_NoMem();
222 new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T);
224 if (mode_is_float(mode)) {
225 /* floating point operations don't support implicit store */
226 set_ia32_am_support(new_op, ia32_am_None);
229 set_ia32_am_support(new_op, ia32_am_Dest);
232 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
238 * Creates an ia32 Add with immediate.
240 * @param env The transformation environment
241 * @param expr_op The expression operator
242 * @param const_op The constant
243 * @return the created ia32 Add node
245 static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
246 ir_node *new_op = NULL;
247 tarval *tv = get_ia32_Immop_tarval(const_op);
248 firm_dbg_module_t *mod = env->mod;
249 dbg_info *dbg = env->dbg;
250 ir_mode *mode = env->mode;
251 ir_graph *irg = env->irg;
252 ir_node *block = env->block;
253 ir_node *noreg = be_new_NoReg(irg);
254 ir_node *nomem = new_NoMem();
256 tarval_classification_t class_tv, class_negtv;
258 /* const_op: tarval or SymConst? */
260 /* optimize tarvals */
261 class_tv = classify_tarval(tv);
262 class_negtv = classify_tarval(tarval_neg(tv));
264 if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
265 DB((env->mod, LEVEL_2, "Add(1) to Inc ... "));
266 new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
269 else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
270 DB((mod, LEVEL_2, "Add(-1) to Dec ... "));
271 new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
277 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
278 set_ia32_Immop_attr(new_op, const_op);
285 * Creates an ia32 Add.
287 * @param dbg firm node dbg
288 * @param block the block the new node should belong to
289 * @param op1 first operator
290 * @param op2 second operator
291 * @param mode node mode
292 * @return the created ia32 Add node
294 static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
295 ir_node *new_op = NULL;
296 dbg_info *dbg = env->dbg;
297 ir_mode *mode = env->mode;
298 ir_graph *irg = env->irg;
299 ir_node *block = env->block;
300 ir_node *noreg = be_new_NoReg(irg);
301 ir_node *nomem = new_NoMem();
302 ir_node *expr_op, *imm_op;
304 imm_op = get_immediate_op(op1, op2);
305 expr_op = get_expr_op(op1, op2);
307 assert((expr_op || imm_op) && "invalid operands");
309 if (mode_is_float(mode)) {
310 return gen_binop(env, op1, op2, new_rd_ia32_fAdd);
315 /* No expr_op means, that we have two const - one symconst and */
316 /* one tarval or another symconst - because this case is not */
317 /* covered by constant folding */
319 new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode_T);
320 add_ia32_am_offs(new_op, get_ia32_cnst(op1));
321 add_ia32_am_offs(new_op, get_ia32_cnst(op2));
324 set_ia32_am_support(new_op, ia32_am_Source);
325 set_ia32_op_type(new_op, ia32_AddrModeS);
328 /* This is expr + const */
329 new_op = gen_imm_Add(env, expr_op, imm_op);
332 set_ia32_am_support(new_op, ia32_am_Dest);
335 /* This is a normal add */
336 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
339 set_ia32_am_support(new_op, ia32_am_Full);
343 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
349 * Creates an ia32 Mul.
351 * @param dbg firm node dbg
352 * @param block the block the new node should belong to
353 * @param op1 first operator
354 * @param op2 second operator
355 * @param mode node mode
356 * @return the created ia32 Mul node
358 ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
361 if (mode_is_float(env->mode)) {
362 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul);
365 new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
374 * Creates an ia32 Mulh.
375 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
376 * this result while Mul returns the lower 32 bit.
378 * @param env The transformation environment
379 * @param op1 The first operator
380 * @param op2 The second operator
381 * @return the created ia32 Mulh node
383 static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
384 ir_node *proj_EAX, *proj_EDX, *mulh;
387 assert(mode_is_float(env->mode) && "Mulh with float not supported");
388 proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh);
389 mulh = get_Proj_pred(proj_EAX);
390 proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX);
392 /* to be on the save side */
393 set_Proj_proj(proj_EAX, pn_EAX);
395 if (get_ia32_cnst(mulh)) {
396 /* Mulh with const cannot have AM */
397 set_ia32_am_support(mulh, ia32_am_None);
400 /* Mulh cannot have AM for destination */
401 set_ia32_am_support(mulh, ia32_am_Source);
407 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);
415 * Creates an ia32 And.
417 * @param env The transformation environment
418 * @param op1 The first operator
419 * @param op2 The second operator
420 * @return The created ia32 And node
422 static ir_node *gen_And(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
423 if (mode_is_float(env->mode)) {
424 return gen_binop(env, op1, op2, new_rd_ia32_fAnd);
427 return gen_binop(env, op1, op2, new_rd_ia32_And);
434 * Creates an ia32 Or.
436 * @param env The transformation environment
437 * @param op1 The first operator
438 * @param op2 The second operator
439 * @return The created ia32 Or node
441 static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
442 if (mode_is_float(env->mode)) {
443 return gen_binop(env, op1, op2, new_rd_ia32_fOr);
446 return gen_binop(env, op1, op2, new_rd_ia32_Or);
453 * Creates an ia32 Eor.
455 * @param env The transformation environment
456 * @param op1 The first operator
457 * @param op2 The second operator
458 * @return The created ia32 Eor node
460 static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
461 if (mode_is_float(env->mode)) {
462 return gen_binop(env, op1, op2, new_rd_ia32_fEor);
465 return gen_binop(env, op1, op2, new_rd_ia32_Eor);
472 * Creates an ia32 Max.
474 * @param env The transformation environment
475 * @param op1 The first operator
476 * @param op2 The second operator
477 * @return the created ia32 Max node
479 static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
482 if (mode_is_float(env->mode)) {
483 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax);
486 new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
487 set_ia32_am_support(new_op, ia32_am_None);
496 * Creates an ia32 Min.
498 * @param env The transformation environment
499 * @param op1 The first operator
500 * @param op2 The second operator
501 * @return the created ia32 Min node
503 static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
506 if (mode_is_float(env->mode)) {
507 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin);
510 new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
511 set_ia32_am_support(new_op, ia32_am_None);
520 * Creates an ia32 Sub with immediate.
522 * @param env The transformation environment
523 * @param op1 The first operator
524 * @param op2 The second operator
525 * @return The created ia32 Sub node
527 static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
528 ir_node *new_op = NULL;
529 tarval *tv = get_ia32_Immop_tarval(const_op);
530 firm_dbg_module_t *mod = env->mod;
531 dbg_info *dbg = env->dbg;
532 ir_mode *mode = env->mode;
533 ir_graph *irg = env->irg;
534 ir_node *block = env->block;
535 ir_node *noreg = be_new_NoReg(irg);
536 ir_node *nomem = new_NoMem();
538 tarval_classification_t class_tv, class_negtv;
540 /* const_op: tarval or SymConst? */
542 /* optimize tarvals */
543 class_tv = classify_tarval(tv);
544 class_negtv = classify_tarval(tarval_neg(tv));
546 if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
547 DB((mod, LEVEL_2, "Sub(1) to Dec ... "));
548 new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
551 else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
552 DB((mod, LEVEL_2, "Sub(-1) to Inc ... "));
553 new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
559 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
560 set_ia32_Immop_attr(new_op, const_op);
567 * Creates an ia32 Sub.
569 * @param env The transformation environment
570 * @param op1 The first operator
571 * @param op2 The second operator
572 * @return The created ia32 Sub node
574 static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
575 ir_node *new_op = NULL;
576 dbg_info *dbg = env->dbg;
577 ir_mode *mode = env->mode;
578 ir_graph *irg = env->irg;
579 ir_node *block = env->block;
580 ir_node *noreg = be_new_NoReg(irg);
581 ir_node *nomem = new_NoMem();
582 ir_node *expr_op, *imm_op;
584 imm_op = get_immediate_op(NULL, op2);
585 expr_op = get_expr_op(op1, op2);
587 assert((expr_op || imm_op) && "invalid operands");
589 if (mode_is_float(mode)) {
590 return gen_binop(env, op1, op2, new_rd_ia32_fSub);
595 /* No expr_op means, that we have two const - one symconst and */
596 /* one tarval or another symconst - because this case is not */
597 /* covered by constant folding */
599 new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
600 add_ia32_am_offs(new_op, get_ia32_cnst(op1));
601 sub_ia32_am_offs(new_op, get_ia32_cnst(op2));
604 set_ia32_am_support(new_op, ia32_am_Source);
605 set_ia32_op_type(new_op, ia32_AddrModeS);
608 /* This is expr - const */
609 new_op = gen_imm_Sub(env, expr_op, imm_op);
612 set_ia32_am_support(new_op, ia32_am_Dest);
615 /* This is a normal sub */
616 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
619 set_ia32_am_support(new_op, ia32_am_Full);
623 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
629 * Generates an ia32 DivMod with additional infrastructure for the
630 * register allocator if needed.
632 * @param env The transformation environment
633 * @param dividend -no comment- :)
634 * @param divisor -no comment- :)
635 * @param dm_flav flavour_Div/Mod/DivMod
636 * @return The created ia32 DivMod node
638 static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
640 ir_node *edx_node, *cltd;
642 dbg_info *dbg = env->dbg;
643 ir_graph *irg = env->irg;
644 ir_node *block = env->block;
645 ir_mode *mode = env->mode;
646 ir_node *irn = env->irn;
651 mem = get_Div_mem(irn);
654 mem = get_Mod_mem(irn);
657 mem = get_DivMod_mem(irn);
663 if (mode_is_signed(mode)) {
664 /* in signed mode, we need to sign extend the dividend */
665 cltd = new_rd_ia32_Cdq(dbg, irg, block, dividend, mode_T);
666 dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX);
667 edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX);
670 edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
671 set_ia32_Const_type(edx_node, ia32_Const);
672 set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
675 res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode);
677 set_ia32_flavour(res, dm_flav);
678 set_ia32_n_res(res, 2);
680 /* Only one proj is used -> We must add a second proj and */
681 /* connect this one to a Keep node to eat up the second */
682 /* destroyed register. */
683 if (get_irn_n_edges(irn) == 1) {
684 proj = get_edge_src_irn(get_irn_out_edge_first(irn));
685 assert(is_Proj(proj) && "non-Proj to Div/Mod node");
687 if (get_Proj_proj(proj) == pn_DivMod_res_div) {
688 in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_mod);
691 in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
694 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
702 * Wrapper for generate_DivMod. Sets flavour_Mod.
704 static ir_node *gen_Mod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
705 return generate_DivMod(env, op1, op2, flavour_Mod);
711 * Wrapper for generate_DivMod. Sets flavour_Div.
713 static ir_node *gen_Div(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
714 return generate_DivMod(env, op1, op2, flavour_Div);
720 * Wrapper for generate_DivMod. Sets flavour_DivMod.
722 static ir_node *gen_DivMod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
723 return generate_DivMod(env, op1, op2, flavour_DivMod);
729 * Creates an ia32 floating Div.
731 * @param env The transformation environment
732 * @param op1 The first operator
733 * @param op2 The second operator
734 * @return The created ia32 fDiv node
736 static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
737 return gen_binop(env, op1, op2, new_rd_ia32_fDiv);
743 * Creates an ia32 Shl.
745 * @param env The transformation environment
746 * @param op1 The first operator
747 * @param op2 The second operator
748 * @return The created ia32 Shl node
750 static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
751 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shl);
757 * Creates an ia32 Shr.
759 * @param env The transformation environment
760 * @param op1 The first operator
761 * @param op2 The second operator
762 * @return The created ia32 Shr node
764 static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
765 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shr);
771 * Creates an ia32 Shrs.
773 * @param env The transformation environment
774 * @param op1 The first operator
775 * @param op2 The second operator
776 * @return The created ia32 Shrs node
778 static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
779 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shrs);
785 * Creates an ia32 RotL.
787 * @param env The transformation environment
788 * @param op1 The first operator
789 * @param op2 The second operator
790 * @return The created ia32 RotL node
792 static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
793 return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL);
799 * Creates an ia32 RotR.
800 * NOTE: There is no RotR with immediate because this would always be a RotL
801 * "imm-mode_size_bits" which can be pre-calculated.
803 * @param env The transformation environment
804 * @param op1 The first operator
805 * @param op2 The second operator
806 * @return The created ia32 RotR node
808 static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
809 return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR);
815 * Creates an ia32 RotR or RotL (depending on the found pattern).
817 * @param env The transformation environment
818 * @param op1 The first operator
819 * @param op2 The second operator
820 * @return The created ia32 RotL or RotR node
822 static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
823 ir_node *rotate = NULL;
825 /* Firm has only Rot (which is a RotL), so we are looking for a right (op2)
826 operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
827 that means we can create a RotR instead of an Add and a RotL */
830 ir_node *pred = get_Proj_pred(op2);
832 if (is_ia32_Add(pred)) {
833 ir_node *pred_pred = get_irn_n(pred, 2);
834 tarval *tv = get_ia32_Immop_tarval(pred);
835 long bits = get_mode_size_bits(env->mode);
837 if (is_Proj(pred_pred)) {
838 pred_pred = get_Proj_pred(pred_pred);
841 if (is_ia32_Minus(pred_pred) &&
842 tarval_is_long(tv) &&
843 get_tarval_long(tv) == bits)
845 DB((env->mod, LEVEL_1, "RotL into RotR ... "));
846 rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
853 rotate = gen_RotL(env, op1, op2);
862 * Transforms a Minus node.
864 * @param env The transformation environment
865 * @param op The operator
866 * @return The created ia32 Minus node
868 static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
871 if (mode_is_float(env->mode)) {
875 new_op = gen_unop(env, op, new_rd_ia32_Minus);
884 * Transforms a Conv node.
886 * @param env The transformation environment
887 * @param op The operator
888 * @return The created ia32 Conv node
890 static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
891 return new_rd_ia32_Conv(env->dbg, env->irg, env->block, op, env->mode);
897 * Transforms a Not node.
899 * @param env The transformation environment
900 * @param op The operator
901 * @return The created ia32 Not node
903 static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
906 if (mode_is_float(env->mode)) {
910 new_op = gen_unop(env, op, new_rd_ia32_Not);
919 * Transforms an Abs node.
921 * @param env The transformation environment
922 * @param op The operator
923 * @return The created ia32 Abs node
925 static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
926 ir_node *res, *p_eax, *p_edx;
927 dbg_info *dbg = env->dbg;
928 ir_mode *mode = env->mode;
929 ir_graph *irg = env->irg;
930 ir_node *block = env->block;
931 ir_node *noreg = be_new_NoReg(irg);
932 ir_node *nomem = new_NoMem();
934 if (mode_is_float(mode)) {
938 res = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T);
939 p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
940 p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
941 res = new_rd_ia32_Eor(dbg, irg, block, noreg, noreg, p_eax, p_edx, nomem, mode_T);
942 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
943 res = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, res, p_edx, nomem, mode_T);
944 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
954 * @param mod the debug module
955 * @param block the block the new node should belong to
956 * @param node the ir Load node
957 * @param mode node mode
958 * @return the created ia32 Load node
960 static ir_node *gen_Load(ia32_transform_env_t *env) {
961 ir_node *node = env->irn;
962 ir_node *noreg = be_new_NoReg(env->irg);
964 if (mode_is_float(env->mode)) {
965 return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
967 return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
973 * Transforms a Store.
975 * @param mod the debug module
976 * @param block the block the new node should belong to
977 * @param node the ir Store node
978 * @param mode node mode
979 * @return the created ia32 Store node
981 ir_node *gen_Store(ia32_transform_env_t *env) {
982 ir_node *node = env->irn;
983 ir_node *noreg = be_new_NoReg(env->irg);
985 if (mode_is_float(env->mode)) {
986 return new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode);
988 return new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode);
994 * Transforms a Call and its arguments corresponding to the calling convention.
996 * @param mod the debug module
997 * @param block the block the new node should belong to
998 * @param node the ir Call node
999 * @param dummy mode doesn't matter
1000 * @return the created ia32 Call node
1002 static ir_node *gen_Call(ia32_transform_env_t *env) {
1003 const ia32_register_req_t **in_req;
1005 ir_node *new_call, *sync;
1006 int i, j, n_new_call_in, ignore = 0;
1008 dbg_info *dbg = env->dbg;
1009 ir_graph *irg = env->irg;
1010 ir_node *block = env->block;
1011 ir_node *call = env->irn;
1012 ir_node **stack_param = NULL;
1013 ir_node **param = get_Call_param_arr(call);
1014 ir_node *call_Mem = get_Call_mem(call);
1015 unsigned cc = get_method_calling_convention(get_Call_type(call));
1016 int n = get_Call_n_params(call);
1019 int n_res = get_method_n_ress(get_Call_type(call));
1021 assert(n_res <= 2 && "method with more than two results not supported");
1023 if (cc & cc_reg_param)
1024 biggest_n = ia32_get_n_regparam_class(n, param, &ignore, &ignore);
1026 /* remember: biggest_n = x means we can pass (x + 1) parameters in register */
1028 /* do we need to pass arguments on stack? */
1029 if (biggest_n + 1 < n)
1030 stack_param = xcalloc(n - biggest_n - 1, sizeof(ir_node *));
1032 /* we need at least one in, either for the stack params or the call_Mem */
1033 n_new_call_in = biggest_n + 2;
1035 /* the call has one IN for all stack parameter and one IN for each reg param */
1036 in = xcalloc(n_new_call_in, sizeof(ir_node *));
1037 in_req = xcalloc(n_new_call_in, sizeof(arch_register_req_t *));
1039 /* loop over all parameters and set the register requirements */
1040 for (i = 0; i <= biggest_n && (cc & cc_reg_param); i++) {
1041 in_req[i] = ia32_get_RegParam_req(n, param, i, cc);
1045 /* create remaining stack parameters */
1046 if (cc & cc_last_on_top) {
1047 for (i = stack_idx; i < n; i++) {
1048 /* pass it on stack */
1049 if (mode_is_float(get_irn_mode(param[i]))) {
1050 stack_param[i - stack_idx] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg,
1051 block, call_Mem, param[i], mode_M);
1054 stack_param[i - stack_idx] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg,
1055 block, call_Mem, param[i], mode_M);
1057 /* set the argument number for later lowering */
1058 set_ia32_pncode(stack_param[i - stack_idx], i - stack_idx);
1062 for (i = n - 1, j = 0; i >= stack_idx; i--, j++) {
1063 /* pass it on stack */
1064 if (mode_is_float(get_irn_mode(param[i]))) {
1065 stack_param[j] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg,
1066 block, call_Mem, param[i], mode_M);
1069 stack_param[j] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg,
1070 block, call_Mem, param[i], mode_M);
1072 /* set the argument number for later lowering */
1073 set_ia32_pncode(stack_param[j], j);
1078 sync = new_r_Sync(irg, block, n - biggest_n - 1, stack_param);
1079 in[n_new_call_in - 1] = sync;
1082 in[n_new_call_in - 1] = call_Mem;
1085 /* create the new node */
1086 new_call = new_rd_ia32_Call(dbg, irg, block, n_new_call_in, in);
1087 set_ia32_Immop_attr(new_call, get_Call_ptr(call));
1089 /* set register requirements for in and out */
1090 attr = get_ia32_attr(new_call);
1091 attr->in_req = in_req;
1093 set_ia32_n_res(new_call, n_res);
1096 attr->out_req = xcalloc(n_res, sizeof(ia32_register_req_t *));
1097 attr->slots = xcalloc(n_res, sizeof(arch_register_t *));
1100 /* two results only appear when a 64bit int result is broken up into two 32bit results */
1102 if (mode_is_float(get_type_mode(get_method_res_type(get_Call_type(call), 0))))
1103 attr->out_req[0] = &ia32_default_req_ia32_fp_xmm0;
1105 attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
1107 else if (n_res == 2) {
1108 attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
1109 attr->out_req[1] = &ia32_default_req_ia32_gp_edx;
1112 /* stack parameter has no OUT register */
1113 attr->in_req[n_new_call_in - 1] = &ia32_default_req_none;
1121 * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
1123 * @param env The transformation environment
1124 * @return The transformed node.
1126 static ir_node *gen_Cond(ia32_transform_env_t *env) {
1127 dbg_info *dbg = env->dbg;
1128 ir_graph *irg = env->irg;
1129 ir_node *block = env->block;
1130 ir_node *node = env->irn;
1131 ir_node *sel = get_Cond_selector(node);
1132 ir_mode *sel_mode = get_irn_mode(sel);
1133 ir_node *res = NULL;
1134 ir_node *pred = NULL;
1135 ir_node *noreg = be_new_NoReg(irg);
1136 ir_node *nomem = new_NoMem();
1137 ir_node *cmp_a, *cmp_b, *cnst, *expr;
1139 if (is_Proj(sel) && sel_mode == mode_b) {
1140 pred = get_Proj_pred(sel);
1142 /* get both compare operators */
1143 cmp_a = get_Cmp_left(pred);
1144 cmp_b = get_Cmp_right(pred);
1146 /* check if we can use a CondJmp with immediate */
1147 cnst = get_immediate_op(cmp_a, cmp_b);
1148 expr = get_expr_op(cmp_a, cmp_b);
1151 res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T);
1152 set_ia32_Immop_attr(res, cnst);
1155 res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T);
1158 set_ia32_pncode(res, get_Proj_proj(sel));
1161 res = new_rd_ia32_SwitchJmp(dbg, irg, block, noreg, noreg, sel, nomem, mode_T);
1162 set_ia32_pncode(res, get_Cond_defaultProj(node));
1171 * Transform the argument projs from a start node corresponding to the
1172 * calling convention.
1173 * It transforms "Proj Arg x -> ProjT -> Start <- ProjM" into
1174 * "RegParam x -> ProjT -> Start" OR
1175 * "StackParam x -> ProjM -> Start"
1176 * whether parameter is passed in register or on stack.
1178 * @param mod the debug module
1179 * @param block the block the nodes should belong to
1180 * @param proj the ProjT node which points to Start
1181 * @param start the Start node
1182 * @return Should be always NULL
1184 static ir_node *gen_Proj_Start(ia32_transform_env_t *env, ir_node *proj, ir_node *start) {
1185 const ia32_register_req_t *temp_req;
1186 const ir_edge_t *edge;
1187 ir_node *succ, *irn;
1192 ir_node *proj_M = get_irg_initial_mem(current_ir_graph);
1193 entity *irg_ent = get_irg_entity(current_ir_graph);
1194 ir_type *tp = get_entity_type(irg_ent);
1196 ir_graph *irg = env->irg;
1197 ir_node *block = env->block;
1199 assert(is_Method_type(tp) && "irg type is not a method");
1201 switch(get_Proj_proj(proj)) {
1202 case pn_Start_T_args:
1203 /* We cannot use get_method_n_params here as the function might
1204 be variadic or one argument is not used. */
1205 n = get_irn_n_edges(proj);
1207 /* Allocate memory for all non variadic parameters in advance to be on the save side */
1208 env->cg->reg_param_req = xcalloc(get_method_n_params(tp), sizeof(ia32_register_req_t *));
1210 /* we are done here when there are no parameters */
1214 /* temporary remember all proj arg x */
1215 projargs = xcalloc(n, sizeof(ir_node *));
1218 foreach_out_edge((const ir_node *)proj, edge) {
1219 succ = get_edge_src_irn(edge);
1220 assert(is_Proj(succ) && "non-Proj from a Proj_T (pn_Start_T_args).");
1221 projargs[i++] = succ;
1224 cc = get_method_calling_convention(tp);
1226 /* loop over all parameters and check whether its a int or float */
1227 for (i = 0; i < n; i++) {
1228 mode = get_irn_mode(projargs[i]);
1229 cur_pn = get_Proj_proj(projargs[i]);
1231 if (cc & cc_reg_param) {
1232 temp_req = ia32_get_RegParam_req(n, projargs, cur_pn, cc);
1239 /* passed in register */
1240 env->cg->reg_param_req[cur_pn] = temp_req;
1243 /* passed on stack */
1244 if (mode_is_float(mode))
1245 irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode);
1247 irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode);
1249 set_ia32_pncode(irn, cur_pn);
1251 /* kill the old "Proj Arg" and replace with the new stack param */
1252 exchange(projargs[i], irn);
1259 case pn_Start_P_frame_base:
1260 case pn_Start_X_initial_exec:
1262 case pn_Start_P_globals:
1263 case pn_Start_P_value_arg_base:
1266 assert(0 && "unsupported Proj(Start)");
1273 * Transform some Proj's (Proj_Proj, Proj_Start, Proj_Cmp, Proj_Cond, Proj_Call).
1274 * All others are ignored.
1276 * @param mod the debug module
1277 * @param block the block the new node should belong to
1278 * @param node the ir Proj node
1279 * @param mode mode of the Proj
1280 * @return The transformed node.
1282 static ir_node *gen_Proj(ia32_transform_env_t *env) {
1283 ir_node *new_node = NULL;
1284 ir_node *pred = get_Proj_pred(env->irn);
1286 if (env->mode == mode_M)
1289 if (get_irn_op(pred) == op_Start) {
1290 new_node = gen_Proj_Start(env, env->irn, pred);
1298 /*********************************************************
1301 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
1302 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
1303 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
1304 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
1306 *********************************************************/
1311 * Transforms the given firm node (and maybe some other related nodes)
1312 * into one or more assembler nodes.
1314 * @param node the firm node
1315 * @param env the debug module
1317 void ia32_transform_node(ir_node *node, void *env) {
1318 ia32_code_gen_t *cgenv = (ia32_code_gen_t *)env;
1319 opcode code = get_irn_opcode(node);
1320 ir_node *asm_node = NULL;
1321 ia32_transform_env_t tenv;
1326 tenv.arch_env = cgenv->arch_env;
1327 tenv.block = get_nodes_block(node);
1328 tenv.dbg = get_irn_dbg_info(node);
1329 tenv.irg = current_ir_graph;
1331 tenv.mod = cgenv->mod;
1332 tenv.mode = get_irn_mode(node);
1335 #define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
1336 #define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
1337 #define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break
1338 #define IGN(a) case iro_##a: break
1339 #define BAD(a) case iro_##a: goto bad
1341 DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1383 /* constant transformation happens earlier */
1405 if (get_irn_op(node) == get_op_Max()) {
1406 asm_node = gen_Max(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1408 else if (get_irn_op(node) == get_op_Min()) {
1409 asm_node = gen_Min(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1411 else if (get_irn_op(node) == get_op_Mulh()) {
1412 asm_node = gen_Mulh(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1416 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1421 exchange(node, asm_node);
1422 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1425 DB((tenv.mod, LEVEL_1, "ignored\n"));