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