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