cb4119938b09cc910291eb54568e2476725fba1a
[libfirm] / ir / be / arm / arm_emitter.c
1 /*
2  * Copyright (C) 1995-2007 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
24  * @version $Id$
25  */
26 #define SILENCER
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <limits.h>
33
34 #include "xmalloc.h"
35 #include "tv.h"
36 #include "iredges.h"
37 #include "debug.h"
38 #include "irgwalk.h"
39 #include "irtools.h"
40 #include "irprintf.h"
41 #include "irop_t.h"
42 #include "irprog_t.h"
43 #include "irargs_t.h"
44 #include "error.h"
45
46 #include "../besched.h"
47 #include "../beblocksched.h"
48 #include "../beirg_t.h"
49 #include "../begnuas.h"
50
51 #include "arm_emitter.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_t.h"
59
60 #define SNPRINTF_BUF_LEN 128
61
62 static const arch_env_t *arch_env = NULL;
63
64 /**
65  * Returns the register at in position pos.
66  */
67 static const arch_register_t *get_in_reg(const arch_env_t *arch_env, const ir_node *irn, int pos) {
68         ir_node                *op;
69         const arch_register_t  *reg = NULL;
70
71         assert(get_irn_arity(irn) > pos && "Invalid IN position");
72
73         /* The out register of the operator at position pos is the
74            in register we need. */
75         op = get_irn_n(irn, pos);
76
77         reg = arch_get_irn_register(arch_env, op);
78
79         assert(reg && "no in register found");
80         return reg;
81 }
82
83
84 /**
85  * Returns the register at out position pos.
86  */
87 static const arch_register_t *get_out_reg(const arch_env_t *arch_env,
88                                           const ir_node *node, int pos)
89 {
90     ir_node                *proj;
91     const arch_register_t  *reg = NULL;
92
93     /* 1st case: irn is not of mode_T, so it has only                 */
94     /*           one OUT register -> good                             */
95     /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
96     /*           Proj with the corresponding projnum for the register */
97
98     if (get_irn_mode(node) != mode_T) {
99         reg = arch_get_irn_register(arch_env, node);
100     } else if (is_arm_irn(node)) {
101         reg = get_arm_out_reg(node, pos);
102     } else {
103         const ir_edge_t *edge;
104
105         foreach_out_edge(node, edge) {
106             proj = get_edge_src_irn(edge);
107             assert(is_Proj(proj) && "non-Proj from mode_T node");
108             if (get_Proj_proj(proj) == pos) {
109                 reg = arch_get_irn_register(arch_env, proj);
110                 break;
111             }
112         }
113     }
114
115     assert(reg && "no out register found");
116     return reg;
117 }
118
119 /*************************************************************
120  *             _       _    __   _          _
121  *            (_)     | |  / _| | |        | |
122  *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
123  * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
124  * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
125  * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
126  * | |                                       | |
127  * |_|                                       |_|
128  *************************************************************/
129
130 /**
131  * Emits a block label from the given block.
132  */
133 static void arm_emit_block_label(arm_emit_env_t *env, const ir_node *block) {
134         be_emit_irprintf(env->emit, "BLOCK_%u", get_irn_node_nr(block));
135 }
136
137 /**
138  * Emit the name of the source register at given input position.
139  */
140 void arm_emit_source_register(arm_emit_env_t *env, const ir_node *node, int pos) {
141         const arch_register_t *reg = get_in_reg(env->arch_env, node, pos);
142         be_emit_string(env->emit, 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(arm_emit_env_t *env, const ir_node *node, int pos) {
149         const arch_register_t *reg = get_out_reg(env->arch_env, node, pos);
150         be_emit_string(env->emit, arch_register_get_name(reg));
151 }
152
153 /**
154  * Emit a node's offset.
155  */
156 void arm_emit_offset(arm_emit_env_t *env, const ir_node *node) {
157         int offset = 0;
158         ir_op *irn_op = get_irn_op(node);
159
160         if (irn_op == op_be_StackParam) {
161                 ir_entity *ent = be_get_frame_entity(node);
162                 offset = get_entity_offset(ent);
163         } else if (irn_op == op_be_Reload || irn_op == op_be_Spill) {
164                 ir_entity *ent = be_get_frame_entity(node);
165                 offset = get_entity_offset(ent);
166         } else if (irn_op == op_be_IncSP) {
167                 offset = - be_get_IncSP_offset(node);
168         } else {
169                 assert(!"unimplemented arm_emit_offset for this node type");
170                 panic("unimplemented arm_emit_offset for this node type");
171         }
172         be_emit_irprintf(env->emit, "%d", offset);
173 }
174
175 /**
176  * Emit the instruction suffix depending on the mode.
177  */
178 void arm_emit_mode(arm_emit_env_t *env, const ir_node *node) {
179         const arm_attr_t *attr = get_arm_attr_const(node);
180         ir_mode          *mode = attr->op_mode ? attr->op_mode : get_irn_mode(node);
181         int              bits = get_mode_size_bits(mode);
182
183         if (bits == 32)
184                 be_emit_char(env->emit, 's');
185         else if (bits == 64)
186                 be_emit_char(env->emit, 'd');
187         else
188                 be_emit_char(env->emit, 'e');
189 }
190
191
192 /**
193  * Returns non-zero if a mode has a Immediate attribute.
194  */
195 int is_immediate_node(const ir_node *irn) {
196         const arm_attr_t *attr = get_arm_attr_const(irn);
197         return ARM_GET_SHF_MOD(attr) == ARM_SHF_IMM;
198 }
199
200 /**
201  * Emit a const or SymConst value.
202  */
203 void arm_emit_immediate(arm_emit_env_t *env, const ir_node *node) {
204         if (is_immediate_node(node)) {
205                 be_emit_irprintf(env->emit, "#0x%X", arm_decode_imm_w_shift(get_arm_value(node)));
206         } else if (is_arm_SymConst(node))
207                 be_emit_ident(env->emit, get_arm_symconst_id(node));
208         else {
209                 assert(!"not a Constant");
210         }
211 }
212
213 /**
214  * Returns the tarval or offset of an arm node as a string.
215  */
216 void arm_emit_shift(arm_emit_env_t *env, const ir_node *node) {
217         arm_shift_modifier mod;
218
219         mod = get_arm_shift_modifier(node);
220         if (ARM_HAS_SHIFT(mod)) {
221                 long v = get_tarval_long(get_arm_value(node));
222
223                 be_emit_irprintf(env->emit, ", %s #%ld", arm_shf_mod_name(mod), v);
224         }
225 }
226
227 /**
228  * Returns a unique label. This number will not be used a second time.
229  */
230 static unsigned get_unique_label(void) {
231         static unsigned id = 0;
232         return ++id;
233 }
234
235 /**
236  * Emit a SymConst.
237  */
238 static void emit_arm_SymConst(arm_emit_env_t *env, const ir_node *irn) {
239         ident *id = get_arm_symconst_id(irn);
240         pmap_entry *entry = pmap_find(env->symbols, id);
241         unsigned label;
242
243         if (entry == NULL) {
244                 /* allocate a label */
245                 label = get_unique_label();
246                 pmap_insert(env->symbols, id, INT_TO_PTR(label));
247         } else {
248                 label = PTR_TO_INT(entry->value);
249         }
250
251         /* load the symbol indirect */
252         be_emit_cstring(env->emit, "\tldr ");
253         arm_emit_dest_register(env, irn, 0);
254         be_emit_irprintf(env->emit, ", .L%u", label);
255         be_emit_finish_line_gas(env->emit, irn);
256 }
257
258 /**
259  * Returns the next block in a block schedule.
260  */
261 static ir_node *sched_next_block(ir_node *block) {
262     return get_irn_link(block);
263 }
264
265 /**
266  * Emit a conditional jump.
267  */
268 static void emit_arm_CondJmp(arm_emit_env_t *env, const ir_node *irn) {
269         const ir_edge_t *edge;
270         ir_node *true_block = NULL;
271         ir_node *false_block = NULL;
272         ir_node *op1 = get_irn_n(irn, 0);
273         ir_mode *opmode = get_irn_mode(op1);
274         const char *suffix;
275         int proj_num = get_arm_CondJmp_proj_num(irn);
276
277         foreach_out_edge(irn, edge) {
278                 ir_node *proj = get_edge_src_irn(edge);
279                 long nr = get_Proj_proj(proj);
280                 ir_node *block = get_irn_link(proj);
281                 if (nr == pn_Cond_true) {
282                         true_block = block;
283                 } else {
284                         false_block = block;
285                 }
286         }
287
288         if (proj_num == pn_Cmp_False) {
289                 /* always false: should not happen */
290                 be_emit_cstring(env->emit, "\tb ");
291                 arm_emit_block_label(env, false_block);
292                 be_emit_finish_line_gas(env->emit, irn);
293         } else if (proj_num == pn_Cmp_True) {
294                 /* always true: should not happen */
295                 be_emit_cstring(env->emit, "\tb ");
296                 arm_emit_block_label(env, true_block);
297                 be_emit_finish_line_gas(env->emit, irn);
298         } else {
299                 ir_node *block = get_nodes_block(irn);
300
301                 if (mode_is_float(opmode)) {
302                         suffix = "ICHWILLIMPLEMENTIERTWERDEN";
303
304                         be_emit_cstring(env->emit, "\tfcmp ");
305                         arm_emit_source_register(env, irn, 0);
306                         be_emit_cstring(env->emit, ", ");
307                         arm_emit_source_register(env, irn, 1);
308                         be_emit_finish_line_gas(env->emit, irn);
309
310                         be_emit_cstring(env->emit, "\tfmstat");
311                         be_emit_pad_comment(env->emit);
312                         be_emit_cstring(env->emit, "/* FCSPR -> CPSR */");
313                         be_emit_finish_line_gas(env->emit, NULL);
314                 } else {
315                         if (true_block == sched_next_block(block)) {
316                                 /* negate it */
317                                 proj_num = get_negated_pnc(proj_num, opmode);
318                         }
319                         switch (proj_num) {
320                                 case pn_Cmp_Eq:  suffix = "eq"; break;
321                                 case pn_Cmp_Lt:  suffix = "lt"; break;
322                                 case pn_Cmp_Le:  suffix = "le"; break;
323                                 case pn_Cmp_Gt:  suffix = "gt"; break;
324                                 case pn_Cmp_Ge:  suffix = "ge"; break;
325                                 case pn_Cmp_Lg:  suffix = "ne"; break;
326                                 case pn_Cmp_Leg: suffix = "al"; break;
327                                 default: assert(!"Cmp unsupported"); suffix = "al";
328                         }
329                         be_emit_cstring(env->emit, "\tcmp ");
330                         arm_emit_source_register(env, irn, 0);
331                         be_emit_cstring(env->emit, ", ");
332                         arm_emit_source_register(env, irn, 1);
333                         be_emit_finish_line_gas(env->emit, irn);
334                 }
335
336                 if (true_block == sched_next_block(block)) {
337                         be_emit_irprintf(env->emit, "\tb%s ", suffix);
338                         arm_emit_block_label(env, true_block);
339                         be_emit_pad_comment(env->emit);
340                         be_emit_cstring(env->emit, "/* false case */");
341                         be_emit_finish_line_gas(env->emit, NULL);
342
343                         be_emit_pad_comment(env->emit);
344                         be_emit_cstring(env->emit, "/* fallthrough ");
345                         arm_emit_block_label(env, false_block);
346                         be_emit_cstring(env->emit, " */");
347                         be_emit_finish_line_gas(env->emit, NULL);
348                 } else {
349                         be_emit_irprintf(env->emit, "\tb%s ", suffix);
350                         arm_emit_block_label(env, true_block);
351                         be_emit_pad_comment(env->emit);
352                         be_emit_cstring(env->emit, "/* true case */");
353                         be_emit_finish_line_gas(env->emit, NULL);
354
355                         if (false_block == sched_next_block(block)) {
356                                 be_emit_pad_comment(env->emit);
357                                 be_emit_cstring(env->emit, "/* fallthrough ");
358                                 arm_emit_block_label(env, false_block);
359                                 be_emit_cstring(env->emit, " */");
360                                 be_emit_finish_line_gas(env->emit, NULL);
361                         } else {
362                                 be_emit_cstring(env->emit, "b ");
363                                 arm_emit_block_label(env, false_block);
364                                 be_emit_pad_comment(env->emit);
365                                 be_emit_cstring(env->emit, "/* false case */");
366                                 be_emit_finish_line_gas(env->emit, NULL);
367                         }
368                 }
369         }
370 }
371
372 /**
373  * Create the CopyB instruction sequence.
374  */
375 static void emit_arm_CopyB(arm_emit_env_t *env, const ir_node *irn) {
376         unsigned int size = get_tarval_long(get_arm_value(irn));
377
378         be_emit_cstring(env->emit, "/* MemCopy (");
379         arm_emit_source_register(env, irn, 1);
380         be_emit_cstring(env->emit, ")->(");
381         arm_emit_source_register(env, irn, 0);
382         be_emit_irprintf(env->emit, " [%d bytes], Uses ", size);
383         arm_emit_source_register(env, irn, 2);
384         be_emit_cstring(env->emit, ", ");
385         arm_emit_source_register(env, irn, 3);
386         be_emit_cstring(env->emit, ", ");
387         arm_emit_source_register(env, irn, 4);
388         be_emit_cstring(env->emit, ", and %r12 */");
389         be_emit_finish_line_gas(env->emit, NULL);
390
391         assert ( size > 0 && "CopyB needs size > 0" );
392         if (size & 3)
393                 size += 4;
394         size >>= 2;
395         switch(size & 3) {
396         case 0:
397                 break;
398         case 1:
399                 be_emit_cstring(env->emit, "\tldr %%r12, [");
400                 arm_emit_source_register(env, irn, 1);
401                 be_emit_cstring(env->emit, ", #0]!");
402                 be_emit_finish_line_gas(env->emit, NULL);
403
404                 be_emit_cstring(env->emit, "\tstr %%r12, [");
405                 arm_emit_source_register(env, irn, 0);
406                 be_emit_cstring(env->emit, ", #0]!");
407                 be_emit_finish_line_gas(env->emit, irn);
408                 break;
409         case 2:
410                 be_emit_cstring(env->emit, "\tldmia ");
411                 arm_emit_source_register(env, irn, 1);
412                 be_emit_cstring(env->emit, "!, {%r12, ");
413                 arm_emit_source_register(env, irn, 2);
414                 be_emit_char(env->emit, '}');
415                 be_emit_finish_line_gas(env->emit, NULL);
416
417                 be_emit_cstring(env->emit, "\tstmia ");
418                 arm_emit_source_register(env, irn, 0);
419                 be_emit_cstring(env->emit, "!, {%r12, ");
420                 arm_emit_source_register(env, irn, 2);
421                 be_emit_char(env->emit, '}');
422                 be_emit_finish_line_gas(env->emit, irn);
423                 break;
424         case 3:
425                 be_emit_cstring(env->emit, "\tldmia ");
426                 arm_emit_source_register(env, irn, 1);
427                 be_emit_cstring(env->emit, "!, {%r12, ");
428                 arm_emit_source_register(env, irn, 2);
429                 be_emit_cstring(env->emit, ", ");
430                 arm_emit_source_register(env, irn, 3);
431                 be_emit_char(env->emit, '}');
432                 be_emit_finish_line_gas(env->emit, NULL);
433
434                 be_emit_cstring(env->emit, "\tstmia ");
435                 arm_emit_source_register(env, irn, 0);
436                 be_emit_cstring(env->emit, "!, {%r12, ");
437                 arm_emit_source_register(env, irn, 2);
438                 be_emit_cstring(env->emit, ", ");
439                 arm_emit_source_register(env, irn, 3);
440                 be_emit_char(env->emit, '}');
441                 be_emit_finish_line_gas(env->emit, irn);
442                 break;
443         }
444         size >>= 2;
445         while (size) {
446                 be_emit_cstring(env->emit, "\tldmia ");
447                 arm_emit_source_register(env, irn, 1);
448                 be_emit_cstring(env->emit, "!, {%r12, ");
449                 arm_emit_source_register(env, irn, 2);
450                 be_emit_cstring(env->emit, ", ");
451                 arm_emit_source_register(env, irn, 3);
452                 be_emit_cstring(env->emit, ", ");
453                 arm_emit_source_register(env, irn, 4);
454                 be_emit_char(env->emit, '}');
455                 be_emit_finish_line_gas(env->emit, NULL);
456
457                 be_emit_cstring(env->emit, "\tstmia ");
458                 arm_emit_source_register(env, irn, 0);
459                 be_emit_cstring(env->emit, "!, {%r12, ");
460                 arm_emit_source_register(env, irn, 2);
461                 be_emit_cstring(env->emit, ", ");
462                 arm_emit_source_register(env, irn, 3);
463                 be_emit_cstring(env->emit, ", ");
464                 arm_emit_source_register(env, irn, 4);
465                 be_emit_char(env->emit, '}');
466                 be_emit_finish_line_gas(env->emit, irn);
467                 --size;
468         }
469 }
470
471 static void emit_arm_SwitchJmp(arm_emit_env_t *env, const ir_node *irn) {
472         const ir_edge_t    *edge;
473         ir_node            *proj;
474         int i;
475         ir_node **projs;
476         int n_projs;
477         int block_nr;
478         ir_node *default_block = NULL;
479
480         block_nr = get_irn_node_nr(irn);
481         n_projs = get_arm_SwitchJmp_n_projs(irn);
482
483         projs = xcalloc(n_projs , sizeof(ir_node*));
484
485         foreach_out_edge(irn, edge) {
486                 proj = get_edge_src_irn(edge);
487                 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
488
489                 if (get_Proj_proj(proj) == get_arm_SwitchJmp_default_proj_num(irn))
490                         default_block = get_irn_link(proj);
491
492                 projs[get_Proj_proj(proj)] = proj;
493         }
494         assert(default_block != NULL);
495
496         /*
497            CMP %1S, n_projs - 1
498            BHI default
499         */
500
501         be_emit_cstring(env->emit, "\tcmp ");
502         arm_emit_source_register(env, irn, 0);
503         be_emit_irprintf(env->emit, ", #%u", n_projs - 1);
504         be_emit_finish_line_gas(env->emit, irn);
505
506         be_emit_cstring(env->emit, "\tbhi ");
507         arm_emit_block_label(env, default_block);
508         be_emit_finish_line_gas(env->emit, NULL);
509
510         /*
511            LDR %r12, .TABLE_X_START
512            ADD %r12, %r12, [%1S, LSL #2]
513            LDR %r15, %r12
514          */
515
516         be_emit_irprintf(env->emit, "\tldr %%r12, TABLE_%d_START", block_nr);
517         be_emit_finish_line_gas(env->emit, NULL);
518
519         be_emit_irprintf(env->emit, "\tadd %%r12, %%r12, ");
520         arm_emit_source_register(env, irn, 0);
521         be_emit_cstring(env->emit, ", LSL #2");
522         be_emit_finish_line_gas(env->emit, NULL);
523
524         be_emit_cstring(env->emit, "\tldr %r15, [%r12, #0]");
525         be_emit_finish_line_gas(env->emit, NULL);
526
527         be_emit_irprintf(env->emit, "TABLE_%d_START:\n\t.word\tTABLE_%d", block_nr, block_nr);
528         be_emit_finish_line_gas(env->emit, NULL);
529         be_emit_irprintf(env->emit, "\t.align 2");
530         be_emit_finish_line_gas(env->emit, NULL);
531         be_emit_irprintf(env->emit, "TABLE_%d:", block_nr);
532         be_emit_finish_line_gas(env->emit, NULL);
533
534         for (i = 0; i < n_projs; ++i) {
535                 ir_node *block;
536                 proj = projs[i];
537                 if ( proj ) {
538                         block = get_irn_link(proj);
539                 } else {
540                         block = get_irn_link(projs[get_arm_SwitchJmp_default_proj_num(irn)]);
541                 }
542                 be_emit_cstring(env->emit, "\t.word\t");
543                 arm_emit_block_label(env, block);
544                 be_emit_finish_line_gas(env->emit, NULL);
545         }
546         be_emit_irprintf(env->emit, "\t.align 2\n");
547         be_emit_finish_line_gas(env->emit, NULL);
548         xfree(projs);
549 }
550
551 /************************************************************************/
552 /* emit_be                                                              */
553 /************************************************************************/
554
555 static void emit_be_Call(arm_emit_env_t *env, const ir_node *irn) {
556         ir_entity *ent = be_Call_get_entity(irn);
557
558         be_emit_cstring(env->emit, "\tbl ");
559         if (ent) {
560                 mark_entity_visited(ent);
561                 be_emit_ident(env->emit, get_entity_ld_ident(ent));
562         } else {
563                 arm_emit_source_register(env, irn, be_pos_Call_ptr);
564         }
565         be_emit_finish_line_gas(env->emit, irn);
566 }
567
568 /** Emit an IncSP node */
569 static void emit_be_IncSP(arm_emit_env_t *env, const ir_node *irn) {
570         int offs = be_get_IncSP_offset(irn);
571
572         if (offs != 0) {
573                 be_emit_cstring(env->emit, "\tadd ");
574                 arm_emit_dest_register(env, irn, 0);
575                 be_emit_cstring(env->emit, ", ");
576                 arm_emit_source_register(env, irn, 0);
577                 be_emit_cstring(env->emit, ", #");
578                 arm_emit_offset(env, irn);
579         } else {
580                 be_emit_cstring(env->emit, "\t/* omitted IncSP(");
581                 arm_emit_offset(env, irn);
582                 be_emit_cstring(env->emit,") */");
583         }
584         be_emit_finish_line_gas(env->emit, irn);
585 }
586
587 static void emit_be_Copy(arm_emit_env_t *env, const ir_node *irn) {
588         ir_mode *mode = get_irn_mode(irn);
589
590         if (get_in_reg(env->arch_env, irn, 0) == get_out_reg(env->arch_env, irn, 0)) {
591                 be_emit_cstring(env->emit, "\t/* omitted Copy: ");
592                 arm_emit_source_register(env, irn, 0);
593                 be_emit_cstring(env->emit, " -> ");
594                 arm_emit_dest_register(env, irn, 0);
595                 be_emit_finish_line_gas(env->emit, irn);
596                 return;
597         }
598
599         if (mode_is_float(mode)) {
600                 if (USE_FPA(env->cg->isa)) {
601                         be_emit_cstring(env->emit, "\tmvf");
602                         arm_emit_mode(env, irn);
603                         be_emit_char(env->emit, ' ');
604                         arm_emit_dest_register(env, irn, 0);
605                         be_emit_cstring(env->emit, ", ");
606                         arm_emit_source_register(env, irn, 0);
607                         be_emit_finish_line_gas(env->emit, irn);
608                 } else {
609                         assert(0 && "move not supported for this mode");
610                         panic("emit_be_Copy: move not supported for this mode");
611                 }
612         } else if (mode_is_numP(mode)) {
613                 be_emit_cstring(env->emit, "\tmov ");
614                 arm_emit_dest_register(env, irn, 0);
615                 be_emit_cstring(env->emit, ", ");
616                 arm_emit_source_register(env, irn, 0);
617                         be_emit_finish_line_gas(env->emit, irn);
618         } else {
619                 assert(0 && "move not supported for this mode");
620                 panic("emit_be_Copy: move not supported for this mode");
621         }
622 }
623
624 /**
625  * Emit code for a Spill.
626  */
627 static void emit_be_Spill(arm_emit_env_t *env, const ir_node *irn) {
628         ir_mode *mode = get_irn_mode(irn);
629
630         if (mode_is_float(mode)) {
631                 if (USE_FPA(env->cg->isa)) {
632                         be_emit_cstring(env->emit, "\tstf ");
633                 } else {
634                         assert(0 && "spill not supported for this mode");
635                         panic("emit_be_Spill: spill not supported for this mode");
636                 }
637         } else if (mode_is_dataM(mode)) {
638                 be_emit_cstring(env->emit, "\tstr ");
639         } else {
640                 assert(0 && "spill not supported for this mode");
641                 panic("emit_be_Spill: spill not supported for this mode");
642         }
643         arm_emit_source_register(env, irn, 1);
644         be_emit_cstring(env->emit, ", [");
645         arm_emit_source_register(env, irn, 0);
646         be_emit_cstring(env->emit, ", #");
647         arm_emit_offset(env, irn);
648         be_emit_char(env->emit, ']');
649         be_emit_finish_line_gas(env->emit, irn);
650 }
651
652 /**
653  * Emit code for a Reload.
654  */
655 static void emit_be_Reload(arm_emit_env_t *env, const ir_node *irn) {
656         ir_mode *mode = get_irn_mode(irn);
657
658         if (mode_is_float(mode)) {
659                 if (USE_FPA(env->cg->isa)) {
660                         be_emit_cstring(env->emit, "\tldf ");
661                 } else {
662                         assert(0 && "reload not supported for this mode");
663                         panic("emit_be_Reload: reload not supported for this mode");
664                 }
665         } else if (mode_is_dataM(mode)) {
666                 be_emit_cstring(env->emit, "\tldr ");
667         } else {
668                 assert(0 && "reload not supported for this mode");
669                 panic("emit_be_Reload: reload not supported for this mode");
670         }
671         arm_emit_dest_register(env, irn, 0);
672         be_emit_cstring(env->emit, ", [");
673         arm_emit_source_register(env, irn, 0);
674         be_emit_cstring(env->emit, ", #");
675         arm_emit_offset(env, irn);
676         be_emit_char(env->emit, ']');
677         be_emit_finish_line_gas(env->emit, irn);
678 }
679
680 static void emit_be_Perm(arm_emit_env_t *env, const ir_node *irn) {
681         be_emit_cstring(env->emit, "\teor ");
682         arm_emit_source_register(env, irn, 0);
683         be_emit_cstring(env->emit, ", ");
684         arm_emit_source_register(env, irn, 0);
685         be_emit_cstring(env->emit, ", ");
686         arm_emit_source_register(env, irn, 1);
687         be_emit_finish_line_gas(env->emit, NULL);
688
689         be_emit_cstring(env->emit, "\teor ");
690         arm_emit_source_register(env, irn, 1);
691         be_emit_cstring(env->emit, ", ");
692         arm_emit_source_register(env, irn, 0);
693         be_emit_cstring(env->emit, ", ");
694         arm_emit_source_register(env, irn, 1);
695         be_emit_finish_line_gas(env->emit, NULL);
696
697         be_emit_cstring(env->emit, "\teor ");
698         arm_emit_source_register(env, irn, 0);
699         be_emit_cstring(env->emit, ", ");
700         arm_emit_source_register(env, irn, 0);
701         be_emit_cstring(env->emit, ", ");
702         arm_emit_source_register(env, irn, 1);
703         be_emit_finish_line_gas(env->emit, irn);
704 }
705
706 static void emit_be_StackParam(arm_emit_env_t *env, const ir_node *irn) {
707         ir_mode *mode = get_irn_mode(irn);
708
709         if (mode_is_float(mode)) {
710                 if (USE_FPA(env->cg->isa)) {
711                         be_emit_cstring(env->emit,"\tldf ");
712                 } else {
713                         assert(0 && "stackparam not supported for this mode");
714                         panic("emit_be_StackParam: stackparam not supported for this mode");
715                 }
716         } else {
717                 be_emit_cstring(env->emit,"\tldr ");
718         }
719         arm_emit_dest_register(env, irn, 0);
720         be_emit_cstring(env->emit, ", [");
721         arm_emit_source_register(env, irn, 0);
722         be_emit_cstring(env->emit,", #");
723         arm_emit_offset(env, irn);
724         be_emit_finish_line_gas(env->emit, irn);
725 }
726
727 /************************************************************************/
728 /* emit                                                                 */
729 /************************************************************************/
730
731 static void emit_Jmp(arm_emit_env_t *env, const ir_node *irn) {
732         const ir_edge_t *edge = get_irn_out_edge_first(irn);
733         ir_node *target_block = get_edge_src_irn(edge);
734         ir_node *block = get_nodes_block(irn);
735
736         if (target_block == sched_next_block(block)) {
737                 be_emit_pad_comment(env->emit);
738                 be_emit_cstring(env->emit, "/* fallthrough ");
739                 arm_emit_block_label(env, target_block);
740                 be_emit_cstring(env->emit, " */");
741                 be_emit_finish_line_gas(env->emit, NULL);
742         } else {
743                 be_emit_cstring(env->emit, "\tb ");
744                 arm_emit_block_label(env, target_block);
745                 be_emit_finish_line_gas(env->emit, irn);
746         }
747 }
748
749 static void emit_arm_fpaDbl2GP(arm_emit_env_t *env, const ir_node *irn) {
750         be_emit_cstring(env->emit, "\tstfd ");
751         arm_emit_source_register(env, irn, 0);
752         be_emit_cstring(env->emit, ", [sp, #-8]!");
753         be_emit_pad_comment(env->emit);
754         be_emit_cstring(env->emit, "/* Push fp to stack */");
755         be_emit_finish_line_gas(env->emit, NULL);
756
757         be_emit_cstring(env->emit, "\tldmfd sp!, {");
758         arm_emit_dest_register(env, irn, 1);
759         be_emit_cstring(env->emit, ", ");
760         arm_emit_dest_register(env, irn, 0);
761         be_emit_char(env->emit, '}');
762         be_emit_pad_comment(env->emit);
763         be_emit_cstring(env->emit, "/* Pop destination */");
764         be_emit_finish_line_gas(env->emit, irn);
765 }
766
767 /***********************************************************************************
768  *                  _          __                                             _
769  *                 (_)        / _|                                           | |
770  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
771  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
772  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
773  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
774  *
775  ***********************************************************************************/
776
777 static void emit_silence(arm_emit_env_t *env, const ir_node *irn) {
778         /* Do nothing. */
779 }
780
781 /**
782  * The type of a emitter function.
783  */
784 typedef void (emit_func)(arm_emit_env_t *env, const ir_node *irn);
785
786 /**
787  * Set a node emitter. Make it a bit more type safe.
788  */
789 static INLINE void set_emitter(ir_op *op, emit_func arm_emit_node) {
790         op->ops.generic = (op_func)arm_emit_node;
791 }
792
793 /**
794  * Enters the emitter functions for handled nodes into the generic
795  * pointer of an opcode.
796  */
797 static void arm_register_emitters(void) {
798
799 #define ARM_EMIT(a)  set_emitter(op_arm_##a, emit_arm_##a)
800 #define EMIT(a)      set_emitter(op_##a, emit_##a)
801 #define BE_EMIT(a)   set_emitter(op_be_##a, emit_be_##a)
802 #define SILENCE(a)   set_emitter(op_##a, emit_silence)
803
804         /* first clear the generic function pointer for all ops */
805         clear_irp_opcodes_generic_func();
806
807         /* register all emitter functions defined in spec */
808         arm_register_spec_emitters();
809
810         /* other emitter functions */
811         ARM_EMIT(CondJmp);
812         ARM_EMIT(CopyB);
813 //      ARM_EMIT(CopyB_i);
814 //      ARM_EMIT(Const);
815         ARM_EMIT(SymConst);
816         ARM_EMIT(SwitchJmp);
817         ARM_EMIT(fpaDbl2GP);
818
819         /* benode emitter */
820         BE_EMIT(Call);
821         BE_EMIT(IncSP);
822 //      BE_EMIT(AddSP);
823         BE_EMIT(Copy);
824         BE_EMIT(Spill);
825         BE_EMIT(Reload);
826         BE_EMIT(Perm);
827         BE_EMIT(StackParam);
828
829         /* firm emitter */
830         EMIT(Jmp);
831
832         /* noisy stuff */
833 #ifdef SILENCER
834         SILENCE(Start);
835         SILENCE(Proj);
836         SILENCE(Phi);
837         SILENCE(be_Keep);
838         SILENCE(be_CopyKeep);
839         SILENCE(be_RegParams);
840         SILENCE(be_Barrier);
841         SILENCE(be_Return);
842 #endif
843
844 #undef ARM_EMIT
845 #undef BE_EMIT
846 #undef EMIT
847 #undef SILENCE
848 }
849
850 /**
851  * Emits code for a node.
852  */
853 static void arm_emit_node(arm_emit_env_t *env, const ir_node *irn) {
854         ir_op *op = get_irn_op(irn);
855
856         if (op->ops.generic) {
857                 emit_func *emit = (emit_func *)op->ops.generic;
858                 (*emit)(env, irn);
859         } else {
860                 be_emit_cstring(env->emit, "\t/* TODO */");
861                 be_emit_finish_line_gas(env->emit, irn);
862         }
863 }
864
865 /**
866  * Walks over the nodes in a block connected by scheduling edges
867  * and emits code for each node.
868  */
869 void arm_gen_block(ir_node *block, void *ctx) {
870         arm_emit_env_t *env = ctx;
871         ir_node *irn;
872
873         arm_emit_block_label(env, block);
874         be_emit_cstring(env->emit, ":\n");
875         be_emit_write_line(env->emit);
876
877         sched_foreach(block, irn) {
878                 arm_emit_node(env, irn);
879         }
880 }
881
882
883 /**
884  * Emits code for function start.
885  */
886 void arm_func_prolog(arm_emit_env_t *env, ir_graph *irg) {
887         be_emit_env_t *eenv = env->emit;
888         ir_entity *ent = get_irg_entity(irg);
889         const char *irg_name = get_entity_ld_name(ent);
890
891         be_emit_write_line(eenv);
892         be_gas_emit_switch_section(eenv, GAS_SECTION_TEXT);
893         be_emit_cstring(eenv, "\t.align  2\n");
894
895         if (get_entity_visibility(ent) == visibility_external_visible)
896                 be_emit_irprintf(eenv, "\t.global %s\n", irg_name);
897         be_emit_irprintf(eenv, "%s:\n", irg_name);
898 }
899
900 /**
901  * Emits code for function end
902  */
903 void arm_emit_end(FILE *F, ir_graph *irg) {
904         fprintf(F, "\t.ident \"firmcc\"\n");
905 }
906
907 /**
908  * Sets labels for control flow nodes (jump target)
909  * TODO: Jump optimization
910  */
911 void arm_gen_labels(ir_node *block, void *env) {
912         ir_node *pred;
913         int n = get_Block_n_cfgpreds(block);
914
915         for (n--; n >= 0; n--) {
916                 pred = get_Block_cfgpred(block, n);
917                 set_irn_link(pred, block);
918         }
919 }
920
921
922 /**
923  * Main driver. Emits the code for one routine.
924  */
925 void arm_gen_routine(const arm_code_gen_t *cg, ir_graph *irg)
926 {
927         arm_emit_env_t emit_env;
928         ir_node **blk_sched;
929         int i, n;
930         pmap_entry *entry;
931
932         emit_env.emit     = &cg->isa->emit;
933         emit_env.arch_env = cg->arch_env;
934         emit_env.cg       = cg;
935         emit_env.symbols  = pmap_create();
936         FIRM_DBG_REGISTER(emit_env.mod, "firm.be.arm.emit");
937
938         /* set the global arch_env (needed by print hooks) */
939         arch_env = cg->arch_env;
940
941         arm_register_emitters();
942
943         /* create the block schedule. For now, we don't need it earlier. */
944         blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
945
946         arm_func_prolog(&emit_env, irg);
947         irg_block_walk_graph(irg, arm_gen_labels, NULL, &emit_env);
948
949         n = ARR_LEN(blk_sched);
950         for (i = 0; i < n;) {
951                 ir_node *block, *next_bl;
952
953                 block   = blk_sched[i];
954                 ++i;
955                 next_bl = i < n ? blk_sched[i] : NULL;
956
957                 /* set here the link. the emitter expects to find the next block here */
958                 set_irn_link(block, next_bl);
959                 arm_gen_block(block, &emit_env);
960         }
961
962         /* emit SymConst values */
963         if (pmap_count(emit_env.symbols) > 0) {
964                 be_emit_cstring(emit_env.emit, "\t.align 2\n");
965
966                 pmap_foreach(emit_env.symbols, entry) {
967                         ident *id = entry->key;
968
969                         be_emit_irprintf(emit_env.emit, ".L%u:\n", PTR_TO_INT(entry->value));
970                         be_emit_cstring(emit_env.emit, "\t.word\t");
971                         be_emit_ident(emit_env.emit, id);
972                         be_emit_char(emit_env.emit, '\n');
973                         be_emit_write_line(emit_env.emit);
974                 }
975                 be_emit_char(emit_env.emit, '\n');
976                 be_emit_write_line(emit_env.emit);
977         }
978         pmap_destroy(emit_env.symbols);
979 }