📄 h8300.md
字号:
;; GCC machine description for Hitachi H8/300;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,;; 2001, 2002, 2003 Free Software Foundation, Inc.;; Contributed by Steve Chamberlain (sac@cygnus.com),;; Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@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.;; Some of the extend instructions accept a general_operand_src, which;; allows all the normal memory addressing modes. The length computations;; don't take this into account. The lengths in the MD file should be;; "worst case" and then be adjusted to their correct values by;; h8300_adjust_insn_length.;; On the H8/300H and H8S, adds/subs operate on the 32bit "er";; registers. Right now GCC doesn't expose the "e" half to the;; compiler, so using add/subs for addhi and subhi is safe. Long;; term, we want to expose the "e" half to the compiler (gives us 8;; more 16bit registers). At that point addhi and subhi can't use;; adds/subs.;; There's currently no way to have an insv/extzv expander for the H8/300H;; because word_mode is different for the H8/300 and H8/300H.;; Shifts/rotates by small constants should be handled by special;; patterns so we get the length and cc status correct.;; Bitfield operations no longer accept memory operands. We need;; to add variants which operate on memory back to the MD.;; ??? Implement remaining bit ops available on the h8300;; ----------------------------------------------------------------------;; CONSTANTS;; ----------------------------------------------------------------------(define_constants [(SC_REG 3) (FP_REG 6) (SP_REG 7) (MAC_REG 8) (AP_REG 9) (RAP_REG 10)]);; ----------------------------------------------------------------------;; ATTRIBUTES;; ----------------------------------------------------------------------(define_attr "cpu" "h8300,h8300h" (const (symbol_ref "cpu_type")))(define_attr "type" "branch,arith" (const_string "arith"));; The size of instructions in bytes.(define_attr "length" "" (cond [(eq_attr "type" "branch") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -126)) (le (minus (match_dup 0) (pc)) (const_int 126))) (const_int 2) (if_then_else (and (eq_attr "cpu" "h8300h") (and (ge (minus (pc) (match_dup 0)) (const_int -32000)) (le (minus (pc) (match_dup 0)) (const_int 32000)))) (const_int 4) (const_int 6)))] (const_int 200)));; The necessity of instruction length adjustment.(define_attr "adjust_length" "yes,no" (cond [(eq_attr "type" "branch") (const_string "no")] (const_string "yes")));; Condition code settings.;;;; none - insn does not affect cc;; none_0hit - insn does not affect cc but it does modify operand 0;; This attribute is used to keep track of when operand 0 changes.;; See the description of NOTICE_UPDATE_CC for more info.;; set_znv - insn sets z,n,v to usable values (like a tst insn); c is unknown.;; set_zn - insn sets z,n to usable values; v,c are unknown.;; compare - compare instruction;; clobber - value of cc is unknown(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber" (const_string "clobber"));; ----------------------------------------------------------------------;; MOVE INSTRUCTIONS;; ----------------------------------------------------------------------;; movqi(define_insn "pushqi1_h8300" [(parallel [(set (reg:HI SP_REG) (plus:HI (reg:HI SP_REG) (const_int -2))) (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1))) (match_operand:QI 0 "register_operand" "r"))])] "TARGET_H8300 && REGNO (operands[0]) != SP_REG" "mov.w\\t%T0,@-r7" [(set_attr "length" "2") (set_attr "cc" "clobber")])(define_insn "pushqi1_h8300hs" [(parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4))) (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3))) (match_operand:QI 0 "register_operand" "r"))])] "(TARGET_H8300H || TARGET_H8300S) && REGNO (operands[0]) != SP_REG" "mov.l\\t%S0,@-er7" [(set_attr "length" "4") (set_attr "cc" "clobber")])(define_expand "pushqi1" [(use (match_operand:QI 0 "register_operand" ""))] "" "{ if (TARGET_H8300) emit_insn (gen_pushqi1_h8300 (operands[0])); else emit_insn (gen_pushqi1_h8300hs (operands[0])); DONE;}")(define_insn "" [(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m") (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))] "TARGET_H8300 && (register_operand (operands[0], QImode) || register_operand (operands[1], QImode))" "@ sub.b %X0,%X0 mov.b %R1,%X0 mov.b %X1,%R0 mov.b %R1,%X0 mov.b %R1,%X0 mov.b %X1,%R0" [(set_attr "length" "2,2,2,2,4,4") (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])(define_insn "" [(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m") (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))] "(TARGET_H8300H || TARGET_H8300S) && (register_operand (operands[0], QImode) || register_operand (operands[1], QImode))" "@ sub.b %X0,%X0 mov.b %R1,%X0 mov.b %X1,%R0 mov.b %R1,%X0 mov.b %R1,%X0 mov.b %X1,%R0" [(set_attr "length" "2,2,2,2,8,8") (set_attr "cc" "set_zn,set_znv,set_znv,clobber,set_znv,set_znv")])(define_expand "movqi" [(set (match_operand:QI 0 "general_operand_dst" "") (match_operand:QI 1 "general_operand_src" ""))] "" "{ /* One of the ops has to be in a register. */ if (!register_operand (operand0, QImode) && !register_operand (operand1, QImode)) { operands[1] = copy_to_mode_reg (QImode, operand1); }}")(define_insn "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r,r,r")) (match_operand:QI 1 "general_operand_src" "I,r,n,m"))] "" "@ sub.b %X0,%X0 mov.b %X1,%X0 mov.b %R1,%X0 mov.b %R1,%X0" [(set_attr_alternative "length" [(const_int 2) (const_int 2) (const_int 2) (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))]) (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")]);; movhi(define_expand "pushhi1_h8300" [(set (mem:HI (pre_dec:HI (reg:HI SP_REG))) (match_operand:HI 0 "register_operand" ""))] "TARGET_H8300 && REGNO (operands[0]) != SP_REG" "")(define_insn "pushhi1_h8300hs" [(parallel [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4))) (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2))) (match_operand:HI 0 "register_operand" "r"))])] "(TARGET_H8300H || TARGET_H8300S) && REGNO (operands[0]) != SP_REG" "mov.l\\t%S0,@-er7" [(set_attr "length" "4") (set_attr "cc" "clobber")])(define_expand "pushhi1" [(use (match_operand:HI 0 "register_operand" ""))] "" "{ if (TARGET_H8300) emit_insn (gen_pushhi1_h8300 (operands[0])); else emit_insn (gen_pushhi1_h8300hs (operands[0])); DONE;}")(define_insn "" [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m") (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))] "TARGET_H8300 && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode)) && !(GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG && GET_CODE (operands[1]) == REG && REGNO (XEXP (XEXP (operands[0], 0), 0)) == REGNO (operands[1]))" "@ sub.w %T0,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0" [(set_attr "length" "2,2,2,4,4,4") (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])(define_insn "" [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m") (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))] "(TARGET_H8300H || TARGET_H8300S) && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode))" "@ sub.w %T0,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0" [(set_attr "length" "2,2,2,4,8,8") (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])(define_expand "movhi" [(set (match_operand:HI 0 "general_operand_dst" "") (match_operand:HI 1 "general_operand_src" ""))] "" "{ /* One of the ops has to be in a register. */ if (!register_operand (operand1, HImode) && !register_operand (operand0, HImode)) { operands[1] = copy_to_mode_reg (HImode, operand1); }}")(define_insn "movstricthi" [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r,r")) (match_operand:HI 1 "general_operand_src" "I,r,i,m"))] "" "@ sub.w %T0,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0" [(set_attr_alternative "length" [(const_int 2) (const_int 2) (const_int 4) (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))]) (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")]);; movsi(define_expand "movsi" [(set (match_operand:SI 0 "general_operand_dst" "") (match_operand:SI 1 "general_operand_src" ""))] "" "{ if (TARGET_H8300) { if (do_movsi (operands)) DONE; } else { /* One of the ops has to be in a register. */ if (!register_operand (operand1, SImode) && !register_operand (operand0, SImode)) { operands[1] = copy_to_mode_reg (SImode, operand1); } }}")(define_expand "movsf" [(set (match_operand:SF 0 "general_operand_dst" "") (match_operand:SF 1 "general_operand_src" ""))] "" "{ if (TARGET_H8300) { if (do_movsi (operands)) DONE; } else { /* 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 "movsi_h8300" [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,o,<,r") (match_operand:SI 1 "general_operand_src" "I,r,io,r,r,>"))] "TARGET_H8300 && (register_operand (operands[0], SImode) || register_operand (operands[1], SImode))" "*{ int rn = -1; switch (which_alternative) { case 0: return \"sub.w %e0,%e0\;sub.w %f0,%f0\"; case 1: if (REGNO (operands[0]) < REGNO (operands[1])) return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; else return \"mov.w %f1,%f0\;mov.w %e1,%e0\"; case 2: /* Make sure we don't trample the register we index with. */ if (GET_CODE (operands[1]) == MEM) { rtx inside = XEXP (operands[1], 0); if (REG_P (inside)) { rn = REGNO (inside); } else if (GET_CODE (inside) == PLUS) { rtx lhs = XEXP (inside, 0); rtx rhs = XEXP (inside, 1); if (REG_P (lhs)) rn = REGNO (lhs); if (REG_P (rhs)) rn = REGNO (rhs); } } if (rn == REGNO (operands[0])) { /* Move the second word first. */ return \"mov.w %f1,%f0\;mov.w %e1,%e0\"; } else { /* See if either half is zero. If so, use sub.w to clear that half. */ if (GET_CODE (operands[1]) == CONST_INT) { if ((INTVAL (operands[1]) & 0xffff) == 0) return \"mov.w %e1,%e0\;sub.w %f0,%f0\"; if (((INTVAL (operands[1]) >> 16) & 0xffff) == 0) return \"sub.w %e0,%e0\;mov.w %f1,%f0\"; } return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; } case 3: return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; case 4: return \"mov.w %f1,%T0\;mov.w %e1,%T0\"; case 5: return \"mov.w %T1,%e0\;mov.w %T1,%f0\"; default: abort (); }}" [(set_attr "length" "4,4,8,8,4,4") (set_attr "cc" "clobber")])(define_insn "movsf_h8300" [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,o,<,r") (match_operand:SF 1 "general_operand_src" "I,r,io,r,r,>"))] "TARGET_H8300 && (register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode))" "*{ /* Copy of the movsi stuff. */ int rn = -1; switch (which_alternative) { case 0: return \"sub.w %e0,%e0\;sub.w %f0,%f0\"; case 1: if (REGNO (operands[0]) < REGNO (operands[1])) return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; else return \"mov.w %f1,%f0\;mov.w %e1,%e0\"; case 2: /* Make sure we don't trample the register we index with. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -