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