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;
69 * Returns the register at in position pos.
71 static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
73 ir_node *op = get_irn_n(irn, pos);
74 return arch_get_irn_register(op);
77 static void arm_emit_register(const arch_register_t *reg)
79 be_emit_string(arch_register_get_name(reg));
82 void arm_emit_source_register(const ir_node *node, int pos)
84 const arch_register_t *reg = get_in_reg(node, pos);
85 arm_emit_register(reg);
88 void arm_emit_dest_register(const ir_node *node, int pos)
90 const arch_register_t *reg = arch_irn_get_register(node, pos);
91 arm_emit_register(reg);
94 void arm_emit_offset(const ir_node *node)
96 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
97 assert(attr->base.is_load_store);
99 be_emit_irprintf("0x%X", attr->offset);
103 * Emit the arm fpa instruction suffix depending on the mode.
105 static void arm_emit_fpa_postfix(const ir_mode *mode)
107 int bits = get_mode_size_bits(mode);
117 void arm_emit_float_load_store_mode(const ir_node *node)
119 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
120 arm_emit_fpa_postfix(attr->load_store_mode);
123 void arm_emit_float_arithmetic_mode(const ir_node *node)
125 const arm_farith_attr_t *attr = get_arm_farith_attr_const(node);
126 arm_emit_fpa_postfix(attr->mode);
129 void arm_emit_symconst(const ir_node *node)
131 const arm_SymConst_attr_t *symconst = get_arm_SymConst_attr_const(node);
132 ir_entity *entity = symconst->entity;
134 be_gas_emit_entity(entity);
136 /* TODO do something with offset */
139 void arm_emit_load_mode(const ir_node *node)
141 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
142 ir_mode *mode = attr->load_store_mode;
143 int bits = get_mode_size_bits(mode);
144 bool is_signed = mode_is_signed(mode);
146 be_emit_string(is_signed ? "sh" : "h");
147 } else if (bits == 8) {
148 be_emit_string(is_signed ? "sb" : "b");
154 void arm_emit_store_mode(const ir_node *node)
156 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
157 ir_mode *mode = attr->load_store_mode;
158 int bits = get_mode_size_bits(mode);
160 be_emit_cstring("h");
161 } else if (bits == 8) {
162 be_emit_cstring("b");
168 static void emit_shf_mod_name(arm_shift_modifier_t mod)
171 case ARM_SHF_ASR_REG:
172 case ARM_SHF_ASR_IMM:
173 be_emit_cstring("asr");
175 case ARM_SHF_LSL_REG:
176 case ARM_SHF_LSL_IMM:
177 be_emit_cstring("lsl");
179 case ARM_SHF_LSR_REG:
180 case ARM_SHF_LSR_IMM:
181 be_emit_cstring("lsr");
183 case ARM_SHF_ROR_REG:
184 case ARM_SHF_ROR_IMM:
185 be_emit_cstring("ror");
190 panic("can't emit this shf_mod_name %d", (int) mod);
193 void arm_emit_shifter_operand(const ir_node *node)
195 const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(node);
197 switch (attr->shift_modifier) {
199 arm_emit_source_register(node, get_irn_arity(node) - 1);
202 unsigned val = attr->immediate_value;
203 val = (val >> attr->shift_immediate)
204 | (val << (32-attr->shift_immediate));
206 be_emit_irprintf("#0x%X", val);
209 case ARM_SHF_ASR_IMM:
210 case ARM_SHF_LSL_IMM:
211 case ARM_SHF_LSR_IMM:
212 case ARM_SHF_ROR_IMM:
213 arm_emit_source_register(node, get_irn_arity(node) - 1);
214 be_emit_cstring(", ");
215 emit_shf_mod_name(attr->shift_modifier);
216 be_emit_irprintf(" #0x%X", attr->shift_immediate);
219 case ARM_SHF_ASR_REG:
220 case ARM_SHF_LSL_REG:
221 case ARM_SHF_LSR_REG:
222 case ARM_SHF_ROR_REG:
223 arm_emit_source_register(node, get_irn_arity(node) - 2);
224 be_emit_cstring(", ");
225 emit_shf_mod_name(attr->shift_modifier);
226 be_emit_cstring(" ");
227 arm_emit_source_register(node, get_irn_arity(node) - 1);
231 arm_emit_source_register(node, get_irn_arity(node) - 1);
232 panic("RRX shifter emitter TODO");
234 case ARM_SHF_INVALID:
237 panic("Invalid shift_modifier while emitting %+F", node);
240 /** An entry in the sym_or_tv set. */
241 typedef struct sym_or_tv_t {
243 ir_entity *entity; /**< An entity. */
244 ir_tarval *tv; /**< A tarval. */
245 const void *generic; /**< For generic compare. */
247 unsigned label; /**< the associated label. */
248 bool is_entity; /**< true if an entity is stored. */
252 * Returns a unique label. This number will not be used a second time.
254 static unsigned get_unique_label(void)
256 static unsigned id = 0;
260 static void emit_constant_name(const sym_or_tv_t *entry)
262 be_emit_irprintf("%sC%u", be_gas_get_private_prefix(), entry->label);
268 static void emit_arm_SymConst(const ir_node *irn)
270 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
271 sym_or_tv_t key, *entry;
273 key.u.entity = attr->entity;
274 key.is_entity = true;
276 entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
277 if (entry->label == 0) {
278 /* allocate a label */
279 entry->label = get_unique_label();
282 /* load the symbol indirect */
283 be_emit_cstring("\tldr ");
284 arm_emit_dest_register(irn, 0);
285 be_emit_cstring(", ");
286 emit_constant_name(entry);
287 be_emit_finish_line_gas(irn);
290 static void emit_arm_FrameAddr(const ir_node *irn)
292 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
294 be_emit_cstring("\tadd ");
295 arm_emit_dest_register(irn, 0);
296 be_emit_cstring(", ");
297 arm_emit_source_register(irn, 0);
298 be_emit_cstring(", ");
299 be_emit_irprintf("#0x%X", attr->fp_offset);
300 be_emit_finish_line_gas(irn);
304 * Emit a floating point fpa constant.
306 static void emit_arm_fConst(const ir_node *irn)
308 sym_or_tv_t key, *entry;
311 key.u.tv = get_fConst_value(irn);
312 key.is_entity = false;
314 entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
315 if (entry->label == 0) {
316 /* allocate a label */
317 entry->label = get_unique_label();
320 /* load the tarval indirect */
321 mode = get_irn_mode(irn);
322 be_emit_cstring("\tldf");
323 arm_emit_fpa_postfix(mode);
326 arm_emit_dest_register(irn, 0);
327 be_emit_cstring(", ");
328 emit_constant_name(entry);
329 be_emit_finish_line_gas(irn);
333 * Returns the next block in a block schedule.
335 static ir_node *sched_next_block(const ir_node *block)
337 return (ir_node*)get_irn_link(block);
341 * Returns the target block for a control flow node.
343 static ir_node *get_cfop_target_block(const ir_node *irn)
345 return (ir_node*)get_irn_link(irn);
349 * Emit the target label for a control flow node.
351 static void arm_emit_cfop_target(const ir_node *irn)
353 ir_node *block = get_cfop_target_block(irn);
355 be_gas_emit_block_name(block);
359 * Emit a Compare with conditional branch.
361 static void emit_arm_B(const ir_node *irn)
363 const ir_edge_t *edge;
364 const ir_node *proj_true = NULL;
365 const ir_node *proj_false = NULL;
366 const ir_node *block;
367 const ir_node *next_block;
368 ir_node *op1 = get_irn_n(irn, 0);
370 ir_relation relation = get_arm_CondJmp_relation(irn);
371 const arm_cmp_attr_t *cmp_attr = get_arm_cmp_attr_const(op1);
372 bool is_signed = !cmp_attr->is_unsigned;
374 assert(is_arm_Cmp(op1) || is_arm_Tst(op1));
376 foreach_out_edge(irn, edge) {
377 ir_node *proj = get_edge_src_irn(edge);
378 long nr = get_Proj_proj(proj);
379 if (nr == pn_Cond_true) {
386 if (cmp_attr->ins_permuted) {
387 relation = get_inversed_relation(relation);
390 /* for now, the code works for scheduled and non-schedules blocks */
391 block = get_nodes_block(irn);
393 /* we have a block schedule */
394 next_block = sched_next_block(block);
396 assert(relation != ir_relation_false);
397 assert(relation != ir_relation_true);
399 if (get_cfop_target_block(proj_true) == next_block) {
400 /* exchange both proj's so the second one can be omitted */
401 const ir_node *t = proj_true;
403 proj_true = proj_false;
405 relation = get_negated_relation(relation);
408 switch (relation & (ir_relation_less_equal_greater)) {
409 case ir_relation_equal: suffix = "eq"; break;
410 case ir_relation_less: suffix = is_signed ? "lt" : "lo"; break;
411 case ir_relation_less_equal: suffix = is_signed ? "le" : "ls"; break;
412 case ir_relation_greater: suffix = is_signed ? "gt" : "hi"; break;
413 case ir_relation_greater_equal: suffix = is_signed ? "ge" : "hs"; break;
414 case ir_relation_less_greater: suffix = "ne"; break;
415 case ir_relation_less_equal_greater: suffix = "al"; break;
416 default: panic("Cmp has unsupported relation");
419 /* emit the true proj */
420 be_emit_irprintf("\tb%s ", suffix);
421 arm_emit_cfop_target(proj_true);
422 be_emit_finish_line_gas(proj_true);
424 if (get_cfop_target_block(proj_false) == next_block) {
425 be_emit_cstring("\t/* fallthrough to ");
426 arm_emit_cfop_target(proj_false);
427 be_emit_cstring(" */");
428 be_emit_finish_line_gas(proj_false);
430 be_emit_cstring("\tb ");
431 arm_emit_cfop_target(proj_false);
432 be_emit_finish_line_gas(proj_false);
436 /** Sort register in ascending order. */
437 static int reg_cmp(const void *a, const void *b)
439 const arch_register_t * const *ra = (const arch_register_t**)a;
440 const arch_register_t * const *rb = (const arch_register_t**)b;
442 return *ra < *rb ? -1 : (*ra != *rb);
446 * Create the CopyB instruction sequence.
448 static void emit_arm_CopyB(const ir_node *irn)
450 const arm_CopyB_attr_t *attr = get_arm_CopyB_attr_const(irn);
451 unsigned size = attr->size;
453 const char *tgt = arch_register_get_name(get_in_reg(irn, 0));
454 const char *src = arch_register_get_name(get_in_reg(irn, 1));
455 const char *t0, *t1, *t2, *t3;
457 const arch_register_t *tmpregs[4];
459 /* collect the temporary registers and sort them, we need ascending order */
460 tmpregs[0] = get_in_reg(irn, 2);
461 tmpregs[1] = get_in_reg(irn, 3);
462 tmpregs[2] = get_in_reg(irn, 4);
463 tmpregs[3] = &arm_registers[REG_R12];
465 /* Note: R12 is always the last register because the RA did not assign higher ones */
466 qsort((void *)tmpregs, 3, sizeof(tmpregs[0]), reg_cmp);
468 /* need ascending order */
469 t0 = arch_register_get_name(tmpregs[0]);
470 t1 = arch_register_get_name(tmpregs[1]);
471 t2 = arch_register_get_name(tmpregs[2]);
472 t3 = arch_register_get_name(tmpregs[3]);
474 be_emit_cstring("/* MemCopy (");
476 be_emit_cstring(")->(");
477 arm_emit_source_register(irn, 0);
478 be_emit_irprintf(" [%u bytes], Uses ", size);
480 be_emit_cstring(", ");
482 be_emit_cstring(", ");
484 be_emit_cstring(", and ");
486 be_emit_cstring("*/");
487 be_emit_finish_line_gas(NULL);
489 assert(size > 0 && "CopyB needs size > 0" );
492 fprintf(stderr, "strange hack enabled: copy more bytes than needed!");
501 be_emit_cstring("\tldr ");
503 be_emit_cstring(", [");
505 be_emit_cstring(", #0]");
506 be_emit_finish_line_gas(NULL);
508 be_emit_cstring("\tstr ");
510 be_emit_cstring(", [");
512 be_emit_cstring(", #0]");
513 be_emit_finish_line_gas(irn);
516 be_emit_cstring("\tldmia ");
518 be_emit_cstring("!, {");
520 be_emit_cstring(", ");
523 be_emit_finish_line_gas(NULL);
525 be_emit_cstring("\tstmia ");
527 be_emit_cstring("!, {");
529 be_emit_cstring(", ");
532 be_emit_finish_line_gas(irn);
535 be_emit_cstring("\tldmia ");
537 be_emit_cstring("!, {");
539 be_emit_cstring(", ");
541 be_emit_cstring(", ");
544 be_emit_finish_line_gas(NULL);
546 be_emit_cstring("\tstmia ");
548 be_emit_cstring("!, {");
550 be_emit_cstring(", ");
552 be_emit_cstring(", ");
555 be_emit_finish_line_gas(irn);
560 be_emit_cstring("\tldmia ");
562 be_emit_cstring("!, {");
564 be_emit_cstring(", ");
566 be_emit_cstring(", ");
568 be_emit_cstring(", ");
571 be_emit_finish_line_gas(NULL);
573 be_emit_cstring("\tstmia ");
575 be_emit_cstring("!, {");
577 be_emit_cstring(", ");
579 be_emit_cstring(", ");
581 be_emit_cstring(", ");
584 be_emit_finish_line_gas(irn);
589 static void emit_arm_SwitchJmp(const ir_node *irn)
591 const ir_edge_t *edge;
597 ir_node *default_proj = NULL;
599 block_nr = get_irn_node_nr(irn);
600 n_projs = get_arm_SwitchJmp_n_projs(irn);
602 projs = XMALLOCNZ(ir_node*, n_projs);
604 foreach_out_edge(irn, edge) {
605 proj = get_edge_src_irn(edge);
606 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
608 if (get_Proj_proj(proj) == get_arm_SwitchJmp_default_proj_num(irn))
611 projs[get_Proj_proj(proj)] = proj;
613 assert(default_proj != NULL && "SwitchJmp should have a Default Proj");
620 be_emit_cstring("\tcmp ");
621 arm_emit_source_register(irn, 0);
622 be_emit_irprintf(", #%u", n_projs - 1);
623 be_emit_finish_line_gas(irn);
625 be_emit_cstring("\tbhi ");
626 arm_emit_cfop_target(default_proj);
627 be_emit_finish_line_gas(default_proj);
630 LDR %r12, .TABLE_X_START
631 ADD %r12, %r12, [%1S, LSL #2]
635 be_emit_irprintf("\tldr %%r12, TABLE_%d_START", block_nr);
636 be_emit_finish_line_gas(NULL);
638 be_emit_irprintf("\tadd %%r12, %%r12, ");
639 arm_emit_source_register(irn, 0);
640 be_emit_cstring(", LSL #2");
641 be_emit_finish_line_gas(NULL);
643 be_emit_cstring("\tldr %r15, [%r12, #0]");
644 be_emit_finish_line_gas(NULL);
646 be_emit_irprintf("TABLE_%d_START:\n\t.word\tTABLE_%d", block_nr, block_nr);
647 be_emit_finish_line_gas(NULL);
648 be_emit_irprintf("\t.align 2");
649 be_emit_finish_line_gas(NULL);
650 be_emit_irprintf("TABLE_%d:", block_nr);
651 be_emit_finish_line_gas(NULL);
653 for (i = 0; i < n_projs; ++i) {
656 proj = projs[get_arm_SwitchJmp_default_proj_num(irn)];
658 be_emit_cstring("\t.word\t");
659 arm_emit_cfop_target(proj);
660 be_emit_finish_line_gas(proj);
662 be_emit_irprintf("\t.align 2\n");
663 be_emit_finish_line_gas(NULL);
667 /** Emit an IncSP node */
668 static void emit_be_IncSP(const ir_node *irn)
670 int offs = -be_get_IncSP_offset(irn);
674 be_emit_cstring("\tsub ");
677 be_emit_cstring("\tadd ");
679 arm_emit_dest_register(irn, 0);
680 be_emit_cstring(", ");
681 arm_emit_source_register(irn, 0);
682 be_emit_irprintf(", #0x%X", offs);
683 be_emit_finish_line_gas(irn);
685 /* omitted IncSP(0) */
690 static void emit_be_Copy(const ir_node *irn)
692 ir_mode *mode = get_irn_mode(irn);
694 if (get_in_reg(irn, 0) == arch_irn_get_register(irn, 0)) {
699 if (mode_is_float(mode)) {
701 be_emit_cstring("\tmvf");
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");
710 } else if (mode_is_data(mode)) {
711 be_emit_cstring("\tmov ");
712 arm_emit_dest_register(irn, 0);
713 be_emit_cstring(", ");
714 arm_emit_source_register(irn, 0);
715 be_emit_finish_line_gas(irn);
717 panic("emit_be_Copy: move not supported for this mode");
721 static void emit_be_Perm(const ir_node *irn)
723 be_emit_cstring("\teor ");
724 arm_emit_source_register(irn, 0);
725 be_emit_cstring(", ");
726 arm_emit_source_register(irn, 0);
727 be_emit_cstring(", ");
728 arm_emit_source_register(irn, 1);
729 be_emit_finish_line_gas(NULL);
731 be_emit_cstring("\teor ");
732 arm_emit_source_register(irn, 1);
733 be_emit_cstring(", ");
734 arm_emit_source_register(irn, 0);
735 be_emit_cstring(", ");
736 arm_emit_source_register(irn, 1);
737 be_emit_finish_line_gas(NULL);
739 be_emit_cstring("\teor ");
740 arm_emit_source_register(irn, 0);
741 be_emit_cstring(", ");
742 arm_emit_source_register(irn, 0);
743 be_emit_cstring(", ");
744 arm_emit_source_register(irn, 1);
745 be_emit_finish_line_gas(irn);
748 static void emit_be_MemPerm(const ir_node *node)
754 /* TODO: this implementation is slower than necessary.
755 The longterm goal is however to avoid the memperm node completely */
757 memperm_arity = be_get_MemPerm_entity_arity(node);
758 if (memperm_arity > 12)
759 panic("memperm with more than 12 inputs not supported yet");
761 for (i = 0; i < memperm_arity; ++i) {
763 ir_entity *entity = be_get_MemPerm_in_entity(node, i);
766 be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
767 be_emit_finish_line_gas(node);
769 /* load from entity */
770 offset = get_entity_offset(entity) + sp_change;
771 be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
772 be_emit_finish_line_gas(node);
775 for (i = memperm_arity-1; i >= 0; --i) {
777 ir_entity *entity = be_get_MemPerm_out_entity(node, i);
779 /* store to new entity */
780 offset = get_entity_offset(entity) + sp_change;
781 be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
782 be_emit_finish_line_gas(node);
783 /* restore register */
784 be_emit_irprintf("\tldr r%d, [sp], #4", i);
786 be_emit_finish_line_gas(node);
788 assert(sp_change == 0);
791 static void emit_be_Start(const ir_node *node)
793 ir_graph *irg = get_irn_irg(node);
794 ir_type *frame_type = get_irg_frame_type(irg);
795 unsigned size = get_type_size_bytes(frame_type);
797 /* allocate stackframe */
799 be_emit_cstring("\tsub ");
800 arm_emit_register(&arm_registers[REG_SP]);
801 be_emit_cstring(", ");
802 arm_emit_register(&arm_registers[REG_SP]);
803 be_emit_irprintf(", #0x%X", size);
804 be_emit_finish_line_gas(node);
808 static void emit_be_Return(const ir_node *node)
810 ir_graph *irg = get_irn_irg(node);
811 ir_type *frame_type = get_irg_frame_type(irg);
812 unsigned size = get_type_size_bytes(frame_type);
814 /* deallocate stackframe */
816 be_emit_cstring("\tadd ");
817 arm_emit_register(&arm_registers[REG_SP]);
818 be_emit_cstring(", ");
819 arm_emit_register(&arm_registers[REG_SP]);
820 be_emit_irprintf(", #0x%X", size);
821 be_emit_finish_line_gas(node);
824 be_emit_cstring("\tmov pc, lr");
825 be_emit_finish_line_gas(node);
829 static void emit_arm_Jmp(const ir_node *node)
831 ir_node *block, *next_block;
833 /* for now, the code works for scheduled and non-schedules blocks */
834 block = get_nodes_block(node);
836 /* we have a block schedule */
837 next_block = sched_next_block(block);
838 if (get_cfop_target_block(node) != next_block) {
839 be_emit_cstring("\tb ");
840 arm_emit_cfop_target(node);
842 be_emit_cstring("\t/* fallthrough to ");
843 arm_emit_cfop_target(node);
844 be_emit_cstring(" */");
846 be_emit_finish_line_gas(node);
849 static void emit_nothing(const ir_node *irn)
855 * The type of a emitter function.
857 typedef void (emit_func)(const ir_node *irn);
860 * Set a node emitter. Make it a bit more type safe.
862 static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
864 op->ops.generic = (op_func)arm_emit_node;
868 * Enters the emitter functions for handled nodes into the generic
869 * pointer of an opcode.
871 static void arm_register_emitters(void)
873 /* first clear the generic function pointer for all ops */
874 clear_irp_opcodes_generic_func();
876 /* register all emitter functions defined in spec */
877 arm_register_spec_emitters();
880 set_emitter(op_arm_B, emit_arm_B);
881 set_emitter(op_arm_CopyB, emit_arm_CopyB);
882 set_emitter(op_arm_fConst, emit_arm_fConst);
883 set_emitter(op_arm_FrameAddr, emit_arm_FrameAddr);
884 set_emitter(op_arm_Jmp, emit_arm_Jmp);
885 set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp);
886 set_emitter(op_arm_SymConst, emit_arm_SymConst);
887 set_emitter(op_be_Copy, emit_be_Copy);
888 set_emitter(op_be_CopyKeep, emit_be_Copy);
889 set_emitter(op_be_IncSP, emit_be_IncSP);
890 set_emitter(op_be_MemPerm, emit_be_MemPerm);
891 set_emitter(op_be_Perm, emit_be_Perm);
892 set_emitter(op_be_Return, emit_be_Return);
893 set_emitter(op_be_Start, emit_be_Start);
895 /* no need to emit anything for the following nodes */
896 set_emitter(op_Phi, emit_nothing);
897 set_emitter(op_be_Keep, emit_nothing);
901 * Emits code for a node.
903 static void arm_emit_node(const ir_node *irn)
905 ir_op *op = get_irn_op(irn);
907 if (op->ops.generic) {
908 emit_func *emit = (emit_func *)op->ops.generic;
909 be_dbg_set_dbg_info(get_irn_dbg_info(irn));
912 panic("Error: No emit handler for node %+F (graph %+F)\n",
913 irn, current_ir_graph);
918 * emit the block label if needed.
920 static void arm_emit_block_header(ir_node *block, ir_node *prev)
925 ir_graph *irg = get_irn_irg(block);
926 ir_exec_freq *exec_freq = be_get_irg_exec_freq(irg);
929 n_cfgpreds = get_Block_n_cfgpreds(block);
930 if (n_cfgpreds == 1) {
931 ir_node *pred = get_Block_cfgpred(block, 0);
932 ir_node *pred_block = get_nodes_block(pred);
934 /* we don't need labels for fallthrough blocks, however switch-jmps
935 * are no fallthroughs */
936 if (pred_block == prev &&
937 !(is_Proj(pred) && is_arm_SwitchJmp(get_Proj_pred(pred)))) {
947 be_gas_emit_block_name(block);
950 be_emit_pad_comment();
951 be_emit_cstring(" /* preds:");
953 /* emit list of pred blocks in comment */
954 arity = get_irn_arity(block);
955 for (i = 0; i < arity; ++i) {
956 ir_node *predblock = get_Block_cfgpred_block(block, i);
957 be_emit_irprintf(" %d", get_irn_node_nr(predblock));
960 be_emit_cstring("\t/* ");
961 be_gas_emit_block_name(block);
962 be_emit_cstring(": ");
964 if (exec_freq != NULL) {
965 be_emit_irprintf(" freq: %f",
966 get_block_execfreq(exec_freq, block));
968 be_emit_cstring(" */\n");
969 be_emit_write_line();
973 * Walks over the nodes in a block connected by scheduling edges
974 * and emits code for each node.
976 static void arm_gen_block(ir_node *block, ir_node *prev_block)
980 arm_emit_block_header(block, prev_block);
981 be_dbg_set_dbg_info(get_irn_dbg_info(block));
982 sched_foreach(block, irn) {
989 * Sets labels for control flow nodes (jump target)
991 static void arm_gen_labels(ir_node *block, void *env)
994 int n = get_Block_n_cfgpreds(block);
997 for (n--; n >= 0; n--) {
998 pred = get_Block_cfgpred(block, n);
999 set_irn_link(pred, block);
1004 * Compare two entries of the symbol or tarval set.
1006 static int cmp_sym_or_tv(const void *elt, const void *key, size_t size)
1008 const sym_or_tv_t *p1 = (const sym_or_tv_t*)elt;
1009 const sym_or_tv_t *p2 = (const sym_or_tv_t*)key;
1012 /* as an identifier NEVER can point to a tarval, it's enough
1013 to compare it this way */
1014 return p1->u.generic != p2->u.generic;
1017 void arm_gen_routine(ir_graph *irg)
1019 ir_node *last_block = NULL;
1020 ir_entity *entity = get_irg_entity(irg);
1021 const arch_env_t *arch_env = be_get_irg_arch_env(irg);
1022 ir_node **blk_sched;
1025 isa = (arm_isa_t*) arch_env;
1026 sym_or_tv = new_set(cmp_sym_or_tv, 8);
1028 be_gas_elf_type_char = '%';
1030 arm_register_emitters();
1032 be_dbg_method_begin(entity);
1034 /* create the block schedule */
1035 blk_sched = be_create_block_schedule(irg);
1037 be_gas_emit_function_prolog(entity, 4);
1039 irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
1041 n = ARR_LEN(blk_sched);
1042 for (i = 0; i < n;) {
1043 ir_node *block, *next_bl;
1045 block = blk_sched[i];
1047 next_bl = i < n ? blk_sched[i] : NULL;
1049 /* set here the link. the emitter expects to find the next block here */
1050 set_irn_link(block, next_bl);
1051 arm_gen_block(block, last_block);
1055 /* emit SymConst values */
1056 if (set_count(sym_or_tv) > 0) {
1059 be_emit_cstring("\t.align 2\n");
1061 foreach_set(sym_or_tv, sym_or_tv_t*, entry) {
1062 emit_constant_name(entry);
1063 be_emit_cstring(":\n");
1064 be_emit_write_line();
1066 if (entry->is_entity) {
1067 be_emit_cstring("\t.word\t");
1068 be_gas_emit_entity(entry->u.entity);
1070 be_emit_write_line();
1072 ir_tarval *tv = entry->u.tv;
1074 int size = get_mode_size_bytes(get_tarval_mode(tv));
1076 /* beware: ARM fpa uses big endian format */
1077 for (vi = ((size + 3) & ~3) - 4; vi >= 0; vi -= 4) {
1080 v = get_tarval_sub_bits(tv, vi+3);
1081 v = (v << 8) | get_tarval_sub_bits(tv, vi+2);
1082 v = (v << 8) | get_tarval_sub_bits(tv, vi+1);
1083 v = (v << 8) | get_tarval_sub_bits(tv, vi+0);
1084 be_emit_irprintf("\t.word\t%u\n", v);
1085 be_emit_write_line();
1090 be_emit_write_line();
1094 be_gas_emit_function_epilog(entity);
1095 be_dbg_method_end();
1098 void arm_init_emitter(void)
1100 FIRM_DBG_REGISTER(dbg, "firm.be.arm.emit");