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
41 #include "raw_bitset.h"
44 #include "../besched.h"
45 #include "../beblocksched.h"
47 #include "../begnuas.h"
48 #include "../be_dbgout.h"
50 #include "arm_emitter.h"
51 #include "arm_optimize.h"
52 #include "gen_arm_emitter.h"
53 #include "arm_nodes_attr.h"
54 #include "arm_new_nodes.h"
55 #include "arm_map_regs.h"
56 #include "gen_arm_regalloc_if.h"
58 #include "../benode.h"
60 #define BLOCK_PREFIX ".L"
61 #define SNPRINTF_BUF_LEN 128
63 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
65 static const arm_code_gen_t *cg;
66 static set *sym_or_tv;
69 * Returns the register at in position pos.
71 static const arch_register_t *get_in_reg(const ir_node *irn, int pos)
74 const arch_register_t *reg = NULL;
76 assert(get_irn_arity(irn) > pos && "Invalid IN position");
78 /* The out register of the operator at position pos is the
79 in register we need. */
80 op = get_irn_n(irn, pos);
82 reg = arch_get_irn_register(op);
84 assert(reg && "no in register found");
86 /* in case of a joker register: just return a valid register */
87 if (arch_register_type_is(reg, joker)) {
88 const arch_register_req_t *req = arch_get_register_req(irn, pos);
90 if (arch_register_req_is(req, limited)) {
91 /* in case of limited requirements: get the first allowed register */
92 unsigned idx = rbitset_next(req->limited, 0, 1);
93 reg = arch_register_for_index(req->cls, idx);
95 /* otherwise get first register in class */
96 reg = arch_register_for_index(req->cls, 0);
104 * Returns the register at out position pos.
106 static const arch_register_t *get_out_reg(const ir_node *node, int pos)
109 const arch_register_t *reg = NULL;
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 */
116 if (get_irn_mode(node) != mode_T) {
117 reg = arch_get_irn_register(node);
118 } else if (is_arm_irn(node)) {
119 reg = arch_irn_get_register(node, pos);
121 const ir_edge_t *edge;
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(proj);
133 assert(reg && "no out register found");
138 * Emit the name of the source register at given input position.
140 void arm_emit_source_register(const ir_node *node, int pos) {
141 const arch_register_t *reg = get_in_reg(node, pos);
142 be_emit_string(arch_register_get_name(reg));
146 * Emit the name of the destination register at given output position.
148 void arm_emit_dest_register(const ir_node *node, int pos) {
149 const arch_register_t *reg = get_out_reg(node, pos);
150 be_emit_string(arch_register_get_name(reg));
154 * Emit a node's offset.
156 void arm_emit_offset(const ir_node *node)
158 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
159 assert(attr->base.is_load_store);
161 be_emit_irprintf("0x%X", attr->offset);
165 * Emit the arm fpa instruction suffix depending on the mode.
167 static void arm_emit_fpa_postfix(const ir_mode *mode) {
168 int bits = get_mode_size_bits(mode);
179 * Emit the instruction suffix depending on the mode.
181 void arm_emit_mode(const ir_node *node) {
184 if (is_arm_irn(node)) {
185 const arm_attr_t *attr = get_arm_attr_const(node);
186 mode = attr->op_mode ? attr->op_mode : get_irn_mode(node);
188 mode = get_irn_mode(node);
190 arm_emit_fpa_postfix(mode);
194 * Emit a const or SymConst value.
196 void arm_emit_immediate(const ir_node *node)
198 const arm_attr_t *attr = get_arm_attr_const(node);
200 if (ARM_GET_FPA_IMM(attr)) {
202 //be_emit_irprintf("#%s", arm_get_fpa_imm_name(get_arm_imm_value(node)));
204 assert(!"not a Constant");
208 void arm_emit_load_mode(const ir_node *node)
210 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
211 ir_mode *mode = attr->load_store_mode;
212 int bits = get_mode_size_bits(mode);
213 bool is_signed = mode_is_signed(mode);
215 be_emit_string(is_signed ? "sh" : "h");
216 } else if (bits == 8) {
217 be_emit_string(is_signed ? "sb" : "b");
223 void arm_emit_store_mode(const ir_node *node)
225 const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
226 ir_mode *mode = attr->load_store_mode;
227 int bits = get_mode_size_bits(mode);
229 be_emit_cstring("h");
230 } else if (bits == 8) {
231 be_emit_cstring("b");
238 static void emit_shf_mod_name(arm_shift_modifier mod)
241 case ARM_SHF_ASR_REG:
242 case ARM_SHF_ASR_IMM:
243 be_emit_cstring("asr");
245 case ARM_SHF_LSL_REG:
246 case ARM_SHF_LSL_IMM:
247 be_emit_cstring("lsl");
249 case ARM_SHF_LSR_REG:
250 case ARM_SHF_LSR_IMM:
251 be_emit_cstring("lsr");
253 case ARM_SHF_ROR_REG:
254 case ARM_SHF_ROR_IMM:
255 be_emit_cstring("ror");
260 panic("can't emit this shf_mod_name %d", (int) mod);
263 void arm_emit_shifter_operand(const ir_node *node)
265 const arm_shifter_operand_t *attr = get_irn_generic_attr_const(node);
267 switch (attr->shift_modifier) {
269 arm_emit_source_register(node, get_irn_arity(node) - 1);
272 unsigned val = attr->immediate_value;
273 val = (val >> attr->shift_immediate)
274 | (val << (32-attr->shift_immediate));
276 be_emit_irprintf("#0x%X", val);
279 case ARM_SHF_ASR_IMM:
280 case ARM_SHF_LSL_IMM:
281 case ARM_SHF_LSR_IMM:
282 case ARM_SHF_ROR_IMM:
283 arm_emit_source_register(node, get_irn_arity(node) - 1);
284 be_emit_cstring(", ");
285 emit_shf_mod_name(attr->shift_modifier);
286 be_emit_irprintf(" #0x%X", attr->shift_immediate);
289 case ARM_SHF_ASR_REG:
290 case ARM_SHF_LSL_REG:
291 case ARM_SHF_LSR_REG:
292 case ARM_SHF_ROR_REG:
293 arm_emit_source_register(node, get_irn_arity(node) - 2);
294 be_emit_cstring(", ");
295 emit_shf_mod_name(attr->shift_modifier);
296 be_emit_cstring(" ");
297 arm_emit_source_register(node, get_irn_arity(node) - 1);
301 arm_emit_source_register(node, get_irn_arity(node) - 1);
302 panic("RRX shifter emitter TODO");
305 case ARM_SHF_INVALID:
308 panic("Invalid shift_modifier while emitting %+F", node);
311 /** An entry in the sym_or_tv set. */
312 typedef struct sym_or_tv_t {
314 ident *id; /**< An ident. */
315 tarval *tv; /**< A tarval. */
316 const void *generic; /**< For generic compare. */
318 unsigned label; /**< the associated label. */
319 char is_ident; /**< Non-zero if an ident is stored. */
323 * Returns a unique label. This number will not be used a second time.
325 static unsigned get_unique_label(void) {
326 static unsigned id = 0;
333 static void emit_arm_SymConst(const ir_node *irn)
335 const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
336 sym_or_tv_t key, *entry;
339 set_entity_backend_marked(attr->entity, 1);
341 key.u.id = get_entity_ld_ident(attr->entity);
344 entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
345 if (entry->label == 0) {
346 /* allocate a label */
347 entry->label = get_unique_label();
349 label = entry->label;
351 /* load the symbol indirect */
352 be_emit_cstring("\tldr ");
353 arm_emit_dest_register(irn, 0);
354 be_emit_irprintf(", .L%u", label);
355 be_emit_finish_line_gas(irn);
358 static void emit_arm_FrameAddr(const ir_node *irn)
360 const arm_SymConst_attr_t *attr = get_irn_generic_attr_const(irn);
362 be_emit_cstring("\tadd ");
363 arm_emit_dest_register(irn, 0);
364 be_emit_cstring(", ");
365 arm_emit_source_register(irn, 0);
366 be_emit_cstring(", ");
367 be_emit_irprintf("#0x%X", attr->fp_offset);
368 be_emit_finish_line_gas(irn);
372 * Emit a floating point fpa constant.
374 static void emit_arm_fpaConst(const ir_node *irn) {
375 sym_or_tv_t key, *entry;
379 key.u.tv = get_fpaConst_value(irn);
382 entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
383 if (entry->label == 0) {
384 /* allocate a label */
385 entry->label = get_unique_label();
387 label = entry->label;
389 /* load the tarval indirect */
390 mode = get_irn_mode(irn);
391 be_emit_cstring("\tldf");
392 arm_emit_fpa_postfix(mode);
395 arm_emit_dest_register(irn, 0);
396 be_emit_irprintf(", .L%u", label);
397 be_emit_finish_line_gas(irn);
401 * Returns the next block in a block schedule.
403 static ir_node *sched_next_block(const ir_node *block) {
404 return get_irn_link(block);
408 * Returns the target block for a control flow node.
410 static ir_node *get_cfop_target_block(const ir_node *irn) {
411 return get_irn_link(irn);
415 * Emits a block label for the given block.
417 static void arm_emit_block_name(const ir_node *block) {
418 if (has_Block_entity(block)) {
419 ir_entity *entity = get_Block_entity(block);
420 be_gas_emit_entity(entity);
422 be_emit_cstring(BLOCK_PREFIX);
423 be_emit_irprintf("%d", get_irn_node_nr(block));
428 * Emit the target label for a control flow node.
430 static void arm_emit_cfop_target(const ir_node *irn) {
431 ir_node *block = get_cfop_target_block(irn);
433 arm_emit_block_name(block);
437 * Emit a Compare with conditional branch.
439 static void emit_arm_B(const ir_node *irn)
441 const ir_edge_t *edge;
442 const ir_node *proj_true = NULL;
443 const ir_node *proj_false = NULL;
444 const ir_node *block;
445 const ir_node *next_block;
446 ir_node *op1 = get_irn_n(irn, 0);
448 int proj_num = get_arm_CondJmp_proj_num(irn);
449 const arm_cmp_attr_t *cmp_attr = get_irn_generic_attr_const(op1);
450 bool is_signed = !cmp_attr->is_unsigned;
452 assert(is_arm_Cmp(op1) || is_arm_Tst(op1));
454 foreach_out_edge(irn, edge) {
455 ir_node *proj = get_edge_src_irn(edge);
456 long nr = get_Proj_proj(proj);
457 if (nr == pn_Cond_true) {
464 if (cmp_attr->ins_permuted) {
465 proj_num = get_mirrored_pnc(proj_num);
468 /* for now, the code works for scheduled and non-schedules blocks */
469 block = get_nodes_block(irn);
471 /* we have a block schedule */
472 next_block = sched_next_block(block);
474 assert(proj_num != pn_Cmp_False);
475 assert(proj_num != pn_Cmp_True);
477 if (get_cfop_target_block(proj_true) == next_block) {
478 /* exchange both proj's so the second one can be omitted */
479 const ir_node *t = proj_true;
481 proj_true = proj_false;
483 proj_num = get_negated_pnc(proj_num, mode_Iu);
487 case pn_Cmp_Eq: suffix = "eq"; break;
488 case pn_Cmp_Lt: suffix = is_signed ? "lt" : "lo"; break;
489 case pn_Cmp_Le: suffix = is_signed ? "le" : "ls"; break;
490 case pn_Cmp_Gt: suffix = is_signed ? "gt" : "hi"; break;
491 case pn_Cmp_Ge: suffix = is_signed ? "ge" : "hs"; break;
492 case pn_Cmp_Lg: suffix = "ne"; break;
493 case pn_Cmp_Leg: suffix = "al"; break;
494 default: panic("Cmp has unsupported pnc");
497 /* emit the true proj */
498 be_emit_irprintf("\tb%s ", suffix);
499 arm_emit_cfop_target(proj_true);
500 be_emit_finish_line_gas(proj_true);
502 if (get_cfop_target_block(proj_false) == next_block) {
503 be_emit_cstring("\t/* fallthrough to ");
504 arm_emit_cfop_target(proj_false);
505 be_emit_cstring(" */");
506 be_emit_finish_line_gas(proj_false);
508 be_emit_cstring("\tb ");
509 arm_emit_cfop_target(proj_false);
510 be_emit_finish_line_gas(proj_false);
514 /** Sort register in ascending order. */
515 static int reg_cmp(const void *a, const void *b) {
516 const arch_register_t * const *ra = a;
517 const arch_register_t * const *rb = b;
519 return *ra < *rb ? -1 : (*ra != *rb);
523 * Create the CopyB instruction sequence.
525 static void emit_arm_CopyB(const ir_node *irn)
527 const arm_CopyB_attr_t *attr = get_irn_generic_attr_const(irn);
528 unsigned size = attr->size;
530 const char *tgt = arch_register_get_name(get_in_reg(irn, 0));
531 const char *src = arch_register_get_name(get_in_reg(irn, 1));
532 const char *t0, *t1, *t2, *t3;
534 const arch_register_t *tmpregs[4];
536 /* collect the temporary registers and sort them, we need ascending order */
537 tmpregs[0] = get_in_reg(irn, 2);
538 tmpregs[1] = get_in_reg(irn, 3);
539 tmpregs[2] = get_in_reg(irn, 4);
540 tmpregs[3] = &arm_gp_regs[REG_R12];
542 /* Note: R12 is always the last register because the RA did not assign higher ones */
543 qsort((void *)tmpregs, 3, sizeof(tmpregs[0]), reg_cmp);
545 /* need ascending order */
546 t0 = arch_register_get_name(tmpregs[0]);
547 t1 = arch_register_get_name(tmpregs[1]);
548 t2 = arch_register_get_name(tmpregs[2]);
549 t3 = arch_register_get_name(tmpregs[3]);
551 be_emit_cstring("/* MemCopy (");
553 be_emit_cstring(")->(");
554 arm_emit_source_register(irn, 0);
555 be_emit_irprintf(" [%u bytes], Uses ", size);
557 be_emit_cstring(", ");
559 be_emit_cstring(", ");
561 be_emit_cstring(", and ");
563 be_emit_cstring("*/");
564 be_emit_finish_line_gas(NULL);
566 assert(size > 0 && "CopyB needs size > 0" );
569 assert(!"strange hack enabled: copy more bytes than needed!");
578 be_emit_cstring("\tldr ");
580 be_emit_cstring(", [");
582 be_emit_cstring(", #0]");
583 be_emit_finish_line_gas(NULL);
585 be_emit_cstring("\tstr ");
587 be_emit_cstring(", [");
589 be_emit_cstring(", #0]");
590 be_emit_finish_line_gas(irn);
593 be_emit_cstring("\tldmia ");
595 be_emit_cstring("!, {");
597 be_emit_cstring(", ");
600 be_emit_finish_line_gas(NULL);
602 be_emit_cstring("\tstmia ");
604 be_emit_cstring("!, {");
606 be_emit_cstring(", ");
609 be_emit_finish_line_gas(irn);
612 be_emit_cstring("\tldmia ");
614 be_emit_cstring("!, {");
616 be_emit_cstring(", ");
618 be_emit_cstring(", ");
621 be_emit_finish_line_gas(NULL);
623 be_emit_cstring("\tstmia ");
625 be_emit_cstring("!, {");
627 be_emit_cstring(", ");
629 be_emit_cstring(", ");
632 be_emit_finish_line_gas(irn);
637 be_emit_cstring("\tldmia ");
639 be_emit_cstring("!, {");
641 be_emit_cstring(", ");
643 be_emit_cstring(", ");
645 be_emit_cstring(", ");
648 be_emit_finish_line_gas(NULL);
650 be_emit_cstring("\tstmia ");
652 be_emit_cstring("!, {");
654 be_emit_cstring(", ");
656 be_emit_cstring(", ");
658 be_emit_cstring(", ");
661 be_emit_finish_line_gas(irn);
666 static void emit_arm_SwitchJmp(const ir_node *irn) {
667 const ir_edge_t *edge;
673 ir_node *default_proj = NULL;
675 block_nr = get_irn_node_nr(irn);
676 n_projs = get_arm_SwitchJmp_n_projs(irn);
678 projs = XMALLOCNZ(ir_node*, n_projs);
680 foreach_out_edge(irn, edge) {
681 proj = get_edge_src_irn(edge);
682 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
684 if (get_Proj_proj(proj) == get_arm_SwitchJmp_default_proj_num(irn))
687 projs[get_Proj_proj(proj)] = proj;
689 assert(default_proj != NULL && "SwitchJmp should have a Default Proj");
696 be_emit_cstring("\tcmp ");
697 arm_emit_source_register(irn, 0);
698 be_emit_irprintf(", #%u", n_projs - 1);
699 be_emit_finish_line_gas(irn);
701 be_emit_cstring("\tbhi ");
702 arm_emit_cfop_target(default_proj);
703 be_emit_finish_line_gas(default_proj);
706 LDR %r12, .TABLE_X_START
707 ADD %r12, %r12, [%1S, LSL #2]
711 be_emit_irprintf("\tldr %%r12, TABLE_%d_START", block_nr);
712 be_emit_finish_line_gas(NULL);
714 be_emit_irprintf("\tadd %%r12, %%r12, ");
715 arm_emit_source_register(irn, 0);
716 be_emit_cstring(", LSL #2");
717 be_emit_finish_line_gas(NULL);
719 be_emit_cstring("\tldr %r15, [%r12, #0]");
720 be_emit_finish_line_gas(NULL);
722 be_emit_irprintf("TABLE_%d_START:\n\t.word\tTABLE_%d", block_nr, block_nr);
723 be_emit_finish_line_gas(NULL);
724 be_emit_irprintf("\t.align 2");
725 be_emit_finish_line_gas(NULL);
726 be_emit_irprintf("TABLE_%d:", block_nr);
727 be_emit_finish_line_gas(NULL);
729 for (i = 0; i < n_projs; ++i) {
732 proj = projs[get_arm_SwitchJmp_default_proj_num(irn)];
734 be_emit_cstring("\t.word\t");
735 arm_emit_cfop_target(proj);
736 be_emit_finish_line_gas(proj);
738 be_emit_irprintf("\t.align 2\n");
739 be_emit_finish_line_gas(NULL);
743 /************************************************************************/
745 /************************************************************************/
747 static void arm_emit_entity(ir_entity *entity)
749 set_entity_backend_marked(entity, 1);
750 be_emit_ident(get_entity_ld_ident(entity));
753 static void emit_be_Call(const ir_node *irn)
755 ir_entity *entity = be_Call_get_entity(irn);
757 if (entity != NULL) {
758 be_emit_cstring("\tbl ");
759 arm_emit_entity(entity);
760 be_emit_finish_line_gas(irn);
762 be_emit_cstring("\tmov lr, pc");
763 be_emit_finish_line_gas(irn);
764 be_emit_cstring("\tmov pc, ");
765 arm_emit_source_register(irn, be_pos_Call_ptr);
766 be_emit_finish_line_gas(irn);
770 /** Emit an IncSP node */
771 static void emit_be_IncSP(const ir_node *irn) {
772 int offs = -be_get_IncSP_offset(irn);
776 be_emit_cstring("\tsub ");
779 be_emit_cstring("\tadd ");
781 arm_emit_dest_register(irn, 0);
782 be_emit_cstring(", ");
783 arm_emit_source_register(irn, 0);
784 be_emit_irprintf(", #0x%X", offs);
786 /* omitted IncSP(0) */
789 be_emit_finish_line_gas(irn);
792 static void emit_be_Copy(const ir_node *irn) {
793 ir_mode *mode = get_irn_mode(irn);
795 if (get_in_reg(irn, 0) == get_out_reg(irn, 0)) {
800 if (mode_is_float(mode)) {
801 if (USE_FPA(cg->isa)) {
802 be_emit_cstring("\tmvf");
805 arm_emit_dest_register(irn, 0);
806 be_emit_cstring(", ");
807 arm_emit_source_register(irn, 0);
808 be_emit_finish_line_gas(irn);
810 assert(0 && "move not supported for this mode");
811 panic("emit_be_Copy: move not supported for this mode");
813 } else if (mode_is_data(mode)) {
814 be_emit_cstring("\tmov ");
815 arm_emit_dest_register(irn, 0);
816 be_emit_cstring(", ");
817 arm_emit_source_register(irn, 0);
818 be_emit_finish_line_gas(irn);
820 assert(0 && "move not supported for this mode");
821 panic("emit_be_Copy: move not supported for this mode");
825 static void emit_be_Perm(const ir_node *irn)
827 be_emit_cstring("\teor ");
828 arm_emit_source_register(irn, 0);
829 be_emit_cstring(", ");
830 arm_emit_source_register(irn, 0);
831 be_emit_cstring(", ");
832 arm_emit_source_register(irn, 1);
833 be_emit_finish_line_gas(NULL);
835 be_emit_cstring("\teor ");
836 arm_emit_source_register(irn, 1);
837 be_emit_cstring(", ");
838 arm_emit_source_register(irn, 0);
839 be_emit_cstring(", ");
840 arm_emit_source_register(irn, 1);
841 be_emit_finish_line_gas(NULL);
843 be_emit_cstring("\teor ");
844 arm_emit_source_register(irn, 0);
845 be_emit_cstring(", ");
846 arm_emit_source_register(irn, 0);
847 be_emit_cstring(", ");
848 arm_emit_source_register(irn, 1);
849 be_emit_finish_line_gas(irn);
852 static void emit_be_MemPerm(const ir_node *node)
858 /* TODO: this implementation is slower than necessary.
859 The longterm goal is however to avoid the memperm node completely */
861 memperm_arity = be_get_MemPerm_entity_arity(node);
862 if (memperm_arity > 12)
863 panic("memperm with more than 12 inputs not supported yet");
865 for (i = 0; i < memperm_arity; ++i) {
867 ir_entity *entity = be_get_MemPerm_in_entity(node, i);
870 be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
871 be_emit_finish_line_gas(node);
873 /* load from entity */
874 offset = get_entity_offset(entity) + sp_change;
875 be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
876 be_emit_finish_line_gas(node);
879 for (i = memperm_arity-1; i >= 0; --i) {
881 ir_entity *entity = be_get_MemPerm_out_entity(node, i);
883 /* store to new entity */
884 offset = get_entity_offset(entity) + sp_change;
885 be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
886 be_emit_finish_line_gas(node);
887 /* restore register */
888 be_emit_irprintf("\tldr r%d, [sp], #4", i);
890 be_emit_finish_line_gas(node);
892 assert(sp_change == 0);
895 static void emit_be_Return(const ir_node *node)
897 be_emit_cstring("\tmov pc, lr");
898 be_emit_finish_line_gas(node);
901 /************************************************************************/
903 /************************************************************************/
905 static void emit_arm_Jmp(const ir_node *node)
907 ir_node *block, *next_block;
909 /* for now, the code works for scheduled and non-schedules blocks */
910 block = get_nodes_block(node);
912 /* we have a block schedule */
913 next_block = sched_next_block(block);
914 if (get_cfop_target_block(node) != next_block) {
915 be_emit_cstring("\tb ");
916 arm_emit_cfop_target(node);
918 be_emit_cstring("\t/* fallthrough to ");
919 arm_emit_cfop_target(node);
920 be_emit_cstring(" */");
922 be_emit_finish_line_gas(node);
925 static void emit_arm_fpaDbl2GP(const ir_node *irn) {
926 be_emit_cstring("\tstfd ");
927 arm_emit_source_register(irn, 0);
928 be_emit_cstring(", [sp, #-8]!");
929 be_emit_pad_comment();
930 be_emit_cstring("/* Push fp to stack */");
931 be_emit_finish_line_gas(NULL);
933 be_emit_cstring("\tldmfd sp!, {");
934 arm_emit_dest_register(irn, 1);
935 be_emit_cstring(", ");
936 arm_emit_dest_register(irn, 0);
938 be_emit_pad_comment();
939 be_emit_cstring("/* Pop destination */");
940 be_emit_finish_line_gas(irn);
943 static void emit_arm_LdTls(const ir_node *irn) {
945 panic("TLS not supported for this target");
946 /* Er... our gcc does not support it... Install a newer toolchain. */
949 static void emit_nothing(const ir_node *irn)
955 * The type of a emitter function.
957 typedef void (emit_func)(const ir_node *irn);
960 * Set a node emitter. Make it a bit more type safe.
962 static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
964 op->ops.generic = (op_func)arm_emit_node;
968 * Enters the emitter functions for handled nodes into the generic
969 * pointer of an opcode.
971 static void arm_register_emitters(void)
973 /* first clear the generic function pointer for all ops */
974 clear_irp_opcodes_generic_func();
976 /* register all emitter functions defined in spec */
977 arm_register_spec_emitters();
980 set_emitter(op_arm_B, emit_arm_B);
981 set_emitter(op_arm_CopyB, emit_arm_CopyB);
982 set_emitter(op_arm_fpaConst, emit_arm_fpaConst);
983 set_emitter(op_arm_fpaDbl2GP, emit_arm_fpaDbl2GP);
984 set_emitter(op_arm_FrameAddr, emit_arm_FrameAddr);
985 set_emitter(op_arm_Jmp, emit_arm_Jmp);
986 set_emitter(op_arm_LdTls, emit_arm_LdTls);
987 set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp);
988 set_emitter(op_arm_SymConst, emit_arm_SymConst);
989 set_emitter(op_be_Call, emit_be_Call);
990 set_emitter(op_be_Copy, emit_be_Copy);
991 set_emitter(op_be_CopyKeep, emit_be_Copy);
992 set_emitter(op_be_IncSP, emit_be_IncSP);
993 set_emitter(op_be_MemPerm, emit_be_MemPerm);
994 set_emitter(op_be_Perm, emit_be_Perm);
995 set_emitter(op_be_Return, emit_be_Return);
997 /* no need to emit anything for the following nodes */
998 set_emitter(op_Phi, emit_nothing);
999 set_emitter(op_be_Keep, emit_nothing);
1000 set_emitter(op_be_Start, emit_nothing);
1001 set_emitter(op_be_Barrier, emit_nothing);
1005 * Emits code for a node.
1007 static void arm_emit_node(const ir_node *irn) {
1008 ir_op *op = get_irn_op(irn);
1010 if (op->ops.generic) {
1011 emit_func *emit = (emit_func *)op->ops.generic;
1012 be_dbg_set_dbg_info(get_irn_dbg_info(irn));
1015 panic("Error: No emit handler for node %+F (graph %+F)\n",
1016 irn, current_ir_graph);
1021 * emit the block label if needed.
1023 static void arm_emit_block_header(ir_node *block, ir_node *prev)
1028 ir_exec_freq *exec_freq = cg->birg->exec_freq;
1031 n_cfgpreds = get_Block_n_cfgpreds(block);
1032 if (n_cfgpreds == 1) {
1033 ir_node *pred = get_Block_cfgpred(block, 0);
1034 ir_node *pred_block = get_nodes_block(pred);
1036 /* we don't need labels for fallthrough blocks, however switch-jmps
1037 * are no fallthroughs */
1038 if (pred_block == prev &&
1039 !(is_Proj(pred) && is_arm_SwitchJmp(get_Proj_pred(pred)))) {
1049 arm_emit_block_name(block);
1052 be_emit_pad_comment();
1053 be_emit_cstring(" /* preds:");
1055 /* emit list of pred blocks in comment */
1056 arity = get_irn_arity(block);
1057 for (i = 0; i < arity; ++i) {
1058 ir_node *predblock = get_Block_cfgpred_block(block, i);
1059 be_emit_irprintf(" %d", get_irn_node_nr(predblock));
1062 be_emit_cstring("\t/* ");
1063 arm_emit_block_name(block);
1064 be_emit_cstring(": ");
1066 if (exec_freq != NULL) {
1067 be_emit_irprintf(" freq: %f",
1068 get_block_execfreq(exec_freq, block));
1070 be_emit_cstring(" */\n");
1071 be_emit_write_line();
1075 * Walks over the nodes in a block connected by scheduling edges
1076 * and emits code for each node.
1078 static void arm_gen_block(ir_node *block, ir_node *prev_block) {
1081 arm_emit_block_header(block, prev_block);
1082 be_dbg_set_dbg_info(get_irn_dbg_info(block));
1083 sched_foreach(block, irn) {
1090 * Sets labels for control flow nodes (jump target)
1092 static void arm_gen_labels(ir_node *block, void *env) {
1094 int n = get_Block_n_cfgpreds(block);
1097 for (n--; n >= 0; n--) {
1098 pred = get_Block_cfgpred(block, n);
1099 set_irn_link(pred, block);
1104 * Compare two entries of the symbol or tarval set.
1106 static int cmp_sym_or_tv(const void *elt, const void *key, size_t size) {
1107 const sym_or_tv_t *p1 = elt;
1108 const sym_or_tv_t *p2 = key;
1111 /* as an identifier NEVER can point to a tarval, it's enough
1112 to compare it this way */
1113 return p1->u.generic != p2->u.generic;
1117 * Main driver. Emits the code for one routine.
1119 void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg)
1121 ir_node **blk_sched;
1123 ir_node *last_block = NULL;
1124 ir_entity *entity = get_irg_entity(irg);
1127 sym_or_tv = new_set(cmp_sym_or_tv, 8);
1129 be_gas_elf_type_char = '%';
1131 arm_register_emitters();
1133 be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
1135 /* create the block schedule. For now, we don't need it earlier. */
1136 blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
1138 be_gas_emit_function_prolog(entity, 4);
1140 irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
1142 n = ARR_LEN(blk_sched);
1143 for (i = 0; i < n;) {
1144 ir_node *block, *next_bl;
1146 block = blk_sched[i];
1148 next_bl = i < n ? blk_sched[i] : NULL;
1150 /* set here the link. the emitter expects to find the next block here */
1151 set_irn_link(block, next_bl);
1152 arm_gen_block(block, last_block);
1156 be_gas_emit_function_epilog(entity);
1157 be_dbg_method_end();
1159 /* emit SymConst values */
1160 if (set_count(sym_or_tv) > 0) {
1163 be_emit_cstring("\t.align 2\n");
1165 foreach_set(sym_or_tv, entry) {
1166 be_emit_irprintf(".L%u:\n", entry->label);
1168 if (entry->is_ident) {
1169 be_emit_cstring("\t.word\t");
1170 be_emit_ident(entry->u.id);
1172 be_emit_write_line();
1174 tarval *tv = entry->u.tv;
1175 int i, size = get_mode_size_bytes(get_tarval_mode(tv));
1178 /* beware: ARM fpa uses big endian format */
1179 for (i = ((size + 3) & ~3) - 4; i >= 0; i -= 4) {
1181 v = get_tarval_sub_bits(tv, i+3);
1182 v = (v << 8) | get_tarval_sub_bits(tv, i+2);
1183 v = (v << 8) | get_tarval_sub_bits(tv, i+1);
1184 v = (v << 8) | get_tarval_sub_bits(tv, i+0);
1185 be_emit_irprintf("\t.word\t%u\n", v);
1186 be_emit_write_line();
1191 be_emit_write_line();
1196 void arm_init_emitter(void)
1198 FIRM_DBG_REGISTER(dbg, "firm.be.arm.emit");