emit arm symconsts as .LC%u instead of .L%u to avoid clashed with block numbers
[libfirm] / ir / be / arm / arm_emitter.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   arm emitter
23  * @author  Oliver Richter, Tobias Gneist, Michael Beck
24  * @version $Id$
25  */
26 #include "config.h"
27
28 #include <limits.h>
29 #include <stdbool.h>
30
31 #include "xmalloc.h"
32 #include "tv.h"
33 #include "iredges.h"
34 #include "debug.h"
35 #include "irgwalk.h"
36 #include "irtools.h"
37 #include "irprintf.h"
38 #include "irop_t.h"
39 #include "irprog_t.h"
40 #include "irargs_t.h"
41 #include "error.h"
42 #include "raw_bitset.h"
43 #include "dbginfo.h"
44
45 #include "../besched.h"
46 #include "../beblocksched.h"
47 #include "../beirg.h"
48 #include "../begnuas.h"
49 #include "../be_dbgout.h"
50
51 #include "arm_emitter.h"
52 #include "arm_optimize.h"
53 #include "gen_arm_emitter.h"
54 #include "arm_nodes_attr.h"
55 #include "arm_new_nodes.h"
56 #include "arm_map_regs.h"
57 #include "gen_arm_regalloc_if.h"
58
59 #include "../benode.h"
60
61 #define SNPRINTF_BUF_LEN 128
62
63 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
64
65 static const arm_code_gen_t *cg;
66 static set                  *sym_or_tv;
67
68 /**
69  * Returns the register at in position pos.
70  */
71 static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
72 {
73         ir_node                *op;
74         const arch_register_t  *reg = NULL;
75
76         assert(get_irn_arity(irn) > pos && "Invalid IN position");
77
78         /* The out register of the operator at position pos is the
79            in register we need. */
80         op = get_irn_n(irn, pos);
81
82         reg = arch_get_irn_register(op);
83
84         assert(reg && "no in register found");
85
86         /* in case of a joker register: just return a valid register */
87         if (arch_register_type_is(reg, joker)) {
88                 const arch_register_req_t *req = arch_get_register_req(irn, pos);
89
90                 if (arch_register_req_is(req, limited)) {
91                         /* in case of limited requirements: get the first allowed register */
92                         unsigned idx = rbitset_next(req->limited, 0, 1);
93                         reg = arch_register_for_index(req->cls, idx);
94                 } else {
95                         /* otherwise get first register in class */
96                         reg = arch_register_for_index(req->cls, 0);
97                 }
98         }
99         return reg;
100 }
101
102
103 /**
104  * Returns the register at out position pos.
105  */
106 static const arch_register_t *get_out_reg(const ir_node *node, int pos)
107 {
108     ir_node                *proj;
109     const arch_register_t  *reg = NULL;
110
111     /* 1st case: irn is not of mode_T, so it has only                 */
112     /*           one OUT register -> good                             */
113     /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
114     /*           Proj with the corresponding projnum for the register */
115
116     if (get_irn_mode(node) != mode_T) {
117         reg = arch_get_irn_register(node);
118     } else if (is_arm_irn(node)) {
119         reg = arch_irn_get_register(node, pos);
120     } else {
121         const ir_edge_t *edge;
122
123         foreach_out_edge(node, edge) {
124             proj = get_edge_src_irn(edge);
125             assert(is_Proj(proj) && "non-Proj from mode_T node");
126             if (get_Proj_proj(proj) == pos) {
127                 reg = arch_get_irn_register(proj);
128                 break;
129             }
130         }
131     }
132
133     assert(reg && "no out register found");
134     return reg;
135 }
136
137 /**
138  * Emit the name of the source register at given input position.
139  */
140 void arm_emit_source_register(const ir_node *node, int pos)
141 {
142         const arch_register_t *reg = get_in_reg(node, pos);
143         be_emit_string(arch_register_get_name(reg));
144 }
145
146 /**
147  * Emit the name of the destination register at given output position.
148  */
149 void arm_emit_dest_register(const ir_node *node, int pos)
150 {
151         const arch_register_t *reg = get_out_reg(node, pos);
152         be_emit_string(arch_register_get_name(reg));
153 }
154
155 /**
156  * Emit a node's offset.
157  */
158 void arm_emit_offset(const ir_node *node)
159 {
160         const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
161         assert(attr->base.is_load_store);
162
163         be_emit_irprintf("0x%X", attr->offset);
164 }
165
166 /**
167  * Emit the arm fpa instruction suffix depending on the mode.
168  */
169 static void arm_emit_fpa_postfix(const ir_mode *mode)
170 {
171         int bits = get_mode_size_bits(mode);
172         char c = 'e';
173
174         if (bits == 32)
175                 c = 's';
176         else if (bits == 64)
177                 c = 'd';
178         be_emit_char(c);
179 }
180
181 /**
182  * Emit the instruction suffix depending on the mode.
183  */
184 void arm_emit_mode(const ir_node *node)
185 {
186         ir_mode *mode;
187
188         if (is_arm_irn(node)) {
189                 const arm_attr_t *attr = get_arm_attr_const(node);
190                 mode = attr->op_mode ? attr->op_mode : get_irn_mode(node);
191         } else {
192                 mode = get_irn_mode(node);
193         }
194         arm_emit_fpa_postfix(mode);
195 }
196
197 void arm_emit_symconst(const ir_node *node)
198 {
199         const arm_SymConst_attr_t *symconst = get_arm_SymConst_attr_const(node);
200         ir_entity                 *entity   = symconst->entity;
201
202         be_gas_emit_entity(entity);
203
204         /* TODO do something with offset */
205 }
206
207 void arm_emit_load_mode(const ir_node *node)
208 {
209         const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
210         ir_mode *mode      = attr->load_store_mode;
211         int      bits      = get_mode_size_bits(mode);
212         bool     is_signed = mode_is_signed(mode);
213         if (bits == 16) {
214                 be_emit_string(is_signed ? "sh" : "h");
215         } else if (bits == 8) {
216                 be_emit_string(is_signed ? "sb" : "b");
217         } else {
218                 assert(bits == 32);
219         }
220 }
221
222 void arm_emit_store_mode(const ir_node *node)
223 {
224         const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
225         ir_mode *mode      = attr->load_store_mode;
226         int      bits      = get_mode_size_bits(mode);
227         if (bits == 16) {
228                 be_emit_cstring("h");
229         } else if (bits == 8) {
230                 be_emit_cstring("b");
231         } else {
232                 assert(bits == 32);
233         }
234 }
235
236
237 static void emit_shf_mod_name(arm_shift_modifier_t mod)
238 {
239         switch (mod) {
240         case ARM_SHF_ASR_REG:
241         case ARM_SHF_ASR_IMM:
242                 be_emit_cstring("asr");
243                 return;
244         case ARM_SHF_LSL_REG:
245         case ARM_SHF_LSL_IMM:
246                 be_emit_cstring("lsl");
247                 return;
248         case ARM_SHF_LSR_REG:
249         case ARM_SHF_LSR_IMM:
250                 be_emit_cstring("lsr");
251                 return;
252         case ARM_SHF_ROR_REG:
253         case ARM_SHF_ROR_IMM:
254                 be_emit_cstring("ror");
255                 return;
256         default:
257                 break;
258         }
259         panic("can't emit this shf_mod_name %d", (int) mod);
260 }
261
262 void arm_emit_shifter_operand(const ir_node *node)
263 {
264         const arm_shifter_operand_t *attr = get_irn_generic_attr_const(node);
265
266         switch (attr->shift_modifier) {
267         case ARM_SHF_REG:
268                 arm_emit_source_register(node, get_irn_arity(node) - 1);
269                 return;
270         case ARM_SHF_IMM: {
271                 unsigned val = attr->immediate_value;
272                 val = (val >> attr->shift_immediate)
273                         | (val << (32-attr->shift_immediate));
274                 val &= 0xFFFFFFFF;
275                 be_emit_irprintf("#0x%X", val);
276                 return;
277         }
278         case ARM_SHF_ASR_IMM:
279         case ARM_SHF_LSL_IMM:
280         case ARM_SHF_LSR_IMM:
281         case ARM_SHF_ROR_IMM:
282                 arm_emit_source_register(node, get_irn_arity(node) - 1);
283                 be_emit_cstring(", ");
284                 emit_shf_mod_name(attr->shift_modifier);
285                 be_emit_irprintf(" #0x%X", attr->shift_immediate);
286                 return;
287
288         case ARM_SHF_ASR_REG:
289         case ARM_SHF_LSL_REG:
290         case ARM_SHF_LSR_REG:
291         case ARM_SHF_ROR_REG:
292                 arm_emit_source_register(node, get_irn_arity(node) - 2);
293                 be_emit_cstring(", ");
294                 emit_shf_mod_name(attr->shift_modifier);
295                 be_emit_cstring(" ");
296                 arm_emit_source_register(node, get_irn_arity(node) - 1);
297                 return;
298
299         case ARM_SHF_RRX:
300                 arm_emit_source_register(node, get_irn_arity(node) - 1);
301                 panic("RRX shifter emitter TODO");
302
303         case ARM_SHF_INVALID:
304                 break;
305         }
306         panic("Invalid shift_modifier while emitting %+F", node);
307 }
308
309 /** An entry in the sym_or_tv set. */
310 typedef struct sym_or_tv_t {
311         union {
312                 ir_entity  *entity;  /**< An entity. */
313                 tarval     *tv;      /**< A tarval. */
314                 const void *generic; /**< For generic compare. */
315         } u;
316         unsigned label;      /**< the associated label. */
317         bool     is_entity;  /**< true if an entity is stored. */
318 } sym_or_tv_t;
319
320 /**
321  * Returns a unique label. This number will not be used a second time.
322  */
323 static unsigned get_unique_label(void)
324 {
325         static unsigned id = 0;
326         return ++id;
327 }
328
329 static void emit_constant_name(const sym_or_tv_t *entry)
330 {
331         be_emit_irprintf("%sC%u", be_gas_get_private_prefix(), entry->label);
332 }
333
334 /**
335  * Emit a SymConst.
336  */
337 static void emit_arm_SymConst(const ir_node *irn)
338 {
339         const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
340         sym_or_tv_t key, *entry;
341         unsigned label;
342
343         key.u.entity  = attr->entity;
344         key.is_entity = true;
345         key.label     = 0;
346         entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
347         if (entry->label == 0) {
348                 /* allocate a label */
349                 entry->label = get_unique_label();
350         }
351         label = entry->label;
352
353         /* load the symbol indirect */
354         be_emit_cstring("\tldr ");
355         arm_emit_dest_register(irn, 0);
356         be_emit_cstring(", ");
357         emit_constant_name(entry);
358         be_emit_finish_line_gas(irn);
359 }
360
361 static void emit_arm_FrameAddr(const ir_node *irn)
362 {
363         const arm_SymConst_attr_t *attr = get_irn_generic_attr_const(irn);
364
365         be_emit_cstring("\tadd ");
366         arm_emit_dest_register(irn, 0);
367         be_emit_cstring(", ");
368         arm_emit_source_register(irn, 0);
369         be_emit_cstring(", ");
370         be_emit_irprintf("#0x%X", attr->fp_offset);
371         be_emit_finish_line_gas(irn);
372 }
373
374 /**
375  * Emit a floating point fpa constant.
376  */
377 static void emit_arm_fpaConst(const ir_node *irn)
378 {
379         sym_or_tv_t key, *entry;
380         unsigned label;
381         ir_mode *mode;
382
383         key.u.tv      = get_fpaConst_value(irn);
384         key.is_entity = false;
385         key.label     = 0;
386         entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
387         if (entry->label == 0) {
388                 /* allocate a label */
389                 entry->label = get_unique_label();
390         }
391         label = entry->label;
392
393         /* load the tarval indirect */
394         mode = get_irn_mode(irn);
395         be_emit_cstring("\tldf");
396         arm_emit_fpa_postfix(mode);
397         be_emit_char(' ');
398
399         arm_emit_dest_register(irn, 0);
400         be_emit_cstring(", ");
401         emit_constant_name(entry);
402         be_emit_finish_line_gas(irn);
403 }
404
405 /**
406  * Returns the next block in a block schedule.
407  */
408 static ir_node *sched_next_block(const ir_node *block)
409 {
410     return get_irn_link(block);
411 }
412
413 /**
414  * Returns the target block for a control flow node.
415  */
416 static ir_node *get_cfop_target_block(const ir_node *irn)
417 {
418         return get_irn_link(irn);
419 }
420
421 /**
422  * Emit the target label for a control flow node.
423  */
424 static void arm_emit_cfop_target(const ir_node *irn)
425 {
426         ir_node *block = get_cfop_target_block(irn);
427
428         be_gas_emit_block_name(block);
429 }
430
431 /**
432  * Emit a Compare with conditional branch.
433  */
434 static void emit_arm_B(const ir_node *irn)
435 {
436         const ir_edge_t *edge;
437         const ir_node *proj_true  = NULL;
438         const ir_node *proj_false = NULL;
439         const ir_node *block;
440         const ir_node *next_block;
441         ir_node *op1 = get_irn_n(irn, 0);
442         const char *suffix;
443         pn_Cmp pnc = get_arm_CondJmp_pnc(irn);
444         const arm_cmp_attr_t *cmp_attr = get_irn_generic_attr_const(op1);
445         bool is_signed = !cmp_attr->is_unsigned;
446
447         assert(is_arm_Cmp(op1) || is_arm_Tst(op1));
448
449         foreach_out_edge(irn, edge) {
450                 ir_node *proj = get_edge_src_irn(edge);
451                 long nr = get_Proj_proj(proj);
452                 if (nr == pn_Cond_true) {
453                         proj_true = proj;
454                 } else {
455                         proj_false = proj;
456                 }
457         }
458
459         if (cmp_attr->ins_permuted) {
460                 pnc = get_mirrored_pnc(pnc);
461         }
462
463         /* for now, the code works for scheduled and non-schedules blocks */
464         block = get_nodes_block(irn);
465
466         /* we have a block schedule */
467         next_block = sched_next_block(block);
468
469         assert(pnc != pn_Cmp_False);
470         assert(pnc != pn_Cmp_True);
471
472         if (get_cfop_target_block(proj_true) == next_block) {
473                 /* exchange both proj's so the second one can be omitted */
474                 const ir_node *t = proj_true;
475
476                 proj_true  = proj_false;
477                 proj_false = t;
478                 pnc        = get_negated_pnc(pnc, mode_Iu);
479         }
480
481         switch (pnc) {
482                 case pn_Cmp_Eq:  suffix = "eq"; break;
483                 case pn_Cmp_Lt:  suffix = is_signed ? "lt" : "lo"; break;
484                 case pn_Cmp_Le:  suffix = is_signed ? "le" : "ls"; break;
485                 case pn_Cmp_Gt:  suffix = is_signed ? "gt" : "hi"; break;
486                 case pn_Cmp_Ge:  suffix = is_signed ? "ge" : "hs"; break;
487                 case pn_Cmp_Lg:  suffix = "ne"; break;
488                 case pn_Cmp_Leg: suffix = "al"; break;
489                 default: panic("Cmp has unsupported pnc");
490         }
491
492         /* emit the true proj */
493         be_emit_irprintf("\tb%s ", suffix);
494         arm_emit_cfop_target(proj_true);
495         be_emit_finish_line_gas(proj_true);
496
497         if (get_cfop_target_block(proj_false) == next_block) {
498                 be_emit_cstring("\t/* fallthrough to ");
499                 arm_emit_cfop_target(proj_false);
500                 be_emit_cstring(" */");
501                 be_emit_finish_line_gas(proj_false);
502         } else {
503                 be_emit_cstring("\tb ");
504                 arm_emit_cfop_target(proj_false);
505                 be_emit_finish_line_gas(proj_false);
506         }
507 }
508
509 /** Sort register in ascending order. */
510 static int reg_cmp(const void *a, const void *b)
511 {
512         const arch_register_t * const *ra = a;
513         const arch_register_t * const *rb = b;
514
515         return *ra < *rb ? -1 : (*ra != *rb);
516 }
517
518 /**
519  * Create the CopyB instruction sequence.
520  */
521 static void emit_arm_CopyB(const ir_node *irn)
522 {
523         const arm_CopyB_attr_t *attr = get_irn_generic_attr_const(irn);
524         unsigned size = attr->size;
525
526         const char *tgt = arch_register_get_name(get_in_reg(irn, 0));
527         const char *src = arch_register_get_name(get_in_reg(irn, 1));
528         const char *t0, *t1, *t2, *t3;
529
530         const arch_register_t *tmpregs[4];
531
532         /* collect the temporary registers and sort them, we need ascending order */
533         tmpregs[0] = get_in_reg(irn, 2);
534         tmpregs[1] = get_in_reg(irn, 3);
535         tmpregs[2] = get_in_reg(irn, 4);
536         tmpregs[3] = &arm_gp_regs[REG_R12];
537
538         /* Note: R12 is always the last register because the RA did not assign higher ones */
539         qsort((void *)tmpregs, 3, sizeof(tmpregs[0]), reg_cmp);
540
541         /* need ascending order */
542         t0 = arch_register_get_name(tmpregs[0]);
543         t1 = arch_register_get_name(tmpregs[1]);
544         t2 = arch_register_get_name(tmpregs[2]);
545         t3 = arch_register_get_name(tmpregs[3]);
546
547         be_emit_cstring("/* MemCopy (");
548         be_emit_string(src);
549         be_emit_cstring(")->(");
550         arm_emit_source_register(irn, 0);
551         be_emit_irprintf(" [%u bytes], Uses ", size);
552         be_emit_string(t0);
553         be_emit_cstring(", ");
554         be_emit_string(t1);
555         be_emit_cstring(", ");
556         be_emit_string(t2);
557         be_emit_cstring(", and ");
558         be_emit_string(t3);
559         be_emit_cstring("*/");
560         be_emit_finish_line_gas(NULL);
561
562         assert(size > 0 && "CopyB needs size > 0" );
563
564         if (size & 3) {
565                 fprintf(stderr, "strange hack enabled: copy more bytes than needed!");
566                 size += 4;
567         }
568
569         size >>= 2;
570         switch (size & 3) {
571         case 0:
572                 break;
573         case 1:
574                 be_emit_cstring("\tldr ");
575                 be_emit_string(t3);
576                 be_emit_cstring(", [");
577                 be_emit_string(src);
578                 be_emit_cstring(", #0]");
579                 be_emit_finish_line_gas(NULL);
580
581                 be_emit_cstring("\tstr ");
582                 be_emit_string(t3);
583                 be_emit_cstring(", [");
584                 be_emit_string(tgt);
585                 be_emit_cstring(", #0]");
586                 be_emit_finish_line_gas(irn);
587                 break;
588         case 2:
589                 be_emit_cstring("\tldmia ");
590                 be_emit_string(src);
591                 be_emit_cstring("!, {");
592                 be_emit_string(t0);
593                 be_emit_cstring(", ");
594                 be_emit_string(t1);
595                 be_emit_char('}');
596                 be_emit_finish_line_gas(NULL);
597
598                 be_emit_cstring("\tstmia ");
599                 be_emit_string(tgt);
600                 be_emit_cstring("!, {");
601                 be_emit_string(t0);
602                 be_emit_cstring(", ");
603                 be_emit_string(t1);
604                 be_emit_char('}');
605                 be_emit_finish_line_gas(irn);
606                 break;
607         case 3:
608                 be_emit_cstring("\tldmia ");
609                 be_emit_string(src);
610                 be_emit_cstring("!, {");
611                 be_emit_string(t0);
612                 be_emit_cstring(", ");
613                 be_emit_string(t1);
614                 be_emit_cstring(", ");
615                 be_emit_string(t2);
616                 be_emit_char('}');
617                 be_emit_finish_line_gas(NULL);
618
619                 be_emit_cstring("\tstmia ");
620                 be_emit_string(tgt);
621                 be_emit_cstring("!, {");
622                 be_emit_string(t0);
623                 be_emit_cstring(", ");
624                 be_emit_string(t1);
625                 be_emit_cstring(", ");
626                 be_emit_string(t2);
627                 be_emit_char('}');
628                 be_emit_finish_line_gas(irn);
629                 break;
630         }
631         size >>= 2;
632         while (size) {
633                 be_emit_cstring("\tldmia ");
634                 be_emit_string(src);
635                 be_emit_cstring("!, {");
636                 be_emit_string(t0);
637                 be_emit_cstring(", ");
638                 be_emit_string(t1);
639                 be_emit_cstring(", ");
640                 be_emit_string(t2);
641                 be_emit_cstring(", ");
642                 be_emit_string(t3);
643                 be_emit_char('}');
644                 be_emit_finish_line_gas(NULL);
645
646                 be_emit_cstring("\tstmia ");
647                 be_emit_string(tgt);
648                 be_emit_cstring("!, {");
649                 be_emit_string(t0);
650                 be_emit_cstring(", ");
651                 be_emit_string(t1);
652                 be_emit_cstring(", ");
653                 be_emit_string(t2);
654                 be_emit_cstring(", ");
655                 be_emit_string(t3);
656                 be_emit_char('}');
657                 be_emit_finish_line_gas(irn);
658                 --size;
659         }
660 }
661
662 static void emit_arm_SwitchJmp(const ir_node *irn)
663 {
664         const ir_edge_t    *edge;
665         ir_node            *proj;
666         int i;
667         ir_node **projs;
668         int n_projs;
669         int block_nr;
670         ir_node *default_proj = NULL;
671
672         block_nr = get_irn_node_nr(irn);
673         n_projs = get_arm_SwitchJmp_n_projs(irn);
674
675         projs = XMALLOCNZ(ir_node*, n_projs);
676
677         foreach_out_edge(irn, edge) {
678                 proj = get_edge_src_irn(edge);
679                 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
680
681                 if (get_Proj_proj(proj) == get_arm_SwitchJmp_default_proj_num(irn))
682                         default_proj = proj;
683
684                 projs[get_Proj_proj(proj)] = proj;
685         }
686         assert(default_proj != NULL && "SwitchJmp should have a Default Proj");
687
688         /*
689            CMP %1S, n_projs - 1
690            BHI default
691         */
692
693         be_emit_cstring("\tcmp ");
694         arm_emit_source_register(irn, 0);
695         be_emit_irprintf(", #%u", n_projs - 1);
696         be_emit_finish_line_gas(irn);
697
698         be_emit_cstring("\tbhi ");
699         arm_emit_cfop_target(default_proj);
700         be_emit_finish_line_gas(default_proj);
701
702         /*
703            LDR %r12, .TABLE_X_START
704            ADD %r12, %r12, [%1S, LSL #2]
705            LDR %r15, %r12
706          */
707
708         be_emit_irprintf("\tldr %%r12, TABLE_%d_START", block_nr);
709         be_emit_finish_line_gas(NULL);
710
711         be_emit_irprintf("\tadd %%r12, %%r12, ");
712         arm_emit_source_register(irn, 0);
713         be_emit_cstring(", LSL #2");
714         be_emit_finish_line_gas(NULL);
715
716         be_emit_cstring("\tldr %r15, [%r12, #0]");
717         be_emit_finish_line_gas(NULL);
718
719         be_emit_irprintf("TABLE_%d_START:\n\t.word\tTABLE_%d", block_nr, block_nr);
720         be_emit_finish_line_gas(NULL);
721         be_emit_irprintf("\t.align 2");
722         be_emit_finish_line_gas(NULL);
723         be_emit_irprintf("TABLE_%d:", block_nr);
724         be_emit_finish_line_gas(NULL);
725
726         for (i = 0; i < n_projs; ++i) {
727                 proj = projs[i];
728                 if (proj == NULL) {
729                         proj = projs[get_arm_SwitchJmp_default_proj_num(irn)];
730                 }
731                 be_emit_cstring("\t.word\t");
732                 arm_emit_cfop_target(proj);
733                 be_emit_finish_line_gas(proj);
734         }
735         be_emit_irprintf("\t.align 2\n");
736         be_emit_finish_line_gas(NULL);
737         xfree(projs);
738 }
739
740
741 static void arm_emit_entity(ir_entity *entity)
742 {
743         be_emit_ident(get_entity_ld_ident(entity));
744 }
745
746 static void emit_be_Call(const ir_node *irn)
747 {
748         ir_entity *entity = be_Call_get_entity(irn);
749
750         if (entity != NULL) {
751                 be_emit_cstring("\tbl ");
752                 arm_emit_entity(entity);
753                 be_emit_finish_line_gas(irn);
754         } else {
755                 be_emit_cstring("\tmov lr, pc");
756                 be_emit_finish_line_gas(irn);
757                 be_emit_cstring("\tmov pc, ");
758                 arm_emit_source_register(irn, be_pos_Call_ptr);
759                 be_emit_finish_line_gas(irn);
760         }
761 }
762
763 /** Emit an IncSP node */
764 static void emit_be_IncSP(const ir_node *irn)
765 {
766         int offs = -be_get_IncSP_offset(irn);
767
768         if (offs != 0) {
769                 if (offs < 0) {
770                         be_emit_cstring("\tsub ");
771                         offs = -offs;
772                 } else {
773                         be_emit_cstring("\tadd ");
774                 }
775                 arm_emit_dest_register(irn, 0);
776                 be_emit_cstring(", ");
777                 arm_emit_source_register(irn, 0);
778                 be_emit_irprintf(", #0x%X", offs);
779         } else {
780                 /* omitted IncSP(0) */
781                 return;
782         }
783         be_emit_finish_line_gas(irn);
784 }
785
786 static void emit_be_Copy(const ir_node *irn)
787 {
788         ir_mode *mode = get_irn_mode(irn);
789
790         if (get_in_reg(irn, 0) == get_out_reg(irn, 0)) {
791                 /* omitted Copy */
792                 return;
793         }
794
795         if (mode_is_float(mode)) {
796                 if (USE_FPA(cg->isa)) {
797                         be_emit_cstring("\tmvf");
798                         arm_emit_mode(irn);
799                         be_emit_char(' ');
800                         arm_emit_dest_register(irn, 0);
801                         be_emit_cstring(", ");
802                         arm_emit_source_register(irn, 0);
803                         be_emit_finish_line_gas(irn);
804                 } else {
805                         panic("emit_be_Copy: move not supported for this mode");
806                 }
807         } else if (mode_is_data(mode)) {
808                 be_emit_cstring("\tmov ");
809                 arm_emit_dest_register(irn, 0);
810                 be_emit_cstring(", ");
811                 arm_emit_source_register(irn, 0);
812                 be_emit_finish_line_gas(irn);
813         } else {
814                 panic("emit_be_Copy: move not supported for this mode");
815         }
816 }
817
818 static void emit_be_Perm(const ir_node *irn)
819 {
820         be_emit_cstring("\teor ");
821         arm_emit_source_register(irn, 0);
822         be_emit_cstring(", ");
823         arm_emit_source_register(irn, 0);
824         be_emit_cstring(", ");
825         arm_emit_source_register(irn, 1);
826         be_emit_finish_line_gas(NULL);
827
828         be_emit_cstring("\teor ");
829         arm_emit_source_register(irn, 1);
830         be_emit_cstring(", ");
831         arm_emit_source_register(irn, 0);
832         be_emit_cstring(", ");
833         arm_emit_source_register(irn, 1);
834         be_emit_finish_line_gas(NULL);
835
836         be_emit_cstring("\teor ");
837         arm_emit_source_register(irn, 0);
838         be_emit_cstring(", ");
839         arm_emit_source_register(irn, 0);
840         be_emit_cstring(", ");
841         arm_emit_source_register(irn, 1);
842         be_emit_finish_line_gas(irn);
843 }
844
845 static void emit_be_MemPerm(const ir_node *node)
846 {
847         int i;
848         int memperm_arity;
849         int sp_change = 0;
850
851         /* TODO: this implementation is slower than necessary.
852            The longterm goal is however to avoid the memperm node completely */
853
854         memperm_arity = be_get_MemPerm_entity_arity(node);
855         if (memperm_arity > 12)
856                 panic("memperm with more than 12 inputs not supported yet");
857
858         for (i = 0; i < memperm_arity; ++i) {
859                 int offset;
860                 ir_entity *entity = be_get_MemPerm_in_entity(node, i);
861
862                 /* spill register */
863                 be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
864                 be_emit_finish_line_gas(node);
865                 sp_change += 4;
866                 /* load from entity */
867                 offset = get_entity_offset(entity) + sp_change;
868                 be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
869                 be_emit_finish_line_gas(node);
870         }
871
872         for (i = memperm_arity-1; i >= 0; --i) {
873                 int        offset;
874                 ir_entity *entity = be_get_MemPerm_out_entity(node, i);
875
876                 /* store to new entity */
877                 offset = get_entity_offset(entity) + sp_change;
878                 be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
879                 be_emit_finish_line_gas(node);
880                 /* restore register */
881                 be_emit_irprintf("\tldr r%d, [sp], #4", i);
882                 sp_change -= 4;
883                 be_emit_finish_line_gas(node);
884         }
885         assert(sp_change == 0);
886 }
887
888 static void emit_be_Return(const ir_node *node)
889 {
890         be_emit_cstring("\tmov pc, lr");
891         be_emit_finish_line_gas(node);
892 }
893
894
895 static void emit_arm_Jmp(const ir_node *node)
896 {
897         ir_node *block, *next_block;
898
899         /* for now, the code works for scheduled and non-schedules blocks */
900         block = get_nodes_block(node);
901
902         /* we have a block schedule */
903         next_block = sched_next_block(block);
904         if (get_cfop_target_block(node) != next_block) {
905                 be_emit_cstring("\tb ");
906                 arm_emit_cfop_target(node);
907         } else {
908                 be_emit_cstring("\t/* fallthrough to ");
909                 arm_emit_cfop_target(node);
910                 be_emit_cstring(" */");
911         }
912         be_emit_finish_line_gas(node);
913 }
914
915 static void emit_arm_fpaDbl2GP(const ir_node *irn)
916 {
917         be_emit_cstring("\tstfd ");
918         arm_emit_source_register(irn, 0);
919         be_emit_cstring(", [sp, #-8]!");
920         be_emit_pad_comment();
921         be_emit_cstring("/* Push fp to stack */");
922         be_emit_finish_line_gas(NULL);
923
924         be_emit_cstring("\tldmfd sp!, {");
925         arm_emit_dest_register(irn, 1);
926         be_emit_cstring(", ");
927         arm_emit_dest_register(irn, 0);
928         be_emit_char('}');
929         be_emit_pad_comment();
930         be_emit_cstring("/* Pop destination */");
931         be_emit_finish_line_gas(irn);
932 }
933
934 static void emit_arm_LdTls(const ir_node *irn)
935 {
936         (void) irn;
937         panic("TLS not supported for this target");
938         /* Er... our gcc does not support it... Install a newer toolchain. */
939 }
940
941 static void emit_nothing(const ir_node *irn)
942 {
943         (void) irn;
944 }
945
946 /**
947  * The type of a emitter function.
948  */
949 typedef void (emit_func)(const ir_node *irn);
950
951 /**
952  * Set a node emitter. Make it a bit more type safe.
953  */
954 static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
955 {
956         op->ops.generic = (op_func)arm_emit_node;
957 }
958
959 /**
960  * Enters the emitter functions for handled nodes into the generic
961  * pointer of an opcode.
962  */
963 static void arm_register_emitters(void)
964 {
965         /* first clear the generic function pointer for all ops */
966         clear_irp_opcodes_generic_func();
967
968         /* register all emitter functions defined in spec */
969         arm_register_spec_emitters();
970
971         /* custom emitter */
972         set_emitter(op_arm_B,          emit_arm_B);
973         set_emitter(op_arm_CopyB,      emit_arm_CopyB);
974         set_emitter(op_arm_fpaConst,   emit_arm_fpaConst);
975         set_emitter(op_arm_fpaDbl2GP,  emit_arm_fpaDbl2GP);
976         set_emitter(op_arm_FrameAddr,  emit_arm_FrameAddr);
977         set_emitter(op_arm_Jmp,        emit_arm_Jmp);
978         set_emitter(op_arm_LdTls,      emit_arm_LdTls);
979         set_emitter(op_arm_SwitchJmp,  emit_arm_SwitchJmp);
980         set_emitter(op_arm_SymConst,   emit_arm_SymConst);
981         set_emitter(op_be_Call,        emit_be_Call);
982         set_emitter(op_be_Copy,        emit_be_Copy);
983         set_emitter(op_be_CopyKeep,    emit_be_Copy);
984         set_emitter(op_be_IncSP,       emit_be_IncSP);
985         set_emitter(op_be_MemPerm,     emit_be_MemPerm);
986         set_emitter(op_be_Perm,        emit_be_Perm);
987         set_emitter(op_be_Return,      emit_be_Return);
988
989         /* no need to emit anything for the following nodes */
990         set_emitter(op_Phi,            emit_nothing);
991         set_emitter(op_be_Keep,        emit_nothing);
992         set_emitter(op_be_Start,       emit_nothing);
993         set_emitter(op_be_Barrier,     emit_nothing);
994 }
995
996 /**
997  * Emits code for a node.
998  */
999 static void arm_emit_node(const ir_node *irn)
1000 {
1001         ir_op *op = get_irn_op(irn);
1002
1003         if (op->ops.generic) {
1004                 emit_func *emit = (emit_func *)op->ops.generic;
1005                 be_dbg_set_dbg_info(get_irn_dbg_info(irn));
1006                 (*emit)(irn);
1007         } else {
1008                 panic("Error: No emit handler for node %+F (graph %+F)\n",
1009                       irn, current_ir_graph);
1010         }
1011 }
1012
1013 /**
1014  * emit the block label if needed.
1015  */
1016 static void arm_emit_block_header(ir_node *block, ir_node *prev)
1017 {
1018         int           n_cfgpreds;
1019         int           need_label;
1020         int           i, arity;
1021         ir_exec_freq  *exec_freq = be_get_irg_exec_freq(cg->irg);
1022
1023         need_label = 0;
1024         n_cfgpreds = get_Block_n_cfgpreds(block);
1025         if (n_cfgpreds == 1) {
1026                 ir_node *pred       = get_Block_cfgpred(block, 0);
1027                 ir_node *pred_block = get_nodes_block(pred);
1028
1029                 /* we don't need labels for fallthrough blocks, however switch-jmps
1030                  * are no fallthroughs */
1031                 if (pred_block == prev &&
1032                                 !(is_Proj(pred) && is_arm_SwitchJmp(get_Proj_pred(pred)))) {
1033                         need_label = 0;
1034                 } else {
1035                         need_label = 1;
1036                 }
1037         } else {
1038                 need_label = 1;
1039         }
1040
1041         if (need_label) {
1042                 be_gas_emit_block_name(block);
1043                 be_emit_char(':');
1044
1045                 be_emit_pad_comment();
1046                 be_emit_cstring("   /* preds:");
1047
1048                 /* emit list of pred blocks in comment */
1049                 arity = get_irn_arity(block);
1050                 for (i = 0; i < arity; ++i) {
1051                         ir_node *predblock = get_Block_cfgpred_block(block, i);
1052                         be_emit_irprintf(" %d", get_irn_node_nr(predblock));
1053                 }
1054         } else {
1055                 be_emit_cstring("\t/* ");
1056                 be_gas_emit_block_name(block);
1057                 be_emit_cstring(": ");
1058         }
1059         if (exec_freq != NULL) {
1060                 be_emit_irprintf(" freq: %f",
1061                                  get_block_execfreq(exec_freq, block));
1062         }
1063         be_emit_cstring(" */\n");
1064         be_emit_write_line();
1065 }
1066
1067 /**
1068  * Walks over the nodes in a block connected by scheduling edges
1069  * and emits code for each node.
1070  */
1071 static void arm_gen_block(ir_node *block, ir_node *prev_block)
1072 {
1073         ir_node *irn;
1074
1075         arm_emit_block_header(block, prev_block);
1076         be_dbg_set_dbg_info(get_irn_dbg_info(block));
1077         sched_foreach(block, irn) {
1078                 arm_emit_node(irn);
1079         }
1080 }
1081
1082 /**
1083  * Block-walker:
1084  * Sets labels for control flow nodes (jump target)
1085  */
1086 static void arm_gen_labels(ir_node *block, void *env)
1087 {
1088         ir_node *pred;
1089         int n = get_Block_n_cfgpreds(block);
1090         (void)env;
1091
1092         for (n--; n >= 0; n--) {
1093                 pred = get_Block_cfgpred(block, n);
1094                 set_irn_link(pred, block);
1095         }
1096 }
1097
1098 /**
1099  * Compare two entries of the symbol or tarval set.
1100  */
1101 static int cmp_sym_or_tv(const void *elt, const void *key, size_t size)
1102 {
1103         const sym_or_tv_t *p1 = elt;
1104         const sym_or_tv_t *p2 = key;
1105         (void) size;
1106
1107         /* as an identifier NEVER can point to a tarval, it's enough
1108            to compare it this way */
1109         return p1->u.generic != p2->u.generic;
1110 }
1111
1112 /**
1113  * Main driver. Emits the code for one routine.
1114  */
1115 void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg)
1116 {
1117         ir_node   **blk_sched;
1118         int       i, n;
1119         ir_node   *last_block = NULL;
1120         ir_entity *entity     = get_irg_entity(irg);
1121
1122         cg        = arm_cg;
1123         sym_or_tv = new_set(cmp_sym_or_tv, 8);
1124
1125         be_gas_elf_type_char = '%';
1126
1127         arm_register_emitters();
1128
1129         be_dbg_method_begin(entity);
1130
1131         /* create the block schedule */
1132         blk_sched = be_create_block_schedule(irg);
1133
1134         be_gas_emit_function_prolog(entity, 4);
1135
1136         irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
1137
1138         n = ARR_LEN(blk_sched);
1139         for (i = 0; i < n;) {
1140                 ir_node *block, *next_bl;
1141
1142                 block   = blk_sched[i];
1143                 ++i;
1144                 next_bl = i < n ? blk_sched[i] : NULL;
1145
1146                 /* set here the link. the emitter expects to find the next block here */
1147                 set_irn_link(block, next_bl);
1148                 arm_gen_block(block, last_block);
1149                 last_block = block;
1150         }
1151
1152         /* emit SymConst values */
1153         if (set_count(sym_or_tv) > 0) {
1154                 sym_or_tv_t *entry;
1155
1156                 be_emit_cstring("\t.align 2\n");
1157
1158                 foreach_set(sym_or_tv, entry) {
1159                         emit_constant_name(entry);
1160                         be_emit_cstring(":\n");
1161                         be_emit_write_line();
1162
1163                         if (entry->is_entity) {
1164                                 be_emit_cstring("\t.word\t");
1165                                 be_gas_emit_entity(entry->u.entity);
1166                                 be_emit_char('\n');
1167                                 be_emit_write_line();
1168                         } else {
1169                                 tarval *tv = entry->u.tv;
1170                                 int i, size = get_mode_size_bytes(get_tarval_mode(tv));
1171                                 unsigned v;
1172
1173                                 /* beware: ARM fpa uses big endian format */
1174                                 for (i = ((size + 3) & ~3) - 4; i >= 0; i -= 4) {
1175                                         /* get 32 bits */
1176                                         v =            get_tarval_sub_bits(tv, i+3);
1177                                         v = (v << 8) | get_tarval_sub_bits(tv, i+2);
1178                                         v = (v << 8) | get_tarval_sub_bits(tv, i+1);
1179                                         v = (v << 8) | get_tarval_sub_bits(tv, i+0);
1180                                         be_emit_irprintf("\t.word\t%u\n", v);
1181                                         be_emit_write_line();
1182                                 }
1183                         }
1184                 }
1185                 be_emit_char('\n');
1186                 be_emit_write_line();
1187         }
1188         del_set(sym_or_tv);
1189
1190         be_gas_emit_function_epilog(entity);
1191         be_dbg_method_end();
1192 }
1193
1194 void arm_init_emitter(void)
1195 {
1196         FIRM_DBG_REGISTER(dbg, "firm.be.arm.emit");
1197 }