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