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