Fixed a type and a small bug
[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 "irgmod.h"
9 #include "iredges.h"
10 #include "irvrfy.h"
11 #include "ircons.h"
12 #include "dbginfo.h"
13 #include "iropt_t.h"
14 #include "debug.h"
15
16 #include "../benode_t.h"
17 #include "bearch_ia32_t.h"
18
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
24 #include "gen_ia32_regalloc_if.h"
25
26 #define SFP_SIGN "0x80000000"
27 #define DFP_SIGN "0x8000000000000000"
28 #define SFP_ABS  "0x7FFFFFFF"
29 #define DFP_ABS  "0x7FFFFFFFFFFFFFFF"
30
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"
35
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"
40
41 extern ir_op *get_op_Mulh(void);
42
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);
45
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);
48
49 typedef enum {
50         ia32_SSIGN, ia32_DSIGN, ia32_SABS, ia32_DABS
51 } ia32_known_const_t;
52
53 /****************************************************************************************************
54  *                  _        _                        __                           _   _
55  *                 | |      | |                      / _|                         | | (_)
56  *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
57  * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
58  * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
59  * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
60  *
61  ****************************************************************************************************/
62
63 struct tv_ent {
64         entity *ent;
65         tarval *tv;
66 };
67
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;
72
73         return !(e1->tv == e2->tv);
74 }
75
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;
79         struct tv_ent  key;
80         struct tv_ent *entry;
81         char          *tp_name;
82         char          *ent_name;
83         char          *cnst_str;
84         ir_type       *tp;
85         ir_node       *cnst;
86         ir_graph      *rem;
87         entity        *ent;
88
89         if (! const_set) {
90                 const_set = new_set(cmp_tv_ent, 10);
91         }
92
93         switch (kct) {
94                 case ia32_SSIGN:
95                         tp_name  = TP_SFP_SIGN;
96                         ent_name = ENT_SFP_SIGN;
97                         cnst_str = SFP_SIGN;
98                         break;
99                 case ia32_DSIGN:
100                         tp_name  = TP_DFP_SIGN;
101                         ent_name = ENT_DFP_SIGN;
102                         cnst_str = DFP_SIGN;
103                         break;
104                 case ia32_SABS:
105                         tp_name  = TP_SFP_ABS;
106                         ent_name = ENT_SFP_ABS;
107                         cnst_str = SFP_ABS;
108                         break;
109                 case ia32_DABS:
110                         tp_name  = TP_DFP_ABS;
111                         ent_name = ENT_DFP_ABS;
112                         cnst_str = DFP_ABS;
113                         break;
114         }
115
116
117         key.tv  = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
118         key.ent = NULL;
119
120         entry = set_insert(const_set, &key, sizeof(key), HASH_PTR(key.tv));
121
122         if (! entry->ent) {
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);
125
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);
130
131                 /* we create a new entity here: It's initialization must resist on the
132                     const code irg */
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;
137
138                 set_atomic_ent_value(ent, cnst);
139
140                 /* set the entry for hashmap */
141                 entry->ent = ent;
142         }
143
144         return ent_name;
145 }
146
147
148
149 /* determine if one operator is an Imm */
150 static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
151         if (op1)
152                 return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL);
153         else return is_ia32_Cnst(op2) ? op2 : NULL;
154 }
155
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);
159 }
160
161
162 /**
163  * Construct a standard binary operation, set AM and immediate if required.
164  *
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.
170  */
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;
182
183
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);
188         }
189         else {
190                 imm_op  = get_immediate_op(NULL, op2);
191                 expr_op = get_expr_op(op1, op2);
192         }
193
194         assert((expr_op || imm_op) && "invalid operands");
195
196         if (!expr_op) {
197                 /* We have two consts here: not yet supported */
198                 imm_op = NULL;
199         }
200
201         if (mode_is_float(mode)) {
202                 /* floating point operations */
203                 if (imm_op) {
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);
207                 }
208                 else {
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);
211                 }
212         }
213         else {
214                 /* integer operations */
215                 if (imm_op) {
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);
219
220                         /* set AM support */
221                         set_ia32_am_support(new_op, ia32_am_Dest);
222                 }
223                 else {
224                         /* This is a normal operation */
225                         new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode_T);
226
227                         /* set AM support */
228                         set_ia32_am_support(new_op, ia32_am_Full);
229                 }
230         }
231
232         if (is_op_commutative(get_irn_op(env->irn))) {
233                 set_ia32_commutative(new_op);
234         }
235
236         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
237 }
238
239
240
241 /**
242  * Construct a shift/rotate binary operation, sets AM and immediate if required.
243  *
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.
249  */
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;
260         tarval            *tv;
261
262         assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
263
264         imm_op  = get_immediate_op(NULL, op2);
265         expr_op = get_expr_op(op1, op2);
266
267         assert((expr_op || imm_op) && "invalid operands");
268
269         if (!expr_op) {
270                 /* We have two consts here: not yet supported */
271                 imm_op = NULL;
272         }
273
274         /* Limit imm_op within range imm8 */
275         if (imm_op) {
276                 tv = get_ia32_Immop_tarval(imm_op);
277
278                 if (tv) {
279                         tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
280                 }
281                 else {
282                         imm_op = NULL;
283                 }
284         }
285
286         /* integer operations */
287         if (imm_op) {
288                 /* This is shift/rot with const */
289
290                 new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
291                 set_ia32_Immop_attr(new_op, imm_op);
292         }
293         else {
294                 /* This is a normal shift/rot */
295                 new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
296         }
297
298         /* set AM support */
299         set_ia32_am_support(new_op, ia32_am_Dest);
300
301         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
302 }
303
304
305 /**
306  * Construct a standard unary operation, set AM and immediate if required.
307  *
308  * @param env   The transformation environment
309  * @param op    The operand
310  * @param func  The node constructor function
311  * @return The constructed ia32 node.
312  */
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();
321
322         new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T);
323
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);
327         }
328         else {
329                 set_ia32_am_support(new_op, ia32_am_Dest);
330         }
331
332         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
333 }
334
335
336
337 /**
338  * Creates an ia32 Add with immediate.
339  *
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
344  */
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();
355         int                     normal_add = 1;
356         tarval_classification_t class_tv, class_negtv;
357
358         /* const_op: tarval or SymConst? */
359         if (tv) {
360                 /* optimize tarvals */
361                 class_tv    = classify_tarval(tv);
362                 class_negtv = classify_tarval(tarval_neg(tv));
363
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);
367                         normal_add = 0;
368                 }
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);
372                         normal_add = 0;
373                 }
374         }
375
376         if (normal_add) {
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);
379         }
380
381         return new_op;
382 }
383
384 /**
385  * Creates an ia32 Add.
386  *
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
393  */
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;
403
404         imm_op  = get_immediate_op(op1, op2);
405         expr_op = get_expr_op(op1, op2);
406
407         assert((expr_op || imm_op) && "invalid operands");
408
409         if (mode_is_float(mode)) {
410                 return gen_binop(env, op1, op2, new_rd_ia32_fAdd);
411         }
412         else {
413                 /* integer ADD */
414                 if (!expr_op) {
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                                 */
418
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));
422
423                         /* set AM support */
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);
427
428                         /* Lea doesn't need a Proj */
429                         return new_op;
430                 }
431                 else if (imm_op) {
432                         /* This is expr + const */
433                         new_op = gen_imm_Add(env, expr_op, imm_op);
434
435                         /* set AM support */
436                         set_ia32_am_support(new_op, ia32_am_Dest);
437                 }
438                 else {
439                         /* This is a normal add */
440                         new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
441
442                         /* set AM support */
443                         set_ia32_am_support(new_op, ia32_am_Full);
444                 }
445         }
446
447         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
448 }
449
450
451
452 /**
453  * Creates an ia32 Mul.
454  *
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
461  */
462 static ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
463         ir_node *new_op;
464
465         if (mode_is_float(env->mode)) {
466                 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul);
467         }
468         else {
469                 new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
470         }
471
472         return new_op;
473 }
474
475
476
477 /**
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.
481  *
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
486  */
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;
489         ir_node *in[1];
490
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);
495
496         /* to be on the save side */
497         set_Proj_proj(proj_EAX, pn_EAX);
498
499         if (get_ia32_cnst(mulh)) {
500                 /* Mulh with const cannot have AM */
501                 set_ia32_am_support(mulh, ia32_am_None);
502         }
503         else {
504                 /* Mulh cannot have AM for destination */
505                 set_ia32_am_support(mulh, ia32_am_Source);
506         }
507
508         in[0] = proj_EAX;
509
510         /* keep EAX */
511         be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);
512
513         return proj_EDX;
514 }
515
516
517
518 /**
519  * Creates an ia32 And.
520  *
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
525  */
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);
529         }
530         else {
531                 return gen_binop(env, op1, op2, new_rd_ia32_And);
532         }
533 }
534
535
536
537 /**
538  * Creates an ia32 Or.
539  *
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
544  */
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);
548         }
549         else {
550                 return gen_binop(env, op1, op2, new_rd_ia32_Or);
551         }
552 }
553
554
555
556 /**
557  * Creates an ia32 Eor.
558  *
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
563  */
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);
567         }
568         else {
569                 return gen_binop(env, op1, op2, new_rd_ia32_Eor);
570         }
571 }
572
573
574
575 /**
576  * Creates an ia32 Max.
577  *
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
582  */
583 static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
584         ir_node *new_op;
585
586         if (mode_is_float(env->mode)) {
587                 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax);
588         }
589         else {
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);
592         }
593
594         return new_op;
595 }
596
597
598
599 /**
600  * Creates an ia32 Min.
601  *
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
606  */
607 static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
608         ir_node *new_op;
609
610         if (mode_is_float(env->mode)) {
611                 new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin);
612         }
613         else {
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);
616         }
617
618         return new_op;
619 }
620
621
622
623 /**
624  * Creates an ia32 Sub with immediate.
625  *
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
630  */
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();
641         int                     normal_sub = 1;
642         tarval_classification_t class_tv, class_negtv;
643
644         /* const_op: tarval or SymConst? */
645         if (tv) {
646                 /* optimize tarvals */
647                 class_tv    = classify_tarval(tv);
648                 class_negtv = classify_tarval(tarval_neg(tv));
649
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);
653                         normal_sub = 0;
654                 }
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);
658                         normal_sub = 0;
659                 }
660         }
661
662         if (normal_sub) {
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);
665         }
666
667         return new_op;
668 }
669
670 /**
671  * Creates an ia32 Sub.
672  *
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
677  */
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;
687
688         imm_op  = get_immediate_op(NULL, op2);
689         expr_op = get_expr_op(op1, op2);
690
691         assert((expr_op || imm_op) && "invalid operands");
692
693         if (mode_is_float(mode)) {
694                 return gen_binop(env, op1, op2, new_rd_ia32_fSub);
695         }
696         else {
697                 /* integer SUB */
698                 if (!expr_op) {
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                                 */
702
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));
706
707                         /* set AM support */
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);
711
712                         /* Lea doesn't need a Proj */
713                         return new_op;
714                 }
715                 else if (imm_op) {
716                         /* This is expr - const */
717                         new_op = gen_imm_Sub(env, expr_op, imm_op);
718
719                         /* set AM support */
720                         set_ia32_am_support(new_op, ia32_am_Dest);
721                 }
722                 else {
723                         /* This is a normal sub */
724                         new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
725
726                         /* set AM support */
727                         set_ia32_am_support(new_op, ia32_am_Full);
728                 }
729         }
730
731         return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
732 }
733
734
735
736 /**
737  * Generates an ia32 DivMod with additional infrastructure for the
738  * register allocator if needed.
739  *
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
745  */
746 static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
747         ir_node  *res, *proj;
748         ir_node  *edx_node, *cltd;
749         ir_node  *in_keep[1];
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;
755         ir_node  *mem;
756
757         switch (dm_flav) {
758                 case flavour_Div:
759                         mem = get_Div_mem(irn);
760                         break;
761                 case flavour_Mod:
762                         mem = get_Mod_mem(irn);
763                         break;
764                 case flavour_DivMod:
765                         mem = get_DivMod_mem(irn);
766                         break;
767                 default:
768                         assert(0);
769         }
770
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);
776         }
777         else {
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));
781         }
782
783         res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode);
784
785         set_ia32_flavour(res, dm_flav);
786         set_ia32_n_res(res, 2);
787
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");
794
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);
797                 }
798                 else {
799                         in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
800                 }
801
802                 be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
803         }
804
805         return res;
806 }
807
808
809 /**
810  * Wrapper for generate_DivMod. Sets flavour_Mod.
811  */
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);
814 }
815
816
817
818 /**
819  * Wrapper for generate_DivMod. Sets flavour_Div.
820  */
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);
823 }
824
825
826
827 /**
828  * Wrapper for generate_DivMod. Sets flavour_DivMod.
829  */
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);
832 }
833
834
835
836 /**
837  * Creates an ia32 floating Div.
838  *
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
843  */
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);
847         ir_node *new_op;
848
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);
851
852         return new_op;
853 }
854
855
856
857 /**
858  * Creates an ia32 Shl.
859  *
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
864  */
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);
867 }
868
869
870
871 /**
872  * Creates an ia32 Shr.
873  *
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
878  */
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);
881 }
882
883
884
885 /**
886  * Creates an ia32 Shrs.
887  *
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
892  */
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);
895 }
896
897
898
899 /**
900  * Creates an ia32 RotL.
901  *
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
906  */
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);
909 }
910
911
912
913 /**
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.
917  *
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
922  */
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);
925 }
926
927
928
929 /**
930  * Creates an ia32 RotR or RotL (depending on the found pattern).
931  *
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
936  */
937 static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
938         ir_node *rotate = NULL;
939
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 */
943
944         if (is_Proj(op2)) {
945                 ir_node *pred = get_Proj_pred(op2);
946
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);
951
952                         if (is_Proj(pred_pred)) {
953                                 pred_pred = get_Proj_pred(pred_pred);
954                         }
955
956                         if (is_ia32_Minus(pred_pred) &&
957                                 tarval_is_long(tv)       &&
958                                 get_tarval_long(tv) == bits)
959                         {
960                                 DB((env->mod, LEVEL_1, "RotL into RotR ... "));
961                                 rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
962                         }
963
964                 }
965         }
966
967         if (!rotate) {
968                 rotate = gen_RotL(env, op1, op2);
969         }
970
971         return rotate;
972 }
973
974
975
976 /**
977  * Transforms a Conv node.
978  *
979  * @param env   The transformation environment
980  * @param op    The operator
981  * @return The created ia32 Conv node
982  */
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);
985 }
986
987
988
989 /**
990  * Transforms a Minus node.
991  *
992  * @param env   The transformation environment
993  * @param op    The operator
994  * @return The created ia32 Minus node
995  */
996 static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
997         char    *name;
998         ir_node *new_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);
1002         int      size;
1003
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);
1006
1007                 size   = get_mode_size_bits(env->mode);
1008                 name   = gen_fp_known_const(env->mode, size == 32 ? ia32_SSIGN : ia32_DSIGN);
1009
1010                 set_ia32_sc(new_op, name);
1011
1012                 new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
1013         }
1014         else {
1015                 new_op = gen_unop(env, op, new_rd_ia32_Minus);
1016         }
1017
1018         return new_op;
1019 }
1020
1021
1022
1023 /**
1024  * Transforms a Not node.
1025  *
1026  * @param env   The transformation environment
1027  * @param op    The operator
1028  * @return The created ia32 Not node
1029  */
1030 static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
1031         ir_node *new_op;
1032
1033         if (mode_is_float(env->mode)) {
1034                 assert(0);
1035         }
1036         else {
1037                 new_op = gen_unop(env, op, new_rd_ia32_Not);
1038         }
1039
1040         return new_op;
1041 }
1042
1043
1044
1045 /**
1046  * Transforms an Abs node.
1047  *
1048  * @param env   The transformation environment
1049  * @param op    The operator
1050  * @return The created ia32 Abs node
1051  */
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();
1061         int       size;
1062         char     *name;
1063
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);
1066
1067                 size   = get_mode_size_bits(mode);
1068                 name   = gen_fp_known_const(mode, size == 32 ? ia32_SABS : ia32_DABS);
1069
1070                 set_ia32_sc(res, name);
1071
1072                 res = new_rd_Proj(dbg, irg, block, res, mode, 0);
1073         }
1074         else {
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);
1082         }
1083
1084         return res;
1085 }
1086
1087
1088
1089 /**
1090  * Transforms a Load.
1091  *
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
1097  */
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);
1101         ir_node *new_op;
1102
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);
1105         }
1106         else {
1107                 new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
1108         }
1109
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));
1114
1115         return new_op;
1116 }
1117
1118
1119
1120 /**
1121  * Transforms a Store.
1122  *
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
1128  */
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;
1136         ir_node *new_op;
1137
1138         /* in case of storing a const -> make it an attribute */
1139         if (is_ia32_Cnst(val)) {
1140                 sval = noreg;
1141         }
1142
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);
1145         }
1146         else {
1147                 new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode);
1148         }
1149
1150         /* stored const is an attribute (saves a register) */
1151         if (is_ia32_Cnst(val)) {
1152                 set_ia32_Immop_attr(new_op, val);
1153         }
1154
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));
1159         return new_op;
1160 }
1161
1162
1163
1164 /**
1165  * Transforms a Call and its arguments corresponding to the calling convention.
1166  *
1167  * @param env   The transformation environment
1168  * @return The created ia32 Call node
1169  */
1170 static ir_node *gen_Call(ia32_transform_env_t *env) {
1171 }
1172
1173
1174
1175 /**
1176  * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
1177  *
1178  * @param env   The transformation environment
1179  * @return The transformed node.
1180  */
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;
1193
1194         if (is_Proj(sel) && sel_mode == mode_b) {
1195                 pred  = get_Proj_pred(sel);
1196
1197                 /* get both compare operators */
1198                 cmp_a = get_Cmp_left(pred);
1199                 cmp_b = get_Cmp_right(pred);
1200
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);
1204
1205                 if (cnst && expr) {
1206                         res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T);
1207                         set_ia32_Immop_attr(res, cnst);
1208                 }
1209                 else {
1210                         res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T);
1211                 }
1212
1213                 set_ia32_pncode(res, get_Proj_proj(sel));
1214         }
1215         else {
1216                 res = new_rd_ia32_SwitchJmp(dbg, irg, block, noreg, noreg, sel, nomem, mode_T);
1217                 set_ia32_pncode(res, get_Cond_defaultProj(node));
1218         }
1219
1220         return res;
1221 }
1222
1223
1224
1225 /**
1226  * Transforms a CopyB node.
1227  *
1228  * @param env   The transformation environment
1229  * @return The transformed node.
1230  */
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));
1243         int       rem;
1244
1245         /* If we have to copy more than 16 bytes, we use REP MOVSx and */
1246         /* then we need the size explicitly in ECX.                    */
1247         if (size >= 16) {
1248                 rem = size & 0x3; /* size % 4 */
1249                 size >>= 2;
1250
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));
1254
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));
1257         }
1258         else {
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));
1261         }
1262
1263         return res;
1264 }
1265
1266
1267
1268 /**
1269  * Transforms a Mux node into CMov.
1270  *
1271  * @param env   The transformation environment
1272  * @return The transformed node.
1273  */
1274 static ir_node *gen_Mux(ia32_transform_env_t *env) {
1275         ir_node  *node  = env->irn;
1276
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);
1279 }
1280
1281
1282
1283 /*********************************************************
1284  *                  _             _      _
1285  *                 (_)           | |    (_)
1286  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1287  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1288  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1289  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1290  *
1291  *********************************************************/
1292
1293
1294
1295 /**
1296  * Transforms the given firm node (and maybe some other related nodes)
1297  * into one or more assembler nodes.
1298  *
1299  * @param node    the firm node
1300  * @param env     the debug module
1301  */
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;
1307
1308         if (is_Block(node))
1309                 return;
1310
1311         tenv.block    = get_nodes_block(node);
1312         tenv.dbg      = get_irn_dbg_info(node);
1313         tenv.irg      = current_ir_graph;
1314         tenv.irn      = node;
1315         tenv.mod      = cgenv->mod;
1316         tenv.mode     = get_irn_mode(node);
1317         tenv.cg       = cgenv;
1318
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
1324
1325         DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
1326
1327         switch (code) {
1328                 BINOP(Add);
1329                 BINOP(Sub);
1330                 BINOP(Mul);
1331                 BINOP(And);
1332                 BINOP(Or);
1333                 BINOP(Eor);
1334
1335                 BINOP(Shl);
1336                 BINOP(Shr);
1337                 BINOP(Shrs);
1338
1339                 BINOP(Quot);
1340
1341                 BINOP(Div);
1342                 BINOP(Mod);
1343                 BINOP(DivMod);
1344
1345                 UNOP(Minus);
1346                 UNOP(Conv);
1347                 UNOP(Abs);
1348                 UNOP(Not);
1349
1350                 GEN(Load);
1351                 GEN(Store);
1352                 GEN(Cond);
1353
1354                 GEN(CopyB);
1355                 GEN(Mux);
1356
1357                 IGN(Call);
1358                 IGN(Alloc);
1359
1360                 IGN(Proj);
1361                 IGN(Block);
1362                 IGN(Start);
1363                 IGN(End);
1364                 IGN(NoMem);
1365                 IGN(Phi);
1366                 IGN(IJmp);
1367                 IGN(Break);
1368                 IGN(Cmp);
1369                 IGN(Unknown);
1370                 /* constant transformation happens earlier */
1371                 IGN(Const);
1372                 IGN(SymConst);
1373                 IGN(Sync);
1374
1375                 BAD(Raise);
1376                 BAD(Sel);
1377                 BAD(InstOf);
1378                 BAD(Cast);
1379                 BAD(Free);
1380                 BAD(Tuple);
1381                 BAD(Id);
1382                 BAD(Bad);
1383                 BAD(Confirm);
1384                 BAD(Filter);
1385                 BAD(CallBegin);
1386                 BAD(EndReg);
1387                 BAD(EndExcept);
1388
1389                 default:
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));
1392                         }
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));
1395                         }
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));
1398                         }
1399                         break;
1400 bad:
1401                 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1402                 assert(0);
1403         }
1404
1405         if (asm_node) {
1406                 exchange(node, asm_node);
1407                 DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1408         }
1409         else {
1410                 DB((tenv.mod, LEVEL_1, "ignored\n"));
1411         }
1412 }