2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
23 * @author Oliver Richter, Tobias Gneist, Michael Beck
42 #include "raw_bitset.h"
45 #include "../besched.h"
46 #include "../beblocksched.h"
48 #include "../begnuas.h"
49 #include "../be_dbgout.h"
51 #include "arm_emitter.h"
52 #include "arm_optimize.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"
59 #include "../benode.h"
61 #define SNPRINTF_BUF_LEN 128
63 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
65 static set *sym_or_tv;
66 static arm_isa_t *isa;
68 static void arm_emit_register(const arch_register_t *reg)
70 be_emit_string(arch_register_get_name(reg));
73 void arm_emit_source_register(const ir_node *node, int pos)
75 const arch_register_t *reg = arch_get_irn_register_in(node, pos);
76 arm_emit_register(reg);
79 void arm_emit_dest_register(const ir_node *node, int pos)
81 const arch_register_t *reg = arch_get_irn_register_out(node, pos);
82 arm_emit_register(reg);
85 void arm_emit_offset(const ir_node *node)
87 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
88 assert(attr->base.is_load_store);
90 be_emit_irprintf("0x%X", attr->offset);
94 * Emit the arm fpa instruction suffix depending on the mode.
96 static void arm_emit_fpa_postfix(const ir_mode *mode)
98 int bits = get_mode_size_bits(mode);
108 void arm_emit_float_load_store_mode(const ir_node *node)
110 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
111 arm_emit_fpa_postfix(attr->load_store_mode);
114 void arm_emit_float_arithmetic_mode(const ir_node *node)
116 const arm_farith_attr_t *attr = get_arm_farith_attr_const(node);
117 arm_emit_fpa_postfix(attr->mode);
120 void arm_emit_symconst(const ir_node *node)
122 const arm_SymConst_attr_t *symconst = get_arm_SymConst_attr_const(node);
123 ir_entity *entity = symconst->entity;
125 be_gas_emit_entity(entity);
127 /* TODO do something with offset */
130 void arm_emit_load_mode(const ir_node *node)
132 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
133 ir_mode *mode = attr->load_store_mode;
134 int bits = get_mode_size_bits(mode);
135 bool is_signed = mode_is_signed(mode);
137 be_emit_string(is_signed ? "sh" : "h");
138 } else if (bits == 8) {
139 be_emit_string(is_signed ? "sb" : "b");
145 void arm_emit_store_mode(const ir_node *node)
147 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
148 ir_mode *mode = attr->load_store_mode;
149 int bits = get_mode_size_bits(mode);
151 be_emit_cstring("h");
152 } else if (bits == 8) {
153 be_emit_cstring("b");
159 static void emit_shf_mod_name(arm_shift_modifier_t mod)
162 case ARM_SHF_ASR_REG:
163 case ARM_SHF_ASR_IMM:
164 be_emit_cstring("asr");
166 case ARM_SHF_LSL_REG:
167 case ARM_SHF_LSL_IMM:
168 be_emit_cstring("lsl");
170 case ARM_SHF_LSR_REG:
171 case ARM_SHF_LSR_IMM:
172 be_emit_cstring("lsr");
174 case ARM_SHF_ROR_REG:
175 case ARM_SHF_ROR_IMM:
176 be_emit_cstring("ror");
181 panic("can't emit this shf_mod_name %d", (int) mod);
184 void arm_emit_shifter_operand(const ir_node *node)
186 const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(node);
188 switch (attr->shift_modifier) {
190 arm_emit_source_register(node, get_irn_arity(node) - 1);
193 unsigned val = attr->immediate_value;
194 val = (val >> attr->shift_immediate)
195 | (val << (32-attr->shift_immediate));
197 be_emit_irprintf("#0x%X", val);
200 case ARM_SHF_ASR_IMM:
201 case ARM_SHF_LSL_IMM:
202 case ARM_SHF_LSR_IMM:
203 case ARM_SHF_ROR_IMM:
204 arm_emit_source_register(node, get_irn_arity(node) - 1);
205 be_emit_cstring(", ");
206 emit_shf_mod_name(attr->shift_modifier);
207 be_emit_irprintf(" #0x%X", attr->shift_immediate);
210 case ARM_SHF_ASR_REG:
211 case ARM_SHF_LSL_REG:
212 case ARM_SHF_LSR_REG:
213 case ARM_SHF_ROR_REG:
214 arm_emit_source_register(node, get_irn_arity(node) - 2);
215 be_emit_cstring(", ");
216 emit_shf_mod_name(attr->shift_modifier);
217 be_emit_cstring(" ");
218 arm_emit_source_register(node, get_irn_arity(node) - 1);
222 arm_emit_source_register(node, get_irn_arity(node) - 1);
223 panic("RRX shifter emitter TODO");
225 case ARM_SHF_INVALID:
228 panic("Invalid shift_modifier while emitting %+F", node);
231 /** An entry in the sym_or_tv set. */
232 typedef struct sym_or_tv_t {
234 ir_entity *entity; /**< An entity. */
235 ir_tarval *tv; /**< A tarval. */
236 const void *generic; /**< For generic compare. */
238 unsigned label; /**< the associated label. */
239 bool is_entity; /**< true if an entity is stored. */
243 * Returns a unique label. This number will not be used a second time.
245 static unsigned get_unique_label(void)
247 static unsigned id = 0;
251 static void emit_constant_name(const sym_or_tv_t *entry)
253 be_emit_irprintf("%sC%u", be_gas_get_private_prefix(), entry->label);
259 static void emit_arm_SymConst(const ir_node *irn)
261 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
262 sym_or_tv_t key, *entry;
264 key.u.entity = attr->entity;
265 key.is_entity = true;
267 entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
268 if (entry->label == 0) {
269 /* allocate a label */
270 entry->label = get_unique_label();
273 /* load the symbol indirect */
274 be_emit_cstring("\tldr ");
275 arm_emit_dest_register(irn, 0);
276 be_emit_cstring(", ");
277 emit_constant_name(entry);
278 be_emit_finish_line_gas(irn);
281 static void emit_arm_FrameAddr(const ir_node *irn)
283 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
285 be_emit_cstring("\tadd ");
286 arm_emit_dest_register(irn, 0);
287 be_emit_cstring(", ");
288 arm_emit_source_register(irn, 0);
289 be_emit_cstring(", ");
290 be_emit_irprintf("#0x%X", attr->fp_offset);
291 be_emit_finish_line_gas(irn);
295 * Emit a floating point fpa constant.
297 static void emit_arm_fConst(const ir_node *irn)
299 sym_or_tv_t key, *entry;
302 key.u.tv = get_fConst_value(irn);
303 key.is_entity = false;
305 entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
306 if (entry->label == 0) {
307 /* allocate a label */
308 entry->label = get_unique_label();
311 /* load the tarval indirect */
312 mode = get_irn_mode(irn);
313 be_emit_cstring("\tldf");
314 arm_emit_fpa_postfix(mode);
317 arm_emit_dest_register(irn, 0);
318 be_emit_cstring(", ");
319 emit_constant_name(entry);
320 be_emit_finish_line_gas(irn);
324 * Returns the next block in a block schedule.
326 static ir_node *sched_next_block(const ir_node *block)
328 return (ir_node*)get_irn_link(block);
332 * Returns the target block for a control flow node.
334 static ir_node *get_cfop_target_block(const ir_node *irn)
336 return (ir_node*)get_irn_link(irn);
340 * Emit the target label for a control flow node.
342 static void arm_emit_cfop_target(const ir_node *irn)
344 ir_node *block = get_cfop_target_block(irn);
346 be_gas_emit_block_name(block);
350 * Emit a Compare with conditional branch.
352 static void emit_arm_B(const ir_node *irn)
354 const ir_edge_t *edge;
355 const ir_node *proj_true = NULL;
356 const ir_node *proj_false = NULL;
357 const ir_node *block;
358 const ir_node *next_block;
359 ir_node *op1 = get_irn_n(irn, 0);
361 ir_relation relation = get_arm_CondJmp_relation(irn);
362 const arm_cmp_attr_t *cmp_attr = get_arm_cmp_attr_const(op1);
363 bool is_signed = !cmp_attr->is_unsigned;
365 assert(is_arm_Cmp(op1) || is_arm_Tst(op1));
367 foreach_out_edge(irn, edge) {
368 ir_node *proj = get_edge_src_irn(edge);
369 long nr = get_Proj_proj(proj);
370 if (nr == pn_Cond_true) {
377 if (cmp_attr->ins_permuted) {
378 relation = get_inversed_relation(relation);
381 /* for now, the code works for scheduled and non-schedules blocks */
382 block = get_nodes_block(irn);
384 /* we have a block schedule */
385 next_block = sched_next_block(block);
387 assert(relation != ir_relation_false);
388 assert(relation != ir_relation_true);
390 if (get_cfop_target_block(proj_true) == next_block) {
391 /* exchange both proj's so the second one can be omitted */
392 const ir_node *t = proj_true;
394 proj_true = proj_false;
396 relation = get_negated_relation(relation);
399 switch (relation & (ir_relation_less_equal_greater)) {
400 case ir_relation_equal: suffix = "eq"; break;
401 case ir_relation_less: suffix = is_signed ? "lt" : "lo"; break;
402 case ir_relation_less_equal: suffix = is_signed ? "le" : "ls"; break;
403 case ir_relation_greater: suffix = is_signed ? "gt" : "hi"; break;
404 case ir_relation_greater_equal: suffix = is_signed ? "ge" : "hs"; break;
405 case ir_relation_less_greater: suffix = "ne"; break;
406 case ir_relation_less_equal_greater: suffix = "al"; break;
407 default: panic("Cmp has unsupported relation");
410 /* emit the true proj */
411 be_emit_irprintf("\tb%s ", suffix);
412 arm_emit_cfop_target(proj_true);
413 be_emit_finish_line_gas(proj_true);
415 if (get_cfop_target_block(proj_false) == next_block) {
416 be_emit_cstring("\t/* fallthrough to ");
417 arm_emit_cfop_target(proj_false);
418 be_emit_cstring(" */");
419 be_emit_finish_line_gas(proj_false);
421 be_emit_cstring("\tb ");
422 arm_emit_cfop_target(proj_false);
423 be_emit_finish_line_gas(proj_false);
427 /** Sort register in ascending order. */
428 static int reg_cmp(const void *a, const void *b)
430 const arch_register_t * const *ra = (const arch_register_t**)a;
431 const arch_register_t * const *rb = (const arch_register_t**)b;
433 return *ra < *rb ? -1 : (*ra != *rb);
437 * Create the CopyB instruction sequence.
439 static void emit_arm_CopyB(const ir_node *irn)
441 const arm_CopyB_attr_t *attr = get_arm_CopyB_attr_const(irn);
442 unsigned size = attr->size;
444 const char *tgt = arch_register_get_name(arch_get_irn_register_in(irn, 0));
445 const char *src = arch_register_get_name(arch_get_irn_register_in(irn, 1));
446 const char *t0, *t1, *t2, *t3;
448 const arch_register_t *tmpregs[4];
450 /* collect the temporary registers and sort them, we need ascending order */
451 tmpregs[0] = arch_get_irn_register_in(irn, 2);
452 tmpregs[1] = arch_get_irn_register_in(irn, 3);
453 tmpregs[2] = arch_get_irn_register_in(irn, 4);
454 tmpregs[3] = &arm_registers[REG_R12];
456 /* Note: R12 is always the last register because the RA did not assign higher ones */
457 qsort((void *)tmpregs, 3, sizeof(tmpregs[0]), reg_cmp);
459 /* need ascending order */
460 t0 = arch_register_get_name(tmpregs[0]);
461 t1 = arch_register_get_name(tmpregs[1]);
462 t2 = arch_register_get_name(tmpregs[2]);
463 t3 = arch_register_get_name(tmpregs[3]);
465 be_emit_cstring("/* MemCopy (");
467 be_emit_cstring(")->(");
468 arm_emit_source_register(irn, 0);
469 be_emit_irprintf(" [%u bytes], Uses ", size);
471 be_emit_cstring(", ");
473 be_emit_cstring(", ");
475 be_emit_cstring(", and ");
477 be_emit_cstring("*/");
478 be_emit_finish_line_gas(NULL);
480 assert(size > 0 && "CopyB needs size > 0" );
483 fprintf(stderr, "strange hack enabled: copy more bytes than needed!");
492 be_emit_cstring("\tldr ");
494 be_emit_cstring(", [");
496 be_emit_cstring(", #0]");
497 be_emit_finish_line_gas(NULL);
499 be_emit_cstring("\tstr ");
501 be_emit_cstring(", [");
503 be_emit_cstring(", #0]");
504 be_emit_finish_line_gas(irn);
507 be_emit_cstring("\tldmia ");
509 be_emit_cstring("!, {");
511 be_emit_cstring(", ");
514 be_emit_finish_line_gas(NULL);
516 be_emit_cstring("\tstmia ");
518 be_emit_cstring("!, {");
520 be_emit_cstring(", ");
523 be_emit_finish_line_gas(irn);
526 be_emit_cstring("\tldmia ");
528 be_emit_cstring("!, {");
530 be_emit_cstring(", ");
532 be_emit_cstring(", ");
535 be_emit_finish_line_gas(NULL);
537 be_emit_cstring("\tstmia ");
539 be_emit_cstring("!, {");
541 be_emit_cstring(", ");
543 be_emit_cstring(", ");
546 be_emit_finish_line_gas(irn);
551 be_emit_cstring("\tldmia ");
553 be_emit_cstring("!, {");
555 be_emit_cstring(", ");
557 be_emit_cstring(", ");
559 be_emit_cstring(", ");
562 be_emit_finish_line_gas(NULL);
564 be_emit_cstring("\tstmia ");
566 be_emit_cstring("!, {");
568 be_emit_cstring(", ");
570 be_emit_cstring(", ");
572 be_emit_cstring(", ");
575 be_emit_finish_line_gas(irn);
580 static void emit_arm_SwitchJmp(const ir_node *irn)
582 const ir_edge_t *edge;
588 ir_node *default_proj = NULL;
590 block_nr = get_irn_node_nr(irn);
591 n_projs = get_arm_SwitchJmp_n_projs(irn);
593 projs = XMALLOCNZ(ir_node*, n_projs);
595 foreach_out_edge(irn, edge) {
596 proj = get_edge_src_irn(edge);
597 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
599 if (get_Proj_proj(proj) == get_arm_SwitchJmp_default_proj_num(irn))
602 projs[get_Proj_proj(proj)] = proj;
604 assert(default_proj != NULL && "SwitchJmp should have a Default Proj");
611 be_emit_cstring("\tcmp ");
612 arm_emit_source_register(irn, 0);
613 be_emit_irprintf(", #%u", n_projs - 1);
614 be_emit_finish_line_gas(irn);
616 be_emit_cstring("\tbhi ");
617 arm_emit_cfop_target(default_proj);
618 be_emit_finish_line_gas(default_proj);
621 LDR %r12, .TABLE_X_START
622 ADD %r12, %r12, [%1S, LSL #2]
626 be_emit_irprintf("\tldr %%r12, TABLE_%d_START", block_nr);
627 be_emit_finish_line_gas(NULL);
629 be_emit_irprintf("\tadd %%r12, %%r12, ");
630 arm_emit_source_register(irn, 0);
631 be_emit_cstring(", LSL #2");
632 be_emit_finish_line_gas(NULL);
634 be_emit_cstring("\tldr %r15, [%r12, #0]");
635 be_emit_finish_line_gas(NULL);
637 be_emit_irprintf("TABLE_%d_START:\n\t.word\tTABLE_%d", block_nr, block_nr);
638 be_emit_finish_line_gas(NULL);
639 be_emit_irprintf("\t.align 2");
640 be_emit_finish_line_gas(NULL);
641 be_emit_irprintf("TABLE_%d:", block_nr);
642 be_emit_finish_line_gas(NULL);
644 for (i = 0; i < n_projs; ++i) {
647 proj = projs[get_arm_SwitchJmp_default_proj_num(irn)];
649 be_emit_cstring("\t.word\t");
650 arm_emit_cfop_target(proj);
651 be_emit_finish_line_gas(proj);
653 be_emit_irprintf("\t.align 2\n");
654 be_emit_finish_line_gas(NULL);
658 /** Emit an IncSP node */
659 static void emit_be_IncSP(const ir_node *irn)
661 int offs = -be_get_IncSP_offset(irn);
665 be_emit_cstring("\tsub ");
668 be_emit_cstring("\tadd ");
670 arm_emit_dest_register(irn, 0);
671 be_emit_cstring(", ");
672 arm_emit_source_register(irn, 0);
673 be_emit_irprintf(", #0x%X", offs);
674 be_emit_finish_line_gas(irn);
676 /* omitted IncSP(0) */
681 static void emit_be_Copy(const ir_node *irn)
683 ir_mode *mode = get_irn_mode(irn);
685 if (arch_get_irn_register_in(irn, 0) == arch_get_irn_register_out(irn, 0)) {
690 if (mode_is_float(mode)) {
692 be_emit_cstring("\tmvf");
694 arm_emit_dest_register(irn, 0);
695 be_emit_cstring(", ");
696 arm_emit_source_register(irn, 0);
697 be_emit_finish_line_gas(irn);
699 panic("emit_be_Copy: move not supported for this mode");
701 } else if (mode_is_data(mode)) {
702 be_emit_cstring("\tmov ");
703 arm_emit_dest_register(irn, 0);
704 be_emit_cstring(", ");
705 arm_emit_source_register(irn, 0);
706 be_emit_finish_line_gas(irn);
708 panic("emit_be_Copy: move not supported for this mode");
712 static void emit_be_Perm(const ir_node *irn)
714 be_emit_cstring("\teor ");
715 arm_emit_source_register(irn, 0);
716 be_emit_cstring(", ");
717 arm_emit_source_register(irn, 0);
718 be_emit_cstring(", ");
719 arm_emit_source_register(irn, 1);
720 be_emit_finish_line_gas(NULL);
722 be_emit_cstring("\teor ");
723 arm_emit_source_register(irn, 1);
724 be_emit_cstring(", ");
725 arm_emit_source_register(irn, 0);
726 be_emit_cstring(", ");
727 arm_emit_source_register(irn, 1);
728 be_emit_finish_line_gas(NULL);
730 be_emit_cstring("\teor ");
731 arm_emit_source_register(irn, 0);
732 be_emit_cstring(", ");
733 arm_emit_source_register(irn, 0);
734 be_emit_cstring(", ");
735 arm_emit_source_register(irn, 1);
736 be_emit_finish_line_gas(irn);
739 static void emit_be_MemPerm(const ir_node *node)
745 /* TODO: this implementation is slower than necessary.
746 The longterm goal is however to avoid the memperm node completely */
748 memperm_arity = be_get_MemPerm_entity_arity(node);
749 if (memperm_arity > 12)
750 panic("memperm with more than 12 inputs not supported yet");
752 for (i = 0; i < memperm_arity; ++i) {
754 ir_entity *entity = be_get_MemPerm_in_entity(node, i);
757 be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
758 be_emit_finish_line_gas(node);
760 /* load from entity */
761 offset = get_entity_offset(entity) + sp_change;
762 be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
763 be_emit_finish_line_gas(node);
766 for (i = memperm_arity-1; i >= 0; --i) {
768 ir_entity *entity = be_get_MemPerm_out_entity(node, i);
770 /* store to new entity */
771 offset = get_entity_offset(entity) + sp_change;
772 be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
773 be_emit_finish_line_gas(node);
774 /* restore register */
775 be_emit_irprintf("\tldr r%d, [sp], #4", i);
777 be_emit_finish_line_gas(node);
779 assert(sp_change == 0);
782 static void emit_be_Start(const ir_node *node)
784 ir_graph *irg = get_irn_irg(node);
785 ir_type *frame_type = get_irg_frame_type(irg);
786 unsigned size = get_type_size_bytes(frame_type);
788 /* allocate stackframe */
790 be_emit_cstring("\tsub ");
791 arm_emit_register(&arm_registers[REG_SP]);
792 be_emit_cstring(", ");
793 arm_emit_register(&arm_registers[REG_SP]);
794 be_emit_irprintf(", #0x%X", size);
795 be_emit_finish_line_gas(node);
799 static void emit_be_Return(const ir_node *node)
801 ir_graph *irg = get_irn_irg(node);
802 ir_type *frame_type = get_irg_frame_type(irg);
803 unsigned size = get_type_size_bytes(frame_type);
805 /* deallocate stackframe */
807 be_emit_cstring("\tadd ");
808 arm_emit_register(&arm_registers[REG_SP]);
809 be_emit_cstring(", ");
810 arm_emit_register(&arm_registers[REG_SP]);
811 be_emit_irprintf(", #0x%X", size);
812 be_emit_finish_line_gas(node);
815 be_emit_cstring("\tmov pc, lr");
816 be_emit_finish_line_gas(node);
820 static void emit_arm_Jmp(const ir_node *node)
822 ir_node *block, *next_block;
824 /* for now, the code works for scheduled and non-schedules blocks */
825 block = get_nodes_block(node);
827 /* we have a block schedule */
828 next_block = sched_next_block(block);
829 if (get_cfop_target_block(node) != next_block) {
830 be_emit_cstring("\tb ");
831 arm_emit_cfop_target(node);
833 be_emit_cstring("\t/* fallthrough to ");
834 arm_emit_cfop_target(node);
835 be_emit_cstring(" */");
837 be_emit_finish_line_gas(node);
840 static void emit_nothing(const ir_node *irn)
846 * The type of a emitter function.
848 typedef void (emit_func)(const ir_node *irn);
851 * Set a node emitter. Make it a bit more type safe.
853 static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
855 op->ops.generic = (op_func)arm_emit_node;
859 * Enters the emitter functions for handled nodes into the generic
860 * pointer of an opcode.
862 static void arm_register_emitters(void)
864 /* first clear the generic function pointer for all ops */
865 clear_irp_opcodes_generic_func();
867 /* register all emitter functions defined in spec */
868 arm_register_spec_emitters();
871 set_emitter(op_arm_B, emit_arm_B);
872 set_emitter(op_arm_CopyB, emit_arm_CopyB);
873 set_emitter(op_arm_fConst, emit_arm_fConst);
874 set_emitter(op_arm_FrameAddr, emit_arm_FrameAddr);
875 set_emitter(op_arm_Jmp, emit_arm_Jmp);
876 set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp);
877 set_emitter(op_arm_SymConst, emit_arm_SymConst);
878 set_emitter(op_be_Copy, emit_be_Copy);
879 set_emitter(op_be_CopyKeep, emit_be_Copy);
880 set_emitter(op_be_IncSP, emit_be_IncSP);
881 set_emitter(op_be_MemPerm, emit_be_MemPerm);
882 set_emitter(op_be_Perm, emit_be_Perm);
883 set_emitter(op_be_Return, emit_be_Return);
884 set_emitter(op_be_Start, emit_be_Start);
886 /* no need to emit anything for the following nodes */
887 set_emitter(op_Phi, emit_nothing);
888 set_emitter(op_be_Keep, emit_nothing);
892 * Emits code for a node.
894 static void arm_emit_node(const ir_node *irn)
896 ir_op *op = get_irn_op(irn);
898 if (op->ops.generic) {
899 emit_func *emit = (emit_func *)op->ops.generic;
900 be_dbg_set_dbg_info(get_irn_dbg_info(irn));
903 panic("Error: No emit handler for node %+F (graph %+F)\n",
904 irn, current_ir_graph);
909 * emit the block label if needed.
911 static void arm_emit_block_header(ir_node *block, ir_node *prev)
916 ir_graph *irg = get_irn_irg(block);
917 ir_exec_freq *exec_freq = be_get_irg_exec_freq(irg);
920 n_cfgpreds = get_Block_n_cfgpreds(block);
921 if (n_cfgpreds == 1) {
922 ir_node *pred = get_Block_cfgpred(block, 0);
923 ir_node *pred_block = get_nodes_block(pred);
925 /* we don't need labels for fallthrough blocks, however switch-jmps
926 * are no fallthroughs */
927 if (pred_block == prev &&
928 !(is_Proj(pred) && is_arm_SwitchJmp(get_Proj_pred(pred)))) {
938 be_gas_emit_block_name(block);
941 be_emit_pad_comment();
942 be_emit_cstring(" /* preds:");
944 /* emit list of pred blocks in comment */
945 arity = get_irn_arity(block);
946 for (i = 0; i < arity; ++i) {
947 ir_node *predblock = get_Block_cfgpred_block(block, i);
948 be_emit_irprintf(" %d", get_irn_node_nr(predblock));
951 be_emit_cstring("\t/* ");
952 be_gas_emit_block_name(block);
953 be_emit_cstring(": ");
955 if (exec_freq != NULL) {
956 be_emit_irprintf(" freq: %f",
957 get_block_execfreq(exec_freq, block));
959 be_emit_cstring(" */\n");
960 be_emit_write_line();
964 * Walks over the nodes in a block connected by scheduling edges
965 * and emits code for each node.
967 static void arm_gen_block(ir_node *block, ir_node *prev_block)
971 arm_emit_block_header(block, prev_block);
972 be_dbg_set_dbg_info(get_irn_dbg_info(block));
973 sched_foreach(block, irn) {
980 * Sets labels for control flow nodes (jump target)
982 static void arm_gen_labels(ir_node *block, void *env)
985 int n = get_Block_n_cfgpreds(block);
988 for (n--; n >= 0; n--) {
989 pred = get_Block_cfgpred(block, n);
990 set_irn_link(pred, block);
995 * Compare two entries of the symbol or tarval set.
997 static int cmp_sym_or_tv(const void *elt, const void *key, size_t size)
999 const sym_or_tv_t *p1 = (const sym_or_tv_t*)elt;
1000 const sym_or_tv_t *p2 = (const sym_or_tv_t*)key;
1003 /* as an identifier NEVER can point to a tarval, it's enough
1004 to compare it this way */
1005 return p1->u.generic != p2->u.generic;
1008 void arm_gen_routine(ir_graph *irg)
1010 ir_node *last_block = NULL;
1011 ir_entity *entity = get_irg_entity(irg);
1012 const arch_env_t *arch_env = be_get_irg_arch_env(irg);
1013 ir_node **blk_sched;
1016 isa = (arm_isa_t*) arch_env;
1017 sym_or_tv = new_set(cmp_sym_or_tv, 8);
1019 be_gas_elf_type_char = '%';
1021 arm_register_emitters();
1023 be_dbg_method_begin(entity);
1025 /* create the block schedule */
1026 blk_sched = be_create_block_schedule(irg);
1028 be_gas_emit_function_prolog(entity, 4);
1030 irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
1032 n = ARR_LEN(blk_sched);
1033 for (i = 0; i < n;) {
1034 ir_node *block, *next_bl;
1036 block = blk_sched[i];
1038 next_bl = i < n ? blk_sched[i] : NULL;
1040 /* set here the link. the emitter expects to find the next block here */
1041 set_irn_link(block, next_bl);
1042 arm_gen_block(block, last_block);
1046 /* emit SymConst values */
1047 if (set_count(sym_or_tv) > 0) {
1050 be_emit_cstring("\t.align 2\n");
1052 foreach_set(sym_or_tv, sym_or_tv_t*, entry) {
1053 emit_constant_name(entry);
1054 be_emit_cstring(":\n");
1055 be_emit_write_line();
1057 if (entry->is_entity) {
1058 be_emit_cstring("\t.word\t");
1059 be_gas_emit_entity(entry->u.entity);
1061 be_emit_write_line();
1063 ir_tarval *tv = entry->u.tv;
1065 int size = get_mode_size_bytes(get_tarval_mode(tv));
1067 /* beware: ARM fpa uses big endian format */
1068 for (vi = ((size + 3) & ~3) - 4; vi >= 0; vi -= 4) {
1071 v = get_tarval_sub_bits(tv, vi+3);
1072 v = (v << 8) | get_tarval_sub_bits(tv, vi+2);
1073 v = (v << 8) | get_tarval_sub_bits(tv, vi+1);
1074 v = (v << 8) | get_tarval_sub_bits(tv, vi+0);
1075 be_emit_irprintf("\t.word\t%u\n", v);
1076 be_emit_write_line();
1081 be_emit_write_line();
1085 be_gas_emit_function_epilog(entity);
1086 be_dbg_method_end();
1089 void arm_init_emitter(void)
1091 FIRM_DBG_REGISTER(dbg, "firm.be.arm.emit");