Adapted to recent changes
[libfirm] / ir / be / ia32 / ia32_emitter.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <limits.h>
6
7 #include "tv.h"
8 #include "iredges.h"
9 #include "debug.h"
10 #include "irgwalk.h"
11 #include "irprintf.h"
12 #include "irop_t.h"
13 #include "irargs_t.h"
14
15 #include "../besched.h"
16
17 #include "ia32_emitter.h"
18 #include "gen_ia32_emitter.h"
19 #include "ia32_nodes_attr.h"
20 #include "ia32_new_nodes.h"
21 #include "ia32_map_regs.h"
22
23 #define SNPRINTF_BUF_LEN 128
24
25 static const arch_env_t *arch_env = NULL;
26
27
28 /*************************************************************
29  *             _       _    __   _          _
30  *            (_)     | |  / _| | |        | |
31  *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
32  * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
33  * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
34  * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
35  * | |                                       | |
36  * |_|                                       |_|
37  *************************************************************/
38
39 /**
40  * Return node's tarval as string.
41  */
42 const char *node_const_to_str(ir_node *n) {
43         char   *buf;
44         tarval *tv = get_ia32_Immop_tarval(n);
45
46         if (tv) {
47                 buf = malloc(SNPRINTF_BUF_LEN);
48                 tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
49                 return buf;
50         }
51         else if (get_ia32_old_ir(n)) {
52                 return get_sc_name(get_ia32_old_ir(n));
53         }
54         else
55                 return "0";
56 }
57
58 /**
59  * Returns node's offset as string.
60  */
61 char *node_offset_to_str(ir_node *n) {
62         char   *buf;
63         tarval *tv = get_ia32_am_offs(n);
64
65         if (tv) {
66                 buf = malloc(SNPRINTF_BUF_LEN);
67                 tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
68                 return buf;
69         }
70         else
71                 return "";
72 }
73
74 /* We always pass the ir_node which is a pointer. */
75 static int ia32_get_arg_type(const lc_arg_occ_t *occ) {
76         return lc_arg_type_ptr;
77 }
78
79
80 /**
81  * Returns the register at in position pos.
82  */
83 static const arch_register_t *get_in_reg(ir_node *irn, int pos) {
84         ir_node                *op;
85         const arch_register_t  *reg = NULL;
86
87         assert(get_irn_arity(irn) > pos && "Invalid IN position");
88
89         /* The out register of the operator at position pos is the
90            in register we need. */
91         op = get_irn_n(irn, pos);
92
93         reg = arch_get_irn_register(arch_env, op);
94
95         assert(reg && "no in register found");
96         return reg;
97 }
98
99 /**
100  * Returns the register at out position pos.
101  */
102 static const arch_register_t *get_out_reg(ir_node *irn, int pos) {
103         ir_node                *proj;
104         const arch_register_t  *reg = NULL;
105
106         assert(get_irn_n_edges(irn) > pos && "Invalid OUT position");
107
108         /* 1st case: irn is not of mode_T, so it has only                 */
109         /*           one OUT register -> good                             */
110         /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
111         /*           Proj with the corresponding projnum for the register */
112
113         if (get_irn_mode(irn) != mode_T) {
114                 reg = arch_get_irn_register(arch_env, irn);
115         }
116         else if (is_ia32_irn(irn)) {
117                 reg = get_ia32_out_reg(irn, pos);
118         }
119         else {
120                 const ir_edge_t *edge;
121
122                 foreach_out_edge(irn, edge) {
123                         proj = get_edge_src_irn(edge);
124                         assert(is_Proj(proj) && "non-Proj from mode_T node");
125                         if (get_Proj_proj(proj) == pos) {
126                                 reg = arch_get_irn_register(arch_env, proj);
127                                 break;
128                         }
129                 }
130         }
131
132         assert(reg && "no out register found");
133         return reg;
134 }
135
136 /**
137  * Returns the number of the in register at position pos.
138  */
139 int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) {
140         const arch_register_t *reg;
141         ir_node               *op;
142
143         if (in_out == 1) {
144                 /* special case Proj P_fame_base */
145                 op = get_irn_n(irn, pos);
146                 if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) {
147                         return 10;
148                 }
149
150                 reg = get_in_reg(irn, pos);
151         }
152         else {
153                 reg = get_out_reg(irn, pos);
154         }
155
156         return arch_register_get_index(reg);
157 }
158
159 /**
160  * Returns the name of the in register at position pos.
161  */
162 const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) {
163         const arch_register_t *reg;
164         ir_node               *op;
165
166         if (in_out == 1) {
167                 /* special case Proj P_fame_base */
168                 op = get_irn_n(irn, pos);
169                 if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) {
170                         return "x(esp)";
171                 }
172                 reg = get_in_reg(irn, pos);
173         }
174         else {
175                 reg = get_out_reg(irn, pos);
176         }
177
178         return arch_register_get_name(reg);
179 }
180
181 /**
182  * Get the register name for a node.
183  */
184 static int ia32_get_reg_name(lc_appendable_t *app,
185     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
186 {
187         const char *buf;
188         ir_node    *X  = arg->v_ptr;
189         int         nr = occ->width - 1;
190
191         if (!X)
192                 return lc_arg_append(app, occ, "(null)", 6);
193
194         if (occ->conversion == 'S') {
195                 buf = get_ia32_reg_name(X, nr, 1);
196         }
197         else { /* 'D' */
198                 buf = get_ia32_reg_name(X, nr, 0);
199         }
200
201         lc_appendable_chadd(app, '%');
202         return lc_arg_append(app, occ, buf, strlen(buf));
203 }
204
205 /**
206  * Returns the tarval or offset of an ia32 as a string.
207  */
208 static int ia32_const_to_str(lc_appendable_t *app,
209     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
210 {
211         const char *buf;
212         ir_node    *X = arg->v_ptr;
213
214         if (!X)
215                 return lc_arg_append(app, occ, "(null)", 6);
216
217         if (occ->conversion == 'C') {
218                 buf = node_const_to_str(X);
219         }
220         else { /* 'O' */
221                 buf = node_offset_to_str(X);
222         }
223
224         return lc_arg_append(app, occ, buf, strlen(buf));
225 }
226
227 /**
228  * Determines the SSE suffix depending on the mode.
229  */
230 static int ia32_get_mode_suffix(lc_appendable_t *app,
231     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
232 {
233         ir_node *X = arg->v_ptr;
234
235         if (!X)
236                 return lc_arg_append(app, occ, "(null)", 6);
237
238         if (get_mode_size_bits(get_irn_mode(X)) == 32)
239                 return lc_appendable_chadd(app, 's');
240         else
241                 return lc_appendable_chadd(app, 'd');
242 }
243
244 /**
245  * Return the ia32 printf arg environment.
246  * We use the firm environment with some additional handlers.
247  */
248 const lc_arg_env_t *ia32_get_arg_env(void) {
249         static lc_arg_env_t *env = NULL;
250
251         static const lc_arg_handler_t ia32_reg_handler   = { ia32_get_arg_type, ia32_get_reg_name };
252         static const lc_arg_handler_t ia32_const_handler = { ia32_get_arg_type, ia32_const_to_str };
253         static const lc_arg_handler_t ia32_mode_handler  = { ia32_get_arg_type, ia32_get_mode_suffix };
254
255         if(env == NULL) {
256                 /* extend the firm printer */
257                 env = firm_get_arg_env();
258                         //lc_arg_new_env();
259
260                 lc_arg_register(env, "ia32:sreg", 'S', &ia32_reg_handler);
261                 lc_arg_register(env, "ia32:dreg", 'D', &ia32_reg_handler);
262                 lc_arg_register(env, "ia32:cnst", 'C', &ia32_const_handler);
263                 lc_arg_register(env, "ia32:offs", 'O', &ia32_const_handler);
264                 lc_arg_register(env, "ia32:mode", 'M', &ia32_mode_handler);
265         }
266
267         return env;
268 }
269
270 /**
271  * For 2-address code we need to make sure the first src reg is equal to dest reg.
272  */
273 void equalize_dest_src(FILE *F, ir_node *n) {
274         if (get_ia32_reg_nr(n, 0, 1) != get_ia32_reg_nr(n, 0, 0)) {
275                 if (get_irn_arity(n) > 1 && get_ia32_reg_nr(n, 1, 1) == get_ia32_reg_nr(n, 0, 0)) {
276                         if (! is_op_commutative(get_irn_op(n))) {
277                                 /* we only need to exchange for non-commutative ops */
278                                 lc_efprintf(ia32_get_arg_env(), F, "\txchg %1S, %2S\t\t\t/* xchg src1 <-> src2 for 2 address code */\n", n, n);
279                         }
280                 }
281                 else {
282                         lc_efprintf(ia32_get_arg_env(), F, "\tmovl %1S, %1D\t\t\t/* src -> dest for 2 address code */\n", n, n);
283                 }
284         }
285 }
286
287 /*
288  * Add a number to a prefix. This number will not be used a second time.
289  */
290 char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
291         static unsigned long id = 0;
292         snprintf(buf, buflen, "%s%lu", prefix, ++id);
293         return buf;
294 }
295
296
297 /*************************************************
298  *                 _ _                         _
299  *                (_) |                       | |
300  *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
301  *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
302  * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
303  *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
304  *
305  *************************************************/
306
307 /*
308  * coding of conditions
309  */
310 struct cmp2conditon_t {
311         const char *name;
312         pn_Cmp      num;
313 };
314
315 /*
316  * positive conditions for signed compares
317  */
318 static const struct cmp2conditon_t cmp2condition_s[] = {
319   { NULL,              pn_Cmp_False },  /* always false */
320   { "e",               pn_Cmp_Eq },     /* == */
321   { "l",               pn_Cmp_Lt },     /* < */
322   { "le",              pn_Cmp_Le },     /* <= */
323   { "g",               pn_Cmp_Gt },     /* > */
324   { "ge",              pn_Cmp_Ge },     /* >= */
325   { "ne",              pn_Cmp_Lg },     /* != */
326   { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
327   { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
328   { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
329   { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
330   { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
331   { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
332   { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
333   { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
334   { NULL,              pn_Cmp_True },   /* always true */
335 };
336
337 /*
338  * positive conditions for unsigned compares
339  */
340 static const struct cmp2conditon_t cmp2condition_u[] = {
341   { NULL,              pn_Cmp_False },  /* always false */
342   { "e",               pn_Cmp_Eq },     /* == */
343   { "b",               pn_Cmp_Lt },     /* < */
344   { "be",              pn_Cmp_Le },     /* <= */
345   { "a",               pn_Cmp_Gt },     /* > */
346   { "ae",              pn_Cmp_Ge },     /* >= */
347   { "ne",              pn_Cmp_Lg },     /* != */
348   { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
349   { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
350   { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
351   { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
352   { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
353   { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
354   { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
355   { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
356   { NULL,              pn_Cmp_True },   /* always true */
357 };
358
359 /*
360  * returns the condition code
361  */
362 static const char *get_cmp_suffix(int cmp_code, int unsigned_cmp)
363 {
364         assert(cmp2condition_s[cmp_code].num == cmp_code);
365         assert(cmp2condition_u[cmp_code].num == cmp_code);
366
367         return unsigned_cmp ? cmp2condition_u[cmp_code & 7].name : cmp2condition_s[cmp_code & 7].name;
368 }
369
370 /**
371  * Returns the target label for a control flow node.
372  */
373 static char *get_cfop_target(const ir_node *irn, char *buf) {
374         ir_node *bl = get_irn_link(irn);
375
376         snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
377         return buf;
378 }
379
380 /**
381  * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
382  */
383 static void finish_CondJmp(FILE *F, ir_node *irn) {
384         const ir_node   *proj;
385         const ir_edge_t *edge;
386         char buf[SNPRINTF_BUF_LEN];
387
388         edge = get_irn_out_edge_first(irn);
389         proj = get_edge_src_irn(edge);
390         assert(is_Proj(proj) && "CondJmp with a non-Proj");
391
392         if (get_Proj_proj(proj) == 1) {
393                 fprintf(F, "\tj%s %s\t\t\t/* cmp(a, b) == TRUE */\n",
394                                         get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
395                                         get_cfop_target(proj, buf));
396         }
397         else  {
398                 fprintf(F, "\tjn%s %s\t\t\t/* cmp(a, b) == FALSE */\n",
399                                         get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
400                                         get_cfop_target(proj, buf));
401         }
402
403         edge = get_irn_out_edge_next(irn, edge);
404         if (edge) {
405                 proj = get_edge_src_irn(edge);
406                 assert(is_Proj(proj) && "CondJmp with a non-Proj");
407                 fprintf(F, "\tjmp %s\t\t\t/* otherwise */\n", get_cfop_target(proj, buf));
408         }
409 }
410
411 /**
412  * Emits code for conditional jump with two variables.
413  */
414 static void emit_ia32_CondJmp(ir_node *irn, emit_env_t *env) {
415         FILE *F = env->out;
416
417         lc_efprintf(ia32_get_arg_env(), F, "\tcmp %2S, %1S\t\t\t/* CondJmp(%+F, %+F) */\n", irn, irn,
418                                                                                                                                         get_irn_n(irn, 0), get_irn_n(irn, 1));
419         finish_CondJmp(F, irn);
420 }
421
422 /**
423  * Emits code for conditional jump with immediate.
424  */
425 void emit_ia32_CondJmp_i(ir_node *irn, emit_env_t *env) {
426         FILE *F = env->out;
427
428         lc_efprintf(ia32_get_arg_env(), F, "\tcmp %C, %1S\t\t\t/* CondJmp_i(%+F) */\n", irn, irn, get_irn_n(irn, 0));
429         finish_CondJmp(F, irn);
430 }
431
432
433
434 /*********************************************************
435  *                 _ _       _
436  *                (_) |     (_)
437  *   ___ _ __ ___  _| |_     _ _   _ _ __ ___  _ __  ___
438  *  / _ \ '_ ` _ \| | __|   | | | | | '_ ` _ \| '_ \/ __|
439  * |  __/ | | | | | | |_    | | |_| | | | | | | |_) \__ \
440  *  \___|_| |_| |_|_|\__|   | |\__,_|_| |_| |_| .__/|___/
441  *                         _/ |               | |
442  *                        |__/                |_|
443  *********************************************************/
444
445 /* jump table entry (target and corresponding number) */
446 typedef struct _branch_t {
447         ir_node *target;
448         int      value;
449 } branch_t;
450
451 /* jump table for switch generation */
452 typedef struct _jmp_tbl_t {
453         ir_node  *defProj;         /**< default target */
454         int       min_value;       /**< smallest switch case */
455         int       max_value;       /**< largest switch case */
456         int       num_branches;    /**< number of jumps */
457         char     *label;           /**< label of the jump table */
458         branch_t *branches;        /**< jump array */
459 } jmp_tbl_t;
460
461 /**
462  * Compare two variables of type branch_t. Used to sort all switch cases
463  */
464 static int ia32_cmp_branch_t(const void *a, const void *b) {
465         branch_t *b1 = (branch_t *)a;
466         branch_t *b2 = (branch_t *)b;
467
468         if (b1->value <= b2->value)
469                 return -1;
470         else
471                 return 1;
472 }
473
474 /**
475  * Emits code for a SwitchJmp (creates a jump table if
476  * possible otherwise a cmp-jmp cascade). Port from
477  * cggg ia32 backend
478  */
479 void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) {
480         unsigned long       interval;
481         char                buf[SNPRINTF_BUF_LEN];
482         int                 last_value, i, pn, do_jmp_tbl = 1;
483         jmp_tbl_t           tbl;
484         ir_node            *proj;
485         const ir_edge_t    *edge;
486         const lc_arg_env_t *env = ia32_get_arg_env();
487         FILE               *F   = emit_env->out;
488
489         /* fill the table structure */
490         tbl.label        = malloc(SNPRINTF_BUF_LEN);
491         tbl.label        = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
492         tbl.defProj      = NULL;
493         tbl.num_branches = get_irn_n_edges(irn);
494         tbl.branches     = calloc(tbl.num_branches, sizeof(tbl.branches[0]));
495         tbl.min_value    = INT_MAX;
496         tbl.max_value    = INT_MIN;
497
498         i = 0;
499         /* go over all proj's and collect them */
500         foreach_out_edge(irn, edge) {
501                 proj = get_edge_src_irn(edge);
502                 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
503
504                 pn = get_Proj_proj(proj);
505
506                 /* create branch entry */
507                 tbl.branches[i].target = proj;
508                 tbl.branches[i].value  = pn;
509
510                 tbl.min_value = pn < tbl.min_value ? pn : tbl.min_value;
511                 tbl.max_value = pn > tbl.max_value ? pn : tbl.max_value;
512
513                 /* check for default proj */
514                 if (pn == get_ia32_pncode(irn)) {
515                         assert(tbl.defProj == NULL && "found two defProjs at SwitchJmp");
516                         tbl.defProj = proj;
517                 }
518
519                 i++;
520         }
521
522         /* sort the branches by their number */
523         qsort(tbl.branches, tbl.num_branches, sizeof(tbl.branches[0]), ia32_cmp_branch_t);
524
525         /* two-complement's magic make this work without overflow */
526         interval = tbl.max_value - tbl.min_value;
527
528         /* check value interval */
529         if (interval > 16 * 1024) {
530                 do_jmp_tbl = 0;
531         }
532
533         /* check ratio of value interval to number of branches */
534         if ((float)(interval + 1) / (float)tbl.num_branches > 8.0) {
535                 do_jmp_tbl = 0;
536         }
537
538         if (do_jmp_tbl) {
539                 /* emit the table */
540                 if (tbl.min_value != 0) {
541                         fprintf(F, "\tcmpl %lu, -%d", interval, tbl.min_value);
542                         lc_efprintf(env, F, "(%1S)\t\t/* first switch value is not 0 */\n", irn);
543                 }
544                 else {
545                         fprintf(F, "\tcmpl %lu, ", interval);
546                         lc_efprintf(env, F, "%1S\t\t\t/* compare for switch */\n", irn);
547                 }
548
549                 fprintf(F, "\tja %s\t\t\t/* default jump if out of range  */\n", get_cfop_target(tbl.defProj, buf));
550
551                 if (tbl.num_branches > 1) {
552                         /* create table */
553
554                         //fprintf(F, "\tjmp *%s", tbl.label);
555                         lc_efprintf(env, F, "\tjmp *%s(,%1S,4)\t\t/* get jump table entry as target */\n", tbl.label, irn);
556
557                         fprintf(F, "\t.section\t.rodata\t\t/* start jump table */\n");
558                         fprintf(F, "\t.align 4\n");
559
560                         fprintf(F, "%s:\n", tbl.label);
561                         fprintf(F, "\t.long %s\t\t\t/* case %d */\n", get_cfop_target(tbl.branches[0].target, buf), tbl.branches[0].value);
562
563                         last_value = tbl.branches[0].value;
564                         for (i = 1; i < tbl.num_branches; ++i) {
565                                 while (++last_value < tbl.branches[i].value) {
566                                         fprintf(F, "\t.long %s\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
567                                 }
568                                 fprintf(F, "\t.long %s\t\t\t/* case %d */\n", get_cfop_target(tbl.branches[i].target, buf), last_value);
569                         }
570
571                         fprintf(F, "\t.text\t\t\t\t/* end of jump table */\n");
572                 }
573                 else {
574                         /* one jump is enough */
575                         fprintf(F, "\tjmp %s\t\t/* only one case given */\n", get_cfop_target(tbl.branches[0].target, buf));
576                 }
577         }
578         else { // no jump table
579                 for (i = 0; i < tbl.num_branches; ++i) {
580                         fprintf(F, "\tcmpl %d, ", tbl.branches[i].value);
581                         lc_efprintf(env, F, "%1S", irn);
582                         fprintf(F, "\t\t\t/* case %d */\n", tbl.branches[i].value);
583                         fprintf(F, "\tje %s\n", get_cfop_target(tbl.branches[i].target, buf));
584                 }
585
586                 fprintf(F, "\tjmp %s\t\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
587         }
588
589         if (tbl.label)
590                 free(tbl.label);
591         if (tbl.branches)
592                 free(tbl.branches);
593 }
594
595 /**
596  * Emits code for a unconditional jump.
597  */
598 void emit_Jmp(ir_node *irn, emit_env_t *env) {
599         FILE *F = env->out;
600
601         char buf[SNPRINTF_BUF_LEN];
602         ir_fprintf(F, "\tjmp %s\t\t\t/* Jmp(%+F) */\n", get_cfop_target(irn, buf), get_irn_link(irn));
603 }
604
605
606
607 /****************************
608  *                  _
609  *                 (_)
610  *  _ __  _ __ ___  _  ___
611  * | '_ \| '__/ _ \| |/ __|
612  * | |_) | | | (_) | |\__ \
613  * | .__/|_|  \___/| ||___/
614  * | |            _/ |
615  * |_|           |__/
616  ****************************/
617
618 /**
619  * Emits code for a proj -> node
620  */
621 void emit_Proj(ir_node *irn, emit_env_t *env) {
622         ir_node *pred = get_Proj_pred(irn);
623
624         if (get_irn_opcode(pred) == iro_Start) {
625                 switch(get_Proj_proj(irn)) {
626                         case pn_Start_X_initial_exec:
627                                 emit_Jmp(irn, env);
628                                 break;
629                         default:
630                                 break;
631                 }
632         }
633 }
634
635
636
637 /***********************************************************************************
638  *                  _          __                                             _
639  *                 (_)        / _|                                           | |
640  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
641  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
642  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
643  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
644  *
645  ***********************************************************************************/
646
647 /**
648  * Emits code for a node.
649  */
650 void ia32_emit_node(ir_node *irn, void *env) {
651         emit_env_t *emit_env   = env;
652         firm_dbg_module_t *mod = emit_env->mod;
653         FILE              *F   = emit_env->out;
654
655         DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
656
657 #define IA32_EMIT(a) if (is_ia32_##a(irn))               { emit_ia32_##a(irn, emit_env); return; }
658 #define EMIT(a)      if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; }
659
660         /* generated int emitter functions */
661         IA32_EMIT(Copy);
662         IA32_EMIT(Perm);
663
664         IA32_EMIT(Const);
665
666         IA32_EMIT(Add);
667         IA32_EMIT(Add_i);
668         IA32_EMIT(Sub);
669         IA32_EMIT(Sub_i);
670         IA32_EMIT(Minus);
671         IA32_EMIT(Inc);
672         IA32_EMIT(Dec);
673
674         IA32_EMIT(Max);
675         IA32_EMIT(Min);
676
677         IA32_EMIT(And);
678         IA32_EMIT(And_i);
679         IA32_EMIT(Or);
680         IA32_EMIT(Or_i);
681         IA32_EMIT(Eor);
682         IA32_EMIT(Eor_i);
683         IA32_EMIT(Not);
684
685         IA32_EMIT(Shl);
686         IA32_EMIT(Shl_i);
687         IA32_EMIT(Shr);
688         IA32_EMIT(Shr_i);
689         IA32_EMIT(Shrs);
690         IA32_EMIT(Shrs_i);
691         IA32_EMIT(RotL);
692         IA32_EMIT(RotL_i);
693         IA32_EMIT(RotR);
694
695         IA32_EMIT(Lea);
696         IA32_EMIT(Lea_i);
697
698         IA32_EMIT(Mul);
699         IA32_EMIT(Mul_i);
700
701         IA32_EMIT(Cltd);
702         IA32_EMIT(DivMod);
703
704         IA32_EMIT(Store);
705         IA32_EMIT(Load);
706
707         /* generated floating point emitter */
708         IA32_EMIT(fConst);
709
710         IA32_EMIT(fAdd);
711         IA32_EMIT(fSub);
712         IA32_EMIT(fMinus);
713
714         IA32_EMIT(fMul);
715         IA32_EMIT(fDiv);
716
717         IA32_EMIT(fMin);
718         IA32_EMIT(fMax);
719
720         IA32_EMIT(fLoad);
721         IA32_EMIT(fStore);
722
723         /* other emitter functions */
724         IA32_EMIT(CondJmp);
725         IA32_EMIT(CondJmp_i);
726         IA32_EMIT(SwitchJmp);
727
728         EMIT(Jmp);
729         EMIT(Proj);
730
731         ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
732 }
733
734 /**
735  * Walks over the nodes in a block connected by scheduling edges
736  * and emits code for each node.
737  */
738 void ia32_gen_block(ir_node *block, void *env) {
739         ir_node *irn;
740
741         if (! is_Block(block))
742                 return;
743
744         fprintf(((emit_env_t *)env)->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
745         sched_foreach(block, irn) {
746                 ia32_emit_node(irn, env);
747         }
748 }
749
750
751 /**
752  * Emits code for function start.
753  */
754 void ia32_emit_start(FILE *F, ir_graph *irg) {
755         const char *irg_name = get_entity_name(get_irg_entity(irg));
756
757         fprintf(F, "\t.text\n");
758         fprintf(F, ".globl %s\n", irg_name);
759         fprintf(F, "\t.type\t%s, @function\n", irg_name);
760         fprintf(F, "%s:\n", irg_name);
761 }
762
763 /**
764  * Emits code for function end
765  */
766 void ia32_emit_end(FILE *F, ir_graph *irg) {
767         const char *irg_name = get_entity_name(get_irg_entity(irg));
768
769         fprintf(F, "\tret\n");
770         fprintf(F, "\t.size\t%s, .-%s\n\n", irg_name, irg_name);
771 }
772
773 /**
774  * Sets labels for control flow nodes (jump target)
775  * TODO: Jump optimization
776  */
777 void ia32_gen_labels(ir_node *block, void *env) {
778         ir_node *pred;
779         int n = get_Block_n_cfgpreds(block);
780
781         for (n--; n >= 0; n--) {
782                 pred = get_Block_cfgpred(block, n);
783                 set_irn_link(pred, block);
784         }
785 }
786
787 /**
788  * Main driver
789  */
790 void ia32_gen_routine(FILE *F, ir_graph *irg, const arch_env_t *env) {
791         emit_env_t emit_env;
792
793         emit_env.mod      = firm_dbg_register("ir.be.codegen.ia32");
794         emit_env.out      = F;
795         emit_env.arch_env = env;
796
797         arch_env = env;
798
799         ia32_emit_start(F, irg);
800         irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env);
801         irg_walk_blkwise_graph(irg, NULL, ia32_gen_block, &emit_env);
802         ia32_emit_end(F, irg);
803 }