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