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 key.u.id = get_entity_ld_ident(attr->entity);
342 entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
343 if (entry->label == 0) {
344 /* allocate a label */
345 entry->label = get_unique_label();
347 label = entry->label;
349 /* load the symbol indirect */
350 be_emit_cstring("\tldr ");
351 arm_emit_dest_register(irn, 0);
352 be_emit_irprintf(", .L%u", label);
353 be_emit_finish_line_gas(irn);
356 static void emit_arm_FrameAddr(const ir_node *irn)
358 const arm_SymConst_attr_t *attr = get_irn_generic_attr_const(irn);
360 be_emit_cstring("\tadd ");
361 arm_emit_dest_register(irn, 0);
362 be_emit_cstring(", ");
363 arm_emit_source_register(irn, 0);
364 be_emit_cstring(", ");
365 be_emit_irprintf("#0x%X", attr->fp_offset);
366 be_emit_finish_line_gas(irn);
370 * Emit a floating point fpa constant.
372 static void emit_arm_fpaConst(const ir_node *irn) {
373 sym_or_tv_t key, *entry;
377 key.u.tv = get_fpaConst_value(irn);
380 entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
381 if (entry->label == 0) {
382 /* allocate a label */
383 entry->label = get_unique_label();
385 label = entry->label;
387 /* load the tarval indirect */
388 mode = get_irn_mode(irn);
389 be_emit_cstring("\tldf");
390 arm_emit_fpa_postfix(mode);
393 arm_emit_dest_register(irn, 0);
394 be_emit_irprintf(", .L%u", label);
395 be_emit_finish_line_gas(irn);
399 * Returns the next block in a block schedule.
401 static ir_node *sched_next_block(const ir_node *block) {
402 return get_irn_link(block);
406 * Returns the target block for a control flow node.
408 static ir_node *get_cfop_target_block(const ir_node *irn) {
409 return get_irn_link(irn);
413 * Emits a block label for the given block.
415 static void arm_emit_block_name(const ir_node *block) {
416 if (has_Block_entity(block)) {
417 ir_entity *entity = get_Block_entity(block);
418 be_gas_emit_entity(entity);
420 be_emit_cstring(BLOCK_PREFIX);
421 be_emit_irprintf("%d", get_irn_node_nr(block));
426 * Emit the target label for a control flow node.
428 static void arm_emit_cfop_target(const ir_node *irn) {
429 ir_node *block = get_cfop_target_block(irn);
431 arm_emit_block_name(block);
435 * Emit a Compare with conditional branch.
437 static void emit_arm_B(const ir_node *irn)
439 const ir_edge_t *edge;
440 const ir_node *proj_true = NULL;
441 const ir_node *proj_false = NULL;
442 const ir_node *block;
443 const ir_node *next_block;
444 ir_node *op1 = get_irn_n(irn, 0);
446 int proj_num = get_arm_CondJmp_proj_num(irn);
447 const arm_cmp_attr_t *cmp_attr = get_irn_generic_attr_const(op1);
448 bool is_signed = !cmp_attr->is_unsigned;
450 assert(is_arm_Cmp(op1) || is_arm_Tst(op1));
452 foreach_out_edge(irn, edge) {
453 ir_node *proj = get_edge_src_irn(edge);
454 long nr = get_Proj_proj(proj);
455 if (nr == pn_Cond_true) {
462 if (cmp_attr->ins_permuted) {
463 proj_num = get_mirrored_pnc(proj_num);
466 /* for now, the code works for scheduled and non-schedules blocks */
467 block = get_nodes_block(irn);
469 /* we have a block schedule */
470 next_block = sched_next_block(block);
472 assert(proj_num != pn_Cmp_False);
473 assert(proj_num != pn_Cmp_True);
475 if (get_cfop_target_block(proj_true) == next_block) {
476 /* exchange both proj's so the second one can be omitted */
477 const ir_node *t = proj_true;
479 proj_true = proj_false;
481 proj_num = get_negated_pnc(proj_num, mode_Iu);
485 case pn_Cmp_Eq: suffix = "eq"; break;
486 case pn_Cmp_Lt: suffix = is_signed ? "lt" : "lo"; break;
487 case pn_Cmp_Le: suffix = is_signed ? "le" : "ls"; break;
488 case pn_Cmp_Gt: suffix = is_signed ? "gt" : "hi"; break;
489 case pn_Cmp_Ge: suffix = is_signed ? "ge" : "hs"; break;
490 case pn_Cmp_Lg: suffix = "ne"; break;
491 case pn_Cmp_Leg: suffix = "al"; break;
492 default: panic("Cmp has unsupported pnc");
495 /* emit the true proj */
496 be_emit_irprintf("\tb%s ", suffix);
497 arm_emit_cfop_target(proj_true);
498 be_emit_finish_line_gas(proj_true);
500 if (get_cfop_target_block(proj_false) == next_block) {
501 be_emit_cstring("\t/* fallthrough to ");
502 arm_emit_cfop_target(proj_false);
503 be_emit_cstring(" */");
504 be_emit_finish_line_gas(proj_false);
506 be_emit_cstring("\tb ");
507 arm_emit_cfop_target(proj_false);
508 be_emit_finish_line_gas(proj_false);
512 /** Sort register in ascending order. */
513 static int reg_cmp(const void *a, const void *b) {
514 const arch_register_t * const *ra = a;
515 const arch_register_t * const *rb = b;
517 return *ra < *rb ? -1 : (*ra != *rb);
521 * Create the CopyB instruction sequence.
523 static void emit_arm_CopyB(const ir_node *irn)
525 const arm_CopyB_attr_t *attr = get_irn_generic_attr_const(irn);
526 unsigned size = attr->size;
528 const char *tgt = arch_register_get_name(get_in_reg(irn, 0));
529 const char *src = arch_register_get_name(get_in_reg(irn, 1));
530 const char *t0, *t1, *t2, *t3;
532 const arch_register_t *tmpregs[4];
534 /* collect the temporary registers and sort them, we need ascending order */
535 tmpregs[0] = get_in_reg(irn, 2);
536 tmpregs[1] = get_in_reg(irn, 3);
537 tmpregs[2] = get_in_reg(irn, 4);
538 tmpregs[3] = &arm_gp_regs[REG_R12];
540 /* Note: R12 is always the last register because the RA did not assign higher ones */
541 qsort((void *)tmpregs, 3, sizeof(tmpregs[0]), reg_cmp);
543 /* need ascending order */
544 t0 = arch_register_get_name(tmpregs[0]);
545 t1 = arch_register_get_name(tmpregs[1]);
546 t2 = arch_register_get_name(tmpregs[2]);
547 t3 = arch_register_get_name(tmpregs[3]);
549 be_emit_cstring("/* MemCopy (");
551 be_emit_cstring(")->(");
552 arm_emit_source_register(irn, 0);
553 be_emit_irprintf(" [%u bytes], Uses ", size);
555 be_emit_cstring(", ");
557 be_emit_cstring(", ");
559 be_emit_cstring(", and ");
561 be_emit_cstring("*/");
562 be_emit_finish_line_gas(NULL);
564 assert(size > 0 && "CopyB needs size > 0" );
567 assert(!"strange hack enabled: copy more bytes than needed!");
576 be_emit_cstring("\tldr ");
578 be_emit_cstring(", [");
580 be_emit_cstring(", #0]");
581 be_emit_finish_line_gas(NULL);
583 be_emit_cstring("\tstr ");
585 be_emit_cstring(", [");
587 be_emit_cstring(", #0]");
588 be_emit_finish_line_gas(irn);
591 be_emit_cstring("\tldmia ");
593 be_emit_cstring("!, {");
595 be_emit_cstring(", ");
598 be_emit_finish_line_gas(NULL);
600 be_emit_cstring("\tstmia ");
602 be_emit_cstring("!, {");
604 be_emit_cstring(", ");
607 be_emit_finish_line_gas(irn);
610 be_emit_cstring("\tldmia ");
612 be_emit_cstring("!, {");
614 be_emit_cstring(", ");
616 be_emit_cstring(", ");
619 be_emit_finish_line_gas(NULL);
621 be_emit_cstring("\tstmia ");
623 be_emit_cstring("!, {");
625 be_emit_cstring(", ");
627 be_emit_cstring(", ");
630 be_emit_finish_line_gas(irn);
635 be_emit_cstring("\tldmia ");
637 be_emit_cstring("!, {");
639 be_emit_cstring(", ");
641 be_emit_cstring(", ");
643 be_emit_cstring(", ");
646 be_emit_finish_line_gas(NULL);
648 be_emit_cstring("\tstmia ");
650 be_emit_cstring("!, {");
652 be_emit_cstring(", ");
654 be_emit_cstring(", ");
656 be_emit_cstring(", ");
659 be_emit_finish_line_gas(irn);
664 static void emit_arm_SwitchJmp(const ir_node *irn) {
665 const ir_edge_t *edge;
671 ir_node *default_proj = NULL;
673 block_nr = get_irn_node_nr(irn);
674 n_projs = get_arm_SwitchJmp_n_projs(irn);
676 projs = XMALLOCNZ(ir_node*, n_projs);
678 foreach_out_edge(irn, edge) {
679 proj = get_edge_src_irn(edge);
680 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
682 if (get_Proj_proj(proj) == get_arm_SwitchJmp_default_proj_num(irn))
685 projs[get_Proj_proj(proj)] = proj;
687 assert(default_proj != NULL && "SwitchJmp should have a Default Proj");
694 be_emit_cstring("\tcmp ");
695 arm_emit_source_register(irn, 0);
696 be_emit_irprintf(", #%u", n_projs - 1);
697 be_emit_finish_line_gas(irn);
699 be_emit_cstring("\tbhi ");
700 arm_emit_cfop_target(default_proj);
701 be_emit_finish_line_gas(default_proj);
704 LDR %r12, .TABLE_X_START
705 ADD %r12, %r12, [%1S, LSL #2]
709 be_emit_irprintf("\tldr %%r12, TABLE_%d_START", block_nr);
710 be_emit_finish_line_gas(NULL);
712 be_emit_irprintf("\tadd %%r12, %%r12, ");
713 arm_emit_source_register(irn, 0);
714 be_emit_cstring(", LSL #2");
715 be_emit_finish_line_gas(NULL);
717 be_emit_cstring("\tldr %r15, [%r12, #0]");
718 be_emit_finish_line_gas(NULL);
720 be_emit_irprintf("TABLE_%d_START:\n\t.word\tTABLE_%d", block_nr, block_nr);
721 be_emit_finish_line_gas(NULL);
722 be_emit_irprintf("\t.align 2");
723 be_emit_finish_line_gas(NULL);
724 be_emit_irprintf("TABLE_%d:", block_nr);
725 be_emit_finish_line_gas(NULL);
727 for (i = 0; i < n_projs; ++i) {
730 proj = projs[get_arm_SwitchJmp_default_proj_num(irn)];
732 be_emit_cstring("\t.word\t");
733 arm_emit_cfop_target(proj);
734 be_emit_finish_line_gas(proj);
736 be_emit_irprintf("\t.align 2\n");
737 be_emit_finish_line_gas(NULL);
741 /************************************************************************/
743 /************************************************************************/
745 static void arm_emit_entity(ir_entity *entity)
747 be_emit_ident(get_entity_ld_ident(entity));
750 static void emit_be_Call(const ir_node *irn)
752 ir_entity *entity = be_Call_get_entity(irn);
754 if (entity != NULL) {
755 be_emit_cstring("\tbl ");
756 arm_emit_entity(entity);
757 be_emit_finish_line_gas(irn);
759 be_emit_cstring("\tmov lr, pc");
760 be_emit_finish_line_gas(irn);
761 be_emit_cstring("\tmov pc, ");
762 arm_emit_source_register(irn, be_pos_Call_ptr);
763 be_emit_finish_line_gas(irn);
767 /** Emit an IncSP node */
768 static void emit_be_IncSP(const ir_node *irn) {
769 int offs = -be_get_IncSP_offset(irn);
773 be_emit_cstring("\tsub ");
776 be_emit_cstring("\tadd ");
778 arm_emit_dest_register(irn, 0);
779 be_emit_cstring(", ");
780 arm_emit_source_register(irn, 0);
781 be_emit_irprintf(", #0x%X", offs);
783 /* omitted IncSP(0) */
786 be_emit_finish_line_gas(irn);
789 static void emit_be_Copy(const ir_node *irn) {
790 ir_mode *mode = get_irn_mode(irn);
792 if (get_in_reg(irn, 0) == get_out_reg(irn, 0)) {
797 if (mode_is_float(mode)) {
798 if (USE_FPA(cg->isa)) {
799 be_emit_cstring("\tmvf");
802 arm_emit_dest_register(irn, 0);
803 be_emit_cstring(", ");
804 arm_emit_source_register(irn, 0);
805 be_emit_finish_line_gas(irn);
807 assert(0 && "move not supported for this mode");
808 panic("emit_be_Copy: move not supported for this mode");
810 } else if (mode_is_data(mode)) {
811 be_emit_cstring("\tmov ");
812 arm_emit_dest_register(irn, 0);
813 be_emit_cstring(", ");
814 arm_emit_source_register(irn, 0);
815 be_emit_finish_line_gas(irn);
817 assert(0 && "move not supported for this mode");
818 panic("emit_be_Copy: move not supported for this mode");
822 static void emit_be_Perm(const ir_node *irn)
824 be_emit_cstring("\teor ");
825 arm_emit_source_register(irn, 0);
826 be_emit_cstring(", ");
827 arm_emit_source_register(irn, 0);
828 be_emit_cstring(", ");
829 arm_emit_source_register(irn, 1);
830 be_emit_finish_line_gas(NULL);
832 be_emit_cstring("\teor ");
833 arm_emit_source_register(irn, 1);
834 be_emit_cstring(", ");
835 arm_emit_source_register(irn, 0);
836 be_emit_cstring(", ");
837 arm_emit_source_register(irn, 1);
838 be_emit_finish_line_gas(NULL);
840 be_emit_cstring("\teor ");
841 arm_emit_source_register(irn, 0);
842 be_emit_cstring(", ");
843 arm_emit_source_register(irn, 0);
844 be_emit_cstring(", ");
845 arm_emit_source_register(irn, 1);
846 be_emit_finish_line_gas(irn);
849 static void emit_be_MemPerm(const ir_node *node)
855 /* TODO: this implementation is slower than necessary.
856 The longterm goal is however to avoid the memperm node completely */
858 memperm_arity = be_get_MemPerm_entity_arity(node);
859 if (memperm_arity > 12)
860 panic("memperm with more than 12 inputs not supported yet");
862 for (i = 0; i < memperm_arity; ++i) {
864 ir_entity *entity = be_get_MemPerm_in_entity(node, i);
867 be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
868 be_emit_finish_line_gas(node);
870 /* load from entity */
871 offset = get_entity_offset(entity) + sp_change;
872 be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
873 be_emit_finish_line_gas(node);
876 for (i = memperm_arity-1; i >= 0; --i) {
878 ir_entity *entity = be_get_MemPerm_out_entity(node, i);
880 /* store to new entity */
881 offset = get_entity_offset(entity) + sp_change;
882 be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
883 be_emit_finish_line_gas(node);
884 /* restore register */
885 be_emit_irprintf("\tldr r%d, [sp], #4", i);
887 be_emit_finish_line_gas(node);
889 assert(sp_change == 0);
892 static void emit_be_Return(const ir_node *node)
894 be_emit_cstring("\tmov pc, lr");
895 be_emit_finish_line_gas(node);
898 /************************************************************************/
900 /************************************************************************/
902 static void emit_arm_Jmp(const ir_node *node)
904 ir_node *block, *next_block;
906 /* for now, the code works for scheduled and non-schedules blocks */
907 block = get_nodes_block(node);
909 /* we have a block schedule */
910 next_block = sched_next_block(block);
911 if (get_cfop_target_block(node) != next_block) {
912 be_emit_cstring("\tb ");
913 arm_emit_cfop_target(node);
915 be_emit_cstring("\t/* fallthrough to ");
916 arm_emit_cfop_target(node);
917 be_emit_cstring(" */");
919 be_emit_finish_line_gas(node);
922 static void emit_arm_fpaDbl2GP(const ir_node *irn) {
923 be_emit_cstring("\tstfd ");
924 arm_emit_source_register(irn, 0);
925 be_emit_cstring(", [sp, #-8]!");
926 be_emit_pad_comment();
927 be_emit_cstring("/* Push fp to stack */");
928 be_emit_finish_line_gas(NULL);
930 be_emit_cstring("\tldmfd sp!, {");
931 arm_emit_dest_register(irn, 1);
932 be_emit_cstring(", ");
933 arm_emit_dest_register(irn, 0);
935 be_emit_pad_comment();
936 be_emit_cstring("/* Pop destination */");
937 be_emit_finish_line_gas(irn);
940 static void emit_arm_LdTls(const ir_node *irn) {
942 panic("TLS not supported for this target");
943 /* Er... our gcc does not support it... Install a newer toolchain. */
946 static void emit_nothing(const ir_node *irn)
952 * The type of a emitter function.
954 typedef void (emit_func)(const ir_node *irn);
957 * Set a node emitter. Make it a bit more type safe.
959 static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
961 op->ops.generic = (op_func)arm_emit_node;
965 * Enters the emitter functions for handled nodes into the generic
966 * pointer of an opcode.
968 static void arm_register_emitters(void)
970 /* first clear the generic function pointer for all ops */
971 clear_irp_opcodes_generic_func();
973 /* register all emitter functions defined in spec */
974 arm_register_spec_emitters();
977 set_emitter(op_arm_B, emit_arm_B);
978 set_emitter(op_arm_CopyB, emit_arm_CopyB);
979 set_emitter(op_arm_fpaConst, emit_arm_fpaConst);
980 set_emitter(op_arm_fpaDbl2GP, emit_arm_fpaDbl2GP);
981 set_emitter(op_arm_FrameAddr, emit_arm_FrameAddr);
982 set_emitter(op_arm_Jmp, emit_arm_Jmp);
983 set_emitter(op_arm_LdTls, emit_arm_LdTls);
984 set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp);
985 set_emitter(op_arm_SymConst, emit_arm_SymConst);
986 set_emitter(op_be_Call, emit_be_Call);
987 set_emitter(op_be_Copy, emit_be_Copy);
988 set_emitter(op_be_CopyKeep, emit_be_Copy);
989 set_emitter(op_be_IncSP, emit_be_IncSP);
990 set_emitter(op_be_MemPerm, emit_be_MemPerm);
991 set_emitter(op_be_Perm, emit_be_Perm);
992 set_emitter(op_be_Return, emit_be_Return);
994 /* no need to emit anything for the following nodes */
995 set_emitter(op_Phi, emit_nothing);
996 set_emitter(op_be_Keep, emit_nothing);
997 set_emitter(op_be_Start, emit_nothing);
998 set_emitter(op_be_Barrier, emit_nothing);
1002 * Emits code for a node.
1004 static void arm_emit_node(const ir_node *irn) {
1005 ir_op *op = get_irn_op(irn);
1007 if (op->ops.generic) {
1008 emit_func *emit = (emit_func *)op->ops.generic;
1009 be_dbg_set_dbg_info(get_irn_dbg_info(irn));
1012 panic("Error: No emit handler for node %+F (graph %+F)\n",
1013 irn, current_ir_graph);
1018 * emit the block label if needed.
1020 static void arm_emit_block_header(ir_node *block, ir_node *prev)
1025 ir_exec_freq *exec_freq = cg->birg->exec_freq;
1028 n_cfgpreds = get_Block_n_cfgpreds(block);
1029 if (n_cfgpreds == 1) {
1030 ir_node *pred = get_Block_cfgpred(block, 0);
1031 ir_node *pred_block = get_nodes_block(pred);
1033 /* we don't need labels for fallthrough blocks, however switch-jmps
1034 * are no fallthroughs */
1035 if (pred_block == prev &&
1036 !(is_Proj(pred) && is_arm_SwitchJmp(get_Proj_pred(pred)))) {
1046 arm_emit_block_name(block);
1049 be_emit_pad_comment();
1050 be_emit_cstring(" /* preds:");
1052 /* emit list of pred blocks in comment */
1053 arity = get_irn_arity(block);
1054 for (i = 0; i < arity; ++i) {
1055 ir_node *predblock = get_Block_cfgpred_block(block, i);
1056 be_emit_irprintf(" %d", get_irn_node_nr(predblock));
1059 be_emit_cstring("\t/* ");
1060 arm_emit_block_name(block);
1061 be_emit_cstring(": ");
1063 if (exec_freq != NULL) {
1064 be_emit_irprintf(" freq: %f",
1065 get_block_execfreq(exec_freq, block));
1067 be_emit_cstring(" */\n");
1068 be_emit_write_line();
1072 * Walks over the nodes in a block connected by scheduling edges
1073 * and emits code for each node.
1075 static void arm_gen_block(ir_node *block, ir_node *prev_block) {
1078 arm_emit_block_header(block, prev_block);
1079 be_dbg_set_dbg_info(get_irn_dbg_info(block));
1080 sched_foreach(block, irn) {
1087 * Sets labels for control flow nodes (jump target)
1089 static void arm_gen_labels(ir_node *block, void *env) {
1091 int n = get_Block_n_cfgpreds(block);
1094 for (n--; n >= 0; n--) {
1095 pred = get_Block_cfgpred(block, n);
1096 set_irn_link(pred, block);
1101 * Compare two entries of the symbol or tarval set.
1103 static int cmp_sym_or_tv(const void *elt, const void *key, size_t size) {
1104 const sym_or_tv_t *p1 = elt;
1105 const sym_or_tv_t *p2 = key;
1108 /* as an identifier NEVER can point to a tarval, it's enough
1109 to compare it this way */
1110 return p1->u.generic != p2->u.generic;
1114 * Main driver. Emits the code for one routine.
1116 void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg)
1118 ir_node **blk_sched;
1120 ir_node *last_block = NULL;
1121 ir_entity *entity = get_irg_entity(irg);
1124 sym_or_tv = new_set(cmp_sym_or_tv, 8);
1126 be_gas_elf_type_char = '%';
1128 arm_register_emitters();
1130 be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
1132 /* create the block schedule. For now, we don't need it earlier. */
1133 blk_sched = be_create_block_schedule(cg->irg, cg->birg->exec_freq);
1135 be_gas_emit_function_prolog(entity, 4);
1137 irg_block_walk_graph(irg, arm_gen_labels, NULL, NULL);
1139 n = ARR_LEN(blk_sched);
1140 for (i = 0; i < n;) {
1141 ir_node *block, *next_bl;
1143 block = blk_sched[i];
1145 next_bl = i < n ? blk_sched[i] : NULL;
1147 /* set here the link. the emitter expects to find the next block here */
1148 set_irn_link(block, next_bl);
1149 arm_gen_block(block, last_block);
1153 be_gas_emit_function_epilog(entity);
1154 be_dbg_method_end();
1156 /* emit SymConst values */
1157 if (set_count(sym_or_tv) > 0) {
1160 be_emit_cstring("\t.align 2\n");
1162 foreach_set(sym_or_tv, entry) {
1163 be_emit_irprintf(".L%u:\n", entry->label);
1165 if (entry->is_ident) {
1166 be_emit_cstring("\t.word\t");
1167 be_emit_ident(entry->u.id);
1169 be_emit_write_line();
1171 tarval *tv = entry->u.tv;
1172 int i, size = get_mode_size_bytes(get_tarval_mode(tv));
1175 /* beware: ARM fpa uses big endian format */
1176 for (i = ((size + 3) & ~3) - 4; i >= 0; i -= 4) {
1178 v = get_tarval_sub_bits(tv, i+3);
1179 v = (v << 8) | get_tarval_sub_bits(tv, i+2);
1180 v = (v << 8) | get_tarval_sub_bits(tv, i+1);
1181 v = (v << 8) | get_tarval_sub_bits(tv, i+0);
1182 be_emit_irprintf("\t.word\t%u\n", v);
1183 be_emit_write_line();
1188 be_emit_write_line();
1193 void arm_init_emitter(void)
1195 FIRM_DBG_REGISTER(dbg, "firm.be.arm.emit");