📄 avr.md
字号:
;; -*- Mode: Scheme -*-;; Machine description for GNU compiler,;; for ATMEL AVR micro controllers.;; Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.;; Contributed by Denis Chertykov (denisc@overta.ru);; This file is part of GNU CC.;; GNU CC 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.;; GNU CC 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 GNU CC; 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.;; ~ 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)(define_expand "movstrhi" [(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" "")) (clobber (match_dup 4)) (clobber (match_dup 5)) (clobber (match_dup 6))])] "" "{ rtx addr0, addr1; int cnt8; enum machine_mode mode; if (GET_CODE (operands[2]) != CONST_INT) FAIL; cnt8 = byte_immediate_operand (operands[2], GET_MODE (operands[2])); mode = cnt8 ? QImode : HImode; operands[2] = copy_to_mode_reg (mode, gen_int_mode (INTVAL (operands[2]), mode)); operands[4] = operands[2]; addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); operands[5] = addr0; operands[6] = addr1; operands[0] = gen_rtx (MEM, BLKmode, addr0); operands[1] = gen_rtx (MEM, BLKmode, addr1);}")(define_insn "*movstrqi_insn" [(set (mem:BLK (match_operand:HI 0 "register_operand" "e")) (mem:BLK (match_operand:HI 1 "register_operand" "e"))) (use (match_operand:QI 2 "register_operand" "r")) (use (match_operand:QI 3 "const_int_operand" "i")) (clobber (match_dup 2)) (clobber (match_dup 0)) (clobber (match_dup 1))] "" "ld __tmp_reg__,%a1+ st %a0+,__tmp_reg__ dec %2 brne .-8" [(set_attr "length" "4") (set_attr "cc" "clobber")])(define_insn "*movstrhi" [(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e")) (mem:BLK (match_operand:HI 1 "register_operand" "e,e"))) (use (match_operand:HI 2 "register_operand" "!w,d")) (use (match_operand:HI 3 "const_int_operand" "")) (clobber (match_dup 2)) (clobber (match_dup 0)) (clobber (match_dup 1))] "" "*{ if (which_alternative==0) return (AS2 (ld,__tmp_reg__,%a1+) CR_TAB AS2 (st,%a0+,__tmp_reg__) CR_TAB AS2 (sbiw,%A2,1) CR_TAB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -