📄 avr.c
字号:
if (do_save) { fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB); size++; } if (do_cli) { fprintf (file, "cli" CR_TAB); size++; } /* Do SPH first - maybe this will disable interrupts for one instruction someday (a suggestion has been sent to avr@atmel.com for consideration in future devices - that would make -mno-interrupts always safe). */ if (do_sph) { fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB); size++; } /* Set/restore the I flag now - interrupts will be really enabled only after the next instruction. This is not clearly documented, but believed to be true for all AVR devices. */ if (do_save) { fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB); size++; } else if (do_sei) { fprintf (file, "sei" CR_TAB); size++; } fprintf (file, AS2 (out, __SP_L__, r28) "\n"); return size;}/* Output function prologue */static voidavr_output_function_prologue (file, size) FILE *file; HOST_WIDE_INT size;{ int reg; int interrupt_func_p; int signal_func_p; int leaf_func_p; int main_p; int live_seq; int minimize; if (avr_naked_function_p (current_function_decl)) { fprintf (file, "/* prologue: naked */\n"); return; } interrupt_func_p = interrupt_function_p (current_function_decl); signal_func_p = signal_function_p (current_function_decl); leaf_func_p = leaf_function_p (); main_p = MAIN_NAME_P (DECL_NAME (current_function_decl)); live_seq = sequent_regs_live (); minimize = (TARGET_CALL_PROLOGUES && !interrupt_func_p && !signal_func_p && live_seq); last_insn_address = 0; jump_tables_size = 0; prologue_size = 0; fprintf (file, "/* prologue: frame size=%d */\n", size); if (interrupt_func_p) { fprintf (file,"\tsei\n"); ++prologue_size; } if (interrupt_func_p | signal_func_p) { fprintf (file, "\t" AS1 (push,__zero_reg__) CR_TAB AS1 (push,__tmp_reg__) CR_TAB AS2 (in,__tmp_reg__,__SREG__) CR_TAB AS1 (push,__tmp_reg__) CR_TAB AS1 (clr,__zero_reg__) "\n"); prologue_size += 5; } if (main_p) { fprintf (file, ("\t" AS2 (ldi,r28,lo8(%s - %d)) CR_TAB AS2 (ldi,r29,hi8(%s - %d)) CR_TAB AS2 (out,__SP_H__,r29) CR_TAB AS2 (out,__SP_L__,r28) "\n"), avr_init_stack, size, avr_init_stack, size); prologue_size += 4; } else if (minimize && (frame_pointer_needed || live_seq > 6)) { fprintf (file, ("\t" AS2 (ldi, r26, lo8(%d)) CR_TAB AS2 (ldi, r27, hi8(%d)) CR_TAB), size, size); fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB) ,current_function_name, current_function_name); prologue_size += 4; if (AVR_MEGA) { fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n", (18 - live_seq) * 2); prologue_size += 2; } else { fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n", (18 - live_seq) * 2); ++prologue_size; } fprintf (file, ".L_%s_body:\n", current_function_name); } else { for (reg = 0; reg < 32; ++reg) { if ((!leaf_func_p && (call_used_regs[reg] && (interrupt_func_p || signal_func_p) && !(reg == TMP_REGNO || reg == ZERO_REGNO))) || (regs_ever_live[reg] && (!call_used_regs[reg] || interrupt_func_p || signal_func_p) && ! (frame_pointer_needed && (reg == REG_Y || reg == (REG_Y+1))))) { fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]); ++prologue_size; } } if (frame_pointer_needed) { { fprintf (file, "\t" AS1 (push,r28) CR_TAB AS1 (push,r29) CR_TAB AS2 (in,r28,__SP_L__) CR_TAB AS2 (in,r29,__SP_H__) "\n"); prologue_size += 4; if (size) { fputs ("\t", file); prologue_size += out_adj_frame_ptr (file, size); if (interrupt_func_p) { prologue_size += out_set_stack_ptr (file, 1, 1); } else if (signal_func_p) { prologue_size += out_set_stack_ptr (file, 0, 0); } else { prologue_size += out_set_stack_ptr (file, -1, -1); } } } } } fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);}/* Output function epilogue */static voidavr_output_function_epilogue (file, size) FILE *file; HOST_WIDE_INT size;{ int reg; int interrupt_func_p; int signal_func_p; int leaf_func_p; int main_p; int function_size; int live_seq; int minimize; if (avr_naked_function_p (current_function_decl)) { fprintf (file, "/* epilogue: naked */\n"); return; } interrupt_func_p = interrupt_function_p (current_function_decl); signal_func_p = signal_function_p (current_function_decl); leaf_func_p = leaf_function_p (); main_p = MAIN_NAME_P (DECL_NAME (current_function_decl)); function_size = (INSN_ADDRESSES (INSN_UID (get_last_insn ())) - INSN_ADDRESSES (INSN_UID (get_insns ()))); function_size += jump_tables_size; live_seq = sequent_regs_live (); minimize = (TARGET_CALL_PROLOGUES && !interrupt_func_p && !signal_func_p && live_seq); epilogue_size = 0; fprintf (file, "/* epilogue: frame size=%d */\n", size); if (main_p) { fprintf (file, "__stop_progIi__:\n\trjmp __stop_progIi__\n"); ++epilogue_size; } else if (minimize && (frame_pointer_needed || live_seq > 4)) { fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq); ++epilogue_size; if (frame_pointer_needed) { epilogue_size += out_adj_frame_ptr (file, -size); } else { fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB AS2 (in , r29, __SP_H__) CR_TAB)); epilogue_size += 2; } if (AVR_MEGA) { fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n", (18 - live_seq) * 2); epilogue_size += 2; } else { fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n", (18 - live_seq) * 2); ++epilogue_size; } } else { if (frame_pointer_needed) { if (size) { fputs ("\t", file); epilogue_size += out_adj_frame_ptr (file, -size); if (interrupt_func_p | signal_func_p) { epilogue_size += out_set_stack_ptr (file, -1, 0); } else { epilogue_size += out_set_stack_ptr (file, -1, -1); } } fprintf (file, "\t" AS1 (pop,r29) CR_TAB AS1 (pop,r28) "\n"); epilogue_size += 2; } for (reg = 31; reg >= 0; --reg) { if ((!leaf_func_p && (call_used_regs[reg] && (interrupt_func_p || signal_func_p) && !(reg == TMP_REGNO || reg == ZERO_REGNO))) || (regs_ever_live[reg] && (!call_used_regs[reg] || interrupt_func_p || signal_func_p) && ! (frame_pointer_needed && (reg == REG_Y || reg == (REG_Y+1))))) { fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]); ++epilogue_size; } } if (interrupt_func_p | signal_func_p) { fprintf (file, "\t" AS1 (pop,__tmp_reg__) CR_TAB AS2 (out,__SREG__,__tmp_reg__) CR_TAB AS1 (pop,__tmp_reg__) CR_TAB AS1 (pop,__zero_reg__) "\n"); epilogue_size += 4; fprintf (file, "\treti\n"); } else fprintf (file, "\tret\n"); ++epilogue_size; } fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size); fprintf (file, "/* function %s size %d (%d) */\n", current_function_name, prologue_size + function_size + epilogue_size, function_size); commands_in_file += prologue_size + function_size + epilogue_size; commands_in_prologues += prologue_size; commands_in_epilogues += epilogue_size;}/* Return nonzero if X (an RTX) is a legitimate memory address on the target machine for a memory operand of mode MODE. */intlegitimate_address_p (mode, x, strict) enum machine_mode mode; rtx x; int strict;{ enum reg_class r = NO_REGS; if (TARGET_ALL_DEBUG) { fprintf (stderr, "mode: (%s) %s %s %s %s:", GET_MODE_NAME(mode), strict ? "(strict)": "", reload_completed ? "(reload_completed)": "", reload_in_progress ? "(reload_in_progress)": "", reg_renumber ? "(reg_renumber)" : ""); if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode) && reg_renumber ) fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)), true_regnum (XEXP (x, 0))); debug_rtx (x); } if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x) : REG_OK_FOR_BASE_NOSTRICT_P (x))) r = POINTER_REGS; else if (CONSTANT_ADDRESS_P (x)) r = ALL_REGS; else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0) { int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode); if (fit) { if (! strict || REGNO (XEXP (x,0)) == REG_Y || REGNO (XEXP (x,0)) == REG_Z) r = BASE_POINTER_REGS; if (XEXP (x,0) == frame_pointer_rtx || XEXP (x,0) == arg_pointer_rtx) r = BASE_POINTER_REGS; } else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx) r = POINTER_Y_REGS; } else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC) && REG_P (XEXP (x, 0)) && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0)) : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0)))) { r = POINTER_REGS; } if (TARGET_ALL_DEBUG) { fprintf (stderr, " ret = %c\n", r); } return r == NO_REGS ? 0 : (int)r;}/* Attempts to replace X with a valid memory address for an operand of mode MODE */rtxlegitimize_address (x, oldx, mode) rtx x; rtx oldx; enum machine_mode mode;{ x = oldx; if (TARGET_ALL_DEBUG) { fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode)); debug_rtx (oldx); } if (GET_CODE (oldx) == PLUS && REG_P (XEXP (oldx,0))) { if (REG_P (XEXP (oldx,1))) x = force_reg (GET_MODE (oldx), oldx); else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT) { int offs = INTVAL (XEXP (oldx,1)); if (frame_pointer_rtx != XEXP (oldx,0)) if (offs > MAX_LD_OFFSET (mode)) { if (TARGET_ALL_DEBUG) fprintf (stderr, "force_reg (big offset)\n"); x = force_reg (GET_MODE (oldx), oldx); } } } return x;}/* Return a pointer register name as a string */static const char *ptrreg_to_str (regno) int regno;{ switch (regno) { case REG_X: return "X"; case REG_Y: return "Y"; case REG_Z: return "Z"; default: abort (); } return NULL;}/* Return the condition name as a string. Used in conditional jump constructing */static const char *cond_string (code) enum rtx_code code;{ switch (code) { case NE: return "ne"; case EQ: return "eq"; case GE: if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE) return "pl"; else return "ge"; case LT: if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE) return "mi"; else return "lt"; case GEU: return "sh"; case LTU: return "lo"; default: abort (); }}/* Output ADDR to FILE as address */voidprint_operand_address (file, addr) FILE *file; rtx addr;{ switch (GET_CODE (addr)) { case REG: fprintf (file, ptrreg_to_str (REGNO (addr))); break; case PRE_DEC: fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0)))); break; case POST_INC: fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0)))); break; default: if (CONSTANT_ADDRESS_P (addr) && (SYMBOL_REF_FLAG (addr) || GET_CODE (addr) == LABEL_REF)) { fprintf (file, "pm("); output_addr_const (file,addr); fprintf (file ,")"); } else output_addr_const (file, addr); }}/* Output X as assembler operand to file FILE */ voidprint_operand (file, x, code) FILE *file; rtx x; int code;{ int abcd = 0; if (code >= 'A' && code <= 'D') abcd = code - 'A';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -