X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fsparc%2Fsparc_emitter.c;h=ac2bb1d99c48aa6d8b3bdcdccaaea9ece9716b18;hb=102e656aacc831319f5677cb4d024df1b96fe39e;hp=268215bd74fa920b13492a57d8f6dcf950e0e881;hpb=6e5fd745c70d70f56fbe65df64983675897eb304;p=libfirm diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index 268215bd7..ac2bb1d99 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -191,7 +191,7 @@ void sparc_emit_reg_or_imm(const ir_node *node, int pos) static bool is_stack_pointer_relative(const ir_node *node) { - const arch_register_t *sp = &sparc_gp_regs[REG_SP]; + const arch_register_t *sp = &sparc_registers[REG_SP]; return (is_sparc_St(node) && get_in_reg(node, n_sparc_St_ptr) == sp) || (is_sparc_Ld(node) && get_in_reg(node, n_sparc_Ld_ptr) == sp); } @@ -332,7 +332,7 @@ void sparc_emit_fp_mode_suffix(const ir_node *node) static ir_node *get_jump_target(const ir_node *jump) { - return get_irn_link(jump); + return (ir_node*)get_irn_link(jump); } /** @@ -352,7 +352,7 @@ static int get_sparc_Call_dest_addr_pos(const ir_node *node) static bool ba_is_fallthrough(const ir_node *node) { ir_node *block = get_nodes_block(node); - ir_node *next_block = get_irn_link(block); + ir_node *next_block = (ir_node*)get_irn_link(block); return get_irn_link(node) == next_block; } @@ -366,6 +366,8 @@ static bool is_no_instruction(const ir_node *node) if (src_reg == dest_reg) return true; } + if (be_is_IncSP(node) && be_get_IncSP_offset(node) == 0) + return true; /* Ba is not emitted if it is a simple fallthrough */ if (is_sparc_Ba(node) && ba_is_fallthrough(node)) return true; @@ -381,7 +383,8 @@ static bool has_delay_slot(const ir_node *node) return is_sparc_Bicc(node) || is_sparc_fbfcc(node) || is_sparc_Ba(node) || is_sparc_SwitchJmp(node) || is_sparc_Call(node) - || is_sparc_SDiv(node) || is_sparc_UDiv(node); + || is_sparc_SDiv(node) || is_sparc_UDiv(node) + || be_is_Return(node); } /** returns true if the emitter for this sparc node can produce more than one @@ -396,7 +399,7 @@ static bool emits_multiple_instructions(const ir_node *node) return true; return is_sparc_Mulh(node) || is_sparc_SDiv(node) || is_sparc_UDiv(node) - || be_is_MemPerm(node) || be_is_Perm(node) || be_is_Return(node); + || be_is_MemPerm(node) || be_is_Perm(node); } /** @@ -427,6 +430,20 @@ static const ir_node *pick_delay_slot_for(const ir_node *node) /* the Call also destroys the value of %o7, but since this is currently * marked as ignore register in the backend, it should never be used by * the instruction in the delay slot. */ + } else if (be_is_Return(node)) { + /* we only have to check the jump destination value */ + int arity = get_irn_arity(node); + int i; + + check = NULL; + for (i = 0; i < arity; ++i) { + ir_node *in = get_irn_n(node, i); + const arch_register_t *reg = arch_get_irn_register(in); + if (reg == &sparc_registers[REG_O7]) { + check = skip_Proj(in); + break; + } + } } else { check = node; } @@ -434,9 +451,6 @@ static const ir_node *pick_delay_slot_for(const ir_node *node) while (sched_has_prev(schedpoint)) { schedpoint = sched_prev(schedpoint); - if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE) - break; - if (has_delay_slot(schedpoint)) break; @@ -444,6 +458,9 @@ static const ir_node *pick_delay_slot_for(const ir_node *node) if (is_no_instruction(schedpoint)) continue; + if (tries++ >= PICK_DELAY_SLOT_MAX_DISTANCE) + break; + if (emits_multiple_instructions(schedpoint)) continue; @@ -485,19 +502,6 @@ static void emit_be_IncSP(const ir_node *irn) be_emit_finish_line_gas(irn); } -/** - * emits code for save instruction with min. required stack space - */ -static void emit_sparc_Save(const ir_node *irn) -{ - const sparc_save_attr_t *save_attr = get_sparc_save_attr_const(irn); - be_emit_cstring("\tsave "); - sparc_emit_source_register(irn, 0); - be_emit_irprintf(", %d, ", -save_attr->initial_stacksize); - sparc_emit_dest_register(irn, 0); - be_emit_finish_line_gas(irn); -} - /** * emits code for mulh */ @@ -566,18 +570,6 @@ static void emit_sparc_UDiv(const ir_node *node) emit_sparc_Div(node, false); } -/** - * Emits code for return node - */ -static void emit_be_Return(const ir_node *irn) -{ - be_emit_cstring("\tret"); - //be_emit_cstring("\tjmp %i7+8"); - be_emit_finish_line_gas(irn); - be_emit_cstring("\trestore"); - be_emit_finish_line_gas(irn); -} - /** * Emits code for Call node */ @@ -688,6 +680,24 @@ static void emit_be_MemPerm(const ir_node *node) assert(sp_change == 0); } +static void emit_be_Return(const ir_node *node) +{ + const char *destreg = "%o7"; + + /* hack: we don't explicitely model register changes because of the + * restore node. So we have to do it manually here */ + if (delay_slot_filler != NULL && + (is_sparc_Restore(delay_slot_filler) + || is_sparc_RestoreZero(delay_slot_filler))) { + destreg = "%i7"; + } + be_emit_cstring("\tjmp "); + be_emit_string(destreg); + be_emit_cstring("+8"); + be_emit_finish_line_gas(node); + fill_delay_slot(); +} + static void emit_sparc_FrameAddr(const ir_node *node) { const sparc_attr_t *attr = get_sparc_attr_const(node); @@ -791,7 +801,7 @@ static void emit_sparc_branch(const ir_node *node, get_cc_func get_cc) block = get_nodes_block(node); /* we have a block schedule */ - next_block = get_irn_link(block); + next_block = (ir_node*)get_irn_link(block); if (get_irn_link(proj_true) == next_block) { /* exchange both proj's so the second one can be omitted */ @@ -932,9 +942,9 @@ static void emit_sparc_SwitchJmp(const ir_node *node) static void emit_fmov(const ir_node *node, const arch_register_t *src_reg, const arch_register_t *dst_reg) { - be_emit_cstring("\tfmov "); + be_emit_cstring("\tfmovs %"); be_emit_string(arch_register_get_name(src_reg)); - be_emit_cstring(", "); + be_emit_cstring(", %"); be_emit_string(arch_register_get_name(dst_reg)); be_emit_finish_line_gas(node); } @@ -942,10 +952,10 @@ static void emit_fmov(const ir_node *node, const arch_register_t *src_reg, static const arch_register_t *get_next_fp_reg(const arch_register_t *reg) { unsigned index = reg->index; - assert(reg == &sparc_fp_regs[index]); + assert(reg == &sparc_registers[index]); index++; - assert(index < N_sparc_fp_REGS); - return &sparc_fp_regs[index]; + assert(index - REG_F0 < N_sparc_fp_REGS); + return &sparc_registers[index]; } static void emit_be_Copy(const ir_node *node) @@ -1014,7 +1024,6 @@ static void sparc_register_emitters(void) set_emitter(op_sparc_fbfcc, emit_sparc_fbfcc); set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr); set_emitter(op_sparc_Mulh, emit_sparc_Mulh); - set_emitter(op_sparc_Save, emit_sparc_Save); set_emitter(op_sparc_SDiv, emit_sparc_SDiv); set_emitter(op_sparc_SwitchJmp, emit_sparc_SwitchJmp); set_emitter(op_sparc_UDiv, emit_sparc_UDiv); @@ -1038,7 +1047,7 @@ static void sparc_emit_node(const ir_node *node) be_dbg_set_dbg_info(get_irn_dbg_info(node)); (*func) (node); } else { - panic("No emit handler for node %+F (graph %+F)\n", node, + panic("No emit handler for node %+F (graph %+F)\n", node, current_ir_graph); } }