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