fixed some bugs
[libfirm] / ir / be / ia32 / ia32_transform.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "irnode_t.h"
6 #include "irgraph_t.h"
7 #include "irmode_t.h"
8 #include "iropt_t.h"
9 #include "irop_t.h"
10 #include "irprog_t.h"
11 #include "irgmod.h"
12 #include "iredges.h"
13 #include "irvrfy.h"
14 #include "ircons.h"
15 #include "dbginfo.h"
16 #include "debug.h"
17
18 #include "../benode_t.h"
19 #include "bearch_ia32_t.h"
20
21 #include "ia32_nodes_attr.h"
22 #include "../arch/archop.h"     /* we need this for Min and Max nodes */
23 #include "ia32_transform.h"
24 #include "ia32_new_nodes.h"
25
26 #include "gen_ia32_regalloc_if.h"
27
28 #define SFP_SIGN "0x80000000"
29 #define DFP_SIGN "0x8000000000000000"
30 #define SFP_ABS  "0x7FFFFFFF"
31 #define DFP_ABS  "0x7FFFFFFFFFFFFFFF"
32
33 #define TP_SFP_SIGN "ia32_sfp_sign"
34 #define TP_DFP_SIGN "ia32_dfp_sign"
35 #define TP_SFP_ABS  "ia32_sfp_abs"
36 #define TP_DFP_ABS  "ia32_dfp_abs"
37
38 #define ENT_SFP_SIGN "IA32_SFP_SIGN"
39 #define ENT_DFP_SIGN "IA32_DFP_SIGN"
40 #define ENT_SFP_ABS  "IA32_SFP_ABS"
41 #define ENT_DFP_ABS  "IA32_DFP_ABS"
42
43 extern ir_op *get_op_Mulh(void);
44
45 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
46                                                                           ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode);
47
48 typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
49                                                                          ir_node *op, ir_node *mem, ir_mode *mode);
50
51 typedef enum {
52         ia32_SSIGN, ia32_DSIGN, ia32_SABS, ia32_DABS
53 } ia32_known_const_t;
54
55 /****************************************************************************************************
56  *                  _        _                        __                           _   _
57  *                 | |      | |                      / _|                         | | (_)
58  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
59  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
60  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
61  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
62  *
63  ****************************************************************************************************/
64
65 struct tv_ent {
66         entity *ent;
67         tarval *tv;
68 };
69
70 /* Compares two (entity, tarval) combinations */
71 static int cmp_tv_ent(const void *a, const void *b, size_t len) {
72         const struct tv_ent *e1 = a;
73         const struct tv_ent *e2 = b;
74
75         return !(e1->tv == e2->tv);
76 }
77
78 /* Generates an entity for a known FP const (used for FP Neg + Abs) */
79 static char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) {
80         static set    *const_set = NULL;
81         struct tv_ent  key;
82         struct tv_ent *entry;
83         char          *tp_name;
84         char          *ent_name;
85         char          *cnst_str;
86         ir_type       *tp;
87         ir_node       *cnst;
88         ir_graph      *rem;
89         entity        *ent;
90
91         if (! const_set) {
92                 const_set = new_set(cmp_tv_ent, 10);
93         }
94
95         switch (kct) {
96                 case ia32_SSIGN:
97                         tp_name  = TP_SFP_SIGN;
98                         ent_name = ENT_SFP_SIGN;
99                         cnst_str = SFP_SIGN;
100                         break;
101                 case ia32_DSIGN:
102                         tp_name  = TP_DFP_SIGN;
103                         ent_name = ENT_DFP_SIGN;
104                         cnst_str = DFP_SIGN;
105                         break;
106                 case ia32_SABS:
107                         tp_name  = TP_SFP_ABS;
108                         ent_name = ENT_SFP_ABS;
109                         cnst_str = SFP_ABS;
110                         break;
111                 case ia32_DABS:
112                         tp_name  = TP_DFP_ABS;
113                         ent_name = ENT_DFP_ABS;
114                         cnst_str = DFP_ABS;
115                         break;
116         }
117
118
119         key.tv  = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
120         key.ent = NULL;
121
122         entry = set_insert(const_set, &key, sizeof(key), HASH_PTR(key.tv));
123
124         if (! entry->ent) {
125                 tp  = new_type_primitive(new_id_from_str(tp_name), mode);
126                 ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);
127
128                 set_entity_ld_ident(ent, get_entity_ident(ent));
129                 set_entity_visibility(ent, visibility_local);
130                 set_entity_variability(ent, variability_constant);
131                 set_entity_allocation(ent, allocation_static);
132
133                 /* we create a new entity here: It's initialization must resist on the
134                     const code irg */
135                 rem = current_ir_graph;
136                 current_ir_graph = get_const_code_irg();
137                 cnst = new_Const(mode, key.tv);
138                 current_ir_graph = rem;
139
140                 set_atomic_ent_value(ent, cnst);
141
142                 /* set the entry for hashmap */
143                 entry->ent = ent;
144         }
145
146         return ent_name;
147 }
148
149
150
151 /* determine if one operator is an Imm */
152 static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
153         if (op1)
154                 return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL);
155         else return is_ia32_Cnst(op2) ? op2 : NULL;
156 }
157
158 /* determine if one operator is not an Imm */
159 static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
160         return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL);
161 }
162
163
164 /**
165  * Construct a standard binary operation, set AM and immediate if required.
166  *
167  * @param env   The transformation environment
168  * @param op1   The first operand
169  * @param op2   The second operand
170  * @param func  The node constructor function
171  * @return The constructed ia32 node.
172  */
173 static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
174         ir_node           *new_op   = NULL;
175         ir_mode           *mode     = env->mode;
176         dbg_info          *dbg      = env->dbg;
177         ir_graph          *irg      = env->irg;
178         ir_node           *block    = env->block;
179         firm_dbg_module_t *mod      = env->mod;
180         ir_node           *noreg_gp = ia32_new_NoReg_gp(env->cg);
181         ir_node           *noreg_fp = ia32_new_NoReg_fp(env->cg);
182         ir_node           *nomem    = new_NoMem();
183         ir_node           *expr_op, *imm_op;
184
185
186         /* Check if immediate optimization is on and */
187         /* if it's an operation with immediate.      */
188         if (! env->cg->opt.immops) {
189                 expr_op = op1;
190                 imm_op  = NULL;
191         }
192         else 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);
195         }
196         else {
197                 imm_op  = get_immediate_op(NULL, op2);
198                 expr_op = get_expr_op(op1, op2);
199         }
200
201         assert((expr_op || imm_op) && "invalid operands");
202
203         if (!expr_op) {
204                 /* We have two consts here: not yet supported */
205                 imm_op = NULL;
206         }
207
208         if (mode_is_float(mode)) {
209                 /* floating point operations */
210                 if (imm_op) {
211                         new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_fp, nomem, mode_T);
212                         set_ia32_Immop_attr(new_op, imm_op);
213                         set_ia32_am_support(new_op, ia32_am_None);
214                 }
215                 else {
216                         new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode_T);
217                         set_ia32_am_support(new_op, ia32_am_Source);
218                 }
219         }
220         else {
221                 /* integer operations */
222                 if (imm_op) {
223                         /* This is expr + const */
224                         new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_gp, nomem, mode_T);
225                         set_ia32_Immop_attr(new_op, imm_op);
226
227                         /* set AM support */
228                         set_ia32_am_support(new_op, ia32_am_Dest);
229                 }
230                 else {
231                         /* This is a normal operation */
232                         new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode_T);
233
234                         /* set AM support */
235                         set_ia32_am_support(new_op, ia32_am_Full);
236                 }
237         }
238
239         if (is_op_commutative(get_irn_op(env->irn))) {
240                 set_ia32_commutative(new_op);
241         }
242
243         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
244 }
245
246
247
248 /**
249  * Construct a shift/rotate binary operation, sets AM and immediate if required.
250  *
251  * @param env   The transformation environment
252  * @param op1   The first operand
253  * @param op2   The second operand
254  * @param func  The node constructor function
255  * @return The constructed ia32 node.
256  */
257 static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
258         ir_node           *new_op = NULL;
259         ir_mode           *mode   = env->mode;
260         dbg_info          *dbg    = env->dbg;
261         ir_graph          *irg    = env->irg;
262         ir_node           *block  = env->block;
263         firm_dbg_module_t *mod    = env->mod;
264         ir_node           *noreg  = ia32_new_NoReg_gp(env->cg);
265         ir_node           *nomem  = new_NoMem();
266         ir_node           *expr_op, *imm_op;
267         tarval            *tv;
268
269         assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
270
271         /* Check if immediate optimization is on and */
272         /* if it's an operation with immediate.      */
273         imm_op  = env->cg->opt.immops ? get_immediate_op(NULL, op2) : NULL;
274         expr_op = get_expr_op(op1, op2);
275
276         assert((expr_op || imm_op) && "invalid operands");
277
278         if (!expr_op) {
279                 /* We have two consts here: not yet supported */
280                 imm_op = NULL;
281         }
282
283         /* Limit imm_op within range imm8 */
284         if (imm_op) {
285                 tv = get_ia32_Immop_tarval(imm_op);
286
287                 if (tv) {
288                         tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
289                 }
290                 else {
291                         imm_op = NULL;
292                 }
293         }
294
295         /* integer operations */
296         if (imm_op) {
297                 /* This is shift/rot with const */
298
299                 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
300                 set_ia32_Immop_attr(new_op, imm_op);
301         }
302         else {
303                 /* This is a normal shift/rot */
304                 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
305         }
306
307         /* set AM support */
308         set_ia32_am_support(new_op, ia32_am_Dest);
309
310         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
311 }
312
313
314 /**
315  * Construct a standard unary operation, set AM and immediate if required.
316  *
317  * @param env   The transformation environment
318  * @param op    The operand
319  * @param func  The node constructor function
320  * @return The constructed ia32 node.
321  */
322 static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) {
323         ir_node           *new_op = NULL;
324         ir_mode           *mode   = env->mode;
325         dbg_info          *dbg    = env->dbg;
326         ir_graph          *irg    = env->irg;
327         ir_node           *block  = env->block;
328         ir_node           *noreg  = ia32_new_NoReg_gp(env->cg);
329         ir_node           *nomem  = new_NoMem();
330
331         new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T);
332
333         if (mode_is_float(mode)) {
334                 /* floating point operations don't support implicit store */
335                 set_ia32_am_support(new_op, ia32_am_None);
336         }
337         else {
338                 set_ia32_am_support(new_op, ia32_am_Dest);
339         }
340
341         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
342 }
343
344
345
346 /**
347  * Creates an ia32 Add with immediate.
348  *
349  * @param env       The transformation environment
350  * @param expr_op   The expression operator
351  * @param const_op  The constant
352  * @return the created ia32 Add node
353  */
354 static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
355         ir_node                *new_op     = NULL;
356         tarval                 *tv         = get_ia32_Immop_tarval(const_op);
357         firm_dbg_module_t      *mod        = env->mod;
358         dbg_info               *dbg        = env->dbg;
359         ir_mode                *mode       = env->mode;
360         ir_graph               *irg        = env->irg;
361         ir_node                *block      = env->block;
362         ir_node                *noreg      = ia32_new_NoReg_gp(env->cg);
363         ir_node                *nomem      = new_NoMem();
364         int                     normal_add = 1;
365         tarval_classification_t class_tv, class_negtv;
366
367         /* try to optimize to inc/dec  */
368         if (env->cg->opt.incdec && tv) {
369                 /* optimize tarvals */
370                 class_tv    = classify_tarval(tv);
371                 class_negtv = classify_tarval(tarval_neg(tv));
372
373                 if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
374                         DB((env->mod, LEVEL_2, "Add(1) to Inc ... "));
375                         new_op     = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
376                         normal_add = 0;
377                 }
378                 else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
379                         DB((mod, LEVEL_2, "Add(-1) to Dec ... "));
380                         new_op     = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
381                         normal_add = 0;
382                 }
383         }
384
385         if (normal_add) {
386                 new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
387                 set_ia32_Immop_attr(new_op, const_op);
388         }
389
390         return new_op;
391 }
392
393 /**
394  * Creates an ia32 Add.
395  *
396  * @param dbg       firm node dbg
397  * @param block     the block the new node should belong to
398  * @param op1       first operator
399  * @param op2       second operator
400  * @param mode      node mode
401  * @return the created ia32 Add node
402  */
403 static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
404         ir_node  *new_op = NULL;
405         dbg_info *dbg    = env->dbg;
406         ir_mode  *mode   = env->mode;
407         ir_graph *irg    = env->irg;
408         ir_node  *block  = env->block;
409         ir_node  *noreg  = ia32_new_NoReg_gp(env->cg);
410         ir_node  *nomem  = new_NoMem();
411         ir_node  *expr_op, *imm_op;
412
413         /* Check if immediate optimization is on and */
414         /* if it's an operation with immediate.      */
415         imm_op  = env->cg->opt.immops ? get_immediate_op(op1, op2) : NULL;
416         expr_op = get_expr_op(op1, op2);
417
418         assert((expr_op || imm_op) && "invalid operands");
419
420         if (mode_is_float(mode)) {
421                 return gen_binop(env, op1, op2, new_rd_ia32_fAdd);
422         }
423         else {
424                 /* integer ADD */
425                 if (!expr_op) {
426                         /* No expr_op means, that we have two const - one symconst and */
427                         /* one tarval or another symconst - because this case is not   */
428                         /* covered by constant folding                                 */
429
430                         new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
431                         add_ia32_am_offs(new_op, get_ia32_cnst(op1));
432                         add_ia32_am_offs(new_op, get_ia32_cnst(op2));
433
434                         /* set AM support */
435                         set_ia32_am_support(new_op, ia32_am_Source);
436                         set_ia32_op_type(new_op, ia32_AddrModeS);
437                         set_ia32_am_flavour(new_op, ia32_am_O);
438
439                         /* Lea doesn't need a Proj */
440                         return new_op;
441                 }
442                 else if (imm_op) {
443                         /* This is expr + const */
444                         new_op = gen_imm_Add(env, expr_op, imm_op);
445
446                         /* set AM support */
447                         set_ia32_am_support(new_op, ia32_am_Dest);
448                 }
449                 else {
450                         /* This is a normal add */
451                         new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
452
453                         /* set AM support */
454                         set_ia32_am_support(new_op, ia32_am_Full);
455                 }
456         }
457
458         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
459 }
460
461
462
463 /**
464  * Creates an ia32 Mul.
465  *
466  * @param dbg       firm node dbg
467  * @param block     the block the new node should belong to
468  * @param op1       first operator
469  * @param op2       second operator
470  * @param mode      node mode
471  * @return the created ia32 Mul node
472  */
473 static ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
474         ir_node *new_op;
475
476         if (mode_is_float(env->mode)) {
477                 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul);
478         }
479         else {
480                 new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
481         }
482
483         return new_op;
484 }
485
486
487
488 /**
489  * Creates an ia32 Mulh.
490  * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
491  * this result while Mul returns the lower 32 bit.
492  *
493  * @param env   The transformation environment
494  * @param op1   The first operator
495  * @param op2   The second operator
496  * @return the created ia32 Mulh node
497  */
498 static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
499         ir_node *proj_EAX, *proj_EDX, *mulh;
500         ir_node *in[1];
501
502         assert(mode_is_float(env->mode) && "Mulh with float not supported");
503         proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh);
504         mulh     = get_Proj_pred(proj_EAX);
505         proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX);
506
507         /* to be on the save side */
508         set_Proj_proj(proj_EAX, pn_EAX);
509
510         if (get_ia32_cnst(mulh)) {
511                 /* Mulh with const cannot have AM */
512                 set_ia32_am_support(mulh, ia32_am_None);
513         }
514         else {
515                 /* Mulh cannot have AM for destination */
516                 set_ia32_am_support(mulh, ia32_am_Source);
517         }
518
519         in[0] = proj_EAX;
520
521         /* keep EAX */
522         be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);
523
524         return proj_EDX;
525 }
526
527
528
529 /**
530  * Creates an ia32 And.
531  *
532  * @param env   The transformation environment
533  * @param op1   The first operator
534  * @param op2   The second operator
535  * @return The created ia32 And node
536  */
537 static ir_node *gen_And(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
538         if (mode_is_float(env->mode)) {
539                 return gen_binop(env, op1, op2, new_rd_ia32_fAnd);
540         }
541         else {
542                 return gen_binop(env, op1, op2, new_rd_ia32_And);
543         }
544 }
545
546
547
548 /**
549  * Creates an ia32 Or.
550  *
551  * @param env   The transformation environment
552  * @param op1   The first operator
553  * @param op2   The second operator
554  * @return The created ia32 Or node
555  */
556 static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
557         if (mode_is_float(env->mode)) {
558                 return gen_binop(env, op1, op2, new_rd_ia32_fOr);
559         }
560         else {
561                 return gen_binop(env, op1, op2, new_rd_ia32_Or);
562         }
563 }
564
565
566
567 /**
568  * Creates an ia32 Eor.
569  *
570  * @param env   The transformation environment
571  * @param op1   The first operator
572  * @param op2   The second operator
573  * @return The created ia32 Eor node
574  */
575 static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
576         if (mode_is_float(env->mode)) {
577                 return gen_binop(env, op1, op2, new_rd_ia32_fEor);
578         }
579         else {
580                 return gen_binop(env, op1, op2, new_rd_ia32_Eor);
581         }
582 }
583
584
585
586 /**
587  * Creates an ia32 Max.
588  *
589  * @param env      The transformation environment
590  * @param op1      The first operator
591  * @param op2      The second operator
592  * @return the created ia32 Max node
593  */
594 static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
595         ir_node *new_op;
596
597         if (mode_is_float(env->mode)) {
598                 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax);
599         }
600         else {
601                 new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
602                 set_ia32_am_support(new_op, ia32_am_None);
603         }
604
605         return new_op;
606 }
607
608
609
610 /**
611  * Creates an ia32 Min.
612  *
613  * @param env      The transformation environment
614  * @param op1      The first operator
615  * @param op2      The second operator
616  * @return the created ia32 Min node
617  */
618 static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
619         ir_node *new_op;
620
621         if (mode_is_float(env->mode)) {
622                 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin);
623         }
624         else {
625                 new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
626                 set_ia32_am_support(new_op, ia32_am_None);
627         }
628
629         return new_op;
630 }
631
632
633
634 /**
635  * Creates an ia32 Sub with immediate.
636  *
637  * @param env   The transformation environment
638  * @param op1   The first operator
639  * @param op2   The second operator
640  * @return The created ia32 Sub node
641  */
642 static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
643         ir_node                *new_op     = NULL;
644         tarval                 *tv         = get_ia32_Immop_tarval(const_op);
645         firm_dbg_module_t      *mod        = env->mod;
646         dbg_info               *dbg        = env->dbg;
647         ir_mode                *mode       = env->mode;
648         ir_graph               *irg        = env->irg;
649         ir_node                *block      = env->block;
650         ir_node                *noreg      = ia32_new_NoReg_gp(env->cg);
651         ir_node                *nomem      = new_NoMem();
652         int                     normal_sub = 1;
653         tarval_classification_t class_tv, class_negtv;
654
655         /* try to optimize to inc/dec  */
656         if (env->cg->opt.incdec && tv) {
657                 /* optimize tarvals */
658                 class_tv    = classify_tarval(tv);
659                 class_negtv = classify_tarval(tarval_neg(tv));
660
661                 if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
662                         DB((mod, LEVEL_2, "Sub(1) to Dec ... "));
663                         new_op     = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
664                         normal_sub = 0;
665                 }
666                 else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
667                         DB((mod, LEVEL_2, "Sub(-1) to Inc ... "));
668                         new_op     = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
669                         normal_sub = 0;
670                 }
671         }
672
673         if (normal_sub) {
674                 new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
675                 set_ia32_Immop_attr(new_op, const_op);
676         }
677
678         return new_op;
679 }
680
681 /**
682  * Creates an ia32 Sub.
683  *
684  * @param env   The transformation environment
685  * @param op1   The first operator
686  * @param op2   The second operator
687  * @return The created ia32 Sub node
688  */
689 static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
690         ir_node  *new_op = NULL;
691         dbg_info *dbg    = env->dbg;
692         ir_mode  *mode   = env->mode;
693         ir_graph *irg    = env->irg;
694         ir_node  *block  = env->block;
695         ir_node  *noreg  = ia32_new_NoReg_gp(env->cg);
696         ir_node  *nomem  = new_NoMem();
697         ir_node  *expr_op, *imm_op;
698
699         /* Check if immediate optimization is on and */
700         /* if it's an operation with immediate.      */
701         imm_op  = env->cg->opt.immops ? get_immediate_op(NULL, op2) : NULL;
702         expr_op = get_expr_op(op1, op2);
703
704         assert((expr_op || imm_op) && "invalid operands");
705
706         if (mode_is_float(mode)) {
707                 return gen_binop(env, op1, op2, new_rd_ia32_fSub);
708         }
709         else {
710                 /* integer SUB */
711                 if (!expr_op) {
712                         /* No expr_op means, that we have two const - one symconst and */
713                         /* one tarval or another symconst - because this case is not   */
714                         /* covered by constant folding                                 */
715
716                         new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
717                         add_ia32_am_offs(new_op, get_ia32_cnst(op1));
718                         sub_ia32_am_offs(new_op, get_ia32_cnst(op2));
719
720                         /* set AM support */
721                         set_ia32_am_support(new_op, ia32_am_Source);
722                         set_ia32_op_type(new_op, ia32_AddrModeS);
723                         set_ia32_am_flavour(new_op, ia32_am_O);
724
725                         /* Lea doesn't need a Proj */
726                         return new_op;
727                 }
728                 else if (imm_op) {
729                         /* This is expr - const */
730                         new_op = gen_imm_Sub(env, expr_op, imm_op);
731
732                         /* set AM support */
733                         set_ia32_am_support(new_op, ia32_am_Dest);
734                 }
735                 else {
736                         /* This is a normal sub */
737                         new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
738
739                         /* set AM support */
740                         set_ia32_am_support(new_op, ia32_am_Full);
741                 }
742         }
743
744         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
745 }
746
747
748
749 /**
750  * Generates an ia32 DivMod with additional infrastructure for the
751  * register allocator if needed.
752  *
753  * @param env      The transformation environment
754  * @param dividend -no comment- :)
755  * @param divisor  -no comment- :)
756  * @param dm_flav  flavour_Div/Mod/DivMod
757  * @return The created ia32 DivMod node
758  */
759 static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
760         ir_node  *res, *proj;
761         ir_node  *edx_node, *cltd;
762         ir_node  *in_keep[1];
763         dbg_info *dbg   = env->dbg;
764         ir_graph *irg   = env->irg;
765         ir_node  *block = env->block;
766         ir_mode  *mode  = env->mode;
767         ir_node  *irn   = env->irn;
768         ir_node  *mem;
769
770         switch (dm_flav) {
771                 case flavour_Div:
772                         mem = get_Div_mem(irn);
773                         break;
774                 case flavour_Mod:
775                         mem = get_Mod_mem(irn);
776                         break;
777                 case flavour_DivMod:
778                         mem = get_DivMod_mem(irn);
779                         break;
780                 default:
781                         assert(0);
782         }
783
784         if (mode_is_signed(mode)) {
785                 /* in signed mode, we need to sign extend the dividend */
786                 cltd     = new_rd_ia32_Cdq(dbg, irg, block, dividend, mode_T);
787                 dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX);
788                 edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX);
789         }
790         else {
791                 edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
792                 set_ia32_Const_type(edx_node, ia32_Const);
793                 set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
794         }
795
796         res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode);
797
798         set_ia32_flavour(res, dm_flav);
799         set_ia32_n_res(res, 2);
800
801         /* Only one proj is used -> We must add a second proj and */
802         /* connect this one to a Keep node to eat up the second   */
803         /* destroyed register.                                    */
804         if (get_irn_n_edges(irn) == 1) {
805                 proj = get_edge_src_irn(get_irn_out_edge_first(irn));
806                 assert(is_Proj(proj) && "non-Proj to Div/Mod node");
807
808                 if (get_Proj_proj(proj) == pn_DivMod_res_div) {
809                         in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_mod);
810                 }
811                 else {
812                         in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
813                 }
814
815                 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
816         }
817
818         return res;
819 }
820
821
822 /**
823  * Wrapper for generate_DivMod. Sets flavour_Mod.
824  */
825 static ir_node *gen_Mod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
826         return generate_DivMod(env, op1, op2, flavour_Mod);
827 }
828
829
830
831 /**
832  * Wrapper for generate_DivMod. Sets flavour_Div.
833  */
834 static ir_node *gen_Div(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
835         return generate_DivMod(env, op1, op2, flavour_Div);
836 }
837
838
839
840 /**
841  * Wrapper for generate_DivMod. Sets flavour_DivMod.
842  */
843 static ir_node *gen_DivMod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
844         return generate_DivMod(env, op1, op2, flavour_DivMod);
845 }
846
847
848
849 /**
850  * Creates an ia32 floating Div.
851  *
852  * @param env   The transformation environment
853  * @param op1   The first operator
854  * @param op2   The second operator
855  * @return The created ia32 fDiv node
856  */
857 static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
858         ir_node *noreg = ia32_new_NoReg_gp(env->cg);
859         ir_node *nomem = new_rd_NoMem(env->irg);
860         ir_node *new_op;
861
862         new_op = new_rd_ia32_fDiv(env->dbg, env->irg, env->block, noreg, noreg, op1, op2, nomem, env->mode);
863         set_ia32_am_support(new_op, ia32_am_Source);
864
865         return new_op;
866 }
867
868
869
870 /**
871  * Creates an ia32 Shl.
872  *
873  * @param env   The transformation environment
874  * @param op1   The first operator
875  * @param op2   The second operator
876  * @return The created ia32 Shl node
877  */
878 static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
879         return gen_shift_binop(env, op1, op2, new_rd_ia32_Shl);
880 }
881
882
883
884 /**
885  * Creates an ia32 Shr.
886  *
887  * @param env   The transformation environment
888  * @param op1   The first operator
889  * @param op2   The second operator
890  * @return The created ia32 Shr node
891  */
892 static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
893         return gen_shift_binop(env, op1, op2, new_rd_ia32_Shr);
894 }
895
896
897
898 /**
899  * Creates an ia32 Shrs.
900  *
901  * @param env   The transformation environment
902  * @param op1   The first operator
903  * @param op2   The second operator
904  * @return The created ia32 Shrs node
905  */
906 static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
907         return gen_shift_binop(env, op1, op2, new_rd_ia32_Shrs);
908 }
909
910
911
912 /**
913  * Creates an ia32 RotL.
914  *
915  * @param env   The transformation environment
916  * @param op1   The first operator
917  * @param op2   The second operator
918  * @return The created ia32 RotL node
919  */
920 static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
921         return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL);
922 }
923
924
925
926 /**
927  * Creates an ia32 RotR.
928  * NOTE: There is no RotR with immediate because this would always be a RotL
929  *       "imm-mode_size_bits" which can be pre-calculated.
930  *
931  * @param env   The transformation environment
932  * @param op1   The first operator
933  * @param op2   The second operator
934  * @return The created ia32 RotR node
935  */
936 static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
937         return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR);
938 }
939
940
941
942 /**
943  * Creates an ia32 RotR or RotL (depending on the found pattern).
944  *
945  * @param env   The transformation environment
946  * @param op1   The first operator
947  * @param op2   The second operator
948  * @return The created ia32 RotL or RotR node
949  */
950 static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
951         ir_node *rotate = NULL;
952
953         /* Firm has only Rot (which is a RotL), so we are looking for a right (op2)
954                  operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
955                  that means we can create a RotR instead of an Add and a RotL */
956
957         if (is_Proj(op2)) {
958                 ir_node *pred = get_Proj_pred(op2);
959
960                 if (is_ia32_Add(pred)) {
961                         ir_node *pred_pred = get_irn_n(pred, 2);
962                         tarval  *tv        = get_ia32_Immop_tarval(pred);
963                         long     bits      = get_mode_size_bits(env->mode);
964
965                         if (is_Proj(pred_pred)) {
966                                 pred_pred = get_Proj_pred(pred_pred);
967                         }
968
969                         if (is_ia32_Minus(pred_pred) &&
970                                 tarval_is_long(tv)       &&
971                                 get_tarval_long(tv) == bits)
972                         {
973                                 DB((env->mod, LEVEL_1, "RotL into RotR ... "));
974                                 rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
975                         }
976
977                 }
978         }
979
980         if (!rotate) {
981                 rotate = gen_RotL(env, op1, op2);
982         }
983
984         return rotate;
985 }
986
987
988
989 /**
990  * Transforms a Conv node.
991  *
992  * @param env   The transformation environment
993  * @param op    The operator
994  * @return The created ia32 Conv node
995  */
996 static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
997         return new_rd_ia32_Conv(env->dbg, env->irg, env->block, op, env->mode);
998 }
999
1000
1001
1002 /**
1003  * Transforms a Minus node.
1004  *
1005  * @param env   The transformation environment
1006  * @param op    The operator
1007  * @return The created ia32 Minus node
1008  */
1009 static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
1010         char    *name;
1011         ir_node *new_op;
1012         ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg);
1013         ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg);
1014         ir_node *nomem    = new_rd_NoMem(env->irg);
1015         int      size;
1016
1017         if (mode_is_float(env->mode)) {
1018                 new_op = new_rd_ia32_fEor(env->dbg, env->irg, env->block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T);
1019
1020                 size   = get_mode_size_bits(env->mode);
1021                 name   = gen_fp_known_const(env->mode, size == 32 ? ia32_SSIGN : ia32_DSIGN);
1022
1023                 set_ia32_sc(new_op, name);
1024
1025                 new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
1026         }
1027         else {
1028                 new_op = gen_unop(env, op, new_rd_ia32_Minus);
1029         }
1030
1031         return new_op;
1032 }
1033
1034
1035
1036 /**
1037  * Transforms a Not node.
1038  *
1039  * @param env   The transformation environment
1040  * @param op    The operator
1041  * @return The created ia32 Not node
1042  */
1043 static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
1044         ir_node *new_op;
1045
1046         if (mode_is_float(env->mode)) {
1047                 assert(0);
1048         }
1049         else {
1050                 new_op = gen_unop(env, op, new_rd_ia32_Not);
1051         }
1052
1053         return new_op;
1054 }
1055
1056
1057
1058 /**
1059  * Transforms an Abs node.
1060  *
1061  * @param env   The transformation environment
1062  * @param op    The operator
1063  * @return The created ia32 Abs node
1064  */
1065 static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
1066         ir_node  *res, *p_eax, *p_edx;
1067         dbg_info *dbg      = env->dbg;
1068         ir_mode  *mode     = env->mode;
1069         ir_graph *irg      = env->irg;
1070         ir_node  *block    = env->block;
1071         ir_node  *noreg_gp = ia32_new_NoReg_gp(env->cg);
1072         ir_node  *noreg_fp = ia32_new_NoReg_fp(env->cg);
1073         ir_node  *nomem    = new_NoMem();
1074         int       size;
1075         char     *name;
1076
1077         if (mode_is_float(mode)) {
1078                 res = new_rd_ia32_fAnd(dbg,irg, block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T);
1079
1080                 size   = get_mode_size_bits(mode);
1081                 name   = gen_fp_known_const(mode, size == 32 ? ia32_SABS : ia32_DABS);
1082
1083                 set_ia32_sc(res, name);
1084
1085                 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
1086         }
1087         else {
1088                 res   = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T);
1089                 p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
1090                 p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
1091                 res   = new_rd_ia32_Eor(dbg, irg, block, noreg_gp, noreg_gp, p_eax, p_edx, nomem, mode_T);
1092                 res   = new_rd_Proj(dbg, irg, block, res, mode, 0);
1093                 res   = new_rd_ia32_Sub(dbg, irg, block, noreg_gp, noreg_gp, res, p_edx, nomem, mode_T);
1094                 res   = new_rd_Proj(dbg, irg, block, res, mode, 0);
1095         }
1096
1097         return res;
1098 }
1099
1100
1101
1102 /**
1103  * Transforms a Load.
1104  *
1105  * @param mod     the debug module
1106  * @param block   the block the new node should belong to
1107  * @param node    the ir Load node
1108  * @param mode    node mode
1109  * @return the created ia32 Load node
1110  */
1111 static ir_node *gen_Load(ia32_transform_env_t *env) {
1112         ir_node *node  = env->irn;
1113         ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1114         ir_node *new_op;
1115
1116         if (mode_is_float(env->mode)) {
1117                 new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
1118         }
1119         else {
1120                 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
1121         }
1122
1123         set_ia32_am_support(new_op, ia32_am_Source);
1124         set_ia32_op_type(new_op, ia32_AddrModeS);
1125         set_ia32_am_flavour(new_op, ia32_B);
1126         set_ia32_ls_mode(new_op, get_Load_mode(node));
1127
1128         return new_op;
1129 }
1130
1131
1132
1133 /**
1134  * Transforms a Store.
1135  *
1136  * @param mod     the debug module
1137  * @param block   the block the new node should belong to
1138  * @param node    the ir Store node
1139  * @param mode    node mode
1140  * @return the created ia32 Store node
1141  */
1142 static ir_node *gen_Store(ia32_transform_env_t *env) {
1143         ir_node *node  = env->irn;
1144         ir_node *noreg = ia32_new_NoReg_gp(env->cg);
1145         ir_node *val   = get_Store_value(node);
1146         ir_node *ptr   = get_Store_ptr(node);
1147         ir_node *mem   = get_Store_mem(node);
1148         ir_node *sval  = val;
1149         ir_node *new_op;
1150
1151         /* in case of storing a const -> make it an attribute */
1152         if (is_ia32_Cnst(val)) {
1153                 sval = noreg;
1154         }
1155
1156         if (mode_is_float(env->mode)) {
1157                 new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
1158         }
1159         else {
1160                 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
1161         }
1162
1163         /* stored const is an attribute (saves a register) */
1164         if (is_ia32_Cnst(val)) {
1165                 set_ia32_Immop_attr(new_op, val);
1166         }
1167
1168         set_ia32_am_support(new_op, ia32_am_Dest);
1169         set_ia32_op_type(new_op, ia32_AddrModeD);
1170         set_ia32_am_flavour(new_op, ia32_B);
1171         set_ia32_ls_mode(new_op, get_irn_mode(val));
1172         return new_op;
1173 }
1174
1175
1176
1177 /**
1178  * Transforms a Call and its arguments corresponding to the calling convention.
1179  *
1180  * @param env   The transformation environment
1181  * @return The created ia32 Call node
1182  */
1183 static ir_node *gen_Call(ia32_transform_env_t *env) {
1184 }
1185
1186
1187
1188 /**
1189  * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
1190  *
1191  * @param env   The transformation environment
1192  * @return The transformed node.
1193  */
1194 static ir_node *gen_Cond(ia32_transform_env_t *env) {
1195         dbg_info *dbg      = env->dbg;
1196         ir_graph *irg      = env->irg;
1197         ir_node  *block    = env->block;
1198         ir_node  *node     = env->irn;
1199         ir_node  *sel      = get_Cond_selector(node);
1200         ir_mode  *sel_mode = get_irn_mode(sel);
1201         ir_node  *res      = NULL;
1202         ir_node  *pred     = NULL;
1203         ir_node  *noreg    = ia32_new_NoReg_gp(env->cg);
1204         ir_node  *nomem    = new_NoMem();
1205         ir_node  *cmp_a, *cmp_b, *cnst, *expr;
1206
1207         if (is_Proj(sel) && sel_mode == mode_b) {
1208                 pred  = get_Proj_pred(sel);
1209
1210                 /* get both compare operators */
1211                 cmp_a = get_Cmp_left(pred);
1212                 cmp_b = get_Cmp_right(pred);
1213
1214                 /* check if we can use a CondJmp with immediate */
1215                 cnst = env->cg->opt.immops ? get_immediate_op(cmp_a, cmp_b) : NULL;
1216                 expr = get_expr_op(cmp_a, cmp_b);
1217
1218                 if (cnst && expr) {
1219                         res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T);
1220                         set_ia32_Immop_attr(res, cnst);
1221                 }
1222                 else {
1223                         res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T);
1224                 }
1225
1226                 set_ia32_pncode(res, get_Proj_proj(sel));
1227                 set_ia32_am_support(res, ia32_am_Source);
1228         }
1229         else {
1230                 res = new_rd_ia32_SwitchJmp(dbg, irg, block, sel, mode_T);
1231                 set_ia32_pncode(res, get_Cond_defaultProj(node));
1232         }
1233
1234         return res;
1235 }
1236
1237
1238
1239 /**
1240  * Transforms a CopyB node.
1241  *
1242  * @param env   The transformation environment
1243  * @return The transformed node.
1244  */
1245 static ir_node *gen_CopyB(ia32_transform_env_t *env) {
1246         ir_node  *res   = NULL;
1247         dbg_info *dbg   = env->dbg;
1248         ir_graph *irg   = env->irg;
1249         ir_mode  *mode  = env->mode;
1250         ir_node  *block = env->block;
1251         ir_node  *node  = env->irn;
1252         ir_node  *src   = get_CopyB_src(node);
1253         ir_node  *dst   = get_CopyB_dst(node);
1254         ir_node  *mem   = get_CopyB_mem(node);
1255         ir_node  *noreg = ia32_new_NoReg_gp(env->cg);
1256         int       size  = get_type_size_bytes(get_CopyB_type(node));
1257         int       rem;
1258
1259         /* If we have to copy more than 16 bytes, we use REP MOVSx and */
1260         /* then we need the size explicitly in ECX.                    */
1261         if (size >= 16 * 4) {
1262                 rem = size & 0x3; /* size % 4 */
1263                 size >>= 2;
1264
1265                 res = new_rd_ia32_Const(dbg, irg, block, mode_Is);
1266                 set_ia32_op_type(res, ia32_Const);
1267                 set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
1268
1269                 res = new_rd_ia32_CopyB(dbg, irg, block, dst, src, res, mem, mode);
1270                 set_ia32_Immop_tarval(res, new_tarval_from_long(rem, mode_Is));
1271         }
1272         else {
1273                 res = new_rd_ia32_CopyB_i(dbg, irg, block, dst, src, mem, mode);
1274                 set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is));
1275         }
1276
1277         return res;
1278 }
1279
1280
1281
1282 /**
1283  * Transforms a Mux node into CMov.
1284  *
1285  * @param env   The transformation environment
1286  * @return The transformed node.
1287  */
1288 static ir_node *gen_Mux(ia32_transform_env_t *env) {
1289         ir_node *node  = env->irn;
1290
1291         return new_rd_ia32_CMov(env->dbg, env->irg, env->block,
1292                 get_Mux_sel(node), get_Mux_false(node), get_Mux_true(node), env->mode);
1293 }
1294
1295
1296
1297 /********************************************
1298  *  _                          _
1299  * | |                        | |
1300  * | |__   ___ _ __   ___   __| | ___  ___
1301  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
1302  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
1303  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
1304  *
1305  ********************************************/
1306
1307 static ir_node *gen_FrameAddr(ia32_transform_env_t *env) {
1308         ir_node *new_op = NULL;
1309         ir_node *node   = env->irn;
1310         ir_node *op     = get_irn_n(node, 0);
1311         ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
1312         ir_node *nomem  = new_rd_NoMem(env->irg);
1313
1314         new_op = new_rd_ia32_Add(env->dbg, env->irg, env->block, noreg, noreg, op, noreg, nomem, mode_T);
1315         set_ia32_frame_ent(new_op, be_get_frame_entity(node));
1316         set_ia32_am_support(new_op, ia32_am_Full);
1317         set_ia32_use_frame(new_op);
1318
1319         return new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
1320 }
1321
1322 static ir_node *gen_FrameLoad(ia32_transform_env_t *env) {
1323         ir_node *new_op = NULL;
1324
1325         return new_op;
1326 }
1327
1328 static ir_node *gen_FrameStore(ia32_transform_env_t *env) {
1329         ir_node *new_op = NULL;
1330
1331         return new_op;
1332 }
1333
1334
1335
1336 /*********************************************************
1337  *                  _             _      _
1338  *                 (_)           | |    (_)
1339  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1340  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1341  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1342  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1343  *
1344  *********************************************************/
1345
1346 /**
1347  * Transforms the given firm node (and maybe some other related nodes)
1348  * into one or more assembler nodes.
1349  *
1350  * @param node    the firm node
1351  * @param env     the debug module
1352  */
1353 void ia32_transform_node(ir_node *node, void *env) {
1354         ia32_code_gen_t *cgenv = (ia32_code_gen_t *)env;
1355         opcode  code           = get_irn_opcode(node);
1356         ir_node *asm_node      = NULL;
1357         ia32_transform_env_t  tenv;
1358
1359         if (is_Block(node))
1360                 return;
1361
1362         tenv.block    = get_nodes_block(node);
1363         tenv.dbg      = get_irn_dbg_info(node);
1364         tenv.irg      = current_ir_graph;
1365         tenv.irn      = node;
1366         tenv.mod      = cgenv->mod;
1367         tenv.mode     = get_irn_mode(node);
1368         tenv.cg       = cgenv;
1369
1370 #define UNOP(a)  case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
1371 #define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
1372 #define GEN(a)   case iro_##a: asm_node = gen_##a(&tenv); break
1373 #define IGN(a)   case iro_##a: break
1374 #define BAD(a)   case iro_##a: goto bad
1375 #define OTHER_BIN(a)                                                       \
1376         if (get_irn_op(node) == get_op_##a()) {                                \
1377                 asm_node = gen_##a(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); \
1378                 break;                                                             \
1379         }
1380 #define BE_GEN(a)                  \
1381         if (be_is_##a(node)) {         \
1382                 asm_node = gen_##a(&tenv); \
1383                 break;                     \
1384         }
1385
1386         DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1387
1388         switch (code) {
1389                 BINOP(Add);
1390                 BINOP(Sub);
1391                 BINOP(Mul);
1392                 BINOP(And);
1393                 BINOP(Or);
1394                 BINOP(Eor);
1395
1396                 BINOP(Shl);
1397                 BINOP(Shr);
1398                 BINOP(Shrs);
1399
1400                 BINOP(Quot);
1401
1402                 BINOP(Div);
1403                 BINOP(Mod);
1404                 BINOP(DivMod);
1405
1406                 UNOP(Minus);
1407                 UNOP(Conv);
1408                 UNOP(Abs);
1409                 UNOP(Not);
1410
1411                 GEN(Load);
1412                 GEN(Store);
1413                 GEN(Cond);
1414
1415                 GEN(CopyB);
1416                 GEN(Mux);
1417
1418                 IGN(Call);
1419                 IGN(Alloc);
1420
1421                 IGN(Proj);
1422                 IGN(Block);
1423                 IGN(Start);
1424                 IGN(End);
1425                 IGN(NoMem);
1426                 IGN(Phi);
1427                 IGN(IJmp);
1428                 IGN(Break);
1429                 IGN(Cmp);
1430                 IGN(Unknown);
1431
1432                 /* constant transformation happens earlier */
1433                 IGN(Const);
1434                 IGN(SymConst);
1435                 IGN(Sync);
1436
1437                 BAD(Raise);
1438                 BAD(Sel);
1439                 BAD(InstOf);
1440                 BAD(Cast);
1441                 BAD(Free);
1442                 BAD(Tuple);
1443                 BAD(Id);
1444                 BAD(Bad);
1445                 BAD(Confirm);
1446                 BAD(Filter);
1447                 BAD(CallBegin);
1448                 BAD(EndReg);
1449                 BAD(EndExcept);
1450
1451                 default:
1452                         OTHER_BIN(Max);
1453                         OTHER_BIN(Min);
1454                         OTHER_BIN(Mulh);
1455
1456                         BE_GEN(FrameAddr);
1457                         BE_GEN(FrameLoad);
1458                         BE_GEN(FrameStore);
1459                         break;
1460 bad:
1461                 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1462                 assert(0);
1463         }
1464
1465         /* exchange nodes if a new one was generated */
1466         if (asm_node) {
1467                 exchange(node, asm_node);
1468                 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1469         }
1470         else {
1471                 DB((tenv.mod, LEVEL_1, "ignored\n"));
1472         }
1473
1474 #undef UNOP
1475 #undef BINOP
1476 #undef GEN
1477 #undef IGN
1478 #undef BAD
1479 #undef OTHER_BIN
1480 #undef BE_GEN
1481 }