;; GCC machine description for Renesas H8/300 ;; Copyright (C) 1992-2015 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)])

;; ---------------------------------------------------------------------- ;; 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,addb,addw,addl,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 “cc” “none,none_0hit,set_znv,set_zn,compare,clobber” (const_string “clobber”))

;; 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_H8300”) (const_int 4) (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”)])

;; ---------------------------------------------------------------------- ;; MOVE INSTRUCTIONS ;; ----------------------------------------------------------------------

;; movqi

(define_insn “*movqi_h8300” [(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 && h8300_move_ok (operands[0], operands[1])” “@ 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 “*movqi_h8300hs” [(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) && !TARGET_H8300SX && h8300_move_ok (operands[0], operands[1])” “@ 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”) (symbol_ref “compute_mov_length (operands)”)) (set_attr “cc” “set_zn,set_znv,set_znv,clobber,set_znv,set_znv”)])

(define_insn “*movqi_h8sx” [(set (match_operand:QI 0 “general_operand_dst” “=Z,rQ”) (match_operand:QI 1 “general_operand_src” “P4>X,rQi”))] “TARGET_H8300SX” “@ mov.b %X1:4,%X0 mov.b %X1,%X0” [(set_attr “length_table” “mov_imm4,movb”) (set_attr “cc” “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 (!TARGET_H8300SX && !h8300_move_ok (operands[0], operands[1])) operands[1] = copy_to_mode_reg (QImode, operands[1]); })

(define_insn “movstrictqi” [(set (strict_low_part (match_operand:QI 0 “general_operand_dst” “+r,r”)) (match_operand:QI 1 “general_operand_src” “I,rmi>”))] "" “@ sub.b %X0,%X0 mov.b %X1,%X0” [(set_attr “length” “2,*”) (set_attr “length_table” “*,movb”) (set_attr “cc” “set_zn,set_znv”)])

;; movhi

(define_insn “*movhi_h8300” [(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 && h8300_move_ok (operands[0], 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”) (symbol_ref “compute_mov_length (operands)”)) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv,set_znv,set_znv”)])

(define_insn “*movhi_h8300hs” [(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) && !TARGET_H8300SX && h8300_move_ok (operands[0], 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”) (symbol_ref “compute_mov_length (operands)”)) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv,set_znv,set_znv”)])

(define_insn “*movhi_h8sx” [(set (match_operand:HI 0 “general_operand_dst” “=r,r,Z,Q,rQ”) (match_operand:HI 1 “general_operand_src” “I,P3>X,P4>X,IP8>X,rQi”))] “TARGET_H8300SX” “@ sub.w %T0,%T0 mov.w %T1:3,%T0 mov.w %T1:4,%T0 mov.w %T1,%T0 mov.w %T1,%T0” [(set_attr “length_table” “,,mov_imm4,short_immediate,movw”) (set_attr “length” “2,2,,,*”) (set_attr “cc” “set_zn,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 (!h8300_move_ok (operands[0], operands[1])) 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”)) (match_operand:HI 1 “general_operand_src” “I,P3>X,rmi”))] "" “@ sub.w %T0,%T0 mov.w %T1,%T0 mov.w %T1,%T0” [(set_attr “length” “2,2,*”) (set_attr “length_table” “,,movw”) (set_attr “cc” “set_zn,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 (h8300_expand_movsi (operands)) DONE; } else if (!TARGET_H8300SX) { /* One of the ops has to be in a register. */ if (!h8300_move_ok (operands[0], operands[1])) operands[1] = copy_to_mode_reg (SImode, 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 && h8300_move_ok (operands[0], operands[1])” { unsigned 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 { if (GET_CODE (operands[1]) == CONST_INT) { / If either half is zero, use sub.w to clear that half. / 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”; / If the upper half and the lower half are the same, copy one half to the other. */ if ((INTVAL (operands[1]) & 0xffff) == ((INTVAL (operands[1]) >> 16) & 0xffff)) return “mov.w\t%e1,%e0;mov.w\t%e0,%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: gcc_unreachable (); } } [(set (attr “length”) (symbol_ref “compute_mov_length (operands)”))])

(define_insn “*movsi_h8300hs” [(set (match_operand:SI 0 “general_operand_dst” “=r,r,r,<,r,r,m,*a,*a,r”) (match_operand:SI 1 “general_operand_src” “I,r,i,r,>,m,r,I,r,*a”))] “(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX && h8300_move_ok (operands[0], operands[1])” { switch (which_alternative) { case 0: return “sub.l %S0,%S0”; case 7: return “clrmac”; case 8: return “clrmac;ldmac %1,macl”; case 9: return “stmac macl,%0”; default: if (GET_CODE (operands[1]) == CONST_INT) { int val = INTVAL (operands[1]);

  /* Look for constants which can be made by adding an 8-bit
     number to zero in one of the two low bytes.  */
  if (val == (val & 0xff))
    {
      operands[1] = GEN_INT ((char) val & 0xff);
      return "sub.l\\t%S0,%S0\;add.b\\t%1,%w0";
    }

  if (val == (val & 0xff00))
    {
      operands[1] = GEN_INT ((char) (val >> 8) & 0xff);
      return "sub.l\\t%S0,%S0\;add.b\\t%1,%x0";
    }

  /* Look for constants that can be obtained by subs, inc, and
     dec to 0.  */
  switch (val & 0xffffffff)
    {
    case 0xffffffff:
      return "sub.l\\t%S0,%S0\;subs\\t#1,%S0";
    case 0xfffffffe:
      return "sub.l\\t%S0,%S0\;subs\\t#2,%S0";
    case 0xfffffffc:
      return "sub.l\\t%S0,%S0\;subs\\t#4,%S0";

    case 0x0000ffff:
      return "sub.l\\t%S0,%S0\;dec.w\\t#1,%f0";
    case 0x0000fffe:
      return "sub.l\\t%S0,%S0\;dec.w\\t#2,%f0";

    case 0xffff0000:
      return "sub.l\\t%S0,%S0\;dec.w\\t#1,%e0";
    case 0xfffe0000:
      return "sub.l\\t%S0,%S0\;dec.w\\t#2,%e0";

    case 0x00010000:
      return "sub.l\\t%S0,%S0\;inc.w\\t#1,%e0";
    case 0x00020000:
      return "sub.l\\t%S0,%S0\;inc.w\\t#2,%e0";
    }
}
}

return “mov.l %S1,%S0”; } [(set (attr “length”) (symbol_ref “compute_mov_length (operands)”)) (set_attr “cc” “set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv”)])

(define_insn “*movsi_h8sx” [(set (match_operand:SI 0 “general_operand_dst” “=r,r,Q,rQ,*a,*a,r”) (match_operand:SI 1 “general_operand_src” “I,P3>X,IP8>X,rQi,I,r,*a”))] “TARGET_H8300SX” “@ sub.l %S0,%S0 mov.l %S1:3,%S0 mov.l %S1,%S0 mov.l %S1,%S0 clrmac clrmac;ldmac %1,macl stmac macl,%0” [(set_attr “length_table” “,,short_immediate,movl,,,*”) (set_attr “length” “2,2,,,2,6,4”) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv”)])

(define_insn “*movsf_h8sx” [(set (match_operand:SF 0 “general_operand_dst” “=r,rQ”) (match_operand:SF 1 “general_operand_src” “G,rQi”))] “TARGET_H8300SX” “@ sub.l %S0,%S0 mov.l %S1,%S0” [(set_attr “length” “2,*”) (set_attr “length_table” “*,movl”) (set_attr “cc” “set_zn,set_znv”)])

;; Implement block moves using movmd. Defining movmemsi allows the full ;; range of constant lengths (up to 0x40000 bytes when using movmd.l). ;; See h8sx_emit_movmd for details.

(define_expand “movmemsi” [(use (match_operand:BLK 0 “memory_operand” "")) (use (match_operand:BLK 1 “memory_operand” "")) (use (match_operand:SI 2 "" "")) (use (match_operand:SI 3 “const_int_operand” ""))] “TARGET_H8300SX” { if (h8sx_emit_movmd (operands[0], operands[1], operands[2], INTVAL (operands[3]))) DONE; else FAIL; })

;; Expander for generating movmd insns. Operand 0 is the destination ;; memory region, operand 1 is the source, operand 2 is the counter ;; register and operand 3 is the chunk size (1, 2 or 4).

(define_expand “movmd” [(parallel [(set (match_operand:BLK 0 “memory_operand” "") (match_operand:BLK 1 “memory_operand” "")) (unspec [(match_operand:HI 2 “register_operand” "") (match_operand:HI 3 “const_int_operand” "")] UNSPEC_MOVMD) (clobber (match_dup 4)) (clobber (match_dup 5)) (set (match_dup 2) (const_int 0))])] “TARGET_H8300SX” { operands[4] = copy_rtx (XEXP (operands[0], 0)); operands[5] = copy_rtx (XEXP (operands[1], 0)); })

;; This is a difficult instruction to reload since operand 0 must be the ;; frame pointer. See h8300_reg_class_from_letter for an explanation.

(define_insn “movmd_internal_normal” [(set (mem:BLK (match_operand:HI 3 “register_operand” “0,r”)) (mem:BLK (match_operand:HI 4 “register_operand” “1,1”))) (unspec [(match_operand:HI 5 “register_operand” “2,2”) (match_operand:HI 6 “const_int_operand” “n,n”)] UNSPEC_MOVMD) (clobber (match_operand:HI 0 “register_operand” “=d,??D”)) (clobber (match_operand:HI 1 “register_operand” “=f,f”)) (set (match_operand:HI 2 “register_operand” “=c,c”) (const_int 0))] “TARGET_H8300SX && TARGET_NORMAL_MODE” “@ movmd%m6 #” [(set_attr “length” “2,14”) (set_attr “can_delay” “no”) (set_attr “cc” “none,clobber”)])

(define_insn “movmd_internal” [(set (mem:BLK (match_operand:SI 3 “register_operand” “0,r”)) (mem:BLK (match_operand:SI 4 “register_operand” “1,1”))) (unspec [(match_operand:HI 5 “register_operand” “2,2”) (match_operand:HI 6 “const_int_operand” “n,n”)] UNSPEC_MOVMD) (clobber (match_operand:SI 0 “register_operand” “=d,??D”)) (clobber (match_operand:SI 1 “register_operand” “=f,f”)) (set (match_operand:HI 2 “register_operand” “=c,c”) (const_int 0))] “TARGET_H8300SX && !TARGET_NORMAL_MODE” “@ movmd%m6 #” [(set_attr “length” “2,14”) (set_attr “can_delay” “no”) (set_attr “cc” “none,clobber”)])

;; Split the above instruction if the destination register isn't er6. ;; We need a sequence like: ;; ;; mov.l er6,@-er7 ;; mov.l ,er6 ;; movmd.sz ;; mov.l er6, ;; mov.l @er7+,er6 ;; ;; where is the current destination register (operand 4). ;; The fourth instruction will be deleted if dies here.

(define_split [(set (match_operand:BLK 0 “memory_operand” "") (match_operand:BLK 1 “memory_operand” "")) (unspec [(match_operand:HI 2 “register_operand” "") (match_operand:HI 3 “const_int_operand” "")] UNSPEC_MOVMD) (clobber (match_operand:HI 4 “register_operand” "")) (clobber (match_operand:HI 5 “register_operand” "")) (set (match_dup 2) (const_int 0))] “TARGET_H8300SX && TARGET_NORMAL_MODE && reload_completed && REGNO (operands[4]) != DESTINATION_REG” [(const_int 0)] { rtx dest;

h8300_swap_into_er6 (XEXP (operands[0], 0));
dest = replace_equiv_address (operands[0], hard_frame_pointer_rtx);
emit_insn (gen_movmd (dest, operands[1], operands[2], operands[3]));
h8300_swap_out_of_er6 (operands[4]);
DONE;

})

(define_split [(set (match_operand:BLK 0 “memory_operand” "") (match_operand:BLK 1 “memory_operand” "")) (unspec [(match_operand:HI 2 “register_operand” "") (match_operand:HI 3 “const_int_operand” "")] UNSPEC_MOVMD) (clobber (match_operand:SI 4 “register_operand” "")) (clobber (match_operand:SI 5 “register_operand” "")) (set (match_dup 2) (const_int 0))] “TARGET_H8300SX && !TARGET_NORMAL_MODE && reload_completed && REGNO (operands[4]) != DESTINATION_REG” [(const_int 0)] { rtx dest;

h8300_swap_into_er6 (XEXP (operands[0], 0));
dest = replace_equiv_address (operands[0], hard_frame_pointer_rtx);
emit_insn (gen_movmd (dest, operands[1], operands[2], operands[3]));
h8300_swap_out_of_er6 (operands[4]);
DONE;

})

;; Expand a call to stpcpy() using movsd. Operand 0 should point to ;; the final character, but movsd leaves it pointing to the character ;; after that.

(define_expand “movstr” [(use (match_operand 0 “register_operand” "")) (use (match_operand:BLK 1 “memory_operand” "")) (use (match_operand:BLK 2 “memory_operand” ""))] “TARGET_H8300SX” { operands[1] = replace_equiv_address (operands[1], copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); operands[2] = replace_equiv_address (operands[2], copy_to_mode_reg (Pmode, XEXP (operands[2], 0))); emit_insn (gen_movsd (operands[1], operands[2], gen_reg_rtx (Pmode))); emit_insn (gen_add3_insn (operands[0], XEXP (operands[1], 0), constm1_rtx)); DONE; })

;; Expander for generating a movsd instruction. Operand 0 is the ;; destination string, operand 1 is the source string and operand 2 ;; is a scratch register.

(define_expand “movsd” [(parallel [(set (match_operand:BLK 0 “memory_operand” "") (unspec:BLK [(match_operand:BLK 1 “memory_operand” "")] UNSPEC_STPCPY)) (clobber (match_dup 3)) (clobber (match_dup 4)) (clobber (match_operand 2 “register_operand” ""))])] “TARGET_H8300SX” { operands[3] = copy_rtx (XEXP (operands[0], 0)); operands[4] = copy_rtx (XEXP (operands[1], 0)); })

;; See comments above memcpy_internal().

(define_insn “stpcpy_internal_normal” [(set (mem:BLK (match_operand:HI 3 “register_operand” “0,r”)) (unspec:BLK [(mem:BLK (match_operand:HI 4 “register_operand” “1,1”))] UNSPEC_STPCPY)) (clobber (match_operand:HI 0 “register_operand” “=d,??D”)) (clobber (match_operand:HI 1 “register_operand” “=f,f”)) (clobber (match_operand:HI 2 “register_operand” “=c,c”))] “TARGET_H8300SX && TARGET_NORMAL_MODE” “@ \n1:\tmovsd\t2f;bra\t1b\n2: #” [(set_attr “length” “6,18”) (set_attr “cc” “none,clobber”)])

(define_insn “stpcpy_internal” [(set (mem:BLK (match_operand:SI 3 “register_operand” “0,r”)) (unspec:BLK [(mem:BLK (match_operand:SI 4 “register_operand” “1,1”))] UNSPEC_STPCPY)) (clobber (match_operand:SI 0 “register_operand” “=d,??D”)) (clobber (match_operand:SI 1 “register_operand” “=f,f”)) (clobber (match_operand:SI 2 “register_operand” “=c,c”))] “TARGET_H8300SX && !TARGET_NORMAL_MODE” “@ \n1:\tmovsd\t2f;bra\t1b\n2: #” [(set_attr “length” “6,18”) (set_attr “cc” “none,clobber”)])

;; Split the above instruction if the destination isn't er6. This works ;; in the same way as the movmd splitter.

(define_split [(set (match_operand:BLK 0 “memory_operand” "") (unspec:BLK [(match_operand:BLK 1 “memory_operand” "")] UNSPEC_STPCPY)) (clobber (match_operand:HI 2 “register_operand” "")) (clobber (match_operand:HI 3 “register_operand” "")) (clobber (match_operand:HI 4 “register_operand” ""))] “TARGET_H8300SX && TARGET_NORMAL_MODE && reload_completed && REGNO (operands[2]) != DESTINATION_REG” [(const_int 0)] { rtx dest;

h8300_swap_into_er6 (XEXP (operands[0], 0));
dest = replace_equiv_address (operands[0], hard_frame_pointer_rtx);
emit_insn (gen_movsd (dest, operands[1], operands[4]));
h8300_swap_out_of_er6 (operands[2]);
DONE;

})

(define_split [(set (match_operand:BLK 0 “memory_operand” "") (unspec:BLK [(match_operand:BLK 1 “memory_operand” "")] UNSPEC_STPCPY)) (clobber (match_operand:SI 2 “register_operand” "")) (clobber (match_operand:SI 3 “register_operand” "")) (clobber (match_operand:SI 4 “register_operand” ""))] “TARGET_H8300SX && !TARGET_NORMAL_MODE && reload_completed && REGNO (operands[2]) != DESTINATION_REG” [(const_int 0)] { rtx dest;

h8300_swap_into_er6 (XEXP (operands[0], 0));
dest = replace_equiv_address (operands[0], hard_frame_pointer_rtx);
emit_insn (gen_movsd (dest, operands[1], operands[4]));
h8300_swap_out_of_er6 (operands[2]);
DONE;

})

(include “mova.md”)

(define_expand “movsf” [(set (match_operand:SF 0 “general_operand_dst” "") (match_operand:SF 1 “general_operand_src” ""))] "" { if (TARGET_H8300) { if (h8300_expand_movsi (operands)) DONE; } else if (!TARGET_H8300SX) { /* 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 “*movsf_h8300” [(set (match_operand:SF 0 “general_operand_dst” “=r,r,r,o,<,r”) (match_operand:SF 1 “general_operand_src” “G,r,io,r,r,>”))] “TARGET_H8300 && (register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode))” { /* Copy of the movsi stuff. / unsigned 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 / Move the first word first. */ 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:
  gcc_unreachable ();
}

} [(set (attr “length”) (symbol_ref “compute_mov_length (operands)”))])

(define_insn “*movsf_h8300hs” [(set (match_operand:SF 0 “general_operand_dst” “=r,r,r,m,<,r”) (match_operand:SF 1 “general_operand_src” “G,r,im,r,r,>”))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX && (register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode))” “@ sub.l %S0,%S0 mov.l %S1,%S0 mov.l %S1,%S0 mov.l %S1,%S0 mov.l %S1,%S0 mov.l %S1,%S0” [(set (attr “length”) (symbol_ref “compute_mov_length (operands)”)) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv,set_znv,set_znv”)]) ;; ---------------------------------------------------------------------- ;; PUSH INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn “*pushqi1_h8300” [(set (mem:QI (pre_modify:HI (reg:HI SP_REG) (plus:HI (reg:HI SP_REG) (const_int -2)))) (match_operand:QI 0 “register_no_sp_elim_operand” “r”))] “TARGET_H8300” “mov.w\t%T0,@-r7” [(set_attr “length” “2”)])

(define_insn “*pushqi1_h8300hs_” [(set (mem:QI (pre_modify:P (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -4)))) (match_operand:QI 0 “register_no_sp_elim_operand” “r”))] “TARGET_H8300H || TARGET_H8300S” “mov.l\t%S0,@-er7” [(set_attr “length” “4”)])

(define_insn “*pushhi1_h8300hs_” [(set (mem:HI (pre_modify:P (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -4)))) (match_operand:HI 0 “register_no_sp_elim_operand” “r”))] “TARGET_H8300H || TARGET_H8300S” “mov.l\t%S0,@-er7” [(set_attr “length” “4”)]) ;; ---------------------------------------------------------------------- ;; TEST INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn "" [(set (cc0) (compare (zero_extract:QI (match_operand:QI 0 “bit_memory_operand” “r,U”) (const_int 1) (match_operand 1 “const_int_operand” “n,n”)) (const_int 0)))] “TARGET_H8300” “btst %Z1,%Y0” [(set_attr “length” “2,4”) (set_attr “cc” “set_zn,set_zn”)])

(define_insn "" [(set (cc0) (compare (zero_extract:HI (match_operand:HI 0 “register_operand” “r”) (const_int 1) (match_operand 1 “const_int_operand” “n”)) (const_int 0)))] “TARGET_H8300” “btst %Z1,%Y0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn_and_split “*tst_extzv_1_n” [(set (cc0) (compare (zero_extract:SI (match_operand:QI 0 “general_operand_src” “r,U,mn>”) (const_int 1) (match_operand 1 “const_int_operand” “n,n,n”)) (const_int 0))) (clobber (match_scratch:QI 2 “=X,X,&r”))] “TARGET_H8300H || TARGET_H8300S” “@ btst\t%Z1,%Y0 btst\t%Z1,%Y0 #” “&& reload_completed && !satisfies_constraint_U (operands[0])” [(set (match_dup 2) (match_dup 0)) (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2) (const_int 1) (match_dup 1)) (const_int 0))) (clobber (scratch:QI))])] "" [(set_attr “length” “2,8,10”) (set_attr “cc” “set_zn,set_zn,set_zn”)])

(define_insn "" [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 “register_operand” “r”) (const_int 1) (match_operand 1 “const_int_operand” “n”)) (const_int 0)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) <= 15” “btst %Z1,%Y0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn_and_split “*tstsi_upper_bit” [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 “register_operand” “r”) (const_int 1) (match_operand 1 “const_int_operand” “n”)) (const_int 0))) (clobber (match_scratch:SI 2 “=&r”))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) >= 16” “#” “&& reload_completed” [(set (match_dup 2) (ior:SI (and:SI (match_dup 2) (const_int -65536)) (lshiftrt:SI (match_dup 0) (const_int 16)))) (set (cc0) (compare (zero_extract:SI (match_dup 2) (const_int 1) (match_dup 3)) (const_int 0)))] { operands[3] = GEN_INT (INTVAL (operands[1]) - 16); })

(define_insn “*tstsi_variable_bit” [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 “register_operand” “r”) (const_int 1) (and:SI (match_operand:SI 1 “register_operand” “r”) (const_int 7))) (const_int 0)))] “TARGET_H8300H || TARGET_H8300S” “btst %w1,%w0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn_and_split “*tstsi_variable_bit_qi” [(set (cc0) (compare (zero_extract:SI (zero_extend:SI (match_operand:QI 0 “general_operand_src” “r,U,mn>”)) (const_int 1) (and:SI (match_operand:SI 1 “register_operand” “r,r,r”) (const_int 7))) (const_int 0))) (clobber (match_scratch:QI 2 “=X,X,&r”))] “TARGET_H8300H || TARGET_H8300S” “@ btst\t%w1,%X0 btst\t%w1,%X0 #” “&& reload_completed && !satisfies_constraint_U (operands[0])” [(set (match_dup 2) (match_dup 0)) (parallel [(set (cc0) (compare (zero_extract:SI (zero_extend:SI (match_dup 2)) (const_int 1) (and:SI (match_dup 1) (const_int 7))) (const_int 0))) (clobber (scratch:QI))])] "" [(set_attr “length” “2,8,10”) (set_attr “cc” “set_zn,set_zn,set_zn”)])

(define_insn “*tstqi” [(set (cc0) (compare (match_operand:QI 0 “register_operand” “r”) (const_int 0)))] "" “mov.b %X0,%X0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “*tsthi” [(set (cc0) (compare (match_operand:HI 0 “register_operand” “r”) (const_int 0)))] "" “mov.w %T0,%T0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “*tsthi_upper” [(set (cc0) (compare (and:HI (match_operand:HI 0 “register_operand” “r”) (const_int -256)) (const_int 0)))] "" “mov.b %t0,%t0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “*tstsi” [(set (cc0) (compare (match_operand:SI 0 “register_operand” “r”) (const_int 0)))] “TARGET_H8300H || TARGET_H8300S” “mov.l %S0,%S0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “*tstsi_upper” [(set (cc0) (compare (and:SI (match_operand:SI 0 “register_operand” “r”) (const_int -65536)) (const_int 0)))] "" “mov.w %e0,%e0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “*cmpqi” [(set (cc0) (compare (match_operand:QI 0 “h8300_dst_operand” “rQ”) (match_operand:QI 1 “h8300_src_operand” “rQi”)))] "" “cmp.b %X1,%X0” [(set_attr “length_table” “addb”) (set_attr “cc” “compare”)])

(define_insn “*cmphi_h8300_znvc” [(set (cc0) (compare (match_operand:HI 0 “register_operand” “r”) (match_operand:HI 1 “register_operand” “r”)))] “TARGET_H8300” “cmp.w %T1,%T0” [(set_attr “length” “2”) (set_attr “cc” “compare”)])

(define_insn “*cmphi_h8300hs_znvc” [(set (cc0) (compare (match_operand:HI 0 “h8300_dst_operand” “rU,rQ”) (match_operand:HI 1 “h8300_src_operand” “P3>X,rQi”)))] “TARGET_H8300H || TARGET_H8300S” { switch (which_alternative) { case 0: if (!TARGET_H8300SX) return “cmp.w %T1,%T0”; else return “cmp.w %T1:3,%T0”; case 1: return “cmp.w %T1,%T0”; default: gcc_unreachable (); } } [(set_attr “length_table” “short_immediate,addw”) (set_attr “cc” “compare,compare”)])

(define_insn “cmpsi” [(set (cc0) (compare (match_operand:SI 0 “h8300_dst_operand” “r,rQ”) (match_operand:SI 1 “h8300_src_operand” “P3>X,rQi”)))] “TARGET_H8300H || TARGET_H8300S” { switch (which_alternative) { case 0: if (!TARGET_H8300SX) return “cmp.l %S1,%S0”; else return “cmp.l %S1:3,%S0”; case 1: return “cmp.l %S1,%S0”; default: gcc_unreachable (); } } [(set_attr “length” “2,*”) (set_attr “length_table” “*,addl”) (set_attr “cc” “compare,compare”)]) ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_expand “addqi3” [(set (match_operand:QI 0 “register_operand” "") (plus:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “h8300_src_operand” "")))] "" "")

(define_insn “*addqi3” [(set (match_operand:QI 0 “h8300_dst_operand” “=rQ”) (plus:QI (match_operand:QI 1 “h8300_dst_operand” “%0”) (match_operand:QI 2 “h8300_src_operand” “rQi”)))] “h8300_operands_match_p (operands)” “add.b %X2,%X0” [(set_attr “length_table” “addb”) (set_attr “cc” “set_zn”)])

(define_expand “addhi3” [(set (match_operand:HI 0 “register_operand” "") (plus:HI (match_operand:HI 1 “register_operand” "") (match_operand:HI 2 “h8300_src_operand” "")))] "" "")

(define_insn “*addhi3_h8300” [(set (match_operand:HI 0 “register_operand” “=r,r,r,r,r”) (plus:HI (match_operand:HI 1 “register_operand” “%0,0,0,0,0”) (match_operand:HI 2 “h8300_src_operand” “L,N,J,n,r”)))] “TARGET_H8300” “@ adds %2,%T0 subs %G2,%T0 add.b %t2,%t0 add.b %s2,%s0;addx %t2,%t0 add.w %T2,%T0” [(set_attr “length” “2,2,2,4,2”) (set_attr “cc” “none_0hit,none_0hit,clobber,clobber,set_zn”)])

;; This splitter is very important to make the stack adjustment ;; interrupt-safe. The combination of add.b and addx is unsafe! ;; ;; We apply this split after the peephole2 pass so that we won't end ;; up creating too many adds/subs when a scratch register is ;; available, which is actually a common case because stack unrolling ;; tends to happen immediately after a function call.

(define_split [(set (match_operand:HI 0 “stack_pointer_operand” "") (plus:HI (match_dup 0) (match_operand 1 “const_int_gt_2_operand” "")))] “TARGET_H8300 && epilogue_completed” [(const_int 0)] { split_adds_subs (HImode, operands); DONE; })

(define_peephole2 [(match_scratch:HI 2 “r”) (set (match_operand:HI 0 “stack_pointer_operand” "") (plus:HI (match_dup 0) (match_operand:HI 1 “const_int_ge_8_operand” "")))] “TARGET_H8300” [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 2)))] "")

(define_insn “*addhi3_h8300hs” [(set (match_operand:HI 0 “register_operand” “=r,r,r,r,r”) (plus:HI (match_operand:HI 1 “register_operand” “%0,0,0,0,0”) (match_operand:HI 2 “h8300_src_operand” “L,N,J,n,r”)))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX” “@ adds %2,%S0 subs %G2,%S0 add.b %t2,%t0 add.w %T2,%T0 add.w %T2,%T0” [(set_attr “length” “2,2,2,4,2”) (set_attr “cc” “none_0hit,none_0hit,clobber,set_zn,set_zn”)])

(define_insn “*addhi3_incdec” [(set (match_operand:HI 0 “register_operand” “=r,r”) (unspec:HI [(match_operand:HI 1 “register_operand” “0,0”) (match_operand:HI 2 “incdec_operand” “M,O”)] UNSPEC_INCDEC))] “TARGET_H8300H || TARGET_H8300S” “@ inc.w %2,%T0 dec.w %G2,%T0” [(set_attr “length” “2,2”) (set_attr “cc” “set_zn,set_zn”)])

(define_insn “*addhi3_h8sx” [(set (match_operand:HI 0 “h8300_dst_operand” “=rU,rU,r,rQ”) (plus:HI (match_operand:HI 1 “h8300_dst_operand” “%0,0,0,0”) (match_operand:HI 2 “h8300_src_operand” “P3>X,P3<X,J,rQi”)))] “TARGET_H8300SX && h8300_operands_match_p (operands)” “@ add.w %T2:3,%T0 sub.w %G2:3,%T0 add.b %t2,%t0 add.w %T2,%T0” [(set_attr “length_table” “short_immediate,short_immediate,*,addw”) (set_attr “length” “,,2,*”) (set_attr “cc” “set_zn”)])

(define_split [(set (match_operand:HI 0 “register_operand” "") (plus:HI (match_dup 0) (match_operand:HI 1 “two_insn_adds_subs_operand” "")))] "" [(const_int 0)] { split_adds_subs (HImode, operands); DONE; })

(define_expand “addsi3” [(set (match_operand:SI 0 “register_operand” "") (plus:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “h8300_src_operand” "")))] "" "")

(define_insn “*addsi_h8300” [(set (match_operand:SI 0 “register_operand” “=r,r”) (plus:SI (match_operand:SI 1 “register_operand” “%0,0”) (match_operand:SI 2 “h8300_src_operand” “n,r”)))] “TARGET_H8300” { return output_plussi (operands); } [(set (attr “length”) (symbol_ref “compute_plussi_length (operands)”)) (set (attr “cc”) (symbol_ref “compute_plussi_cc (operands)”))])

(define_insn “*addsi_h8300hs” [(set (match_operand:SI 0 “h8300_dst_operand” “=rQ,rQ”) (plus:SI (match_operand:SI 1 “h8300_dst_operand” “%0,0”) (match_operand:SI 2 “h8300_src_operand” “i,rQ”)))] “(TARGET_H8300H || TARGET_H8300S) && h8300_operands_match_p (operands)” {
return output_plussi (operands); } [(set (attr “length”) (symbol_ref “compute_plussi_length (operands)”)) (set (attr “cc”) (symbol_ref “compute_plussi_cc (operands)”))])

(define_insn “*addsi3_incdec” [(set (match_operand:SI 0 “register_operand” “=r,r”) (unspec:SI [(match_operand:SI 1 “register_operand” “0,0”) (match_operand:SI 2 “incdec_operand” “M,O”)] UNSPEC_INCDEC))] “TARGET_H8300H || TARGET_H8300S” “@ inc.l %2,%S0 dec.l %G2,%S0” [(set_attr “length” “2,2”) (set_attr “cc” “set_zn,set_zn”)])

(define_split [(set (match_operand:SI 0 “register_operand” "") (plus:SI (match_dup 0) (match_operand:SI 1 “two_insn_adds_subs_operand” "")))] “TARGET_H8300H || TARGET_H8300S” [(const_int 0)] { split_adds_subs (SImode, operands); DONE; })

;; ---------------------------------------------------------------------- ;; SUBTRACT INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_expand “subqi3” [(set (match_operand:QI 0 “register_operand” "") (minus:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “h8300_src_operand” "")))] "" "")

(define_insn “*subqi3” [(set (match_operand:QI 0 “h8300_dst_operand” “=rQ”) (minus:QI (match_operand:QI 1 “h8300_dst_operand” “0”) (match_operand:QI 2 “h8300_dst_operand” “rQ”)))] “h8300_operands_match_p (operands)” “sub.b %X2,%X0” [(set_attr “length_table” “addb”) (set_attr “cc” “set_zn”)])

(define_expand “subhi3” [(set (match_operand:HI 0 “register_operand” "") (minus:HI (match_operand:HI 1 “register_operand” "") (match_operand:HI 2 “h8300_src_operand” "")))] "" "")

(define_insn “*subhi3_h8300” [(set (match_operand:HI 0 “register_operand” “=r,r”) (minus:HI (match_operand:HI 1 “register_operand” “0,0”) (match_operand:HI 2 “h8300_src_operand” “r,n”)))] “TARGET_H8300” “@ sub.w %T2,%T0 add.b %E2,%s0;addx %F2,%t0” [(set_attr “length” “2,4”) (set_attr “cc” “set_zn,clobber”)])

(define_insn “*subhi3_h8300hs” [(set (match_operand:HI 0 “h8300_dst_operand” “=rQ,rQ”) (minus:HI (match_operand:HI 1 “h8300_dst_operand” “0,0”) (match_operand:HI 2 “h8300_src_operand” “rQ,i”)))] “(TARGET_H8300H || TARGET_H8300S) && h8300_operands_match_p (operands)” “@ sub.w %T2,%T0 sub.w %T2,%T0” [(set_attr “length_table” “addw”) (set_attr “cc” “set_zn”)])

(define_expand “subsi3” [(set (match_operand:SI 0 “register_operand” "") (minus:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “h8300_src_operand” "")))] "" { if (TARGET_H8300) operands[2] = force_reg (SImode, operands[2]); })

(define_insn “*subsi3_h8300” [(set (match_operand:SI 0 “register_operand” “=r”) (minus:SI (match_operand:SI 1 “register_operand” “0”) (match_operand:SI 2 “register_operand” “r”)))] “TARGET_H8300” “sub.w %f2,%f0;subx %y2,%y0;subx %z2,%z0” [(set_attr “length” “6”)])

(define_insn “*subsi3_h8300hs” [(set (match_operand:SI 0 “h8300_dst_operand” “=rQ,rQ”) (minus:SI (match_operand:SI 1 “h8300_dst_operand” “0,0”) (match_operand:SI 2 “h8300_src_operand” “rQ,i”)))] “(TARGET_H8300H || TARGET_H8300S) && h8300_operands_match_p (operands)” “@ sub.l %S2,%S0 sub.l %S2,%S0” [(set_attr “length_table” “addl”) (set_attr “cc” “set_zn”)]) ;; ---------------------------------------------------------------------- ;; MULTIPLY INSTRUCTIONS ;; ----------------------------------------------------------------------

;; Note that the H8/300 can only handle umulqihi3.

(define_expand “mulqihi3” [(set (match_operand:HI 0 “register_operand” "") (mult:HI (sign_extend:HI (match_operand:QI 1 “register_operand” "")) ;; intentionally-mismatched modes (match_operand:QI 2 “reg_or_nibble_operand” "")))] “TARGET_H8300H || TARGET_H8300S” { if (GET_MODE (operands[2]) != VOIDmode) operands[2] = gen_rtx_SIGN_EXTEND (HImode, operands[2]); })

(define_insn “*mulqihi3_const” [(set (match_operand:HI 0 “register_operand” “=r”) (mult:HI (sign_extend:HI (match_operand:QI 1 “register_operand” “%0”)) (match_operand:QI 2 “nibble_operand” “IP4>X”)))] “TARGET_H8300SX” “mulxs.b %X2,%T0” [(set_attr “length” “4”) (set_attr “cc” “set_zn”)])

(define_insn “*mulqihi3” [(set (match_operand:HI 0 “register_operand” “=r”) (mult:HI (sign_extend:HI (match_operand:QI 1 “register_operand” “%0”)) (sign_extend:HI (match_operand:QI 2 “register_operand” “r”))))] “TARGET_H8300H || TARGET_H8300S” “mulxs.b %X2,%T0” [(set_attr “length” “4”) (set_attr “cc” “set_zn”)])

(define_expand “mulhisi3” [(set (match_operand:SI 0 “register_operand” "") (mult:SI (sign_extend:SI (match_operand:HI 1 “register_operand” "")) ;; intentionally-mismatched modes (match_operand:HI 2 “reg_or_nibble_operand” "")))] “TARGET_H8300H || TARGET_H8300S” { if (GET_MODE (operands[2]) != VOIDmode) operands[2] = gen_rtx_SIGN_EXTEND (SImode, operands[2]); })

(define_insn “*mulhisi3_const” [(set (match_operand:SI 0 “register_operand” “=r”) (mult:SI (sign_extend:SI (match_operand:HI 1 “register_operand” “%0”)) (match_operand:SI 2 “nibble_operand” “IP4>X”)))] “TARGET_H8300SX” “mulxs.w %T2,%S0” [(set_attr “length” “4”) (set_attr “cc” “set_zn”)])

(define_insn “*mulhisi3” [(set (match_operand:SI 0 “register_operand” “=r”) (mult:SI (sign_extend:SI (match_operand:HI 1 “register_operand” “%0”)) (sign_extend:SI (match_operand:HI 2 “register_operand” “r”))))] “TARGET_H8300H || TARGET_H8300S” “mulxs.w %T2,%S0” [(set_attr “length” “4”) (set_attr “cc” “set_zn”)])

(define_expand “umulqihi3” [(set (match_operand:HI 0 “register_operand” "") (mult:HI (zero_extend:HI (match_operand:QI 1 “register_operand” "")) ;; intentionally-mismatched modes (match_operand:QI 2 “reg_or_nibble_operand” "")))] “TARGET_H8300H || TARGET_H8300S” { if (GET_MODE (operands[2]) != VOIDmode) operands[2] = gen_rtx_ZERO_EXTEND (HImode, operands[2]); })

(define_insn “*umulqihi3_const” [(set (match_operand:HI 0 “register_operand” “=r”) (mult:HI (zero_extend:HI (match_operand:QI 1 “register_operand” “%0”)) (match_operand:QI 2 “nibble_operand” “IP4>X”)))] “TARGET_H8300SX” “mulxu.b %X2,%T0” [(set_attr “length” “4”) (set_attr “cc” “set_zn”)])

(define_insn “*umulqihi3” [(set (match_operand:HI 0 “register_operand” “=r”) (mult:HI (zero_extend:HI (match_operand:QI 1 “register_operand” “%0”)) (zero_extend:HI (match_operand:QI 2 “register_operand” “r”))))] "" “mulxu.b %X2,%T0” [(set_attr “length” “2”) (set_attr “cc” “none_0hit”)])

(define_expand “umulhisi3” [(set (match_operand:SI 0 “register_operand” "") (mult:SI (zero_extend:SI (match_operand:HI 1 “register_operand” "")) ;; intentionally-mismatched modes (match_operand:HI 2 “reg_or_nibble_operand” "")))] “TARGET_H8300H || TARGET_H8300S” { if (GET_MODE (operands[2]) != VOIDmode) operands[2] = gen_rtx_ZERO_EXTEND (SImode, operands[2]); })

(define_insn “*umulhisi3_const” [(set (match_operand:SI 0 “register_operand” “=r”) (mult:SI (zero_extend:SI (match_operand:HI 1 “register_operand” “%0”)) (match_operand:SI 2 “nibble_operand” “IP4>X”)))] “TARGET_H8300SX” “mulxu.w %T2,%S0” [(set_attr “length” “4”) (set_attr “cc” “set_zn”)])

(define_insn “*umulhisi3” [(set (match_operand:SI 0 “register_operand” “=r”) (mult:SI (zero_extend:SI (match_operand:HI 1 “register_operand” “%0”)) (zero_extend:SI (match_operand:HI 2 “register_operand” “r”))))] “TARGET_H8300H || TARGET_H8300S” “mulxu.w %T2,%S0” [(set_attr “length” “2”) (set_attr “cc” “none_0hit”)])

;; We could have used mulu.[wl] here, but mulu.[lw] is only available ;; on a H8SX with a multiplier, whereas muls.w seems to be available ;; on all H8SX variants.

(define_insn “mulhi3” [(set (match_operand:HI 0 “register_operand” “=r”) (mult:HI (match_operand:HI 1 “register_operand” “%0”) (match_operand:HI 2 “reg_or_nibble_operand” “r IP4>X”)))] “TARGET_H8300SX” “muls.w\t%T2,%T0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn “mulsi3” [(set (match_operand:SI 0 “register_operand” “=r”) (mult:SI (match_operand:SI 1 “register_operand” “%0”) (match_operand:SI 2 “reg_or_nibble_operand” “r IP4>X”)))] “TARGET_H8300SX” “muls.l\t%S2,%S0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn “smulsi3_highpart” [(set (match_operand:SI 0 “register_operand” “=r”) (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 “register_operand” “%0”)) (sign_extend:DI (match_operand:SI 2 “reg_or_nibble_operand” “r IP4>X”))) (const_int 32))))] “TARGET_H8300SXMUL” “muls/u.l\t%S2,%S0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn “umulsi3_highpart” [(set (match_operand:SI 0 “register_operand” “=r”) (truncate:SI (ashiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 “register_operand” “%0”)) (zero_extend:DI (match_operand:SI 2 “reg_or_nibble_operand” “r IP4>X”))) (const_int 32))))] “TARGET_H8300SX” “mulu/u.l\t%S2,%S0” [(set_attr “length” “2”) (set_attr “cc” “none_0hit”)])

;; This is a “bridge” instruction. Combine can‘t cram enough insns ;; together to crate a MAC instruction directly, but it can create ;; this instruction, which then allows combine to create the real ;; MAC insn. ;; ;; Unfortunately, if combine doesn’t create a MAC instruction, this ;; insn must generate reasonably correct code. Egad.

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=a”) (mult:SI (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 1 “register_operand” “r”)))) (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 2 “register_operand” “r”))))))] “TARGET_MAC” “clrmac;mac @%2+,@%1+” [(set_attr “length” “6”) (set_attr “cc” “none_0hit”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=a”) (plus:SI (mult:SI (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 1 “register_operand” “r”)))) (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 2 “register_operand” “r”))))) (match_operand:SI 3 “register_operand” “0”)))] “TARGET_MAC” “mac @%2+,@%1+” [(set_attr “length” “4”) (set_attr “cc” “none_0hit”)])

;; ---------------------------------------------------------------------- ;; DIVIDE/MOD INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn “udivhi3” [(set (match_operand:HI 0 “register_operand” “=r”) (udiv:HI (match_operand:HI 1 “register_operand” “0”) (match_operand:HI 2 “reg_or_nibble_operand” “r IP4>X”)))] “TARGET_H8300SX” “divu.w\t%T2,%T0” [(set_attr “length” “2”)])

(define_insn “divhi3” [(set (match_operand:HI 0 “register_operand” “=r”) (div:HI (match_operand:HI 1 “register_operand” “0”) (match_operand:HI 2 “reg_or_nibble_operand” “r IP4>X”)))] “TARGET_H8300SX” “divs.w\t%T2,%T0” [(set_attr “length” “2”)])

(define_insn “udivsi3” [(set (match_operand:SI 0 “register_operand” “=r”) (udiv:SI (match_operand:SI 1 “register_operand” “0”) (match_operand:SI 2 “reg_or_nibble_operand” “r IP4>X”)))] “TARGET_H8300SX” “divu.l\t%S2,%S0” [(set_attr “length” “2”)])

(define_insn “divsi3” [(set (match_operand:SI 0 “register_operand” “=r”) (div:SI (match_operand:SI 1 “register_operand” “0”) (match_operand:SI 2 “reg_or_nibble_operand” “r IP4>X”)))] “TARGET_H8300SX” “divs.l\t%S2,%S0” [(set_attr “length” “2”)])

(define_insn “udivmodqi4” [(set (match_operand:QI 0 “register_operand” “=r”) (truncate:QI (udiv:HI (match_operand:HI 1 “register_operand” “0”) (zero_extend:HI (match_operand:QI 2 “register_operand” “r”))))) (set (match_operand:QI 3 “register_operand” “=r”) (truncate:QI (umod:HI (match_dup 1) (zero_extend:HI (match_dup 2)))))] "" { if (find_reg_note (insn, REG_UNUSED, operands[3])) return “divxu.b\t%X2,%T0”; else return “divxu.b\t%X2,%T0;mov.b\t%t0,%s3”; } [(set_attr “length” “4”)])

(define_insn “divmodqi4” [(set (match_operand:QI 0 “register_operand” “=r”) (truncate:QI (div:HI (match_operand:HI 1 “register_operand” “0”) (sign_extend:HI (match_operand:QI 2 “register_operand” “r”))))) (set (match_operand:QI 3 “register_operand” “=r”) (truncate:QI (mod:HI (match_dup 1) (sign_extend:HI (match_dup 2)))))] “TARGET_H8300H || TARGET_H8300S” { if (find_reg_note (insn, REG_UNUSED, operands[3])) return “divxs.b\t%X2,%T0”; else return “divxs.b\t%X2,%T0;mov.b\t%t0,%s3”; } [(set_attr “length” “6”)])

(define_insn “udivmodhi4” [(set (match_operand:HI 0 “register_operand” “=r”) (truncate:HI (udiv:SI (match_operand:SI 1 “register_operand” “0”) (zero_extend:SI (match_operand:HI 2 “register_operand” “r”))))) (set (match_operand:HI 3 “register_operand” “=r”) (truncate:HI (umod:SI (match_dup 1) (zero_extend:SI (match_dup 2)))))] “TARGET_H8300H || TARGET_H8300S” { if (find_reg_note (insn, REG_UNUSED, operands[3])) return “divxu.w\t%T2,%S0”; else return “divxu.w\t%T2,%S0;mov.w\t%e0,%f3”; } [(set_attr “length” “4”)])

(define_insn “divmodhi4” [(set (match_operand:HI 0 “register_operand” “=r”) (truncate:HI (div:SI (match_operand:SI 1 “register_operand” “0”) (sign_extend:SI (match_operand:HI 2 “register_operand” “r”))))) (set (match_operand:HI 3 “register_operand” “=r”) (truncate:HI (mod:SI (match_dup 1) (sign_extend:SI (match_dup 2)))))] “TARGET_H8300H || TARGET_H8300S” { if (find_reg_note (insn, REG_UNUSED, operands[3])) return “divxs.w\t%T2,%S0”; else return “divxs.w\t%T2,%S0;mov.w\t%e0,%f3”; } [(set_attr “length” “6”)]) ;; ---------------------------------------------------------------------- ;; AND INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn “bclrqi_msx” [(set (match_operand:QI 0 “bit_register_indirect_operand” “=WU”) (and:QI (match_operand:QI 1 “bit_register_indirect_operand” “%0”) (match_operand:QI 2 “single_zero_operand” “Y0”)))] “TARGET_H8300SX && rtx_equal_p (operands[0], operands[1])” “bclr\t%W2,%0” [(set_attr “length” “8”)])

(define_split [(set (match_operand:HI 0 “bit_register_indirect_operand”) (and:HI (match_operand:HI 1 “bit_register_indirect_operand”) (match_operand:HI 2 “single_zero_operand”)))] “TARGET_H8300SX” [(set (match_dup 0) (and:QI (match_dup 1) (match_dup 2)))] { if (abs (INTVAL (operands[2])) > 0xFF) { operands[0] = adjust_address (operands[0], QImode, 0); operands[1] = adjust_address (operands[1], QImode, 0); operands[2] = GEN_INT ((INTVAL (operands[2])) >> 8); } else { operands[0] = adjust_address (operands[0], QImode, 1); operands[1] = adjust_address (operands[1], QImode, 1); } })

(define_insn “bclrhi_msx” [(set (match_operand:HI 0 “bit_register_indirect_operand” “=m”) (and:HI (match_operand:HI 1 “bit_register_indirect_operand” “%0”) (match_operand:HI 2 “single_zero_operand” “Y0”)))] “TARGET_H8300SX” “bclr\t%W2,%0” [(set_attr “length” “8”)])

(define_insn “*andqi3_2” [(set (match_operand:QI 0 “bit_operand” “=U,rQ,r”) (and:QI (match_operand:QI 1 “bit_operand” “%0,0,WU”) (match_operand:QI 2 “h8300_src_operand” “Y0,rQi,IP1>X”)))] “TARGET_H8300SX” “@ bclr\t %W2,%R0 and %X2,%X0 bfld %2,%1,%R0” [(set_attr “length” “8,*,8”) (set_attr “length_table” “,logicb,”) (set_attr “cc” “none_0hit,set_znv,none_0hit”)])

(define_insn “andqi3_1” [(set (match_operand:QI 0 “bit_operand” “=U,r”) (and:QI (match_operand:QI 1 “bit_operand” “%0,0”) (match_operand:QI 2 “h8300_src_operand” “Y0,rn”)))] “register_operand (operands[0], QImode) || single_zero_operand (operands[2], QImode)” “@ bclr %W2,%R0 and %X2,%X0” [(set_attr “length” “2,8”) (set_attr “cc” “none_0hit,set_znv”)])

(define_expand “andqi3” [(set (match_operand:QI 0 “register_operand” "") (and:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “h8300_src_operand” "")))] "" "")

(define_expand “andhi3” [(set (match_operand:HI 0 “register_operand” "") (and:HI (match_operand:HI 1 “register_operand” "") (match_operand:HI 2 “h8300_src_operand” "")))] "" "")

(define_insn “*andorqi3” [(set (match_operand:QI 0 “register_operand” “=r”) (ior:QI (and:QI (match_operand:QI 2 “register_operand” “r”) (match_operand:QI 3 “single_one_operand” “n”)) (match_operand:QI 1 “register_operand” “0”)))] "" “bld\t%V3,%X2;bor\t%V3,%X0;bst\t%V3,%X0” [(set_attr “length” “6”)])

(define_insn “*andorhi3” [(set (match_operand:HI 0 “register_operand” “=r”) (ior:HI (and:HI (match_operand:HI 2 “register_operand” “r”) (match_operand:HI 3 “single_one_operand” “n”)) (match_operand:HI 1 “register_operand” “0”)))] "" { operands[3] = GEN_INT (INTVAL (operands[3]) & 0xffff); if (INTVAL (operands[3]) > 128) { operands[3] = GEN_INT (INTVAL (operands[3]) >> 8); return “bld\t%V3,%t2;bor\t%V3,%t0;bst\t%V3,%t0”; } return “bld\t%V3,%s2;bor\t%V3,%s0;bst\t%V3,%s0”; } [(set_attr “length” “6”)])

(define_insn “*andorsi3” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (and:SI (match_operand:SI 2 “register_operand” “r”) (match_operand:SI 3 “single_one_operand” “n”)) (match_operand:SI 1 “register_operand” “0”)))] “(INTVAL (operands[3]) & 0xffff) != 0” { operands[3] = GEN_INT (INTVAL (operands[3]) & 0xffff); if (INTVAL (operands[3]) > 128) { operands[3] = GEN_INT (INTVAL (operands[3]) >> 8); return “bld\t%V3,%x2;bor\t%V3,%x0;bst\t%V3,%x0”; } return “bld\t%V3,%w2;bor\t%V3,%w0;bst\t%V3,%w0”; } [(set_attr “length” “6”)])

(define_insn “*andorsi3_shift_8” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (and:SI (ashift:SI (match_operand:SI 2 “register_operand” “r”) (const_int 8)) (const_int 65280)) (match_operand:SI 1 “register_operand” “0”)))] "" “or.b\t%w2,%x0” [(set_attr “length” “2”)])

(define_expand “andsi3” [(set (match_operand:SI 0 “register_operand” "") (and:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “h8300_src_operand” "")))] "" "")

;; ---------------------------------------------------------------------- ;; OR INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn “bsetqi_msx” [(set (match_operand:QI 0 “bit_register_indirect_operand” “=WU”) (ior:QI (match_operand:QI 1 “bit_register_indirect_operand” “%0”) (match_operand:QI 2 “single_one_operand” “Y2”)))] “TARGET_H8300SX && rtx_equal_p (operands[0], operands[1])” “bset\t%V2,%0” [(set_attr “length” “8”)])

(define_split [(set (match_operand:HI 0 “bit_register_indirect_operand”) (ior:HI (match_operand:HI 1 “bit_register_indirect_operand”) (match_operand:HI 2 “single_one_operand”)))] “TARGET_H8300SX” [(set (match_dup 0) (ior:QI (match_dup 1) (match_dup 2)))] { if (abs (INTVAL (operands[2])) > 0xFF) { operands[0] = adjust_address (operands[0], QImode, 0); operands[1] = adjust_address (operands[1], QImode, 0); operands[2] = GEN_INT ((INTVAL (operands[2])) >> 8); } else { operands[0] = adjust_address (operands[0], QImode, 1); operands[1] = adjust_address (operands[1], QImode, 1); } })

(define_insn “bsethi_msx” [(set (match_operand:HI 0 “bit_register_indirect_operand” “=m”) (ior:HI (match_operand:HI 1 “bit_register_indirect_operand” “%0”) (match_operand:HI 2 “single_one_operand” “Y2”)))] “TARGET_H8300SX” “bset\t%V2,%0” [(set_attr “length” “8”)])

(define_insn “iorqi3_1” [(set (match_operand:QI 0 “bit_operand” “=U,rQ”) (ior:QI (match_operand:QI 1 “bit_operand” “%0,0”) (match_operand:QI 2 “h8300_src_operand” “Y2,rQi”)))] “TARGET_H8300SX || register_operand (operands[0], QImode) || single_one_operand (operands[2], QImode)” “@ bset\t%V2,%R0 or\t%X2,%X0” [(set_attr “length” “8,*”) (set_attr “length_table” “*,logicb”) (set_attr “cc” “none_0hit,set_znv”)])

(define_expand “iorqi3” [(set (match_operand:QI 0 “register_operand” "") (ior:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “h8300_src_operand” "")))] "" "")

(define_expand “iorhi3” [(set (match_operand:HI 0 “register_operand” "") (ior:HI (match_operand:HI 1 “register_operand” "") (match_operand:HI 2 “h8300_src_operand” "")))] "" "")

(define_expand “iorsi3” [(set (match_operand:SI 0 “register_operand” "") (ior:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “h8300_src_operand” "")))] "" "")

;; ---------------------------------------------------------------------- ;; XOR INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn “bnotqi_msx” [(set (match_operand:QI 0 “bit_register_indirect_operand” “=WU”) (xor:QI (match_operand:QI 1 “bit_register_indirect_operand” “%0”) (match_operand:QI 2 “single_one_operand” “Y2”)))] “TARGET_H8300SX && rtx_equal_p (operands[0], operands[1])” “bnot\t%V2,%0” [(set_attr “length” “8”)])

(define_split [(set (match_operand:HI 0 “bit_register_indirect_operand”) (xor:HI (match_operand:HI 1 “bit_register_indirect_operand”) (match_operand:HI 2 “single_one_operand”)))] “TARGET_H8300SX” [(set (match_dup 0) (xor:QI (match_dup 1) (match_dup 2)))] { if (abs (INTVAL (operands[2])) > 0xFF) { operands[0] = adjust_address (operands[0], QImode, 0); operands[1] = adjust_address (operands[1], QImode, 0); operands[2] = GEN_INT ((INTVAL (operands[2])) >> 8); } else { operands[0] = adjust_address (operands[0], QImode, 1); operands[1] = adjust_address (operands[1], QImode, 1); } })

(define_insn “bnothi_msx” [(set (match_operand:HI 0 “bit_register_indirect_operand” “=m”) (xor:HI (match_operand:HI 1 “bit_register_indirect_operand” “%0”) (match_operand:HI 2 “single_one_operand” “Y2”)))] “TARGET_H8300SX” “bnot\t%V2,%0” [(set_attr “length” “8”)])

(define_insn “xorqi3_1” [(set (match_operand:QI 0 “bit_operand” “=U,r”) (xor:QI (match_operand:QI 1 “bit_operand” “%0,0”) (match_operand:QI 2 “h8300_src_operand” “Y2,rQi”)))] “TARGET_H8300SX || register_operand (operands[0], QImode) || single_one_operand (operands[2], QImode)” “@ bnot\t%V2,%R0 xor\t%X2,%X0” [(set_attr “length” “8,*”) (set_attr “length_table” “*,logicb”) (set_attr “cc” “none_0hit,set_znv”)])

(define_expand “xorqi3” [(set (match_operand:QI 0 “register_operand” "") (xor:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “h8300_src_operand” "")))] "" "")

(define_expand “xorhi3” [(set (match_operand:HI 0 “register_operand” "") (xor:HI (match_operand:HI 1 “register_operand” "") (match_operand:HI 2 “h8300_src_operand” "")))] "" "")

(define_expand “xorsi3” [(set (match_operand:SI 0 “register_operand” "") (xor:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “h8300_src_operand” "")))] "" "")

;; ---------------------------------------------------------------------- ;; {AND,IOR,XOR}{HI3,SI3} PATTERNS ;; ----------------------------------------------------------------------

;; We need a separate pattern here because machines other than the ;; original H8300 don't have to split the 16-bit operand into a pair ;; of high/low instructions, so we can accept literal addresses, that ;; have to be loaded into a register on H8300.

(define_insn “*logicalhi3_sn” [(set (match_operand:HI 0 “h8300_dst_operand” “=rQ”) (match_operator:HI 3 “bit_operator” [(match_operand:HI 1 “h8300_dst_operand” “%0”) (match_operand:HI 2 “h8300_src_operand” “rQi”)]))] “(TARGET_H8300S || TARGET_H8300H) && h8300_operands_match_p (operands)” { return output_logical_op (HImode, operands); } [(set (attr “length”) (symbol_ref “compute_logical_op_length (HImode, operands)”)) (set (attr “cc”) (symbol_ref “compute_logical_op_cc (HImode, operands)”))])

(define_insn “*logicalsi3_sn” [(set (match_operand:SI 0 “h8300_dst_operand” “=rQ”) (match_operator:SI 3 “bit_operator” [(match_operand:SI 1 “h8300_dst_operand” “%0”) (match_operand:SI 2 “h8300_src_operand” “rQi”)]))] “(TARGET_H8300S || TARGET_H8300H) && h8300_operands_match_p (operands)” { return output_logical_op (SImode, operands); } [(set (attr “length”) (symbol_ref “compute_logical_op_length (SImode, operands)”)) (set (attr “cc”) (symbol_ref “compute_logical_op_cc (SImode, operands)”))])

(define_insn “*logicalhi3” [(set (match_operand:HI 0 “h8300_dst_operand” “=rQ”) (match_operator:HI 3 “bit_operator” [(match_operand:HI 1 “h8300_dst_operand” “%0”) (match_operand:HI 2 “h8300_src_operand” “rQi”)]))] “h8300_operands_match_p (operands)” { return output_logical_op (HImode, operands); } [(set (attr “length”) (symbol_ref “compute_logical_op_length (HImode, operands)”)) (set (attr “cc”) (symbol_ref “compute_logical_op_cc (HImode, operands)”))])

(define_insn “*logicalsi3” [(set (match_operand:SI 0 “h8300_dst_operand” “=rQ”) (match_operator:SI 3 “bit_operator” [(match_operand:SI 1 “h8300_dst_operand” “%0”) (match_operand:SI 2 “h8300_src_operand” “rQi”)]))] “h8300_operands_match_p (operands)” { return output_logical_op (SImode, operands); } [(set (attr “length”) (symbol_ref “compute_logical_op_length (SImode, operands)”)) (set (attr “cc”) (symbol_ref “compute_logical_op_cc (SImode, operands)”))]) ;; ---------------------------------------------------------------------- ;; NEGATION INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_expand “negqi2” [(set (match_operand:QI 0 “register_operand” "") (neg:QI (match_operand:QI 1 “register_operand” "")))] "" "")

(define_insn “*negqi2” [(set (match_operand:QI 0 “h8300_dst_operand” “=rQ”) (neg:QI (match_operand:QI 1 “h8300_dst_operand” “0”)))] "" “neg %X0” [(set_attr “length_table” “unary”) (set_attr “cc” “set_zn”)])

(define_expand “neghi2” [(set (match_operand:HI 0 “register_operand” "") (neg:HI (match_operand:HI 1 “register_operand” "")))] "" { if (TARGET_H8300) { emit_insn (gen_neghi2_h8300 (operands[0], operands[1])); DONE; } })

(define_expand “neghi2_h8300” [(set (match_dup 2) (not:HI (match_operand:HI 1 “register_operand” ""))) (set (match_dup 2) (plus:HI (match_dup 2) (const_int 1))) (set (match_operand:HI 0 “register_operand” "") (match_dup 2))] "" { operands[2] = gen_reg_rtx (HImode); })

(define_insn “*neghi2_h8300hs” [(set (match_operand:HI 0 “h8300_dst_operand” “=rQ”) (neg:HI (match_operand:HI 1 “h8300_dst_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && h8300_operands_match_p (operands)” “neg.w %T0” [(set_attr “length_table” “unary”) (set_attr “cc” “set_zn”)])

(define_expand “negsi2” [(set (match_operand:SI 0 “register_operand” "") (neg:SI (match_operand:SI 1 “register_operand” "")))] "" { if (TARGET_H8300) { emit_insn (gen_negsi2_h8300 (operands[0], operands[1])); DONE; } })

(define_expand “negsi2_h8300” [(set (match_dup 2) (not:SI (match_operand:SI 1 “register_operand” ""))) (set (match_dup 2) (plus:SI (match_dup 2) (const_int 1))) (set (match_operand:SI 0 “register_operand” "") (match_dup 2))] "" { operands[2] = gen_reg_rtx (SImode); })

(define_insn “*negsi2_h8300hs” [(set (match_operand:SI 0 “h8300_dst_operand” “=rQ”) (neg:SI (match_operand:SI 1 “h8300_dst_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && h8300_operands_match_p (operands)” “neg.l %S0” [(set_attr “length_table” “unary”) (set_attr “cc” “set_zn”)])

(define_expand “negsf2” [(set (match_operand:SF 0 “register_operand” "") (neg:SF (match_operand:SF 1 “register_operand” "")))] "" "")

(define_insn “*negsf2_h8300” [(set (match_operand:SF 0 “register_operand” “=r”) (neg:SF (match_operand:SF 1 “register_operand” “0”)))] “TARGET_H8300” “xor.b\t#128,%z0” [(set_attr “length” “2”)])

(define_insn “*negsf2_h8300hs” [(set (match_operand:SF 0 “register_operand” “=r”) (neg:SF (match_operand:SF 1 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “xor.w\t#32768,%e0” [(set_attr “length” “4”)]) ;; ---------------------------------------------------------------------- ;; ABSOLUTE VALUE INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_expand “abssf2” [(set (match_operand:SF 0 “register_operand” "") (abs:SF (match_operand:SF 1 “register_operand” "")))] "" "")

(define_insn “*abssf2_h8300” [(set (match_operand:SF 0 “register_operand” “=r”) (abs:SF (match_operand:SF 1 “register_operand” “0”)))] “TARGET_H8300” “and.b\t#127,%z0” [(set_attr “length” “2”)])

(define_insn “*abssf2_h8300hs” [(set (match_operand:SF 0 “register_operand” “=r”) (abs:SF (match_operand:SF 1 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “and.w\t#32767,%e0” [(set_attr “length” “4”)]) ;; ---------------------------------------------------------------------- ;; NOT INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_expand “one_cmplqi2” [(set (match_operand:QI 0 “register_operand” "") (not:QI (match_operand:QI 1 “register_operand” "")))] "" "")

(define_insn “*one_cmplqi2” [(set (match_operand:QI 0 “h8300_dst_operand” “=rQ”) (not:QI (match_operand:QI 1 “h8300_dst_operand” “0”)))] "" “not %X0” [(set_attr “length_table” “unary”) (set_attr “cc” “set_znv”)])

(define_expand “one_cmplhi2” [(set (match_operand:HI 0 “register_operand” "") (not:HI (match_operand:HI 1 “register_operand” "")))] "" "")

(define_insn “*one_cmplhi2_h8300” [(set (match_operand:HI 0 “register_operand” “=r”) (not:HI (match_operand:HI 1 “register_operand” “0”)))] “TARGET_H8300” “not %s0;not %t0” [(set_attr “length” “4”)])

(define_insn “*one_cmplhi2_h8300hs” [(set (match_operand:HI 0 “h8300_dst_operand” “=rQ”) (not:HI (match_operand:HI 1 “h8300_dst_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && h8300_operands_match_p (operands)” “not.w %T0” [(set_attr “cc” “set_znv”) (set_attr “length_table” “unary”)])

(define_expand “one_cmplsi2” [(set (match_operand:SI 0 “register_operand” "") (not:SI (match_operand:SI 1 “register_operand” "")))] "" "")

(define_insn “*one_cmplsi2_h8300” [(set (match_operand:SI 0 “register_operand” “=r”) (not:SI (match_operand:SI 1 “register_operand” “0”)))] “TARGET_H8300” “not %w0;not %x0;not %y0;not %z0” [(set_attr “length” “8”)])

(define_insn “*one_cmplsi2_h8300hs” [(set (match_operand:SI 0 “h8300_dst_operand” “=rQ”) (not:SI (match_operand:SI 1 “h8300_dst_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && h8300_operands_match_p (operands)” “not.l %S0” [(set_attr “cc” “set_znv”) (set_attr “length_table” “unary”)]) ;; ---------------------------------------------------------------------- ;; JUMP INSTRUCTIONS ;; ----------------------------------------------------------------------

;; Conditional jump instructions

(define_expand “cbranchqi4” [(use (match_operator 0 “ordered_comparison_operator” [(match_operand:QI 1 “h8300_dst_operand” "") (match_operand:QI 2 “h8300_src_operand” "")])) (use (match_operand 3 ""))] "" { h8300_expand_branch (operands); DONE; })

(define_expand “cbranchhi4” [(use (match_operator 0 “ordered_comparison_operator” [(match_operand:HI 1 “h8300_dst_operand” "") (match_operand:HI 2 “h8300_src_operand” "")])) (use (match_operand 3 ""))] "" { /* Force operand1 into a register if we're compiling for the H8/300. */ if ((GET_CODE (operands[2]) != REG && operands[2] != const0_rtx) && TARGET_H8300) operands[2] = force_reg (HImode, operands[2]); h8300_expand_branch (operands); DONE; })

(define_expand “cbranchsi4” [(use (match_operator 0 “ordered_comparison_operator” [(match_operand:SI 1 “h8300_dst_operand” "") (match_operand:SI 2 “h8300_src_operand” "")])) (use (match_operand 3 ""))] “TARGET_H8300H || TARGET_H8300S” { h8300_expand_branch (operands); DONE; })

(define_insn “branch_true” [(set (pc) (if_then_else (match_operator 1 “comparison_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] "" { if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 && (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE || GET_CODE (operands[1]) == LE || GET_CODE (operands[1]) == LT)) { cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; return 0; }

if (get_attr_length (insn) == 2) return “b%j1 %l0”; else if (get_attr_length (insn) == 4) return “b%j1 %l0:16”; else return “b%k1 .Lh8BR%=;jmp @%l0\n.Lh8BR%=:”; } [(set_attr “type” “branch”) (set_attr “cc” “none”)])

(define_insn “branch_false” [(set (pc) (if_then_else (match_operator 1 “comparison_operator” [(cc0) (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] "" { if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 && (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE || GET_CODE (operands[1]) == LE || GET_CODE (operands[1]) == LT)) { cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; return 0; }

if (get_attr_length (insn) == 2) return “b%k1 %l0”; else if (get_attr_length (insn) == 4) return “b%k1 %l0:16”; else return “b%j1 .Lh8BR%=;jmp @%l0\n.Lh8BR%=:”; } [(set_attr “type” “branch”) (set_attr “cc” “none”)])

(define_insn “*brabc” [(set (pc) (if_then_else (eq (zero_extract (match_operand:QI 1 “bit_memory_operand” “WU”) (const_int 1) (match_operand:QI 2 “immediate_operand” “n”)) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] “TARGET_H8300SX” { switch (get_attr_length (insn) - h8300_insn_length_from_table (insn, operands)) { case 2: return “bra/bc %2,%R1,%l0”; case 4: return “bra/bc %2,%R1,%l0:16”; default: return “bra/bs %2,%R1,.Lh8BR%=;jmp @%l0\n.Lh8BR%=:”; } } [(set_attr “type” “bitbranch”) (set_attr “length_table” “bitbranch”) (set_attr “cc” “none”)])

(define_insn “*brabs” [(set (pc) (if_then_else (ne (zero_extract (match_operand:QI 1 “bit_memory_operand” “WU”) (const_int 1) (match_operand:QI 2 “immediate_operand” “n”)) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] “TARGET_H8300SX” { switch (get_attr_length (insn) - h8300_insn_length_from_table (insn, operands)) { case 2: return “bra/bs %2,%R1,%l0”; case 4: return “bra/bs %2,%R1,%l0:16”; default: return “bra/bc %2,%R1,.Lh8BR%=;jmp @%l0\n.Lh8BR%=:”; } } [(set_attr “type” “bitbranch”) (set_attr “length_table” “bitbranch”) (set_attr “cc” “none”)])

;; Unconditional and other jump instructions.

(define_insn “jump” [(set (pc) (label_ref (match_operand 0 "" "")))] "" { if (final_sequence != 0) { if (get_attr_length (insn) == 2) return “bra/s %l0”; else { /* The branch isn't short enough to use bra/s. Output the branch and delay slot in their normal order.

     If this is a backward branch, it will now be branching two
     bytes further than previously thought.  The length-based
     test for bra vs. jump is very conservative though, so the
     branch will still be within range.  */
  rtx_sequence *seq;
  int seen;

  seq = final_sequence;
  final_sequence = 0;
  final_scan_insn (seq->insn (1), asm_out_file, optimize, 1, & seen);
  final_scan_insn (seq->insn (0), asm_out_file, optimize, 1, & seen);
  seq->insn (1)->set_deleted ();
  return "";
}
}

else if (get_attr_length (insn) == 2) return “bra %l0”; else if (get_attr_length (insn) == 4) return “bra %l0:16”; else return “jmp @%l0”; } [(set_attr “type” “branch”) (set (attr “delay_slot”) (if_then_else (match_test “TARGET_H8300SX”) (const_string “jump”) (const_string “none”))) (set_attr “cc” “none”)])

;; This is a define expand, because pointers may be either 16 or 32 bits.

(define_expand “tablejump” [(parallel [(set (pc) (match_operand 0 “register_operand” "")) (use (label_ref (match_operand 1 "" "")))])] "" "")

(define_insn “*tablejump_h8300” [(set (pc) (match_operand:HI 0 “register_operand” “r”)) (use (label_ref (match_operand 1 "" "")))] “TARGET_H8300” “jmp @%0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

(define_insn “*tablejump_h8300hs_advanced” [(set (pc) (match_operand:SI 0 “register_operand” “r”)) (use (label_ref (match_operand 1 "" "")))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_NORMAL_MODE” “jmp @%0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

(define_insn “*tablejump_h8300hs_normal” [(set (pc) (match_operand:HI 0 “register_operand” “r”)) (use (label_ref (match_operand 1 "" "")))] “(TARGET_H8300H || TARGET_H8300S) && TARGET_NORMAL_MODE” “jmp @%S0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

;; This is a define expand, because pointers may be either 16 or 32 bits.

(define_expand “indirect_jump” [(set (pc) (match_operand 0 “jump_address_operand” ""))] "" "")

(define_insn “*indirect_jump_h8300” [(set (pc) (match_operand:HI 0 “jump_address_operand” “Vr”))] “TARGET_H8300” “jmp @%0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

(define_insn “*indirect_jump_h8300hs_advanced” [(set (pc) (match_operand:SI 0 “jump_address_operand” “Vr”))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_NORMAL_MODE” “jmp @%0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

(define_insn “*indirect_jump_h8300hs_normal” [(set (pc) (match_operand:HI 0 “jump_address_operand” “Vr”))] “(TARGET_H8300H || TARGET_H8300S) && TARGET_NORMAL_MODE” “jmp @%S0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

;; Call subroutine with no return value.

;; ??? Even though we use HImode here, this works on the H8/300H and H8S.

(define_insn “call” [(call (match_operand:QI 0 “call_insn_operand” “or”) (match_operand:HI 1 “general_operand” “g”))] "" { if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF && (SYMBOL_REF_FLAGS (XEXP (operands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) return “jsr\t@%0:8”; else return “jsr\t%0”; } [(set_attr “type” “call”) (set (attr “length”) (if_then_else (match_operand:QI 0 “small_call_insn_operand” "") (const_int 2) (const_int 4)))])

;; Call subroutine, returning value in operand 0 ;; (which must be a hard register).

;; ??? Even though we use HImode here, this works on the H8/300H and H8S.

(define_insn “call_value” [(set (match_operand 0 "" “=r”) (call (match_operand:QI 1 “call_insn_operand” “or”) (match_operand:HI 2 “general_operand” “g”)))] "" { if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF && (SYMBOL_REF_FLAGS (XEXP (operands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) return “jsr\t@%1:8”; else return “jsr\t%1”; } [(set_attr “type” “call”) (set (attr “length”) (if_then_else (match_operand:QI 0 “small_call_insn_operand” "") (const_int 2) (const_int 4)))])

(define_insn “nop” [(const_int 0)] "" “nop” [(set_attr “cc” “none”) (set_attr “length” “2”)]) ;; ---------------------------------------------------------------------- ;; PROLOGUE/EPILOGUE-RELATED INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_expand “push_h8300” [(set (mem:HI (pre_dec:HI (reg:HI SP_REG))) (match_operand:HI 0 “register_operand” ""))] “TARGET_H8300” "")

(define_expand “push_h8300hs_advanced” [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 0 “register_operand” ""))] “TARGET_H8300H && TARGET_H8300S && !TARGET_NORMAL_MODE” "")

(define_expand “push_h8300hs_normal” [(set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 0 “register_operand” ""))] “TARGET_H8300H && TARGET_H8300S && TARGET_NORMAL_MODE” "")

(define_expand “pop_h8300” [(set (match_operand:HI 0 “register_operand” "") (mem:HI (post_inc:HI (reg:HI SP_REG))))] “TARGET_H8300” "")

(define_expand “pop_h8300hs_advanced” [(set (match_operand:SI 0 “register_operand” "") (mem:SI (post_inc:SI (reg:SI SP_REG))))] “TARGET_H8300H && TARGET_H8300S && !TARGET_NORMAL_MODE” "")

(define_expand “pop_h8300hs_normal” [(set (match_operand:SI 0 “register_operand” "") (mem:SI (post_inc:HI (reg:HI SP_REG))))] “TARGET_H8300H && TARGET_H8300S && TARGET_NORMAL_MODE” "")

(define_insn “ldm_h8300sx” [(match_parallel 0 “h8300_ldm_parallel” [(set (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “memory_operand” ""))])] “TARGET_H8300S” { operands[3] = SET_DEST (XVECEXP (operands[0], 0, XVECLEN (operands[0], 0) - 2)); return “ldm.l\t@er7+,%S1-%S3”; } [(set_attr “cc” “none”) (set_attr “length” “4”)])

(define_insn “stm_h8300sx” [(match_parallel 0 “h8300_stm_parallel” [(set (match_operand:SI 1 “memory_operand” "") (match_operand:SI 2 “register_operand” ""))])] “TARGET_H8300S” { operands[3] = SET_SRC (XVECEXP (operands[0], 0, XVECLEN (operands[0], 0) - 2)); return “stm.l\t%S2-%S3,@-er7”; } [(set_attr “cc” “none”) (set_attr “length” “4”)])

(define_insn “return_h8sx” [(match_parallel 0 “h8300_return_parallel” [(return) (set (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “memory_operand” ""))])] “TARGET_H8300SX” { operands[3] = SET_DEST (XVECEXP (operands[0], 0, XVECLEN (operands[0], 0) - 2)); if (h8300_current_function_interrupt_function_p () || h8300_current_function_monitor_function_p ()) return “rte/l\t%S1-%S3”; else return “rts/l\t%S1-%S3”; } [(set_attr “cc” “none”) (set_attr “can_delay” “no”) (set_attr “length” “2”)])

(define_expand “return” [(return)] “h8300_can_use_return_insn_p ()” "")

(define_insn “*return_1” [(return)] “reload_completed” { if (h8300_current_function_interrupt_function_p () || h8300_current_function_monitor_function_p ()) return “rte”; else return “rts”; } [(set_attr “cc” “none”) (set_attr “can_delay” “no”) (set_attr “length” “2”)])

(define_expand “prologue” [(const_int 0)] "" { h8300_expand_prologue (); DONE; })

(define_expand “epilogue” [(return)] "" { h8300_expand_epilogue (); DONE; })

(define_insn “monitor_prologue” [(unspec_volatile [(const_int 0)] UNSPEC_MONITOR)] "" { if (TARGET_H8300) return “subs\t#2,r7;mov.w\tr0,@-r7;stc\tccr,r0l;mov.b\tr0l,@(2,r7);mov.w\t@r7+,r0;orc\t#128,ccr”; else if (TARGET_H8300H && TARGET_NORMAL_MODE) return “subs\t#2,er7;mov.l\ter0,@-er7;stc\tccr,r0l;mov.b\tr0l,@(4,er7);mov.l\t@er7+,er0;orc\t#128,ccr”; else if (TARGET_H8300H) return “mov.l\ter0,@-er7;stc\tccr,r0l;mov.b\tr0l,@(4,er7);mov.l\t@er7+,er0;orc\t#128,ccr”; else if (TARGET_H8300S && TARGET_NEXR ) return “mov.l\ter0,@-er7;stc\tccr,r0l;mov.b\tr0l,@(4,er7);mov.l\t@er7+,er0;orc\t#128,ccr”; else if (TARGET_H8300S && TARGET_NEXR && TARGET_NORMAL_MODE) return “subs\t#2,er7;mov.l\ter0,@-er7;stc\tccr,r0l;mov.b\tr0l,@(4,er7);mov.l\t@er7+,er0;orc\t#128,ccr”; else if (TARGET_H8300S && TARGET_NORMAL_MODE) return “subs\t#2,er7;stc\texr,@-er7;mov.l\ter0,@-er7;stc\tccr,r0l;mov.b\tr0l,@(6,er7);mov.l\t@er7+,er0;orc\t#128,ccr”; else if (TARGET_H8300S) return “stc\texr,@-er7;mov.l\ter0,@-er7;stc\tccr,r0l;mov.b\tr0l,@(6,er7);mov.l\t@er7+,er0;orc\t#128,ccr”; gcc_unreachable (); } [(set_attr “length” “20”)]) ;; ---------------------------------------------------------------------- ;; EXTEND INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_expand “zero_extendqihi2” [(set (match_operand:HI 0 “register_operand” "") (zero_extend:HI (match_operand:QI 1 “general_operand_src” "")))] "" "")

(define_insn “*zero_extendqihi2_h8300” [(set (match_operand:HI 0 “register_operand” “=r,r”) (zero_extend:HI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ mov.b #0,%t0 #” [(set_attr “length” “2,10”)])

(define_insn “*zero_extendqihi2_h8300hs” [(set (match_operand:HI 0 “register_operand” “=r,r”) (zero_extend:HI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300H || TARGET_H8300S” “@ extu.w %T0 #” [(set_attr “length” “2,10”) (set_attr “cc” “set_znv,set_znv”)])

;; Split the zero extension of a general operand (actually a memory ;; operand) into a load of the operand and the actual zero extension ;; so that 1) the length will be accurate, and 2) the zero extensions ;; appearing at the end of basic blocks may be merged.

(define_split [(set (match_operand:HI 0 “register_operand” "") (zero_extend:HI (match_operand:QI 1 “general_operand_src” "")))] “reload_completed” [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (zero_extend:HI (match_dup 2)))] { operands[2] = gen_rtx_REG (QImode, REGNO (operands[0])); })

(define_expand “zero_extendqisi2” [(set (match_operand:SI 0 “register_operand” "") (zero_extend:SI (match_operand:QI 1 “general_operand_src” "")))] "" { if (TARGET_H8300SX) operands[1] = force_reg (QImode, operands[1]); })

(define_insn “*zero_extendqisi2_h8300” [(set (match_operand:SI 0 “register_operand” “=r,r”) (zero_extend:SI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ mov.b #0,%x0;sub.w %e0,%e0 mov.b %R1,%w0;mov.b #0,%x0;sub.w %e0,%e0” [(set_attr “length” “4,8”)])

(define_insn “*zero_extendqisi2_h8300hs” [(set (match_operand:SI 0 “register_operand” “=r,r”) (zero_extend:SI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX” “#”)

(define_split [(set (match_operand:SI 0 “register_operand” "") (zero_extend:SI (match_operand:QI 1 “general_operand_src” "")))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX && reg_overlap_mentioned_p (operands[0], operands[1]) && reload_completed” [(set (match_dup 2) (match_dup 1)) (set (match_dup 3) (zero_extend:HI (match_dup 2))) (set (match_dup 0) (zero_extend:SI (match_dup 3)))] { operands[2] = gen_lowpart (QImode, operands[0]); operands[3] = gen_lowpart (HImode, operands[0]); })

(define_split [(set (match_operand:SI 0 “register_operand” "") (zero_extend:SI (match_operand:QI 1 “general_operand_src” "")))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX && !reg_overlap_mentioned_p (operands[0], operands[1]) && reload_completed” [(set (match_dup 0) (const_int 0)) (set (strict_low_part (match_dup 2)) (match_dup 1))] { operands[2] = gen_rtx_REG (QImode, REGNO (operands[0])); })

(define_insn “*zero_extendqisi2_h8sx” [(set (match_operand:SI 0 “register_operand” “=r”) (zero_extend:SI (match_operand:QI 1 “register_operand” “0”)))] “TARGET_H8300SX” “extu.l\t#2,%0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_expand “zero_extendhisi2” [(set (match_operand:SI 0 “register_operand” "") (zero_extend:SI (match_operand:HI 1 “register_operand” "")))] "" "")

;; %e prints the high part of a CONST_INT, not the low part. Arggh. (define_insn “*zero_extendhisi2_h8300” [(set (match_operand:SI 0 “register_operand” “=r,r,r”) (zero_extend:SI (match_operand:HI 1 “general_operand_src” “0,i,g>”)))] “TARGET_H8300” “@ sub.w %e0,%e0 mov.w %f1,%f0;sub.w %e0,%e0 mov.w %e1,%f0;sub.w %e0,%e0” [(set_attr “length” “2,4,6”)])

(define_insn “*zero_extendhisi2_h8300hs” [(set (match_operand:SI 0 “register_operand” “=r”) (zero_extend:SI (match_operand:HI 1 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “extu.l %S0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_expand “extendqihi2” [(set (match_operand:HI 0 “register_operand” "") (sign_extend:HI (match_operand:QI 1 “register_operand” "")))] "" "")

(define_insn “*extendqihi2_h8300” [(set (match_operand:HI 0 “register_operand” “=r,r”) (sign_extend:HI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ bld #7,%s0;subx %t0,%t0 mov.b %R1,%s0;bld #7,%s0;subx %t0,%t0” [(set_attr “length” “4,8”)])

(define_insn “*extendqihi2_h8300hs” [(set (match_operand:HI 0 “register_operand” “=r”) (sign_extend:HI (match_operand:QI 1 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “exts.w %T0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_expand “extendqisi2” [(set (match_operand:SI 0 “register_operand” "") (sign_extend:SI (match_operand:QI 1 “register_operand” "")))] "" "")

(define_insn “*extendqisi2_h8300” [(set (match_operand:SI 0 “register_operand” “=r,r”) (sign_extend:SI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ bld #7,%w0;subx %x0,%x0;subx %y0,%y0;subx %z0,%z0 mov.b %R1,%w0;bld #7,%w0;subx %x0,%x0;subx %y0,%y0;subx %z0,%z0” [(set_attr “length” “8,12”)])

;; The following pattern is needed because without the pattern, the ;; combiner would split (sign_extend:SI (reg:QI)) into two 24-bit ;; shifts, one ashift and one ashiftrt.

(define_insn_and_split “*extendqisi2_h8300hs” [(set (match_operand:SI 0 “register_operand” “=r”) (sign_extend:SI (match_operand:QI 1 “register_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX” “#” “&& reload_completed” [(set (match_dup 2) (sign_extend:HI (match_dup 1))) (set (match_dup 0) (sign_extend:SI (match_dup 2)))] { operands[2] = gen_rtx_REG (HImode, REGNO (operands[0])); })

(define_insn “*extendqisi2_h8sx” [(set (match_operand:SI 0 “register_operand” “=r”) (sign_extend:SI (match_operand:QI 1 “register_operand” “0”)))] “TARGET_H8300SX” “exts.l\t#2,%0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_expand “extendhisi2” [(set (match_operand:SI 0 “register_operand” "") (sign_extend:SI (match_operand:HI 1 “register_operand” "")))] "" "")

(define_insn “*extendhisi2_h8300” [(set (match_operand:SI 0 “register_operand” “=r,r”) (sign_extend:SI (match_operand:HI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ bld #7,%x0;subx %y0,%y0;subx %z0,%z0 mov.w %T1,%f0;bld #7,%x0;subx %y0,%y0;subx %z0,%z0” [(set_attr “length” “6,10”)])

(define_insn “*extendhisi2_h8300hs” [(set (match_operand:SI 0 “register_operand” “=r”) (sign_extend:SI (match_operand:HI 1 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “exts.l %S0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)]) ;; ---------------------------------------------------------------------- ;; SHIFTS ;; ---------------------------------------------------------------------- ;; ;; We make some attempt to provide real efficient shifting. One example is ;; doing an 8-bit shift of a 16-bit value by moving a byte reg into the other ;; reg and moving 0 into the former reg. ;; ;; We also try to achieve this in a uniform way. IE: We don‘t try to achieve ;; this in both rtl and at insn emit time. Ideally, we’d use rtl as that would ;; give the optimizer more cracks at the code. However, we wish to do things ;; like optimizing shifting the sign bit to bit 0 by rotating the other way. ;; There is rtl to handle this (rotate + and), but the H8/300 doesn‘t handle ;; 16-bit rotates. Also, if we emit complicated rtl, combine may not be able ;; to detect cases it can optimize. ;; ;; For these and other fuzzy reasons, I’ve decided to go the less pretty but ;; easier “do it at insn emit time” route.

;; QI BIT SHIFTS

(define_expand “ashlqi3” [(set (match_operand:QI 0 “register_operand” "") (ashift:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (QImode, ASHIFT, operands)) DONE; })

(define_expand “ashrqi3” [(set (match_operand:QI 0 “register_operand” "") (ashiftrt:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (QImode, ASHIFTRT, operands)) DONE; })

(define_expand “lshrqi3” [(set (match_operand:QI 0 “register_operand” "") (lshiftrt:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (QImode, LSHIFTRT, operands)) DONE; })

(define_insn "" [(set (match_operand:QI 0 “h8300_dst_operand” “=rQ”) (match_operator:QI 3 “h8sx_unary_shift_operator” [(match_operand:QI 1 “h8300_dst_operand” “0”) (match_operand:QI 2 “const_int_operand” "")]))] “h8300_operands_match_p (operands)” { return output_h8sx_shift (operands, ‘b’, ‘X’); } [(set_attr “length_table” “unary”) (set_attr “cc” “set_znv”)])

(define_insn "" [(set (match_operand:QI 0 “register_operand” “=r”) (match_operator:QI 3 “h8sx_binary_shift_operator” [(match_operand:QI 1 “register_operand” “0”) (match_operand:QI 2 “nonmemory_operand” “r P3>X”)]))] "" { return output_h8sx_shift (operands, ‘b’, ‘X’); } [(set_attr “length” “4”) (set_attr “cc” “set_znv”)])

(define_insn “*shiftqi” [(set (match_operand:QI 0 “register_operand” “=r,r”) (match_operator:QI 3 “nshift_operator” [(match_operand:QI 1 “register_operand” “0,0”) (match_operand:QI 2 “nonmemory_operand” “R,rn”)])) (clobber (match_scratch:QI 4 “=X,&r”))] "" { return output_a_shift (operands); } [(set (attr “length”) (symbol_ref “compute_a_shift_length (insn, operands)”)) (set (attr “cc”) (symbol_ref “compute_a_shift_cc (insn, operands)”))])

;; HI BIT SHIFTS

(define_expand “ashlhi3” [(set (match_operand:HI 0 “register_operand” "") (ashift:HI (match_operand:HI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (HImode, ASHIFT, operands)) DONE; })

(define_expand “lshrhi3” [(set (match_operand:HI 0 “register_operand” "") (lshiftrt:HI (match_operand:HI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (HImode, LSHIFTRT, operands)) DONE; })

(define_expand “ashrhi3” [(set (match_operand:HI 0 “register_operand” "") (ashiftrt:HI (match_operand:HI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (HImode, ASHIFTRT, operands)) DONE; })

(define_insn "" [(set (match_operand:HI 0 “h8300_dst_operand” “=rQ”) (match_operator:HI 3 “h8sx_unary_shift_operator” [(match_operand:HI 1 “h8300_dst_operand” “0”) (match_operand:QI 2 “const_int_operand” "")]))] “h8300_operands_match_p (operands)” { return output_h8sx_shift (operands, ‘w’, ‘T’); } [(set_attr “length_table” “unary”) (set_attr “cc” “set_znv”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r”) (match_operator:HI 3 “h8sx_binary_shift_operator” [(match_operand:HI 1 “register_operand” “0”) (match_operand:QI 2 “nonmemory_operand” “r P4>X”)]))] "" { return output_h8sx_shift (operands, ‘w’, ‘T’); } [(set_attr “length” “4”) (set_attr “cc” “set_znv”)])

(define_insn “*shifthi” [(set (match_operand:HI 0 “register_operand” “=r,r”) (match_operator:HI 3 “nshift_operator” [(match_operand:HI 1 “register_operand” “0,0”) (match_operand:QI 2 “nonmemory_operand” “S,rn”)])) (clobber (match_scratch:QI 4 “=X,&r”))] "" { return output_a_shift (operands); } [(set (attr “length”) (symbol_ref “compute_a_shift_length (insn, operands)”)) (set (attr “cc”) (symbol_ref “compute_a_shift_cc (insn, operands)”))])

;; SI BIT SHIFTS

(define_expand “ashlsi3” [(set (match_operand:SI 0 “register_operand” "") (ashift:SI (match_operand:SI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (SImode, ASHIFT, operands)) DONE; })

(define_expand “lshrsi3” [(set (match_operand:SI 0 “register_operand” "") (lshiftrt:SI (match_operand:SI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (SImode, LSHIFTRT, operands)) DONE; })

(define_expand “ashrsi3” [(set (match_operand:SI 0 “register_operand” "") (ashiftrt:SI (match_operand:SI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE; })

(define_insn "" [(set (match_operand:SI 0 “h8300_dst_operand” “=rQ”) (match_operator:SI 3 “h8sx_unary_shift_operator” [(match_operand:SI 1 “h8300_dst_operand” “0”) (match_operand:QI 2 “const_int_operand” "")]))] “h8300_operands_match_p (operands)” { return output_h8sx_shift (operands, ‘l’, ‘S’); } [(set_attr “length_table” “unary”) (set_attr “cc” “set_znv”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (match_operator:SI 3 “h8sx_binary_shift_operator” [(match_operand:SI 1 “register_operand” “0”) (match_operand:QI 2 “nonmemory_operand” “r P5>X”)]))] "" { return output_h8sx_shift (operands, ‘l’, ‘S’); } [(set_attr “length” “4”) (set_attr “cc” “set_znv”)])

(define_insn “*shiftsi” [(set (match_operand:SI 0 “register_operand” “=r,r”) (match_operator:SI 3 “nshift_operator” [(match_operand:SI 1 “register_operand” “0,0”) (match_operand:QI 2 “nonmemory_operand” “T,rn”)])) (clobber (match_scratch:QI 4 “=X,&r”))] "" { return output_a_shift (operands); } [(set (attr “length”) (symbol_ref “compute_a_shift_length (insn, operands)”)) (set (attr “cc”) (symbol_ref “compute_a_shift_cc (insn, operands)”))])

;; Split a variable shift into a loop. If the register containing ;; the shift count dies, then we just use that register.

(define_split [(set (match_operand 0 “register_operand” "") (match_operator 2 “nshift_operator” [(match_dup 0) (match_operand:QI 1 “register_operand” "")])) (clobber (match_operand:QI 3 “register_operand” ""))] “epilogue_completed && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))” [(set (cc0) (compare (match_dup 1) (const_int 0))) (set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_dup 5)) (pc))) (match_dup 4) (parallel [(set (match_dup 0) (match_op_dup 2 [(match_dup 0) (const_int 1)])) (clobber (scratch:QI))]) (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1))) (set (cc0) (compare (match_dup 1) (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_dup 4)) (pc))) (match_dup 5)] { operands[4] = gen_label_rtx (); operands[5] = gen_label_rtx (); })

(define_split [(set (match_operand 0 “register_operand” "") (match_operator 2 “nshift_operator” [(match_dup 0) (match_operand:QI 1 “register_operand” "")])) (clobber (match_operand:QI 3 “register_operand” ""))] “epilogue_completed && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))” [(set (match_dup 3) (match_dup 1)) (set (cc0) (compare (match_dup 3) (const_int 0))) (set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_dup 5)) (pc))) (match_dup 4) (parallel [(set (match_dup 0) (match_op_dup 2 [(match_dup 0) (const_int 1)])) (clobber (scratch:QI))]) (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1))) (set (cc0) (compare (match_dup 3) (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_dup 4)) (pc))) (match_dup 5)] { operands[4] = gen_label_rtx (); operands[5] = gen_label_rtx (); }) ;; ---------------------------------------------------------------------- ;; ROTATIONS ;; ----------------------------------------------------------------------

(define_expand “rotlqi3” [(set (match_operand:QI 0 “register_operand” "") (rotate:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_rotate (operands)) DONE; })

(define_insn “rotlqi3_1” [(set (match_operand:QI 0 “register_operand” “=r”) (rotate:QI (match_operand:QI 1 “register_operand” “0”) (match_operand:QI 2 “immediate_operand” "")))] "" { return output_a_rotate (ROTATE, operands); } [(set (attr “length”) (symbol_ref “compute_a_rotate_length (operands)”))])

(define_expand “rotlhi3” [(set (match_operand:HI 0 “register_operand” "") (rotate:HI (match_operand:HI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" { if (expand_a_rotate (operands)) DONE; })

(define_insn “rotlhi3_1” [(set (match_operand:HI 0 “register_operand” “=r”) (rotate:HI (match_operand:HI 1 “register_operand” “0”) (match_operand:QI 2 “immediate_operand” "")))] "" { return output_a_rotate (ROTATE, operands); } [(set (attr “length”) (symbol_ref “compute_a_rotate_length (operands)”))])

(define_expand “rotlsi3” [(set (match_operand:SI 0 “register_operand” "") (rotate:SI (match_operand:SI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] “TARGET_H8300H || TARGET_H8300S” { if (expand_a_rotate (operands)) DONE; })

(define_insn “rotlsi3_1” [(set (match_operand:SI 0 “register_operand” “=r”) (rotate:SI (match_operand:SI 1 “register_operand” “0”) (match_operand:QI 2 “immediate_operand” "")))] “TARGET_H8300H || TARGET_H8300S” { return output_a_rotate (ROTATE, operands); } [(set (attr “length”) (symbol_ref “compute_a_rotate_length (operands)”))]) ;; ----------------------------------------------------------------- ;; BIT FIELDS ;; ----------------------------------------------------------------- ;; The H8/300 has given 1/8th of its opcode space to bitfield ;; instructions so let's use them as well as we can.

;; You'll never believe all these patterns perform one basic action -- ;; load a bit from the source, optionally invert the bit, then store it ;; in the destination (which is known to be zero). ;; ;; Combine obviously need some work to better identify this situation and ;; canonicalize the form better.

;; ;; Normal loads with a 16bit destination. ;;

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=&r”) (zero_extract:HI (match_operand:HI 1 “register_operand” “r”) (const_int 1) (match_operand:HI 2 “immediate_operand” “n”)))] “TARGET_H8300” “sub.w %0,%0;bld %Z2,%Y1;bst #0,%X0” [(set_attr “length” “6”)])

;; ;; Inverted loads with a 16bit destination. ;;

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=&r”) (zero_extract:HI (xor:HI (match_operand:HI 1 “register_operand” “r”) (match_operand:HI 3 “const_int_operand” “n”)) (const_int 1) (match_operand:HI 2 “const_int_operand” “n”)))] “(TARGET_H8300 || TARGET_H8300SX) && (1 << INTVAL (operands[2])) == INTVAL (operands[3])” “sub.w %0,%0;bild %Z2,%Y1;bst #0,%X0” [(set_attr “length” “8”)])

;; ;; Normal loads with a 32bit destination. ;;

(define_insn “*extzv_1_r_h8300” [(set (match_operand:SI 0 “register_operand” “=&r”) (zero_extract:SI (match_operand:HI 1 “register_operand” “r”) (const_int 1) (match_operand 2 “const_int_operand” “n”)))] “TARGET_H8300 && INTVAL (operands[2]) < 16” { return output_simode_bld (0, operands); } [(set_attr “length” “8”)])

(define_insn “*extzv_1_r_h8300hs” [(set (match_operand:SI 0 “register_operand” “=r,r”) (zero_extract:SI (match_operand:SI 1 “register_operand” “?0,r”) (const_int 1) (match_operand 2 “const_int_operand” “n,n”)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[2]) < 16” { return output_simode_bld (0, operands); } [(set_attr “cc” “set_znv,set_znv”) (set_attr “length” “8,6”)])

;; ;; Inverted loads with a 32bit destination. ;;

(define_insn “*extzv_1_r_inv_h8300” [(set (match_operand:SI 0 “register_operand” “=&r”) (zero_extract:SI (xor:HI (match_operand:HI 1 “register_operand” “r”) (match_operand:HI 3 “const_int_operand” “n”)) (const_int 1) (match_operand 2 “const_int_operand” “n”)))] “TARGET_H8300 && INTVAL (operands[2]) < 16 && (1 << INTVAL (operands[2])) == INTVAL (operands[3])” { return output_simode_bld (1, operands); } [(set_attr “length” “8”)])

(define_insn “*extzv_1_r_inv_h8300hs” [(set (match_operand:SI 0 “register_operand” “=r,r”) (zero_extract:SI (xor:SI (match_operand:SI 1 “register_operand” “?0,r”) (match_operand 3 “const_int_operand” “n,n”)) (const_int 1) (match_operand 2 “const_int_operand” “n,n”)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[2]) < 16 && (1 << INTVAL (operands[2])) == INTVAL (operands[3])” { return output_simode_bld (1, operands); } [(set_attr “cc” “set_znv,set_znv”) (set_attr “length” “8,6”)])

(define_expand “insv” [(set (zero_extract:HI (match_operand:HI 0 “general_operand” "") (match_operand:HI 1 “general_operand” "") (match_operand:HI 2 “general_operand” "")) (match_operand:HI 3 “general_operand” ""))] “TARGET_H8300 || TARGET_H8300SX” { if (TARGET_H8300SX) { if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[1]) <= 8 && INTVAL (operands[2]) >= 0 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8 && memory_operand (operands[0], GET_MODE (operands[0]))) { /* If the source operand is zero, it's better to use AND rather than BFST. Likewise OR if the operand is all ones. */ if (GET_CODE (operands[3]) == CONST_INT) { HOST_WIDE_INT mask = (1 << INTVAL (operands[1])) - 1; if ((INTVAL (operands[3]) & mask) == 0) FAIL; if ((INTVAL (operands[3]) & mask) == mask) FAIL; } if (! bit_memory_operand (operands[0], GET_MODE (operands[0]))) { if (!can_create_pseudo_p ()) FAIL; operands[0] = replace_equiv_address (operands[0], force_reg (Pmode, XEXP (operands[0], 0))); } operands[3] = gen_lowpart (QImode, operands[3]); if (! operands[3]) FAIL; if (! register_operand (operands[3], QImode)) { if (!can_create_pseudo_p ()) FAIL; operands[3] = force_reg (QImode, operands[3]); } emit_insn (gen_bfst (adjust_address (operands[0], QImode, 0), operands[3], operands[1], operands[2])); DONE; } FAIL; }

/* We only have single bit bit-field instructions.  */
if (INTVAL (operands[1]) != 1)
  FAIL;

/* For now, we don't allow memory operands.  */
if (GET_CODE (operands[0]) == MEM
|| GET_CODE (operands[3]) == MEM)
  FAIL;

if (GET_CODE (operands[3]) != REG)
  operands[3] = force_reg (HImode, operands[3]);

})

(define_insn "" [(set (zero_extract:HI (match_operand:HI 0 “register_operand” “+r”) (const_int 1) (match_operand:HI 1 “immediate_operand” “n”)) (match_operand:HI 2 “register_operand” “r”))] "" “bld #0,%R2;bst %Z1,%Y0 ; i1” [(set_attr “length” “4”)])

(define_expand “extzv” [(set (match_operand:HI 0 “register_operand” "") (zero_extract:HI (match_operand:HI 1 “bit_operand” "") (match_operand:HI 2 “general_operand” "") (match_operand:HI 3 “general_operand” "")))] “TARGET_H8300 || TARGET_H8300SX” { if (TARGET_H8300SX) { if (GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[2]) <= 8 && INTVAL (operands[3]) >= 0 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8 && memory_operand (operands[1], QImode)) { rtx temp;

    /* Optimize the case where we're extracting into a paradoxical
       subreg.  It's only necessary to extend to the inner reg.  */
    if (GET_CODE (operands[0]) == SUBREG
	&& subreg_lowpart_p (operands[0])
	&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0])))
	    < GET_MODE_SIZE (GET_MODE (operands[0])))
	&& (GET_MODE_CLASS (GET_MODE (SUBREG_REG (operands[0])))
	    == MODE_INT))
      operands[0] = SUBREG_REG (operands[0]);

    if (!can_create_pseudo_p ())
      temp = gen_lowpart (QImode, operands[0]);
    else
      temp = gen_reg_rtx (QImode);
    if (! temp)
      FAIL;
        if (! bit_memory_operand (operands[1], QImode))
      {
	if (!can_create_pseudo_p ())
	  FAIL;
	operands[1] = replace_equiv_address (operands[1],
					     force_reg (Pmode, XEXP (operands[1], 0)));
      }
    emit_insn (gen_bfld (temp, operands[1], operands[2], operands[3]));
    convert_move (operands[0], temp, 1);
    DONE;
      }
FAIL;
  }

/* We only have single bit bit-field instructions.  */
if (INTVAL (operands[2]) != 1)
  FAIL;

/* For now, we don't allow memory operands.  */
if (GET_CODE (operands[1]) == MEM)
  FAIL;

})

;; BAND, BOR, and BXOR patterns

(define_insn "" [(set (match_operand:HI 0 “bit_operand” “=Ur”) (match_operator:HI 4 “bit_operator” [(zero_extract:HI (match_operand:HI 1 “register_operand” “r”) (const_int 1) (match_operand:HI 2 “immediate_operand” “n”)) (match_operand:HI 3 “bit_operand” “0”)]))] "" “bld %Z2,%Y1;b%c4 #0,%R0;bst #0,%R0; bl1” [(set_attr “length” “6”)])

(define_insn "" [(set (match_operand:HI 0 “bit_operand” “=Ur”) (match_operator:HI 5 “bit_operator” [(zero_extract:HI (match_operand:HI 1 “register_operand” “r”) (const_int 1) (match_operand:HI 2 “immediate_operand” “n”)) (zero_extract:HI (match_operand:HI 3 “register_operand” “r”) (const_int 1) (match_operand:HI 4 “immediate_operand” “n”))]))] "" “bld %Z2,%Y1;b%c5 %Z4,%Y3;bst #0,%R0; bl3” [(set_attr “length” “6”)])

(define_insn “bfld” [(set (match_operand:QI 0 “register_operand” “=r”) (zero_extract:QI (match_operand:QI 1 “bit_memory_operand” “WU”) (match_operand:QI 2 “immediate_operand” “n”) (match_operand:QI 3 “immediate_operand” “n”)))] “TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8” { operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3]))) - (1 << INTVAL (operands[3]))); return “bfld %2,%1,%R0”; } [(set_attr “cc” “none_0hit”) (set_attr “length_table” “bitfield”)])

(define_insn “bfst” [(set (zero_extract:QI (match_operand:QI 0 “bit_memory_operand” “+WU”) (match_operand:QI 2 “immediate_operand” “n”) (match_operand:QI 3 “immediate_operand” “n”)) (match_operand:QI 1 “register_operand” “r”))] “TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8” { operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3]))) - (1 << INTVAL (operands[3]))); return “bfst %R1,%2,%0”; } [(set_attr “cc” “none_0hit”) (set_attr “length_table” “bitfield”)])

(define_expand “cstoreqi4” [(use (match_operator 1 “eqne_operator” [(match_operand:QI 2 “h8300_dst_operand” "") (match_operand:QI 3 “h8300_src_operand” "")])) (clobber (match_operand:HI 0 “register_operand”))] “TARGET_H8300SX” { h8300_expand_store (operands); DONE; })

(define_expand “cstorehi4” [(use (match_operator 1 “eqne_operator” [(match_operand:HI 2 “h8300_dst_operand” "") (match_operand:HI 3 “h8300_src_operand” "")])) (clobber (match_operand:HI 0 “register_operand”))] “TARGET_H8300SX” { h8300_expand_store (operands); DONE; })

(define_expand “cstoresi4” [(use (match_operator 1 “eqne_operator” [(match_operand:SI 2 “h8300_dst_operand” "") (match_operand:SI 3 “h8300_src_operand” "")])) (clobber (match_operand:HI 0 “register_operand”))] “TARGET_H8300SX” { h8300_expand_store (operands); DONE; })

(define_insn “*bstzhireg” [(set (match_operand:HI 0 “register_operand” “=r”) (match_operator:HI 1 “eqne_operator” [(cc0) (const_int 0)]))] “TARGET_H8300SX” “mulu.w #0,%T0;b%k1 .Lh8BR%=;inc.w #1,%T0\n.Lh8BR%=:” [(set_attr “cc” “clobber”)])

(define_insn_and_split “*cmpstz” [(set (zero_extract:QI (match_operand:QI 0 “bit_memory_operand” “+WU,WU”) (const_int 1) (match_operand:QI 1 “immediate_operand” “n,n”)) (match_operator:QI 2 “eqne_operator” [(match_operand 3 “h8300_dst_operand” “r,rQ”) (match_operand 4 “h8300_src_operand” “I,rQi”)]))] “TARGET_H8300SX && (GET_MODE (operands[3]) == GET_MODE (operands[4]) || GET_CODE (operands[4]) == CONST_INT) && GET_MODE_CLASS (GET_MODE (operands[3])) == MODE_INT && GET_MODE_SIZE (GET_MODE (operands[3])) <= 4” “#” “reload_completed” [(set (cc0) (match_dup 5)) (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1)) (match_op_dup:QI 2 [(cc0) (const_int 0)]))] { operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]); } [(set_attr “cc” “set_znv,compare”)])

(define_insn “*bstz” [(set (zero_extract:QI (match_operand:QI 0 “bit_memory_operand” “+WU”) (const_int 1) (match_operand:QI 1 “immediate_operand” “n”)) (eq:QI (cc0) (const_int 0)))] “TARGET_H8300SX && reload_completed” “bstz %1,%0” [(set_attr “cc” “none_0hit”) (set_attr “length_table” “unary”)])

(define_insn “*bistz” [(set (zero_extract:QI (match_operand:QI 0 “bit_memory_operand” “+WU”) (const_int 1) (match_operand:QI 1 “immediate_operand” “n”)) (ne:QI (cc0) (const_int 0)))] “TARGET_H8300SX && reload_completed” “bistz %1,%0” [(set_attr “cc” “none_0hit”) (set_attr “length_table” “unary”)])

(define_insn_and_split “*cmpcondbset” [(set (match_operand:QI 0 “nonimmediate_operand” “=WU,WU”) (if_then_else:QI (match_operator 1 “eqne_operator” [(match_operand 2 “h8300_dst_operand” “r,rQ”) (match_operand 3 “h8300_src_operand” “I,rQi”)]) (ior:QI (match_operand:QI 4 “bit_memory_operand” “0,0”) (match_operand:QI 5 “single_one_operand” “n,n”)) (match_dup 4)))] “TARGET_H8300SX” “#” “reload_completed” [(set (cc0) (match_dup 6)) (set (match_dup 0) (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (ior:QI (match_dup 4) (match_dup 5)) (match_dup 4)))] { operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); } [(set_attr “cc” “set_znv,compare”)])

(define_insn “*condbset” [(set (match_operand:QI 0 “bit_memory_operand” “=WU”) (if_then_else:QI (match_operator:QI 2 “eqne_operator” [(cc0) (const_int 0)]) (ior:QI (match_operand:QI 3 “bit_memory_operand” “0”) (match_operand:QI 1 “single_one_operand” “n”)) (match_dup 3)))] “TARGET_H8300SX && reload_completed” “bset/%j2\t%V1,%0” [(set_attr “cc” “none_0hit”) (set_attr “length_table” “logicb”)])

(define_insn_and_split “*cmpcondbclr” [(set (match_operand:QI 0 “nonimmediate_operand” “=WU,WU”) (if_then_else:QI (match_operator 1 “eqne_operator” [(match_operand 2 “h8300_dst_operand” “r,rQ”) (match_operand 3 “h8300_src_operand” “I,rQi”)]) (and:QI (match_operand:QI 4 “bit_memory_operand” “0,0”) (match_operand:QI 5 “single_zero_operand” “n,n”)) (match_dup 4)))] “TARGET_H8300SX” “#” “reload_completed” [(set (cc0) (match_dup 6)) (set (match_dup 0) (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (and:QI (match_dup 4) (match_dup 5)) (match_dup 4)))] { operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); } [(set_attr “cc” “set_znv,compare”)])

(define_insn “*condbclr” [(set (match_operand:QI 0 “bit_memory_operand” “=WU”) (if_then_else:QI (match_operator:QI 2 “eqne_operator” [(cc0) (const_int 0)]) (and:QI (match_operand:QI 3 “bit_memory_operand” “0”) (match_operand:QI 1 “single_zero_operand” “n”)) (match_dup 3)))] “TARGET_H8300SX && reload_completed” “bclr/%j2\t%W1,%0” [(set_attr “cc” “none_0hit”) (set_attr “length_table” “logicb”)])

(define_insn_and_split “*cmpcondbsetreg” [(set (match_operand:QI 0 “nonimmediate_operand” “=WU,WU”) (if_then_else:QI (match_operator 1 “eqne_operator” [(match_operand 2 “h8300_dst_operand” “r,rQ”) (match_operand 3 “h8300_src_operand” “I,rQi”)]) (ior:QI (match_operand:QI 4 “bit_memory_operand” “0,0”) (ashift:QI (const_int 1) (match_operand:QI 5 “register_operand” “r,r”))) (match_dup 4)))] “TARGET_H8300SX” “#” “reload_completed” [(set (cc0) (match_dup 6)) (set (match_dup 0) (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (ior:QI (match_dup 4) (ashift:QI (const_int 1) (match_operand:QI 5 “register_operand” “r,r”))) (match_dup 4)))] { operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); } [(set_attr “cc” “set_znv,compare”)])

(define_insn “*condbsetreg” [(set (match_operand:QI 0 “bit_memory_operand” “=WU”) (if_then_else:QI (match_operator:QI 2 “eqne_operator” [(cc0) (const_int 0)]) (ior:QI (match_operand:QI 3 “bit_memory_operand” “0”) (ashift:QI (const_int 1) (match_operand:QI 1 “register_operand” “r”))) (match_dup 3)))] “TARGET_H8300SX && reload_completed” “bset/%j2\t%R1,%0” [(set_attr “cc” “none_0hit”) (set_attr “length_table” “logicb”)])

(define_insn_and_split “*cmpcondbclrreg” [(set (match_operand:QI 0 “nonimmediate_operand” “=WU,WU”) (if_then_else:QI (match_operator 1 “eqne_operator” [(match_operand 2 “h8300_dst_operand” “r,rQ”) (match_operand 3 “h8300_src_operand” “I,rQi”)]) (and:QI (match_operand:QI 4 “bit_memory_operand” “0,0”) (ashift:QI (const_int 1) (match_operand:QI 5 “register_operand” “r,r”))) (match_dup 4)))] “TARGET_H8300SX” “#” “reload_completed” [(set (cc0) (match_dup 6)) (set (match_dup 0) (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (and:QI (match_dup 4) (ashift:QI (const_int 1) (match_operand:QI 5 “register_operand” “r,r”))) (match_dup 4)))] { operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); } [(set_attr “cc” “set_znv,compare”)])

(define_insn “*condbclrreg” [(set (match_operand:QI 0 “bit_memory_operand” “=WU”) (if_then_else:QI (match_operator:QI 2 “eqne_operator” [(cc0) (const_int 0)]) (and:QI (match_operand:QI 3 “bit_memory_operand” “0”) (ashift:QI (const_int 1) (match_operand:QI 1 “register_operand” “r”))) (match_dup 3)))] “TARGET_H8300SX && reload_completed” “bclr/%j2\t%R1,%0” [(set_attr “cc” “none_0hit”) (set_attr “length_table” “logicb”)])

;; ----------------------------------------------------------------- ;; COMBINE PATTERNS ;; -----------------------------------------------------------------

;; insv:SI

(define_insn “*insv_si_1_n” [(set (zero_extract:SI (match_operand:SI 0 “register_operand” “+r”) (const_int 1) (match_operand:SI 1 “const_int_operand” “n”)) (match_operand:SI 2 “register_operand” “r”))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) < 16” “bld\t#0,%w2;bst\t%Z1,%Y0” [(set_attr “length” “4”)])

(define_insn “*insv_si_1_n_lshiftrt” [(set (zero_extract:SI (match_operand:SI 0 “register_operand” “+r”) (const_int 1) (match_operand:SI 1 “const_int_operand” “n”)) (lshiftrt:SI (match_operand:SI 2 “register_operand” “r”) (match_operand:SI 3 “const_int_operand” “n”)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) < 16 && INTVAL (operands[3]) < 16” “bld\t%Z3,%Y2;bst\t%Z1,%Y0” [(set_attr “length” “4”)])

(define_insn “*insv_si_1_n_lshiftrt_16” [(set (zero_extract:SI (match_operand:SI 0 “register_operand” “+r”) (const_int 1) (match_operand:SI 1 “const_int_operand” “n”)) (lshiftrt:SI (match_operand:SI 2 “register_operand” “r”) (const_int 16)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) < 16” “rotr.w\t%e2;rotl.w\t%e2;bst\t%Z1,%Y0” [(set_attr “length” “6”)])

(define_insn “*insv_si_8_8” [(set (zero_extract:SI (match_operand:SI 0 “register_operand” “+r”) (const_int 8) (const_int 8)) (match_operand:SI 1 “register_operand” “r”))] “TARGET_H8300H || TARGET_H8300S” “mov.b\t%w1,%x0” [(set_attr “length” “2”)])

(define_insn “*insv_si_8_8_lshiftrt_8” [(set (zero_extract:SI (match_operand:SI 0 “register_operand” “+r”) (const_int 8) (const_int 8)) (lshiftrt:SI (match_operand:SI 1 “register_operand” “r”) (const_int 8)))] “TARGET_H8300H || TARGET_H8300S” “mov.b\t%x1,%x0” [(set_attr “length” “2”)])

;; extzv:SI

(define_insn “*extzv_8_8” [(set (match_operand:SI 0 “register_operand” “=r,r”) (zero_extract:SI (match_operand:SI 1 “register_operand” “?0,r”) (const_int 8) (const_int 8)))] “TARGET_H8300H || TARGET_H8300S” “@ mov.b\t%x1,%w0;extu.w\t%f0;extu.l\t%S0 sub.l\t%S0,%S0;mov.b\t%x1,%w0” [(set_attr “cc” “set_znv,clobber”) (set_attr “length” “6,4”)])

(define_insn “*extzv_8_16” [(set (match_operand:SI 0 “register_operand” “=r”) (zero_extract:SI (match_operand:SI 1 “register_operand” “r”) (const_int 8) (const_int 16)))] “TARGET_H8300H || TARGET_H8300S” “mov.w\t%e1,%f0;extu.w\t%f0;extu.l\t%S0” [(set_attr “cc” “set_znv”) (set_attr “length” “6”)])

(define_insn “*extzv_16_8” [(set (match_operand:SI 0 “register_operand” “=r”) (zero_extract:SI (match_operand:SI 1 “register_operand” “r”) (const_int 16) (const_int 8))) (clobber (match_scratch:SI 2 “=&r”))] “TARGET_H8300H” “mov.w\t%e1,%f2;mov.b\t%x1,%w0;mov.b\t%w2,%x0;extu.l\t%S0” [(set_attr “length” “8”) (set_attr “cc” “set_znv”)])

;; Extract the exponent of a float.

(define_insn_and_split “*extzv_8_23” [(set (match_operand:SI 0 “register_operand” “=r”) (zero_extract:SI (match_operand:SI 1 “register_operand” “0”) (const_int 8) (const_int 23)))] “(TARGET_H8300H || TARGET_H8300S)” “#” “&& reload_completed” [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 1))) (clobber (scratch:QI))]) (parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24))) (clobber (scratch:QI))])] "")

;; and:SI

;; ((SImode) HImode) << 15

(define_insn_and_split “*twoshifts_l16_r1” [(set (match_operand:SI 0 “register_operand” “=r”) (and:SI (ashift:SI (match_operand:SI 1 “register_operand” “0”) (const_int 15)) (const_int 2147450880)))] “(TARGET_H8300H || TARGET_H8300S)” “#” “&& reload_completed” [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16))) (clobber (scratch:QI))]) (parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 1))) (clobber (scratch:QI))])] "")

;; Transform (SImode << B) & 0xffff into (SImode) (HImode << B).

(define_insn_and_split “*andsi3_ashift_n_lower” [(set (match_operand:SI 0 “register_operand” “=r,r”) (and:SI (ashift:SI (match_operand:SI 1 “register_operand” “0,0”) (match_operand:QI 2 “const_int_operand” “S,n”)) (match_operand:SI 3 “const_int_operand” “n,n”))) (clobber (match_scratch:QI 4 “=X,&r”))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[2]) <= 15 && INTVAL (operands[3]) == ((-1 << INTVAL (operands[2])) & 0xffff)” “#” “&& reload_completed” [(parallel [(set (match_dup 5) (ashift:HI (match_dup 5) (match_dup 2))) (clobber (match_dup 4))]) (set (match_dup 0) (zero_extend:SI (match_dup 5)))] { operands[5] = gen_rtx_REG (HImode, REGNO (operands[0])); })

;; Accept (A >> 30) & 2 and the like.

(define_insn “*andsi3_lshiftrt_n_sb” [(set (match_operand:SI 0 “register_operand” “=r”) (and:SI (lshiftrt:SI (match_operand:SI 1 “register_operand” “0”) (match_operand:SI 2 “const_int_operand” “n”)) (match_operand:SI 3 “single_one_operand” “n”)))] “(TARGET_H8300H || TARGET_H8300S) && exact_log2 (INTVAL (operands[3])) < 16 && INTVAL (operands[2]) + exact_log2 (INTVAL (operands[3])) == 31” { operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3]))); return “shll.l\t%S0;xor.l\t%S0,%S0;bst\t%Z3,%Y0”; } [(set_attr “length” “8”)])

(define_insn_and_split “*andsi3_lshiftrt_9_sb” [(set (match_operand:SI 0 “register_operand” “=r”) (and:SI (lshiftrt:SI (match_operand:SI 1 “register_operand” “0”) (const_int 9)) (const_int 4194304)))] “TARGET_H8300H || TARGET_H8300S” “#” “&& reload_completed” [(set (match_dup 0) (and:SI (lshiftrt:SI (match_dup 0) (const_int 25)) (const_int 64))) (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16))) (clobber (scratch:QI))])] "")

;; plus:SI

(define_insn “*addsi3_upper” [(set (match_operand:SI 0 “register_operand” “=r”) (plus:SI (mult:SI (match_operand:SI 1 “register_operand” “r”) (const_int 65536)) (match_operand:SI 2 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “add.w\t%f1,%e0” [(set_attr “length” “2”)])

(define_insn “*addsi3_lshiftrt_16_zexthi” [(set (match_operand:SI 0 “register_operand” “=r”) (plus:SI (lshiftrt:SI (match_operand:SI 1 “register_operand” “r”) (const_int 16)) (zero_extend:SI (match_operand:HI 2 “register_operand” “0”))))] “TARGET_H8300H || TARGET_H8300S” “add.w\t%e1,%f0;xor.w\t%e0,%e0;rotxl.w\t%e0” [(set_attr “length” “6”)])

(define_insn_and_split “*addsi3_and_r_1” [(set (match_operand:SI 0 “register_operand” “=r”) (plus:SI (and:SI (match_operand:SI 1 “register_operand” “r”) (const_int 1)) (match_operand:SI 2 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “#” “&& reload_completed” [(set (cc0) (compare (zero_extract:SI (match_dup 1) (const_int 1) (const_int 0)) (const_int 0))) (set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_dup 3)) (pc))) (set (match_dup 2) (plus:SI (match_dup 2) (const_int 1))) (match_dup 3)] { operands[3] = gen_label_rtx (); })

(define_insn_and_split “*addsi3_and_not_r_1” [(set (match_operand:SI 0 “register_operand” “=r”) (plus:SI (and:SI (not:SI (match_operand:SI 1 “register_operand” “r”)) (const_int 1)) (match_operand:SI 2 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “#” “&& reload_completed” [(set (cc0) (compare (zero_extract:SI (match_dup 1) (const_int 1) (const_int 0)) (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_dup 3)) (pc))) (set (match_dup 2) (plus:SI (match_dup 2) (const_int 1))) (match_dup 3)] { operands[3] = gen_label_rtx (); })

;; [ix]or:HI

(define_insn “*ixorhi3_zext” [(set (match_operand:HI 0 “register_operand” “=r”) (match_operator:HI 1 “iorxor_operator” [(zero_extend:HI (match_operand:QI 2 “register_operand” “r”)) (match_operand:HI 3 “register_operand” “0”)]))] "" “%c1.b\t%X2,%s0” [(set_attr “length” “2”)])

;; [ix]or:SI

(define_insn “*ixorsi3_zext_qi” [(set (match_operand:SI 0 “register_operand” “=r”) (match_operator:SI 1 “iorxor_operator” [(zero_extend:SI (match_operand:QI 2 “register_operand” “r”)) (match_operand:SI 3 “register_operand” “0”)]))] "" “%c1.b\t%X2,%w0” [(set_attr “length” “2”)])

(define_insn “*ixorsi3_zext_hi” [(set (match_operand:SI 0 “register_operand” “=r”) (match_operator:SI 1 “iorxor_operator” [(zero_extend:SI (match_operand:HI 2 “register_operand” “r”)) (match_operand:SI 3 “register_operand” “0”)]))] “TARGET_H8300H || TARGET_H8300S” “%c1.w\t%T2,%f0” [(set_attr “length” “2”)])

(define_insn “*ixorsi3_ashift_16” [(set (match_operand:SI 0 “register_operand” “=r”) (match_operator:SI 1 “iorxor_operator” [(ashift:SI (match_operand:SI 2 “register_operand” “r”) (const_int 16)) (match_operand:SI 3 “register_operand” “0”)]))] “TARGET_H8300H || TARGET_H8300S” “%c1.w\t%f2,%e0” [(set_attr “length” “2”)])

(define_insn “*ixorsi3_lshiftrt_16” [(set (match_operand:SI 0 “register_operand” “=r”) (match_operator:SI 1 “iorxor_operator” [(lshiftrt:SI (match_operand:SI 2 “register_operand” “r”) (const_int 16)) (match_operand:SI 3 “register_operand” “0”)]))] “TARGET_H8300H || TARGET_H8300S” “%c1.w\t%e2,%f0” [(set_attr “length” “2”)])

;; ior:HI

(define_insn “*iorhi3_ashift_8” [(set (match_operand:HI 0 “register_operand” “=r”) (ior:HI (ashift:HI (match_operand:HI 1 “register_operand” “r”) (const_int 8)) (match_operand:HI 2 “register_operand” “0”)))] "" “or.b\t%s1,%t0” [(set_attr “length” “2”)])

(define_insn “*iorhi3_lshiftrt_8” [(set (match_operand:HI 0 “register_operand” “=r”) (ior:HI (lshiftrt:HI (match_operand:HI 1 “register_operand” “r”) (const_int 8)) (match_operand:HI 2 “register_operand” “0”)))] "" “or.b\t%t1,%s0” [(set_attr “length” “2”)])

(define_insn “*iorhi3_two_qi” [(set (match_operand:HI 0 “register_operand” “=r”) (ior:HI (zero_extend:HI (match_operand:QI 1 “register_operand” “0”)) (ashift:HI (match_operand:HI 2 “register_operand” “r”) (const_int 8))))] "" “mov.b\t%s2,%t0” [(set_attr “length” “2”)])

(define_insn “*iorhi3_two_qi_mem” [(set (match_operand:HI 0 “register_operand” “=&r”) (ior:HI (zero_extend:HI (match_operand:QI 1 “memory_operand” “m”)) (ashift:HI (subreg:HI (match_operand:QI 2 “memory_operand” “m”) 0) (const_int 8))))] "" “mov.b\t%X2,%t0;mov.b\t%X1,%s0” [(set_attr “length” “16”)])

(define_split [(set (match_operand:HI 0 “register_operand” "") (ior:HI (zero_extend:HI (match_operand:QI 1 “memory_operand” "")) (ashift:HI (subreg:HI (match_operand:QI 2 “memory_operand” "") 0) (const_int 8))))] “(TARGET_H8300H || TARGET_H8300S) && reload_completed && byte_accesses_mergeable_p (XEXP (operands[2], 0), XEXP (operands[1], 0))” [(set (match_dup 0) (match_dup 3))] { operands[3] = gen_rtx_MEM (HImode, XEXP (operands[2], 0)); })

;; ior:SI

(define_insn “*iorsi3_two_hi” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (zero_extend:SI (match_operand:HI 1 “register_operand” “0”)) (ashift:SI (match_operand:SI 2 “register_operand” “r”) (const_int 16))))] “TARGET_H8300H || TARGET_H8300S” “mov.w\t%f2,%e0” [(set_attr “length” “2”)])

(define_insn_and_split “*iorsi3_two_qi_zext” [(set (match_operand:SI 0 “register_operand” “=&r”) (ior:SI (zero_extend:SI (match_operand:QI 1 “memory_operand” “m”)) (and:SI (ashift:SI (subreg:SI (match_operand:QI 2 “memory_operand” “m”) 0) (const_int 8)) (const_int 65280))))] “TARGET_H8300H || TARGET_H8300S” “#” “&& reload_completed” [(set (match_dup 3) (ior:HI (zero_extend:HI (match_dup 1)) (ashift:HI (subreg:HI (match_dup 2) 0) (const_int 8)))) (set (match_dup 0) (zero_extend:SI (match_dup 3)))] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); })

(define_insn “*iorsi3_e2f” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (and:SI (match_operand:SI 1 “register_operand” “0”) (const_int -65536)) (lshiftrt:SI (match_operand:SI 2 “register_operand” “r”) (const_int 16))))] “TARGET_H8300H || TARGET_H8300S” “mov.w\t%e2,%f0” [(set_attr “length” “2”)])

(define_insn_and_split “*iorsi3_two_qi_sext” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (zero_extend:SI (match_operand:QI 1 “register_operand” “0”)) (ashift:SI (sign_extend:SI (match_operand:QI 2 “register_operand” “r”)) (const_int 8))))] “TARGET_H8300H || TARGET_H8300S” “#” “&& reload_completed” [(set (match_dup 3) (ior:HI (zero_extend:HI (match_dup 1)) (ashift:HI (match_dup 4) (const_int 8)))) (set (match_dup 0) (sign_extend:SI (match_dup 3)))] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); operands[4] = gen_rtx_REG (HImode, REGNO (operands[2])); })

(define_insn “*iorsi3_w” [(set (match_operand:SI 0 “register_operand” “=r,&r”) (ior:SI (and:SI (match_operand:SI 1 “register_operand” “0,0”) (const_int -256)) (zero_extend:SI (match_operand:QI 2 “general_operand_src” “r,g>”))))] “TARGET_H8300H || TARGET_H8300S” “mov.b\t%X2,%w0” [(set_attr “length” “2,8”)])

(define_insn “*iorsi3_ashift_31” [(set (match_operand:SI 0 “register_operand” “=&r”) (ior:SI (ashift:SI (match_operand:SI 1 “register_operand” “r”) (const_int 31)) (match_operand:SI 2 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “rotxl.l\t%S0;bor\t#0,%w1;rotxr.l\t%S0” [(set_attr “length” “6”) (set_attr “cc” “set_znv”)])

(define_insn “*iorsi3_and_ashift” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (and:SI (ashift:SI (match_operand:SI 1 “register_operand” “r”) (match_operand:SI 2 “const_int_operand” “n”)) (match_operand:SI 3 “single_one_operand” “n”)) (match_operand:SI 4 “register_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && (INTVAL (operands[3]) & ~0xffff) == 0” { rtx srcpos = GEN_INT (exact_log2 (INTVAL (operands[3])) - INTVAL (operands[2])); rtx dstpos = GEN_INT (exact_log2 (INTVAL (operands[3]))); operands[2] = srcpos; operands[3] = dstpos; return “bld\t%Z2,%Y1;bor\t%Z3,%Y0;bst\t%Z3,%Y0”; } [(set_attr “length” “6”)])

(define_insn “*iorsi3_and_lshiftrt” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 “register_operand” “r”) (match_operand:SI 2 “const_int_operand” “n”)) (match_operand:SI 3 “single_one_operand” “n”)) (match_operand:SI 4 “register_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && ((INTVAL (operands[3]) << INTVAL (operands[2])) & ~0xffff) == 0” { rtx srcpos = GEN_INT (exact_log2 (INTVAL (operands[3])) + INTVAL (operands[2])); rtx dstpos = GEN_INT (exact_log2 (INTVAL (operands[3]))); operands[2] = srcpos; operands[3] = dstpos; return “bld\t%Z2,%Y1;bor\t%Z3,%Y0;bst\t%Z3,%Y0”; } [(set_attr “length” “6”)])

(define_insn “*iorsi3_zero_extract” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (zero_extract:SI (match_operand:SI 1 “register_operand” “r”) (const_int 1) (match_operand:SI 2 “const_int_operand” “n”)) (match_operand:SI 3 “register_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[2]) < 16” “bld\t%Z2,%Y1;bor\t#0,%w0;bst\t#0,%w0” [(set_attr “length” “6”)])

(define_insn “*iorsi3_and_lshiftrt_n_sb” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 “register_operand” “r”) (const_int 30)) (const_int 2)) (match_operand:SI 2 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “rotl.l\t%S1;rotr.l\t%S1;bor\t#1,%w0;bst\t#1,%w0” [(set_attr “length” “8”)])

(define_insn “*iorsi3_and_lshiftrt_9_sb” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 “register_operand” “r”) (const_int 9)) (const_int 4194304)) (match_operand:SI 2 “register_operand” “0”))) (clobber (match_scratch:HI 3 “=&r”))] “TARGET_H8300H || TARGET_H8300S” { if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) return “shll.l\t%S1;xor.w\t%T3,%T3;bst\t#6,%s3;or.w\t%T3,%e0”; else return “rotl.l\t%S1;rotr.l\t%S1;xor.w\t%T3,%T3;bst\t#6,%s3;or.w\t%T3,%e0”; } [(set_attr “length” “10”)])

;; Used to OR the exponent of a float.

(define_insn “*iorsi3_shift” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (ashift:SI (match_operand:SI 1 “register_operand” “r”) (const_int 23)) (match_operand:SI 2 “register_operand” “0”))) (clobber (match_scratch:SI 3 “=&r”))] “TARGET_H8300H || TARGET_H8300S” “#”)

(define_split [(set (match_operand:SI 0 “register_operand” "") (ior:SI (ashift:SI (match_operand:SI 1 “register_operand” "") (const_int 23)) (match_dup 0))) (clobber (match_operand:SI 2 “register_operand” ""))] “(TARGET_H8300H || TARGET_H8300S) && epilogue_completed && find_regno_note (insn, REG_DEAD, REGNO (operands[1])) && REGNO (operands[0]) != REGNO (operands[1])” [(parallel [(set (match_dup 3) (ashift:HI (match_dup 3) (const_int 7))) (clobber (scratch:QI))]) (set (match_dup 0) (ior:SI (ashift:SI (match_dup 1) (const_int 16)) (match_dup 0)))] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[1])); })

(define_split [(set (match_operand:SI 0 “register_operand” "") (ior:SI (ashift:SI (match_operand:SI 1 “register_operand” "") (const_int 23)) (match_dup 0))) (clobber (match_operand:SI 2 “register_operand” ""))] “(TARGET_H8300H || TARGET_H8300S) && epilogue_completed && !(find_regno_note (insn, REG_DEAD, REGNO (operands[1])) && REGNO (operands[0]) != REGNO (operands[1]))” [(set (match_dup 2) (match_dup 1)) (parallel [(set (match_dup 3) (ashift:HI (match_dup 3) (const_int 7))) (clobber (scratch:QI))]) (set (match_dup 0) (ior:SI (ashift:SI (match_dup 2) (const_int 16)) (match_dup 0)))] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[2])); })

(define_insn “*iorsi2_and_1_lshiftrt_1” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (and:SI (match_operand:SI 1 “register_operand” “0”) (const_int 1)) (lshiftrt:SI (match_dup 1) (const_int 1))))] “TARGET_H8300H || TARGET_H8300S” “shlr.l\t%S0;bor\t#0,%w0;bst\t#0,%w0” [(set_attr “length” “6”)])

(define_insn_and_split “*iorsi3_ashift_16_ashift_24” [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (ashift:SI (match_operand:SI 1 “register_operand” “0”) (const_int 16)) (ashift:SI (match_operand:SI 2 “register_operand” “r”) (const_int 24))))] “TARGET_H8300H || TARGET_H8300S” “#” “&& reload_completed” [(set (match_dup 3) (ior:HI (ashift:HI (match_dup 4) (const_int 8)) (match_dup 3))) (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16))) (clobber (scratch:QI))])] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); operands[4] = gen_rtx_REG (HImode, REGNO (operands[2])); })

(define_insn_and_split “*iorsi3_ashift_16_ashift_24_mem” [(set (match_operand:SI 0 “register_operand” “=&r”) (ior:SI (and:SI (ashift:SI (subreg:SI (match_operand:QI 1 “memory_operand” “m”) 0) (const_int 16)) (const_int 16711680)) (ashift:SI (subreg:SI (match_operand:QI 2 “memory_operand” “m”) 0) (const_int 24))))] “TARGET_H8300H || TARGET_H8300S” “#” “&& reload_completed” [(set (match_dup 3) (ior:HI (zero_extend:HI (match_dup 1)) (ashift:HI (subreg:HI (match_dup 2) 0) (const_int 8)))) (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16))) (clobber (scratch:QI))])] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); })

;; Used to add the exponent of a float.

(define_insn “*addsi3_shift” [(set (match_operand:SI 0 “register_operand” “=r”) (plus:SI (mult:SI (match_operand:SI 1 “register_operand” “r”) (const_int 8388608)) (match_operand:SI 2 “register_operand” “0”))) (clobber (match_scratch:SI 3 “=&r”))] “TARGET_H8300H || TARGET_H8300S” “#”)

(define_split [(set (match_operand:SI 0 “register_operand” "") (plus:SI (mult:SI (match_operand:SI 1 “register_operand” "") (const_int 8388608)) (match_dup 0))) (clobber (match_operand:SI 2 “register_operand” ""))] “(TARGET_H8300H || TARGET_H8300S) && epilogue_completed && find_regno_note (insn, REG_DEAD, REGNO (operands[1])) && REGNO (operands[0]) != REGNO (operands[1])” [(parallel [(set (match_dup 3) (ashift:HI (match_dup 3) (const_int 7))) (clobber (scratch:QI))]) (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 65536)) (match_dup 0)))] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[1])); })

(define_split [(set (match_operand:SI 0 “register_operand” "") (plus:SI (mult:SI (match_operand:SI 1 “register_operand” "") (const_int 8388608)) (match_dup 0))) (clobber (match_operand:SI 2 “register_operand” ""))] “(TARGET_H8300H || TARGET_H8300S) && epilogue_completed && !(find_regno_note (insn, REG_DEAD, REGNO (operands[1])) && REGNO (operands[0]) != REGNO (operands[1]))” [(set (match_dup 2) (match_dup 1)) (parallel [(set (match_dup 3) (ashift:HI (match_dup 3) (const_int 7))) (clobber (scratch:QI))]) (set (match_dup 0) (plus:SI (mult:SI (match_dup 2) (const_int 65536)) (match_dup 0)))] { operands[3] = gen_rtx_REG (HImode, REGNO (operands[2])); })

;; ashift:SI

(define_insn_and_split “*ashiftsi_sextqi_7” [(set (match_operand:SI 0 “register_operand” “=r”) (ashift:SI (sign_extend:SI (match_operand:QI 1 “register_operand” “0”)) (const_int 7)))] “TARGET_H8300H || TARGET_H8300S” “#” “&& reload_completed” [(parallel [(set (match_dup 2) (ashift:HI (match_dup 2) (const_int 8))) (clobber (scratch:QI))]) (set (match_dup 0) (sign_extend:SI (match_dup 2))) (parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 1))) (clobber (scratch:QI))])] { operands[2] = gen_rtx_REG (HImode, REGNO (operands[0])); })

;; Storing a part of HImode to QImode.

(define_insn "" [(set (match_operand:QI 0 “general_operand_dst” “=rm<”) (subreg:QI (lshiftrt:HI (match_operand:HI 1 “register_operand” “r”) (const_int 8)) 1))] "" “mov.b\t%t1,%R0” [(set_attr “cc” “set_znv”) (set_attr “length” “8”)])

;; Storing a part of SImode to QImode.

(define_insn "" [(set (match_operand:QI 0 “general_operand_dst” “=rm<”) (subreg:QI (lshiftrt:SI (match_operand:SI 1 “register_operand” “r”) (const_int 8)) 3))] "" “mov.b\t%x1,%R0” [(set_attr “cc” “set_znv”) (set_attr “length” “8”)])

(define_insn "" [(set (match_operand:QI 0 “general_operand_dst” “=rm<”) (subreg:QI (lshiftrt:SI (match_operand:SI 1 “register_operand” “r”) (const_int 16)) 3)) (clobber (match_scratch:SI 2 “=&r”))] “TARGET_H8300H || TARGET_H8300S” “mov.w\t%e1,%f2;mov.b\t%w2,%R0” [(set_attr “cc” “set_znv”) (set_attr “length” “10”)])

(define_insn "" [(set (match_operand:QI 0 “general_operand_dst” “=rm<”) (subreg:QI (lshiftrt:SI (match_operand:SI 1 “register_operand” “r”) (const_int 24)) 3)) (clobber (match_scratch:SI 2 “=&r”))] “TARGET_H8300H || TARGET_H8300S” “mov.w\t%e1,%f2;mov.b\t%x2,%R0” [(set_attr “cc” “set_znv”) (set_attr “length” “10”)])

(define_insn_and_split "" [(set (pc) (if_then_else (eq (zero_extract:SI (subreg:SI (match_operand:QI 0 “register_operand” "") 0) (const_int 1) (const_int 7)) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "" “#” "" [(set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_dup 1)) (pc)))] "")

(define_insn_and_split "" [(set (pc) (if_then_else (ne (zero_extract:SI (subreg:SI (match_operand:QI 0 “register_operand” "") 0) (const_int 1) (const_int 7)) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "" “#” "" [(set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_dup 1)) (pc)))] "") ;; ----------------------------------------------------------------- ;; PEEPHOLE PATTERNS ;; -----------------------------------------------------------------

;; Convert (A >> B) & C to (A & 255) >> B if C == 255 >> B.

(define_peephole2 [(parallel [(set (match_operand:HI 0 “register_operand” "") (lshiftrt:HI (match_dup 0) (match_operand:HI 1 “const_int_operand” ""))) (clobber (match_operand:HI 2 "" ""))]) (set (match_dup 0) (and:HI (match_dup 0) (match_operand:HI 3 “const_int_operand” "")))] “INTVAL (operands[3]) == (255 >> INTVAL (operands[1]))” [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255))) (parallel [(set (match_dup 0) (lshiftrt:HI (match_dup 0) (match_dup 1))) (clobber (match_dup 2))])] "")

;; Convert (A << B) & C to (A & 255) << B if C == 255 << B.

(define_peephole2 [(parallel [(set (match_operand:HI 0 “register_operand” "") (ashift:HI (match_dup 0) (match_operand:HI 1 “const_int_operand” ""))) (clobber (match_operand:HI 2 "" ""))]) (set (match_dup 0) (and:HI (match_dup 0) (match_operand:HI 3 “const_int_operand” "")))] “INTVAL (operands[3]) == (255 << INTVAL (operands[1]))” [(set (match_dup 0) (and:HI (match_dup 0) (const_int 255))) (parallel [(set (match_dup 0) (ashift:HI (match_dup 0) (match_dup 1))) (clobber (match_dup 2))])] "")

;; Convert (A >> B) & C to (A & 255) >> B if C == 255 >> B.

(define_peephole2 [(parallel [(set (match_operand:SI 0 “register_operand” "") (lshiftrt:SI (match_dup 0) (match_operand:SI 1 “const_int_operand” ""))) (clobber (match_operand:SI 2 "" ""))]) (set (match_dup 0) (and:SI (match_dup 0) (match_operand:SI 3 “const_int_operand” "")))] “INTVAL (operands[3]) == (255 >> INTVAL (operands[1]))” [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255))) (parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) (clobber (match_dup 2))])] "")

;; Convert (A << B) & C to (A & 255) << B if C == 255 << B.

(define_peephole2 [(parallel [(set (match_operand:SI 0 “register_operand” "") (ashift:SI (match_dup 0) (match_operand:SI 1 “const_int_operand” ""))) (clobber (match_operand:SI 2 "" ""))]) (set (match_dup 0) (and:SI (match_dup 0) (match_operand:SI 3 “const_int_operand” "")))] “INTVAL (operands[3]) == (255 << INTVAL (operands[1]))” [(set (match_dup 0) (and:SI (match_dup 0) (const_int 255))) (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 1))) (clobber (match_dup 2))])] "")

;; Convert (A >> B) & C to (A & 65535) >> B if C == 65535 >> B.

(define_peephole2 [(parallel [(set (match_operand:SI 0 “register_operand” "") (lshiftrt:SI (match_dup 0) (match_operand:SI 1 “const_int_operand” ""))) (clobber (match_operand:SI 2 "" ""))]) (set (match_dup 0) (and:SI (match_dup 0) (match_operand:SI 3 “const_int_operand” "")))] “INTVAL (operands[3]) == (65535 >> INTVAL (operands[1]))” [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535))) (parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1))) (clobber (match_dup 2))])] "")

;; Convert (A << B) & C to (A & 65535) << B if C == 65535 << B.

(define_peephole2 [(parallel [(set (match_operand:SI 0 “register_operand” "") (ashift:SI (match_dup 0) (match_operand:SI 1 “const_int_operand” ""))) (clobber (match_operand:SI 2 "" ""))]) (set (match_dup 0) (and:SI (match_dup 0) (match_operand:SI 3 “const_int_operand” "")))] “INTVAL (operands[3]) == (65535 << INTVAL (operands[1]))” [(set (match_dup 0) (and:SI (match_dup 0) (const_int 65535))) (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 1))) (clobber (match_dup 2))])] "")

;; Convert a QImode push into an SImode push so that the ;; define_peephole2 below can cram multiple pushes into one stm.l.

(define_peephole2 [(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” ""))])] “TARGET_H8300S && !TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG” [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))] { operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); })

(define_peephole2 [(parallel [(set (reg:HI SP_REG) (plus:HI (reg:HI SP_REG) (const_int -4))) (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -3))) (match_operand:QI 0 “register_operand” ""))])] “TARGET_H8300S && TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG” [(set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_dup 0))] { operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); })

;; Convert a HImode push into an SImode push so that the ;; define_peephole2 below can cram multiple pushes into one stm.l.

(define_peephole2 [(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” ""))])] “TARGET_H8300S && !TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG” [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))] { operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); })

(define_peephole2 [(parallel [(set (reg:HI SP_REG) (plus:HI (reg:HI SP_REG) (const_int -4))) (set (mem:HI (plus:HI (reg:HI SP_REG) (const_int -2))) (match_operand:HI 0 “register_operand” ""))])] “TARGET_H8300S && TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG” [(set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_dup 0))] { operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); })

;; Cram four pushes into stm.l.

(define_peephole2 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 0 “register_operand” "")) (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 1 “register_operand” "")) (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 2 “register_operand” "")) (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 3 “register_operand” ""))] “TARGET_H8300S && !TARGET_NORMAL_MODE && (REGNO_REG_CLASS (REGNO (operands[3])) == GENERAL_REGS && REGNO (operands[1]) == REGNO (operands[0]) + 1 && REGNO (operands[2]) == REGNO (operands[0]) + 2 && REGNO (operands[3]) == REGNO (operands[0]) + 3 && (TARGET_H8300SX || REGNO (operands[0]) == 0))” [(parallel [(set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4))) (match_dup 0)) (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8))) (match_dup 1)) (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12))) (match_dup 2)) (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -16))) (match_dup 3)) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -16)))])] "")

(define_peephole2 [(set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 0 “register_operand” "")) (set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 1 “register_operand” "")) (set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 2 “register_operand” "")) (set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 3 “register_operand” ""))] “TARGET_H8300S && TARGET_NORMAL_MODE && (REGNO_REG_CLASS (REGNO (operands[3])) == GENERAL_REGS && REGNO (operands[1]) == REGNO (operands[0]) + 1 && REGNO (operands[2]) == REGNO (operands[0]) + 2 && REGNO (operands[3]) == REGNO (operands[0]) + 3 && (TARGET_H8300SX || REGNO (operands[0]) == 0))” [(parallel [(set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -4))) (match_dup 0)) (set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -8))) (match_dup 1)) (set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -12))) (match_dup 2)) (set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -16))) (match_dup 3)) (set (reg:HI SP_REG) (plus:HI (reg:HI SP_REG) (const_int -16)))])] "")

;; Cram three pushes into stm.l.

(define_peephole2 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 0 “register_operand” "")) (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 1 “register_operand” "")) (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 2 “register_operand” ""))] “TARGET_H8300S && !TARGET_NORMAL_MODE && (REGNO_REG_CLASS (REGNO (operands[2])) == GENERAL_REGS && REGNO (operands[1]) == REGNO (operands[0]) + 1 && REGNO (operands[2]) == REGNO (operands[0]) + 2 && (TARGET_H8300SX || (REGNO (operands[0]) & 3) == 0))” [(parallel [(set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4))) (match_dup 0)) (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8))) (match_dup 1)) (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12))) (match_dup 2)) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -12)))])] "")

(define_peephole2 [(set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 0 “register_operand” "")) (set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 1 “register_operand” "")) (set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 2 “register_operand” ""))] “TARGET_H8300S && TARGET_NORMAL_MODE && (REGNO_REG_CLASS (REGNO (operands[2])) == GENERAL_REGS && REGNO (operands[1]) == REGNO (operands[0]) + 1 && REGNO (operands[2]) == REGNO (operands[0]) + 2 && (TARGET_H8300SX || (REGNO (operands[0]) & 3) == 0))” [(parallel [(set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -4))) (match_dup 0)) (set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -8))) (match_dup 1)) (set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -12))) (match_dup 2)) (set (reg:HI SP_REG) (plus:HI (reg:HI SP_REG) (const_int -12)))])] "")

;; Cram two pushes into stm.l.

(define_peephole2 [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 0 “register_operand” "")) (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_operand:SI 1 “register_operand” ""))] “TARGET_H8300S && !TARGET_NORMAL_MODE && (REGNO_REG_CLASS (REGNO (operands[1])) == GENERAL_REGS && REGNO (operands[1]) == REGNO (operands[0]) + 1 && (TARGET_H8300SX || (REGNO (operands[0]) & 1) == 0))” [(parallel [(set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4))) (match_dup 0)) (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8))) (match_dup 1)) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -8)))])] "")

(define_peephole2 [(set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 0 “register_operand” "")) (set (mem:SI (pre_dec:HI (reg:HI SP_REG))) (match_operand:SI 1 “register_operand” ""))] “TARGET_H8300S && TARGET_NORMAL_MODE && (REGNO_REG_CLASS (REGNO (operands[1])) == GENERAL_REGS && REGNO (operands[1]) == REGNO (operands[0]) + 1 && (TARGET_H8300SX || (REGNO (operands[0]) & 1) == 0))” [(parallel [(set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -4))) (match_dup 0)) (set (mem:SI (plus:HI (reg:HI SP_REG) (const_int -8))) (match_dup 1)) (set (reg:HI SP_REG) (plus:HI (reg:HI SP_REG) (const_int -8)))])] "")

;; Turn ;; ;; mov.w #2,r0 ;; add.w r7,r0 (6 bytes) ;; ;; into ;; ;; mov.w r7,r0 ;; adds #2,r0 (4 bytes)

(define_peephole2 [(set (match_operand:HI 0 “register_operand” "") (match_operand:HI 1 “const_int_operand” "")) (set (match_dup 0) (plus:HI (match_dup 0) (match_operand:HI 2 “register_operand” "")))] “REG_P (operands[0]) && REG_P (operands[2]) && REGNO (operands[0]) != REGNO (operands[2]) && (satisfies_constraint_J (operands[1]) || satisfies_constraint_L (operands[1]) || satisfies_constraint_N (operands[1]))” [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))] "")

;; Turn ;; ;; sub.l er0,er0 ;; add.b #4,r0l ;; add.l er7,er0 (6 bytes) ;; ;; into ;; ;; mov.l er7,er0 ;; adds #4,er0 (4 bytes)

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” "")) (set (match_dup 0) (plus:SI (match_dup 0) (match_operand:SI 2 “register_operand” "")))] “(TARGET_H8300H || TARGET_H8300S) && REG_P (operands[0]) && REG_P (operands[2]) && REGNO (operands[0]) != REGNO (operands[2]) && (satisfies_constraint_L (operands[1]) || satisfies_constraint_N (operands[1]))” [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] "")

;; Turn ;; ;; mov.l er7,er0 ;; add.l #10,er0 (takes 8 bytes) ;; ;; into ;; ;; sub.l er0,er0 ;; add.b #10,r0l ;; add.l er7,er0 (takes 6 bytes)

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “register_operand” "")) (set (match_dup 0) (plus:SI (match_dup 0) (match_operand:SI 2 “const_int_operand” "")))] “(TARGET_H8300H || TARGET_H8300S) && REG_P (operands[0]) && REG_P (operands[1]) && REGNO (operands[0]) != REGNO (operands[1]) && !satisfies_constraint_L (operands[2]) && !satisfies_constraint_N (operands[2]) && ((INTVAL (operands[2]) & 0xff) == INTVAL (operands[2]) || (INTVAL (operands[2]) & 0xff00) == INTVAL (operands[2]) || INTVAL (operands[2]) == 0xffff || INTVAL (operands[2]) == 0xfffe)” [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] "")

;; Turn ;; ;; subs #1,er4 ;; mov.w r4,r4 ;; bne .L2028 ;; ;; into ;; ;; dec.w #1,r4 ;; bne .L2028

(define_peephole2 [(set (match_operand:HI 0 “register_operand” "") (plus:HI (match_dup 0) (match_operand 1 “incdec_operand” ""))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “TARGET_H8300H || TARGET_H8300S” [(set (match_operand:HI 0 “register_operand” "") (unspec:HI [(match_dup 0) (match_dup 1)] UNSPEC_INCDEC)) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] "")

;; The SImode version of the previous pattern.

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (plus:SI (match_dup 0) (match_operand 1 “incdec_operand” ""))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “TARGET_H8300H || TARGET_H8300S” [(set (match_operand:SI 0 “register_operand” "") (unspec:SI [(match_dup 0) (match_dup 1)] UNSPEC_INCDEC)) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] "")

(define_peephole2 [(parallel [(set (cc0) (compare (zero_extract:SI (match_operand:QI 0 “register_operand” "") (const_int 1) (const_int 7)) (const_int 0))) (clobber (scratch:QI))]) (set (pc) (if_then_else (match_operator 1 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “TARGET_H8300H || TARGET_H8300S” [(set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[3] = ((GET_CODE (operands[1]) == EQ) ? gen_rtx_GE (VOIDmode, cc0_rtx, const0_rtx) : gen_rtx_LT (VOIDmode, cc0_rtx, const0_rtx)); })

;; The next three peephole2's will try to transform ;; ;; mov.b A,r0l (or mov.l A,er0) ;; and.l #CST,er0 ;; ;; into ;; ;; sub.l er0 ;; mov.b A,r0l ;; and.b #CST,r0l (if CST is not 255)

(define_peephole2 [(set (match_operand:QI 0 “register_operand” "") (match_operand:QI 1 “general_operand” "")) (set (match_operand:SI 2 “register_operand” "") (and:SI (match_dup 2) (const_int 255)))] “(TARGET_H8300H || TARGET_H8300S) && !reg_overlap_mentioned_p (operands[2], operands[1]) && REGNO (operands[0]) == REGNO (operands[2])” [(set (match_dup 2) (const_int 0)) (set (strict_low_part (match_dup 0)) (match_dup 1))] "")

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “general_operand” "")) (set (match_dup 0) (and:SI (match_dup 0) (const_int 255)))] “(TARGET_H8300H || TARGET_H8300S) && !reg_overlap_mentioned_p (operands[0], operands[1]) && !(GET_CODE (operands[1]) == MEM && !offsettable_memref_p (operands[1])) && !(GET_CODE (operands[1]) == MEM && MEM_VOLATILE_P (operands[1]))” [(set (match_dup 0) (const_int 0)) (set (strict_low_part (match_dup 2)) (match_dup 3))] { operands[2] = gen_lowpart (QImode, operands[0]); operands[3] = gen_lowpart (QImode, operands[1]); })

(define_peephole2 [(set (match_operand 0 “register_operand” "") (match_operand 1 “general_operand” "")) (set (match_operand:SI 2 “register_operand” "") (and:SI (match_dup 2) (match_operand:SI 3 “const_int_qi_operand” "")))] “(TARGET_H8300H || TARGET_H8300S) && (GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode || GET_MODE (operands[0]) == SImode) && GET_MODE (operands[0]) == GET_MODE (operands[1]) && REGNO (operands[0]) == REGNO (operands[2]) && !reg_overlap_mentioned_p (operands[2], operands[1]) && !(GET_MODE (operands[1]) != QImode && GET_CODE (operands[1]) == MEM && !offsettable_memref_p (operands[1])) && !(GET_MODE (operands[1]) != QImode && GET_CODE (operands[1]) == MEM && MEM_VOLATILE_P (operands[1]))” [(set (match_dup 2) (const_int 0)) (set (strict_low_part (match_dup 4)) (match_dup 5)) (set (match_dup 2) (and:SI (match_dup 2) (match_dup 6)))] { operands[4] = gen_lowpart (QImode, operands[0]); operands[5] = gen_lowpart (QImode, operands[1]); operands[6] = GEN_INT (~0xff | INTVAL (operands[3])); })

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “register_operand” "")) (set (match_dup 0) (and:SI (match_dup 0) (const_int 65280)))] “(TARGET_H8300H || TARGET_H8300S) && !reg_overlap_mentioned_p (operands[0], operands[1])” [(set (match_dup 0) (const_int 0)) (set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8)) (lshiftrt:SI (match_dup 1) (const_int 8)))] "")

;; If a load of mem:SI is followed by an AND that turns off the upper ;; half, then we can load mem:HI instead.

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “memory_operand” "")) (set (match_dup 0) (and:SI (match_dup 0) (match_operand:SI 2 “const_int_operand” "")))] “(TARGET_H8300H || TARGET_H8300S) && !MEM_VOLATILE_P (operands[1]) && offsettable_memref_p (operands[1]) && (INTVAL (operands[2]) & ~0xffff) == 0 && INTVAL (operands[2]) != 255” [(set (match_dup 3) (match_dup 4)) (set (match_dup 0) (and:SI (match_dup 0) (match_dup 2)))] { operands[3] = gen_lowpart (HImode, operands[0]); operands[4] = gen_lowpart (HImode, operands[1]); })

;; Convert a memory comparison to a move if there is a scratch register.

(define_peephole2 [(match_scratch:QI 1 “r”) (set (cc0) (compare (match_operand:QI 0 “memory_operand” "") (const_int 0)))] "" [(set (match_dup 1) (match_dup 0)) (set (cc0) (compare (match_dup 1) (const_int 0)))] "")

(define_peephole2 [(match_scratch:HI 1 “r”) (set (cc0) (compare (match_operand:HI 0 “memory_operand” "") (const_int 0)))] “TARGET_H8300H || TARGET_H8300S” [(set (match_dup 1) (match_dup 0)) (set (cc0) (compare (match_dup 1) (const_int 0)))] "")

(define_peephole2 [(match_scratch:SI 1 “r”) (set (cc0) (compare (match_operand:SI 0 “memory_operand” "") (const_int 0)))] “TARGET_H8300H || TARGET_H8300S” [(set (match_dup 1) (match_dup 0)) (set (cc0) (compare (match_dup 1) (const_int 0)))] "")

;; (compare (reg:HI) (const_int)) takes 4 bytes, so we try to achieve ;; the equivalent with shorter sequences. Here is the summary. Cases ;; are grouped for each define_peephole2. ;; ;; reg const_int use insn ;; -------------------------------------------------------- ;; dead -2 eq/ne inc.l ;; dead -1 eq/ne inc.l ;; dead 1 eq/ne dec.l ;; dead 2 eq/ne dec.l ;; ;; dead 1 ge/lt shar.l ;; dead 3 (H8S) ge/lt shar.l ;; ;; dead 1 geu/ltu shar.l ;; dead 3 (H8S) geu/ltu shar.l ;; ;; ---- 255 ge/lt mov.b ;; ;; ---- 255 geu/ltu mov.b

;; Transform ;; ;; cmp.w #1,r0 ;; bne .L1 ;; ;; into ;; ;; dec.w #1,r0 ;; bne .L1

(define_peephole2 [(set (cc0) (compare (match_operand:HI 0 “register_operand” "") (match_operand:HI 1 “incdec_operand” ""))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) != 0 && peep2_reg_dead_p (1, operands[0])” [(set (match_dup 0) (unspec:HI [(match_dup 0) (match_dup 4)] UNSPEC_INCDEC)) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[4] = GEN_INT (- INTVAL (operands[1])); })

;; Transform ;; ;; cmp.w #1,r0 ;; bgt .L1 ;; ;; into ;; ;; shar.w r0 ;; bgt .L1

(define_peephole2 [(set (cc0) (compare (match_operand:HI 0 “register_operand” "") (match_operand:HI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 2 “gtle_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && (INTVAL (operands[1]) == 1 || (TARGET_H8300S && INTVAL (operands[1]) == 3))” [(parallel [(set (match_dup 0) (ashiftrt:HI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) (pc)))] { operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); })

;; Transform ;; ;; cmp.w #1,r0 ;; bhi .L1 ;; ;; into ;; ;; shar.w r0 ;; bne .L1

(define_peephole2 [(set (cc0) (compare (match_operand:HI 0 “register_operand” "") (match_operand:HI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 2 “gtuleu_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && (INTVAL (operands[1]) == 1 || (TARGET_H8300S && INTVAL (operands[1]) == 3))” [(parallel [(set (match_dup 0) (ashiftrt:HI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) (pc)))] { operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[2]) == GTU ? NE : EQ, VOIDmode, cc0_rtx, const0_rtx); })

;; Transform ;; ;; cmp.w #255,r0 ;; bgt .L1 ;; ;; into ;; ;; mov.b r0h,r0h ;; bgt .L1

(define_peephole2 [(set (cc0) (compare (match_operand:HI 0 “register_operand” "") (const_int 255))) (set (pc) (if_then_else (match_operator 1 “gtle_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “TARGET_H8300H || TARGET_H8300S” [(set (cc0) (compare (and:HI (match_dup 0) (const_int -256)) (const_int 0))) (set (pc) (if_then_else (match_dup 1) (label_ref (match_dup 2)) (pc)))] "")

;; Transform ;; ;; cmp.w #255,r0 ;; bhi .L1 ;; ;; into ;; ;; mov.b r0h,r0h ;; bne .L1

(define_peephole2 [(set (cc0) (compare (match_operand:HI 0 “register_operand” "") (const_int 255))) (set (pc) (if_then_else (match_operator 1 “gtuleu_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “TARGET_H8300H || TARGET_H8300S” [(set (cc0) (compare (and:HI (match_dup 0) (const_int -256)) (const_int 0))) (set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 2)) (pc)))] { operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[1]) == GTU ? NE : EQ, VOIDmode, cc0_rtx, const0_rtx); })

;; (compare (reg:SI) (const_int)) takes 6 bytes, so we try to achieve ;; the equivalent with shorter sequences. Here is the summary. Cases ;; are grouped for each define_peephole2. ;; ;; reg const_int use insn ;; -------------------------------------------------------- ;; live -2 eq/ne copy and inc.l ;; live -1 eq/ne copy and inc.l ;; live 1 eq/ne copy and dec.l ;; live 2 eq/ne copy and dec.l ;; ;; dead -2 eq/ne inc.l ;; dead -1 eq/ne inc.l ;; dead 1 eq/ne dec.l ;; dead 2 eq/ne dec.l ;; ;; dead -131072 eq/ne inc.w and test ;; dead -65536 eq/ne inc.w and test ;; dead 65536 eq/ne dec.w and test ;; dead 131072 eq/ne dec.w and test ;; ;; dead 0x000000?? except 1 and 2 eq/ne xor.b and test ;; dead 0x0000??00 eq/ne xor.b and test ;; dead 0x0000ffff eq/ne not.w and test ;; ;; dead 0xffffff?? except -1 and -2 eq/ne xor.b and not.l ;; dead 0xffff??ff eq/ne xor.b and not.l ;; dead 0x40000000 (H8S) eq/ne rotl.l and dec.l ;; dead 0x80000000 eq/ne rotl.l and dec.l ;; ;; live 1 ge/lt copy and shar.l ;; live 3 (H8S) ge/lt copy and shar.l ;; ;; live 1 geu/ltu copy and shar.l ;; live 3 (H8S) geu/ltu copy and shar.l ;; ;; dead 1 ge/lt shar.l ;; dead 3 (H8S) ge/lt shar.l ;; ;; dead 1 geu/ltu shar.l ;; dead 3 (H8S) geu/ltu shar.l ;; ;; dead 3 (H8/300H) ge/lt and.b and test ;; dead 7 ge/lt and.b and test ;; dead 15 ge/lt and.b and test ;; dead 31 ge/lt and.b and test ;; dead 63 ge/lt and.b and test ;; dead 127 ge/lt and.b and test ;; dead 255 ge/lt and.b and test ;; ;; dead 3 (H8/300H) geu/ltu and.b and test ;; dead 7 geu/ltu and.b and test ;; dead 15 geu/ltu and.b and test ;; dead 31 geu/ltu and.b and test ;; dead 63 geu/ltu and.b and test ;; dead 127 geu/ltu and.b and test ;; dead 255 geu/ltu and.b and test ;; ;; ---- 65535 ge/lt mov.w ;; ;; ---- 65535 geu/ltu mov.w

;; Transform ;; ;; cmp.l #1,er0 ;; beq .L1 ;; ;; into ;; ;; dec.l #1,er0 ;; beq .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “incdec_operand” ""))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) != 0 && peep2_reg_dead_p (1, operands[0])” [(set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 4)] UNSPEC_INCDEC)) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[4] = GEN_INT (- INTVAL (operands[1])); })

;; Transform ;; ;; cmp.l #65536,er0 ;; beq .L1 ;; ;; into ;; ;; dec.l #1,e0 ;; beq .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && (INTVAL (operands[1]) == -131072 || INTVAL (operands[1]) == -65536 || INTVAL (operands[1]) == 65536 || INTVAL (operands[1]) == 131072)” [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[4] = GEN_INT (- INTVAL (operands[1])); })

;; Transform ;; ;; cmp.l #100,er0 ;; beq .L1 ;; ;; into ;; ;; xor.b #100,er0 ;; mov.l er0,er0 ;; beq .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && ((INTVAL (operands[1]) & 0x00ff) == INTVAL (operands[1]) || (INTVAL (operands[1]) & 0xff00) == INTVAL (operands[1]) || INTVAL (operands[1]) == 0x0000ffff) && INTVAL (operands[1]) != 0 && INTVAL (operands[1]) != 1 && INTVAL (operands[1]) != 2” [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] "")

;; Transform ;; ;; cmp.l #-100,er0 ;; beq .L1 ;; ;; into ;; ;; xor.b #99,er0 ;; not.l er0 ;; beq .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && ((INTVAL (operands[1]) | 0x00ff) == -1 || (INTVAL (operands[1]) | 0xff00) == -1) && INTVAL (operands[1]) != -1 && INTVAL (operands[1]) != -2” [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 4))) (set (match_dup 0) (not:SI (match_dup 0))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[4] = GEN_INT (INTVAL (operands[1]) ^ -1); })

;; Transform ;; ;; cmp.l #-2147483648,er0 ;; beq .L1 ;; ;; into ;; ;; rotl.l er0 ;; dec.l #1,er0 ;; beq .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && (INTVAL (operands[1]) == -2147483647 - 1 || (TARGET_H8300S && INTVAL (operands[1]) == 1073741824))” [(set (match_dup 0) (rotate:SI (match_dup 0) (match_dup 4))) (set (match_dup 0) (unspec:SI [(match_dup 0) (const_int -1)] UNSPEC_INCDEC)) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[4] = GEN_INT (INTVAL (operands[1]) == -2147483647 - 1 ? 1 : 2); })

;; Transform ;; ;; cmp.l #1,er0 ;; bgt .L1 ;; ;; into ;; ;; mov.l er0,er1 ;; shar.l er1 ;; bgt .L1

;; We avoid this transformation if we see more than one copy of the ;; same compare insn immediately before this one.

(define_peephole2 [(match_scratch:SI 4 “r”) (set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 2 “gtle_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && !peep2_reg_dead_p (1, operands[0]) && (INTVAL (operands[1]) == 1 || (TARGET_H8300S && INTVAL (operands[1]) == 3)) && !same_cmp_preceding_p (insn)” [(set (match_dup 4) (match_dup 0)) (parallel [(set (match_dup 4) (ashiftrt:SI (match_dup 4) (match_dup 5))) (clobber (scratch:QI))]) (set (cc0) (compare (match_dup 4) (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) (pc)))] { operands[5] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); })

;; Transform ;; ;; cmp.l #1,er0 ;; bhi .L1 ;; ;; into ;; ;; mov.l er0,er1 ;; shar.l er1 ;; bne .L1

;; We avoid this transformation if we see more than one copy of the ;; same compare insn immediately before this one.

(define_peephole2 [(match_scratch:SI 4 “r”) (set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 2 “gtuleu_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && !peep2_reg_dead_p (1, operands[0]) && (INTVAL (operands[1]) == 1 || (TARGET_H8300S && INTVAL (operands[1]) == 3)) && !same_cmp_preceding_p (insn)” [(set (match_dup 4) (match_dup 0)) (parallel [(set (match_dup 4) (ashiftrt:SI (match_dup 4) (match_dup 5))) (clobber (scratch:QI))]) (set (cc0) (compare (match_dup 4) (const_int 0))) (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 3)) (pc)))] { operands[5] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[2]) == GTU ? NE : EQ, VOIDmode, cc0_rtx, const0_rtx); })

;; Transform ;; ;; cmp.l #1,er0 ;; bgt .L1 ;; ;; into ;; ;; shar.l er0 ;; bgt .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 2 “gtle_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && (INTVAL (operands[1]) == 1 || (TARGET_H8300S && INTVAL (operands[1]) == 3))” [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) (pc)))] { operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); })

;; Transform ;; ;; cmp.l #1,er0 ;; bhi .L1 ;; ;; into ;; ;; shar.l er0 ;; bne .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 2 “gtuleu_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && (INTVAL (operands[1]) == 1 || (TARGET_H8300S && INTVAL (operands[1]) == 3))” [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) (pc)))] { operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[2]) == GTU ? NE : EQ, VOIDmode, cc0_rtx, const0_rtx); })

;; Transform ;; ;; cmp.l #15,er0 ;; bgt .L1 ;; ;; into ;; ;; and #240,r0l ;; mov.l er0,er0 ;; bgt .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 2 “gtle_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && ((TARGET_H8300H && INTVAL (operands[1]) == 3) || INTVAL (operands[1]) == 7 || INTVAL (operands[1]) == 15 || INTVAL (operands[1]) == 31 || INTVAL (operands[1]) == 63 || INTVAL (operands[1]) == 127 || INTVAL (operands[1]) == 255)” [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 4))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) (pc)))] { operands[4] = GEN_INT (~INTVAL (operands[1])); })

;; Transform ;; ;; cmp.l #15,er0 ;; bhi .L1 ;; ;; into ;; ;; and #240,r0l ;; mov.l er0,er0 ;; bne .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “const_int_operand” ""))) (set (pc) (if_then_else (match_operator 2 “gtuleu_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && peep2_reg_dead_p (1, operands[0]) && ((TARGET_H8300H && INTVAL (operands[1]) == 3) || INTVAL (operands[1]) == 7 || INTVAL (operands[1]) == 15 || INTVAL (operands[1]) == 31 || INTVAL (operands[1]) == 63 || INTVAL (operands[1]) == 127 || INTVAL (operands[1]) == 255)” [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 4))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) (pc)))] { operands[4] = GEN_INT (~INTVAL (operands[1])); operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[2]) == GTU ? NE : EQ, VOIDmode, cc0_rtx, const0_rtx); })

;; Transform ;; ;; cmp.l #65535,er0 ;; bgt .L1 ;; ;; into ;; ;; mov.l e0,e0 ;; bgt .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (const_int 65535))) (set (pc) (if_then_else (match_operator 1 “gtle_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “TARGET_H8300H || TARGET_H8300S” [(set (cc0) (compare (and:SI (match_dup 0) (const_int -65536)) (const_int 0))) (set (pc) (if_then_else (match_dup 1) (label_ref (match_dup 2)) (pc)))] "")

;; Transform ;; ;; cmp.l #65535,er0 ;; bhi .L1 ;; ;; into ;; ;; mov.l e0,e0 ;; bne .L1

(define_peephole2 [(set (cc0) (compare (match_operand:SI 0 “register_operand” "") (const_int 65535))) (set (pc) (if_then_else (match_operator 1 “gtuleu_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “TARGET_H8300H || TARGET_H8300S” [(set (cc0) (compare (and:SI (match_dup 0) (const_int -65536)) (const_int 0))) (set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 2)) (pc)))] {
operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[1]) == GTU ? NE : EQ, VOIDmode, cc0_rtx, const0_rtx); })

;; Transform ;; ;; cmp.l #1,er0 ;; beq .L1 ;; ;; into ;; ;; mov.l er0,er1 ;; dec.l #1,er1 ;; beq .L1

;; We avoid this transformation if we see more than one copy of the ;; same compare insn.

(define_peephole2 [(match_scratch:SI 4 “r”) (set (cc0) (compare (match_operand:SI 0 “register_operand” "") (match_operand:SI 1 “incdec_operand” ""))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) != 0 && !peep2_reg_dead_p (1, operands[0]) && !same_cmp_following_p (insn)” [(set (match_dup 4) (match_dup 0)) (set (match_dup 4) (unspec:SI [(match_dup 4) (match_dup 5)] UNSPEC_INCDEC)) (set (cc0) (compare (match_dup 4) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[5] = GEN_INT (- INTVAL (operands[1])); }) ;; Narrow the mode of testing if possible.

(define_peephole2 [(set (match_operand:HI 0 “register_operand” "") (and:HI (match_dup 0) (match_operand:HI 1 “const_int_qi_operand” ""))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “peep2_reg_dead_p (2, operands[0])” [(set (match_dup 4) (and:QI (match_dup 4) (match_dup 5))) (set (cc0) (compare (match_dup 4) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[4] = gen_rtx_REG (QImode, REGNO (operands[0])); operands[5] = gen_int_mode (INTVAL (operands[1]), QImode); })

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (and:SI (match_dup 0) (match_operand:SI 1 “const_int_qi_operand” ""))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “peep2_reg_dead_p (2, operands[0])” [(set (match_dup 4) (and:QI (match_dup 4) (match_dup 5))) (set (cc0) (compare (match_dup 4) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[4] = gen_rtx_REG (QImode, REGNO (operands[0])); operands[5] = gen_int_mode (INTVAL (operands[1]), QImode); })

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (and:SI (match_dup 0) (match_operand:SI 1 “const_int_hi_operand” ""))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_operator 3 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] “peep2_reg_dead_p (2, operands[0])” [(set (match_dup 4) (and:HI (match_dup 4) (match_dup 5))) (set (cc0) (compare (match_dup 4) (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) (pc)))] { operands[4] = gen_rtx_REG (HImode, REGNO (operands[0])); operands[5] = gen_int_mode (INTVAL (operands[1]), HImode); })

(define_peephole2 [(set (match_operand:SI 0 “register_operand” "") (and:SI (match_dup 0) (match_operand:SI 1 “const_int_qi_operand” ""))) (set (match_dup 0) (xor:SI (match_dup 0) (match_operand:SI 2 “const_int_qi_operand” ""))) (set (cc0) (compare (match_dup 0) (const_int 0))) (set (pc) (if_then_else (match_operator 4 “eqne_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] “peep2_reg_dead_p (3, operands[0]) && (~INTVAL (operands[1]) & INTVAL (operands[2])) == 0” [(set (match_dup 5) (and:QI (match_dup 5) (match_dup 6))) (set (match_dup 5) (xor:QI (match_dup 5) (match_dup 7))) (set (cc0) (compare (match_dup 5) (const_int 0))) (set (pc) (if_then_else (match_op_dup 4 [(cc0) (const_int 0)]) (label_ref (match_dup 3)) (pc)))] { operands[5] = gen_rtx_REG (QImode, REGNO (operands[0])); operands[6] = gen_int_mode (INTVAL (operands[1]), QImode); operands[7] = gen_int_mode (INTVAL (operands[2]), QImode); })

;; These triggers right at the end of allocation of locals in the ;; prologue (and possibly at other places).

;; stack adjustment of -4, generate one push ;; ;; before : 6 bytes, 10 clocks ;; after : 4 bytes, 10 clocks

(define_peephole2 [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4))) (set (mem:SI (reg:SI SP_REG)) (match_operand:SI 0 “register_operand” ""))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG” [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))] "")

;; stack adjustment of -12, generate one push ;; ;; before : 10 bytes, 14 clocks ;; after : 8 bytes, 14 clocks

(define_peephole2 [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -12))) (set (mem:SI (reg:SI SP_REG)) (match_operand:SI 0 “register_operand” ""))] “(TARGET_H8300H || TARGET_H8300S) && !TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG” [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4))) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4))) (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 0))] "")

;; Transform ;; ;; mov dst,reg ;; op src,reg ;; mov reg,dst ;; ;; into ;; ;; op src,dst ;; ;; if “reg” dies at the end of the sequence.

(define_peephole2 [(set (match_operand 0 “register_operand” "") (match_operand 1 “memory_operand” "")) (set (match_dup 0) (match_operator 2 “h8sx_binary_memory_operator” [(match_dup 0) (match_operand 3 “h8300_src_operand” "")])) (set (match_operand 4 “memory_operand” "") (match_dup 0))] “0 /* Disable because it breaks compiling fp-bit.c. */ && TARGET_H8300SX && peep2_reg_dead_p (3, operands[0]) && !reg_overlap_mentioned_p (operands[0], operands[3]) && !reg_overlap_mentioned_p (operands[0], operands[4]) && h8sx_mergeable_memrefs_p (operands[4], operands[1])” [(set (match_dup 4) (match_dup 5))] { operands[5] = shallow_copy_rtx (operands[2]); XEXP (operands[5], 0) = operands[1]; })

;; Transform ;; ;; mov src,reg ;; op reg,dst ;; ;; into ;; ;; op src,dst ;; ;; if “reg” dies in the second insn.

(define_peephole2 [(set (match_operand 0 “register_operand” "") (match_operand 1 “h8300_src_operand” "")) (set (match_operand 2 “h8300_dst_operand” "") (match_operator 3 “h8sx_binary_memory_operator” [(match_operand 4 “h8300_dst_operand” "") (match_dup 0)]))] “0 /* Disable because it breaks compiling fp-bit.c. */ && TARGET_H8300SX && peep2_reg_dead_p (2, operands[0]) && !reg_overlap_mentioned_p (operands[0], operands[4])” [(set (match_dup 2) (match_dup 5))] { operands[5] = shallow_copy_rtx (operands[3]); XEXP (operands[5], 1) = operands[1]; })

;; Transform ;; ;; mov dst,reg ;; op reg ;; mov reg,dst ;; ;; into ;; ;; op dst ;; ;; if “reg” dies at the end of the sequence.

(define_peephole2 [(set (match_operand 0 “register_operand” "") (match_operand 1 “memory_operand” "")) (set (match_dup 0) (match_operator 2 “h8sx_unary_memory_operator” [(match_dup 0)])) (set (match_operand 3 “memory_operand” "") (match_dup 0))] “TARGET_H8300SX && peep2_reg_dead_p (3, operands[0]) && !reg_overlap_mentioned_p (operands[0], operands[3]) && h8sx_mergeable_memrefs_p (operands[3], operands[1])” [(set (match_dup 3) (match_dup 4))] { operands[4] = shallow_copy_rtx (operands[2]); XEXP (operands[4], 0) = operands[1]; })

;; Transform ;; ;; mov src1,reg ;; cmp reg,src2 ;; ;; into ;; ;; cmp src1,src2 ;; ;; if “reg” dies in the comparison.

(define_peephole2 [(set (match_operand 0 “register_operand” "") (match_operand 1 “h8300_dst_operand” "")) (set (cc0) (compare (match_dup 0) (match_operand 2 “h8300_src_operand” "")))] “TARGET_H8300SX && peep2_reg_dead_p (2, operands[0]) && !reg_overlap_mentioned_p (operands[0], operands[2]) && operands[2] != const0_rtx” [(set (cc0) (compare (match_dup 1) (match_dup 2)))])

;; Likewise for the second operand.

(define_peephole2 [(set (match_operand 0 “register_operand” "") (match_operand 1 “h8300_src_operand” "")) (set (cc0) (compare (match_operand 2 “h8300_dst_operand” "") (match_dup 0)))] “TARGET_H8300SX && peep2_reg_dead_p (2, operands[0]) && !reg_overlap_mentioned_p (operands[0], operands[2])” [(set (cc0) (compare (match_dup 2) (match_dup 1)))])

;; Combine two moves.

(define_peephole2 [(set (match_operand 0 “register_operand” "") (match_operand 1 “h8300_src_operand” "")) (set (match_operand 2 “h8300_dst_operand” "") (match_dup 0))] “TARGET_H8300SX && peep2_reg_dead_p (2, operands[0]) && !reg_overlap_mentioned_p (operands[0], operands[2])” [(set (match_dup 2) (match_dup 1))])