5e0712ce1aa0625b944e1eaf82b0849b2cc42d0a
[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                         DBG((env->mod, LEVEL_2, "optimizing 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                         DBG((mod, LEVEL_2, "optimizing 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                         DBG((mod, LEVEL_2, "optimizing 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                         DBG((mod, LEVEL_2, "optimizing 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   = get_DivMod_mem(irn);
492
493         if (mode_is_signed(mode)) {
494                 /* in signed mode, we need to sign extend the dividend */
495                 cltd     = new_rd_ia32_Cltd(dbg, irg, block, dividend, mode_T);
496                 dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX);
497                 edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX);
498         }
499         else {
500                 edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
501                 set_ia32_Const_type(edx_node, asmop_Const);
502                 set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
503         }
504
505         res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode);
506
507         set_ia32_flavour(res, dm_flav);
508         set_ia32_n_res(res, 2);
509
510         /* Only one proj is used -> We must add a second proj and */
511         /* connect this one to a Keep node to eat up the second   */
512         /* destroyed register.                                    */
513         if (get_irn_n_edges(irn) == 1) {
514                 proj = get_edge_src_irn(get_irn_out_edge_first(irn));
515                 assert(is_Proj(proj) && "non-Proj to Div/Mod node");
516
517                 if (get_Proj_proj(proj) == pn_DivMod_res_div) {
518                         in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_mod);
519                 }
520                 else {
521                         in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
522                 }
523
524                 be_new_Keep(&ia32_reg_classes[CLASS_ia32_general_purpose], irg, block, 1, in_keep);
525         }
526
527         return res;
528 }
529
530
531 /**
532  * Wrapper for generate_DivMod. Sets flavour_Mod.
533  */
534 static ir_node *gen_Mod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
535         return generate_DivMod(env, op1, op2, flavour_Mod);
536 }
537
538
539
540 /**
541  * Wrapper for generate_DivMod. Sets flavour_Div.
542  */
543 static ir_node *gen_Div(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
544         return generate_DivMod(env, op1, op2, flavour_Div);
545 }
546
547
548
549 /**
550  * Wrapper for generate_DivMod. Sets flavour_DivMod.
551  */
552 static ir_node *gen_DivMod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
553         return generate_DivMod(env, op1, op2, flavour_DivMod);
554 }
555
556
557
558 /**
559  * Creates an ia32 floating Div.
560  *
561  * @param dbg       firm node dbg
562  * @param block     the block the new node should belong to
563  * @param op1       first operator
564  * @param op2       second operator
565  * @param mode      node mode
566  * @return the created ia32 fDiv node
567  */
568 static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
569         return new_rd_ia32_fDiv(env->dbg, env->irg, env->block, op1, op2, env->mode);
570 }
571
572
573
574 /**
575  * Creates an ia32 Shl with immediate.
576  *
577  * @param dbg       firm dbg
578  * @param block     the block the new node should belong to
579  * @param expr_op   operator
580  * @param mode      node mode
581  * @return the created ia23 Shl_i node
582  */
583 static ir_node *gen_imm_Shl(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
584         return new_rd_ia32_Shl_i(env->dbg, env->irg, env->block, expr_op, env->mode);
585 }
586
587 /**
588  * Creates an ia32 Shl.
589  *
590  * @param dbg       firm node dbg
591  * @param block     the block the new node should belong to
592  * @param op1       first operator
593  * @param op2       second operator
594  * @param mode      node mode
595  * @return the created ia32 Shl node
596  */
597 static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
598         return new_rd_ia32_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode);
599 }
600
601
602
603 /**
604  * Creates an ia32 Shr with immediate.
605  *
606  * @param dbg       firm dbg
607  * @param block     the block the new node should belong to
608  * @param expr_op   operator
609  * @param mode      node mode
610  * @return the created ia23 Shr_i node
611  */
612 static ir_node *gen_imm_Shr(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
613         return new_rd_ia32_Shr_i(env->dbg, env->irg, env->block, expr_op, env->mode);
614 }
615
616 /**
617  * Creates an ia32 Shr.
618  *
619  * @param dbg       firm node dbg
620  * @param block     the block the new node should belong to
621  * @param op1       first operator
622  * @param op2       second operator
623  * @param mode      node mode
624  * @return the created ia32 Shr node
625  */
626 static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
627         return new_rd_ia32_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode);
628 }
629
630
631
632 /**
633  * Creates an ia32 Shrs with immediate.
634  *
635  * @param dbg       firm dbg
636  * @param block     the block the new node should belong to
637  * @param expr_op   operator
638  * @param mode      node mode
639  * @return the created ia23 Shrs_i node
640  */
641 static ir_node *gen_imm_Shrs(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
642         return new_rd_ia32_Shrs_i(env->dbg, env->irg, env->block, expr_op, env->mode);
643 }
644
645 /**
646  * Creates an ia32 Shrs.
647  *
648  * @param dbg       firm node dbg
649  * @param block     the block the new node should belong to
650  * @param op1       first operator
651  * @param op2       second operator
652  * @param mode      node mode
653  * @return the created ia32 Shrs node
654  */
655 static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
656         return new_rd_ia32_Shrs(env->dbg, env->irg, env->block, op1, op2, env->mode);
657 }
658
659
660
661 /**
662  * Creates an ia32 RotL.
663  *
664  * @param dbg       firm node dbg
665  * @param block     the block the new node should belong to
666  * @param op1       first operator
667  * @param op2       second operator
668  * @param mode      node mode
669  * @return the created ia32 RotL node
670  */
671 static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
672         return new_rd_ia32_RotL(env->dbg, env->irg, env->block, op1, op2, env->mode);
673 }
674
675
676
677 /**
678  * Creates an ia32 RotR.
679  * NOTE: There is no RotR with immediate because this would always be a RotL
680  *       "imm-mode_size_bits" which can be pre-calculated.
681  *
682  * @param dbg       firm node dbg
683  * @param block     the block the new node should belong to
684  * @param op1       first operator
685  * @param op2       second operator
686  * @param mode      node mode
687  * @return the created ia32 RotR node
688  */
689 static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
690         return new_rd_ia32_RotR(env->dbg, env->irg, env->block, op1, op2, env->mode);
691 }
692
693
694
695 /**
696  * Transforms a Rot with immediate into an ia32 RotL with immediate
697  * as the Firm Rot is a RotL (see NOTE on RotR with immediate above).
698  *
699  * @param dbg       firm node dbg
700  * @param block     the block the new node should belong to
701  * @param op1       first operator
702  * @param op2       second operator
703  * @param mode      node mode
704  * @return the created ia32 RotL node
705  */
706 static ir_node *gen_imm_Rot(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
707         return new_rd_ia32_RotL_i(env->dbg, env->irg, env->block, expr_op, env->mode);
708 }
709
710 /**
711  * Creates an ia32 RotR or RotL (depending on the found pattern).
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 or RotR node
719  */
720 static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
721         ir_node *rotate = NULL;
722
723         /* Firm has only Rot (which is a RotL), so we are looking for a right (op2)
724                  operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
725                  that means we can create a RotR instead of an Add and a RotL */
726
727         if (is_ia32_Add_i(op2)) {
728                 ir_node *minus = get_irn_n(op2, 0); // is there an op_Minus?
729
730                 if (is_ia32_Minus(minus)) {
731                         tarval *tv = get_ia32_Immop_tarval(op2);
732                         long bits  = get_mode_size_bits(env->mode);
733
734                         if (tarval_is_long(tv) && get_tarval_long(tv) == bits) {
735                                 DBG((env->mod, LEVEL_1, "optimizing RotL into RotR ... "));
736                                 rotate = gen_RotR(env, op1, get_irn_n(minus, 0));
737                         }
738                 }
739         }
740
741         if (!rotate)
742                 rotate = gen_RotL(env, op1, op2);
743
744         return rotate;
745 }
746
747
748
749 /**
750  * Transforms commutative operations (op_Add, op_And, op_Or, op_Eor)
751  * and non-commutative operations with com == 0 (op_Sub, op_Shl, op_Shr, op_Shrs, op_Rot)
752  *
753  * @param mod       the debug module
754  * @param block     the block node belongs to
755  * @param node      the node to transform
756  * @param op1       first operator
757  * @param op2       second operator
758  * @param mode      node mode
759  * @param com       flag if op is commutative
760  * @return the created assembler node
761  */
762 static ir_node *gen_arith_Op(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, int com) {
763         firm_dbg_module_t *mod      = env->mod;
764         ir_node           *node     = env->irn;
765         ir_node           *imm_op   = NULL;
766         ir_node           *expr_op  = NULL;
767         ir_node           *asm_node = NULL;
768         opcode             opc      = get_irn_opcode(node);
769         ir_op             *op       = get_irn_op(node);
770
771 #undef GENOP
772 #undef GENOPI
773 #undef GENOPI_SETATTR
774 #define GENOP(a)          case iro_##a: asm_node = gen_##a(env, op1, op2); break
775 #define GENOPI(a)         case iro_##a: asm_node = gen_imm_##a(env, expr_op, imm_op); break
776 #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
777
778         if (com)
779                 imm_op  = get_immediate_op(op1, op2);
780         else
781                 imm_op  = get_immediate_op(NULL, op2);
782
783         expr_op = get_expr_op(op1, op2);
784
785         /* TODO: Op(Const, Const) support */
786         if (is_ia32_Const(op1) && is_ia32_Const(op2)) {
787                 DBG((mod, LEVEL_2, "found unexpected %s(Const, Const), creating binop ... ", get_irn_opname(node)));
788                 imm_op = NULL;
789         }
790
791         /* There are arithmetic operations which can't take an immediate */
792         switch(opc) {
793                 case iro_Div:
794                 case iro_Mod:
795                 case iro_DivMod:
796                         DBG((mod, LEVEL_2, "Div/Mod/DivMod imm not available, creating binop ... "));
797                         imm_op = NULL;
798                         break;
799                 default:
800                         if (op == get_op_Min() || op == get_op_Max()) {
801                                 DBG((mod, LEVEL_2, "MIN/MAX imm not available, creating binop ... "));
802                                 imm_op = NULL;
803                         }
804                         break;
805         }
806
807         DBG((mod, LEVEL_1, "(op1: %s -- op2: %s) ... ", get_irn_opname(op1), get_irn_opname(op2)));
808
809         if (!mode_is_float(env->mode) && imm_op) {
810                 DBG((mod, LEVEL_1, "%s with imm ... ", get_irn_opname(node)));
811
812                 switch(opc) {
813                         GENOPI_SETATTR(Add);
814                         GENOPI(Mul);
815                         GENOPI_SETATTR(And);
816                         GENOPI_SETATTR(Or);
817                         GENOPI_SETATTR(Eor);
818
819                         GENOPI_SETATTR(Sub);
820                         GENOPI_SETATTR(Shl);
821                         GENOPI_SETATTR(Shr);
822                         GENOPI_SETATTR(Shrs);
823                         GENOPI_SETATTR(Rot);
824                         default:
825                                 if (op == get_op_Mulh()) {
826                                         asm_node = gen_imm_Mulh(env, expr_op, imm_op);
827                                 }
828                                 else {
829                                         assert("binop_i: THIS SHOULD NOT HAPPEN");
830                                 }
831                 }
832         }
833         else {
834                 DBG((mod, LEVEL_1, "%s as binop ... ", get_irn_opname(node)));
835
836                 switch(opc) {
837                         GENOP(Add);
838                         GENOP(Mul);
839                         GENOP(And);
840                         GENOP(Or);
841                         GENOP(Eor);
842
843                         GENOP(Quot);
844
845                         GENOP(Div);
846                         GENOP(Mod);
847                         GENOP(DivMod);
848
849                         GENOP(Sub);
850                         GENOP(Shl);
851                         GENOP(Shr);
852                         GENOP(Shrs);
853                         GENOP(Rot);
854                         default:
855                                 if (op == get_op_Max()) {
856                                         asm_node = gen_Max(env, op1, op2);
857                                 }
858                                 else if (op == get_op_Min()) {
859                                         asm_node = gen_Min(env, op1, op2);
860                                 }
861                                 else if (op == get_op_Mulh()) {
862                                         asm_node = gen_Mulh(env, op1, op2);
863                                 }
864                                 else {
865                                         assert("binop: THIS SHOULD NOT HAPPEN");
866                                 }
867                 }
868         }
869
870         return asm_node;
871 }
872 #undef GENOP
873 #undef GENOPI
874 #undef GENOPI_SETATTR
875
876
877
878 /**
879  * Transforms a Minus node.
880  *
881  * @param mod     the debug module
882  * @param block   the block the new node should belong to
883  * @param node    the ir Minus node
884  * @param op      operator
885  * @param mode    node mode
886  * @return the created ia32 Minus node
887  */
888 static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
889         if (is_ia32_Minus(op) || is_ia32_fMinus(op)) {
890                 DBG((env->mod, LEVEL_1, "optimizing --(e) to e ..."));
891                 return get_irn_n(op, 0);
892         }
893         else {
894                 if (mode_is_float(env->mode)) {
895                         return new_rd_ia32_fMinus(env->dbg, env->irg, env->block, op, env->mode);
896                 }
897                 return new_rd_ia32_Minus(env->dbg, env->irg, env->block, op, env->mode);
898         }
899 }
900
901
902
903 /**
904  * Transforms a Conv node.
905  *
906  * @param mod     the debug module
907  * @param block   the block the new node should belong to
908  * @param node    the ir Conv node
909  * @param op      operator
910  * @param mode    node mode
911  * @return the created ia32 Conv node
912  */
913 static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
914         return new_rd_ia32_Conv(env->dbg, env->irg, env->block, op, env->mode);
915 }
916
917
918
919 /**
920  * Transforms a Not node.
921  *
922  * @param mod     the debug module
923  * @param block   the block the new node should belong to
924  * @param node    the ir Not node
925  * @param op      operator
926  * @param mode    node mode
927  * @return the created ia32 Not node
928  */
929 static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
930         return new_rd_ia32_Not(env->dbg, env->irg, env->block, op, env->mode);
931 }
932
933
934
935 /**
936  * Transforms an Abs node.
937  *
938  * @param mod     the debug module
939  * @param block   the block the new node should belong to
940  * @param node    the ir Abs node
941  * @param op      operator
942  * @param mode    node mode
943  * @return the created ia32 Abs node
944  */
945 static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
946         ir_node  *res, *p_eax, *p_edx;
947         dbg_info *dbg   = env->dbg;
948         ir_mode  *mode  = env->mode;
949         ir_graph *irg   = env->irg;
950         ir_node  *block = env->block;
951
952         res   = new_rd_ia32_Cltd(dbg, irg, block, op, mode_T);
953         p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
954         p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
955         res   = new_rd_ia32_Eor(dbg, irg, block, p_eax, p_edx, mode);
956         res   = new_rd_ia32_Sub(dbg, irg, block, res, p_edx, mode);
957
958         return res;
959 }
960
961
962
963 /**
964  * Transforms a Load.
965  *
966  * @param mod     the debug module
967  * @param block   the block the new node should belong to
968  * @param node    the ir Load node
969  * @param mode    node mode
970  * @return the created ia32 Load node
971  */
972 static ir_node *gen_Load(ia32_transform_env_t *env) {
973         ir_node *node = env->irn;
974
975         if (mode_is_float(env->mode)) {
976                 return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
977         }
978         return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
979 }
980
981
982
983 /**
984  * Transforms a Store.
985  *
986  * @param mod     the debug module
987  * @param block   the block the new node should belong to
988  * @param node    the ir Store node
989  * @param mode    node mode
990  * @return the created ia32 Store node
991  */
992 ir_node *gen_Store(ia32_transform_env_t *env) {
993         ir_node *node = env->irn;
994
995         if (mode_is_float(env->mode)) {
996                 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);
997         }
998         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);
999 }
1000
1001
1002
1003 /**
1004  * Transforms a Call and its arguments corresponding to the calling convention.
1005  *
1006  * @param mod     the debug module
1007  * @param block   the block the new node should belong to
1008  * @param node    the ir Call node
1009  * @param dummy   mode doesn't matter
1010  * @return the created ia32 Call node
1011  */
1012 static ir_node *gen_Call(ia32_transform_env_t *env) {
1013         const ia32_register_req_t **in_req;
1014         ir_node          **in;
1015         ir_node           *new_call, *sync;
1016         int                i, j, n_new_call_in, ignore = 0;
1017         asmop_attr        *attr;
1018         dbg_info          *dbg          = env->dbg;
1019         ir_graph          *irg          = env->irg;
1020         ir_node           *block        = env->block;
1021         ir_node           *call         = env->irn;
1022         ir_node          **stack_param  = NULL;
1023         ir_node          **param        = get_Call_param_arr(call);
1024         ir_node           *call_Mem     = get_Call_mem(call);
1025         unsigned           cc           = get_method_calling_convention(get_Call_type(call));
1026         int                n            = get_Call_n_params(call);
1027         int                stack_idx    = 0;
1028         int                biggest_n    = -1;
1029
1030         if (cc & cc_reg_param)
1031                 biggest_n = ia32_get_n_regparam_class(n, param, &ignore, &ignore);
1032
1033         /* remember: biggest_n = x means we can pass (x + 1) parameters in register */
1034
1035         /* do we need to pass arguments on stack? */
1036         if (biggest_n + 1 < n)
1037                 stack_param = calloc(n - biggest_n - 1, sizeof(ir_node *));
1038
1039         /* we need at least one in, either for the stack params or the call_Mem */
1040         n_new_call_in = biggest_n + 2;
1041
1042         /* the call has one IN for all stack parameter and one IN for each reg param */
1043         in     = calloc(n_new_call_in, sizeof(ir_node *));
1044         in_req = calloc(n_new_call_in, sizeof(arch_register_req_t *));
1045
1046         /* loop over all parameters and set the register requirements */
1047         for (i = 0; i <= biggest_n && (cc & cc_reg_param); i++) {
1048                 in_req[i] = ia32_get_RegParam_req(n, param, i, cc);
1049         }
1050         stack_idx = i;
1051
1052         /* create remaining stack parameters */
1053         if (cc & cc_last_on_top) {
1054                 for (i = stack_idx; i < n; i++) {
1055                         /* pass it on stack */
1056                         if (mode_is_float(get_irn_mode(param[i]))) {
1057                                 stack_param[i - stack_idx] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg,
1058                                                                                                                 block, call_Mem, param[i], mode_M);
1059                         }
1060                         else {
1061                                 stack_param[i - stack_idx] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg,
1062                                                                                                                 block, call_Mem, param[i], mode_M);
1063                         }
1064                 }
1065         }
1066         else {
1067                 for (i = n - 1, j = 0; i >= stack_idx; i--, j++) {
1068                         /* pass it on stack */
1069                         if (mode_is_float(get_irn_mode(param[i]))) {
1070                                 stack_param[j] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg,
1071                                                                                                                 block, call_Mem, param[i], mode_M);
1072                         }
1073                         else {
1074                                 stack_param[j] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg,
1075                                                                                                                 block, call_Mem, param[i], mode_M);
1076                         }
1077                 }
1078         }
1079
1080         if (stack_param) {
1081                 sync = new_r_Sync(irg, block, n - biggest_n - 1, stack_param);
1082                 in[n_new_call_in - 1] = sync;
1083         }
1084         else {
1085                 in[n_new_call_in - 1] = call_Mem;
1086         }
1087
1088         /* create the new node */
1089         new_call = new_rd_ia32_Call(dbg, irg, block, n_new_call_in, in);
1090         set_ia32_Immop_attr(new_call, get_Call_ptr(call));
1091         set_ia32_n_res(new_call, 1);
1092
1093         /* set register requirements for in and out */
1094         attr             = get_ia32_attr(new_call);
1095         attr->in_req     = in_req;
1096         attr->out_req    = calloc(2, sizeof(ia32_register_req_t *));
1097         attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
1098         attr->out_req[1] = &ia32_default_req_ia32_general_purpose_edx;
1099         attr->slots      = calloc(2, sizeof(arch_register_t *));
1100
1101         /* stack parameter has no OUT register */
1102         attr->in_req[n_new_call_in - 1] = &ia32_default_req_none;
1103
1104         return new_call;
1105 }
1106
1107
1108
1109 /**
1110  * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
1111  *
1112  * @param mod     the debug module
1113  * @param block   the block the new node should belong to
1114  * @param node    the ir Cond node
1115  * @param mode    mode of the Cond
1116  * @return The transformed node.
1117  */
1118 static ir_node *gen_Cond(ia32_transform_env_t *env) {
1119         dbg_info          *dbg      = env->dbg;
1120         ir_graph          *irg      = env->irg;
1121         ir_node           *block    = env->block;
1122         ir_node           *node     = env->irn;
1123         ir_node           *sel      = get_Cond_selector(node);
1124         ir_mode           *sel_mode = get_irn_mode(sel);
1125         ir_node           *res      = NULL;
1126         ir_node           *pred     = NULL;
1127         ir_node           *cmp_a, *cmp_b, *cnst, *expr;
1128
1129         if (is_Proj(sel) && sel_mode == mode_b) {
1130                 pred  = get_Proj_pred(sel);
1131
1132                 /* get both compare operators */
1133                 cmp_a = get_Cmp_left(pred);
1134                 cmp_b = get_Cmp_right(pred);
1135
1136                 /* check if we can use a CondJmp with immediate */
1137                 cnst = get_immediate_op(cmp_a, cmp_b);
1138                 expr = get_expr_op(cmp_a, cmp_b);
1139
1140                 if (cnst && expr) {
1141                         res = new_rd_ia32_CondJmp_i(dbg, irg, block, expr, mode_T);
1142                         set_ia32_Immop_attr(res, cnst);
1143                 }
1144                 else {
1145                         res = new_rd_ia32_CondJmp(dbg, irg, block, cmp_a, cmp_b, mode_T);
1146                 }
1147
1148                 set_ia32_pncode(res, get_Proj_proj(sel));
1149         }
1150         else {
1151                 res = new_rd_ia32_SwitchJmp(dbg, irg, block, sel, mode_T);
1152                 set_ia32_pncode(res, get_Cond_defaultProj(node));
1153         }
1154
1155         return res;
1156 }
1157
1158
1159
1160 /**
1161  * Transform the argument projs from a start node corresponding to the
1162  * calling convention.
1163  * It transforms "Proj Arg x -> ProjT -> Start <- ProjM" into
1164  * "RegParam x   -> ProjT -> Start" OR
1165  * "StackParam x -> ProjM -> Start"
1166  * whether parameter is passed in register or on stack.
1167  *
1168  * @param mod     the debug module
1169  * @param block   the block the nodes should belong to
1170  * @param proj    the ProjT node which points to Start
1171  * @param start   the Start node
1172  * @return Should be always NULL
1173  */
1174 static ir_node *gen_Proj_Start(ia32_transform_env_t *env, ir_node *proj, ir_node *start) {
1175         const ia32_register_req_t *temp_req;
1176         const ir_edge_t   *edge;
1177         ir_node           *succ, *irn;
1178         ir_node          **projargs;
1179         ir_mode           *mode;
1180         int                n, i;
1181         unsigned           cc;
1182         ir_node           *proj_M     = get_irg_initial_mem(current_ir_graph);
1183         entity            *irg_ent    = get_irg_entity(current_ir_graph);
1184         ir_type           *tp         = get_entity_type(irg_ent);
1185         int                cur_pn     = 0;
1186         ir_graph          *irg        = env->irg;
1187         ir_node           *block      = env->block;
1188
1189         assert(is_Method_type(tp) && "irg type is not a method");
1190
1191         switch(get_Proj_proj(proj)) {
1192                 case pn_Start_T_args:
1193                         /* We cannot use get_method_n_params here as the function might
1194                            be variadic or one argument is not used. */
1195                         n = get_irn_n_edges(proj);
1196
1197                         /* Allocate memory for all non variadic parameters in advance to be on the save side */
1198                         env->cg->reg_param_req = calloc(get_method_n_params(tp), sizeof(ia32_register_req_t *));
1199
1200                         /* we are done here when there are no parameters */
1201                         if (n < 1)
1202                                 break;
1203
1204                         /* temporary remember all proj arg x */
1205                         projargs = calloc(n, sizeof(ir_node *));
1206
1207                         i = 0;
1208                         foreach_out_edge((const ir_node *)proj, edge) {
1209                                 succ = get_edge_src_irn(edge);
1210                                 assert(is_Proj(succ) && "non-Proj from a Proj_T (pn_Start_T_args).");
1211                                 projargs[i++] = succ;
1212                         }
1213
1214                         cc = get_method_calling_convention(tp);
1215
1216                         /* loop over all parameters and check whether its a int or float */
1217                         for (i = 0; i < n; i++) {
1218                                 mode   = get_irn_mode(projargs[i]);
1219                                 cur_pn = get_Proj_proj(projargs[i]);
1220
1221                                 if (cc & cc_reg_param) {
1222                                         temp_req = ia32_get_RegParam_req(n, projargs, cur_pn, cc);
1223                                 }
1224                                 else {
1225                                         temp_req = NULL;
1226                                 }
1227
1228                                 if (temp_req) {
1229                                         /* passed in register */
1230                                         env->cg->reg_param_req[cur_pn] = temp_req;
1231                                 }
1232                                 else {
1233                                         /* passed on stack */
1234                                         if (mode_is_float(mode))
1235                                                 irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode);
1236                                         else
1237                                                 irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode);
1238
1239                                         set_ia32_pncode(irn, cur_pn);
1240
1241                                         /* kill the old "Proj Arg" and replace with the new stack param */
1242                                         exchange(projargs[i], irn);
1243                                 }
1244                         }
1245
1246                         free(projargs);
1247
1248                         break;
1249                 case pn_Start_P_frame_base:
1250                 case pn_Start_X_initial_exec:
1251                 case pn_Start_M:
1252                 case pn_Start_P_globals:
1253                 case pn_Start_P_value_arg_base:
1254                         break;
1255                 default:
1256                         assert(0 && "unsupported Proj(Start)");
1257         }
1258
1259         return NULL;
1260 }
1261
1262 /**
1263  * Transform some Proj's (Proj_Proj, Proj_Start, Proj_Cmp, Proj_Cond, Proj_Call).
1264  * All others are ignored.
1265  *
1266  * @param mod     the debug module
1267  * @param block   the block the new node should belong to
1268  * @param node    the ir Proj node
1269  * @param mode    mode of the Proj
1270  * @return The transformed node.
1271  */
1272 static ir_node *gen_Proj(ia32_transform_env_t *env) {
1273         ir_node *new_node  = NULL;
1274         ir_node *pred      = get_Proj_pred(env->irn);
1275
1276         if (env->mode == mode_M)
1277                 return NULL;
1278
1279         if (get_irn_op(pred) == op_Start) {
1280                 new_node = gen_Proj_Start(env, env->irn, pred);
1281         }
1282
1283         return new_node;
1284 }
1285
1286
1287
1288 /*********************************************************
1289  *                  _             _      _
1290  *                 (_)           | |    (_)
1291  *  _ __ ___   __ _ _ _ __     __| |_ __ ___   _____ _ __
1292  * | '_ ` _ \ / _` | | '_ \   / _` | '__| \ \ / / _ \ '__|
1293  * | | | | | | (_| | | | | | | (_| | |  | |\ V /  __/ |
1294  * |_| |_| |_|\__,_|_|_| |_|  \__,_|_|  |_| \_/ \___|_|
1295  *
1296  *********************************************************/
1297
1298
1299
1300 /**
1301  * Transforms the given firm node (and maybe some other related nodes)
1302  * into one or more assembler nodes.
1303  *
1304  * @param node    the firm node
1305  * @param env     the debug module
1306  */
1307 void ia32_transform_node(ir_node *node, void *env) {
1308         ia32_code_gen_t *cgenv = (ia32_code_gen_t *)env;
1309         opcode  code           = get_irn_opcode(node);
1310         ir_node *asm_node      = NULL;
1311         ia32_transform_env_t  tenv;
1312
1313         if (is_Block(node))
1314                 return;
1315
1316         tenv.arch_env = cgenv->arch_env;
1317         tenv.block    = get_nodes_block(node);
1318         tenv.dbg      = get_irn_dbg_info(node);
1319         tenv.irg      = current_ir_graph;
1320         tenv.irn      = node;
1321         tenv.mod      = cgenv->mod;
1322         tenv.mode     = get_irn_mode(node);
1323         tenv.cg       = cgenv;
1324
1325 #define UNOP(a)        case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
1326 #define BINOP(a)       case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
1327 #define BINOP_COM(a)   case iro_##a: asm_node = gen_arith_Op(&tenv, get_##a##_left(node), get_##a##_right(node), 1); break
1328 #define BINOP_NCOM(a)  case iro_##a: asm_node = gen_arith_Op(&tenv, get_##a##_left(node), get_##a##_right(node), 0); break
1329 #define GEN(a)         case iro_##a: asm_node = gen_##a(&tenv); break
1330 #define IGN(a)         case iro_##a: break
1331 #define BAD(a)         case iro_##a: goto bad
1332
1333         DBG((tenv.mod, LEVEL_1, "transforming node %s (%ld) ... ", get_irn_opname(node), get_irn_node_nr(node)));
1334
1335         switch (code) {
1336                 BINOP_COM(Add);
1337                 BINOP_COM(Mul);
1338                 BINOP_COM(And);
1339                 BINOP_COM(Or);
1340                 BINOP_COM(Eor);
1341
1342                 BINOP_NCOM(Sub);
1343                 BINOP_NCOM(Shl);
1344                 BINOP_NCOM(Shr);
1345                 BINOP_NCOM(Shrs);
1346                 BINOP_NCOM(Quot);
1347                 BINOP_NCOM(Div);
1348                 BINOP_NCOM(Mod);
1349                 BINOP_NCOM(DivMod);
1350
1351                 UNOP(Minus);
1352                 UNOP(Conv);
1353                 UNOP(Abs);
1354                 UNOP(Not);
1355
1356                 GEN(Load);
1357                 GEN(Store);
1358                 GEN(Call);
1359                 GEN(Cond);
1360
1361                 GEN(Proj);
1362
1363                 IGN(Block);
1364                 IGN(Start);
1365                 IGN(End);
1366                 IGN(NoMem);
1367                 IGN(Phi);
1368                 IGN(IJmp);
1369                 IGN(Break);
1370                 IGN(Cmp);
1371                 IGN(Unknown);
1372                 /* constant transformation happens earlier */
1373                 IGN(Const);
1374                 IGN(SymConst);
1375
1376                 BAD(Alloc);
1377                 BAD(Raise);
1378                 BAD(Sel);
1379                 BAD(InstOf);
1380                 BAD(Cast);
1381                 BAD(Free);
1382                 BAD(Sync);
1383                 BAD(Tuple);
1384                 BAD(Id);
1385                 BAD(Bad);
1386                 BAD(Confirm);
1387                 BAD(Filter);
1388                 BAD(CallBegin);
1389                 BAD(EndReg);
1390                 BAD(EndExcept);
1391                 BAD(Mux);
1392                 BAD(CopyB);
1393
1394                 default:
1395                         if (get_irn_op(node) == get_op_Max() ||
1396                                 get_irn_op(node) == get_op_Min() ||
1397                                 get_irn_op(node) == get_op_Mulh())
1398                         {
1399                                 asm_node = gen_arith_Op(&tenv, get_irn_n(node, 0), get_irn_n(node, 1), 1);
1400                         }
1401                         break;
1402 bad:
1403                 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1404                 assert(0);
1405         }
1406
1407         if (asm_node) {
1408                 exchange(node, asm_node);
1409                 DBG((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1410         }
1411         else {
1412                 DBG((tenv.mod, LEVEL_1, "ignored\n"));
1413         }
1414 }