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