⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avr.md

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 MD
📖 第 1 页 / 共 5 页
字号:
;; -*- Mode: Scheme -*-;;   Machine description for GNU compiler,;;   for ATMEL AVR micro controllers.;;   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005;;   Free Software Foundation, Inc.;;   Contributed by Denis Chertykov (denisc@overta.ru);; This file is part of GCC.;; GCC is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; GCC is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GCC; see the file COPYING.  If not, write to;; the Free Software Foundation, 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA.;; Special characters after '%':;;  A  No effect (add 0).;;  B  Add 1 to REG number, MEM address or CONST_INT.;;  C  Add 2.;;  D  Add 3.;;  j  Branch condition.;;  k  Reverse branch condition.;;  o  Displacement for (mem (plus (reg) (const_int))) operands.;;  p  POST_INC or PRE_DEC address as a pointer (X, Y, Z);;  r  POST_INC or PRE_DEC address as a register (r26, r28, r30);;  ~  Output 'r' if not AVR_MEGA.;; UNSPEC usage:;;  0  Length of a string, see "strlenhi".;;  1  Read from a word address in program memory, see "casesi".;; Condition code settings.(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber"  (const_string "none"))(define_attr "type" "branch,branch1,arith,xcall"  (const_string "arith"))(define_attr "mcu_enhanced" "yes,no"  (const (if_then_else (symbol_ref "AVR_ENHANCED")		       (const_string "yes")		       (const_string "no"))))(define_attr "mcu_mega" "yes,no"  (const (if_then_else (symbol_ref "AVR_MEGA")		       (const_string "yes")		       (const_string "no"))))  ;; The size of instructions in bytes.;; XXX may depend from "cc"(define_attr "length" ""  (cond [(eq_attr "type" "branch")         (if_then_else (and (ge (minus (pc) (match_dup 0))                                (const_int -63))                            (le (minus (pc) (match_dup 0))                                (const_int 62)))                       (const_int 1)                       (if_then_else (and (ge (minus (pc) (match_dup 0))                                              (const_int -2045))                                          (le (minus (pc) (match_dup 0))                                              (const_int 2045)))                                     (const_int 2)                                     (const_int 3)))         (eq_attr "type" "branch1")         (if_then_else (and (ge (minus (pc) (match_dup 0))                                (const_int -62))                            (le (minus (pc) (match_dup 0))                                (const_int 61)))                       (const_int 2)                       (if_then_else (and (ge (minus (pc) (match_dup 0))                                              (const_int -2044))                                          (le (minus (pc) (match_dup 0))                                              (const_int 2043)))                                     (const_int 3)                                     (const_int 4)))	 (eq_attr "type" "xcall")	 (if_then_else (eq_attr "mcu_mega" "no")		       (const_int 1)		       (const_int 2))]        (const_int 2)))(define_insn "*pop1"  [(set (reg:HI 32) (plus:HI (reg:HI 32) (const_int 1)))]  ""  "pop __tmp_reg__"  [(set_attr "length" "1")])(define_insn "*pop2"  [(set (reg:HI 32) (plus:HI (reg:HI 32) (const_int 2)))]  ""  "pop __tmp_reg__	pop __tmp_reg__"  [(set_attr "length" "2")])(define_insn "*pop3"  [(set (reg:HI 32) (plus:HI (reg:HI 32) (const_int 3)))]  ""  "pop __tmp_reg__	pop __tmp_reg__ 	pop __tmp_reg__"  [(set_attr "length" "3")])(define_insn "*pop4"  [(set (reg:HI 32) (plus:HI (reg:HI 32) (const_int 4)))]  ""  "pop __tmp_reg__	pop __tmp_reg__	pop __tmp_reg__	pop __tmp_reg__"  [(set_attr "length" "4")])(define_insn "*pop5"  [(set (reg:HI 32) (plus:HI (reg:HI 32) (const_int 5)))]  ""  "pop __tmp_reg__	pop __tmp_reg__	pop __tmp_reg__	pop __tmp_reg__	pop __tmp_reg__"  [(set_attr "length" "5")])(define_insn "*pushqi"  [(set (mem:QI (post_dec (reg:HI 32)))        (match_operand:QI 0 "nonmemory_operand" "r,L"))]  "(operands[0] == const0_rtx || register_operand (operands[0], QImode))"  "@	push %0	push __zero_reg__"  [(set_attr "length" "1,1")])(define_insn "*pushhi"  [(set (mem:HI (post_dec (reg:HI 32)))        (match_operand:HI 0 "nonmemory_operand" "r,L"))]  "(operands[0] == const0_rtx || register_operand (operands[0], HImode))"  "@	push %B0\;push %A0	push __zero_reg__\;push __zero_reg__"  [(set_attr "length" "2,2")])(define_insn "*pushsi"  [(set (mem:SI (post_dec (reg:HI 32)))        (match_operand:SI 0 "nonmemory_operand" "r,L"))]  "(operands[0] == const0_rtx || register_operand (operands[0], SImode))"  "@	push %D0\;push %C0\;push %B0\;push %A0	push __zero_reg__\;push __zero_reg__\;push __zero_reg__\;push __zero_reg__"  [(set_attr "length" "4,4")])(define_insn "*pushsf"  [(set (mem:SF (post_dec (reg:HI 32)))        (match_operand:SF 0 "register_operand" "r"))]  ""  "push %D0	push %C0	push %B0	push %A0"  [(set_attr "length" "4")]);;========================================================================;; move byte;; The last alternative (any immediate constant to any register) is;; very expensive.  It should be optimized by peephole2 if a scratch;; register is available, but then that register could just as well be;; allocated for the variable we are loading.  But, most of NO_LD_REGS;; are call-saved registers, and most of LD_REGS are call-used registers,;; so this may still be a win for registers live across function calls.(define_expand "movqi"  [(set (match_operand:QI 0 "nonimmediate_operand" "")	(match_operand:QI 1 "general_operand" ""))]  ""  "/* One of the ops has to be in a register.  */   if (!register_operand(operand0, QImode)       && ! (register_operand(operand1, QImode) || const0_rtx == operand1))       operands[1] = copy_to_mode_reg(QImode, operand1);  ")(define_insn "*movqi"  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")	(match_operand:QI 1 "general_operand"       "r,i,rL,Qm,r,q,i"))]  "(register_operand (operands[0],QImode)    || register_operand (operands[1], QImode) || const0_rtx == operands[1])"  "* return output_movqi (insn, operands, NULL);"  [(set_attr "length" "1,1,5,5,1,1,4")   (set_attr "cc" "none,none,clobber,clobber,none,none,clobber")]);; This is used in peephole2 to optimize loading immediate constants;; if a scratch register from LD_REGS happens to be available.(define_insn "*reload_inqi"  [(set (match_operand:QI 0 "register_operand" "=l")	(match_operand:QI 1 "immediate_operand" "i"))   (clobber (match_operand:QI 2 "register_operand" "=&d"))]  "reload_completed"  "ldi %2,lo8(%1)	mov %0,%2"  [(set_attr "length" "2")   (set_attr "cc" "none")])(define_peephole2  [(match_scratch:QI 2 "d")   (set (match_operand:QI 0 "register_operand" "")	(match_operand:QI 1 "immediate_operand" ""))]  "(operands[1] != const0_rtx    && test_hard_reg_class (NO_LD_REGS, operands[0]))"  [(parallel [(set (match_dup 0) (match_dup 1))	      (clobber (match_dup 2))])]  "if (!avr_peep2_scratch_safe (operands[2]))     FAIL;");;============================================================================;; move word (16 bit)(define_expand "movhi"  [(set (match_operand:HI 0 "nonimmediate_operand" "")        (match_operand:HI 1 "general_operand"       ""))]  ""  "{   /* One of the ops has to be in a register.  */  if (!register_operand(operand0, HImode)      && !(register_operand(operand1, HImode) || const0_rtx == operands[1]))    {      operands[1] = copy_to_mode_reg(HImode, operand1);    }}")(define_peephole2  [(match_scratch:QI 2 "d")   (set (match_operand:HI 0 "register_operand" "")       (match_operand:HI 1 "immediate_operand" ""))]  "(operands[1] != const0_rtx    && test_hard_reg_class (NO_LD_REGS, operands[0]))"  [(parallel [(set (match_dup 0) (match_dup 1))	      (clobber (match_dup 2))])]  "if (!avr_peep2_scratch_safe (operands[2]))     FAIL;");; '*' because it is not used in rtl generation, only in above peephole(define_insn "*reload_inhi"  [(set (match_operand:HI 0 "register_operand" "=r")        (match_operand:HI 1 "immediate_operand" "i"))   (clobber (match_operand:QI 2 "register_operand" "=&d"))]  "reload_completed"  "* return output_reload_inhi (insn, operands, NULL);"  [(set_attr "length" "4")   (set_attr "cc" "none")])(define_insn "*movhi"  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,d,*r,q,r")        (match_operand:HI 1 "general_operand"       "r,m,rL,i,i,r,q"))]  "(register_operand (operands[0],HImode)    || register_operand (operands[1],HImode) || const0_rtx == operands[1])"  "* return output_movhi (insn, operands, NULL);"  [(set_attr "length" "2,6,7,2,6,5,2")   (set_attr "cc" "none,clobber,clobber,none,clobber,none,none")]);;==========================================================================;; move double word (32 bit)(define_expand "movsi"  [(set (match_operand:SI 0 "nonimmediate_operand" "")        (match_operand:SI 1 "general_operand"  ""))]  ""  "{  /* One of the ops has to be in a register.  */  if (!register_operand (operand0, SImode)      && !(register_operand (operand1, SImode) || const0_rtx == operand1))    {      operands[1] = copy_to_mode_reg (SImode, operand1);    }}")(define_peephole2  [(match_scratch:QI 2 "d")   (set (match_operand:SI 0 "register_operand" "")       (match_operand:SI 1 "immediate_operand" ""))]  "(operands[1] != const0_rtx    && test_hard_reg_class (NO_LD_REGS, operands[0]))"  [(parallel [(set (match_dup 0) (match_dup 1))	      (clobber (match_dup 2))])]  "if (!avr_peep2_scratch_safe (operands[2]))     FAIL;");; '*' because it is not used in rtl generation.(define_insn "*reload_insi"  [(set (match_operand:SI 0 "register_operand" "=r")        (match_operand:SI 1 "immediate_operand" "i"))   (clobber (match_operand:QI 2 "register_operand" "=&d"))]  "reload_completed"  "* return output_reload_insisf (insn, operands, NULL);"  [(set_attr "length" "8")   (set_attr "cc" "none")])(define_insn "*movsi"  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")        (match_operand:SI 1 "general_operand"       "r,L,Qm,rL,i,i"))]  "(register_operand (operands[0],SImode)    || register_operand (operands[1],SImode) || const0_rtx == operands[1])"  "* return output_movsisf (insn, operands, NULL);"  [(set_attr "length" "4,4,8,9,4,10")   (set_attr "cc" "none,set_zn,clobber,clobber,none,clobber")]);; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;; move floating point numbers (32 bit)(define_expand "movsf"  [(set (match_operand:SF 0 "nonimmediate_operand" "")        (match_operand:SF 1 "general_operand"  ""))]  ""  "{  /* One of the ops has to be in a register.  */  if (!register_operand (operand1, SFmode)      && !register_operand (operand0, SFmode))    {      operands[1] = copy_to_mode_reg (SFmode, operand1);    }}")(define_insn "*movsf"  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")        (match_operand:SF 1 "general_operand"       "r,G,Qm,r,F,F"))]  "register_operand (operands[0], SFmode)   || register_operand (operands[1], SFmode)"  "* return output_movsisf (insn, operands, NULL);"  [(set_attr "length" "4,4,8,9,4,10")   (set_attr "cc" "none,set_zn,clobber,clobber,none,clobber")]);;=========================================================================;; move string (like memcpy);; implement as RTL loop(define_expand "movmemhi"  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")          (match_operand:BLK 1 "memory_operand" ""))          (use (match_operand:HI 2 "const_int_operand" ""))          (use (match_operand:HI 3 "const_int_operand" ""))])]  ""  "{  int prob;  HOST_WIDE_INT count;  enum machine_mode mode;  rtx label = gen_label_rtx ();  rtx loop_reg;  rtx jump;  /* Copy pointers into new psuedos - they will be changed.  */  rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));  rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));  /* Create rtx for tmp register - we use this as scratch.  */  rtx tmp_reg_rtx  = gen_rtx_REG (QImode, TMP_REGNO);  if (GET_CODE (operands[2]) != CONST_INT)    FAIL;  count = INTVAL (operands[2]);  if (count <= 0)    FAIL;  /* Work out branch probability for latter use.  */  prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / count;  /* See if constant fit 8 bits.  */  mode = (count < 0x100) ? QImode : HImode;  /* Create loop counter register.  */  loop_reg = copy_to_mode_reg (mode, gen_int_mode (count, mode));  /* Now create RTL code for move loop.  */  /* Label at top of loop.  */  emit_label (label);  /* Move one byte into scratch and inc pointer.  */  emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1));  emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));  /* Move to mem and inc pointer.  */  emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg_rtx);  emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));  /* Decrement count.  */  emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));  /* Compare with zero and jump if not equal. */  emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,                           label);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -