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