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