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