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 #define SFP_SIGN "0x80000000"
28 #define DFP_SIGN "0x8000000000000000"
29 #define SFP_ABS "0x7FFFFFFF"
30 #define DFP_ABS "0x7FFFFFFFFFFFFFFF"
32 #define TP_SFP_SIGN "ia32_sfp_sign"
33 #define TP_DFP_SIGN "ia32_dfp_sign"
34 #define TP_SFP_ABS "ia32_sfp_abs"
35 #define TP_DFP_ABS "ia32_dfp_abs"
37 #define ENT_SFP_SIGN "IA32_SFP_SIGN"
38 #define ENT_DFP_SIGN "IA32_DFP_SIGN"
39 #define ENT_SFP_ABS "IA32_SFP_ABS"
40 #define ENT_DFP_ABS "IA32_DFP_ABS"
42 extern ir_op *get_op_Mulh(void);
44 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
45 ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode);
47 typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
48 ir_node *op, ir_node *mem, ir_mode *mode);
51 ia32_SSIGN, ia32_DSIGN, ia32_SABS, ia32_DABS
54 /* TEMPORARY WORKAROUND */
55 ir_node *be_new_NoReg(ir_graph *irg) {
59 /****************************************************************************************************
61 * | | | | / _| | | (_)
62 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
63 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
64 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
65 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
67 ****************************************************************************************************/
74 /* Compares two (entity, tarval) combinations */
75 static int cmp_tv_ent(const void *a, const void *b, size_t len) {
76 const struct tv_ent *e1 = a;
77 const struct tv_ent *e2 = b;
79 return !(e1->tv == e2->tv);
82 /* Generates an entity for a known FP const (used for FP Neg + Abs) */
83 static char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) {
84 static set *const_set = NULL;
96 const_set = new_set(cmp_tv_ent, 10);
101 tp_name = TP_SFP_SIGN;
102 ent_name = ENT_SFP_SIGN;
106 tp_name = TP_DFP_SIGN;
107 ent_name = ENT_DFP_SIGN;
111 tp_name = TP_SFP_ABS;
112 ent_name = ENT_SFP_ABS;
116 tp_name = TP_DFP_ABS;
117 ent_name = ENT_DFP_ABS;
123 key.tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
126 entry = set_insert(const_set, &key, sizeof(key), HASH_PTR(key.tv));
129 tp = new_type_primitive(new_id_from_str(tp_name), mode);
130 ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);
132 set_entity_ld_ident(ent, get_entity_ident(ent));
133 set_entity_visibility(ent, visibility_local);
134 set_entity_variability(ent, variability_constant);
135 set_entity_allocation(ent, allocation_static);
137 /* we create a new entity here: It's initialization must resist on the
139 rem = current_ir_graph;
140 current_ir_graph = get_const_code_irg();
141 cnst = new_Const(mode, key.tv);
142 current_ir_graph = rem;
144 set_atomic_ent_value(ent, cnst);
146 /* set the entry for hashmap */
155 #define is_cnst(op) (is_ia32_Const(op) || is_ia32_fConst(op))
157 /* determine if one operator is an Imm */
158 static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
160 return is_cnst(op1) ? op1 : (is_cnst(op2) ? op2 : NULL);
161 else return is_cnst(op2) ? op2 : NULL;
164 /* determine if one operator is not an Imm */
165 static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
166 return !is_cnst(op1) ? op1 : (!is_cnst(op2) ? op2 : NULL);
171 * Construct a standard binary operation, set AM and immediate if required.
173 * @param env The transformation environment
174 * @param op1 The first operand
175 * @param op2 The second operand
176 * @param func The node constructor function
177 * @return The constructed ia32 node.
179 static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
180 ir_node *new_op = NULL;
181 ir_mode *mode = env->mode;
182 dbg_info *dbg = env->dbg;
183 ir_graph *irg = env->irg;
184 ir_node *block = env->block;
185 firm_dbg_module_t *mod = env->mod;
186 ir_node *noreg = be_new_NoReg(irg);
187 ir_node *nomem = new_NoMem();
188 ir_node *expr_op, *imm_op;
191 /* check if it's an operation with immediate */
192 if (is_op_commutative(get_irn_op(env->irn))) {
193 imm_op = get_immediate_op(op1, op2);
194 expr_op = get_expr_op(op1, op2);
197 imm_op = get_immediate_op(NULL, op2);
198 expr_op = get_expr_op(op1, op2);
201 assert((expr_op || imm_op) && "invalid operands");
204 /* We have two consts here: not yet supported */
208 if (mode_is_float(mode)) {
209 /* floating point operations */
212 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
213 set_ia32_Immop_attr(new_op, imm_op);
214 set_ia32_am_support(new_op, ia32_am_None);
217 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
218 set_ia32_am_support(new_op, ia32_am_Source);
222 /* integer operations */
224 /* This is expr + const */
225 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
226 set_ia32_Immop_attr(new_op, imm_op);
229 set_ia32_am_support(new_op, ia32_am_Dest);
232 /* This is a normal operation */
233 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
236 set_ia32_am_support(new_op, ia32_am_Full);
240 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
246 * Construct a shift/rotate binary operation, sets AM and immediate if required.
248 * @param env The transformation environment
249 * @param op1 The first operand
250 * @param op2 The second operand
251 * @param func The node constructor function
252 * @return The constructed ia32 node.
254 static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
255 ir_node *new_op = NULL;
256 ir_mode *mode = env->mode;
257 dbg_info *dbg = env->dbg;
258 ir_graph *irg = env->irg;
259 ir_node *block = env->block;
260 firm_dbg_module_t *mod = env->mod;
261 ir_node *noreg = be_new_NoReg(irg);
262 ir_node *nomem = new_NoMem();
263 ir_node *expr_op, *imm_op;
266 assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
268 imm_op = get_immediate_op(NULL, op2);
269 expr_op = get_expr_op(op1, op2);
271 assert((expr_op || imm_op) && "invalid operands");
274 /* We have two consts here: not yet supported */
278 /* Limit imm_op within range imm8 */
280 tv = get_ia32_Immop_tarval(imm_op);
283 tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
290 /* integer operations */
292 /* This is shift/rot with const */
294 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
295 set_ia32_Immop_attr(new_op, imm_op);
298 /* This is a normal shift/rot */
299 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
303 set_ia32_am_support(new_op, ia32_am_Dest);
305 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
310 * Construct a standard unary operation, set AM and immediate if required.
312 * @param env The transformation environment
313 * @param op The operand
314 * @param func The node constructor function
315 * @return The constructed ia32 node.
317 static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) {
318 ir_node *new_op = NULL;
319 ir_mode *mode = env->mode;
320 dbg_info *dbg = env->dbg;
321 ir_graph *irg = env->irg;
322 ir_node *block = env->block;
323 ir_node *noreg = be_new_NoReg(irg);
324 ir_node *nomem = new_NoMem();
326 new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T);
328 if (mode_is_float(mode)) {
329 /* floating point operations don't support implicit store */
330 set_ia32_am_support(new_op, ia32_am_None);
333 set_ia32_am_support(new_op, ia32_am_Dest);
336 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
342 * Creates an ia32 Add with immediate.
344 * @param env The transformation environment
345 * @param expr_op The expression operator
346 * @param const_op The constant
347 * @return the created ia32 Add node
349 static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
350 ir_node *new_op = NULL;
351 tarval *tv = get_ia32_Immop_tarval(const_op);
352 firm_dbg_module_t *mod = env->mod;
353 dbg_info *dbg = env->dbg;
354 ir_mode *mode = env->mode;
355 ir_graph *irg = env->irg;
356 ir_node *block = env->block;
357 ir_node *noreg = be_new_NoReg(irg);
358 ir_node *nomem = new_NoMem();
360 tarval_classification_t class_tv, class_negtv;
362 /* const_op: tarval or SymConst? */
364 /* optimize tarvals */
365 class_tv = classify_tarval(tv);
366 class_negtv = classify_tarval(tarval_neg(tv));
368 if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
369 DB((env->mod, LEVEL_2, "Add(1) to Inc ... "));
370 new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
373 else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
374 DB((mod, LEVEL_2, "Add(-1) to Dec ... "));
375 new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
381 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
382 set_ia32_Immop_attr(new_op, const_op);
389 * Creates an ia32 Add.
391 * @param dbg firm node dbg
392 * @param block the block the new node should belong to
393 * @param op1 first operator
394 * @param op2 second operator
395 * @param mode node mode
396 * @return the created ia32 Add node
398 static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
399 ir_node *new_op = NULL;
400 dbg_info *dbg = env->dbg;
401 ir_mode *mode = env->mode;
402 ir_graph *irg = env->irg;
403 ir_node *block = env->block;
404 ir_node *noreg = be_new_NoReg(irg);
405 ir_node *nomem = new_NoMem();
406 ir_node *expr_op, *imm_op;
408 imm_op = get_immediate_op(op1, op2);
409 expr_op = get_expr_op(op1, op2);
411 assert((expr_op || imm_op) && "invalid operands");
413 if (mode_is_float(mode)) {
414 return gen_binop(env, op1, op2, new_rd_ia32_fAdd);
419 /* No expr_op means, that we have two const - one symconst and */
420 /* one tarval or another symconst - because this case is not */
421 /* covered by constant folding */
423 new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode_T);
424 add_ia32_am_offs(new_op, get_ia32_cnst(op1));
425 add_ia32_am_offs(new_op, get_ia32_cnst(op2));
428 set_ia32_am_support(new_op, ia32_am_Source);
429 set_ia32_op_type(new_op, ia32_AddrModeS);
430 set_ia32_am_flavour(new_op, ia32_am_O);
432 /* Lea doesn't need a Proj */
436 /* This is expr + const */
437 new_op = gen_imm_Add(env, expr_op, imm_op);
440 set_ia32_am_support(new_op, ia32_am_Dest);
443 /* This is a normal add */
444 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
447 set_ia32_am_support(new_op, ia32_am_Full);
451 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
457 * Creates an ia32 Mul.
459 * @param dbg firm node dbg
460 * @param block the block the new node should belong to
461 * @param op1 first operator
462 * @param op2 second operator
463 * @param mode node mode
464 * @return the created ia32 Mul node
466 ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
469 if (mode_is_float(env->mode)) {
470 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul);
473 new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
482 * Creates an ia32 Mulh.
483 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
484 * this result while Mul returns the lower 32 bit.
486 * @param env The transformation environment
487 * @param op1 The first operator
488 * @param op2 The second operator
489 * @return the created ia32 Mulh node
491 static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
492 ir_node *proj_EAX, *proj_EDX, *mulh;
495 assert(mode_is_float(env->mode) && "Mulh with float not supported");
496 proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh);
497 mulh = get_Proj_pred(proj_EAX);
498 proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX);
500 /* to be on the save side */
501 set_Proj_proj(proj_EAX, pn_EAX);
503 if (get_ia32_cnst(mulh)) {
504 /* Mulh with const cannot have AM */
505 set_ia32_am_support(mulh, ia32_am_None);
508 /* Mulh cannot have AM for destination */
509 set_ia32_am_support(mulh, ia32_am_Source);
515 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);
523 * Creates an ia32 And.
525 * @param env The transformation environment
526 * @param op1 The first operator
527 * @param op2 The second operator
528 * @return The created ia32 And node
530 static ir_node *gen_And(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
531 if (mode_is_float(env->mode)) {
532 return gen_binop(env, op1, op2, new_rd_ia32_fAnd);
535 return gen_binop(env, op1, op2, new_rd_ia32_And);
542 * Creates an ia32 Or.
544 * @param env The transformation environment
545 * @param op1 The first operator
546 * @param op2 The second operator
547 * @return The created ia32 Or node
549 static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
550 if (mode_is_float(env->mode)) {
551 return gen_binop(env, op1, op2, new_rd_ia32_fOr);
554 return gen_binop(env, op1, op2, new_rd_ia32_Or);
561 * Creates an ia32 Eor.
563 * @param env The transformation environment
564 * @param op1 The first operator
565 * @param op2 The second operator
566 * @return The created ia32 Eor node
568 static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
569 if (mode_is_float(env->mode)) {
570 return gen_binop(env, op1, op2, new_rd_ia32_fEor);
573 return gen_binop(env, op1, op2, new_rd_ia32_Eor);
580 * Creates an ia32 Max.
582 * @param env The transformation environment
583 * @param op1 The first operator
584 * @param op2 The second operator
585 * @return the created ia32 Max node
587 static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
590 if (mode_is_float(env->mode)) {
591 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax);
594 new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
595 set_ia32_am_support(new_op, ia32_am_None);
604 * Creates an ia32 Min.
606 * @param env The transformation environment
607 * @param op1 The first operator
608 * @param op2 The second operator
609 * @return the created ia32 Min node
611 static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
614 if (mode_is_float(env->mode)) {
615 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin);
618 new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
619 set_ia32_am_support(new_op, ia32_am_None);
628 * Creates an ia32 Sub with immediate.
630 * @param env The transformation environment
631 * @param op1 The first operator
632 * @param op2 The second operator
633 * @return The created ia32 Sub node
635 static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
636 ir_node *new_op = NULL;
637 tarval *tv = get_ia32_Immop_tarval(const_op);
638 firm_dbg_module_t *mod = env->mod;
639 dbg_info *dbg = env->dbg;
640 ir_mode *mode = env->mode;
641 ir_graph *irg = env->irg;
642 ir_node *block = env->block;
643 ir_node *noreg = be_new_NoReg(irg);
644 ir_node *nomem = new_NoMem();
646 tarval_classification_t class_tv, class_negtv;
648 /* const_op: tarval or SymConst? */
650 /* optimize tarvals */
651 class_tv = classify_tarval(tv);
652 class_negtv = classify_tarval(tarval_neg(tv));
654 if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
655 DB((mod, LEVEL_2, "Sub(1) to Dec ... "));
656 new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
659 else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
660 DB((mod, LEVEL_2, "Sub(-1) to Inc ... "));
661 new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
667 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
668 set_ia32_Immop_attr(new_op, const_op);
675 * Creates an ia32 Sub.
677 * @param env The transformation environment
678 * @param op1 The first operator
679 * @param op2 The second operator
680 * @return The created ia32 Sub node
682 static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
683 ir_node *new_op = NULL;
684 dbg_info *dbg = env->dbg;
685 ir_mode *mode = env->mode;
686 ir_graph *irg = env->irg;
687 ir_node *block = env->block;
688 ir_node *noreg = be_new_NoReg(irg);
689 ir_node *nomem = new_NoMem();
690 ir_node *expr_op, *imm_op;
692 imm_op = get_immediate_op(NULL, op2);
693 expr_op = get_expr_op(op1, op2);
695 assert((expr_op || imm_op) && "invalid operands");
697 if (mode_is_float(mode)) {
698 return gen_binop(env, op1, op2, new_rd_ia32_fSub);
703 /* No expr_op means, that we have two const - one symconst and */
704 /* one tarval or another symconst - because this case is not */
705 /* covered by constant folding */
707 new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode_T);
708 add_ia32_am_offs(new_op, get_ia32_cnst(op1));
709 sub_ia32_am_offs(new_op, get_ia32_cnst(op2));
712 set_ia32_am_support(new_op, ia32_am_Source);
713 set_ia32_op_type(new_op, ia32_AddrModeS);
714 set_ia32_am_flavour(new_op, ia32_am_O);
716 /* Lea doesn't need a Proj */
720 /* This is expr - const */
721 new_op = gen_imm_Sub(env, expr_op, imm_op);
724 set_ia32_am_support(new_op, ia32_am_Dest);
727 /* This is a normal sub */
728 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
731 set_ia32_am_support(new_op, ia32_am_Full);
735 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
741 * Generates an ia32 DivMod with additional infrastructure for the
742 * register allocator if needed.
744 * @param env The transformation environment
745 * @param dividend -no comment- :)
746 * @param divisor -no comment- :)
747 * @param dm_flav flavour_Div/Mod/DivMod
748 * @return The created ia32 DivMod node
750 static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
752 ir_node *edx_node, *cltd;
754 dbg_info *dbg = env->dbg;
755 ir_graph *irg = env->irg;
756 ir_node *block = env->block;
757 ir_mode *mode = env->mode;
758 ir_node *irn = env->irn;
763 mem = get_Div_mem(irn);
766 mem = get_Mod_mem(irn);
769 mem = get_DivMod_mem(irn);
775 if (mode_is_signed(mode)) {
776 /* in signed mode, we need to sign extend the dividend */
777 cltd = new_rd_ia32_Cdq(dbg, irg, block, dividend, mode_T);
778 dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX);
779 edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX);
782 edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
783 set_ia32_Const_type(edx_node, ia32_Const);
784 set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
787 res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode);
789 set_ia32_flavour(res, dm_flav);
790 set_ia32_n_res(res, 2);
792 /* Only one proj is used -> We must add a second proj and */
793 /* connect this one to a Keep node to eat up the second */
794 /* destroyed register. */
795 if (get_irn_n_edges(irn) == 1) {
796 proj = get_edge_src_irn(get_irn_out_edge_first(irn));
797 assert(is_Proj(proj) && "non-Proj to Div/Mod node");
799 if (get_Proj_proj(proj) == pn_DivMod_res_div) {
800 in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_mod);
803 in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
806 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
814 * Wrapper for generate_DivMod. Sets flavour_Mod.
816 static ir_node *gen_Mod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
817 return generate_DivMod(env, op1, op2, flavour_Mod);
823 * Wrapper for generate_DivMod. Sets flavour_Div.
825 static ir_node *gen_Div(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
826 return generate_DivMod(env, op1, op2, flavour_Div);
832 * Wrapper for generate_DivMod. Sets flavour_DivMod.
834 static ir_node *gen_DivMod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
835 return generate_DivMod(env, op1, op2, flavour_DivMod);
841 * Creates an ia32 floating Div.
843 * @param env The transformation environment
844 * @param op1 The first operator
845 * @param op2 The second operator
846 * @return The created ia32 fDiv node
848 static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
849 return gen_binop(env, op1, op2, new_rd_ia32_fDiv);
855 * Creates an ia32 Shl.
857 * @param env The transformation environment
858 * @param op1 The first operator
859 * @param op2 The second operator
860 * @return The created ia32 Shl node
862 static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
863 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shl);
869 * Creates an ia32 Shr.
871 * @param env The transformation environment
872 * @param op1 The first operator
873 * @param op2 The second operator
874 * @return The created ia32 Shr node
876 static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
877 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shr);
883 * Creates an ia32 Shrs.
885 * @param env The transformation environment
886 * @param op1 The first operator
887 * @param op2 The second operator
888 * @return The created ia32 Shrs node
890 static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
891 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shrs);
897 * Creates an ia32 RotL.
899 * @param env The transformation environment
900 * @param op1 The first operator
901 * @param op2 The second operator
902 * @return The created ia32 RotL node
904 static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
905 return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL);
911 * Creates an ia32 RotR.
912 * NOTE: There is no RotR with immediate because this would always be a RotL
913 * "imm-mode_size_bits" which can be pre-calculated.
915 * @param env The transformation environment
916 * @param op1 The first operator
917 * @param op2 The second operator
918 * @return The created ia32 RotR node
920 static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
921 return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR);
927 * Creates an ia32 RotR or RotL (depending on the found pattern).
929 * @param env The transformation environment
930 * @param op1 The first operator
931 * @param op2 The second operator
932 * @return The created ia32 RotL or RotR node
934 static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
935 ir_node *rotate = NULL;
937 /* Firm has only Rot (which is a RotL), so we are looking for a right (op2)
938 operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
939 that means we can create a RotR instead of an Add and a RotL */
942 ir_node *pred = get_Proj_pred(op2);
944 if (is_ia32_Add(pred)) {
945 ir_node *pred_pred = get_irn_n(pred, 2);
946 tarval *tv = get_ia32_Immop_tarval(pred);
947 long bits = get_mode_size_bits(env->mode);
949 if (is_Proj(pred_pred)) {
950 pred_pred = get_Proj_pred(pred_pred);
953 if (is_ia32_Minus(pred_pred) &&
954 tarval_is_long(tv) &&
955 get_tarval_long(tv) == bits)
957 DB((env->mod, LEVEL_1, "RotL into RotR ... "));
958 rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
965 rotate = gen_RotL(env, op1, op2);
974 * Transforms a Conv node.
976 * @param env The transformation environment
977 * @param op The operator
978 * @return The created ia32 Conv node
980 static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
981 return new_rd_ia32_Conv(env->dbg, env->irg, env->block, op, env->mode);
987 * Transforms a Minus node.
989 * @param env The transformation environment
990 * @param op The operator
991 * @return The created ia32 Minus node
993 static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
996 ir_node *noreg = be_new_NoReg(env->irg);
997 ir_node *nomem = new_rd_NoMem(env->irg);
1000 if (mode_is_float(env->mode)) {
1001 new_op = new_rd_ia32_fEor(env->dbg, env->irg, env->block, noreg, noreg, op, noreg, nomem, mode_T);
1003 size = get_mode_size_bits(env->mode);
1004 name = gen_fp_known_const(env->mode, size == 32 ? ia32_SSIGN : ia32_DSIGN);
1006 set_ia32_sc(new_op, name);
1008 new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
1011 new_op = gen_unop(env, op, new_rd_ia32_Minus);
1020 * Transforms a Not node.
1022 * @param env The transformation environment
1023 * @param op The operator
1024 * @return The created ia32 Not node
1026 static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
1029 if (mode_is_float(env->mode)) {
1033 new_op = gen_unop(env, op, new_rd_ia32_Not);
1042 * Transforms an Abs node.
1044 * @param env The transformation environment
1045 * @param op The operator
1046 * @return The created ia32 Abs node
1048 static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
1049 ir_node *res, *p_eax, *p_edx;
1050 dbg_info *dbg = env->dbg;
1051 ir_mode *mode = env->mode;
1052 ir_graph *irg = env->irg;
1053 ir_node *block = env->block;
1054 ir_node *noreg = be_new_NoReg(irg);
1055 ir_node *nomem = new_NoMem();
1059 if (mode_is_float(mode)) {
1060 res = new_rd_ia32_fAnd(dbg,irg, block, noreg, noreg, op, noreg, nomem, mode_T);
1062 size = get_mode_size_bits(mode);
1063 name = gen_fp_known_const(mode, size == 32 ? ia32_SABS : ia32_DABS);
1065 set_ia32_sc(res, name);
1067 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
1070 res = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T);
1071 p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
1072 p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
1073 res = new_rd_ia32_Eor(dbg, irg, block, noreg, noreg, p_eax, p_edx, nomem, mode_T);
1074 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
1075 res = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, res, p_edx, nomem, mode_T);
1076 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
1085 * Transforms a Load.
1087 * @param mod the debug module
1088 * @param block the block the new node should belong to
1089 * @param node the ir Load node
1090 * @param mode node mode
1091 * @return the created ia32 Load node
1093 static ir_node *gen_Load(ia32_transform_env_t *env) {
1094 ir_node *node = env->irn;
1095 ir_node *noreg = be_new_NoReg(env->irg);
1097 if (mode_is_float(env->mode)) {
1098 return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
1100 return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
1106 * Transforms a Store.
1108 * @param mod the debug module
1109 * @param block the block the new node should belong to
1110 * @param node the ir Store node
1111 * @param mode node mode
1112 * @return the created ia32 Store node
1114 ir_node *gen_Store(ia32_transform_env_t *env) {
1115 ir_node *node = env->irn;
1116 ir_node *noreg = be_new_NoReg(env->irg);
1118 if (mode_is_float(env->mode)) {
1119 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);
1121 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);
1127 * Transforms a Call and its arguments corresponding to the calling convention.
1129 * @param mod the debug module
1130 * @param block the block the new node should belong to
1131 * @param node the ir Call node
1132 * @param dummy mode doesn't matter
1133 * @return the created ia32 Call node
1135 static ir_node *gen_Call(ia32_transform_env_t *env) {
1137 const ia32_register_req_t **in_req;
1139 ir_node *new_call, *sync;
1140 int i, j, n_new_call_in, ignore = 0;
1142 dbg_info *dbg = env->dbg;
1143 ir_graph *irg = env->irg;
1144 ir_node *block = env->block;
1145 ir_node *call = env->irn;
1146 ir_node **stack_param = NULL;
1147 ir_node **param = get_Call_param_arr(call);
1148 ir_node *call_Mem = get_Call_mem(call);
1149 unsigned cc = get_method_calling_convention(get_Call_type(call));
1150 int n = get_Call_n_params(call);
1153 int n_res = get_method_n_ress(get_Call_type(call));
1155 assert(n_res <= 2 && "method with more than two results not supported");
1157 if (cc & cc_reg_param)
1158 biggest_n = ia32_get_n_regparam_class(n, param, &ignore, &ignore);
1160 /* remember: biggest_n = x means we can pass (x + 1) parameters in register */
1162 /* do we need to pass arguments on stack? */
1163 if (biggest_n + 1 < n)
1164 stack_param = xcalloc(n - biggest_n - 1, sizeof(ir_node *));
1166 /* we need at least one in, either for the stack params or the call_Mem */
1167 n_new_call_in = biggest_n + 2;
1169 /* the call has one IN for all stack parameter and one IN for each reg param */
1170 in = xcalloc(n_new_call_in, sizeof(ir_node *));
1171 in_req = xcalloc(n_new_call_in, sizeof(arch_register_req_t *));
1173 /* loop over all parameters and set the register requirements */
1174 for (i = 0; i <= biggest_n && (cc & cc_reg_param); i++) {
1175 in_req[i] = ia32_get_RegParam_req(n, param, i, cc);
1179 /* create remaining stack parameters */
1180 if (cc & cc_last_on_top) {
1181 for (i = stack_idx; i < n; i++) {
1182 /* pass it on stack */
1183 if (mode_is_float(get_irn_mode(param[i]))) {
1184 stack_param[i - stack_idx] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg,
1185 block, call_Mem, param[i], mode_M);
1188 stack_param[i - stack_idx] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg,
1189 block, call_Mem, param[i], mode_M);
1191 /* set the argument number for later lowering */
1192 set_ia32_pncode(stack_param[i - stack_idx], i - stack_idx);
1196 for (i = n - 1, j = 0; i >= stack_idx; i--, j++) {
1197 /* pass it on stack */
1198 if (mode_is_float(get_irn_mode(param[i]))) {
1199 stack_param[j] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg,
1200 block, call_Mem, param[i], mode_M);
1203 stack_param[j] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg,
1204 block, call_Mem, param[i], mode_M);
1206 /* set the argument number for later lowering */
1207 set_ia32_pncode(stack_param[j], j);
1212 sync = new_r_Sync(irg, block, n - biggest_n - 1, stack_param);
1213 in[n_new_call_in - 1] = sync;
1216 in[n_new_call_in - 1] = call_Mem;
1219 /* create the new node */
1220 new_call = new_rd_ia32_Call(dbg, irg, block, n_new_call_in, in);
1221 set_ia32_Immop_attr(new_call, get_Call_ptr(call));
1223 /* set register requirements for in and out */
1224 attr = get_ia32_attr(new_call);
1225 attr->in_req = in_req;
1227 set_ia32_n_res(new_call, n_res);
1230 attr->out_req = xcalloc(n_res, sizeof(ia32_register_req_t *));
1231 attr->slots = xcalloc(n_res, sizeof(arch_register_t *));
1234 /* two results only appear when a 64bit int result is broken up into two 32bit results */
1236 if (mode_is_float(get_type_mode(get_method_res_type(get_Call_type(call), 0))))
1237 attr->out_req[0] = &ia32_default_req_ia32_fp_xmm0;
1239 attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
1241 else if (n_res == 2) {
1242 attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
1243 attr->out_req[1] = &ia32_default_req_ia32_gp_edx;
1246 /* stack parameter has no OUT register */
1247 attr->in_req[n_new_call_in - 1] = &ia32_default_req_none;
1256 * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
1258 * @param env The transformation environment
1259 * @return The transformed node.
1261 static ir_node *gen_Cond(ia32_transform_env_t *env) {
1262 dbg_info *dbg = env->dbg;
1263 ir_graph *irg = env->irg;
1264 ir_node *block = env->block;
1265 ir_node *node = env->irn;
1266 ir_node *sel = get_Cond_selector(node);
1267 ir_mode *sel_mode = get_irn_mode(sel);
1268 ir_node *res = NULL;
1269 ir_node *pred = NULL;
1270 ir_node *noreg = be_new_NoReg(irg);
1271 ir_node *nomem = new_NoMem();
1272 ir_node *cmp_a, *cmp_b, *cnst, *expr;
1274 if (is_Proj(sel) && sel_mode == mode_b) {
1275 pred = get_Proj_pred(sel);
1277 /* get both compare operators */
1278 cmp_a = get_Cmp_left(pred);
1279 cmp_b = get_Cmp_right(pred);
1281 /* check if we can use a CondJmp with immediate */
1282 cnst = get_immediate_op(cmp_a, cmp_b);
1283 expr = get_expr_op(cmp_a, cmp_b);
1286 res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T);
1287 set_ia32_Immop_attr(res, cnst);
1290 res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T);
1293 set_ia32_pncode(res, get_Proj_proj(sel));
1296 res = new_rd_ia32_SwitchJmp(dbg, irg, block, noreg, noreg, sel, nomem, mode_T);
1297 set_ia32_pncode(res, get_Cond_defaultProj(node));
1306 * Transform the argument projs from a start node corresponding to the
1307 * calling convention.
1308 * It transforms "Proj Arg x -> ProjT -> Start <- ProjM" into
1309 * "RegParam x -> ProjT -> Start" OR
1310 * "StackParam x -> ProjM -> Start"
1311 * whether parameter is passed in register or on stack.
1313 * @param mod the debug module
1314 * @param block the block the nodes should belong to
1315 * @param proj the ProjT node which points to Start
1316 * @param start the Start node
1317 * @return Should be always NULL
1319 static ir_node *gen_Proj_Start(ia32_transform_env_t *env, ir_node *proj, ir_node *start) {
1321 const ia32_register_req_t *temp_req;
1322 const ir_edge_t *edge;
1323 ir_node *succ, *irn;
1328 ir_node *proj_M = get_irg_initial_mem(current_ir_graph);
1329 entity *irg_ent = get_irg_entity(current_ir_graph);
1330 ir_type *tp = get_entity_type(irg_ent);
1332 ir_graph *irg = env->irg;
1333 ir_node *block = env->block;
1335 assert(is_Method_type(tp) && "irg type is not a method");
1337 switch(get_Proj_proj(proj)) {
1338 case pn_Start_T_args:
1339 /* We cannot use get_method_n_params here as the function might
1340 be variadic or one argument is not used. */
1341 n = get_irn_n_edges(proj);
1343 /* Allocate memory for all non variadic parameters in advance to be on the save side */
1344 env->cg->reg_param_req = xcalloc(get_method_n_params(tp), sizeof(ia32_register_req_t *));
1346 /* we are done here when there are no parameters */
1350 /* temporary remember all proj arg x */
1351 projargs = xcalloc(n, sizeof(ir_node *));
1354 foreach_out_edge((const ir_node *)proj, edge) {
1355 succ = get_edge_src_irn(edge);
1356 assert(is_Proj(succ) && "non-Proj from a Proj_T (pn_Start_T_args).");
1357 projargs[i++] = succ;
1360 cc = get_method_calling_convention(tp);
1362 /* loop over all parameters and check whether its a int or float */
1363 for (i = 0; i < n; i++) {
1364 mode = get_irn_mode(projargs[i]);
1365 cur_pn = get_Proj_proj(projargs[i]);
1367 if (cc & cc_reg_param) {
1368 temp_req = ia32_get_RegParam_req(n, projargs, cur_pn, cc);
1375 /* passed in register */
1376 env->cg->reg_param_req[cur_pn] = temp_req;
1379 /* passed on stack */
1380 if (mode_is_float(mode))
1381 irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode);
1383 irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode);
1385 set_ia32_pncode(irn, cur_pn);
1387 /* kill the old "Proj Arg" and replace with the new stack param */
1388 exchange(projargs[i], irn);
1395 case pn_Start_P_frame_base:
1396 case pn_Start_X_initial_exec:
1398 case pn_Start_P_globals:
1399 case pn_Start_P_value_arg_base:
1402 assert(0 && "unsupported Proj(Start)");
1410 * Transform some Proj's (Proj_Proj, Proj_Start, Proj_Cmp, Proj_Cond, Proj_Call).
1411 * All others are ignored.
1413 * @param mod the debug module
1414 * @param block the block the new node should belong to
1415 * @param node the ir Proj node
1416 * @param mode mode of the Proj
1417 * @return The transformed node.
1419 static ir_node *gen_Proj(ia32_transform_env_t *env) {
1420 ir_node *new_node = NULL;
1421 ir_node *pred = get_Proj_pred(env->irn);
1423 if (env->mode == mode_M)
1426 if (get_irn_op(pred) == op_Start) {
1427 new_node = gen_Proj_Start(env, env->irn, pred);
1435 /*********************************************************
1438 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
1439 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
1440 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
1441 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
1443 *********************************************************/
1448 * Transforms the given firm node (and maybe some other related nodes)
1449 * into one or more assembler nodes.
1451 * @param node the firm node
1452 * @param env the debug module
1454 void ia32_transform_node(ir_node *node, void *env) {
1455 ia32_code_gen_t *cgenv = (ia32_code_gen_t *)env;
1456 opcode code = get_irn_opcode(node);
1457 ir_node *asm_node = NULL;
1458 ia32_transform_env_t tenv;
1463 tenv.arch_env = cgenv->arch_env;
1464 tenv.block = get_nodes_block(node);
1465 tenv.dbg = get_irn_dbg_info(node);
1466 tenv.irg = current_ir_graph;
1468 tenv.mod = cgenv->mod;
1469 tenv.mode = get_irn_mode(node);
1472 #define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
1473 #define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
1474 #define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break
1475 #define IGN(a) case iro_##a: break
1476 #define BAD(a) case iro_##a: goto bad
1478 DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1520 /* constant transformation happens earlier */
1542 if (get_irn_op(node) == get_op_Max()) {
1543 asm_node = gen_Max(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1545 else if (get_irn_op(node) == get_op_Min()) {
1546 asm_node = gen_Min(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1548 else if (get_irn_op(node) == get_op_Mulh()) {
1549 asm_node = gen_Mulh(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1553 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1558 exchange(node, asm_node);
1559 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1562 DB((tenv.mod, LEVEL_1, "ignored\n"));