;; GCC machine description for Renesas H8/300 ;; Copyright (C) 1992-2021 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 ;; http://www.gnu.org/licenses/.

;; 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 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])

;; 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”)