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