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