44efb2ae34dc8479cf2c73f04553a885caafe841
[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                 be_emit_ident(env->emit, get_entity_ld_ident(ent));
564         } else {
565                 arm_emit_source_register(env, irn, be_pos_Call_ptr);
566         }
567         be_emit_finish_line_gas(env->emit, irn);
568 }
569
570 /** Emit an IncSP node */
571 static void emit_be_IncSP(arm_emit_env_t *env, const ir_node *irn) {
572         int offs = be_get_IncSP_offset(irn);
573
574         if (offs != 0) {
575                 be_emit_cstring(env->emit, "\tadd ");
576                 arm_emit_dest_register(env, irn, 0);
577                 be_emit_cstring(env->emit, ", ");
578                 arm_emit_source_register(env, irn, 0);
579                 be_emit_cstring(env->emit, ", #");
580                 arm_emit_offset(env, irn);
581         } else {
582                 be_emit_cstring(env->emit, "\t/* omitted IncSP(");
583                 arm_emit_offset(env, irn);
584                 be_emit_cstring(env->emit,") */");
585         }
586         be_emit_finish_line_gas(env->emit, irn);
587 }
588
589 static void emit_be_Copy(arm_emit_env_t *env, const ir_node *irn) {
590         ir_mode *mode = get_irn_mode(irn);
591
592         if (get_in_reg(env->arch_env, irn, 0) == get_out_reg(env->arch_env, irn, 0)) {
593                 be_emit_cstring(env->emit, "\t/* omitted Copy: ");
594                 arm_emit_source_register(env, irn, 0);
595                 be_emit_cstring(env->emit, " -> ");
596                 arm_emit_dest_register(env, irn, 0);
597                 be_emit_finish_line_gas(env->emit, irn);
598                 return;
599         }
600
601         if (mode_is_float(mode)) {
602                 if (USE_FPA(env->cg->isa)) {
603                         be_emit_cstring(env->emit, "\tmvf");
604                         arm_emit_mode(env, irn);
605                         be_emit_char(env->emit, ' ');
606                         arm_emit_dest_register(env, irn, 0);
607                         be_emit_cstring(env->emit, ", ");
608                         arm_emit_source_register(env, irn, 0);
609                         be_emit_finish_line_gas(env->emit, irn);
610                 } else {
611                         assert(0 && "move not supported for this mode");
612                         panic("emit_be_Copy: move not supported for this mode");
613                 }
614         } else if (mode_is_numP(mode)) {
615                 be_emit_cstring(env->emit, "\tmov ");
616                 arm_emit_dest_register(env, irn, 0);
617                 be_emit_cstring(env->emit, ", ");
618                 arm_emit_source_register(env, irn, 0);
619                         be_emit_finish_line_gas(env->emit, irn);
620         } else {
621                 assert(0 && "move not supported for this mode");
622                 panic("emit_be_Copy: move not supported for this mode");
623         }
624 }
625
626 /**
627  * Emit code for a Spill.
628  */
629 static void emit_be_Spill(arm_emit_env_t *env, const ir_node *irn) {
630         ir_mode *mode = get_irn_mode(irn);
631
632         if (mode_is_float(mode)) {
633                 if (USE_FPA(env->cg->isa)) {
634                         be_emit_cstring(env->emit, "\tstf ");
635                 } else {
636                         assert(0 && "spill not supported for this mode");
637                         panic("emit_be_Spill: spill not supported for this mode");
638                 }
639         } else if (mode_is_dataM(mode)) {
640                 be_emit_cstring(env->emit, "\tstr ");
641         } else {
642                 assert(0 && "spill not supported for this mode");
643                 panic("emit_be_Spill: spill not supported for this mode");
644         }
645         arm_emit_source_register(env, irn, 1);
646         be_emit_cstring(env->emit, ", [");
647         arm_emit_source_register(env, irn, 0);
648         be_emit_cstring(env->emit, ", #");
649         arm_emit_offset(env, irn);
650         be_emit_char(env->emit, ']');
651         be_emit_finish_line_gas(env->emit, irn);
652 }
653
654 /**
655  * Emit code for a Reload.
656  */
657 static void emit_be_Reload(arm_emit_env_t *env, const ir_node *irn) {
658         ir_mode *mode = get_irn_mode(irn);
659
660         if (mode_is_float(mode)) {
661                 if (USE_FPA(env->cg->isa)) {
662                         be_emit_cstring(env->emit, "\tldf ");
663                 } else {
664                         assert(0 && "reload not supported for this mode");
665                         panic("emit_be_Reload: reload not supported for this mode");
666                 }
667         } else if (mode_is_dataM(mode)) {
668                 be_emit_cstring(env->emit, "\tldr ");
669         } else {
670                 assert(0 && "reload not supported for this mode");
671                 panic("emit_be_Reload: reload not supported for this mode");
672         }
673         arm_emit_dest_register(env, irn, 0);
674         be_emit_cstring(env->emit, ", [");
675         arm_emit_source_register(env, irn, 0);
676         be_emit_cstring(env->emit, ", #");
677         arm_emit_offset(env, irn);
678         be_emit_char(env->emit, ']');
679         be_emit_finish_line_gas(env->emit, irn);
680 }
681
682 static void emit_be_Perm(arm_emit_env_t *env, const ir_node *irn) {
683         be_emit_cstring(env->emit, "\teor ");
684         arm_emit_source_register(env, irn, 0);
685         be_emit_cstring(env->emit, ", ");
686         arm_emit_source_register(env, irn, 0);
687         be_emit_cstring(env->emit, ", ");
688         arm_emit_source_register(env, irn, 1);
689         be_emit_finish_line_gas(env->emit, NULL);
690
691         be_emit_cstring(env->emit, "\teor ");
692         arm_emit_source_register(env, irn, 1);
693         be_emit_cstring(env->emit, ", ");
694         arm_emit_source_register(env, irn, 0);
695         be_emit_cstring(env->emit, ", ");
696         arm_emit_source_register(env, irn, 1);
697         be_emit_finish_line_gas(env->emit, NULL);
698
699         arm_emit_source_register(env, irn, 0);
700         be_emit_cstring(env->emit, ", ");
701         arm_emit_source_register(env, irn, 0);
702         be_emit_cstring(env->emit, ", ");
703         arm_emit_source_register(env, irn, 1);
704         be_emit_finish_line_gas(env->emit, irn);
705 }
706
707 static void emit_be_StackParam(arm_emit_env_t *env, const ir_node *irn) {
708         ir_mode *mode = get_irn_mode(irn);
709
710         if (mode_is_float(mode)) {
711                 if (USE_FPA(env->cg->isa)) {
712                         be_emit_cstring(env->emit,"\tldf ");
713                 } else {
714                         assert(0 && "stackparam not supported for this mode");
715                         panic("emit_be_StackParam: stackparam not supported for this mode");
716                 }
717         } else {
718                 be_emit_cstring(env->emit,"\tldr ");
719         }
720         arm_emit_dest_register(env, irn, 0);
721         be_emit_cstring(env->emit, ", [");
722         arm_emit_source_register(env, irn, 0);
723         be_emit_cstring(env->emit,", #");
724         arm_emit_offset(env, irn);
725         be_emit_finish_line_gas(env->emit, irn);
726 }
727
728 /************************************************************************/
729 /* emit                                                                 */
730 /************************************************************************/
731
732 static void emit_Jmp(arm_emit_env_t *env, const ir_node *irn) {
733         const ir_edge_t *edge = get_irn_out_edge_first(irn);
734         ir_node *target_block = get_edge_src_irn(edge);
735
736         be_emit_cstring(env->emit, "\tb ");
737         arm_emit_block_label(env, target_block);
738         be_emit_finish_line_gas(env->emit, irn);
739 }
740
741 static void emit_arm_fpaDbl2GP(arm_emit_env_t *env, const ir_node *irn) {
742         be_emit_cstring(env->emit, "\tstfd ");
743         arm_emit_source_register(env, irn, 0);
744         be_emit_cstring(env->emit, ", [sp, #-8]!");
745         be_emit_pad_comment(env->emit);
746         be_emit_cstring(env->emit, "/* Push fp to stack */");
747         be_emit_finish_line_gas(env->emit, NULL);
748
749         be_emit_cstring(env->emit, "\tldmfd sp!, {");
750         arm_emit_dest_register(env, irn, 1);
751         be_emit_cstring(env->emit, ", ");
752         arm_emit_dest_register(env, irn, 0);
753         be_emit_char(env->emit, '}');
754         be_emit_pad_comment(env->emit);
755         be_emit_cstring(env->emit, "/* Pop destination */");
756         be_emit_finish_line_gas(env->emit, irn);
757 }
758
759 /***********************************************************************************
760  *                  _          __                                             _
761  *                 (_)        / _|                                           | |
762  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
763  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
764  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
765  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
766  *
767  ***********************************************************************************/
768
769 static void emit_silence(arm_emit_env_t *env, const ir_node *irn) {
770         /* Do nothing. */
771 }
772
773 /**
774  * The type of a emitter function.
775  */
776 typedef void (emit_func)(arm_emit_env_t *env, const ir_node *irn);
777
778 /**
779  * Set a node emitter. Make it a bit more type safe.
780  */
781 static INLINE void set_emitter(ir_op *op, emit_func arm_emit_node) {
782         op->ops.generic = (op_func)arm_emit_node;
783 }
784
785 /**
786  * Enters the emitter functions for handled nodes into the generic
787  * pointer of an opcode.
788  */
789 static void arm_register_emitters(void) {
790
791 #define ARM_EMIT(a)  set_emitter(op_arm_##a, emit_arm_##a)
792 #define EMIT(a)      set_emitter(op_##a, emit_##a)
793 #define BE_EMIT(a)   set_emitter(op_be_##a, emit_be_##a)
794 #define SILENCE(a)   set_emitter(op_##a, emit_silence)
795
796         /* first clear the generic function pointer for all ops */
797         clear_irp_opcodes_generic_func();
798
799         /* register all emitter functions defined in spec */
800         arm_register_spec_emitters();
801
802         /* other emitter functions */
803         ARM_EMIT(CondJmp);
804         ARM_EMIT(CopyB);
805 //      ARM_EMIT(CopyB_i);
806 //      ARM_EMIT(Const);
807         ARM_EMIT(SymConst);
808         ARM_EMIT(SwitchJmp);
809         ARM_EMIT(fpaDbl2GP);
810
811         /* benode emitter */
812         BE_EMIT(Call);
813         BE_EMIT(IncSP);
814 //      BE_EMIT(AddSP);
815         BE_EMIT(Copy);
816         BE_EMIT(Spill);
817         BE_EMIT(Reload);
818         BE_EMIT(Perm);
819         BE_EMIT(StackParam);
820
821         /* firm emitter */
822         EMIT(Jmp);
823
824         /* noisy stuff */
825 #ifdef SILENCER
826         SILENCE(Proj);
827         SILENCE(Phi);
828         SILENCE(be_Keep);
829         SILENCE(be_CopyKeep);
830 #endif
831
832 #undef ARM_EMIT
833 #undef BE_EMIT
834 #undef EMIT
835 #undef SILENCE
836 }
837
838 /**
839  * Emits code for a node.
840  */
841 static void arm_emit_node(arm_emit_env_t *env, const ir_node *irn) {
842         ir_op *op = get_irn_op(irn);
843
844         if (op->ops.generic) {
845                 emit_func *emit = (emit_func *)op->ops.generic;
846                 (*emit)(env, irn);
847         } else {
848                 be_emit_cstring(env->emit, "\t/* TODO */");
849                 be_emit_finish_line_gas(env->emit, irn);
850         }
851 }
852
853 /**
854  * Walks over the nodes in a block connected by scheduling edges
855  * and emits code for each node.
856  */
857 void arm_gen_block(ir_node *block, void *ctx) {
858         arm_emit_env_t *env = ctx;
859         ir_node *irn;
860
861         arm_emit_block_label(env, block);
862         be_emit_cstring(env->emit, ":\n");
863         be_emit_write_line(env->emit);
864
865         sched_foreach(block, irn) {
866                 arm_emit_node(env, irn);
867         }
868 }
869
870
871 /**
872  * Emits code for function start.
873  */
874 void arm_func_prolog(arm_emit_env_t *env, ir_graph *irg) {
875         be_emit_env_t *eenv = env->emit;
876         ir_entity *ent = get_irg_entity(irg);
877         const char *irg_name = get_entity_ld_name(ent);
878
879         be_emit_write_line(eenv);
880         be_gas_emit_switch_section(eenv, GAS_SECTION_TEXT);
881         be_emit_cstring(eenv, "\t.align  2\n");
882
883         if (get_entity_visibility(ent) == visibility_external_visible)
884                 be_emit_irprintf(eenv, "\t.global %s\n", irg_name);
885         be_emit_irprintf(eenv, "%s:\n", irg_name);
886 }
887
888 /**
889  * Emits code for function end
890  */
891 void arm_emit_end(FILE *F, ir_graph *irg) {
892         fprintf(F, "\t.ident \"firmcc\"\n");
893 }
894
895 /**
896  * Sets labels for control flow nodes (jump target)
897  * TODO: Jump optimization
898  */
899 void arm_gen_labels(ir_node *block, void *env) {
900         ir_node *pred;
901         int n = get_Block_n_cfgpreds(block);
902
903         for (n--; n >= 0; n--) {
904                 pred = get_Block_cfgpred(block, n);
905                 set_irn_link(pred, block);
906         }
907 }
908
909
910 /**
911  * Main driver. Emits the code for one routine.
912  */
913 void arm_gen_routine(const arm_code_gen_t *cg, ir_graph *irg)
914 {
915         SymConstEntry *entry;
916         arm_emit_env_t emit_env;
917         ir_node **blk_sched;
918         int i, n;
919
920         emit_env.emit     = &cg->isa->emit;
921         emit_env.arch_env = cg->arch_env;
922         emit_env.cg       = cg;
923         emit_env.symbols  = NULL;
924         obstack_init(&emit_env.obst);
925         FIRM_DBG_REGISTER(emit_env.mod, "firm.be.arm.emit");
926
927         /* set the global arch_env (needed by print hooks) */
928         arch_env = cg->arch_env;
929
930         arm_register_emitters();
931
932         /* create the block schedule. For now, we don't need it earlier. */
933         blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
934
935         arm_func_prolog(&emit_env, irg);
936         irg_block_walk_graph(irg, arm_gen_labels, NULL, &emit_env);
937
938         n = ARR_LEN(blk_sched);
939         for (i = 0; i < n;) {
940                 ir_node *block, *next_bl;
941
942                 block   = blk_sched[i];
943                 ++i;
944                 next_bl = i < n ? blk_sched[i] : NULL;
945
946                 /* set here the link. the emitter expects to find the next block here */
947                 set_irn_link(block, next_bl);
948                 arm_gen_block(block, &emit_env);
949         }
950
951         /* emit SymConst values */
952         if (emit_env.symbols)
953                 be_emit_cstring(emit_env.emit, "\t.align 2\n");
954
955         for (entry = emit_env.symbols; entry; entry = entry->next) {
956                 be_emit_irprintf(emit_env.emit, ".L%u:\n", entry->label);
957                 be_emit_cstring(emit_env.emit, "\t.word\t");
958                 arm_emit_immediate(&emit_env, entry->symconst);
959                 be_emit_char(emit_env.emit, '\n');
960                 be_emit_write_line(emit_env.emit);
961         }
962
963         obstack_free(&emit_env.obst, NULL);
964 }