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

📄 arm.md

📁 gcc库的原代码,对编程有很大帮助.
💻 MD
📖 第 1 页 / 共 5 页
字号:
;;- Machine description for Advanced RISC Machines' ARM for GNU compiler;;  Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl);;             and Martin Simmons (@harleqn.co.uk).;;  More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk);; 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.;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.;; There are patterns in this file to support XFmode arithmetic.;; Unfortunately RISC iX doesn't work well with these so they are disabled.;; (See arm.h);; UNSPEC Usage:;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,;;   the mode is MODE_FLOAT;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,;;   the mode is MODE_FLOAT;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent;;   registers are in parallel (use...) expressions.;; Attributes; condition codes: this one is used by final_prescan_insn to speed up; conditionalizing instructions.  It saves having to scan the rtl to see if; it uses or alters the condition codes.; USE means that the condition codes are used by the insn in the process of; outputting code, this means (at present) that we can't use the insn in; inlined branches; SET means that the purpose of the insn is to set the condition codes in a; well defined manner.; CLOB means that the condition codes are altered in an undefined manner, if; they are altered at all; JUMP_CLOB is used when the conditions are not defined if a branch is taken,; but are if the branch wasn't taken; the effect is to limit the branch; elimination scanning.; NOCOND means that the condition codes are neither altered nor affect the; output of this insn(define_attr "conds" "use,set,clob,jump_clob,nocond"	(const_string "nocond")); CPU attribute is used to determine whether condition codes are clobbered; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the; arm2 and arm3 the condition codes are restored by the return.(define_attr "cpu" "arm2,arm3,arm6" (const (symbol_ref "arm_cpu_attr"))); Floating Point Unit.  If we only have floating point emulation, then there; is no point in scheduling the floating point insns.  (Well, for best; performance we should try and group them together).(define_attr "fpu" "fpa,fpe" (const (symbol_ref "arm_fpu_attr"))); LENGTH of an instruction (in bytes)(define_attr "length" "" (const_int 4)); An assembler sequence may clobber the condition codes without us knowing(define_asm_attributes [(set_attr "conds" "clob")  (set_attr "length" "4")]); TYPE attribute is used to detect floating point instructions which, if; running on a co-processor can run in parallel with other, basic instructions; If write-buffer scheduling is enabled then it can also be used in the; scheduling of writes.; Classification of each insn; normal	any data instruction that doesn't hit memory or fp regs; block		blockage insn, this blocks all functional units; float		a floating point arithmetic operation (subject to expansion); fdivx		XFmode floating point division; fdivd		DFmode floating point division; fdivs		SFmode floating point division; fmul		Floating point multiply; ffmul		Fast floating point multiply; farith	Floating point arithmetic (4 cycle); ffarith	Fast floating point arithmetic (2 cycle); float_em	a floating point arithmetic operation that is normally emulated;		even on a machine with an fpa.; f_load	a floating point load from memory; f_store	a floating point store to memory; f_mem_r	a transfer of a floating point register to a real reg via mem; r_mem_f	the reverse of f_mem_r; f_2_r		fast transfer float to arm (no memory needed); r_2_f		fast transfer arm to float; call		a subroutine call; load		any load from memory; store1	store 1 word to memory from arm registers; store2	store 2 words; store3	store 3 words; store4	store 4 words;(define_attr "type"	"normal,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4" 	(const_string "normal"))(define_attr "write_conflict" "no,yes"  (if_then_else (eq_attr "type"		 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")		(const_string "yes")		(const_string "no"))); The write buffer on some of the arm6 processors is hard to model exactly.; There is room in the buffer for up to two addresses and up to eight words; of memory, but the two needn't be split evenly.  When writing the two; addresses are fully pipelined.  However, a read from memory that is not; currently in the cache will block until the writes have completed.; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous; (they aren't allowed to be at present) then there is a startup cost of 1MCLK; cycle to add as well.;; (define_function_unit {name} {num-units} {n-users} {test};;                       {ready-delay} {issue-delay} [{conflict-list}])(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "fdivx")) 71 69)(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "fdivd")) 59 57)(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "fdivs")) 31 29)(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "fmul")) 9 7)(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "ffmul")) 6 4)(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "farith")) 4 2)(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "ffarith")) 2 2)(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "r_2_f")) 5 3)(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")				     (eq_attr "type" "f_2_r")) 1 2);; The fpa10 doesn't really have a memory read unit, but it can start to;; speculatively execute the instruction in the pipeline, provided the data;; is already loaded, so pretend reads have a delay of 2 (and that the;; pipeline is infinite.(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")					 (eq_attr "type" "f_load")) 3 1)(define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 3 3	[(eq_attr "write_conflict" "yes")])(define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 5 5	[(eq_attr "write_conflict" "yes")])(define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 7 7	[(eq_attr "write_conflict" "yes")])(define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 9 9	[(eq_attr "write_conflict" "yes")])(define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 3 3	[(eq_attr "write_conflict" "yes")]);; Note: For DImode insns, there is normally no reason why operands should;; not be in the same register, what we don't want is for something being;; written to partially overlap something that is an input.;; Addition insns.(define_insn "adddi3"  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")	(plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")		 (match_operand:DI 2 "s_register_operand" "r,0")))   (clobber (reg:CC 24))]  ""  "adds\\t%0, %1, %2\;adc\\t%R0, %R1, %R2"[(set_attr "conds" "clob") (set_attr "length" "8")])(define_insn ""  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")	(plus:DI (sign_extend:DI		  (match_operand:SI 1 "s_register_operand" "r,r"))		 (match_operand:DI 2 "s_register_operand" "r,0")))   (clobber (reg:CC 24))]  ""  "adds\\t%0, %2, %1\;adc\\t%R0, %R2, %1, asr #31"[(set_attr "conds" "clob") (set_attr "length" "8")])(define_insn ""  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")	(plus:DI (zero_extend:DI		  (match_operand:SI 1 "s_register_operand" "r,r"))		 (match_operand:DI 2 "s_register_operand" "r,0")))   (clobber (reg:CC 24))]  ""  "adds\\t%0, %2, %1\;adc\\t%R0, %R2, #0"[(set_attr "conds" "clob") (set_attr "length" "8")])(define_expand "addsi3"  [(set (match_operand:SI 0 "s_register_operand" "")	(plus:SI (match_operand:SI 1 "s_register_operand" "")		 (match_operand:SI 2 "reg_or_int_operand" "")))]  ""  "  if (GET_CODE (operands[2]) == CONST_INT)    {      arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],			  operands[1],			  (reload_in_progress || reload_completed ? 0			   : preserve_subexpressions_p ()));      DONE;    }")(define_split  [(set (match_operand:SI 0 "s_register_operand" "")	(plus:SI (match_operand:SI 1 "s_register_operand" "")		 (match_operand:SI 2 "const_int_operand" "")))]  "! (const_ok_for_arm (INTVAL (operands[2]))      || const_ok_for_arm (-INTVAL (operands[2])))"  [(clobber (const_int 0))]  "  arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],		      operands[1], 0);  DONE;")(define_insn ""  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")	(plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")		 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]  ""  "@   add%?\\t%0, %1, %2   sub%?\\t%0, %1, #%n2   #"[(set_attr "length" "4,4,16")])(define_insn ""  [(set (reg:CC_NOOV 24)	(compare:CC_NOOV	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")		  (match_operand:SI 2 "arm_add_operand" "rI,L"))	 (const_int 0)))   (set (match_operand:SI 0 "s_register_operand" "=r,r")	(plus:SI (match_dup 1) (match_dup 2)))]  ""  "@   add%?s\\t%0, %1, %2   sub%?s\\t%0, %1, #%n2"[(set_attr "conds" "set")])(define_insn ""  [(set (reg:CC 24)	(compare:CC (match_operand:SI 1 "s_register_operand" "r,r")		    (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))   (set (match_operand:SI 0 "s_register_operand" "=r,r")	(plus:SI (match_dup 1) (match_dup 2)))]  ""  "@   add%?s\\t%0, %1, %2   sub%?s\\t%0, %1, #%n2"[(set_attr "conds" "set")])(define_insn "incscc"  [(set (match_operand:SI 0 "s_register_operand" "=r,r")        (plus:SI (match_operator:SI 2 "comparison_operator"                    [(reg 24) (const_int 0)])                 (match_operand:SI 1 "s_register_operand" "0,?r")))]  ""  "@  add%d2\\t%0, %1, #1  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"[(set_attr "conds" "use") (set_attr "length" "4,8")]); If a constant is too big to fit in a single instruction then the constant; will be pre-loaded into a register taking at least two insns, we might be; able to merge it with an add, but it depends on the exact value.(define_split  [(set (match_operand:SI 0 "s_register_operand" "=r")	(plus:SI (match_operand:SI 1 "s_register_operand" "r")		 (match_operand:SI 2 "immediate_operand" "n")))]  "!(const_ok_for_arm (INTVAL (operands[2]))     || const_ok_for_arm (-INTVAL (operands[2])))"  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]  "{  unsigned int val = (unsigned) INTVAL (operands[2]);  int i;  unsigned int temp;  /* this code is similar to the approach followed in movsi, but it must     generate exactly two insns */  for (i = 30; i >= 0; i -= 2)    {      if (val & (3 << i))	{	  i -= 6;	  if (i < 0) i = 0;	  if (const_ok_for_arm (temp = (val & ~(255 << i))))	    {	      val &= 255 << i;	      break;	    }	  /* we might be able to do this as (larger number - small number) */	  temp = ((val >> i) & 255) + 1;	  if (temp > 255 && i < 24)	    {	      i += 2;	      temp = ((val >> i) & 255) + 1;	    }	  if (const_ok_for_arm ((temp << i) - val))	    {	      i = temp << i;	      temp = (unsigned) - (int) (i - val);	      val = i;	      break;	    }	  FAIL;	}    }  /* if we got here, we have found a way of doing it in two instructions.     the two constants are in val and temp */  operands[2] = GEN_INT ((int)val);  operands[3] = GEN_INT ((int)temp);}")(define_insn "addsf3"  [(set (match_operand:SF 0 "s_register_operand" "=f,f")	(plus:SF (match_operand:SF 1 "s_register_operand" "f,f")		 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]  "TARGET_HARD_FLOAT"  "@   adf%?s\\t%0, %1, %2   suf%?s\\t%0, %1, #%N2"[(set_attr "type" "farith")])(define_insn "adddf3"  [(set (match_operand:DF 0 "s_register_operand" "=f,f")	(plus:DF (match_operand:DF 1 "s_register_operand" "f,f")		 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]  "TARGET_HARD_FLOAT"  "@   adf%?d\\t%0, %1, %2   suf%?d\\t%0, %1, #%N2"[(set_attr "type" "farith")])(define_insn ""  [(set (match_operand:DF 0 "s_register_operand" "=f,f")	(plus:DF (float_extend:DF		  (match_operand:SF 1 "s_register_operand" "f,f"))		 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]  "TARGET_HARD_FLOAT"  "@   adf%?d\\t%0, %1, %2   suf%?d\\t%0, %1, #%N2"[(set_attr "type" "farith")])(define_insn ""  [(set (match_operand:DF 0 "s_register_operand" "=f")	(plus:DF (match_operand:DF 1 "s_register_operand" "f")		 (float_extend:DF		  (match_operand:SF 2 "s_register_operand" "f"))))]  "TARGET_HARD_FLOAT"  "adf%?d\\t%0, %1, %2"[(set_attr "type" "farith")])(define_insn ""  [(set (match_operand:DF 0 "s_register_operand" "=f")	(plus:DF (float_extend:DF 		  (match_operand:SF 1 "s_register_operand" "f"))		 (float_extend:DF		  (match_operand:SF 2 "s_register_operand" "f"))))]  "TARGET_HARD_FLOAT"  "adf%?d\\t%0, %1, %2"[(set_attr "type" "farith")])(define_insn "addxf3"  [(set (match_operand:XF 0 "s_register_operand" "=f,f")	(plus:XF (match_operand:XF 1 "s_register_operand" "f,f")		 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"  "@   adf%?e\\t%0, %1, %2   suf%?e\\t%0, %1, #%N2"[(set_attr "type" "farith")])(define_insn "subdi3"  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")	(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")		  (match_operand:DI 2 "s_register_operand" "r,0,0")))   (clobber (reg:CC 24))]  ""  "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, %R2"[(set_attr "conds" "clob") (set_attr "length" "8")])

⌨️ 快捷键说明

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