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