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