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