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