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