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

📄 sh.md

📁 GCC编译器源代码
💻 MD
📖 第 1 页 / 共 5 页
字号:
;;- Machine description for the Hitachi SH.;;  Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.;;  Contributed by Steve Chamberlain (sac@cygnus.com).;;  Improved by Jim Wilson (wilson@cygnus.com).;; 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.;; ??? Should prepend a * to all pattern names which are not used.;; This will make the compiler smaller, and rebuilds after changes faster.;; ??? Should be enhanced to include support for many more GNU superoptimizer;; sequences.  Especially the sequences for arithmetic right shifts.;; ??? Should check all DImode patterns for consistency and usefulness.;; ??? The MAC.W and MAC.L instructions are not supported.  There is no;; way to generate them.;; ??? The cmp/str instruction is not supported.  Perhaps it can be used;; for a str* inline function.;; BSR is not generated by the compiler proper, but when relaxing, it;; generates .uses pseudo-ops that allow linker relaxation to create;; BSR.  This is actually implemented in bfd/{coff,elf32}-sh.c;; Special constraints for SH machine description:;;;;    t -- T;;    x -- mac;;    l -- pr;;    z -- r0;;;; Special formats used for outputting SH instructions:;;;;   %.  --  print a .s if insn needs delay slot;;   %@  --  print rte/rts if is/isn't an interrupt function;;   %#  --  output a nop if there is nothing to put in the delay slot;;   %O  --  print a constant without the #;;   %R  --  print the lsw reg of a double;;   %S  --  print the msw reg of a double;;   %T  --  print next word of a double REG or MEM;;;; Special predicates:;;;;  arith_operand          -- operand is valid source for arithmetic op;;  arith_reg_operand      -- operand is valid register for arithmetic op;;  general_movdst_operand -- operand is valid move destination;;  general_movsrc_operand -- operand is valid move source;;  logical_operand        -- operand is valid source for logical op;; -------------------------------------------------------------------------;; Attributes;; -------------------------------------------------------------------------;; Target CPU.(define_attr "cpu" "sh1,sh2,sh3,sh3e"  (const (symbol_ref "sh_cpu_attr")))(define_attr "endian" "big,little" (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")		      (const_string "little") (const_string "big"))));; cbranch	conditional branch instructions;; jump		unconditional jumps;; arith	ordinary arithmetic;; arith3	a compound insn that behaves similarly to a sequence of;;		three insns of type arith;; arith3b	like above, but might end with a redirected branch;; load		from memory;; load_si	Likewise, SImode variant for general register.;; store	to memory;; move		register to register;; fmove	register to register, floating point;; smpy		word precision integer multiply;; dmpy		longword or doublelongword precision integer multiply;; return	rts;; pload	load of pr reg, which can't be put into delay slot of rts;; pstore	store of pr reg, which can't be put into delay slot of jsr;; pcload	pc relative load of constant value;; pcload_si	Likewise, SImode variant for general register.;; rte		return from exception;; sfunc	special function call with known used registers;; call		function call;; fp		floating point;; fdiv		floating point divide (or square root);; gp_fpul	move between general purpose register and fpul;; nil		no-op move, will be deleted.(define_attr "type" "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,other,load,load_si,store,move,fmove,smpy,dmpy,return,pload,pstore,pcload,pcload_si,rte,sfunc,call,fp,fdiv,gp_fpul,nil"  (const_string "other")); If a conditional branch destination is within -252..258 bytes away; from the instruction it can be 2 bytes long.  Something in the; range -4090..4100 bytes can be 6 bytes long.  All other conditional; branches are initially assumed to be 16 bytes long.; In machine_dependent_reorg, we split all branches that are longer than; 2 bytes.; An unconditional jump in the range -4092..4098 can be 2 bytes long.; For wider ranges, we need a combination of a code and a data part.; If we can get a scratch register for a long range jump, the code; part can be 4 bytes long; otherwise, it must be 8 bytes long.; If the jump is in the range -32764..32770, the data part can be 2 bytes; long; otherwise, it must be 6 bytes long.; All other instructions are two bytes long by default.(define_attr "length" ""  (cond [(eq_attr "type" "cbranch")	 (cond [(ne (symbol_ref "short_cbranch_p (insn)") (const_int 0))		(const_int 2)		(ne (symbol_ref "med_branch_p (insn, 2)") (const_int 0))		(const_int 6)		(ne (symbol_ref "braf_branch_p (insn, 2)") (const_int 0))		(const_int 10)		(ne (pc) (pc))		(const_int 12)		] (const_int 16))	 (eq_attr "type" "jump")	 (cond [(ne (symbol_ref "med_branch_p (insn, 0)") (const_int 0))		(const_int 2)		(and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))")			 (symbol_ref "INSN"))		     (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))")			 (symbol_ref "code_for_indirect_jump_scratch")))		(if_then_else (ne (symbol_ref "braf_branch_p (insn, 0)")				  (const_int 0))			      (const_int 6)			      (const_int 10))		(ne (symbol_ref "braf_branch_p (insn, 0)") (const_int 0))		(const_int 10)		(ne (pc) (pc))		(const_int 12)		] (const_int 14))	 ] (const_int 2)));; (define_function_unit {name} {num-units} {n-users} {test};;                       {ready-delay} {issue-delay} [{conflict-list}]);; Load and store instructions save a cycle if they are aligned on a;; four byte boundary.  Using a function unit for stores encourages;; gcc to separate load and store instructions by one instruction,;; which makes it more likely that the linker will be able to word;; align them when relaxing.;; Loads have a latency of two.;; However, call insn can have ;; a delay slot, so that we want one more;; insn to be scheduled between the load of the function address and the call.;; This is equivalent to a latency of three.;; We cannot use a conflict list for this, because we need to distinguish;; between the actual call address and the function arguments.;; ADJUST_COST can only properly handle reductions of the cost, so we;; use a latency of three here.;; We only do this for SImode loads of general registers, to make the work;; for ADJUST_COST easier.(define_function_unit "memory" 1 0  (eq_attr "type" "load_si,pcload_si")  3 2)(define_function_unit "memory" 1 0  (eq_attr "type" "load,pcload,pload,store,pstore")  2 2)(define_function_unit "int"    1 0  (eq_attr "type" "arith3,arith3b") 3 3)(define_function_unit "int"    1 0  (eq_attr "type" "dyn_shift") 2 2)(define_function_unit "int"    1 0  (eq_attr "type" "arith,arith3b,dyn_shift") 2 2);; ??? These are approximations.(define_function_unit "mpy"    1 0 (eq_attr "type" "smpy") 2 2)(define_function_unit "mpy"    1 0 (eq_attr "type" "dmpy") 3 3)(define_function_unit "fp"     1 0 (eq_attr "type" "fp,fmove") 2 1)(define_function_unit "fp"     1 0 (eq_attr "type" "fdiv") 13 12); Definitions for filling branch delay slots.(define_attr "needs_delay_slot" "yes,no" (const_string "no"))(define_attr "hit_stack" "yes,no" (const_string "no"))(define_attr "interrupt_function" "no,yes"  (const (symbol_ref "pragma_interrupt")))(define_attr "in_delay_slot" "yes,no"  (cond [(eq_attr "type" "cbranch") (const_string "no")	 (eq_attr "type" "pcload,pcload_si") (const_string "no")	 (eq_attr "needs_delay_slot" "yes") (const_string "no")	 (eq_attr "length" "2") (const_string "yes")	 ] (const_string "no")))(define_delay  (eq_attr "needs_delay_slot" "yes")  [(eq_attr "in_delay_slot" "yes") (nil) (nil)]);; On the SH and SH2, the rte instruction reads the return pc from the stack,;; and thus we can't put a pop instruction in its delay slot.;; ??? On the SH3, the rte instruction does not use the stack, so a pop;; instruction can go in the delay slot.;; Since a normal return (rts) implicitly uses the PR register,;; we can't allow PR register loads in an rts delay slot.(define_delay  (eq_attr "type" "return")  [(and (eq_attr "in_delay_slot" "yes")	(ior (and (eq_attr "interrupt_function" "no")		  (eq_attr "type" "!pload"))	     (and (eq_attr "interrupt_function" "yes")		  (eq_attr "hit_stack" "no")))) (nil) (nil)]);; Since a call implicitly uses the PR register, we can't allow;; a PR register store in a jsr delay slot.(define_delay  (ior (eq_attr "type" "call") (eq_attr "type" "sfunc"))  [(and (eq_attr "in_delay_slot" "yes")	(eq_attr "type" "!pstore")) (nil) (nil)]);; Say that we have annulled true branches, since this gives smaller and;; faster code when branches are predicted as not taken.(define_delay  (and (eq_attr "type" "cbranch")       (ne (symbol_ref "TARGET_SH2") (const_int 0)))  [(eq_attr "in_delay_slot" "yes") (eq_attr "in_delay_slot" "yes") (nil)]);; -------------------------------------------------------------------------;; SImode signed integer comparisons;; -------------------------------------------------------------------------(define_insn ""  [(set (reg:SI 18)	(eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")		       (match_operand:SI 1 "arith_operand" "L,r"))	       (const_int 0)))]  ""  "tst	%1,%0");; ??? Perhaps should only accept reg/constant if the register is reg 0.;; That would still allow reload to create cmpi instructions, but would;; perhaps allow forcing the constant into a register when that is better.;; Probably should use r0 for mem/imm compares, but force constant into a;; register for pseudo/imm compares.(define_insn "cmpeqsi_t"  [(set (reg:SI 18) (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")			   (match_operand:SI 1 "arith_operand" "N,rI,r")))]  ""  "@	tst	%0,%0	cmp/eq	%1,%0	cmp/eq	%1,%0")(define_insn "cmpgtsi_t"  [(set (reg:SI 18) (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")			   (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]  ""  "@	cmp/gt	%1,%0	cmp/pl	%0")(define_insn "cmpgesi_t"  [(set (reg:SI 18) (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")			   (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]  ""  "@	cmp/ge	%1,%0	cmp/pz	%0");; -------------------------------------------------------------------------;; SImode unsigned integer comparisons;; -------------------------------------------------------------------------(define_insn "cmpgeusi_t"  [(set (reg:SI 18) (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")			    (match_operand:SI 1 "arith_reg_operand" "r")))]  ""  "cmp/hs	%1,%0")(define_insn "cmpgtusi_t"  [(set (reg:SI 18) (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")			    (match_operand:SI 1 "arith_reg_operand" "r")))]  ""  "cmp/hi	%1,%0");; We save the compare operands in the cmpxx patterns and use them when;; we generate the branch.(define_expand "cmpsi"  [(set (reg:SI 18) (compare (match_operand:SI 0 "arith_operand" "")			     (match_operand:SI 1 "arith_operand" "")))]  ""  "{  sh_compare_op0 = operands[0];  sh_compare_op1 = operands[1];  DONE;}");; -------------------------------------------------------------------------;; DImode signed integer comparisons;; -------------------------------------------------------------------------;; ??? Could get better scheduling by splitting the initial test from the;; rest of the insn after reload.  However, the gain would hardly justify;; the sh.md size increase necessary to do that.(define_insn ""  [(set (reg:SI 18)	(eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")		       (match_operand:DI 1 "arith_operand" "r"))	       (const_int 0)))]  ""  "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",				 insn, operands);"  [(set_attr "length" "6")   (set_attr "type" "arith3b")])(define_insn "cmpeqdi_t"  [(set (reg:SI 18) (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")			   (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]  ""  "*  return output_branchy_insn   (EQ,    (which_alternative     ? \"cmp/eq\\t%S1,%S0\;bf\\t%l9\;cmp/eq\\t%R1,%R0\"     : \"tst\\t%S0,%S0\;bf\\t%l9\;tst\\t%R0,%R0\"),    insn, operands);"  [(set_attr "length" "6")   (set_attr "type" "arith3b")])(define_insn "cmpgtdi_t"  [(set (reg:SI 18) (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")			   (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]  "TARGET_SH2"  "@	cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:	tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"  [(set_attr "length" "8")   (set_attr "type" "arith3")])(define_insn "cmpgedi_t"  [(set (reg:SI 18) (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")			   (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]  "TARGET_SH2"  "@	cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:	cmp/pz\\t%S0"  [(set_attr "length" "8,2")   (set_attr "type" "arith3,arith")]);; -------------------------------------------------------------------------;; DImode unsigned integer comparisons;; -------------------------------------------------------------------------(define_insn "cmpgeudi_t"  [(set (reg:SI 18) (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")			    (match_operand:DI 1 "arith_reg_operand" "r")))]  "TARGET_SH2"  "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"  [(set_attr "length" "8")   (set_attr "type" "arith3")])(define_insn "cmpgtudi_t"  [(set (reg:SI 18) (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")			    (match_operand:DI 1 "arith_reg_operand" "r")))]  "TARGET_SH2"  "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"  [(set_attr "length" "8")   (set_attr "type" "arith3")]);; We save the compare operands in the cmpxx patterns and use them when;; we generate the branch.(define_expand "cmpdi"  [(set (reg:SI 18) (compare (match_operand:DI 0 "arith_operand" "")			     (match_operand:DI 1 "arith_operand" "")))]  "TARGET_SH2"  "{  sh_compare_op0 = operands[0];  sh_compare_op1 = operands[1];

⌨️ 快捷键说明

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