- fix most of the -Wunreachable-code and -Wlogical-op warnings
[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                 fprintf(stderr, "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                         panic("emit_be_Copy: move not supported for this mode");
792                 }
793         } else if (mode_is_data(mode)) {
794                 be_emit_cstring("\tmov ");
795                 arm_emit_dest_register(irn, 0);
796                 be_emit_cstring(", ");
797                 arm_emit_source_register(irn, 0);
798                 be_emit_finish_line_gas(irn);
799         } else {
800                 panic("emit_be_Copy: move not supported for this mode");
801         }
802 }
803
804 static void emit_be_Perm(const ir_node *irn)
805 {
806         be_emit_cstring("\teor ");
807         arm_emit_source_register(irn, 0);
808         be_emit_cstring(", ");
809         arm_emit_source_register(irn, 0);
810         be_emit_cstring(", ");
811         arm_emit_source_register(irn, 1);
812         be_emit_finish_line_gas(NULL);
813
814         be_emit_cstring("\teor ");
815         arm_emit_source_register(irn, 1);
816         be_emit_cstring(", ");
817         arm_emit_source_register(irn, 0);
818         be_emit_cstring(", ");
819         arm_emit_source_register(irn, 1);
820         be_emit_finish_line_gas(NULL);
821
822         be_emit_cstring("\teor ");
823         arm_emit_source_register(irn, 0);
824         be_emit_cstring(", ");
825         arm_emit_source_register(irn, 0);
826         be_emit_cstring(", ");
827         arm_emit_source_register(irn, 1);
828         be_emit_finish_line_gas(irn);
829 }
830
831 static void emit_be_MemPerm(const ir_node *node)
832 {
833         int i;
834         int memperm_arity;
835         int sp_change = 0;
836
837         /* TODO: this implementation is slower than necessary.
838            The longterm goal is however to avoid the memperm node completely */
839
840         memperm_arity = be_get_MemPerm_entity_arity(node);
841         if (memperm_arity > 12)
842                 panic("memperm with more than 12 inputs not supported yet");
843
844         for (i = 0; i < memperm_arity; ++i) {
845                 int offset;
846                 ir_entity *entity = be_get_MemPerm_in_entity(node, i);
847
848                 /* spill register */
849                 be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
850                 be_emit_finish_line_gas(node);
851                 sp_change += 4;
852                 /* load from entity */
853                 offset = get_entity_offset(entity) + sp_change;
854                 be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
855                 be_emit_finish_line_gas(node);
856         }
857
858         for (i = memperm_arity-1; i >= 0; --i) {
859                 int        offset;
860                 ir_entity *entity = be_get_MemPerm_out_entity(node, i);
861
862                 /* store to new entity */
863                 offset = get_entity_offset(entity) + sp_change;
864                 be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
865                 be_emit_finish_line_gas(node);
866                 /* restore register */
867                 be_emit_irprintf("\tldr r%d, [sp], #4", i);
868                 sp_change -= 4;
869                 be_emit_finish_line_gas(node);
870         }
871         assert(sp_change == 0);
872 }
873
874 static void emit_be_Return(const ir_node *node)
875 {
876         be_emit_cstring("\tmov pc, lr");
877         be_emit_finish_line_gas(node);
878 }
879
880 /************************************************************************/
881 /* emit                                                                 */
882 /************************************************************************/
883
884 static void emit_arm_Jmp(const ir_node *node)
885 {
886         ir_node *block, *next_block;
887
888         /* for now, the code works for scheduled and non-schedules blocks */
889         block = get_nodes_block(node);
890
891         /* we have a block schedule */
892         next_block = sched_next_block(block);
893         if (get_cfop_target_block(node) != next_block) {
894                 be_emit_cstring("\tb ");
895                 arm_emit_cfop_target(node);
896         } else {
897                 be_emit_cstring("\t/* fallthrough to ");
898                 arm_emit_cfop_target(node);
899                 be_emit_cstring(" */");
900         }
901         be_emit_finish_line_gas(node);
902 }
903
904 static void emit_arm_fpaDbl2GP(const ir_node *irn)
905 {
906         be_emit_cstring("\tstfd ");
907         arm_emit_source_register(irn, 0);
908         be_emit_cstring(", [sp, #-8]!");
909         be_emit_pad_comment();
910         be_emit_cstring("/* Push fp to stack */");
911         be_emit_finish_line_gas(NULL);
912
913         be_emit_cstring("\tldmfd sp!, {");
914         arm_emit_dest_register(irn, 1);
915         be_emit_cstring(", ");
916         arm_emit_dest_register(irn, 0);
917         be_emit_char('}');
918         be_emit_pad_comment();
919         be_emit_cstring("/* Pop destination */");
920         be_emit_finish_line_gas(irn);
921 }
922
923 static void emit_arm_LdTls(const ir_node *irn)
924 {
925         (void) irn;
926         panic("TLS not supported for this target");
927         /* Er... our gcc does not support it... Install a newer toolchain. */
928 }
929
930 static void emit_nothing(const ir_node *irn)
931 {
932         (void) irn;
933 }
934
935 /**
936  * The type of a emitter function.
937  */
938 typedef void (emit_func)(const ir_node *irn);
939
940 /**
941  * Set a node emitter. Make it a bit more type safe.
942  */
943 static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
944 {
945         op->ops.generic = (op_func)arm_emit_node;
946 }
947
948 /**
949  * Enters the emitter functions for handled nodes into the generic
950  * pointer of an opcode.
951  */
952 static void arm_register_emitters(void)
953 {
954         /* first clear the generic function pointer for all ops */
955         clear_irp_opcodes_generic_func();
956
957         /* register all emitter functions defined in spec */
958         arm_register_spec_emitters();
959
960         /* custom emitter */
961         set_emitter(op_arm_B,          emit_arm_B);
962         set_emitter(op_arm_CopyB,      emit_arm_CopyB);
963         set_emitter(op_arm_fpaConst,   emit_arm_fpaConst);
964         set_emitter(op_arm_fpaDbl2GP,  emit_arm_fpaDbl2GP);
965         set_emitter(op_arm_FrameAddr,  emit_arm_FrameAddr);
966         set_emitter(op_arm_Jmp,        emit_arm_Jmp);
967         set_emitter(op_arm_LdTls,      emit_arm_LdTls);
968         set_emitter(op_arm_SwitchJmp,  emit_arm_SwitchJmp);
969         set_emitter(op_arm_SymConst,   emit_arm_SymConst);
970         set_emitter(op_be_Call,        emit_be_Call);
971         set_emitter(op_be_Copy,        emit_be_Copy);
972         set_emitter(op_be_CopyKeep,    emit_be_Copy);
973         set_emitter(op_be_IncSP,       emit_be_IncSP);
974         set_emitter(op_be_MemPerm,     emit_be_MemPerm);
975         set_emitter(op_be_Perm,        emit_be_Perm);
976         set_emitter(op_be_Return,      emit_be_Return);
977
978         /* no need to emit anything for the following nodes */
979         set_emitter(op_Phi,            emit_nothing);
980         set_emitter(op_be_Keep,        emit_nothing);
981         set_emitter(op_be_Start,       emit_nothing);
982         set_emitter(op_be_Barrier,     emit_nothing);
983 }
984
985 /**
986  * Emits code for a node.
987  */
988 static void arm_emit_node(const ir_node *irn)
989 {
990         ir_op *op = get_irn_op(irn);
991
992         if (op->ops.generic) {
993                 emit_func *emit = (emit_func *)op->ops.generic;
994                 be_dbg_set_dbg_info(get_irn_dbg_info(irn));
995                 (*emit)(irn);
996         } else {
997                 panic("Error: No emit handler for node %+F (graph %+F)\n",
998                       irn, current_ir_graph);
999         }
1000 }
1001
1002 /**
1003  * emit the block label if needed.
1004  */
1005 static void arm_emit_block_header(ir_node *block, ir_node *prev)
1006 {
1007         int           n_cfgpreds;
1008         int           need_label;
1009         int           i, arity;
1010         ir_exec_freq  *exec_freq = cg->birg->exec_freq;
1011
1012         need_label = 0;
1013         n_cfgpreds = get_Block_n_cfgpreds(block);
1014         if (n_cfgpreds == 1) {
1015                 ir_node *pred       = get_Block_cfgpred(block, 0);
1016                 ir_node *pred_block = get_nodes_block(pred);
1017
1018                 /* we don't need labels for fallthrough blocks, however switch-jmps
1019                  * are no fallthroughs */
1020                 if (pred_block == prev &&
1021                                 !(is_Proj(pred) && is_arm_SwitchJmp(get_Proj_pred(pred)))) {
1022                         need_label = 0;
1023                 } else {
1024                         need_label = 1;
1025                 }
1026         } else {
1027                 need_label = 1;
1028         }
1029
1030         if (need_label) {
1031                 be_gas_emit_block_name(block);
1032                 be_emit_char(':');
1033
1034                 be_emit_pad_comment();
1035                 be_emit_cstring("   /* preds:");
1036
1037                 /* emit list of pred blocks in comment */
1038                 arity = get_irn_arity(block);
1039                 for (i = 0; i < arity; ++i) {
1040                         ir_node *predblock = get_Block_cfgpred_block(block, i);
1041                         be_emit_irprintf(" %d", get_irn_node_nr(predblock));
1042                 }
1043         } else {
1044                 be_emit_cstring("\t/* ");
1045                 be_gas_emit_block_name(block);
1046                 be_emit_cstring(": ");
1047         }
1048         if (exec_freq != NULL) {
1049                 be_emit_irprintf(" freq: %f",
1050                                  get_block_execfreq(exec_freq, block));
1051         }
1052         be_emit_cstring(" */\n");
1053         be_emit_write_line();
1054 }
1055
1056 /**
1057  * Walks over the nodes in a block connected by scheduling edges
1058  * and emits code for each node.
1059  */
1060 static void arm_gen_block(ir_node *block, ir_node *prev_block)
1061 {
1062         ir_node *irn;
1063
1064         arm_emit_block_header(block, prev_block);
1065         be_dbg_set_dbg_info(get_irn_dbg_info(block));
1066         sched_foreach(block, irn) {
1067                 arm_emit_node(irn);
1068         }
1069 }
1070
1071 /**
1072  * Block-walker:
1073  * Sets labels for control flow nodes (jump target)
1074  */
1075 static void arm_gen_labels(ir_node *block, void *env)
1076 {
1077         ir_node *pred;
1078         int n = get_Block_n_cfgpreds(block);
1079         (void)env;
1080
1081         for (n--; n >= 0; n--) {
1082                 pred = get_Block_cfgpred(block, n);
1083                 set_irn_link(pred, block);
1084         }
1085 }
1086
1087 /**
1088  * Compare two entries of the symbol or tarval set.
1089  */
1090 static int cmp_sym_or_tv(const void *elt, const void *key, size_t size)
1091 {
1092         const sym_or_tv_t *p1 = elt;
1093         const sym_or_tv_t *p2 = key;
1094         (void) size;
1095
1096         /* as an identifier NEVER can point to a tarval, it's enough
1097            to compare it this way */
1098         return p1->u.generic != p2->u.generic;
1099 }
1100
1101 /**
1102  * Main driver. Emits the code for one routine.
1103  */
1104 void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg)
1105 {
1106         ir_node   **blk_sched;
1107         int       i, n;
1108         ir_node   *last_block = NULL;
1109         ir_entity *entity     = get_irg_entity(irg);
1110
1111         cg        = arm_cg;
1112         sym_or_tv = new_set(cmp_sym_or_tv, 8);
1113
1114         be_gas_elf_type_char = '%';
1115
1116         arm_register_emitters();
1117
1118         be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
1119
1120         /* create the block schedule. For now, we don't need it earlier. */
1121         blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
1122
1123         be_gas_emit_function_prolog(entity, 4);
1124
1125         irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
1126
1127         n = ARR_LEN(blk_sched);
1128         for (i = 0; i < n;) {
1129                 ir_node *block, *next_bl;
1130
1131                 block   = blk_sched[i];
1132                 ++i;
1133                 next_bl = i < n ? blk_sched[i] : NULL;
1134
1135                 /* set here the link. the emitter expects to find the next block here */
1136                 set_irn_link(block, next_bl);
1137                 arm_gen_block(block, last_block);
1138                 last_block = block;
1139         }
1140
1141         be_gas_emit_function_epilog(entity);
1142         be_dbg_method_end();
1143
1144         /* emit SymConst values */
1145         if (set_count(sym_or_tv) > 0) {
1146                 sym_or_tv_t *entry;
1147
1148                 be_emit_cstring("\t.align 2\n");
1149
1150                 foreach_set(sym_or_tv, entry) {
1151                         be_emit_irprintf(".L%u:\n", entry->label);
1152
1153                         if (entry->is_ident) {
1154                                 be_emit_cstring("\t.word\t");
1155                                 be_emit_ident(entry->u.id);
1156                                 be_emit_char('\n');
1157                                 be_emit_write_line();
1158                         } else {
1159                                 tarval *tv = entry->u.tv;
1160                                 int i, size = get_mode_size_bytes(get_tarval_mode(tv));
1161                                 unsigned v;
1162
1163                                 /* beware: ARM fpa uses big endian format */
1164                                 for (i = ((size + 3) & ~3) - 4; i >= 0; i -= 4) {
1165                                         /* get 32 bits */
1166                                         v =            get_tarval_sub_bits(tv, i+3);
1167                                         v = (v << 8) | get_tarval_sub_bits(tv, i+2);
1168                                         v = (v << 8) | get_tarval_sub_bits(tv, i+1);
1169                                         v = (v << 8) | get_tarval_sub_bits(tv, i+0);
1170                                         be_emit_irprintf("\t.word\t%u\n", v);
1171                                         be_emit_write_line();
1172                                 }
1173                         }
1174                 }
1175                 be_emit_char('\n');
1176                 be_emit_write_line();
1177         }
1178         del_set(sym_or_tv);
1179 }
1180
1181 void arm_init_emitter(void)
1182 {
1183         FIRM_DBG_REGISTER(dbg, "firm.be.arm.emit");
1184 }