;; GCC machine description for Renesas H8/300
;; Copyright (C) 1992-2024 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 GCC.
;; GCC 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 3, or (at your option)
;; any later version.
;; GCC 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 GCC; see the file COPYING3. If not see
;; .
;; We compute exact length on each instruction for most of the time.
;; In some case, most notably bit operations that may involve memory
;; operands, the lengths in this file are "worst case".
;; 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
[(UNSPEC_INCDEC 0)
(UNSPEC_MONITOR 1)])
(define_constants
[(UNSPEC_MOVMD 100)
(UNSPEC_STPCPY 101)])
(define_constants
[(R0_REG 0)
(SC_REG 3)
(COUNTER_REG 4)
(SOURCE_REG 5)
(DESTINATION_REG 6)
(HFP_REG 6)
(SP_REG 7)
(MAC_REG 8)
(AP_REG 9)
(RAP_REG 10)
(FP_REG 11)
(CC_REG 12)])
;; ----------------------------------------------------------------------
;; ATTRIBUTES
;; ----------------------------------------------------------------------
(define_attr "cpu" "h8300,h8300h"
(const (symbol_ref "cpu_type")))
(define_attr "type" "branch,arith,bitbranch,call"
(const_string "arith"))
(define_attr "length_table" "none,add,logicb,movb,movw,movl,mova_zero,mova,unary,mov_imm4,short_immediate,bitfield,bitbranch"
(const_string "none"))
;; The size of instructions in bytes.
(define_attr "length" ""
(cond [(eq_attr "type" "branch")
;; In a forward delayed branch, (pc) represents the end of the
;; delay sequence, not the end of the branch itself.
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(le (plus (minus (match_dup 0) (pc))
(symbol_ref "DELAY_SLOT_LENGTH (insn)"))
(const_int 125)))
(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)))
(eq_attr "type" "bitbranch")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(le (minus (match_dup 0) (pc))
(const_int 126)))
(plus (symbol_ref "h8300_insn_length_from_table (insn, operands)")
(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))))
(plus (symbol_ref "h8300_insn_length_from_table (insn, operands)")
(const_int 4))
(plus (symbol_ref "h8300_insn_length_from_table (insn, operands)")
(const_int 6))))
(eq_attr "length_table" "!none")
(symbol_ref "h8300_insn_length_from_table (insn, operands)")]
(const_int 200)))
;; 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 "old_cc" "none,none_0hit,set_znv,set_zn,compare,clobber"
(const_string "clobber"))
;; So the idea here is to define iterators and substitutions so that we
;; can easily modify the patterns with CC clobbers into a pattern
;; which sets appropriate condition codes
;; The modes we're supporting. This is used when we want to generate
;; multiple patterns where only the mode differs from a single template
(define_mode_iterator H8cc [CC CCZN CCZ])
;; This is used to generate multiple define_substs from a single
;; template for the different variants we might have.
(define_mode_attr cc [(CC "cc") (CCZN "cczn") (CCZ "ccz")])
;; The primary substitution pattern. is used to create multiple
;; substitutions based on the CC bits that are set.
;;
;; The mode iterator sets the actual mode on the condition code
;; REG expression.
(define_subst "subst_"
[(set (match_operand 0 "")
(match_operand 1 ""))
(clobber (reg:CC CC_REG))]
""
[(set (reg:H8cc CC_REG)
(compare:H8cc (match_dup 1) (const_int 0)))
(set (match_dup 0) (match_dup 1))])
;; So when we see or in a define_insn pattern, we'll
;; apply the subst_cczn or subset_cc define_subst to generate a
;; new pattern that compare-elim can use
(define_subst_attr "cczn" "subst_cczn" "" "_cczn")
(define_subst_attr "ccz" "subst_ccz" "" "_ccz")
(define_subst_attr "cc" "subst_cc" "" "_cc")
;; Type of delay slot. NONE means the instruction has no delay slot.
;; JUMP means it is an unconditional jump that (if short enough)
;; could be implemented using bra/s.
(define_attr "delay_slot" "none,jump"
(const_string "none"))
;; "yes" if the instruction can be put into a delay slot. It's not
;; entirely clear that jsr is not valid in delay slots, but it
;; definitely doesn't have the effect of causing the called function
;; to return to the target of the delayed branch.
(define_attr "can_delay" "no,yes"
(cond [(eq_attr "type" "branch,bitbranch,call")
(const_string "no")
(geu (symbol_ref "get_attr_length (insn)") (const_int 2))
(const_string "no")]
(const_string "yes")))
;; Only allow jumps to have a delay slot if we think they might
;; be short enough. This is just an optimization: we don't know
;; for certain whether they will be or not.
(define_delay (and (eq_attr "delay_slot" "jump")
(eq (symbol_ref "get_attr_length (insn)") (const_int 2)))
[(eq_attr "can_delay" "yes")
(nil)
(nil)])
;; Provide the maximum length of an assembly instruction in an asm
;; statement. The maximum length of 14 bytes is achieved on H8SX.
(define_asm_attributes
[(set (attr "length")
(cond [(match_test "TARGET_H8300H") (const_int 10)
(match_test "TARGET_H8300S") (const_int 10)]
(const_int 14)))])
(include "predicates.md")
(include "constraints.md")
;; ----------------------------------------------------------------------
;; MACRO DEFINITIONS
;; ----------------------------------------------------------------------
;; This mode iterator allows :P to be used for patterns that operate on
;; pointer-sized quantities. Exactly one of the two alternatives will match.
(define_mode_iterator P [(HI "Pmode == HImode") (SI "Pmode == SImode")])
(define_mode_iterator QHI [QI HI])
(define_mode_iterator HSI [HI SI])
(define_mode_iterator HSI2 [HI SI])
(define_mode_iterator QHSI [QI HI SI])
(define_mode_iterator QHSI2 [QI HI SI])
(define_mode_iterator QHSIF [QI HI SI SF])
(define_mode_iterator SFI [SF SI])
(define_code_iterator shifts [ashift ashiftrt lshiftrt])
(define_code_iterator logicals [ior xor and])
(define_code_iterator ors [ior xor])
(define_code_iterator eqne [eq ne])
(define_code_attr eqne_invert [(eq "ne") (ne "eq")])
;; For storing the C flag, map from the unsigned comparison to the right
;; code for testing the C bit.
(define_code_iterator geultu [geu ltu])
(define_code_attr geultu_to_c [(geu "eq") (ltu "ne")])
(include "movepush.md")
(include "mova.md")
(include "testcompare.md")
(include "addsub.md")
(include "multiply.md")
(include "divmod.md")
(include "logical.md")
(include "other.md")
(include "jumpcall.md")
(include "proepi.md")
(include "extensions.md")
(include "shiftrotate.md")
(include "bitfield.md")
(include "combiner.md")
;;(include "peepholes.md")