X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Fconfig%2Fh8300%2Fh8300.md;h=61f876c83996b9a33c8b0768927d062064f22692;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=51541af4330adca64a724efefa0601144548cc37;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 51541af4..61f876c8 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -1,41 +1,39 @@ -;; GCC machine description for Hitachi H8/300 +;; GCC machine description for Renesas H8/300 ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -;; 2001, 2002 Free Software Foundation, Inc. +;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +;; Free Software Foundation, Inc. ;; Contributed by Steve Chamberlain (sac@cygnus.com), ;; Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com). -;; This file is part of GNU CC. +;; This file is part of GCC. -;; GNU CC is free software; you can redistribute it and/or modify +;; 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 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. -;; GNU CC is distributed in the hope that it will be useful, +;; 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 GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with GCC; see the file COPYING3. If not see +;; . -;; Some of the extend instructions accept a general_operand_src, which -;; allows all the normal memory addressing modes. The length computations -;; don't take this into account. The lengths in the MD file should be -;; "worst case" and then be adjusted to their correct values by -;; h8300_adjust_insn_length. +;; 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 H8/S, adds/subs operate on the 32bit "er" +;; 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 a insv/extzv expander for the H8/300H +;; 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 @@ -51,12 +49,25 @@ ;; ---------------------------------------------------------------------- (define_constants - [(SC_REG 3) - (FP_REG 6) + [(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)]) + (RAP_REG 10) + (FP_REG 11)]) ;; ---------------------------------------------------------------------- ;; ATTRIBUTES @@ -65,17 +76,23 @@ (define_attr "cpu" "h8300,h8300h" (const (symbol_ref "cpu_type"))) -(define_attr "type" "branch,arith" +(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 (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)) @@ -83,21 +100,38 @@ (le (minus (pc) (match_dup 0)) (const_int 32000)))) (const_int 4) - (const_int 6)))] + (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))) -;; The necessity of instruction length adjustment. - -(define_attr "adjust_length" "yes,no" - (cond [(eq_attr "type" "branch") (const_string "no")] - (const_string "yes"))) - ;; Condition code settings. ;; ;; none - insn does not affect cc ;; none_0hit - insn does not affect cc but it does modify operand 0 ;; This attribute is used to keep track of when operand 0 changes. -;; See the description of NOTICE_UPDATE_CC for more info. +;; 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 @@ -105,6 +139,44 @@ (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") + (ne (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 [(ne (symbol_ref "TARGET_H8300") (const_int 0)) (const_int 4) + (ne (symbol_ref "TARGET_H8300H") (const_int 0)) (const_int 10) + (ne (symbol_ref "TARGET_H8300S") (const_int 0)) (const_int 10)] + (const_int 14)))]) + +(include "predicates.md") ;; ---------------------------------------------------------------------- ;; MOVE INSTRUCTIONS @@ -112,39 +184,7 @@ ;; movqi -(define_insn "pushqi1_h8300" - [(parallel [(set (reg:HI SP_REG) - (plus:HI (reg:HI SP_REG) (const_int -2))) - (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1))) - (match_operand:QI 0 "register_operand" "r"))])] - "TARGET_H8300" - "mov.w\\t%T0,@-r7" - [(set_attr "length" "2") - (set_attr "cc" "clobber")]) - -(define_insn "pushqi1_h8300hs" - [(parallel [(set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) (const_int -4))) - (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3))) - (match_operand:QI 0 "register_operand" "r"))])] - "TARGET_H8300H || TARGET_H8300S" - "mov.l\\t%S0,@-er7" - [(set_attr "length" "4") - (set_attr "cc" "clobber")]) - -(define_expand "pushqi1" - [(use (match_operand:QI 0 "register_operand" ""))] - "" - " -{ - if (TARGET_H8300) - emit_insn (gen_pushqi1_h8300 (operands[0])); - else - emit_insn (gen_pushqi1_h8300hs (operands[0])); - DONE; -}") - -(define_insn "" +(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 @@ -160,10 +200,10 @@ [(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 "" +(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_H8300H || TARGET_H8300S) && !TARGET_H8300SX && (register_operand (operands[0], QImode) || register_operand (operands[1], QImode))" "@ @@ -173,9 +213,20 @@ mov.b %R1,%X0 mov.b %R1,%X0 mov.b %X1,%R0" - [(set_attr "length" "2,2,2,2,8,8") + [(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,%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" ""))] @@ -183,7 +234,8 @@ " { /* One of the ops has to be in a register. */ - if (!register_operand (operand0, QImode) + if (!TARGET_H8300SX + && !register_operand (operand0, QImode) && !register_operand (operand1, QImode)) { operands[1] = copy_to_mode_reg (QImode, operand1); @@ -191,50 +243,19 @@ }") (define_insn "movstrictqi" - [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r,r,r")) - (match_operand:QI 1 "general_operand_src" "I,r,n,m"))] + [(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 - mov.b %R1,%X0 - mov.b %R1,%X0" - [(set_attr_alternative "length" - [(const_int 2) (const_int 2) (const_int 2) - (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))]) - (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")]) + mov.b %X1,%X0" + [(set_attr "length" "2,*") + (set_attr "length_table" "*,movb") + (set_attr "cc" "set_zn,set_znv")]) ;; movhi -(define_expand "pushhi1_h8300" - [(set (mem:HI (pre_dec:HI (reg:HI SP_REG))) - (match_operand:HI 0 "register_operand" ""))] - "TARGET_H8300" - "") - -(define_insn "pushhi1_h8300hs" - [(parallel [(set (reg:SI SP_REG) - (plus:SI (reg:SI SP_REG) (const_int -4))) - (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2))) - (match_operand:HI 0 "register_operand" "r"))])] - "TARGET_H8300H || TARGET_H8300S" - "mov.l\\t%S0,@-er7" - [(set_attr "length" "4") - (set_attr "cc" "clobber")]) - -(define_expand "pushhi1" - [(use (match_operand:HI 0 "register_operand" ""))] - "" - " -{ - if (TARGET_H8300) - emit_insn (gen_pushhi1_h8300 (operands[0])); - else - emit_insn (gen_pushhi1_h8300hs (operands[0])); - DONE; -}") - -(define_insn "" +(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 @@ -252,13 +273,14 @@ mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0" - [(set_attr "length" "2,2,2,4,4,4") + [(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 "" +(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_H8300H || TARGET_H8300S) && !TARGET_H8300SX && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode))" "@ @@ -268,9 +290,24 @@ mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0" - [(set_attr "length" "2,2,2,4,8,8") + [(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,%T0 + mov.w %T1,%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" ""))] @@ -286,18 +323,16 @@ }") (define_insn "movstricthi" - [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r,r")) - (match_operand:HI 1 "general_operand_src" "I,r,i,m"))] + [(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 mov.w %T1,%T0" - [(set_attr_alternative "length" - [(const_int 2) (const_int 2) (const_int 4) - (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))]) - (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")]) + [(set_attr "length" "2,2,*") + (set_attr "length_table" "*,*,movw") + (set_attr "cc" "set_zn,set_znv,set_znv")]) ;; movsi @@ -309,10 +344,10 @@ { if (TARGET_H8300) { - if (do_movsi (operands)) + if (h8300_expand_movsi (operands)) DONE; } - else + else if (!TARGET_H8300SX) { /* One of the ops has to be in a register. */ if (!register_operand (operand1, SImode) @@ -323,29 +358,7 @@ } }") -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand_dst" "") - (match_operand:SF 1 "general_operand_src" ""))] - "" - " -{ - if (TARGET_H8300) - { - if (do_movsi (operands)) - DONE; - } - else - { - /* One of the ops has to be in a register. */ - if (!register_operand (operand1, SFmode) - && !register_operand (operand0, SFmode)) - { - operands[1] = copy_to_mode_reg (SFmode, operand1); - } - } -}") - -(define_insn "movsi_h8300" +(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 @@ -353,7 +366,7 @@ || register_operand (operands[1], SImode))" "* { - int rn = -1; + unsigned int rn = -1; switch (which_alternative) { case 0: @@ -387,14 +400,19 @@ } else { - /* See if either half is zero. If so, use sub.w to clear - that half. */ 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\"; } @@ -405,72 +423,16 @@ case 5: return \"mov.w %T1,%e0\;mov.w %T1,%f0\"; default: - abort (); - } -}" - [(set_attr "length" "4,4,8,8,4,4") - (set_attr "cc" "clobber")]) - -(define_insn "movsf_h8300" - [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,o,<,r") - (match_operand:SF 1 "general_operand_src" "I,r,io,r,r,>"))] - "TARGET_H8300 - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode))" - "* -{ - /* Copy of the movsi stuff. */ - int rn = -1; - switch (which_alternative) - { - case 0: - return \"sub.w %e0,%e0\;sub.w %f0,%f0\"; - case 1: - if (REGNO (operands[0]) < REGNO (operands[1])) - return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; - else - return \"mov.w %f1,%f0\;mov.w %e1,%e0\"; - case 2: - /* Make sure we don't trample the register we index with. */ - 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: - abort (); + gcc_unreachable (); } }" - [(set_attr "length" "4,4,8,8,4,4") - (set_attr "cc" "clobber")]) + [(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,m,<,r,*a,*a,r") - (match_operand:SI 1 "general_operand_src" "I,r,i,m,r,r,>,I,r,*a"))] - "(TARGET_H8300S || TARGET_H8300H) +(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 && (register_operand (operands[0], SImode) || register_operand (operands[1], SImode)) && !(GET_CODE (operands[0]) == MEM @@ -510,7 +472,7 @@ } /* Look for constants that can be obtained by subs, inc, and - dec to 0. */ + dec to 0. */ switch (val & 0xffffffff) { case 0xffffffff: @@ -539,182 +501,771 @@ } return \"mov.l %S1,%S0\"; }" - [(set_attr "length" "2,2,6,10,10,4,4,2,6,4") + [(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 "movsf_h8300h" - [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,m,<,r") - (match_operand:SF 1 "general_operand_src" "I,r,im,r,r,>"))] - "(TARGET_H8300H || TARGET_H8300S) - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode))" +(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,%S0 mov.l %S1,%S0 mov.l %S1,%S0 - mov.l %S1,%S0 - mov.l %S1,%S0" - [(set_attr "length" "2,2,10,10,4,4") - (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) - -;; ---------------------------------------------------------------------- -;; TEST INSTRUCTIONS -;; ---------------------------------------------------------------------- + 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; -(define_insn "" - [(set (cc0) (zero_extract:HI (match_operand:QI 0 "bit_memory_operand" "r,U") - (const_int 1) - (match_operand 1 "const_int_operand" "n,n")))] - "TARGET_H8300" - "btst %Z1,%Y0" - [(set_attr "length" "2,4") - (set_attr "cc" "set_zn,set_zn")]) + 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_insn "" - [(set (cc0) (zero_extract:HI (match_operand:HI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n")))] - "TARGET_H8300" - "btst %Z1,%Y0" - [(set_attr "length" "2") - (set_attr "cc" "set_zn")]) +(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; -(define_insn "" - [(set (cc0) (zero_extract:SI (match_operand:QI 0 "bit_memory_operand" "r,U") - (const_int 1) - (match_operand 1 "const_int_operand" "n,n")))] - "TARGET_H8300H || TARGET_H8300S" - "btst %Z1,%Y0" - [(set_attr "length" "2,8") - (set_attr "cc" "set_zn,set_zn")]) + 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")]) -(define_insn "" - [(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n")))] - "(TARGET_H8300H || TARGET_H8300S) - && INTVAL (operands[1]) <= 15" - "btst %Z1,%Y0" - [(set_attr "length" "2") - (set_attr "cc" "set_zn")]) +;; 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; -(define_insn "tstqi" - [(set (cc0) (match_operand:QI 0 "register_operand" "r"))] - "" - "mov.b %X0,%X0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) + 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_insn "tsthi" - [(set (cc0) (match_operand:HI 0 "register_operand" "r"))] - "" - "mov.w %T0,%T0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) +(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; -(define_insn "tstsi" - [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] - "TARGET_H8300H || TARGET_H8300S" - "mov.l %S0,%S0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) + 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_insn "cmpqi" - [(set (cc0) - (compare:QI (match_operand:QI 0 "register_operand" "r") - (match_operand:QI 1 "nonmemory_operand" "rn")))] - "" - "cmp.b %X1,%X0" - [(set_attr "length" "2") - (set_attr "cc" "compare")]) +(include "mova.md") -(define_expand "cmphi" - [(set (cc0) - (compare:HI (match_operand:HI 0 "register_operand" "") - (match_operand:HI 1 "nonmemory_operand" "")))] +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand_dst" "") + (match_operand:SF 1 "general_operand_src" ""))] "" " { - /* Force operand1 into a register if we're compiling - for the H8/300. */ - if (GET_CODE (operands[1]) != REG && TARGET_H8300) - operands[1] = force_reg (HImode, operands[1]); + 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 "" - [(set (cc0) - (compare:HI (match_operand:HI 0 "register_operand" "r") - (match_operand:HI 1 "register_operand" "r")))] - "TARGET_H8300" +(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 (reg:HI SP_REG) + (plus:HI (reg:HI SP_REG) (const_int -2))) + (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1))) + (match_operand:QI 0 "register_operand" "r"))] + "TARGET_H8300 + && operands[0] != stack_pointer_rtx" + "mov.w\\t%T0,@-r7" + [(set_attr "length" "2")]) + +(define_insn "pushqi1_h8300hs_advanced" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (const_int -4))) + (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3))) + (match_operand:QI 0 "register_operand" "r"))] + "(TARGET_H8300H || TARGET_H8300S) + && operands[0] != stack_pointer_rtx" + "mov.l\\t%S0,@-er7" + [(set_attr "length" "4")]) + +(define_insn "pushqi1_h8300hs_normal" + [(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" "r"))] + "(TARGET_H8300H || TARGET_H8300S) + && operands[0] != stack_pointer_rtx" + "mov.l\\t%S0,@-er7" + [(set_attr "length" "4")]) + +(define_expand "pushqi1" + [(match_operand:QI 0 "register_operand" "")] + "" + " +{ + if (TARGET_H8300) + emit_insn (gen_pushqi1_h8300 (operands[0])); + else if (!TARGET_NORMAL_MODE) + emit_insn (gen_pushqi1_h8300hs_advanced (operands[0])); + else + emit_insn (gen_pushqi1_h8300hs_normal (operands[0])); + DONE; +}") + +(define_expand "pushhi1_h8300" + [(set (mem:HI (pre_dec:HI (reg:HI SP_REG))) + (match_operand:HI 0 "register_operand" ""))] + "TARGET_H8300 + && operands[0] != stack_pointer_rtx" + "") + +(define_insn "pushhi1_h8300hs_advanced" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) (const_int -4))) + (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2))) + (match_operand:HI 0 "register_operand" "r"))] + "(TARGET_H8300H || TARGET_H8300S) + && operands[0] != stack_pointer_rtx" + "mov.l\\t%S0,@-er7" + [(set_attr "length" "4")]) + +(define_insn "pushhi1_h8300hs_normal" + [(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" "r"))] + "(TARGET_H8300H || TARGET_H8300S) + && operands[0] != stack_pointer_rtx" + "mov.l\\t%S0,@-er7" + [(set_attr "length" "4")]) + +(define_expand "pushhi1" + [(match_operand:HI 0 "register_operand" "")] + "" + " +{ + if (TARGET_H8300) + emit_insn (gen_pushhi1_h8300 (operands[0])); + else if (!TARGET_NORMAL_MODE) + emit_insn (gen_pushhi1_h8300hs_advanced (operands[0])); + else + emit_insn (gen_pushhi1_h8300hs_normal (operands[0])); + DONE; +}") + +;; ---------------------------------------------------------------------- +;; TEST INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "" + [(set (cc0) (zero_extract:HI (match_operand:QI 0 "bit_memory_operand" "r,U") + (const_int 1) + (match_operand 1 "const_int_operand" "n,n")))] + "TARGET_H8300" + "btst %Z1,%Y0" + [(set_attr "length" "2,4") + (set_attr "cc" "set_zn,set_zn")]) + +(define_insn "" + [(set (cc0) (zero_extract:HI (match_operand:HI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")))] + "TARGET_H8300" + "btst %Z1,%Y0" + [(set_attr "length" "2") + (set_attr "cc" "set_zn")]) + +(define_insn_and_split "*tst_extzv_1_n" + [(set (cc0) + (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"))) + (clobber (match_scratch:QI 2 "=X,X,&r"))] + "(TARGET_H8300H || TARGET_H8300S)" + "@ + btst\\t%Z1,%Y0 + btst\\t%Z1,%Y0 + #" + "&& reload_completed + && !OK_FOR_U (operands[0])" + [(set (match_dup 2) + (match_dup 0)) + (parallel [(set (cc0) (zero_extract:SI (match_dup 2) + (const_int 1) + (match_dup 1))) + (clobber (scratch:QI))])] + "" + [(set_attr "length" "2,8,10") + (set_attr "cc" "set_zn,set_zn,set_zn")]) + +(define_insn "" + [(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")))] + "(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) + (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n"))) + (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) + (zero_extract:SI (match_dup 2) + (const_int 1) + (match_dup 3)))] + "operands[3] = GEN_INT (INTVAL (operands[1]) - 16);") + +(define_insn "*tstsi_variable_bit" + [(set (cc0) + (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))))] + "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) + (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)))) + (clobber (match_scratch:QI 2 "=X,X,&r"))] + "(TARGET_H8300H || TARGET_H8300S)" + "@ + btst\\t%w1,%X0 + btst\\t%w1,%X0 + #" + "&& reload_completed + && !OK_FOR_U (operands[0])" + [(set (match_dup 2) + (match_dup 0)) + (parallel [(set (cc0) (zero_extract:SI (zero_extend:SI (match_dup 2)) + (const_int 1) + (and:SI (match_dup 1) + (const_int 7)))) + (clobber (scratch:QI))])] + "" + [(set_attr "length" "2,8,10") + (set_attr "cc" "set_zn,set_zn,set_zn")]) + +(define_insn "tstqi" + [(set (cc0) (match_operand:QI 0 "register_operand" "r"))] + "" + "mov.b %X0,%X0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "tsthi" + [(set (cc0) (match_operand:HI 0 "register_operand" "r"))] + "" + "mov.w %T0,%T0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "*tsthi_upper" + [(set (cc0) + (and:HI (match_operand:HI 0 "register_operand" "r") + (const_int -256)))] + "" + "mov.b %t0,%t0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "tstsi" + [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] + "TARGET_H8300H || TARGET_H8300S" + "mov.l %S0,%S0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "*tstsi_upper" + [(set (cc0) + (and:SI (match_operand:SI 0 "register_operand" "r") + (const_int -65536)))] + "" + "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_expand "cmphi" + [(set (cc0) + (compare (match_operand:HI 0 "h8300_dst_operand" "") + (match_operand:HI 1 "h8300_src_operand" "")))] + "" + " +{ + /* Force operand1 into a register if we're compiling + for the H8/300. */ + if (GET_CODE (operands[1]) != REG && TARGET_H8300) + operands[1] = force_reg (HImode, operands[1]); +}") + +(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 "" +(define_insn "*cmphi_h8300hs_znvc" [(set (cc0) - (compare:HI (match_operand:HI 0 "register_operand" "r,r") - (match_operand:HI 1 "nonmemory_operand" "r,n")))] + (compare (match_operand:HI 0 "h8300_dst_operand" "rU,rQ") + (match_operand:HI 1 "h8300_src_operand" "P3>X,rQi")))] "TARGET_H8300H || TARGET_H8300S" "cmp.w %T1,%T0" - [(set_attr "length" "2,4") + [(set_attr "length_table" "short_immediate,addw") (set_attr "cc" "compare,compare")]) (define_insn "cmpsi" [(set (cc0) - (compare:SI (match_operand:SI 0 "register_operand" "r,r") - (match_operand:SI 1 "nonmemory_operand" "r,i")))] + (compare (match_operand:SI 0 "h8300_dst_operand" "r,rQ") + (match_operand:SI 1 "h8300_src_operand" "P3>X,rQi")))] "TARGET_H8300H || TARGET_H8300S" "cmp.l %S1,%S0" - [(set_attr "length" "2,6") + [(set_attr "length" "2,*") + (set_attr "length_table" "*,addl") (set_attr "cc" "compare,compare")]) ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "addqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (plus:QI (match_operand:QI 1 "register_operand" "%0") - (match_operand:QI 2 "nonmemory_operand" "rn")))] +(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" "2") + [(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 "nonmemory_operand" "")))] + (match_operand:HI 2 "h8300_src_operand" "")))] "" "") -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,&r") - (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,g") - (match_operand:HI 2 "nonmemory_operand" "L,N,n,r,r")))] +(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 - mov.w %T1,%T0\;add.w %T2,%T0" - [(set_attr "length" "2,2,4,2,6") + 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 "" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") - (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0") - (match_operand:HI 2 "nonmemory_operand" "L,N,n,r")))] +(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" "@ - adds %2,%S0 - subs %G2,%S0 + 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,P3X")))] + "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"))))] @@ -848,7 +1438,28 @@ [(set_attr "length" "4") (set_attr "cc" "set_zn")]) -(define_insn "mulhisi3" +(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"))))] @@ -857,16 +1468,58 @@ [(set_attr "length" "4") (set_attr "cc" "set_zn")]) -(define_insn "umulqihi3" +(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 %X2,%T0" + "mulxu.b %X2,%T0" [(set_attr "length" "2") (set_attr "cc" "none_0hit")]) -(define_insn "umulhisi3" +(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"))))] @@ -875,6 +1528,53 @@ [(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 @@ -911,6 +1611,42 @@ ;; 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 @@ -922,7 +1658,7 @@ (umod:HI (match_dup 1) (zero_extend:HI (match_dup 2)))))] - "TARGET_H8300H || TARGET_H8300S" + "" "* { if (find_reg_note (insn, REG_UNUSED, operands[3])) @@ -930,8 +1666,7 @@ else return \"divxu.b\\t%X2,%T0\;mov.b\\t%t0,%s3\"; }" - [(set_attr "length" "4") - (set_attr "cc" "clobber")]) + [(set_attr "length" "4")]) (define_insn "divmodqi4" [(set (match_operand:QI 0 "register_operand" "=r") @@ -952,8 +1687,7 @@ else return \"divxs.b\\t%X2,%T0\;mov.b\\t%t0,%s3\"; }" - [(set_attr "length" "6") - (set_attr "cc" "clobber")]) + [(set_attr "length" "6")]) (define_insn "udivmodhi4" [(set (match_operand:HI 0 "register_operand" "=r") @@ -974,8 +1708,7 @@ else return \"divxu.w\\t%T2,%S0\;mov.w\\t%e0,%f3\"; }" - [(set_attr "length" "4") - (set_attr "cc" "clobber")]) + [(set_attr "length" "4")]) (define_insn "divmodhi4" [(set (match_operand:HI 0 "register_operand" "=r") @@ -996,293 +1729,260 @@ else return \"divxs.w\\t%T2,%S0\;mov.w\\t%e0,%f3\"; }" - [(set_attr "length" "6") - (set_attr "cc" "clobber")]) + [(set_attr "length" "6")]) ;; ---------------------------------------------------------------------- ;; AND INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "" +(define_insn "*andqi3_2" + [(set (match_operand:QI 0 "bit_operand" "=rQ,r") + (and:QI (match_operand:QI 1 "bit_operand" "%0,WU") + (match_operand:QI 2 "h8300_src_operand" "rQi,IP1>X")))] + "TARGET_H8300SX" + "@ + and %X2,%X0 + bfld %2,%1,%R0" + [(set_attr "length" "*,8") + (set_attr "length_table" "logicb,*") + (set_attr "cc" "set_znv,none_0hit")]) + +(define_insn "andqi3_1" [(set (match_operand:QI 0 "bit_operand" "=r,U") (and:QI (match_operand:QI 1 "bit_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "rn,O")))] - "register_operand (operands[0], QImode) || o_operand (operands[2], QImode)" + (match_operand:QI 2 "h8300_src_operand" "rn,n")))] + "register_operand (operands[0], QImode) + || single_zero_operand (operands[2], QImode)" "@ and %X2,%X0 bclr %W2,%R0" [(set_attr "length" "2,8") - (set_attr "adjust_length" "no") (set_attr "cc" "set_znv,none_0hit")]) (define_expand "andqi3" - [(set (match_operand:QI 0 "bit_operand" "") - (and:QI (match_operand:QI 1 "bit_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] + [(set (match_operand:QI 0 "register_operand" "") + (and:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "h8300_src_operand" "")))] "" - " -{ - if (fix_bit_operand (operands, 'O', AND)) - DONE; -}") + "") (define_expand "andhi3" [(set (match_operand:HI 0 "register_operand" "") (and:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] + (match_operand:HI 2 "h8300_src_operand" "")))] "" "") -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (and:HI (match_operand:HI 1 "register_operand" "%0") - (match_operand:HI 2 "nonmemory_operand" "rn")))] - "TARGET_H8300" - "* return output_logical_op (HImode, AND, operands);" - [(set_attr "length" "4") - (set_attr "cc" "clobber")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (and:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "nonmemory_operand" "r,n")))] - "TARGET_H8300H || TARGET_H8300S" - "* return output_logical_op (HImode, AND, operands);" - [(set_attr "length" "2,4") - (set_attr "cc" "set_znv,clobber")]) +(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 "const_int_operand" "n")) - (match_operand:HI 1 "register_operand" "0")))] - "exact_log2 (INTVAL (operands[3]) & 0xffff) != -1" + (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\;bst\\t%V3,%t0\"; + return \"bld\\t%V3,%t2\;bor\\t%V3,%t0\;bst\\t%V3,%t0\"; } - return \"bld\\t%V3,%s2\;bst\\t%V3,%s0\"; + return \"bld\\t%V3,%s2\;bor\\t%V3,%s0\;bst\\t%V3,%s0\"; }" - [(set_attr "length" "4") - (set_attr "cc" "clobber")]) + [(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 "nonmemory_operand" "")))] + (match_operand:SI 2 "h8300_src_operand" "")))] "" "") -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "nonmemory_operand" "rn")))] - "TARGET_H8300" - "* return output_logical_op (SImode, AND, operands);" - [(set_attr "length" "8") - (set_attr "cc" "clobber")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (and:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] - "TARGET_H8300H || TARGET_H8300S" - "* return output_logical_op (SImode, AND, operands);" - [(set_attr "length" "4,6") - (set_attr "cc" "set_znv,clobber")]) - ;; ---------------------------------------------------------------------- ;; OR INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "" - [(set (match_operand:QI 0 "bit_operand" "=r,U") +(define_insn "iorqi3_1" + [(set (match_operand:QI 0 "bit_operand" "=rQ,U") (ior:QI (match_operand:QI 1 "bit_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "rn,n")))] - "register_operand (operands[0], QImode) - || (GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2]) & 0xff) != -1)" - "* -{ - switch (which_alternative) - { - case 0: - return \"or\t%X2,%X0\"; - case 1: - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); - return \"bset\t%V2,%R0\"; - default: - abort (); - } -}" - [(set_attr "length" "2,8") - (set_attr "adjust_length" "no") + (match_operand:QI 2 "h8300_src_operand" "rQi,n")))] + "TARGET_H8300SX || register_operand (operands[0], QImode) + || single_one_operand (operands[2], QImode)" + "@ + or\\t%X2,%X0 + bset\\t%V2,%R0" + [(set_attr "length" "*,8") + (set_attr "length_table" "logicb,*") (set_attr "cc" "set_znv,none_0hit")]) (define_expand "iorqi3" - [(set (match_operand:QI 0 "bit_operand" "") - (ior:QI (match_operand:QI 1 "bit_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] + [(set (match_operand:QI 0 "register_operand" "") + (ior:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "h8300_src_operand" "")))] "" - " -{ - if (fix_bit_operand (operands, 'P', IOR)) - DONE; -}") + "") (define_expand "iorhi3" [(set (match_operand:HI 0 "register_operand" "") (ior:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] + (match_operand:HI 2 "h8300_src_operand" "")))] "" "") -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=r,r") - (ior:HI (match_operand:HI 1 "general_operand" "%0,0") - (match_operand:HI 2 "general_operand" "J,rn")))] - "TARGET_H8300" - "* return output_logical_op (HImode, IOR, operands);" - [(set_attr "length" "2,4") - (set_attr "cc" "clobber,clobber")]) - -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=r,r,r") - (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0") - (match_operand:HI 2 "general_operand" "J,r,n")))] - "TARGET_H8300H || TARGET_H8300S" - "* return output_logical_op (HImode, IOR, operands);" - [(set_attr "length" "2,2,4") - (set_attr "cc" "clobber,set_znv,clobber")]) - (define_expand "iorsi3" [(set (match_operand:SI 0 "register_operand" "") (ior:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] + (match_operand:SI 2 "h8300_src_operand" "")))] "" "") -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (ior:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "J,rn")))] - "TARGET_H8300" - "* return output_logical_op (SImode, IOR, operands);" - [(set_attr "length" "2,8") - (set_attr "cc" "clobber,clobber")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0") - (match_operand:SI 2 "nonmemory_operand" "J,r,n")))] - "TARGET_H8300H || TARGET_H8300S" - "* return output_logical_op (SImode, IOR, operands);" - [(set_attr "length" "2,4,6") - (set_attr "cc" "clobber,set_znv,clobber")]) - ;; ---------------------------------------------------------------------- ;; XOR INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "" +(define_insn "xorqi3_1" [(set (match_operand:QI 0 "bit_operand" "=r,U") (xor:QI (match_operand:QI 1 "bit_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "rn,n")))] - "register_operand (operands[0], QImode) - || (GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2]) & 0xff) != -1)" - "* -{ - switch (which_alternative) - { - case 0: - return \"xor\t%X2,%X0\"; - case 1: - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); - return \"bnot\t%V2,%R0\"; - default: - abort (); - } -}" - [(set_attr "length" "2,8") - (set_attr "adjust_length" "no") + (match_operand:QI 2 "h8300_src_operand" "rQi,n")))] + "TARGET_H8300SX || register_operand (operands[0], QImode) + || single_one_operand (operands[2], QImode)" + "@ + xor\\t%X2,%X0 + bnot\\t%V2,%R0" + [(set_attr "length" "*,8") + (set_attr "length_table" "logicb,*") (set_attr "cc" "set_znv,none_0hit")]) (define_expand "xorqi3" - [(set (match_operand:QI 0 "bit_operand" "") - (xor:QI (match_operand:QI 1 "bit_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] + [(set (match_operand:QI 0 "register_operand" "") + (xor:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "h8300_src_operand" "")))] "" - " -{ - if (fix_bit_operand (operands, 'O', XOR)) - DONE; -}") + "") (define_expand "xorhi3" [(set (match_operand:HI 0 "register_operand" "") (xor:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] + (match_operand:HI 2 "h8300_src_operand" "")))] "" "") -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (xor:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "nonmemory_operand" "J,rn")))] - "TARGET_H8300" - "* return output_logical_op (HImode, XOR, operands);" - [(set_attr "length" "2,4") - (set_attr "cc" "clobber,clobber")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r,r") - (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0") - (match_operand:HI 2 "nonmemory_operand" "J,r,n")))] - "TARGET_H8300H || TARGET_H8300S" - "* return output_logical_op (HImode, XOR, operands);" - [(set_attr "length" "2,2,4") - (set_attr "cc" "clobber,set_znv,clobber")]) - (define_expand "xorsi3" [(set (match_operand:SI 0 "register_operand" "") (xor:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] + (match_operand:SI 2 "h8300_src_operand" "")))] "" "") -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (xor:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "J,rn")))] - "TARGET_H8300" - "* return output_logical_op (SImode, XOR, operands);" - [(set_attr "length" "2,8") - (set_attr "cc" "clobber,clobber")]) +;; ---------------------------------------------------------------------- +;; {AND,IOR,XOR}{HI3,SI3} PATTERNS +;; ---------------------------------------------------------------------- -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0") - (match_operand:SI 2 "nonmemory_operand" "J,r,n")))] - "TARGET_H8300H || TARGET_H8300S" - "* return output_logical_op (SImode, XOR, operands);" - [(set_attr "length" "2,4,6") - (set_attr "cc" "clobber,set_znv,clobber")]) +;; 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_insn "negqi2" - [(set (match_operand:QI 0 "register_operand" "=r") - (neg:QI (match_operand:QI 1 "register_operand" "0")))] +(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" "2") + [(set_attr "length_table" "unary") (set_attr "cc" "set_zn")]) (define_expand "neghi2" @@ -1307,12 +2007,12 @@ "" "operands[2] = gen_reg_rtx (HImode);") -(define_insn "neghi2_h8300h" - [(set (match_operand:HI 0 "register_operand" "=r") - (neg:HI (match_operand:HI 1 "register_operand" "0")))] - "TARGET_H8300H || TARGET_H8300S" - "neg %T0" - [(set_attr "length" "2") +(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" @@ -1337,69 +2037,117 @@ "" "operands[2] = gen_reg_rtx (SImode);") -(define_insn "negsi2_h8300h" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operand:SI 1 "register_operand" "0")))] - "TARGET_H8300H || TARGET_H8300S" - "neg %S0" - [(set_attr "length" "2") +(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_insn "one_cmplqi2" - [(set (match_operand:QI 0 "register_operand" "=r") - (not:QI (match_operand:QI 1 "register_operand" "0")))] +(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" "2") + [(set_attr "length_table" "unary") (set_attr "cc" "set_znv")]) (define_expand "one_cmplhi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (not:HI (match_operand:HI 1 "register_operand" "0")))] + [(set (match_operand:HI 0 "register_operand" "") + (not:HI (match_operand:HI 1 "register_operand" "")))] "" "") -(define_insn "" +(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 "cc" "clobber") - (set_attr "length" "4")]) + [(set_attr "length" "4")]) -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (not:HI (match_operand:HI 1 "register_operand" "0")))] - "TARGET_H8300H || TARGET_H8300S" - "not %T0" +(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" "2")]) + (set_attr "length_table" "unary")]) (define_expand "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operand:SI 1 "register_operand" "0")))] + [(set (match_operand:SI 0 "register_operand" "") + (not:SI (match_operand:SI 1 "register_operand" "")))] "" "") -(define_insn "" +(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 "cc" "clobber") - (set_attr "length" "8")]) + [(set_attr "length" "8")]) -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operand:SI 1 "register_operand" "0")))] - "TARGET_H8300H || TARGET_H8300S" - "not %S0" +(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" "2")]) + (set_attr "length_table" "unary")]) ;; ---------------------------------------------------------------------- ;; JUMP INSTRUCTIONS @@ -1408,94 +2156,54 @@ ;; Conditional jump instructions (define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (LE, operands[0]); DONE;") (define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (LEU, operands[0]); DONE;") (define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (GE, operands[0]); DONE;") (define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (GEU, operands[0]); DONE;") (define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (LT, operands[0]); DONE;") (define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (LTU, operands[0]); DONE;") (define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (GT, operands[0]); DONE;") (define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (GTU, operands[0]); DONE;") (define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (EQ, operands[0]); DONE;") (define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] + [(match_operand 0 "" "")] "" - "") + "h8300_expand_branch (NE, operands[0]); DONE;") (define_insn "branch_true" [(set (pc) @@ -1508,9 +2216,9 @@ { 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)) + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) { cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; return 0; @@ -1537,9 +2245,9 @@ { 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)) + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) { cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; return 0; @@ -1555,6 +2263,64 @@ [(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" @@ -1563,7 +2329,31 @@ "" "* { - if (get_attr_length (insn) == 2) + 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. */ + rtvec vec; + int seen; + + vec = XVEC (final_sequence, 0); + final_sequence = 0; + final_scan_insn (RTVEC_ELT (vec, 1), asm_out_file, optimize, 1, & seen); + final_scan_insn (RTVEC_ELT (vec, 0), asm_out_file, optimize, 1, & seen); + INSN_DELETED_P (RTVEC_ELT (vec, 1)) = 1; + return \"\"; + } + } + else if (get_attr_length (insn) == 2) return \"bra %l0\"; else if (get_attr_length (insn) == 4) return \"bra %l0:16\"; @@ -1571,6 +2361,10 @@ return \"jmp @%l0\"; }" [(set_attr "type" "branch") + (set (attr "delay_slot") + (if_then_else (ne (symbol_ref "TARGET_H8300SX") (const_int 0)) + (const_string "jump") + (const_string "none"))) (set_attr "cc" "none")]) ;; This is a define expand, because pointers may be either 16 or 32 bits. @@ -1581,7 +2375,7 @@ "" "") -(define_insn "tablejump_h8300" +(define_insn "*tablejump_h8300" [(set (pc) (match_operand:HI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "TARGET_H8300" @@ -1589,14 +2383,22 @@ [(set_attr "cc" "none") (set_attr "length" "2")]) -(define_insn "tablejump_h8300h" +(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_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" @@ -1604,23 +2406,30 @@ "" "") -(define_insn "indirect_jump_h8300" +(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_h8300h" +(define_insn "*indirect_jump_h8300hs_advanced" [(set (pc) (match_operand:SI 0 "jump_address_operand" "Vr"))] - "TARGET_H8300H || TARGET_H8300S" + "(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 H8/S. +;; ??? 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") @@ -1634,16 +2443,16 @@ else return \"jsr\\t%0\"; }" - [(set_attr "cc" "clobber") + [(set_attr "type" "call") (set (attr "length") (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") - (const_int 4) - (const_int 8)))]) + (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 H8/S. +;; ??? Even though we use HImode here, this works on the H8/300H and H8S. (define_insn "call_value" [(set (match_operand 0 "" "=r") @@ -1658,11 +2467,11 @@ else return \"jsr\\t%1\"; }" - [(set_attr "cc" "clobber") + [(set_attr "type" "call") (set (attr "length") (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") - (const_int 4) - (const_int 8)))]) + (const_int 2) + (const_int 4)))]) (define_insn "nop" [(const_int 0)] @@ -1672,6 +2481,134 @@ (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 ()) + 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 ()) + 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) + 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) + 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 ;; ---------------------------------------------------------------------- @@ -1681,37 +2618,98 @@ "" "") -(define_insn "" +(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 - mov.b %R1,%s0\;mov.b #0,%t0" - [(set_attr "length" "2,10") - (set_attr "cc" "clobber,clobber")]) + #" + [(set_attr "length" "2,10")]) -(define_insn "" +(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 - mov.b %R1,%s0\;extu.w %T0" + #" [(set_attr "length" "2,10") (set_attr "cc" "set_znv,set_znv")]) -;; The compiler can synthesize a 300H variant of this which is -;; just as efficient as one that we'd create -(define_insn "zero_extendqisi2" +;; 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,6") - (set_attr "cc" "clobber,clobber")]) + [(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" "") @@ -1720,7 +2718,7 @@ "") ;; %e prints the high part of a CONST_INT, not the low part. Arggh. -(define_insn "" +(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" @@ -1728,10 +2726,9 @@ 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,4") - (set_attr "cc" "clobber,clobber,clobber")]) + [(set_attr "length" "2,4,6")]) -(define_insn "" +(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" @@ -1745,17 +2742,16 @@ "" "") -(define_insn "" +(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") - (set_attr "cc" "clobber,clobber")]) + [(set_attr "length" "4,8")]) -(define_insn "" +(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" @@ -1763,17 +2759,44 @@ [(set_attr "length" "2") (set_attr "cc" "set_znv")]) -;; The compiler can synthesize a 300H variant of this which is -;; just as efficient as one that we'd create -(define_insn "extendqisi2" +(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,10") - (set_attr "cc" "clobber,clobber")]) + [(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" "") @@ -1781,17 +2804,16 @@ "" "") -(define_insn "" +(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,8") - (set_attr "cc" "clobber,clobber")]) + [(set_attr "length" "6,10")]) -(define_insn "" +(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" @@ -1804,7 +2826,7 @@ ;; ---------------------------------------------------------------------- ;; ;; 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 +;; 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 @@ -1812,7 +2834,7 @@ ;; 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 +;; 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 @@ -1825,100 +2847,233 @@ (ashift:QI (match_operand:QI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" "")))] "" - "if (expand_a_shift (QImode, ASHIFT, operands)) DONE; else FAIL;") + "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; else FAIL;") + "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; else FAIL;") + "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" "KM,rn")])) + (match_operand:QI 2 "nonmemory_operand" "R,rn")])) (clobber (match_scratch:QI 4 "=X,&r"))] "" "* return output_a_shift (operands);" - [(set_attr "length" "20") - (set_attr "cc" "clobber")]) + [(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 "nonmemory_operand" "") + (ashift:HI (match_operand:HI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" "")))] "" - "if (expand_a_shift (HImode, ASHIFT, operands)) DONE; else FAIL;") + "if (expand_a_shift (HImode, ASHIFT, operands)) DONE;") (define_expand "lshrhi3" [(set (match_operand:HI 0 "register_operand" "") - (lshiftrt:HI (match_operand:HI 1 "general_operand" "") + (lshiftrt:HI (match_operand:HI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" "")))] "" - "if (expand_a_shift (HImode, LSHIFTRT, operands)) DONE; else FAIL;") + "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; else FAIL;") + "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" "KM,rn")])) + (match_operand:QI 2 "nonmemory_operand" "S,rn")])) (clobber (match_scratch:QI 4 "=X,&r"))] "" "* return output_a_shift (operands);" - [(set_attr "length" "20") - (set_attr "cc" "clobber")]) + [(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 "general_operand" "") + (ashift:SI (match_operand:SI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" "")))] "" - "if (expand_a_shift (SImode, ASHIFT, operands)) DONE; else FAIL;") + "if (expand_a_shift (SImode, ASHIFT, operands)) DONE;") (define_expand "lshrsi3" [(set (match_operand:SI 0 "register_operand" "") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" "")))] "" - "if (expand_a_shift (SImode, LSHIFTRT, operands)) DONE; else FAIL;") + "if (expand_a_shift (SImode, LSHIFTRT, operands)) DONE;") (define_expand "ashrsi3" [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "") + (ashiftrt:SI (match_operand:SI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" "")))] "" - "if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE; else FAIL;") + "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" "K,rn")])) + (match_operand:QI 2 "nonmemory_operand" "T,rn")])) (clobber (match_scratch:QI 4 "=X,&r"))] "" "* return output_a_shift (operands);" - [(set_attr "length" "20") - (set_attr "cc" "clobber")]) + [(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) + (match_dup 1)) + (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) + (match_dup 1)) + (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) + (match_dup 3)) + (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) + (match_dup 3)) + (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 @@ -1929,48 +3084,48 @@ (rotate:QI (match_operand:QI 1 "register_operand" "") (match_operand:QI 2 "nonmemory_operand" "")))] "" - "if (expand_a_rotate (ROTATE, operands)) DONE; else FAIL;") + "if (expand_a_rotate (operands)) DONE;") -(define_insn "*rotlqi3_1" +(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 emit_a_rotate (ROTATE, operands);" - [(set_attr "length" "20") - (set_attr "cc" "clobber")]) + "* 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 (ROTATE, operands)) DONE; else FAIL;") + "if (expand_a_rotate (operands)) DONE;") -(define_insn "*rotlhi3_1" +(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 emit_a_rotate (ROTATE, operands);" - [(set_attr "length" "20") - (set_attr "cc" "clobber")]) + "* 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 (ROTATE, operands)) DONE; else FAIL;") + "if (expand_a_rotate (operands)) DONE;") -(define_insn "*rotlsi3_1" +(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 emit_a_rotate (ROTATE, operands);" - [(set_attr "length" "20") - (set_attr "cc" "clobber")]) + "* return output_a_rotate (ROTATE, operands);" + [(set (attr "length") + (symbol_ref "compute_a_rotate_length (operands)"))]) ;; ----------------------------------------------------------------- ;; BIT FIELDS @@ -1996,8 +3151,7 @@ (match_operand:HI 2 "immediate_operand" "n")))] "TARGET_H8300" "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0" - [(set_attr "cc" "clobber") - (set_attr "length" "6")]) + [(set_attr "length" "6")]) ;; ;; Inverted loads with a 16bit destination. @@ -2012,14 +3166,13 @@ "TARGET_H8300 && (1 << INTVAL (operands[2])) == INTVAL (operands[3])" "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0" - [(set_attr "cc" "clobber") - (set_attr "length" "8")]) + [(set_attr "length" "8")]) ;; ;; Normal loads with a 32bit destination. ;; -(define_insn "" +(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) @@ -2027,25 +3180,24 @@ "TARGET_H8300 && INTVAL (operands[2]) < 16" "* return output_simode_bld (0, operands);" - [(set_attr "cc" "clobber") - (set_attr "length" "6")]) + [(set_attr "length" "8")]) -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") +(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")))] + (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" "clobber") - (set_attr "length" "6")]) + [(set_attr "cc" "set_znv,set_znv") + (set_attr "length" "8,6")]) ;; ;; Inverted loads with a 32bit destination. ;; -(define_insn "" +(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")) @@ -2055,31 +3207,75 @@ && INTVAL (operands[2]) < 16 && (1 << INTVAL (operands[2])) == INTVAL (operands[3])" "* return output_simode_bld (1, operands);" - [(set_attr "cc" "clobber") - (set_attr "length" "6")]) + [(set_attr "length" "8")]) -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (xor:SI (match_operand:SI 1 "register_operand" "r") - (match_operand 3 "const_int_operand" "n")) +(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")))] + (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" "clobber") - (set_attr "length" "6")]) + [(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_H8300 || TARGET_H8300SX" " { - /* We only have single bit bitfield instructions. */ + 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; @@ -2087,6 +3283,9 @@ 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 "" @@ -2096,18 +3295,60 @@ (match_operand:HI 2 "register_operand" "r"))] "" "bld #0,%R2\;bst %Z1,%Y0 ; i1" - [(set_attr "cc" "clobber") - (set_attr "length" "4")]) + [(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_H8300 || TARGET_H8300SX" " { - /* We only have single bit bitfield instructions. */ + 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; @@ -2126,10 +3367,8 @@ (match_operand:HI 2 "immediate_operand" "n")) (match_operand:HI 3 "bit_operand" "0")]))] "" - "bld %Z2,%Y1\;%b4 #0,%R0\;bst #0,%R0; bl1" - [(set_attr "cc" "clobber") - (set_attr "length" "6") - (set_attr "adjust_length" "no")]) + "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") @@ -2141,104 +3380,2741 @@ (const_int 1) (match_operand:HI 4 "immediate_operand" "n"))]))] "" - "bld %Z2,%Y1\;%b5 %Z4,%Y3\;bst #0,%R0; bl3" - [(set_attr "cc" "clobber") - (set_attr "length" "6") - (set_attr "adjust_length" "no")]) + "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 "seq" + [(set (match_operand:HI 0 "register_operand" "") + (eq:HI (cc0) (const_int 0)))] + "TARGET_H8300SX" + "") + +(define_expand "sne" + [(set (match_operand:HI 0 "register_operand" "") + (ne:HI (cc0) (const_int 0)))] + "TARGET_H8300SX" + "") + +(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)]))] + " +{ + if (operands[4] == const0_rtx && GET_CODE (operands[3]) == REG) + operands[5] = operands[3]; + else + 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)))] + " +{ + if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) + operands[6] = operands[2]; + else + 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)))] + " +{ + if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) + operands[6] = operands[2]; + else + 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)))] + " +{ + if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) + operands[6] = operands[2]; + else + 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)))] + " +{ + if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) + operands[6] = operands[2]; + else + 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 ;; ----------------------------------------------------------------- -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) - (match_operand:HI 2 "register_operand" "0")))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[0]) != REGNO (operands[1])" - "or\\t%X1,%s0" - [(set_attr "cc" "clobber") - (set_attr "length" "2")]) +;; insv:SI -(define_insn "" +(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") - (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "0")))] + (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) - && REG_P (operands[0]) - && REG_P (operands[1]) - && (REGNO (operands[0]) != REGNO (operands[1]))" - "or.w\\t%T1,%f0" - [(set_attr "cc" "clobber") - (set_attr "length" "2")]) + && 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 "" +(define_insn_and_split "*andsi3_lshiftrt_9_sb" [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "0")))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[0]) != REGNO (operands[1])" - "or\\t%X1,%s0" - [(set_attr "cc" "clobber") - (set_attr "length" "2")]) + (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))])] + "") -(define_insn "" +;; 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) + (zero_extract:SI (match_dup 1) + (const_int 1) + (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) + (zero_extract:SI (match_dup 1) + (const_int 1) + (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") - (xor:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) - (match_operand:HI 2 "register_operand" "0")))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[0]) != REGNO (operands[1])" - "xor\\t%X1,%s0" - [(set_attr "cc" "clobber") - (set_attr "length" "2")]) + (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")]) -(define_insn "" +;; [ix]or:SI + +(define_insn "*ixorsi3_zext_qi" [(set (match_operand:SI 0 "register_operand" "=r") - (xor:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "0")))] - "(TARGET_H8300H || TARGET_H8300S) - && REG_P (operands[0]) - && REG_P (operands[1]) - && (REGNO (operands[0]) != REGNO (operands[1]))" - "xor.w\\t%T1,%f0" - [(set_attr "cc" "clobber") - (set_attr "length" "2")]) + (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 "" +(define_insn "*ixorsi3_zext_hi" [(set (match_operand:SI 0 "register_operand" "=r") - (xor:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "0")))] - "REG_P (operands[0]) - && REG_P (operands[1]) - && REGNO (operands[0]) != REGNO (operands[1])" - "xor\\t%X1,%s0" - [(set_attr "cc" "clobber") - (set_attr "length" "2")]) + (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 "" +(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")) + (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0")) (ashift:HI (match_operand:HI 2 "register_operand" "r") (const_int 8))))] - "REG_P (operands[0]) - && REG_P (operands[2]) - && REGNO (operands[0]) != REGNO (operands[2])" + "" "mov.b\\t%s2,%t0" - [(set_attr "cc" "clobber") - (set_attr "length" "2")]) + [(set_attr "length" "2")]) -(define_insn "" +(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")) + (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) - && REG_P (operands[0]) - && REG_P (operands[2]) - && (REGNO (operands[0]) != REGNO (operands[2]))" + "TARGET_H8300H || TARGET_H8300S" "mov.w\\t%f2,%e0" - [(set_attr "cc" "clobber") - (set_attr "length" "2")]) + [(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) + (match_dup 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) + (match_dup 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]) + && (CONST_OK_FOR_J (INTVAL (operands[1])) + || CONST_OK_FOR_L (INTVAL (operands[1])) + || CONST_OK_FOR_N (INTVAL (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]) + && (CONST_OK_FOR_L (INTVAL (operands[1])) + || CONST_OK_FOR_N (INTVAL (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]) + && !CONST_OK_FOR_L (INTVAL (operands[2])) + && !CONST_OK_FOR_N (INTVAL (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) + (match_dup 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) + (match_dup 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) + (match_dup 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) + (match_dup 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) + (zero_extract:SI (match_operand:QI 0 "register_operand" "") + (const_int 1) + (const_int 7))) + (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) + (match_dup 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]);") + +;; (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) + && peep2_reg_dead_p (1, operands[0])" + [(set (match_dup 0) + (unspec:HI [(match_dup 0) + (match_dup 4)] + UNSPEC_INCDEC)) + (set (cc0) + (match_dup 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) + (match_dup 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) + (match_dup 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) + (and:HI (match_dup 0) + (const_int -256))) + (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) + (and:HI (match_dup 0) + (const_int -256))) + (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) + && peep2_reg_dead_p (1, operands[0])" + [(set (match_dup 0) + (unspec:SI [(match_dup 0) + (match_dup 4)] + UNSPEC_INCDEC)) + (set (cc0) + (match_dup 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) + (match_dup 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]) != 1 + && INTVAL (operands[1]) != 2" + [(set (match_dup 0) + (xor:SI (match_dup 0) + (match_dup 1))) + (set (cc0) + (match_dup 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) + (match_dup 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) + (match_dup 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) + (match_dup 4)) + (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) + (match_dup 4)) + (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) + (match_dup 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) + (match_dup 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) + (match_dup 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) + (match_dup 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) + (and:SI (match_dup 0) + (const_int -65536))) + (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) + (and:SI (match_dup 0) + (const_int -65536))) + (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) + && !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) + (match_dup 4)) + (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) + (match_dup 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) + (match_dup 4)) + (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) + (match_dup 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) + (match_dup 4)) + (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) + (match_dup 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) + (match_dup 4)) + (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) + (match_dup 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) + (match_dup 5)) + (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])" + [(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))])