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