1d0464a8a44172204538eff0ab01854cc53a3ce3
[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 "xmalloc.h"
8 #include "tv.h"
9 #include "iredges.h"
10 #include "debug.h"
11 #include "irgwalk.h"
12 #include "irprintf.h"
13 #include "irop_t.h"
14 #include "irargs_t.h"
15 #include "irprog_t.h"
16
17 #include "../besched.h"
18 #include "../benode_t.h"
19
20 #include "ia32_emitter.h"
21 #include "gen_ia32_emitter.h"
22 #include "ia32_nodes_attr.h"
23 #include "ia32_new_nodes.h"
24 #include "ia32_map_regs.h"
25
26 #ifdef obstack_chunk_alloc
27 # undef obstack_chunk_alloc
28 # define obstack_chunk_alloc xmalloc
29 #else
30 # define obstack_chunk_alloc xmalloc
31 # define obstack_chunk_free free
32 #endif
33
34 extern int obstack_printf(struct obstack *obst, char *fmt, ...);
35
36 #define SNPRINTF_BUF_LEN 128
37
38 static const arch_env_t *arch_env = NULL;
39
40 /**
41  * Emits registers and/or address mode of a binary operation.
42  */
43 char *ia32_emit_binop(const ir_node *n) {
44         static char *buf = NULL;
45
46         if (! buf) {
47                 buf = xcalloc(1, SNPRINTF_BUF_LEN);
48         }
49         else {
50                 memset(buf, 0, SNPRINTF_BUF_LEN);
51         }
52
53         switch(get_ia32_op_type(n)) {
54                 case ia32_Normal:
55                         if (get_ia32_cnst(n)) {
56                                 lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D, %s", n, get_ia32_cnst(n));
57                         }
58                         else {
59                                 lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D, %4S", n, n);
60                         }
61                         break;
62                 case ia32_AddrModeS:
63                         lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D, %s", n, ia32_emit_am(n));
64                         break;
65                 case ia32_AddrModeD:
66                         if (get_ia32_cnst(n)) {
67                                 lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s, %s", ia32_emit_am(n), get_ia32_cnst(n));
68                         }
69                         else {
70                                 if (is_ia32_St(n)) {
71                                         lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s, %3S", ia32_emit_am(n), n);
72                                 }
73                                 else {
74                                         lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s, %4S", ia32_emit_am(n), n);
75                                 }
76                         }
77                         break;
78                 default:
79                         assert(0 && "unsupported op type");
80         }
81
82         return buf;
83 }
84
85 /**
86  * Emits registers and/or address mode of a unary operation.
87  */
88 char *ia32_emit_unop(const ir_node *n) {
89         static char *buf = NULL;
90
91         if (! buf) {
92                 buf = xcalloc(1, SNPRINTF_BUF_LEN);
93         }
94         else {
95                 memset(buf, 0, SNPRINTF_BUF_LEN);
96         }
97
98         switch(get_ia32_op_type(n)) {
99                 case ia32_Normal:
100                         lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D", n);
101                         break;
102                 case ia32_am_Dest:
103                         snprintf(buf, SNPRINTF_BUF_LEN, ia32_emit_am(n));
104                         break;
105                 default:
106                         assert(0 && "unsupported op type");
107         }
108
109         return buf;
110 }
111
112 /**
113  * Emits adressmode.
114  */
115 char *ia32_emit_am(const ir_node *n) {
116         ia32_am_flavour_t am_flav    = get_ia32_am_flavour(n);
117         int               had_output = 0;
118         char             *s;
119         int               size;
120         static struct obstack *obst  = NULL;
121
122         if (! obst) {
123                 obst = xcalloc(1, sizeof(*obst));
124         }
125         else {
126                 obstack_free(obst, NULL);
127         }
128
129         /* obstack_free with NULL results in an uninitialized obstack */
130         obstack_init(obst);
131
132         obstack_printf(obst, "[");
133
134         if (am_flav & ia32_B) {
135                 lc_eoprintf(ia32_get_arg_env(), obst, "%1S", n);
136                 had_output = 1;
137         }
138
139         if (am_flav & ia32_I) {
140                 if (had_output) {
141                         obstack_printf(obst, "+");
142                 }
143
144                 lc_eoprintf(ia32_get_arg_env(), obst, "%2S", n);
145
146                 if (am_flav & ia32_S) {
147                         obstack_printf(obst, "*%d", 1 << get_ia32_am_scale(n));
148                 }
149
150                 had_output = 1;
151         }
152
153         if (am_flav & ia32_O) {
154                 obstack_printf(obst, get_ia32_am_offs(n));
155         }
156
157         obstack_printf(obst, "] ");
158
159         size        = obstack_object_size(obst);
160         s           = obstack_finish(obst);
161         s[size - 1] = '\0';
162
163         return s;
164 }
165
166 /*************************************************************
167  *             _       _    __   _          _
168  *            (_)     | |  / _| | |        | |
169  *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
170  * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
171  * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
172  * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
173  * | |                                       | |
174  * |_|                                       |_|
175  *************************************************************/
176
177 /* We always pass the ir_node which is a pointer. */
178 static int ia32_get_arg_type(const lc_arg_occ_t *occ) {
179         return lc_arg_type_ptr;
180 }
181
182
183 /**
184  * Returns the register at in position pos.
185  */
186 static const arch_register_t *get_in_reg(const ir_node *irn, int pos) {
187         ir_node                *op;
188         const arch_register_t  *reg = NULL;
189
190         assert(get_irn_arity(irn) > pos && "Invalid IN position");
191
192         /* The out register of the operator at position pos is the
193            in register we need. */
194         op = get_irn_n(irn, pos);
195
196         reg = arch_get_irn_register(arch_env, op);
197
198         assert(reg && "no in register found");
199         return reg;
200 }
201
202 /**
203  * Returns the register at out position pos.
204  */
205 static const arch_register_t *get_out_reg(const ir_node *irn, int pos) {
206         ir_node                *proj;
207         const arch_register_t  *reg = NULL;
208
209         assert(get_irn_n_edges(irn) > pos && "Invalid OUT position");
210
211         /* 1st case: irn is not of mode_T, so it has only                 */
212         /*           one OUT register -> good                             */
213         /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
214         /*           Proj with the corresponding projnum for the register */
215
216         if (get_irn_mode(irn) != mode_T) {
217                 reg = arch_get_irn_register(arch_env, irn);
218         }
219         else if (is_ia32_irn(irn)) {
220                 reg = get_ia32_out_reg(irn, pos);
221         }
222         else {
223                 const ir_edge_t *edge;
224
225                 foreach_out_edge(irn, edge) {
226                         proj = get_edge_src_irn(edge);
227                         assert(is_Proj(proj) && "non-Proj from mode_T node");
228                         if (get_Proj_proj(proj) == pos) {
229                                 reg = arch_get_irn_register(arch_env, proj);
230                                 break;
231                         }
232                 }
233         }
234
235         assert(reg && "no out register found");
236         return reg;
237 }
238
239 /**
240  * Returns the number of the in register at position pos.
241  */
242 int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) {
243         const arch_register_t *reg;
244
245         if (in_out == 1) {
246                 reg = get_in_reg(irn, pos);
247         }
248         else {
249                 reg = get_out_reg(irn, pos);
250         }
251
252         return arch_register_get_index(reg);
253 }
254
255 enum io_direction {
256   IN_REG,
257   OUT_REG
258 };
259
260 /**
261  * Returns the name of the in register at position pos.
262  */
263 static const char *get_ia32_reg_name(ir_node *irn, int pos, enum io_direction in_out) {
264         const arch_register_t *reg;
265
266         if (in_out == IN_REG) {
267                 reg = get_in_reg(irn, pos);
268         }
269         else {
270                 reg = get_out_reg(irn, pos);
271         }
272
273         return arch_register_get_name(reg);
274 }
275
276 /**
277  * Get the register name for a node.
278  */
279 static int ia32_get_reg_name(lc_appendable_t *app,
280     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
281 {
282         const char *buf;
283         ir_node    *X  = arg->v_ptr;
284         int         nr = occ->width - 1;
285
286         if (!X)
287                 return lc_arg_append(app, occ, "(null)", 6);
288
289         buf = get_ia32_reg_name(X, nr, occ->conversion == 'S' ? IN_REG : OUT_REG);
290
291         return lc_arg_append(app, occ, buf, strlen(buf));
292 }
293
294 /**
295  * Returns the tarval, offset or scale of an ia32 as a string.
296  */
297 static int ia32_const_to_str(lc_appendable_t *app,
298     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
299 {
300         const char *buf;
301         ir_node    *X = arg->v_ptr;
302
303         if (!X)
304                 return lc_arg_append(app, occ, "(null)", 6);
305
306         if (occ->conversion == 'C') {
307                 buf = get_ia32_cnst(X);
308         }
309         else { /* 'O' */
310                 buf = get_ia32_am_offs(X);
311         }
312
313         return lc_arg_append(app, occ, buf, strlen(buf));
314 }
315
316 /**
317  * Determines the SSE suffix depending on the mode.
318  */
319 static int ia32_get_mode_suffix(lc_appendable_t *app,
320     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
321 {
322         ir_node *X = arg->v_ptr;
323
324         if (!X)
325                 return lc_arg_append(app, occ, "(null)", 6);
326
327         return lc_appendable_chadd(app, get_mode_size_bits(get_irn_mode(X)) == 32 ? 's' : 'd');
328 }
329
330 /**
331  * Return the ia32 printf arg environment.
332  * We use the firm environment with some additional handlers.
333  */
334 const lc_arg_env_t *ia32_get_arg_env(void) {
335         static lc_arg_env_t *env = NULL;
336
337         static const lc_arg_handler_t ia32_reg_handler   = { ia32_get_arg_type, ia32_get_reg_name };
338         static const lc_arg_handler_t ia32_const_handler = { ia32_get_arg_type, ia32_const_to_str };
339         static const lc_arg_handler_t ia32_mode_handler  = { ia32_get_arg_type, ia32_get_mode_suffix };
340
341         if(env == NULL) {
342                 /* extend the firm printer */
343                 env = firm_get_arg_env();
344
345                 lc_arg_register(env, "ia32:sreg", 'S', &ia32_reg_handler);
346                 lc_arg_register(env, "ia32:dreg", 'D', &ia32_reg_handler);
347                 lc_arg_register(env, "ia32:cnst", 'C', &ia32_const_handler);
348                 lc_arg_register(env, "ia32:offs", 'O', &ia32_const_handler);
349                 lc_arg_register(env, "ia32:mode", 'M', &ia32_mode_handler);
350         }
351
352         return env;
353 }
354
355
356 /*
357  * Add a number to a prefix. This number will not be used a second time.
358  */
359 static char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
360         static unsigned long id = 0;
361         snprintf(buf, buflen, "%s%lu", prefix, ++id);
362         return buf;
363 }
364
365
366 /*************************************************
367  *                 _ _                         _
368  *                (_) |                       | |
369  *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
370  *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
371  * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
372  *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
373  *
374  *************************************************/
375
376 /*
377  * coding of conditions
378  */
379 struct cmp2conditon_t {
380         const char *name;
381         pn_Cmp      num;
382 };
383
384 /*
385  * positive conditions for signed compares
386  */
387 static const struct cmp2conditon_t cmp2condition_s[] = {
388   { NULL,              pn_Cmp_False },  /* always false */
389   { "e",               pn_Cmp_Eq },     /* == */
390   { "l",               pn_Cmp_Lt },     /* < */
391   { "le",              pn_Cmp_Le },     /* <= */
392   { "g",               pn_Cmp_Gt },     /* > */
393   { "ge",              pn_Cmp_Ge },     /* >= */
394   { "ne",              pn_Cmp_Lg },     /* != */
395   { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
396   { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
397   { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
398   { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
399   { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
400   { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
401   { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
402   { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
403   { NULL,              pn_Cmp_True },   /* always true */
404 };
405
406 /*
407  * positive conditions for unsigned compares
408  */
409 static const struct cmp2conditon_t cmp2condition_u[] = {
410   { NULL,              pn_Cmp_False },  /* always false */
411   { "e",               pn_Cmp_Eq },     /* == */
412   { "b",               pn_Cmp_Lt },     /* < */
413   { "be",              pn_Cmp_Le },     /* <= */
414   { "a",               pn_Cmp_Gt },     /* > */
415   { "ae",              pn_Cmp_Ge },     /* >= */
416   { "ne",              pn_Cmp_Lg },     /* != */
417   { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
418   { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
419   { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
420   { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
421   { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
422   { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
423   { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
424   { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
425   { NULL,              pn_Cmp_True },   /* always true */
426 };
427
428 /*
429  * returns the condition code
430  */
431 static const char *get_cmp_suffix(int cmp_code, int unsigned_cmp)
432 {
433         assert(cmp2condition_s[cmp_code].num == cmp_code);
434         assert(cmp2condition_u[cmp_code].num == cmp_code);
435
436         return unsigned_cmp ? cmp2condition_u[cmp_code & 7].name : cmp2condition_s[cmp_code & 7].name;
437 }
438
439 /**
440  * Returns the target label for a control flow node.
441  */
442 static char *get_cfop_target(const ir_node *irn, char *buf) {
443         ir_node *bl = get_irn_link(irn);
444
445         snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
446         return buf;
447 }
448
449 /**
450  * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
451  */
452 static void finish_CondJmp(FILE *F, const ir_node *irn) {
453         const ir_node   *proj;
454         const ir_edge_t *edge;
455         char buf[SNPRINTF_BUF_LEN];
456
457         edge = get_irn_out_edge_first(irn);
458         proj = get_edge_src_irn(edge);
459         assert(is_Proj(proj) && "CondJmp with a non-Proj");
460
461         if (get_Proj_proj(proj) == 1) {
462                 fprintf(F, "\tj%s %s\t\t\t/* cmp(a, b) == TRUE */\n",
463                                         get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
464                                         get_cfop_target(proj, buf));
465         }
466         else  {
467                 fprintf(F, "\tjn%s %s\t\t\t/* cmp(a, b) == FALSE */\n",
468                                         get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
469                                         get_cfop_target(proj, buf));
470         }
471
472         edge = get_irn_out_edge_next(irn, edge);
473         if (edge) {
474                 proj = get_edge_src_irn(edge);
475                 assert(is_Proj(proj) && "CondJmp with a non-Proj");
476                 fprintf(F, "\tjmp %s\t\t\t/* otherwise */\n", get_cfop_target(proj, buf));
477         }
478 }
479
480 /**
481  * Emits code for conditional jump with two variables.
482  */
483 static void emit_ia32_CondJmp(const ir_node *irn, emit_env_t *env) {
484         FILE *F = env->out;
485
486         lc_efprintf(ia32_get_arg_env(), F, "\tcmp %2S, %1S\t\t\t/* CondJmp(%+F, %+F) */\n", irn, irn,
487                                                                                                                                         get_irn_n(irn, 0), get_irn_n(irn, 1));
488         finish_CondJmp(F, irn);
489 }
490
491 /**
492  * Emits code for conditional jump with immediate.
493  */
494 void emit_ia32_CondJmp_i(const ir_node *irn, emit_env_t *env) {
495         FILE *F = env->out;
496
497         lc_efprintf(ia32_get_arg_env(), F, "\tcmp %C, %1S\t\t\t/* CondJmp_i(%+F) */\n", irn, irn, get_irn_n(irn, 0));
498         finish_CondJmp(F, irn);
499 }
500
501
502
503 /*********************************************************
504  *                 _ _       _
505  *                (_) |     (_)
506  *   ___ _ __ ___  _| |_     _ _   _ _ __ ___  _ __  ___
507  *  / _ \ '_ ` _ \| | __|   | | | | | '_ ` _ \| '_ \/ __|
508  * |  __/ | | | | | | |_    | | |_| | | | | | | |_) \__ \
509  *  \___|_| |_| |_|_|\__|   | |\__,_|_| |_| |_| .__/|___/
510  *                         _/ |               | |
511  *                        |__/                |_|
512  *********************************************************/
513
514 /* jump table entry (target and corresponding number) */
515 typedef struct _branch_t {
516         ir_node *target;
517         int      value;
518 } branch_t;
519
520 /* jump table for switch generation */
521 typedef struct _jmp_tbl_t {
522         ir_node  *defProj;         /**< default target */
523         int       min_value;       /**< smallest switch case */
524         int       max_value;       /**< largest switch case */
525         int       num_branches;    /**< number of jumps */
526         char     *label;           /**< label of the jump table */
527         branch_t *branches;        /**< jump array */
528 } jmp_tbl_t;
529
530 /**
531  * Compare two variables of type branch_t. Used to sort all switch cases
532  */
533 static int ia32_cmp_branch_t(const void *a, const void *b) {
534         branch_t *b1 = (branch_t *)a;
535         branch_t *b2 = (branch_t *)b;
536
537         if (b1->value <= b2->value)
538                 return -1;
539         else
540                 return 1;
541 }
542
543 /**
544  * Emits code for a SwitchJmp (creates a jump table if
545  * possible otherwise a cmp-jmp cascade). Port from
546  * cggg ia32 backend
547  */
548 void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) {
549         unsigned long       interval;
550         char                buf[SNPRINTF_BUF_LEN];
551         int                 last_value, i, pn, do_jmp_tbl = 1;
552         jmp_tbl_t           tbl;
553         ir_node            *proj;
554         const ir_edge_t    *edge;
555         const lc_arg_env_t *env = ia32_get_arg_env();
556         FILE               *F   = emit_env->out;
557
558         /* fill the table structure */
559         tbl.label        = xmalloc(SNPRINTF_BUF_LEN);
560         tbl.label        = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
561         tbl.defProj      = NULL;
562         tbl.num_branches = get_irn_n_edges(irn);
563         tbl.branches     = xcalloc(tbl.num_branches, sizeof(tbl.branches[0]));
564         tbl.min_value    = INT_MAX;
565         tbl.max_value    = INT_MIN;
566
567         i = 0;
568         /* go over all proj's and collect them */
569         foreach_out_edge(irn, edge) {
570                 proj = get_edge_src_irn(edge);
571                 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
572
573                 pn = get_Proj_proj(proj);
574
575                 /* create branch entry */
576                 tbl.branches[i].target = proj;
577                 tbl.branches[i].value  = pn;
578
579                 tbl.min_value = pn < tbl.min_value ? pn : tbl.min_value;
580                 tbl.max_value = pn > tbl.max_value ? pn : tbl.max_value;
581
582                 /* check for default proj */
583                 if (pn == get_ia32_pncode(irn)) {
584                         assert(tbl.defProj == NULL && "found two defProjs at SwitchJmp");
585                         tbl.defProj = proj;
586                 }
587
588                 i++;
589         }
590
591         /* sort the branches by their number */
592         qsort(tbl.branches, tbl.num_branches, sizeof(tbl.branches[0]), ia32_cmp_branch_t);
593
594         /* two-complement's magic make this work without overflow */
595         interval = tbl.max_value - tbl.min_value;
596
597         /* check value interval */
598         if (interval > 16 * 1024) {
599                 do_jmp_tbl = 0;
600         }
601
602         /* check ratio of value interval to number of branches */
603         if ((float)(interval + 1) / (float)tbl.num_branches > 8.0) {
604                 do_jmp_tbl = 0;
605         }
606
607         if (do_jmp_tbl) {
608                 /* emit the table */
609                 if (tbl.min_value != 0) {
610                         lc_efprintf(env, F, "\tcmpl %lu, -%d(%1S)\t\t/* first switch value is not 0 */\n",
611                                 interval, tbl.min_value, irn);
612                 }
613                 else {
614                         lc_efprintf(env, F, "\tcmpl %lu, %1S\t\t\t/* compare for switch */\n", interval, irn);
615                 }
616
617                 fprintf(F, "\tja %s\t\t\t/* default jump if out of range  */\n", get_cfop_target(tbl.defProj, buf));
618
619                 if (tbl.num_branches > 1) {
620                         /* create table */
621
622                         lc_efprintf(env, F, "\tjmp *%s(,%1S,4)\t\t/* get jump table entry as target */\n", tbl.label, irn);
623
624                         fprintf(F, "\t.section\t.rodata\t\t/* start jump table */\n");
625                         fprintf(F, "\t.align 4\n");
626
627                         fprintf(F, "%s:\n", tbl.label);
628                         fprintf(F, "\t.long %s\t\t\t/* case %d */\n", get_cfop_target(tbl.branches[0].target, buf), tbl.branches[0].value);
629
630                         last_value = tbl.branches[0].value;
631                         for (i = 1; i < tbl.num_branches; ++i) {
632                                 while (++last_value < tbl.branches[i].value) {
633                                         fprintf(F, "\t.long %s\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
634                                 }
635                                 fprintf(F, "\t.long %s\t\t\t/* case %d */\n", get_cfop_target(tbl.branches[i].target, buf), last_value);
636                         }
637
638                         fprintf(F, "\t.text\t\t\t\t/* end of jump table */\n");
639                 }
640                 else {
641                         /* one jump is enough */
642                         fprintf(F, "\tjmp %s\t\t/* only one case given */\n", get_cfop_target(tbl.branches[0].target, buf));
643                 }
644         }
645         else { // no jump table
646                 for (i = 0; i < tbl.num_branches; ++i) {
647                         lc_efprintf(env, F, "\tcmpl %d, %1S\t\t\t/* case %d */\n", tbl.branches[i].value, irn, i);
648                         fprintf(F, "\tje %s\n", get_cfop_target(tbl.branches[i].target, buf));
649                 }
650
651                 fprintf(F, "\tjmp %s\t\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
652         }
653
654         if (tbl.label)
655                 free(tbl.label);
656         if (tbl.branches)
657                 free(tbl.branches);
658 }
659
660 /**
661  * Emits code for a unconditional jump.
662  */
663 void emit_Jmp(const ir_node *irn, emit_env_t *env) {
664         FILE *F = env->out;
665
666         char buf[SNPRINTF_BUF_LEN];
667         ir_fprintf(F, "\tjmp %s\t\t\t/* Jmp(%+F) */\n", get_cfop_target(irn, buf), get_irn_link(irn));
668 }
669
670
671
672 /****************************
673  *                  _
674  *                 (_)
675  *  _ __  _ __ ___  _  ___
676  * | '_ \| '__/ _ \| |/ __|
677  * | |_) | | | (_) | |\__ \
678  * | .__/|_|  \___/| ||___/
679  * | |            _/ |
680  * |_|           |__/
681  ****************************/
682
683 /**
684  * Emits code for a proj -> node
685  */
686 void emit_Proj(const ir_node *irn, emit_env_t *env) {
687         ir_node *pred = get_Proj_pred(irn);
688
689         if (get_irn_op(pred) == op_Start) {
690                 switch(get_Proj_proj(irn)) {
691                         case pn_Start_X_initial_exec:
692                                 emit_Jmp(irn, env);
693                                 break;
694                         default:
695                                 break;
696                 }
697         }
698 }
699
700 /**********************************
701  *   _____                  ____
702  *  / ____|                |  _ \
703  * | |     ___  _ __  _   _| |_) |
704  * | |    / _ \| '_ \| | | |  _ <
705  * | |___| (_) | |_) | |_| | |_) |
706  *  \_____\___/| .__/ \__, |____/
707  *             | |     __/ |
708  *             |_|    |___/
709  **********************************/
710
711 static void emit_CopyB_prolog(FILE *F, int rem, int size) {
712         fprintf(F, "\t/* memcopy %d bytes*/\n", size);
713         fprintf(F, "\tcld\t\t\t\t/* copy direction forward*/\n");
714
715         switch(rem) {
716                 case 1:
717                         fprintf(F, "\tmovsb\t\t\t\t/* memcopy remainder 1 */\n");
718                         break;
719                 case 2:
720                         fprintf(F, "\tmovsw\t\t\t\t/* memcopy remainder 2 */\n");
721                         break;
722                 case 3:
723                         fprintf(F, "\tmovsb\t\t\t\t/* memcopy remainder 3 */\n");
724                         fprintf(F, "\tmovsw\t\t\t\t/* memcopy remainder 3 */\n");
725                         break;
726         }
727 }
728
729 void emit_ia32_CopyB(const ir_node *irn, emit_env_t *emit_env) {
730         FILE   *F    = emit_env->out;
731         tarval *tv   = get_ia32_Immop_tarval(irn);
732         int     rem  = get_tarval_long(tv);
733         int     size = get_tarval_long(get_ia32_Immop_tarval(get_irn_n(irn, 2)));
734
735         emit_CopyB_prolog(F, rem, size);
736
737         fprintf(F, "\trep movsd\t\t\t\t/* memcopy */\n");
738 }
739
740 void emit_ia32_CopyB_i(const ir_node *irn, emit_env_t *emit_env) {
741         tarval *tv   = get_ia32_Immop_tarval(irn);
742         int     size = get_tarval_long(tv);
743         FILE   *F    = emit_env->out;
744
745         emit_CopyB_prolog(F, size & 0x3, size);
746
747         size >>= 2;
748         while (size--) {
749                 fprintf(F, "\tmovsd\t\t\t\t/* memcopy unrolled */\n");
750         }
751 }
752
753
754
755 /*******************************************
756  *  _                          _
757  * | |                        | |
758  * | |__   ___ _ __   ___   __| | ___  ___
759  * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
760  * | |_) |  __/ | | | (_) | (_| |  __/\__ \
761  * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
762  *
763  *******************************************/
764
765 void emit_be_Call(const ir_node *irn, emit_env_t *emit_env) {
766         FILE *F = emit_env->out;
767
768         lc_efprintf(ia32_get_arg_env(), F, "\tcall %3S\t\t\t/* %+F(%+F) (be_Call) */\n", irn, irn, get_irn_n(irn, 2));
769 }
770
771 void emit_be_IncSP(const ir_node *irn, emit_env_t *emit_env) {
772         FILE          *F    = emit_env->out;
773         unsigned       offs = be_get_IncSP_offset(irn);
774         be_stack_dir_t dir  = be_get_IncSP_direction(irn);
775
776         if (offs) {
777                 lc_efprintf(ia32_get_arg_env(), F, "\tadd %1S,%s%u\t\t\t/* %+F (IncSP) */\n", irn,
778                         (dir == be_stack_dir_along) ? " -" : " ", offs, irn);
779         }
780         else {
781                 fprintf(F, "\t\t\t\t\t/* omitted IncSP with 0 */\n");
782         }
783 }
784
785 void emit_be_AddSP(const ir_node *irn, emit_env_t *emit_env) {
786         FILE *F = emit_env->out;
787         lc_efprintf(ia32_get_arg_env(), F, "\tadd %1D, %1S\t\t\t/* %+F (AddSP) */\n", irn, irn, irn);
788 }
789
790
791
792 /***********************************************************************************
793  *                  _          __                                             _
794  *                 (_)        / _|                                           | |
795  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
796  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
797  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
798  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
799  *
800  ***********************************************************************************/
801
802 /**
803  * Enters the emitter functions for handled nodes into the generic
804  * pointer of an opcode.
805  */
806 void ia32_register_emitters(void) {
807
808 #define IA32_EMIT(a) op_ia32_##a->ops.generic = (op_func)emit_ia32_##a
809 #define EMIT(a)      op_##a->ops.generic = (op_func)emit_##a
810 #define BE_EMIT(a)   op_be_##a->ops.generic = (op_func)emit_be_##a
811
812         /* first clear the generic function pointer for all ops */
813         clear_irp_opcodes_generic_func();
814
815         /* register all emitter functions defined in spec */
816         ia32_register_spec_emitters();
817
818         /* other emitter functions */
819         IA32_EMIT(CondJmp);
820         IA32_EMIT(SwitchJmp);
821         IA32_EMIT(CopyB);
822         IA32_EMIT(CopyB_i);
823
824         /* benode emitter */
825         BE_EMIT(Call);
826         BE_EMIT(IncSP);
827         BE_EMIT(AddSP);
828
829         /* firm emitter */
830         EMIT(Jmp);
831         EMIT(Proj);
832
833 #undef IA32_EMIT
834 #undef BE_EMIT
835 #undef EMIT
836 }
837
838 /**
839  * Emits code for a node.
840  */
841 static void ia32_emit_node(const ir_node *irn, void *env) {
842         emit_env_t        *emit_env = env;
843         firm_dbg_module_t *mod      = emit_env->mod;
844         FILE              *F        = emit_env->out;
845         ir_op             *op       = get_irn_op(irn);
846
847         DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
848
849         if (op->ops.generic) {
850                 void (*emit)(const ir_node *, void *) = (void (*)(const ir_node *, void *))op->ops.generic;
851                 (*emit)(irn, env);
852         }
853         else {
854                 ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
855         }
856 }
857
858 /**
859  * Walks over the nodes in a block connected by scheduling edges
860  * and emits code for each node.
861  */
862 static void ia32_gen_block(ir_node *block, void *env) {
863         const ir_node *irn;
864
865         if (! is_Block(block))
866                 return;
867
868         fprintf(((emit_env_t *)env)->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
869         sched_foreach(block, irn) {
870                 ia32_emit_node(irn, env);
871         }
872 }
873
874
875 /**
876  * Emits code for function start.
877  */
878 static void ia32_emit_func_prolog(FILE *F, ir_graph *irg) {
879         const char *irg_name = get_entity_name(get_irg_entity(irg));
880
881         fprintf(F, "\t.text\n");
882         fprintf(F, ".globl %s\n", irg_name);
883         fprintf(F, "\t.type\t%s, @function\n", irg_name);
884         fprintf(F, "%s:\n", irg_name);
885 }
886
887 /**
888  * Emits code for function end
889  */
890 static void ia32_emit_func_epilog(FILE *F, ir_graph *irg) {
891         const char *irg_name = get_entity_name(get_irg_entity(irg));
892
893         fprintf(F, "\tret\n");
894         fprintf(F, "\t.size\t%s, .-%s\n\n", irg_name, irg_name);
895 }
896
897 /**
898  * Sets labels for control flow nodes (jump target)
899  * TODO: Jump optimization
900  */
901 static void ia32_gen_labels(ir_node *block, void *env) {
902         ir_node *pred;
903         int n = get_Block_n_cfgpreds(block);
904
905         for (n--; n >= 0; n--) {
906                 pred = get_Block_cfgpred(block, n);
907                 set_irn_link(pred, block);
908         }
909 }
910
911 /**
912  * Main driver. Emits the code for one routine.
913  */
914 void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) {
915         emit_env_t emit_env;
916
917         emit_env.mod      = firm_dbg_register("ir.be.codegen.ia32");
918         emit_env.out      = F;
919         emit_env.arch_env = cg->arch_env;
920         emit_env.cg       = cg;
921
922         /* set the global arch_env (needed by print hooks) */
923         arch_env = cg->arch_env;
924
925         ia32_emit_func_prolog(F, irg);
926         irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env);
927         irg_walk_blkwise_graph(irg, NULL, ia32_gen_block, &emit_env);
928         ia32_emit_func_epilog(F, irg);
929 }