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

📄 sh.md

📁 GUN开源阻止下的编译器GCC
💻 MD
📖 第 1 页 / 共 4 页
字号:
;;- Machine description for the Hitachi SH.;;  Copyright (C) 1993, 1994, 1995 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.;; ??? Should add support for using BSR for short function calls.;; ??? The MAC.W and MAC.L instructions are not supported.  There is no;; way to generate them.;; ??? The BSR instruction is not supported.  It might be possible to;; generate it by keeping track of function sizes (and hence relative;; addresses), and then using it only if the target is earlier in the same;; file, and is within range.  Better would be assembler/linker relaxing,;; but that is much harder.;; ??? The cmp/str instruction is not supported.  Perhaps it can be used;; for a str* inline function.;; 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" "sh0,sh1,sh2,sh3"  (const (symbol_ref "sh_cpu_attr")));;;; cbranch	conditional branch instructions;; jump		unconditional jumps;; arith	ordinary arithmetic;; load		from memory;; store	to memory;; move		register to register;; 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;; rte		return from exception;; sfunc	special function call with known used registers;; call		function call(define_attr "type" "cbranch,jump,arith,other,load,store,move,smpy,dmpy,return,pload,pstore,pcload,rte,sfunc,call"  (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 16 bytes long.; An unconditional jump in the range -4092..4098 can be 2 bytes long.; Otherwise, it must be 14 bytes long.; All other instructions are two bytes long by default.; All positive offsets have an adjustment added, which is the number of bytes; difference between this instruction length and the next larger instruction; length.  This is because shorten_branches starts with the largest; instruction size and then tries to reduce them.(define_attr "length" ""  (cond [(eq_attr "type" "cbranch")	 (if_then_else (and (ge (minus (match_dup 0) (pc))				(const_int -252))			    (le (minus (match_dup 0) (pc))				(const_int 262)))		       (const_int 2)		       (if_then_else (and (ge (minus (match_dup 0) (pc))					      (const_int -4090))					  (le (minus (match_dup 0) (pc))					      (const_int 4110)))				     (const_int 6)				     (const_int 16)))	 (eq_attr "type" "jump")	 (if_then_else (and (ge (minus (match_dup 0) (pc))				(const_int -4092))			    (le (minus (match_dup 0) (pc))				(const_int 4110)))		       (const_int 2)		       (const_int 14))	 ] (const_int 2)));; (define_function_unit {name} {num-units} {n-users} {test};;                       {ready-delay} {issue-delay} [{conflict-list}]);; ??? These are probably not correct.(define_function_unit "memory" 1 0 (eq_attr "type" "load,pcload,pload") 2 2)(define_function_unit "mpy"    1 0 (eq_attr "type" "smpy") 2 2)(define_function_unit "mpy"    1 0 (eq_attr "type" "dmpy") 3 3); 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") (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.;; ??? Branches which are out-of-range actually have two delay slots,;; the first is either always executed or else annulled false, and the;; second is always annulled false.  Handling these differently from;; in range branches would give better code.(define_delay  (and (eq_attr "type" "cbranch")       (eq_attr "cpu" "sh2,sh3"))  [(eq_attr "in_delay_slot" "yes") (eq_attr "in_delay_slot" "yes") (nil)]);; -------------------------------------------------------------------------;; SImode signed integer comparisons;; -------------------------------------------------------------------------(define_insn ""  [(set (match_operand:SI 0 "arith_reg_operand" "=r")	(eq:SI (reg:SI 18)	       (const_int 1)))]  ""  "movt	%0");; ??? This combiner pattern does not work, because combine does not combine;; instructions that set a hard register when SMALL_REGISTER_CLASSES is;; defined.  Perhaps use a pseudo-reg for the T bit?(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;}");; -------------------------------------------------------------------------;; Addition instructions;; -------------------------------------------------------------------------;; ??? This should be a define expand.(define_insn "adddi3"  [(set (match_operand:DI 0 "arith_reg_operand" "=r")	(plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")		 (match_operand:DI 2 "arith_reg_operand" "r")))   (clobber (reg:SI 18))]  ""  "clrt\;addc	%R2,%R0\;addc	%S2,%S0"  [(set_attr "length" "6")])(define_insn "addsi3"  [(set (match_operand:SI 0 "arith_reg_operand" "=r")	(plus:SI (match_operand:SI 1 "arith_operand" "%0")		 (match_operand:SI 2 "arith_operand" "rI")))]  ""  "add	%2,%0"  [(set_attr "type" "arith")]);; -------------------------------------------------------------------------;; Subtraction instructions;; -------------------------------------------------------------------------;; ??? This should be a define expand.(define_insn "subdi3"  [(set (match_operand:DI 0 "arith_reg_operand" "=r")	(minus:DI (match_operand:DI 1 "arith_reg_operand" "0")		 (match_operand:DI 2 "arith_reg_operand" "r")))   (clobber (reg:SI 18))]  ""  "clrt\;subc	%R2,%R0\;subc	%S2,%S0"  [(set_attr "length" "6")])(define_insn "subsi3"  [(set (match_operand:SI 0 "arith_reg_operand" "=r")	(minus:SI (match_operand:SI 1 "arith_reg_operand" "0")		  (match_operand:SI 2 "arith_reg_operand" "r")))]  ""  "sub	%2,%0"  [(set_attr "type" "arith")]);; -------------------------------------------------------------------------;; Division instructions;; -------------------------------------------------------------------------;; We take advantage of the library routines which don't clobber as many;; registers as a normal function call would.;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than;; hard register 0.  If we used hard register 0, then the next instruction;; would be a move from hard register 0 to a pseudo-reg.  If the pseudo-reg;; gets allocated to a stack slot that needs its address reloaded, then;; there is nothing to prevent reload from using r0 to reload the address.;; This reload would clobber the value in r0 we are trying to store.;; If we let reload allocate r0, then this problem can never happen.(define_insn ""  [(set (match_operand:SI 1 "register_operand" "=z")	(udiv:SI (reg:SI 4) (reg:SI 5)))   (clobber (reg:SI 18))   (clobber (reg:SI 17))   (clobber (reg:SI 4))   (use (match_operand:SI 0 "arith_reg_operand" "r"))]  ""  "jsr	@%0%#"  [(set_attr "type" "sfunc")   (set_attr "needs_delay_slot" "yes")])(define_expand "udivsi3"  [(set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))   (set (reg:SI 5) (match_operand:SI 2 "general_operand" ""))   (set (match_dup 3) (symbol_ref:SI "__udivsi3"))   (parallel [(set (match_operand:SI 0 "register_operand" "")		   (udiv:SI (reg:SI 4)			    (reg:SI 5)))	      (clobber (reg:SI 18))	      (clobber (reg:SI 17))	      (clobber (reg:SI 4))	      (use (match_dup 3))])]  ""  "operands[3] = gen_reg_rtx(SImode);")(define_insn ""  [(set (match_operand:SI 1 "register_operand" "=z")	(div:SI (reg:SI 4) (reg:SI 5)))   (clobber (reg:SI 18))   (clobber (reg:SI 17))   (clobber (reg:SI 1))   (clobber (reg:SI 2))   (clobber (reg:SI 3))   (use (match_operand:SI 0 "arith_reg_operand" "r"))]  ""  "jsr	@%0%#"  [(set_attr "type" "sfunc")   (set_attr "needs_delay_slot" "yes")])(define_expand "divsi3"  [(set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))   (set (reg:SI 5) (match_operand:SI 2 "general_operand" ""))   (set (match_dup 3) (symbol_ref:SI "__sdivsi3"))   (parallel [(set (match_operand:SI 0 "register_operand" "")		   (div:SI (reg:SI 4)			   (reg:SI 5)))	      (clobber (reg:SI 18))	      (clobber (reg:SI 17))	      (clobber (reg:SI 1))	      (clobber (reg:SI 2))	      (clobber (reg:SI 3))	      (use (match_dup 3))])]  ""  "operands[3] = gen_reg_rtx(SImode);");; -------------------------------------------------------------------------;; Multiplication instructions;; -------------------------------------------------------------------------(define_insn ""  [(set (reg:SI 21)	(mult:SI (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))		 (zero_extend:SI (match_operand:HI 2 "arith_reg_operand" "r"))))]  ""  "mulu	%2,%1"  [(set_attr "type" "smpy")])(define_insn ""  [(set (reg:SI 21)	(mult:SI (sign_extend:SI		  (match_operand:HI 1 "arith_reg_operand" "r"))		 (sign_extend:SI		  (match_operand:HI 2 "arith_reg_operand" "r"))))]  ""  "muls	%2,%1"  [(set_attr "type" "smpy")])(define_expand "mulhisi3"  [(set (reg:SI 21)	(mult:SI (sign_extend:SI		  (match_operand:HI 1 "arith_reg_operand" ""))		 (sign_extend:SI		  (match_operand:HI 2 "arith_reg_operand" ""))))   (set (match_operand:SI 0 "arith_reg_operand" "")	(reg:SI 21))]  ""  "")(define_expand "umulhisi3"  [(set (reg:SI 21)	(mult:SI (zero_extend:SI		  (match_operand:HI 1 "arith_reg_operand" ""))		 (zero_extend:SI		  (match_operand:HI 2 "arith_reg_operand" ""))))   (set (match_operand:SI 0 "arith_reg_operand" "")	(reg:SI 21))]  ""  "");; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate;; a call to a routine which clobbers known registers.(define_insn ""  [(set (match_operand:SI 1 "register_operand" "=z")	(mult:SI (reg:SI 4) (reg:SI 5)))   (clobber (reg:SI 21))   (clobber (reg:SI 18))   (clobber (reg:SI 17))   (clobber (reg:SI 3))   (clobber (reg:SI 2))   (clobber (reg:SI 1))   (use (match_operand:SI 0 "arith_reg_operand" "r"))]  ""  "jsr	@%0%#"  [(set_attr "type" "sfunc")   (set_attr "needs_delay_slot" "yes")])(define_expand "mulsi3_call"  [(set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))   (set (reg:SI 5) (match_operand:SI 2 "general_operand" ""))   (set (match_dup 3) (symbol_ref:SI "__mulsi3"))   (parallel[(set (match_operand:SI 0 "register_operand" "")		  (mult:SI (reg:SI 4)			   (reg:SI 5)))	     (clobber (reg:SI 21))	     (clobber (reg:SI 18))	     (clobber (reg:SI 17))	     (clobber (reg:SI 3))	     (clobber (reg:SI 2))	     (clobber (reg:SI 1))	     (use (match_dup 3))])]  ""  "operands[3] = gen_reg_rtx(SImode);")(define_insn "mul_l"  [(set (reg:SI 21)	(mult:SI (match_operand:SI 0 "arith_reg_operand" "r")		 (match_operand:SI 1 "arith_reg_operand" "r")))]

⌨️ 快捷键说明

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