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