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"
24 #include "gen_ia32_regalloc_if.h"
26 #define SFP_SIGN "0x80000000"
27 #define DFP_SIGN "0x8000000000000000"
28 #define SFP_ABS "0x7FFFFFFF"
29 #define DFP_ABS "0x7FFFFFFFFFFFFFFF"
31 #define TP_SFP_SIGN "ia32_sfp_sign"
32 #define TP_DFP_SIGN "ia32_dfp_sign"
33 #define TP_SFP_ABS "ia32_sfp_abs"
34 #define TP_DFP_ABS "ia32_dfp_abs"
36 #define ENT_SFP_SIGN "IA32_SFP_SIGN"
37 #define ENT_DFP_SIGN "IA32_DFP_SIGN"
38 #define ENT_SFP_ABS "IA32_SFP_ABS"
39 #define ENT_DFP_ABS "IA32_DFP_ABS"
41 extern ir_op *get_op_Mulh(void);
43 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
44 ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode);
46 typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
47 ir_node *op, ir_node *mem, ir_mode *mode);
50 ia32_SSIGN, ia32_DSIGN, ia32_SABS, ia32_DABS
53 /****************************************************************************************************
55 * | | | | / _| | | (_)
56 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
57 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
58 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
59 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
61 ****************************************************************************************************/
68 /* Compares two (entity, tarval) combinations */
69 static int cmp_tv_ent(const void *a, const void *b, size_t len) {
70 const struct tv_ent *e1 = a;
71 const struct tv_ent *e2 = b;
73 return !(e1->tv == e2->tv);
76 /* Generates an entity for a known FP const (used for FP Neg + Abs) */
77 static char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) {
78 static set *const_set = NULL;
90 const_set = new_set(cmp_tv_ent, 10);
95 tp_name = TP_SFP_SIGN;
96 ent_name = ENT_SFP_SIGN;
100 tp_name = TP_DFP_SIGN;
101 ent_name = ENT_DFP_SIGN;
105 tp_name = TP_SFP_ABS;
106 ent_name = ENT_SFP_ABS;
110 tp_name = TP_DFP_ABS;
111 ent_name = ENT_DFP_ABS;
117 key.tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
120 entry = set_insert(const_set, &key, sizeof(key), HASH_PTR(key.tv));
123 tp = new_type_primitive(new_id_from_str(tp_name), mode);
124 ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);
126 set_entity_ld_ident(ent, get_entity_ident(ent));
127 set_entity_visibility(ent, visibility_local);
128 set_entity_variability(ent, variability_constant);
129 set_entity_allocation(ent, allocation_static);
131 /* we create a new entity here: It's initialization must resist on the
133 rem = current_ir_graph;
134 current_ir_graph = get_const_code_irg();
135 cnst = new_Const(mode, key.tv);
136 current_ir_graph = rem;
138 set_atomic_ent_value(ent, cnst);
140 /* set the entry for hashmap */
149 /* determine if one operator is an Imm */
150 static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
152 return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL);
153 else return is_ia32_Cnst(op2) ? op2 : NULL;
156 /* determine if one operator is not an Imm */
157 static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
158 return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL);
163 * Construct a standard binary operation, set AM and immediate if required.
165 * @param env The transformation environment
166 * @param op1 The first operand
167 * @param op2 The second operand
168 * @param func The node constructor function
169 * @return The constructed ia32 node.
171 static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
172 ir_node *new_op = NULL;
173 ir_mode *mode = env->mode;
174 dbg_info *dbg = env->dbg;
175 ir_graph *irg = env->irg;
176 ir_node *block = env->block;
177 firm_dbg_module_t *mod = env->mod;
178 ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg);
179 ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg);
180 ir_node *nomem = new_NoMem();
181 ir_node *expr_op, *imm_op;
184 /* check if it's an operation with immediate */
185 if (is_op_commutative(get_irn_op(env->irn))) {
186 imm_op = get_immediate_op(op1, op2);
187 expr_op = get_expr_op(op1, op2);
190 imm_op = get_immediate_op(NULL, op2);
191 expr_op = get_expr_op(op1, op2);
194 assert((expr_op || imm_op) && "invalid operands");
197 /* We have two consts here: not yet supported */
201 if (mode_is_float(mode)) {
202 /* floating point operations */
204 new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_fp, nomem, mode_T);
205 set_ia32_Immop_attr(new_op, imm_op);
206 set_ia32_am_support(new_op, ia32_am_None);
209 new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode_T);
210 set_ia32_am_support(new_op, ia32_am_Source);
214 /* integer operations */
216 /* This is expr + const */
217 new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_gp, nomem, mode_T);
218 set_ia32_Immop_attr(new_op, imm_op);
221 set_ia32_am_support(new_op, ia32_am_Dest);
224 /* This is a normal operation */
225 new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode_T);
228 set_ia32_am_support(new_op, ia32_am_Full);
232 if (is_op_commutative(get_irn_op(env->irn))) {
233 set_ia32_commutative(new_op);
236 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
242 * Construct a shift/rotate binary operation, sets AM and immediate if required.
244 * @param env The transformation environment
245 * @param op1 The first operand
246 * @param op2 The second operand
247 * @param func The node constructor function
248 * @return The constructed ia32 node.
250 static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
251 ir_node *new_op = NULL;
252 ir_mode *mode = env->mode;
253 dbg_info *dbg = env->dbg;
254 ir_graph *irg = env->irg;
255 ir_node *block = env->block;
256 firm_dbg_module_t *mod = env->mod;
257 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
258 ir_node *nomem = new_NoMem();
259 ir_node *expr_op, *imm_op;
262 assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
264 imm_op = get_immediate_op(NULL, op2);
265 expr_op = get_expr_op(op1, op2);
267 assert((expr_op || imm_op) && "invalid operands");
270 /* We have two consts here: not yet supported */
274 /* Limit imm_op within range imm8 */
276 tv = get_ia32_Immop_tarval(imm_op);
279 tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
286 /* integer operations */
288 /* This is shift/rot with const */
290 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
291 set_ia32_Immop_attr(new_op, imm_op);
294 /* This is a normal shift/rot */
295 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
299 set_ia32_am_support(new_op, ia32_am_Dest);
301 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
306 * Construct a standard unary operation, set AM and immediate if required.
308 * @param env The transformation environment
309 * @param op The operand
310 * @param func The node constructor function
311 * @return The constructed ia32 node.
313 static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) {
314 ir_node *new_op = NULL;
315 ir_mode *mode = env->mode;
316 dbg_info *dbg = env->dbg;
317 ir_graph *irg = env->irg;
318 ir_node *block = env->block;
319 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
320 ir_node *nomem = new_NoMem();
322 new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T);
324 if (mode_is_float(mode)) {
325 /* floating point operations don't support implicit store */
326 set_ia32_am_support(new_op, ia32_am_None);
329 set_ia32_am_support(new_op, ia32_am_Dest);
332 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
338 * Creates an ia32 Add with immediate.
340 * @param env The transformation environment
341 * @param expr_op The expression operator
342 * @param const_op The constant
343 * @return the created ia32 Add node
345 static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
346 ir_node *new_op = NULL;
347 tarval *tv = get_ia32_Immop_tarval(const_op);
348 firm_dbg_module_t *mod = env->mod;
349 dbg_info *dbg = env->dbg;
350 ir_mode *mode = env->mode;
351 ir_graph *irg = env->irg;
352 ir_node *block = env->block;
353 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
354 ir_node *nomem = new_NoMem();
356 tarval_classification_t class_tv, class_negtv;
358 /* const_op: tarval or SymConst? */
360 /* optimize tarvals */
361 class_tv = classify_tarval(tv);
362 class_negtv = classify_tarval(tarval_neg(tv));
364 if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
365 DB((env->mod, LEVEL_2, "Add(1) to Inc ... "));
366 new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
369 else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
370 DB((mod, LEVEL_2, "Add(-1) to Dec ... "));
371 new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
377 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
378 set_ia32_Immop_attr(new_op, const_op);
385 * Creates an ia32 Add.
387 * @param dbg firm node dbg
388 * @param block the block the new node should belong to
389 * @param op1 first operator
390 * @param op2 second operator
391 * @param mode node mode
392 * @return the created ia32 Add node
394 static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
395 ir_node *new_op = NULL;
396 dbg_info *dbg = env->dbg;
397 ir_mode *mode = env->mode;
398 ir_graph *irg = env->irg;
399 ir_node *block = env->block;
400 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
401 ir_node *nomem = new_NoMem();
402 ir_node *expr_op, *imm_op;
404 imm_op = get_immediate_op(op1, op2);
405 expr_op = get_expr_op(op1, op2);
407 assert((expr_op || imm_op) && "invalid operands");
409 if (mode_is_float(mode)) {
410 return gen_binop(env, op1, op2, new_rd_ia32_fAdd);
415 /* No expr_op means, that we have two const - one symconst and */
416 /* one tarval or another symconst - because this case is not */
417 /* covered by constant folding */
419 new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
420 add_ia32_am_offs(new_op, get_ia32_cnst(op1));
421 add_ia32_am_offs(new_op, get_ia32_cnst(op2));
424 set_ia32_am_support(new_op, ia32_am_Source);
425 set_ia32_op_type(new_op, ia32_AddrModeS);
426 set_ia32_am_flavour(new_op, ia32_am_O);
428 /* Lea doesn't need a Proj */
432 /* This is expr + const */
433 new_op = gen_imm_Add(env, expr_op, imm_op);
436 set_ia32_am_support(new_op, ia32_am_Dest);
439 /* This is a normal add */
440 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
443 set_ia32_am_support(new_op, ia32_am_Full);
447 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
453 * Creates an ia32 Mul.
455 * @param dbg firm node dbg
456 * @param block the block the new node should belong to
457 * @param op1 first operator
458 * @param op2 second operator
459 * @param mode node mode
460 * @return the created ia32 Mul node
462 static ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
465 if (mode_is_float(env->mode)) {
466 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul);
469 new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
478 * Creates an ia32 Mulh.
479 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
480 * this result while Mul returns the lower 32 bit.
482 * @param env The transformation environment
483 * @param op1 The first operator
484 * @param op2 The second operator
485 * @return the created ia32 Mulh node
487 static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
488 ir_node *proj_EAX, *proj_EDX, *mulh;
491 assert(mode_is_float(env->mode) && "Mulh with float not supported");
492 proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh);
493 mulh = get_Proj_pred(proj_EAX);
494 proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX);
496 /* to be on the save side */
497 set_Proj_proj(proj_EAX, pn_EAX);
499 if (get_ia32_cnst(mulh)) {
500 /* Mulh with const cannot have AM */
501 set_ia32_am_support(mulh, ia32_am_None);
504 /* Mulh cannot have AM for destination */
505 set_ia32_am_support(mulh, ia32_am_Source);
511 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);
519 * Creates an ia32 And.
521 * @param env The transformation environment
522 * @param op1 The first operator
523 * @param op2 The second operator
524 * @return The created ia32 And node
526 static ir_node *gen_And(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
527 if (mode_is_float(env->mode)) {
528 return gen_binop(env, op1, op2, new_rd_ia32_fAnd);
531 return gen_binop(env, op1, op2, new_rd_ia32_And);
538 * Creates an ia32 Or.
540 * @param env The transformation environment
541 * @param op1 The first operator
542 * @param op2 The second operator
543 * @return The created ia32 Or node
545 static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
546 if (mode_is_float(env->mode)) {
547 return gen_binop(env, op1, op2, new_rd_ia32_fOr);
550 return gen_binop(env, op1, op2, new_rd_ia32_Or);
557 * Creates an ia32 Eor.
559 * @param env The transformation environment
560 * @param op1 The first operator
561 * @param op2 The second operator
562 * @return The created ia32 Eor node
564 static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
565 if (mode_is_float(env->mode)) {
566 return gen_binop(env, op1, op2, new_rd_ia32_fEor);
569 return gen_binop(env, op1, op2, new_rd_ia32_Eor);
576 * Creates an ia32 Max.
578 * @param env The transformation environment
579 * @param op1 The first operator
580 * @param op2 The second operator
581 * @return the created ia32 Max node
583 static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
586 if (mode_is_float(env->mode)) {
587 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax);
590 new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
591 set_ia32_am_support(new_op, ia32_am_None);
600 * Creates an ia32 Min.
602 * @param env The transformation environment
603 * @param op1 The first operator
604 * @param op2 The second operator
605 * @return the created ia32 Min node
607 static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
610 if (mode_is_float(env->mode)) {
611 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin);
614 new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
615 set_ia32_am_support(new_op, ia32_am_None);
624 * Creates an ia32 Sub with immediate.
626 * @param env The transformation environment
627 * @param op1 The first operator
628 * @param op2 The second operator
629 * @return The created ia32 Sub node
631 static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
632 ir_node *new_op = NULL;
633 tarval *tv = get_ia32_Immop_tarval(const_op);
634 firm_dbg_module_t *mod = env->mod;
635 dbg_info *dbg = env->dbg;
636 ir_mode *mode = env->mode;
637 ir_graph *irg = env->irg;
638 ir_node *block = env->block;
639 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
640 ir_node *nomem = new_NoMem();
642 tarval_classification_t class_tv, class_negtv;
644 /* const_op: tarval or SymConst? */
646 /* optimize tarvals */
647 class_tv = classify_tarval(tv);
648 class_negtv = classify_tarval(tarval_neg(tv));
650 if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
651 DB((mod, LEVEL_2, "Sub(1) to Dec ... "));
652 new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
655 else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
656 DB((mod, LEVEL_2, "Sub(-1) to Inc ... "));
657 new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
663 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
664 set_ia32_Immop_attr(new_op, const_op);
671 * Creates an ia32 Sub.
673 * @param env The transformation environment
674 * @param op1 The first operator
675 * @param op2 The second operator
676 * @return The created ia32 Sub node
678 static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
679 ir_node *new_op = NULL;
680 dbg_info *dbg = env->dbg;
681 ir_mode *mode = env->mode;
682 ir_graph *irg = env->irg;
683 ir_node *block = env->block;
684 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
685 ir_node *nomem = new_NoMem();
686 ir_node *expr_op, *imm_op;
688 imm_op = get_immediate_op(NULL, op2);
689 expr_op = get_expr_op(op1, op2);
691 assert((expr_op || imm_op) && "invalid operands");
693 if (mode_is_float(mode)) {
694 return gen_binop(env, op1, op2, new_rd_ia32_fSub);
699 /* No expr_op means, that we have two const - one symconst and */
700 /* one tarval or another symconst - because this case is not */
701 /* covered by constant folding */
703 new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
704 add_ia32_am_offs(new_op, get_ia32_cnst(op1));
705 sub_ia32_am_offs(new_op, get_ia32_cnst(op2));
708 set_ia32_am_support(new_op, ia32_am_Source);
709 set_ia32_op_type(new_op, ia32_AddrModeS);
710 set_ia32_am_flavour(new_op, ia32_am_O);
712 /* Lea doesn't need a Proj */
716 /* This is expr - const */
717 new_op = gen_imm_Sub(env, expr_op, imm_op);
720 set_ia32_am_support(new_op, ia32_am_Dest);
723 /* This is a normal sub */
724 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
727 set_ia32_am_support(new_op, ia32_am_Full);
731 return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
737 * Generates an ia32 DivMod with additional infrastructure for the
738 * register allocator if needed.
740 * @param env The transformation environment
741 * @param dividend -no comment- :)
742 * @param divisor -no comment- :)
743 * @param dm_flav flavour_Div/Mod/DivMod
744 * @return The created ia32 DivMod node
746 static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
748 ir_node *edx_node, *cltd;
750 dbg_info *dbg = env->dbg;
751 ir_graph *irg = env->irg;
752 ir_node *block = env->block;
753 ir_mode *mode = env->mode;
754 ir_node *irn = env->irn;
759 mem = get_Div_mem(irn);
762 mem = get_Mod_mem(irn);
765 mem = get_DivMod_mem(irn);
771 if (mode_is_signed(mode)) {
772 /* in signed mode, we need to sign extend the dividend */
773 cltd = new_rd_ia32_Cdq(dbg, irg, block, dividend, mode_T);
774 dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX);
775 edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX);
778 edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
779 set_ia32_Const_type(edx_node, ia32_Const);
780 set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
783 res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode);
785 set_ia32_flavour(res, dm_flav);
786 set_ia32_n_res(res, 2);
788 /* Only one proj is used -> We must add a second proj and */
789 /* connect this one to a Keep node to eat up the second */
790 /* destroyed register. */
791 if (get_irn_n_edges(irn) == 1) {
792 proj = get_edge_src_irn(get_irn_out_edge_first(irn));
793 assert(is_Proj(proj) && "non-Proj to Div/Mod node");
795 if (get_Proj_proj(proj) == pn_DivMod_res_div) {
796 in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_mod);
799 in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
802 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
810 * Wrapper for generate_DivMod. Sets flavour_Mod.
812 static ir_node *gen_Mod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
813 return generate_DivMod(env, op1, op2, flavour_Mod);
819 * Wrapper for generate_DivMod. Sets flavour_Div.
821 static ir_node *gen_Div(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
822 return generate_DivMod(env, op1, op2, flavour_Div);
828 * Wrapper for generate_DivMod. Sets flavour_DivMod.
830 static ir_node *gen_DivMod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
831 return generate_DivMod(env, op1, op2, flavour_DivMod);
837 * Creates an ia32 floating Div.
839 * @param env The transformation environment
840 * @param op1 The first operator
841 * @param op2 The second operator
842 * @return The created ia32 fDiv node
844 static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
845 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
846 ir_node *nomem = new_rd_NoMem(env->irg);
849 new_op = new_rd_ia32_fDiv(env->dbg, env->irg, env->block, noreg, noreg, op1, op2, nomem, env->mode);
850 set_ia32_am_support(new_op, ia32_am_Source);
858 * Creates an ia32 Shl.
860 * @param env The transformation environment
861 * @param op1 The first operator
862 * @param op2 The second operator
863 * @return The created ia32 Shl node
865 static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
866 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shl);
872 * Creates an ia32 Shr.
874 * @param env The transformation environment
875 * @param op1 The first operator
876 * @param op2 The second operator
877 * @return The created ia32 Shr node
879 static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
880 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shr);
886 * Creates an ia32 Shrs.
888 * @param env The transformation environment
889 * @param op1 The first operator
890 * @param op2 The second operator
891 * @return The created ia32 Shrs node
893 static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
894 return gen_shift_binop(env, op1, op2, new_rd_ia32_Shrs);
900 * Creates an ia32 RotL.
902 * @param env The transformation environment
903 * @param op1 The first operator
904 * @param op2 The second operator
905 * @return The created ia32 RotL node
907 static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
908 return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL);
914 * Creates an ia32 RotR.
915 * NOTE: There is no RotR with immediate because this would always be a RotL
916 * "imm-mode_size_bits" which can be pre-calculated.
918 * @param env The transformation environment
919 * @param op1 The first operator
920 * @param op2 The second operator
921 * @return The created ia32 RotR node
923 static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
924 return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR);
930 * Creates an ia32 RotR or RotL (depending on the found pattern).
932 * @param env The transformation environment
933 * @param op1 The first operator
934 * @param op2 The second operator
935 * @return The created ia32 RotL or RotR node
937 static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
938 ir_node *rotate = NULL;
940 /* Firm has only Rot (which is a RotL), so we are looking for a right (op2)
941 operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
942 that means we can create a RotR instead of an Add and a RotL */
945 ir_node *pred = get_Proj_pred(op2);
947 if (is_ia32_Add(pred)) {
948 ir_node *pred_pred = get_irn_n(pred, 2);
949 tarval *tv = get_ia32_Immop_tarval(pred);
950 long bits = get_mode_size_bits(env->mode);
952 if (is_Proj(pred_pred)) {
953 pred_pred = get_Proj_pred(pred_pred);
956 if (is_ia32_Minus(pred_pred) &&
957 tarval_is_long(tv) &&
958 get_tarval_long(tv) == bits)
960 DB((env->mod, LEVEL_1, "RotL into RotR ... "));
961 rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
968 rotate = gen_RotL(env, op1, op2);
977 * Transforms a Conv node.
979 * @param env The transformation environment
980 * @param op The operator
981 * @return The created ia32 Conv node
983 static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
984 return new_rd_ia32_Conv(env->dbg, env->irg, env->block, op, env->mode);
990 * Transforms a Minus node.
992 * @param env The transformation environment
993 * @param op The operator
994 * @return The created ia32 Minus node
996 static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
999 ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg);
1000 ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg);
1001 ir_node *nomem = new_rd_NoMem(env->irg);
1004 if (mode_is_float(env->mode)) {
1005 new_op = new_rd_ia32_fEor(env->dbg, env->irg, env->block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T);
1007 size = get_mode_size_bits(env->mode);
1008 name = gen_fp_known_const(env->mode, size == 32 ? ia32_SSIGN : ia32_DSIGN);
1010 set_ia32_sc(new_op, name);
1012 new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
1015 new_op = gen_unop(env, op, new_rd_ia32_Minus);
1024 * Transforms a Not node.
1026 * @param env The transformation environment
1027 * @param op The operator
1028 * @return The created ia32 Not node
1030 static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
1033 if (mode_is_float(env->mode)) {
1037 new_op = gen_unop(env, op, new_rd_ia32_Not);
1046 * Transforms an Abs node.
1048 * @param env The transformation environment
1049 * @param op The operator
1050 * @return The created ia32 Abs node
1052 static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
1053 ir_node *res, *p_eax, *p_edx;
1054 dbg_info *dbg = env->dbg;
1055 ir_mode *mode = env->mode;
1056 ir_graph *irg = env->irg;
1057 ir_node *block = env->block;
1058 ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg);
1059 ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg);
1060 ir_node *nomem = new_NoMem();
1064 if (mode_is_float(mode)) {
1065 res = new_rd_ia32_fAnd(dbg,irg, block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T);
1067 size = get_mode_size_bits(mode);
1068 name = gen_fp_known_const(mode, size == 32 ? ia32_SABS : ia32_DABS);
1070 set_ia32_sc(res, name);
1072 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
1075 res = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T);
1076 p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
1077 p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
1078 res = new_rd_ia32_Eor(dbg, irg, block, noreg_gp, noreg_gp, p_eax, p_edx, nomem, mode_T);
1079 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
1080 res = new_rd_ia32_Sub(dbg, irg, block, noreg_gp, noreg_gp, res, p_edx, nomem, mode_T);
1081 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
1090 * Transforms a Load.
1092 * @param mod the debug module
1093 * @param block the block the new node should belong to
1094 * @param node the ir Load node
1095 * @param mode node mode
1096 * @return the created ia32 Load node
1098 static ir_node *gen_Load(ia32_transform_env_t *env) {
1099 ir_node *node = env->irn;
1100 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1103 if (mode_is_float(env->mode)) {
1104 new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
1107 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
1110 set_ia32_am_support(new_op, ia32_am_Source);
1111 set_ia32_op_type(new_op, ia32_AddrModeS);
1112 set_ia32_am_flavour(new_op, ia32_B);
1113 set_ia32_ls_mode(new_op, get_Load_mode(node));
1121 * Transforms a Store.
1123 * @param mod the debug module
1124 * @param block the block the new node should belong to
1125 * @param node the ir Store node
1126 * @param mode node mode
1127 * @return the created ia32 Store node
1129 static ir_node *gen_Store(ia32_transform_env_t *env) {
1130 ir_node *node = env->irn;
1131 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1132 ir_node *val = get_Store_value(node);
1133 ir_node *ptr = get_Store_ptr(node);
1134 ir_node *mem = get_Store_mem(node);
1135 ir_node *sval = val;
1138 /* in case of storing a const -> make it an attribute */
1139 if (is_ia32_Cnst(val)) {
1143 if (mode_is_float(env->mode)) {
1144 new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
1147 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
1150 /* stored const is an attribute (saves a register) */
1151 if (is_ia32_Cnst(val)) {
1152 set_ia32_Immop_attr(new_op, val);
1155 set_ia32_am_support(new_op, ia32_am_Dest);
1156 set_ia32_op_type(new_op, ia32_AddrModeD);
1157 set_ia32_am_flavour(new_op, ia32_B);
1158 set_ia32_ls_mode(new_op, get_irn_mode(val));
1165 * Transforms a Call and its arguments corresponding to the calling convention.
1167 * @param env The transformation environment
1168 * @return The created ia32 Call node
1170 static ir_node *gen_Call(ia32_transform_env_t *env) {
1176 * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
1178 * @param env The transformation environment
1179 * @return The transformed node.
1181 static ir_node *gen_Cond(ia32_transform_env_t *env) {
1182 dbg_info *dbg = env->dbg;
1183 ir_graph *irg = env->irg;
1184 ir_node *block = env->block;
1185 ir_node *node = env->irn;
1186 ir_node *sel = get_Cond_selector(node);
1187 ir_mode *sel_mode = get_irn_mode(sel);
1188 ir_node *res = NULL;
1189 ir_node *pred = NULL;
1190 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1191 ir_node *nomem = new_NoMem();
1192 ir_node *cmp_a, *cmp_b, *cnst, *expr;
1194 if (is_Proj(sel) && sel_mode == mode_b) {
1195 pred = get_Proj_pred(sel);
1197 /* get both compare operators */
1198 cmp_a = get_Cmp_left(pred);
1199 cmp_b = get_Cmp_right(pred);
1201 /* check if we can use a CondJmp with immediate */
1202 cnst = get_immediate_op(cmp_a, cmp_b);
1203 expr = get_expr_op(cmp_a, cmp_b);
1206 res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T);
1207 set_ia32_Immop_attr(res, cnst);
1210 res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T);
1213 set_ia32_pncode(res, get_Proj_proj(sel));
1216 res = new_rd_ia32_SwitchJmp(dbg, irg, block, noreg, noreg, sel, nomem, mode_T);
1217 set_ia32_pncode(res, get_Cond_defaultProj(node));
1226 * Transforms a CopyB node.
1228 * @param env The transformation environment
1229 * @return The transformed node.
1231 static ir_node *gen_CopyB(ia32_transform_env_t *env) {
1232 ir_node *res = NULL;
1233 dbg_info *dbg = env->dbg;
1234 ir_graph *irg = env->irg;
1235 ir_mode *mode = env->mode;
1236 ir_node *block = env->block;
1237 ir_node *node = env->irn;
1238 ir_node *src = get_CopyB_src(node);
1239 ir_node *dst = get_CopyB_dst(node);
1240 ir_node *mem = get_CopyB_mem(node);
1241 ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1242 int size = get_type_size_bytes(get_CopyB_type(node));
1245 /* If we have to copy more than 16 bytes, we use REP MOVSx and */
1246 /* then we need the size explicitly in ECX. */
1248 rem = size & 0x3; /* size % 4 */
1251 res = new_rd_ia32_Const(dbg, irg, block, mode_Is);
1252 set_ia32_op_type(res, ia32_Const);
1253 set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
1255 res = new_rd_ia32_CopyB(dbg, irg, block, dst, src, res, mem, mode);
1256 set_ia32_Immop_tarval(res, new_tarval_from_long(rem, mode_Is));
1259 res = new_rd_ia32_CopyB_i(dbg, irg, block, dst, src, mem, mode);
1260 set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
1269 * Transforms a Mux node into CMov.
1271 * @param env The transformation environment
1272 * @return The transformed node.
1274 static ir_node *gen_Mux(ia32_transform_env_t *env) {
1275 ir_node *node = env->irn;
1277 return new_rd_ia32_CMov(env->dbg, env->irg, env->block,
1278 get_Mux_sel(node), get_Mux_false(node), get_Mux_true(node), env->mode);
1283 /*********************************************************
1286 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
1287 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
1288 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
1289 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
1291 *********************************************************/
1296 * Transforms the given firm node (and maybe some other related nodes)
1297 * into one or more assembler nodes.
1299 * @param node the firm node
1300 * @param env the debug module
1302 void ia32_transform_node(ir_node *node, void *env) {
1303 ia32_code_gen_t *cgenv = (ia32_code_gen_t *)env;
1304 opcode code = get_irn_opcode(node);
1305 ir_node *asm_node = NULL;
1306 ia32_transform_env_t tenv;
1311 tenv.block = get_nodes_block(node);
1312 tenv.dbg = get_irn_dbg_info(node);
1313 tenv.irg = current_ir_graph;
1315 tenv.mod = cgenv->mod;
1316 tenv.mode = get_irn_mode(node);
1319 #define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
1320 #define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
1321 #define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break
1322 #define IGN(a) case iro_##a: break
1323 #define BAD(a) case iro_##a: goto bad
1325 DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1370 /* constant transformation happens earlier */
1390 if (get_irn_op(node) == get_op_Max()) {
1391 asm_node = gen_Max(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1393 else if (get_irn_op(node) == get_op_Min()) {
1394 asm_node = gen_Min(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1396 else if (get_irn_op(node) == get_op_Mulh()) {
1397 asm_node = gen_Mulh(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
1401 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1406 exchange(node, asm_node);
1407 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1410 DB((tenv.mod, LEVEL_1, "ignored\n"));