2 * Copyright (C) 1995-2010 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
22 * @brief emit assembler for a backend graph
40 #include "raw_bitset.h"
44 #include "../besched.h"
45 #include "../beblocksched.h"
47 #include "../begnuas.h"
48 #include "../be_dbgout.h"
49 #include "../benode.h"
51 #include "sparc_emitter.h"
52 #include "gen_sparc_emitter.h"
53 #include "sparc_nodes_attr.h"
54 #include "sparc_new_nodes.h"
55 #include "gen_sparc_regalloc_if.h"
57 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
59 static ir_heights_t *heights;
60 static const ir_node *delay_slot_filler; /**< this node has been choosen to fill
61 the next delay slot */
63 static void sparc_emit_node(const ir_node *node);
66 * Returns the register at in position pos.
68 static const arch_register_t *get_in_reg(const ir_node *node, int pos)
71 const arch_register_t *reg = NULL;
73 assert(get_irn_arity(node) > pos && "Invalid IN position");
75 /* The out register of the operator at position pos is the
76 in register we need. */
77 op = get_irn_n(node, pos);
79 reg = arch_get_irn_register(op);
81 assert(reg && "no in register found");
86 * Returns the register at out position pos.
88 static const arch_register_t *get_out_reg(const ir_node *node, int pos)
91 const arch_register_t *reg = NULL;
93 /* 1st case: irn is not of mode_T, so it has only */
94 /* one OUT register -> good */
95 /* 2nd case: irn is of mode_T -> collect all Projs and ask the */
96 /* Proj with the corresponding projnum for the register */
98 if (get_irn_mode(node) != mode_T) {
99 reg = arch_get_irn_register(node);
100 } else if (is_sparc_irn(node)) {
101 reg = arch_irn_get_register(node, pos);
103 const ir_edge_t *edge;
105 foreach_out_edge(node, edge) {
106 proj = get_edge_src_irn(edge);
107 assert(is_Proj(proj) && "non-Proj from mode_T node");
108 if (get_Proj_proj(proj) == pos) {
109 reg = arch_get_irn_register(proj);
115 assert(reg && "no out register found");
119 static bool is_valid_immediate(int32_t value)
121 return -4096 <= value && value < 4096;
124 void sparc_emit_immediate(const ir_node *node)
126 const sparc_attr_t *attr = get_sparc_attr_const(node);
127 ir_entity *entity = attr->immediate_value_entity;
129 if (entity == NULL) {
130 int32_t value = attr->immediate_value;
131 assert(is_valid_immediate(value));
132 be_emit_irprintf("%d", value);
134 be_emit_cstring("%lo(");
135 be_gas_emit_entity(entity);
136 if (attr->immediate_value != 0) {
137 be_emit_irprintf("%+d", attr->immediate_value);
143 void sparc_emit_high_immediate(const ir_node *node)
145 const sparc_attr_t *attr = get_sparc_attr_const(node);
146 ir_entity *entity = attr->immediate_value_entity;
148 be_emit_cstring("%hi(");
149 if (entity == NULL) {
150 uint32_t value = (uint32_t) attr->immediate_value;
151 be_emit_irprintf("0x%X", value);
153 be_gas_emit_entity(entity);
154 if (attr->immediate_value != 0) {
155 be_emit_irprintf("%+d", attr->immediate_value);
161 void sparc_emit_source_register(const ir_node *node, int pos)
163 const arch_register_t *reg = get_in_reg(node, pos);
165 be_emit_string(arch_register_get_name(reg));
168 void sparc_emit_dest_register(const ir_node *node, int pos)
170 const arch_register_t *reg = get_out_reg(node, pos);
172 be_emit_string(arch_register_get_name(reg));
176 * Emits either a imm or register depending on arity of node
178 * @param register no (-1 if no register)
180 void sparc_emit_reg_or_imm(const ir_node *node, int pos)
182 if (get_irn_arity(node) > pos) {
184 sparc_emit_source_register(node, pos);
186 // we have a imm input
187 sparc_emit_immediate(node);
191 static bool is_stack_pointer_relative(const ir_node *node)
193 const arch_register_t *sp = &sparc_gp_regs[REG_SP];
194 return (is_sparc_St(node) && get_in_reg(node, n_sparc_St_ptr) == sp)
195 || (is_sparc_Ld(node) && get_in_reg(node, n_sparc_Ld_ptr) == sp);
201 void sparc_emit_offset(const ir_node *node, int offset_node_pos)
203 const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
205 if (attr->is_reg_reg) {
206 assert(!attr->is_frame_entity);
207 assert(attr->base.immediate_value == 0);
208 assert(attr->base.immediate_value_entity == NULL);
210 sparc_emit_source_register(node, offset_node_pos);
211 } else if (attr->is_frame_entity) {
212 int32_t offset = attr->base.immediate_value;
213 /* bad hack: the real stack stuff is behind the always-there spill
214 * space for the register window and stack */
215 if (is_stack_pointer_relative(node))
216 offset += SPARC_MIN_STACKSIZE;
218 assert(is_valid_immediate(offset));
219 be_emit_irprintf("%+ld", offset);
221 } else if (attr->base.immediate_value != 0
222 || attr->base.immediate_value_entity != NULL) {
224 sparc_emit_immediate(node);
228 void sparc_emit_float_load_store_mode(const ir_node *node)
230 const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
231 ir_mode *mode = attr->load_store_mode;
232 int bits = get_mode_size_bits(mode);
234 assert(mode_is_float(mode));
238 case 64: be_emit_char('d'); return;
239 case 128: be_emit_char('q'); return;
241 panic("invalid flaot load/store mode %+F", mode);
245 * Emit load mode char
247 void sparc_emit_load_mode(const ir_node *node)
249 const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
250 ir_mode *mode = attr->load_store_mode;
251 int bits = get_mode_size_bits(mode);
252 bool is_signed = mode_is_signed(mode);
255 be_emit_string(is_signed ? "sh" : "uh");
256 } else if (bits == 8) {
257 be_emit_string(is_signed ? "sb" : "ub");
258 } else if (bits == 64) {
266 * Emit store mode char
268 void sparc_emit_store_mode(const ir_node *node)
270 const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node);
271 ir_mode *mode = attr->load_store_mode;
272 int bits = get_mode_size_bits(mode);
276 } else if (bits == 8) {
278 } else if (bits == 64) {
286 * emit integer signed/unsigned prefix char
288 void sparc_emit_mode_sign_prefix(const ir_node *node)
290 ir_mode *mode = get_irn_mode(node);
291 bool is_signed = mode_is_signed(mode);
292 be_emit_string(is_signed ? "s" : "u");
295 static void emit_fp_suffix(const ir_mode *mode)
297 unsigned bits = get_mode_size_bits(mode);
298 assert(mode_is_float(mode));
302 } else if (bits == 64) {
304 } else if (bits == 128) {
307 panic("invalid FP mode");
311 void sparc_emit_fp_conv_source(const ir_node *node)
313 const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(node);
314 emit_fp_suffix(attr->src_mode);
317 void sparc_emit_fp_conv_destination(const ir_node *node)
319 const sparc_fp_conv_attr_t *attr = get_sparc_fp_conv_attr_const(node);
320 emit_fp_suffix(attr->dest_mode);
324 * emits the FP mode suffix char
326 void sparc_emit_fp_mode_suffix(const ir_node *node)
328 const sparc_fp_attr_t *attr = get_sparc_fp_attr_const(node);
329 emit_fp_suffix(attr->fp_mode);
332 static ir_node *get_jump_target(const ir_node *jump)
334 return get_irn_link(jump);
338 * Returns the target label for a control flow node.
340 static void sparc_emit_cfop_target(const ir_node *node)
342 ir_node *block = get_jump_target(node);
343 be_gas_emit_block_name(block);
346 static int get_sparc_Call_dest_addr_pos(const ir_node *node)
348 return get_irn_arity(node)-1;
351 static bool ba_is_fallthrough(const ir_node *node)
353 ir_node *block = get_nodes_block(node);
354 ir_node *next_block = get_irn_link(block);
355 return get_irn_link(node) == next_block;
358 static bool is_no_instruction(const ir_node *node)
360 /* copies are nops if src_reg == dest_reg */
361 if (be_is_Copy(node) || be_is_CopyKeep(node)) {
362 const arch_register_t *src_reg = get_in_reg(node, 0);
363 const arch_register_t *dest_reg = get_out_reg(node, 0);
365 if (src_reg == dest_reg)
368 /* Ba is not emitted if it is a simple fallthrough */
369 if (is_sparc_Ba(node) && ba_is_fallthrough(node))
372 return be_is_Keep(node) || be_is_Barrier(node) || be_is_Start(node)
376 static bool has_delay_slot(const ir_node *node)
378 if (is_sparc_Ba(node) && ba_is_fallthrough(node))
381 return is_sparc_Bicc(node) || is_sparc_fbfcc(node) || is_sparc_Ba(node)
382 || is_sparc_SwitchJmp(node) || is_sparc_Call(node)
383 || is_sparc_SDiv(node) || is_sparc_UDiv(node);
386 /** returns true if the emitter for this sparc node can produce more than one
387 * actual sparc instruction.
388 * Usually it is a bad sign if we have to add instructions here. We should
389 * rather try to get them lowered down. So we can actually put them into
390 * delay slots and make them more accessible to the scheduler.
392 static bool emits_multiple_instructions(const ir_node *node)
394 if (has_delay_slot(node))
397 return is_sparc_Mulh(node) || is_sparc_SDiv(node) || is_sparc_UDiv(node)
398 || be_is_MemPerm(node) || be_is_Perm(node) || be_is_Return(node);
402 * search for an instruction that can fill the delay slot of @p node
404 static const ir_node *pick_delay_slot_for(const ir_node *node)
406 const ir_node *check = node;
407 const ir_node *schedpoint = node;
409 /* currently we don't track which registers are still alive, so we can't
410 * pick any other instructions other than the one directly preceding */
411 static const unsigned PICK_DELAY_SLOT_MAX_DISTANCE = 1;
413 assert(has_delay_slot(node));
415 if (is_sparc_Call(node)) {
416 const sparc_attr_t *attr = get_sparc_attr_const(node);
417 ir_entity *entity = attr->immediate_value_entity;
418 if (entity != NULL) {
419 check = NULL; /* pick any instruction, dependencies on Call
422 /* we only need to check the value for the call destination */
423 check = get_irn_n(node, get_sparc_Call_dest_addr_pos(node));
426 /* the Call also destroys the value of %o7, but since this is currently
427 * marked as ignore register in the backend, it should never be used by
428 * the instruction in the delay slot. */
433 while (sched_has_prev(schedpoint)) {
434 schedpoint = sched_prev(schedpoint);
436 if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE)
439 if (has_delay_slot(schedpoint))
442 /* skip things which don't really result in instructions */
443 if (is_no_instruction(schedpoint))
446 if (emits_multiple_instructions(schedpoint))
449 /* allowed for delayslot: any instruction which is not necessary to
450 * compute an input to the branch. */
452 && heights_reachable_in_block(heights, check, schedpoint))
455 /* found something */
463 * Emits code for stack space management
465 static void emit_be_IncSP(const ir_node *irn)
467 int offs = -be_get_IncSP_offset(irn);
472 /* SPARC stack grows downwards */
474 be_emit_cstring("\tsub ");
477 be_emit_cstring("\tadd ");
480 sparc_emit_source_register(irn, 0);
481 be_emit_irprintf(", %d", offs);
482 be_emit_cstring(", ");
483 sparc_emit_dest_register(irn, 0);
484 be_emit_finish_line_gas(irn);
488 * emits code for save instruction with min. required stack space
490 static void emit_sparc_Save(const ir_node *irn)
492 const sparc_save_attr_t *save_attr = get_sparc_save_attr_const(irn);
493 be_emit_cstring("\tsave ");
494 sparc_emit_source_register(irn, 0);
495 be_emit_irprintf(", %d, ", -save_attr->initial_stacksize);
496 sparc_emit_dest_register(irn, 0);
497 be_emit_finish_line_gas(irn);
501 * emits code for mulh
503 static void emit_sparc_Mulh(const ir_node *irn)
505 be_emit_cstring("\t");
506 sparc_emit_mode_sign_prefix(irn);
507 be_emit_cstring("mul ");
509 sparc_emit_source_register(irn, 0);
510 be_emit_cstring(", ");
511 sparc_emit_reg_or_imm(irn, 1);
512 be_emit_cstring(", ");
513 sparc_emit_dest_register(irn, 0);
514 be_emit_finish_line_gas(irn);
516 // our result is in the y register now
517 // we just copy it to the assigned target reg
518 be_emit_cstring("\tmov %y, ");
519 sparc_emit_dest_register(irn, 0);
520 be_emit_finish_line_gas(irn);
523 static void fill_delay_slot(void)
525 if (delay_slot_filler != NULL) {
526 sparc_emit_node(delay_slot_filler);
527 delay_slot_filler = NULL;
529 be_emit_cstring("\tnop\n");
530 be_emit_write_line();
534 static void emit_sparc_Div(const ir_node *node, bool is_signed)
536 /* can we get the delay count of the wr instruction somewhere? */
537 unsigned wry_delay_count = 3;
540 be_emit_cstring("\twr ");
541 sparc_emit_source_register(node, 0);
542 be_emit_cstring(", 0, %y");
543 be_emit_finish_line_gas(node);
545 for (i = 0; i < wry_delay_count; ++i) {
549 be_emit_irprintf("\t%s ", is_signed ? "sdiv" : "udiv");
550 sparc_emit_source_register(node, 1);
551 be_emit_cstring(", ");
552 sparc_emit_reg_or_imm(node, 2);
553 be_emit_cstring(", ");
554 sparc_emit_dest_register(node, 0);
555 be_emit_finish_line_gas(node);
558 static void emit_sparc_SDiv(const ir_node *node)
560 emit_sparc_Div(node, true);
563 static void emit_sparc_UDiv(const ir_node *node)
565 emit_sparc_Div(node, false);
569 * Emits code for return node
571 static void emit_be_Return(const ir_node *irn)
573 be_emit_cstring("\tret");
574 //be_emit_cstring("\tjmp %i7+8");
575 be_emit_finish_line_gas(irn);
576 be_emit_cstring("\trestore");
577 be_emit_finish_line_gas(irn);
581 * Emits code for Call node
583 static void emit_sparc_Call(const ir_node *node)
585 const sparc_attr_t *attr = get_sparc_attr_const(node);
586 ir_entity *entity = attr->immediate_value_entity;
588 be_emit_cstring("\tcall ");
589 if (entity != NULL) {
590 be_gas_emit_entity(entity);
591 if (attr->immediate_value != 0) {
592 be_emit_irprintf("%+d", attr->immediate_value);
594 be_emit_cstring(", 0");
596 int dest_addr = get_sparc_Call_dest_addr_pos(node);
597 sparc_emit_source_register(node, dest_addr);
599 be_emit_finish_line_gas(node);
605 * Emit code for Perm node
607 static void emit_be_Perm(const ir_node *irn)
609 be_emit_cstring("\txor ");
610 sparc_emit_source_register(irn, 1);
611 be_emit_cstring(", ");
612 sparc_emit_source_register(irn, 0);
613 be_emit_cstring(", ");
614 sparc_emit_source_register(irn, 0);
615 be_emit_finish_line_gas(NULL);
617 be_emit_cstring("\txor ");
618 sparc_emit_source_register(irn, 1);
619 be_emit_cstring(", ");
620 sparc_emit_source_register(irn, 0);
621 be_emit_cstring(", ");
622 sparc_emit_source_register(irn, 1);
623 be_emit_finish_line_gas(NULL);
625 be_emit_cstring("\txor ");
626 sparc_emit_source_register(irn, 1);
627 be_emit_cstring(", ");
628 sparc_emit_source_register(irn, 0);
629 be_emit_cstring(", ");
630 sparc_emit_source_register(irn, 0);
631 be_emit_finish_line_gas(irn);
634 static void emit_be_MemPerm(const ir_node *node)
639 ir_graph *irg = get_irn_irg(node);
640 be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
642 /* this implementation only works with frame pointers currently */
643 assert(layout->sp_relative == false);
645 /* TODO: this implementation is slower than necessary.
646 The longterm goal is however to avoid the memperm node completely */
648 memperm_arity = be_get_MemPerm_entity_arity(node);
649 // we use our local registers - so this is limited to 8 inputs !
650 if (memperm_arity > 8)
651 panic("memperm with more than 8 inputs not supported yet");
653 be_emit_irprintf("\tsub %%sp, %d, %%sp", memperm_arity*4);
654 be_emit_finish_line_gas(node);
656 for (i = 0; i < memperm_arity; ++i) {
657 ir_entity *entity = be_get_MemPerm_in_entity(node, i);
658 int offset = be_get_stack_entity_offset(layout, entity, 0);
661 be_emit_irprintf("\tst %%l%d, [%%sp%+d]", i, sp_change + SPARC_MIN_STACKSIZE);
662 be_emit_finish_line_gas(node);
664 /* load from entity */
665 be_emit_irprintf("\tld [%%fp%+d], %%l%d", offset, i);
666 be_emit_finish_line_gas(node);
670 for (i = memperm_arity-1; i >= 0; --i) {
671 ir_entity *entity = be_get_MemPerm_out_entity(node, i);
672 int offset = be_get_stack_entity_offset(layout, entity, 0);
676 /* store to new entity */
677 be_emit_irprintf("\tst %%l%d, [%%fp%+d]", i, offset);
678 be_emit_finish_line_gas(node);
679 /* restore register */
680 be_emit_irprintf("\tld [%%sp%+d], %%l%d", sp_change + SPARC_MIN_STACKSIZE, i);
681 be_emit_finish_line_gas(node);
684 be_emit_irprintf("\tadd %%sp, %d, %%sp", memperm_arity*4);
685 be_emit_finish_line_gas(node);
687 assert(sp_change == 0);
690 static void emit_sparc_FrameAddr(const ir_node *node)
692 const sparc_attr_t *attr = get_sparc_attr_const(node);
694 // no need to fix offset as we are adressing via the framepointer
695 if (attr->immediate_value >= 0) {
696 be_emit_cstring("\tadd ");
697 sparc_emit_source_register(node, 0);
698 be_emit_cstring(", ");
699 be_emit_irprintf("%ld", attr->immediate_value);
701 be_emit_cstring("\tsub ");
702 sparc_emit_source_register(node, 0);
703 be_emit_cstring(", ");
704 be_emit_irprintf("%ld", -attr->immediate_value);
707 be_emit_cstring(", ");
708 sparc_emit_dest_register(node, 0);
709 be_emit_finish_line_gas(node);
712 static const char *get_icc_unsigned(pn_Cmp pnc)
715 case pn_Cmp_False: return "bn";
716 case pn_Cmp_Eq: return "be";
717 case pn_Cmp_Lt: return "blu";
718 case pn_Cmp_Le: return "bleu";
719 case pn_Cmp_Gt: return "bgu";
720 case pn_Cmp_Ge: return "bgeu";
721 case pn_Cmp_Lg: return "bne";
722 case pn_Cmp_Leg: return "ba";
723 default: panic("Cmp has unsupported pnc");
727 static const char *get_icc_signed(pn_Cmp pnc)
730 case pn_Cmp_False: return "bn";
731 case pn_Cmp_Eq: return "be";
732 case pn_Cmp_Lt: return "bl";
733 case pn_Cmp_Le: return "ble";
734 case pn_Cmp_Gt: return "bg";
735 case pn_Cmp_Ge: return "bge";
736 case pn_Cmp_Lg: return "bne";
737 case pn_Cmp_Leg: return "ba";
738 default: panic("Cmp has unsupported pnc");
742 static const char *get_fcc(pn_Cmp pnc)
745 case pn_Cmp_False: return "fbn";
746 case pn_Cmp_Eq: return "fbe";
747 case pn_Cmp_Lt: return "fbl";
748 case pn_Cmp_Le: return "fble";
749 case pn_Cmp_Gt: return "fbg";
750 case pn_Cmp_Ge: return "fbge";
751 case pn_Cmp_Lg: return "fblg";
752 case pn_Cmp_Leg: return "fbo";
753 case pn_Cmp_Uo: return "fbu";
754 case pn_Cmp_Ue: return "fbue";
755 case pn_Cmp_Ul: return "fbul";
756 case pn_Cmp_Ule: return "fbule";
757 case pn_Cmp_Ug: return "fbug";
758 case pn_Cmp_Uge: return "fbuge";
759 case pn_Cmp_Ne: return "fbne";
760 case pn_Cmp_True: return "fba";
764 panic("invalid pnc");
767 typedef const char* (*get_cc_func)(pn_Cmp pnc);
769 static void emit_sparc_branch(const ir_node *node, get_cc_func get_cc)
771 const sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr_const(node);
772 pn_Cmp pnc = attr->pnc;
773 const ir_node *proj_true = NULL;
774 const ir_node *proj_false = NULL;
775 const ir_edge_t *edge;
776 const ir_node *block;
777 const ir_node *next_block;
779 foreach_out_edge(node, edge) {
780 ir_node *proj = get_edge_src_irn(edge);
781 long nr = get_Proj_proj(proj);
782 if (nr == pn_Cond_true) {
789 /* for now, the code works for scheduled and non-schedules blocks */
790 block = get_nodes_block(node);
792 /* we have a block schedule */
793 next_block = get_irn_link(block);
795 if (get_irn_link(proj_true) == next_block) {
796 /* exchange both proj's so the second one can be omitted */
797 const ir_node *t = proj_true;
799 proj_true = proj_false;
801 if (is_sparc_fbfcc(node)) {
802 pnc = get_negated_pnc(pnc, mode_F);
804 pnc = get_negated_pnc(pnc, mode_Iu);
808 /* emit the true proj */
809 be_emit_cstring("\t");
810 be_emit_string(get_cc(pnc));
812 sparc_emit_cfop_target(proj_true);
813 be_emit_finish_line_gas(proj_true);
817 if (get_irn_link(proj_false) == next_block) {
818 be_emit_cstring("\t/* fallthrough to ");
819 sparc_emit_cfop_target(proj_false);
820 be_emit_cstring(" */");
821 be_emit_finish_line_gas(proj_false);
823 be_emit_cstring("\tba ");
824 sparc_emit_cfop_target(proj_false);
825 be_emit_finish_line_gas(proj_false);
830 static void emit_sparc_Bicc(const ir_node *node)
832 const sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr_const(node);
833 bool is_unsigned = attr->is_unsigned;
834 emit_sparc_branch(node, is_unsigned ? get_icc_unsigned : get_icc_signed);
837 static void emit_sparc_fbfcc(const ir_node *node)
839 emit_sparc_branch(node, get_fcc);
842 static void emit_sparc_Ba(const ir_node *node)
844 if (ba_is_fallthrough(node)) {
845 be_emit_cstring("\t/* fallthrough to ");
846 sparc_emit_cfop_target(node);
847 be_emit_cstring(" */");
849 be_emit_cstring("\tba ");
850 sparc_emit_cfop_target(node);
851 be_emit_finish_line_gas(node);
854 be_emit_finish_line_gas(node);
857 static void emit_jump_table(const ir_node *node)
859 const sparc_switch_jmp_attr_t *attr = get_sparc_switch_jmp_attr_const(node);
860 long switch_min = LONG_MAX;
861 long switch_max = LONG_MIN;
862 long default_pn = attr->default_proj_num;
863 ir_entity *entity = attr->jump_table;
864 ir_node *default_block = NULL;
866 const ir_edge_t *edge;
870 /* go over all proj's and collect them */
871 foreach_out_edge(node, edge) {
872 ir_node *proj = get_edge_src_irn(edge);
873 long pn = get_Proj_proj(proj);
875 /* check for default proj */
876 if (pn == default_pn) {
877 assert(default_block == NULL); /* more than 1 default_pn? */
878 default_block = get_jump_target(proj);
880 switch_min = pn < switch_min ? pn : switch_min;
881 switch_max = pn > switch_max ? pn : switch_max;
884 length = (unsigned long) (switch_max - switch_min) + 1;
885 assert(switch_min < LONG_MAX || switch_max > LONG_MIN);
887 table = XMALLOCNZ(ir_node*, length);
888 foreach_out_edge(node, edge) {
889 ir_node *proj = get_edge_src_irn(edge);
890 long pn = get_Proj_proj(proj);
891 if (pn == default_pn)
894 table[pn - switch_min] = get_jump_target(proj);
898 be_gas_emit_switch_section(GAS_SECTION_RODATA);
899 be_emit_cstring("\t.align 4\n");
900 be_gas_emit_entity(entity);
901 be_emit_cstring(":\n");
902 for (i = 0; i < length; ++i) {
903 ir_node *block = table[i];
905 block = default_block;
906 be_emit_cstring("\t.long ");
907 be_gas_emit_block_name(block);
909 be_emit_write_line();
911 be_gas_emit_switch_section(GAS_SECTION_TEXT);
916 static void emit_sparc_SwitchJmp(const ir_node *node)
918 be_emit_cstring("\tjmp ");
919 sparc_emit_source_register(node, 0);
920 be_emit_finish_line_gas(node);
923 emit_jump_table(node);
926 static void emit_fmov(const ir_node *node, const arch_register_t *src_reg,
927 const arch_register_t *dst_reg)
929 be_emit_cstring("\tfmov ");
930 be_emit_string(arch_register_get_name(src_reg));
931 be_emit_cstring(", ");
932 be_emit_string(arch_register_get_name(dst_reg));
933 be_emit_finish_line_gas(node);
936 static const arch_register_t *get_next_fp_reg(const arch_register_t *reg)
938 unsigned index = reg->index;
939 assert(reg == &sparc_fp_regs[index]);
941 assert(index < N_sparc_fp_REGS);
942 return &sparc_fp_regs[index];
945 static void emit_be_Copy(const ir_node *node)
947 ir_mode *mode = get_irn_mode(node);
948 const arch_register_t *src_reg = get_in_reg(node, 0);
949 const arch_register_t *dst_reg = get_out_reg(node, 0);
951 if (src_reg == dst_reg)
954 if (mode_is_float(mode)) {
955 unsigned bits = get_mode_size_bits(mode);
956 int n = bits > 32 ? bits > 64 ? 3 : 1 : 0;
958 emit_fmov(node, src_reg, dst_reg);
959 for (i = 0; i < n; ++i) {
960 src_reg = get_next_fp_reg(src_reg);
961 dst_reg = get_next_fp_reg(dst_reg);
962 emit_fmov(node, src_reg, dst_reg);
964 } else if (mode_is_data(mode)) {
965 be_emit_cstring("\tmov ");
966 sparc_emit_source_register(node, 0);
967 be_emit_cstring(", ");
968 sparc_emit_dest_register(node, 0);
969 be_emit_finish_line_gas(node);
971 panic("emit_be_Copy: invalid mode");
975 static void emit_nothing(const ir_node *irn)
980 typedef void (*emit_func) (const ir_node *);
982 static inline void set_emitter(ir_op *op, emit_func sparc_emit_node)
984 op->ops.generic = (op_func)sparc_emit_node;
988 * Enters the emitter functions for handled nodes into the generic
989 * pointer of an opcode.
991 static void sparc_register_emitters(void)
993 /* first clear the generic function pointer for all ops */
994 clear_irp_opcodes_generic_func();
995 /* register all emitter functions defined in spec */
996 sparc_register_spec_emitters();
999 set_emitter(op_be_Copy, emit_be_Copy);
1000 set_emitter(op_be_CopyKeep, emit_be_Copy);
1001 set_emitter(op_be_IncSP, emit_be_IncSP);
1002 set_emitter(op_be_MemPerm, emit_be_MemPerm);
1003 set_emitter(op_be_Perm, emit_be_Perm);
1004 set_emitter(op_be_Return, emit_be_Return);
1005 set_emitter(op_sparc_Ba, emit_sparc_Ba);
1006 set_emitter(op_sparc_Bicc, emit_sparc_Bicc);
1007 set_emitter(op_sparc_Call, emit_sparc_Call);
1008 set_emitter(op_sparc_fbfcc, emit_sparc_fbfcc);
1009 set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
1010 set_emitter(op_sparc_Mulh, emit_sparc_Mulh);
1011 set_emitter(op_sparc_Save, emit_sparc_Save);
1012 set_emitter(op_sparc_SDiv, emit_sparc_SDiv);
1013 set_emitter(op_sparc_SwitchJmp, emit_sparc_SwitchJmp);
1014 set_emitter(op_sparc_UDiv, emit_sparc_UDiv);
1016 /* no need to emit anything for the following nodes */
1017 set_emitter(op_be_Barrier, emit_nothing);
1018 set_emitter(op_be_Keep, emit_nothing);
1019 set_emitter(op_be_Start, emit_nothing);
1020 set_emitter(op_Phi, emit_nothing);
1024 * Emits code for a node.
1026 static void sparc_emit_node(const ir_node *node)
1028 ir_op *op = get_irn_op(node);
1030 if (op->ops.generic) {
1031 emit_func func = (emit_func) op->ops.generic;
1032 be_dbg_set_dbg_info(get_irn_dbg_info(node));
1035 panic("No emit handler for node %+F (graph %+F)\n", node,
1040 static ir_node *find_next_delay_slot(ir_node *from)
1042 ir_node *schedpoint = from;
1043 while (!has_delay_slot(schedpoint)) {
1044 if (!sched_has_next(schedpoint))
1046 schedpoint = sched_next(schedpoint);
1052 * Walks over the nodes in a block connected by scheduling edges
1053 * and emits code for each node.
1055 static void sparc_emit_block(ir_node *block)
1058 ir_node *next_delay_slot;
1060 assert(is_Block(block));
1062 be_gas_emit_block_name(block);
1063 be_emit_cstring(":\n");
1064 be_emit_write_line();
1066 next_delay_slot = find_next_delay_slot(sched_first(block));
1067 if (next_delay_slot != NULL)
1068 delay_slot_filler = pick_delay_slot_for(next_delay_slot);
1070 sched_foreach(block, node) {
1071 if (node == delay_slot_filler) {
1075 sparc_emit_node(node);
1077 if (node == next_delay_slot) {
1078 assert(delay_slot_filler == NULL);
1079 next_delay_slot = find_next_delay_slot(sched_next(node));
1080 if (next_delay_slot != NULL)
1081 delay_slot_filler = pick_delay_slot_for(next_delay_slot);
1087 * Emits code for function start.
1089 static void sparc_emit_func_prolog(ir_graph *irg)
1091 ir_entity *ent = get_irg_entity(irg);
1092 be_gas_emit_function_prolog(ent, 4);
1093 be_emit_write_line();
1097 * Emits code for function end
1099 static void sparc_emit_func_epilog(ir_graph *irg)
1101 ir_entity *ent = get_irg_entity(irg);
1102 const char *irg_name = get_entity_ld_name(ent);
1103 be_emit_write_line();
1104 be_emit_irprintf("\t.size %s, .-%s\n", irg_name, irg_name);
1105 be_emit_cstring("# -- End ");
1106 be_emit_string(irg_name);
1107 be_emit_cstring("\n");
1108 be_emit_write_line();
1111 static void sparc_gen_labels(ir_node *block, void *env)
1114 int n = get_Block_n_cfgpreds(block);
1117 for (n--; n >= 0; n--) {
1118 pred = get_Block_cfgpred(block, n);
1119 set_irn_link(pred, block); // link the pred of a block (which is a jmp)
1123 void sparc_emit_routine(ir_graph *irg)
1125 ir_entity *entity = get_irg_entity(irg);
1126 ir_node **block_schedule;
1130 be_gas_elf_type_char = '#';
1131 be_gas_object_file_format = OBJECT_FILE_FORMAT_ELF_SPARC;
1133 heights = heights_new(irg);
1135 /* register all emitter functions */
1136 sparc_register_emitters();
1137 be_dbg_method_begin(entity);
1139 /* create the block schedule. For now, we don't need it earlier. */
1140 block_schedule = be_create_block_schedule(irg);
1142 sparc_emit_func_prolog(irg);
1143 irg_block_walk_graph(irg, sparc_gen_labels, NULL, NULL);
1145 /* inject block scheduling links & emit code of each block */
1146 n = ARR_LEN(block_schedule);
1147 for (i = 0; i < n; ++i) {
1148 ir_node *block = block_schedule[i];
1149 ir_node *next_block = i+1 < n ? block_schedule[i+1] : NULL;
1150 set_irn_link(block, next_block);
1153 for (i = 0; i < n; ++i) {
1154 ir_node *block = block_schedule[i];
1155 if (block == get_irg_end_block(irg))
1157 sparc_emit_block(block);
1160 /* emit function epilog */
1161 sparc_emit_func_epilog(irg);
1163 heights_free(heights);
1166 void sparc_init_emitter(void)
1168 FIRM_DBG_REGISTER(dbg, "firm.be.sparc.emit");