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