📄 avr.c
字号:
if (cum->nregs && bytes <= cum->nregs) return gen_rtx (REG, mode, cum->regno - bytes); return NULL_RTX;}/* Update the summarizer variable CUM to advance past an argument in the argument list. */ voidfunction_arg_advance (cum, mode, type, named) CUMULATIVE_ARGS *cum; /* current arg information */ enum machine_mode mode; /* current arg mode */ tree type; /* type of the argument or 0 if lib support */ int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */{ int bytes = avr_num_arg_regs (mode, type); cum->nregs -= bytes; cum->regno -= bytes; if (cum->nregs <= 0) { cum->nregs = 0; cum->regno = FIRST_CUM_REG; }}/*********************************************************************** Functions for outputting various mov's for a various modes************************************************************************/const char *output_movqi (insn, operands, l) rtx insn; rtx operands[]; int *l;{ int dummy; rtx dest = operands[0]; rtx src = operands[1]; int *real_l = l; if (!l) l = &dummy; *l = 1; if (register_operand (dest, QImode)) { if (register_operand (src, QImode)) /* mov r,r */ { if (test_hard_reg_class (STACK_REG, dest)) return AS2 (out,%0,%1); else if (test_hard_reg_class (STACK_REG, src)) return AS2 (in,%0,%1); return AS2 (mov,%0,%1); } else if (CONSTANT_P (src)) { if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */ return AS2 (ldi,%0,lo8(%1)); if (GET_CODE (src) == CONST_INT) { if (src == const0_rtx) /* mov r,L */ return AS1 (clr,%0); else if (src == const1_rtx) { if (reg_was_0 (insn, dest)) return AS1 (inc,%0 ; reg_was_0); *l = 2; return (AS1 (clr,%0) CR_TAB AS1 (inc,%0)); } else if (src == constm1_rtx) { /* Immediate constants -1 to any register */ if (reg_was_0 (insn, dest)) return AS1 (dec,%0 ; reg_was_0); *l = 2; return (AS1 (clr,%0) CR_TAB AS1 (dec,%0)); } else { int bit_nr = exact_log2 (INTVAL (src)); if (bit_nr >= 0) { if (reg_was_0 (insn, dest)) { *l = 2; if (!real_l) output_asm_insn ("set ; reg_was_0", operands); } else { *l = 3; if (!real_l) output_asm_insn ((AS1 (clr,%0) CR_TAB "set"), operands); } if (!real_l) avr_output_bld (operands, bit_nr); return ""; } } } /* Last resort, larger than loading from memory. */ *l = 4; return (AS2 (mov,__tmp_reg__,r31) CR_TAB AS2 (ldi,r31,lo8(%1)) CR_TAB AS2 (mov,%0,r31) CR_TAB AS2 (mov,r31,__tmp_reg__)); } else if (GET_CODE (src) == MEM) return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */ } else if (GET_CODE (dest) == MEM) { const char *template; if (src == const0_rtx) operands[1] = zero_reg_rtx; template = out_movqi_mr_r (insn, operands, real_l); if (!real_l) output_asm_insn (template, operands); operands[1] = src; } return "";}const char *output_movhi (insn, operands, l) rtx insn; rtx operands[]; int *l;{ int dummy; rtx dest = operands[0]; rtx src = operands[1]; int *real_l = l; if (!l) l = &dummy; if (register_operand (dest, HImode)) { if (register_operand (src, HImode)) /* mov r,r */ { if (test_hard_reg_class (STACK_REG, dest)) { if (TARGET_TINY_STACK) { *l = 1; return AS2 (out,__SP_L__,%A1); } else if (TARGET_NO_INTERRUPTS) { *l = 2; return (AS2 (out,__SP_H__,%B1) CR_TAB AS2 (out,__SP_L__,%A1)); } *l = 5; return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB "cli" CR_TAB AS2 (out,__SP_H__,%B1) CR_TAB AS2 (out,__SREG__,__tmp_reg__) CR_TAB AS2 (out,__SP_L__,%A1)); } else if (test_hard_reg_class (STACK_REG, src)) { *l = 2; return (AS2 (in,%A0,__SP_L__) CR_TAB AS2 (in,%B0,__SP_H__)); } if (AVR_ENHANCED) { *l = 1; return (AS2 (movw,%0,%1)); } if (true_regnum (dest) > true_regnum (src)) { *l = 2; return (AS2 (mov,%B0,%B1) CR_TAB AS2 (mov,%A0,%A1)); } else { *l = 2; return (AS2 (mov,%A0,%A1) CR_TAB AS2 (mov,%B0,%B1)); } } else if (CONSTANT_P (src)) { if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */ { if (byte_immediate_operand (src, HImode) && reg_was_0 (insn, dest)) { *l = 1; return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0)); } *l = 2; return (AS2 (ldi,%A0,lo8(%1)) CR_TAB AS2 (ldi,%B0,hi8(%1))); } if (GET_CODE (src) == CONST_INT) { if (src == const0_rtx) /* mov r,L */ { *l = 2; return (AS1 (clr,%A0) CR_TAB AS1 (clr,%B0)); } else if (src == const1_rtx) { if (reg_was_0 (insn, dest)) { *l = 1; return AS1 (inc,%0 ; reg_was_0); } *l = 3; return (AS1 (clr,%A0) CR_TAB AS1 (clr,%B0) CR_TAB AS1 (inc,%A0)); } else if (src == constm1_rtx) { /* Immediate constants -1 to any register */ if (reg_was_0 (insn, dest)) { *l = 2; return (AS1 (dec,%A0 ; reg_was_0) CR_TAB AS1 (dec,%B0)); } *l = 3; return (AS1 (clr,%0) CR_TAB AS1 (dec,%A0) CR_TAB AS2 (mov,%B0,%A0)); } else { int bit_nr = exact_log2 (INTVAL (src)); if (bit_nr >= 0) { if (reg_was_0 (insn, dest)) { *l = 2; if (!real_l) output_asm_insn ("set ; reg_was_0", operands); } else { *l = 4; if (!real_l) output_asm_insn ((AS1 (clr,%A0) CR_TAB AS1 (clr,%B0) CR_TAB "set"), operands); } if (!real_l) avr_output_bld (operands, bit_nr); return ""; } } if ((INTVAL (src) & 0xff) == 0) { *l = 5; return (AS2 (mov,__tmp_reg__,r31) CR_TAB AS1 (clr,%A0) CR_TAB AS2 (ldi,r31,hi8(%1)) CR_TAB AS2 (mov,%B0,r31) CR_TAB AS2 (mov,r31,__tmp_reg__)); } else if ((INTVAL (src) & 0xff00) == 0) { *l = 5; return (AS2 (mov,__tmp_reg__,r31) CR_TAB AS2 (ldi,r31,lo8(%1)) CR_TAB AS2 (mov,%A0,r31) CR_TAB AS1 (clr,%B0) CR_TAB AS2 (mov,r31,__tmp_reg__)); } } /* Last resort, equal to loading from memory. */ *l = 6; return (AS2 (mov,__tmp_reg__,r31) CR_TAB AS2 (ldi,r31,lo8(%1)) CR_TAB AS2 (mov,%A0,r31) CR_TAB AS2 (ldi,r31,hi8(%1)) CR_TAB AS2 (mov,%B0,r31) CR_TAB AS2 (mov,r31,__tmp_reg__)); } else if (GET_CODE (src) == MEM) return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */ } else if (GET_CODE (dest) == MEM) { const char *template; if (src == const0_rtx) operands[1] = zero_reg_rtx; template = out_movhi_mr_r (insn, operands, real_l); if (!real_l) output_asm_insn (template, operands); operands[1] = src; return ""; } fatal_insn ("invalid insn:", insn); return "";}const char *out_movqi_r_mr (insn, op, l) rtx insn; rtx op[]; int *l; /* instruction length */{ rtx dest = op[0]; rtx src = op[1]; rtx x = XEXP (src, 0); int dummy; if (!l) l = &dummy; if (CONSTANT_ADDRESS_P (x)) { if (avr_io_address_p (x, 1)) { *l = 1; return AS2 (in,%0,%1-0x20); } *l = 2; return AS2 (lds,%0,%1); } /* memory access by reg+disp */ else if (GET_CODE (x) == PLUS && REG_P (XEXP (x,0)) && GET_CODE (XEXP (x,1)) == CONST_INT) { if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63) { int disp = INTVAL (XEXP (x,1)); if (REGNO (XEXP (x,0)) != REG_Y) fatal_insn ("incorrect insn:",insn); if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))) return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB AS2 (ldd,%0,Y+63) CR_TAB AS2 (sbiw,r28,%o1-63)); return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB AS2 (sbci,r29,hi8(-%o1)) CR_TAB AS2 (ld,%0,Y) CR_TAB AS2 (subi,r28,lo8(%o1)) CR_TAB AS2 (sbci,r29,hi8(%o1))); } else if (REGNO (XEXP (x,0)) == REG_X) { /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude it but I have this situation with extremal optimizing options. */ if (reg_overlap_mentioned_p (dest, XEXP (x,0)) || reg_unused_after (insn, XEXP (x,0))) return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB AS2 (ld,%0,X)); return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB AS2 (ld,%0,X) CR_TAB AS2 (sbiw,r26,%o1)); } *l = 1; return AS2 (ldd,%0,%1); } *l = 1; return AS2 (ld,%0,%1);}const char *out_movhi_r_mr (insn, op, l) rtx insn; rtx op[]; int *l; /* instruction length */{ rtx dest = op[0]; rtx src = op[1]; rtx base = XEXP (src, 0); int reg_dest = true_regnum (dest); int reg_base = true_regnum (base); int tmp; if (!l) l = &tmp; if (reg_base > 0) { if (reg_dest == reg_base) /* R = (R) */ { *l = 3; return (AS2 (ld,__tmp_reg__,%1+) CR_TAB AS2 (ld,%B0,%1) CR_TAB AS2 (mov,%A0,__tmp_reg__)); } else if (reg_base == REG_X) /* (R26) */ { if (reg_unused_after (insn, base)) { *l = 2; return (AS2 (ld,%A0,X+) CR_TAB AS2 (ld,%B0,X)); } *l = 3; return (AS2 (ld,%A0,X+) CR_TAB AS2 (ld,%B0,X) CR_TAB AS2 (sbiw,r26,1)); } else /* (R) */ { *l = 2; return (AS2 (ld,%A0,%1) CR_TAB AS2 (ldd,%B0,%1+1)); } } else if (GET_CODE (base) == PLUS) /* (R + i) */ { int disp = INTVAL (XEXP (base, 1)); int reg_base = true_regnum (XEXP (base, 0)); if (disp > MAX_LD_OFFSET (GET_MODE (src))) { if (REGNO (XEXP (base, 0)) != REG_Y) fatal_insn ("incorrect insn:",insn); if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))) return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB AS2 (ldd,%A0,Y+62) CR_TAB AS2 (ldd,%B0,Y+63) CR_TAB AS2 (sbiw,r28,%o1-62)); return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB AS2 (sbci,r29,hi8(-%o1)) CR_TAB AS2 (ld,%A0,Y) CR_TAB AS2 (ldd,%B0,Y+1) CR_TAB AS2 (subi,r28,lo8(%o1)) CR_TAB AS2 (sbci,r29,hi8(%o1))); } if (reg_base == REG_X) { /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude it but I have this situation with extremal optimization options. */ *l = 4; if (reg_base == reg_dest) return (AS2 (adiw,r26,%o1) CR_TAB AS2 (ld,__tmp_reg__,X+) CR_TAB AS2 (ld,%B0,X) CR_TAB AS2 (mov,%A0,__tmp_reg__)); return (AS2 (adiw,r26,%o1) CR_TAB AS2 (ld,%A0,X+) CR_TAB AS2 (ld,%B0,X) CR_TAB AS2 (sbiw,r26,%o1+1)); } if (reg_base == reg_dest) { *l = 3; return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB AS2 (ldd,%B0,%B1) CR_TAB AS2 (mov,%A0,__tmp_reg__)); } *l = 2; return (AS2 (ldd,%A0,%A1) CR_TAB AS2 (ldd,%B0,%B1)); } else if (GET_CODE (base) == PRE_DEC) /* (--R) */ { if (reg_overlap_mentioned_p (dest, XEXP (base, 0))) fatal_insn ("incorrect insn:", insn); *l = 2; return (AS2 (ld,%B0,%1) CR_TAB AS2 (ld,%A0,%1));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -