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