📄 sh.md
字号:
;;- 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 + -