X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Fconfig%2Fstormy16%2Fstormy16.md;fp=gcc%2Fconfig%2Fstormy16%2Fstormy16.md;h=285a82f5dcae36a7a941fedc759b20d197ab5c67;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=9283aafc6614d3ba02723fa368279c61583d0cf1;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/config/stormy16/stormy16.md b/gcc/config/stormy16/stormy16.md index 9283aafc..285a82f5 100644 --- a/gcc/config/stormy16/stormy16.md +++ b/gcc/config/stormy16/stormy16.md @@ -1,26 +1,54 @@ ;; XSTORMY16 Machine description template -;; Copyright (C) 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2007, 2008 +;; Free Software Foundation, Inc. ;; Contributed by Red Hat, Inc. -;; 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 +;; . ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. +;; Constraints +;; a $0 +;; b $1 +;; c $2 +;; d $8 +;; e $0..$7 +;; t $0..$1 +;; z $8..$9 +;; I 0..3 +;; J 2**N mask +;; K 2**N antimask +;; L 0..255 +;; M -255..0 +;; N -3..0 +;; O 1..4 +;; P -4..-1 +;; Q post-inc mem (push) +;; R pre-dec mem (pop) +;; S immediate mem +;; T Rx +;; U -inf..1 or 16..inf +;; Z 0 + +(define_constants + [ + (CARRY_REG 16) + ] +) ;; :::::::::::::::::::: ;; :: @@ -29,11 +57,11 @@ ;; :::::::::::::::::::: ; Categorize branches for the conditional in the length attribute. -(define_attr "branch_class" "notdirectbranch,br12,bcc12,bcc8p2,bcc8p4" +(define_attr "branch_class" "notdirectbranch,br12,bcc12,bcc8p2,bcc8p4" (const_string "notdirectbranch")) ; The length of an instruction, used for branch shortening. -(define_attr "length" "" +(define_attr "length" "" (cond [(eq_attr "branch_class" "br12") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2046)) @@ -66,6 +94,7 @@ (define_asm_attributes [(set_attr "length" "4") (set_attr "psw_operand" "clobber")]) +(include "predicates.md") ;; :::::::::::::::::::: ;; :: @@ -84,7 +113,7 @@ ;; offset. By using separate patterns for push and pop we ensure that ;; insns like this one are never generated. -(define_insn "pushqi" +(define_insn "pushqi1" [(set (mem:QI (post_inc (reg:HI 15))) (match_operand:QI 0 "register_operand" "r"))] "" @@ -92,7 +121,7 @@ [(set_attr "psw_operand" "nop") (set_attr "length" "2")]) -(define_insn "popqi" +(define_insn "popqi1" [(set (match_operand:QI 0 "register_operand" "=r") (mem:QI (pre_dec (reg:HI 15))))] "" @@ -104,11 +133,13 @@ [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "") (match_operand:QI 1 "general_operand" ""))] "" - "{ xstormy16_expand_move (QImode, operands[0], operands[1]); DONE; }") + { xstormy16_expand_move (QImode, operands[0], operands[1]); + DONE; + }) -(define_insn "*movqi_internal" - [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S") - (match_operand:QI 1 "general_operand" "r,e,m,i,i,i,i"))] +(define_insn "movqi_internal" + [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S,W,e") + (match_operand:QI 1 "general_operand" "r,e,m,i,i,i,i,ie,W"))] "" "@ mov %0,%1 @@ -117,8 +148,10 @@ mov %0,%1 mov Rx,%1 mov %0,%1 + mov.b %0,%1 + mov.b %0,%1 mov.b %0,%1" - [(set_attr_alternative "length" + [(set_attr_alternative "length" [(const_int 2) (if_then_else (match_operand:QI 0 "short_memory_operand" "") (const_int 2) @@ -129,10 +162,12 @@ (const_int 2) (const_int 2) (const_int 4) - (const_int 4)]) - (set_attr "psw_operand" "0,0,0,0,nop,0,nop")]) + (const_int 4) + (const_int 2) + (const_int 2)]) + (set_attr "psw_operand" "0,0,0,0,nop,0,nop,0,0")]) -(define_insn "pushhi" +(define_insn "pushhi1" [(set (mem:HI (post_inc (reg:HI 15))) (match_operand:HI 0 "register_operand" "r"))] "" @@ -140,7 +175,7 @@ [(set_attr "psw_operand" "nop") (set_attr "length" "2")]) -(define_insn "pophi" +(define_insn "pophi1" [(set (match_operand:HI 0 "register_operand" "=r") (mem:HI (pre_dec (reg:HI 15))))] "" @@ -150,13 +185,15 @@ (define_expand "movhi" [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "") - (match_operand:HI 1 "general_operand" ""))] + (match_operand:HI 1 "xs_hi_general_operand" ""))] "" - "{ xstormy16_expand_move (HImode, operands[0], operands[1]); DONE; }") + { xstormy16_expand_move (HImode, operands[0], operands[1]); + DONE; + }) -(define_insn "*movhi_internal" - [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S") - (match_operand:HI 1 "general_operand" "r,e,m,L,L,i,i"))] +(define_insn "movhi_internal" + [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S,W,e") + (match_operand:HI 1 "xs_hi_general_operand" "r,e,m,L,L,i,i,ie,W"))] "" "@ mov %0,%1 @@ -165,8 +202,10 @@ mov.w %0,%1 mov.w Rx,%1 mov.w %0,%1 + mov.w %0,%1 + mov.w %0,%1 mov.w %0,%1" - [(set_attr_alternative "length" + [(set_attr_alternative "length" [(const_int 2) (if_then_else (match_operand:QI 0 "short_memory_operand" "") (const_int 2) @@ -177,14 +216,18 @@ (const_int 2) (const_int 2) (const_int 4) + (const_int 4) + (const_int 4) (const_int 4)]) - (set_attr "psw_operand" "0,0,0,0,nop,0,nop")]) + (set_attr "psw_operand" "0,0,0,0,nop,0,nop,0,0")]) (define_expand "movsi" [(set (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "general_operand" ""))] "" - "{ xstormy16_expand_move (SImode, operands[0], operands[1]); DONE; }") + { xstormy16_expand_move (SImode, operands[0], operands[1]); + DONE; + }) (define_insn_and_split "*movsi_internal" [(set (match_operand:SI 0 "nonimmediate_operand" "=r,Q,r,m,e,&e,e,r,S") @@ -193,8 +236,10 @@ "#" "reload_completed" [(pc)] - "{ xstormy16_split_move (SImode, operands[0], operands[1]); DONE; }" - [(set_attr_alternative "length" + { xstormy16_split_move (SImode, operands[0], operands[1]); + DONE; + } + [(set_attr_alternative "length" [(const_int 4) (const_int 4) (const_int 4) @@ -210,7 +255,6 @@ (const_int 4) (const_int 8) (const_int 8)])]) - ;; :::::::::::::::::::: ;; :: @@ -232,10 +276,9 @@ mov.b %0, %1 shl %0,#8\n\tshr %0,#8" [(set_attr "psw_operand" "nop,0") - (set_attr_alternative "length" - [(const_int 2) - (const_int 4)])]) - + (set_attr_alternative "length" + [(const_int 4) + (const_int 8)])]) ;; :::::::::::::::::::: ;; :: @@ -266,53 +309,38 @@ ;; :::::::::::::::::::: ;; :: -;; :: 16 bit Integer arithmetic +;; :: 16-bit Integer arithmetic ;; :: ;; :::::::::::::::::::: ;; Addition -; Operand 3 is marked earlyclobber because that helps reload -; to generate better code---this pattern will never need the -; carry register as an input, and some output reloads or input -; reloads might need to use it. In fact, without the '&' reload -; will fail in some cases. +; Note - the early clobber modifier is no longer needed on operand 3 +; and in fact can cause some reload spill failures if it is present. +; Note that the 'Z' constraint matches "add $reg,0", which reload +; will occasionally emit. We avoid the "add $reg,imm" match because +; it clobbers the carry. (define_insn "addhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r") - (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0,0") - (match_operand:HI 2 "nonmemory_operand" "O,P,L,M,Ir,N,i"))) - (clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))] + [(set (match_operand:HI 0 "register_operand" "=r,r,r,T,T,r,r,r") + (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0,0,0") + (match_operand:HI 2 "xs_hi_nonmemory_operand" "O,P,Z,L,M,Ir,N,i"))) + (clobber (reg:BI CARRY_REG))] "" "@ inc %0,%o2 dec %0,%O2 + ; add Rx,%2 sub Rx,#%n2 add %0,%2 sub %0,#%n2 add %0,%2" - [(set_attr "length" "2,2,2,2,2,2,4")]) - -; Reload can generate addition operations. The SECONDARY_RELOAD_CLASS -; macro causes it to allocate the carry register; this pattern -; shows it how to place the register in RTL to make the addition work. -(define_expand "reload_inhi" - [(parallel [(set (match_operand:HI 0 "register_operand" "=r") - (match_operand:HI 1 "xstormy16_carry_plus_operand" "")) - (clobber (match_operand:BI 2 "" "=&y"))])] - "" - "if (! rtx_equal_p (operands[0], XEXP (operands[1], 0))) - { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], XEXP (operands[1], 0))); - operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), operands[0], - XEXP (operands[1], 1)); - } - ") + [(set_attr "length" "2,2,0,2,2,2,2,4")]) (define_insn "addchi4" [(set (match_operand:HI 0 "register_operand" "=T,r,r") (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0") - (match_operand:HI 2 "nonmemory_operand" "L,Ir,i"))) - (set (match_operand:BI 3 "register_operand" "=y,y,y") + (match_operand:HI 2 "xs_hi_nonmemory_operand" "L,Ir,i"))) + (set (reg:BI CARRY_REG) (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1)) (zero_extend:SI (match_dup 2))) (const_int 16))))] @@ -326,14 +354,12 @@ (define_insn "addchi5" [(set (match_operand:HI 0 "register_operand" "=T,r,r") (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0") - (zero_extend:HI (match_operand:BI 3 - "register_operand" - "y,y,y"))) - (match_operand:HI 2 "nonmemory_operand" "L,Ir,i"))) - (set (match_operand:BI 4 "register_operand" "=y,y,y") - (truncate:BI (lshiftrt:SI (plus:SI (plus:SI + (zero_extend:HI (reg:BI CARRY_REG))) + (match_operand:HI 2 "xs_hi_nonmemory_operand" "L,Ir,i"))) + (set (reg:BI CARRY_REG) + (truncate:BI (lshiftrt:SI (plus:SI (plus:SI (zero_extend:SI (match_dup 1)) - (zero_extend:SI (match_dup 3))) + (zero_extend:SI (reg:BI CARRY_REG))) (zero_extend:SI (match_dup 2))) (const_int 16))))] "" @@ -352,8 +378,8 @@ (define_insn "subhi3" [(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r") (minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0,0,0,0") - (match_operand:HI 2 "nonmemory_operand" "O,P,L,M,rI,M,i"))) - (clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))] + (match_operand:HI 2 "xs_hi_nonmemory_operand" "O,P,L,M,rI,M,i"))) + (clobber (reg:BI CARRY_REG))] "" "@ dec %0,%o2 @@ -368,8 +394,8 @@ (define_insn "subchi4" [(set (match_operand:HI 0 "register_operand" "=T,r,r") (minus:HI (match_operand:HI 1 "register_operand" "0,0,0") - (match_operand:HI 2 "nonmemory_operand" "L,Ir,i"))) - (set (match_operand:BI 3 "register_operand" "=y,y,y") + (match_operand:HI 2 "xs_hi_nonmemory_operand" "L,Ir,i"))) + (set (reg:BI CARRY_REG) (truncate:BI (lshiftrt:SI (minus:SI (zero_extend:SI (match_dup 1)) (zero_extend:SI (match_dup 2))) (const_int 16))))] @@ -383,14 +409,12 @@ (define_insn "subchi5" [(set (match_operand:HI 0 "register_operand" "=T,r,r") (minus:HI (minus:HI (match_operand:HI 1 "register_operand" "0,0,0") - (zero_extend:HI (match_operand:BI 3 - "register_operand" - "y,y,y"))) - (match_operand:HI 2 "nonmemory_operand" "L,Ir,i"))) - (set (match_operand:BI 4 "register_operand" "=y,y,y") - (truncate:BI (lshiftrt:SI (minus:SI (minus:SI + (zero_extend:HI (reg:BI CARRY_REG))) + (match_operand:HI 2 "xs_hi_nonmemory_operand" "L,Ir,i"))) + (set (reg:BI CARRY_REG) + (truncate:BI (lshiftrt:SI (minus:SI (minus:SI (zero_extend:SI (match_dup 1)) - (zero_extend:SI (match_dup 3))) + (zero_extend:SI (reg:BI CARRY_REG))) (zero_extend:SI (match_dup 2))) (const_int 16))))] "" @@ -411,7 +435,7 @@ "mul" [(set_attr "psw_operand" "nop")]) -;; Unsigned multiplication producing 64 bit results from 32 bit inputs +;; Unsigned multiplication producing 64-bit results from 32-bit inputs ; The constraint on operand 0 is 't' because it is actually two regs ; long, and both regs must match the constraint. (define_insn "umulhisi3" @@ -435,20 +459,55 @@ "div" [(set_attr "psw_operand" "nop")]) +;; Signed division giving both quotient and remainder +(define_insn "divmodhi4" + [(set (match_operand:HI 0 "register_operand" "=a") + (div:HI (match_operand:HI 1 "register_operand" "a") + (match_operand:HI 2 "register_operand" "c"))) + (set (match_operand:HI 3 "register_operand" "=b") + (mod:HI (match_dup 1) + (match_dup 2)))] + "" + "sdiv" + [(set_attr "psw_operand" "nop")]) + +;; Signed 32/16 division +(define_insn "sdivlh" + [(set (match_operand:HI 0 "register_operand" "=a") + (div:HI (match_operand:SI 2 "register_operand" "t") + (match_operand:HI 3 "register_operand" "c"))) + (set (match_operand:HI 1 "register_operand" "=b") + (mod:HI (match_dup 2) + (match_dup 3)))] + "" + "sdivlh" + [(set_attr "psw_operand" "nop")]) + +;; Unsigned 32/16 division +(define_insn "udivlh" + [(set (match_operand:HI 0 "register_operand" "=a") + (udiv:HI (match_operand:SI 2 "register_operand" "t") + (match_operand:HI 3 "register_operand" "c"))) + (set (match_operand:HI 1 "register_operand" "=b") + (umod:HI (match_dup 2) + (match_dup 3)))] + "" + "divlh" + [(set_attr "psw_operand" "nop")]) + ;; Negation (define_expand "neghi2" [(set (match_operand:HI 0 "register_operand" "") (not:HI (match_operand:HI 1 "register_operand" ""))) (parallel [(set (match_dup 0) (plus:HI (match_dup 0) (const_int 1))) - (clobber (match_scratch:BI 3 ""))])] + (clobber (reg:BI CARRY_REG))])] "" "") - ;; :::::::::::::::::::: ;; :: -;; :: 16 bit Integer Shifts and Rotates +;; :: 16-bit Integer Shifts and Rotates ;; :: ;; :::::::::::::::::::: @@ -457,7 +516,7 @@ [(set (match_operand:HI 0 "register_operand" "=r") (ashift:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "nonmemory_operand" "ri"))) - (clobber (match_scratch:BI 3 "=y"))] + (clobber (reg:BI CARRY_REG))] "" "shl %0,%2") @@ -466,7 +525,7 @@ [(set (match_operand:HI 0 "register_operand" "=r") (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "nonmemory_operand" "ri"))) - (clobber (match_scratch:BI 3 "=y"))] + (clobber (reg:BI CARRY_REG))] "" "asr %0,%2") @@ -475,44 +534,75 @@ [(set (match_operand:HI 0 "register_operand" "=r") (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "nonmemory_operand" "ri"))) - (clobber (match_scratch:BI 3 "=y"))] + (clobber (reg:BI CARRY_REG))] "" "shr %0,%2") - ;; :::::::::::::::::::: ;; :: -;; :: 16 Bit Integer Logical operations +;; :: 16-Bit Integer Logical operations ;; :: ;; :::::::::::::::::::: -;; Logical AND, 16 bit integers +;; Logical AND, 16-bit integers (define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=T,r,r,r") - (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0") - (match_operand:HI 2 "nonmemory_operand" "L,r,K,i")))] + [(set (match_operand:HI 0 "xstormy16_splittable_below100_or_register" "=T,r,r,r,W") + (and:HI (match_operand:HI 1 "xstormy16_below100_or_register" "%0,0,0,0,0") + (match_operand:HI 2 "nonmemory_operand" "L,r,K,i,K")))] "" "@ and Rx,%2 and %0,%2 clr1 %0,%B2 - and %0,%2" - [(set_attr "length" "2,2,2,4")]) - -;; Inclusive OR, 16 bit integers + and %0,%2 + #" + [(set_attr "length" "2,2,2,4,2")]) + +(define_split + [(set (match_operand:HI 0 "xstormy16_below100_operand" "") + (and:HI (match_operand:HI 1 "xstormy16_below100_operand" "") + (match_operand:HI 2 "xstormy16_onebit_clr_operand" "")))] + "" + [(set (match_dup 3) + (and:QI (match_dup 4) + (match_dup 5)))] + { int s = ((INTVAL (operands[2]) & 0xff) == 0xff) ? 1 : 0; + operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, s); + operands[4] = simplify_gen_subreg (QImode, operands[1], HImode, s); + operands[5] = simplify_gen_subreg (QImode, operands[2], HImode, s); + operands[5] = GEN_INT (INTVAL (operands[5]) | ~ (HOST_WIDE_INT) 0xff); + }) + +;; Inclusive OR, 16-bit integers (define_insn "iorhi3" - [(set (match_operand:HI 0 "register_operand" "=T,r,r,r") - (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0") - (match_operand:HI 2 "nonmemory_operand" "L,r,J,i")))] + [(set (match_operand:HI 0 "xstormy16_splittable_below100_or_register" "=T,r,r,r,W") + (ior:HI (match_operand:HI 1 "xstormy16_below100_or_register" "%0,0,0,0,0") + (match_operand:HI 2 "nonmemory_operand" "L,r,J,i,J")))] "" "@ or Rx,%2 or %0,%2 set1 %0,%B2 - or %0,%2" - [(set_attr "length" "2,2,2,4")]) - -;; Exclusive OR, 16 bit integers + or %0,%2 + #" + [(set_attr "length" "2,2,2,4,2")]) + +(define_split + [(set (match_operand:HI 0 "xstormy16_below100_operand" "") + (ior:HI (match_operand:HI 1 "xstormy16_below100_operand" "") + (match_operand:HI 2 "xstormy16_onebit_set_operand" "")))] + "" + [(set (match_dup 3) + (ior:QI (match_dup 4) + (match_dup 5)))] + { int s = ((INTVAL (operands[2]) & 0xff) == 0x00) ? 1 : 0; + operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, s); + operands[4] = simplify_gen_subreg (QImode, operands[1], HImode, s); + operands[5] = simplify_gen_subreg (QImode, operands[2], HImode, s); + operands[5] = GEN_INT (INTVAL (operands[5]) & 0xff); + }) + +;; Exclusive OR, 16-bit integers (define_insn "xorhi3" [(set (match_operand:HI 0 "register_operand" "=T,r,r") (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0") @@ -524,17 +614,16 @@ xor %0,%2" [(set_attr "length" "2,2,4")]) -;; One's complement, 16 bit integers +;; One's complement, 16-bit integers (define_insn "one_cmplhi2" [(set (match_operand:HI 0 "register_operand" "=r") (not:HI (match_operand:HI 1 "register_operand" "0")))] "" "not %0") - ;; :::::::::::::::::::: ;; :: -;; :: 32 bit Integer arithmetic +;; :: 32-bit Integer arithmetic ;; :: ;; :::::::::::::::::::: @@ -543,13 +632,15 @@ [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "nonmemory_operand" "ri"))) - (clobber (match_scratch:BI 3 "=y"))] + (clobber (reg:BI CARRY_REG))] "" "#" "reload_completed" [(pc)] - "{ xstormy16_expand_arith (SImode, PLUS, operands[0], operands[1], - operands[2], operands[3]); DONE; } " + { xstormy16_expand_arith (SImode, PLUS, operands[0], operands[1], + operands[2]); + DONE; + } [(set_attr "length" "4")]) ;; Subtraction @@ -557,25 +648,40 @@ [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "nonmemory_operand" "ri"))) - (clobber (match_scratch:BI 3 "=y"))] + (clobber (reg:BI CARRY_REG))] "" "#" "reload_completed" [(pc)] - "{ xstormy16_expand_arith (SImode, MINUS, operands[0], operands[1], - operands[2], operands[3]); DONE; } " + { xstormy16_expand_arith (SImode, MINUS, operands[0], operands[1], + operands[2]); + DONE; + } [(set_attr "length" "4")]) (define_expand "negsi2" - [(set (match_operand:SI 0 "register_operand" "") - (neg:SI (match_operand:SI 1 "register_operand" "")))] + [(parallel [(set (match_operand:SI 0 "register_operand" "") + (neg:SI (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:BI CARRY_REG))])] + "" + { operands[2] = gen_reg_rtx (HImode); }) + +(define_insn_and_split "*negsi2_internal" + [(set (match_operand:SI 0 "register_operand" "=&r") + (neg:SI (match_operand:SI 1 "register_operand" "r"))) + (clobber (reg:BI CARRY_REG))] "" - "{ xstormy16_expand_arith (SImode, NEG, operands[0], const0_rtx, - operands[1], gen_reg_rtx (BImode)); DONE; }") + "#" + "reload_completed" + [(pc)] + { xstormy16_expand_arith (SImode, NEG, operands[0], operands[0], + operands[1]); + DONE; + }) ;; :::::::::::::::::::: ;; :: -;; :: 32 bit Integer Shifts and Rotates +;; :: 32-bit Integer Shifts and Rotates ;; :: ;; :::::::::::::::::::: @@ -584,47 +690,52 @@ [(parallel [(set (match_operand:SI 0 "register_operand" "") (ashift:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] + (clobber (reg:BI CARRY_REG)) + (clobber (match_dup 3))])] "" - " if (! const_int_operand (operands[2], SImode)) FAIL; - operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ") + { if (! const_int_operand (operands[2], SImode)) + FAIL; + operands[3] = gen_reg_rtx (HImode); + }) ;; Arithmetic Shift Right (define_expand "ashrsi3" [(parallel [(set (match_operand:SI 0 "register_operand" "") (ashiftrt:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] + (clobber (reg:BI CARRY_REG)) + (clobber (match_dup 3))])] "" - " if (! const_int_operand (operands[2], SImode)) FAIL; - operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ") + { if (! const_int_operand (operands[2], SImode)) + FAIL; + operands[3] = gen_reg_rtx (HImode); + }) ;; Logical Shift Right (define_expand "lshrsi3" [(parallel [(set (match_operand:SI 0 "register_operand" "") (lshiftrt:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] + (clobber (reg:BI CARRY_REG)) + (clobber (match_dup 3))])] "" - " if (! const_int_operand (operands[2], SImode)) FAIL; - operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ") + { if (! const_int_operand (operands[2], SImode)) + FAIL; + operands[3] = gen_reg_rtx (HImode); + }) (define_insn "*shiftsi" [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI 5 "shift_operator" + (match_operator:SI 4 "shift_operator" [(match_operand:SI 1 "register_operand" "0,0") (match_operand:SI 2 "const_int_operand" "U,n")])) - (clobber (match_operand:BI 3 "register_operand" "=y,y")) - (clobber (match_operand:HI 4 "" "=X,r"))] + (clobber (reg:BI CARRY_REG)) + (clobber (match_operand:HI 3 "" "=X,r"))] "" - "* return xstormy16_output_shift (SImode, GET_CODE (operands[5]), - operands[0], operands[2], operands[4]);" + "* return xstormy16_output_shift (SImode, GET_CODE (operands[4]), + operands[0], operands[2], operands[3]);" [(set_attr "length" "6,10") (set_attr "psw_operand" "clobber,clobber")]) - ;; :::::::::::::::::::: ;; :: @@ -641,12 +752,11 @@ (compare (match_operand:HI 0 "register_operand" "") (match_operand:HI 1 "nonmemory_operand" "")))] "" - " -{ - xstormy16_compare_op0 = operands[0]; - xstormy16_compare_op1 = operands[1]; - DONE; -}") + { + xstormy16_compare_op0 = operands[0]; + xstormy16_compare_op1 = operands[1]; + DONE; + }) ; There are no real SImode comparisons, but some can be emulated ; by performing a SImode subtract and looking at the condition flags. @@ -655,13 +765,11 @@ (compare (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "nonmemory_operand" "")))] "" - " -{ - xstormy16_compare_op0 = operands[0]; - xstormy16_compare_op1 = operands[1]; - DONE; -}") - + { + xstormy16_compare_op0 = operands[0]; + xstormy16_compare_op1 = operands[1]; + DONE; + }) ;; :::::::::::::::::::: ;; :: @@ -672,64 +780,63 @@ (define_expand "beq" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (EQ, operands[0]); DONE; }") + { xstormy16_emit_cbranch (EQ, operands[0]); DONE; }) (define_expand "bne" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (NE, operands[0]); DONE; }") + { xstormy16_emit_cbranch (NE, operands[0]); DONE; }) (define_expand "bge" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (GE, operands[0]); DONE; }") + { xstormy16_emit_cbranch (GE, operands[0]); DONE; }) (define_expand "bgt" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (GT, operands[0]); DONE; }") + { xstormy16_emit_cbranch (GT, operands[0]); DONE; }) (define_expand "ble" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (LE, operands[0]); DONE; }") + { xstormy16_emit_cbranch (LE, operands[0]); DONE; }) (define_expand "blt" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (LT, operands[0]); DONE; }") + { xstormy16_emit_cbranch (LT, operands[0]); DONE; }) (define_expand "bgeu" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (GEU, operands[0]); DONE; }") + { xstormy16_emit_cbranch (GEU, operands[0]); DONE; }) (define_expand "bgtu" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (GTU, operands[0]); DONE; }") + { xstormy16_emit_cbranch (GTU, operands[0]); DONE; }) (define_expand "bleu" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (LEU, operands[0]); DONE; }") + { xstormy16_emit_cbranch (LEU, operands[0]); DONE; }) (define_expand "bltu" [(use (match_operand 0 "" ""))] "" - "{ xstormy16_emit_cbranch (LTU, operands[0]); DONE; }") - + { xstormy16_emit_cbranch (LTU, operands[0]); DONE; }) -(define_insn "*cbranchhi" - [(set (pc) +(define_insn "cbranchhi" + [(set (pc) (if_then_else (match_operator:HI 1 "comparison_operator" - [(match_operand:HI 2 "nonmemory_operand" + [(match_operand:HI 2 "nonmemory_operand" "r,e,L") (match_operand:HI 3 "nonmemory_operand" "r,L,e")]) (label_ref (match_operand 0 "" "")) (pc))) - (clobber (match_operand:BI 4 "" "=&y,&y,&y"))] + (clobber (reg:BI CARRY_REG))] "" "* { @@ -738,16 +845,16 @@ [(set_attr "branch_class" "bcc12") (set_attr "psw_operand" "0,0,1")]) -(define_insn "*cbranchhi_neg" - [(set (pc) +(define_insn "cbranchhi_neg" + [(set (pc) (if_then_else (match_operator:HI 1 "comparison_operator" - [(match_operand:HI 2 "nonmemory_operand" + [(match_operand:HI 2 "nonmemory_operand" "r,e,L") (match_operand:HI 3 "nonmemory_operand" "r,L,e")]) (pc) (label_ref (match_operand 0 "" "")))) - (clobber (match_operand:BI 4 "" "=&y,&y,&y"))] + (clobber (reg:BI CARRY_REG))] "" "* { @@ -759,16 +866,12 @@ (define_insn "*eqbranchsi" [(set (pc) (if_then_else (match_operator:SI 1 "equality_operator" - [(match_operand:SI 2 "register_operand" - "+r") + [(match_operand:SI 2 "register_operand" + "r") (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc))) -;; Although I would greatly like the 'match_dup' in the following line -;; to actually be a register constraint, there is (at the time of writing) no -;; way for reload to insert an output reload on the edges out of a branch. -;; If reload is fixed to use insert_insn_on_edge, this can be changed. - (clobber (match_dup 2))] + (clobber (match_operand:SI 3 "register_operand" "=2"))] "" "* { @@ -780,53 +883,40 @@ (define_insn_and_split "*ineqbranchsi" [(set (pc) (if_then_else (match_operator:SI 1 "xstormy16_ineqsi_operator" - [(match_operand:SI 2 "register_operand" - "+r") - (match_operand:SI 3 "nonmemory_operand" + [(match_operand:SI 2 "register_operand" + "r") + (match_operand:SI 3 "nonmemory_operand" "ri")]) (label_ref (match_operand 0 "" "")) (pc))) -;; Although I would greatly like the 'match_dup' in the following line -;; to actually be a register constraint, there is (at the time of writing) no -;; way for reload to insert an output reload on the edges out of a branch. -;; If reload is fixed to use insert_insn_on_edge, this can be changed, -;; preferably to a 'minus' operand that explains the actual operation, like: -; (set (match_operand 5 "register_operand" "=2") -; (minus:SI (match_operand 6 "register_operand" "2") -; (match_operand 7 "register_operand" "3"))) - (clobber (match_dup 2)) - (clobber (match_operand:BI 4 "" "=&y"))] + (clobber (match_operand:SI 4 "register_operand" "=2")) + (clobber (reg:BI CARRY_REG))] "" "#" "reload_completed" [(pc)] - "{ xstormy16_split_cbranch (SImode, operands[0], operands[1], operands[2], - operands[4]); DONE; }" + { xstormy16_split_cbranch (SImode, operands[0], operands[1], operands[2]); DONE; } [(set_attr "length" "8")]) (define_insn "*ineqbranch_1" [(set (pc) - (if_then_else (match_operator:HI 5 "xstormy16_ineqsi_operator" - [(minus:HI (match_operand:HI 1 "register_operand" - "T,r,r") - (zero_extend:HI (match_operand:BI 4 - "register_operand" - "y,y,y"))) + (if_then_else (match_operator:HI 4 "xstormy16_ineqsi_operator" + [(minus:HI (match_operand:HI 1 "register_operand" "T,r,r") + (zero_extend:HI (reg:BI CARRY_REG))) (match_operand:HI 3 "nonmemory_operand" "L,Ir,i")]) (label_ref (match_operand 0 "" "")) (pc))) - (set (match_operand:HI 2 "register_operand" "=2,2,2") - (minus:HI (minus:HI (match_dup 1) (zero_extend:HI (match_dup 4))) + (set (match_operand:HI 2 "register_operand" "=1,1,1") + (minus:HI (minus:HI (match_dup 1) (zero_extend:HI (reg:BI CARRY_REG))) (match_dup 3))) - (clobber (match_operand:BI 6 "" "=y,y,y"))] + (clobber (reg:BI CARRY_REG))] "" "* { - return xstormy16_output_cbranch_si (operands[5], \"%l0\", 0, insn); + return xstormy16_output_cbranch_si (operands[4], \"%l0\", 0, insn); }" [(set_attr "branch_class" "bcc8p2,bcc8p2,bcc8p4") (set_attr "psw_operand" "2,2,2")]) - ;; :::::::::::::::::::: ;; :: @@ -922,7 +1012,7 @@ ;; Indirect jump through a register (define_expand "indirect_jump" [(set (match_dup 1) (const_int 0)) - (parallel [(set (pc) (match_operand:HI 0 "register_operand" "r")) + (parallel [(set (pc) (match_operand:HI 0 "register_operand" "")) (use (match_dup 1))])] "" "operands[1] = gen_reg_rtx (HImode);") @@ -951,13 +1041,12 @@ }") (define_insn "tablejump_pcrel" - [(set (pc) (mem:HI (plus:HI (pc) + [(set (pc) (mem:HI (plus:HI (pc) (match_operand:HI 0 "register_operand" "r")))) (use (label_ref:SI (match_operand 1 "" "")))] "" "br %0" [(set_attr "psw_operand" "nop")]) - ;; :::::::::::::::::::: ;; :: @@ -975,28 +1064,25 @@ (define_expand "prologue" [(const_int 1)] "" - " -{ - xstormy16_expand_prologue (); - DONE; -}") + { + xstormy16_expand_prologue (); + DONE; + }) ;; Called after register allocation to add any instructions needed for ;; the epilogue. Using an epilogue insn is favored compared to putting ;; all of the instructions in the TARGET_ASM_FUNCTION_EPILOGUE macro, ;; since it allows the scheduler to intermix instructions with the -;; restires of the caller saved registers. In some cases, it might be +;; restores of the caller saved registers. In some cases, it might be ;; necessary to emit a barrier instruction as the first insn to ;; prevent such scheduling. (define_expand "epilogue" [(const_int 2)] "" - " -{ - xstormy16_expand_epilogue (); - DONE; -}") - + { + xstormy16_expand_epilogue (); + DONE; + }) ;; :::::::::::::::::::: ;; :: @@ -1019,3 +1105,232 @@ "" [(set_attr "length" "0") (set_attr "psw_operand" "nop")]) + +;;--------------------------------------------------------------------------- + +(define_expand "iorqi3" + [(match_operand:QI 0 "xstormy16_below100_or_register" "") + (match_operand:QI 1 "xstormy16_below100_or_register" "") + (match_operand:QI 2 "nonmemory_operand" "")] + "" + { + xstormy16_expand_iorqi3 (operands); + DONE; + }) + +(define_insn "iorqi3_internal" + [(set (match_operand:QI 0 "xstormy16_below100_or_register" "=Wr") + (ior:QI (match_operand:QI 1 "xstormy16_below100_or_register" "0") + (match_operand:QI 2 "xstormy16_onebit_set_operand" "i")))] + "" + "set1 %0,%B2" + [(set_attr "length" "2") + (set_attr "psw_operand" "0")]) + +(define_peephole2 + [(set (match_operand:QI 0 "register_operand" "") + (match_operand:QI 1 "xstormy16_below100_operand" "")) + (set (match_operand:HI 2 "register_operand" "") + (ior:HI (match_operand:HI 3 "register_operand" "") + (match_operand:QI 4 "xstormy16_onebit_set_operand" ""))) + (set (match_operand:QI 5 "xstormy16_below100_operand" "") + (match_operand:QI 6 "register_operand" "")) + ] + "REGNO (operands[0]) == REGNO (operands[2]) + && REGNO (operands[0]) == REGNO (operands[3]) + && REGNO (operands[0]) == REGNO (operands[6]) + && rtx_equal_p (operands[1], operands[5])" + [(set (match_dup 1) + (ior:QI (match_dup 1) + (match_dup 4))) + ] + "") + + +(define_expand "andqi3" + [(match_operand:QI 0 "xstormy16_below100_or_register" "") + (match_operand:QI 1 "xstormy16_below100_or_register" "") + (match_operand:QI 2 "nonmemory_operand" "")] + "" + { + xstormy16_expand_andqi3 (operands); + DONE; + }) + +(define_insn "andqi3_internal" + [(set (match_operand:QI 0 "xstormy16_below100_or_register" "=Wr") + (and:QI (match_operand:QI 1 "xstormy16_below100_or_register" "0") + (match_operand:QI 2 "xstormy16_onebit_clr_operand" "i")))] + "" + "clr1 %0,%B2" + [(set_attr "length" "2") + (set_attr "psw_operand" "0")]) + +(define_peephole2 + [(set (match_operand:HI 0 "register_operand" "") + (and:HI (match_operand:HI 1 "register_operand" "") + (match_operand 2 "immediate_operand" ""))) + (set (match_operand:HI 3 "register_operand" "") + (zero_extend:HI (match_operand:QI 4 "register_operand" ""))); + ] + "REGNO (operands[0]) == REGNO (operands[1]) + && REGNO (operands[0]) == REGNO (operands[3]) + && REGNO (operands[0]) == REGNO (operands[4])" + [(set (match_dup 0) + (and:HI (match_dup 1) + (match_dup 5))) + ] + "operands[5] = GEN_INT (INTVAL (operands[2]) & 0xff);") + +(define_peephole2 + [(set (match_operand:QI 0 "register_operand" "") + (match_operand:QI 1 "xstormy16_below100_operand" "")) + (set (match_operand:HI 2 "register_operand" "") + (and:HI (match_operand:HI 3 "register_operand" "") + (match_operand:QI 4 "xstormy16_onebit_clr_operand" ""))) + (set (match_operand:QI 5 "xstormy16_below100_operand" "") + (match_operand:QI 6 "register_operand" "")) + ] + "REGNO (operands[0]) == REGNO (operands[2]) + && REGNO (operands[0]) == REGNO (operands[3]) + && REGNO (operands[0]) == REGNO (operands[6]) + && rtx_equal_p (operands[1], operands[5])" + [(set (match_dup 1) + (and:QI (match_dup 1) + (match_dup 4))) + ] + "") + +;; GCC uses different techniques to optimize MSB and LSB accesses, so +;; we have to code those separately. + +(define_insn "*bclrx" + [(set (pc) + (if_then_else (eq:HI (and:QI (match_operand:QI 1 "xstormy16_below100_operand" "W") + (match_operand:HI 2 "immediate_operand" "i")) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bn %1,%B2,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bclrx2" + [(set (pc) + (if_then_else (zero_extract:HI + (xor:HI (subreg:HI + (match_operand:QI 1 "xstormy16_below100_operand" "W") 0) + (match_operand:HI 2 "xstormy16_onebit_set_operand" "J")) + (const_int 1) + (match_operand:HI 3 "immediate_operand" "i")) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bn %1,%B2,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bclrx3" + [(set (pc) + (if_then_else (eq:HI (and:HI (zero_extend:HI (match_operand:QI 1 "xstormy16_below100_operand" "W")) + (match_operand:HI 2 "immediate_operand" "i")) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bn %1,%B2,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bclr7" + [(set (pc) + (if_then_else (xor:HI (lshiftrt:HI (subreg:HI + (match_operand:QI 1 "xstormy16_below100_operand" "W") 0) + (const_int 7)) + (const_int 1)) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bn %1,#7,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bclr15" + [(set (pc) + (if_then_else (ge:HI (sign_extend:HI (match_operand:QI 1 "xstormy16_below100_operand" "W")) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bn %1,#7,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bsetx" + [(set (pc) + (if_then_else (ne:HI (and:QI (match_operand:QI 1 "xstormy16_below100_operand" "W") + (match_operand:HI 2 "immediate_operand" "i")) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bp %1,%B2,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bsetx2" + [(set (pc) + (if_then_else (zero_extract:HI (match_operand:QI 1 "xstormy16_below100_operand" "W") + (const_int 1) + (match_operand:HI 2 "immediate_operand" "i")) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bp %1,%b2,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bsetx3" + [(set (pc) + (if_then_else (ne:HI (and:HI (zero_extend:HI (match_operand:QI 1 "xstormy16_below100_operand" "W")) + (match_operand:HI 2 "immediate_operand" "i")) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bp %1,%B2,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bset7" + [(set (pc) + (if_then_else (lshiftrt:HI (subreg:HI (match_operand:QI 1 "xstormy16_below100_operand" "W") 0) + (const_int 7)) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bp %1,#7,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")]) + +(define_insn "*bset15" + [(set (pc) + (if_then_else (lt:HI (sign_extend:HI (match_operand:QI 1 "xstormy16_below100_operand" "W")) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] + "" + "bp %1,#7,%l0" + [(set_attr "length" "4") + (set_attr "psw_operand" "nop")])