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