rt_gccstream/gcc/config/stormy16/stormy16.md

1251 lines
36 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;; XSTORMY16 Machine description template
;; 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 GCC.
;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
;;- 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)
]
)
;; ::::::::::::::::::::
;; ::
;; :: Attributes
;; ::
;; ::::::::::::::::::::
; Categorize branches for the conditional in the length attribute.
(define_attr "branch_class" "notdirectbranch,br12,bcc12,bcc8p2,bcc8p4"
(const_string "notdirectbranch"))
; The length of an instruction, used for branch shortening.
(define_attr "length" ""
(cond
[(eq_attr "branch_class" "br12")
(if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2046))
(lt (minus (match_dup 0) (pc)) (const_int 2048)))
(const_int 2)
(const_int 4))
(eq_attr "branch_class" "bcc12")
(if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
(lt (minus (match_dup 0) (pc)) (const_int 2048)))
(const_int 4)
(const_int 8))
(eq_attr "branch_class" "bcc8p2")
(if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -124))
(lt (minus (match_dup 0) (pc)) (const_int 128)))
(const_int 4)
(const_int 8))
(eq_attr "branch_class" "bcc8p4")
(if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -122))
(lt (minus (match_dup 0) (pc)) (const_int 128)))
(const_int 6)
(const_int 10))]
(const_int 2)))
; The operand which determines the setting of Rpsw.
; The numbers indicate the operand number,
; 'clobber' indicates it is changed in some unspecified way
; 'nop' means it is not changed.
(define_attr "psw_operand" "clobber,nop,0,1,2,3,4" (const_string "0"))
(define_asm_attributes [(set_attr "length" "4")
(set_attr "psw_operand" "clobber")])
(include "predicates.md")
;; ::::::::::::::::::::
;; ::
;; :: Moves
;; ::
;; ::::::::::::::::::::
;; push/pop qi and hi are here as separate insns rather than part of
;; the movqi/hi patterns because we need to ensure that reload isn't
;; passed anything it can't cope with. Without these patterns, we
;; might end up with
;; (set (mem (post_inc (sp))) mem (post_inc (reg)))
;; If, in this example, reg needs reloading, reload will read reg from
;; the stack , adjust sp, and store reg back at what is now the wrong
;; offset. By using separate patterns for push and pop we ensure that
;; insns like this one are never generated.
(define_insn "pushqi1"
[(set (mem:QI (post_inc (reg:HI 15)))
(match_operand:QI 0 "register_operand" "r"))]
""
"push %0"
[(set_attr "psw_operand" "nop")
(set_attr "length" "2")])
(define_insn "popqi1"
[(set (match_operand:QI 0 "register_operand" "=r")
(mem:QI (pre_dec (reg:HI 15))))]
""
"pop %0"
[(set_attr "psw_operand" "nop")
(set_attr "length" "2")])
(define_expand "movqi"
[(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
{ 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,W,e")
(match_operand:QI 1 "general_operand" "r,e,m,i,i,i,i,ie,W"))]
""
"@
mov %0,%1
mov.b %0,%1
mov.b %0,%1
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"
[(const_int 2)
(if_then_else (match_operand:QI 0 "short_memory_operand" "")
(const_int 2)
(const_int 4))
(if_then_else (match_operand:QI 1 "short_memory_operand" "")
(const_int 2)
(const_int 4))
(const_int 2)
(const_int 2)
(const_int 4)
(const_int 4)
(const_int 2)
(const_int 2)])
(set_attr "psw_operand" "0,0,0,0,nop,0,nop,0,0")])
(define_insn "pushhi1"
[(set (mem:HI (post_inc (reg:HI 15)))
(match_operand:HI 0 "register_operand" "r"))]
""
"push %0"
[(set_attr "psw_operand" "nop")
(set_attr "length" "2")])
(define_insn "pophi1"
[(set (match_operand:HI 0 "register_operand" "=r")
(mem:HI (pre_dec (reg:HI 15))))]
""
"pop %0"
[(set_attr "psw_operand" "nop")
(set_attr "length" "2")])
(define_expand "movhi"
[(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "")
(match_operand:HI 1 "xs_hi_general_operand" ""))]
""
{ 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,W,e")
(match_operand:HI 1 "xs_hi_general_operand" "r,e,m,L,L,i,i,ie,W"))]
""
"@
mov %0,%1
mov.w %0,%1
mov.w %0,%1
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"
[(const_int 2)
(if_then_else (match_operand:QI 0 "short_memory_operand" "")
(const_int 2)
(const_int 4))
(if_then_else (match_operand:QI 1 "short_memory_operand" "")
(const_int 2)
(const_int 4))
(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,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;
})
(define_insn_and_split "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,Q,r,m,e,&e,e,r,S")
(match_operand:SI 1 "general_operand" "r,r,R,e,o, V,L,i,i"))]
""
"#"
"reload_completed"
[(pc)]
{ xstormy16_split_move (SImode, operands[0], operands[1]);
DONE;
}
[(set_attr_alternative "length"
[(const_int 4)
(const_int 4)
(const_int 4)
(if_then_else (match_operand:QI 0 "short_memory_operand" "")
(const_int 6)
(const_int 8))
(if_then_else (match_operand:QI 1 "short_memory_operand" "")
(const_int 6)
(const_int 8))
(if_then_else (match_operand:QI 1 "short_memory_operand" "")
(const_int 6)
(const_int 8))
(const_int 4)
(const_int 8)
(const_int 8)])])
;; ::::::::::::::::::::
;; ::
;; :: Conversions
;; ::
;; ::::::::::::::::::::
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(sign_extend:HI (match_operand:QI 1 "register_operand" "0")))]
""
"cbw %0")
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=e,r")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,0")))]
""
"@
mov.b %0, %1
shl %0,#8\n\tshr %0,#8"
[(set_attr "psw_operand" "nop,0")
(set_attr_alternative "length"
[(const_int 4)
(const_int 8)])])
;; ::::::::::::::::::::
;; ::
;; :: Bit field extraction
;; ::
;; ::::::::::::::::::::
;; Extract an unsigned bit field
;(define_insn "extzv"
; [(set (match_operand:SI 0 "register_operand" "=r")
; (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
; (match_operand:SI 2 "const_int_operand" "n")
; (match_operand:SI 3 "const_int_operand" "n")))]
; ""
; "extzv %0,%1,%2,%3"
; [(set_attr "length" "4")])
;; Insert a bit field
;(define_insn "insv"
; [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
; (match_operand:SI 1 "const_int_operand" "n")
; (match_operand:SI 2 "const_int_operand" "n"))
; (match_operand:SI 3 "nonmemory_operand" "ri"))]
; ""
; "insv %0,%1,%2,%3"
; [(set_attr "length" "4")])
;; ::::::::::::::::::::
;; ::
;; :: 16-bit Integer arithmetic
;; ::
;; ::::::::::::::::::::
;; Addition
; 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,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,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 "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))))]
""
"@
add Rx,%2
add %0,%2
add %0,%2"
[(set_attr "length" "2,2,4")])
(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 (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 (reg:BI CARRY_REG)))
(zero_extend:SI (match_dup 2)))
(const_int 16))))]
""
"@
adc Rx,%2
adc %0,%2
adc %0,%2"
[(set_attr "length" "2,2,4")])
;; Subtraction
; 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.
(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 "xs_hi_nonmemory_operand" "O,P,L,M,rI,M,i")))
(clobber (reg:BI CARRY_REG))]
""
"@
dec %0,%o2
inc %0,%O2
sub Rx,%2
add Rx,#%n2
sub %0,%2
add %0,#%n2
sub %0,%2"
[(set_attr "length" "2,2,2,2,2,2,4")])
(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 "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))))]
""
"@
sub Rx,%2
sub %0,%2
sub %0,%2"
[(set_attr "length" "2,2,4")])
(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 (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 (reg:BI CARRY_REG)))
(zero_extend:SI (match_dup 2)))
(const_int 16))))]
""
"@
sbc Rx,%2
sbc %0,%2
sbc %0,%2"
[(set_attr "length" "2,2,4")])
; Basic multiplication
(define_insn "mulhi3"
[(set (match_operand:HI 0 "register_operand" "=a")
(mult:HI (match_operand:HI 1 "register_operand" "%a")
(match_operand:HI 2 "register_operand" "c")))
(clobber (match_scratch:HI 3 "=b"))
]
""
"mul"
[(set_attr "psw_operand" "nop")])
;; 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"
[(set (match_operand:SI 0 "register_operand" "=t")
(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%a"))
(zero_extend:SI (match_operand:HI 2 "register_operand" "c"))))
]
""
"mul"
[(set_attr "psw_operand" "nop")])
;; Unsigned division giving both quotient and remainder
(define_insn "udivmodhi4"
[(set (match_operand:HI 0 "register_operand" "=a")
(udiv:HI (match_operand:HI 1 "register_operand" "a")
(match_operand:HI 2 "register_operand" "c")))
(set (match_operand:HI 3 "register_operand" "=b")
(umod:HI (match_dup 1)
(match_dup 2)))]
""
"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 (reg:BI CARRY_REG))])]
""
"")
;; ::::::::::::::::::::
;; ::
;; :: 16-bit Integer Shifts and Rotates
;; ::
;; ::::::::::::::::::::
;; Arithmetic Shift Left
(define_insn "ashlhi3"
[(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 (reg:BI CARRY_REG))]
""
"shl %0,%2")
;; Arithmetic Shift Right
(define_insn "ashrhi3"
[(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 (reg:BI CARRY_REG))]
""
"asr %0,%2")
;; Logical Shift Right
(define_insn "lshrhi3"
[(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 (reg:BI CARRY_REG))]
""
"shr %0,%2")
;; ::::::::::::::::::::
;; ::
;; :: 16-Bit Integer Logical operations
;; ::
;; ::::::::::::::::::::
;; Logical AND, 16-bit integers
(define_insn "andhi3"
[(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,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 "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,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")
(match_operand:HI 2 "nonmemory_operand" "L,r,i")))]
""
"@
xor Rx,%2
xor %0,%2
xor %0,%2"
[(set_attr "length" "2,2,4")])
;; 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
;; ::
;; ::::::::::::::::::::
;; Addition
(define_insn_and_split "addsi3"
[(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 (reg:BI CARRY_REG))]
""
"#"
"reload_completed"
[(pc)]
{ xstormy16_expand_arith (SImode, PLUS, operands[0], operands[1],
operands[2]);
DONE;
}
[(set_attr "length" "4")])
;; Subtraction
(define_insn_and_split "subsi3"
[(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 (reg:BI CARRY_REG))]
""
"#"
"reload_completed"
[(pc)]
{ xstormy16_expand_arith (SImode, MINUS, operands[0], operands[1],
operands[2]);
DONE;
}
[(set_attr "length" "4")])
(define_expand "negsi2"
[(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))]
""
"#"
"reload_completed"
[(pc)]
{ xstormy16_expand_arith (SImode, NEG, operands[0], operands[0],
operands[1]);
DONE;
})
;; ::::::::::::::::::::
;; ::
;; :: 32-bit Integer Shifts and Rotates
;; ::
;; ::::::::::::::::::::
;; Arithmetic Shift Left
(define_expand "ashlsi3"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(ashift:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
(clobber (reg:BI CARRY_REG))
(clobber (match_dup 3))])]
""
{ 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 (reg:BI CARRY_REG))
(clobber (match_dup 3))])]
""
{ 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 (reg:BI CARRY_REG))
(clobber (match_dup 3))])]
""
{ 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 4 "shift_operator"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "const_int_operand" "U,n")]))
(clobber (reg:BI CARRY_REG))
(clobber (match_operand:HI 3 "" "=X,r"))]
""
"* 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")])
;; ::::::::::::::::::::
;; ::
;; :: Branches
;; ::
;; ::::::::::::::::::::
(define_expand "cbranchhi4"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY_REG))]
""
{
xstormy16_emit_cbranch (GET_CODE (operands[0]), operands[1], operands[2],
operands[3]);
DONE;
})
(define_insn "cbranchhi"
[(set (pc)
(if_then_else (match_operator:HI 1 "comparison_operator"
[(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 (reg:BI CARRY_REG))]
""
"*
{
return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 0, insn);
}"
[(set_attr "branch_class" "bcc12")
(set_attr "psw_operand" "0,0,1")])
(define_insn "cbranchhi_neg"
[(set (pc)
(if_then_else (match_operator:HI 1 "comparison_operator"
[(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 (reg:BI CARRY_REG))]
""
"*
{
return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 1, insn);
}"
[(set_attr "branch_class" "bcc12")
(set_attr "psw_operand" "0,0,1")])
(define_insn "*eqbranchsi"
[(set (pc)
(if_then_else (match_operator:SI 1 "equality_operator"
[(match_operand:SI 2 "register_operand"
"r")
(const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))
(clobber (match_operand:SI 3 "register_operand" "=2"))]
""
"*
{
return xstormy16_output_cbranch_si (operands[1], \"%l0\", 0, insn);
}"
[(set_attr "branch_class" "bcc8p2")
(set_attr "psw_operand" "clobber")])
(define_insn "*ineqbranch_1"
[(set (pc)
(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,r,i")])
(label_ref (match_operand 0 "" ""))
(pc)))
(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 (reg:BI CARRY_REG))]
""
"*
{
return xstormy16_output_cbranch_si (operands[4], \"%l0\", 0, insn);
}"
[(set_attr "branch_class" "bcc8p2,bcc8p2,bcc8p4")
(set_attr "psw_operand" "2,2,2")])
;; ::::::::::::::::::::
;; ::
;; :: Call and branch instructions
;; ::
;; ::::::::::::::::::::
;; Subroutine call instruction returning no value. Operand 0 is the function
;; to call; operand 1 is the number of bytes of arguments pushed (in mode
;; `SImode', except it is normally a `const_int'); operand 2 is the number of
;; registers used as operands.
;; On most machines, operand 2 is not actually stored into the RTL pattern. It
;; is supplied for the sake of some RISC machines which need to put this
;; information into the assembler code; they can put it in the RTL instead of
;; operand 1.
(define_expand "call"
[(call (match_operand:HI 0 "memory_operand" "m")
(match_operand 1 "" ""))
(use (match_operand 2 "immediate_operand" ""))]
""
"xstormy16_expand_call (NULL_RTX, operands[0], operands[1]); DONE;")
;; Subroutine call instruction returning a value. Operand 0 is the hard
;; register in which the value is returned. There are three more operands, the
;; same as the three operands of the `call' instruction (but with numbers
;; increased by one).
;; Subroutines that return `BLKmode' objects use the `call' insn.
(define_expand "call_value"
[(set (match_operand 0 "register_operand" "=r")
(call (match_operand:HI 1 "memory_operand" "m")
(match_operand:SI 2 "" "")))
(use (match_operand 3 "immediate_operand" ""))]
""
"xstormy16_expand_call (operands[0], operands[1], operands[2]); DONE;")
(define_insn "*call_internal"
[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
(match_operand 1 "" ""))
(use (match_operand:HI 2 "nonmemory_operand" "X,z"))]
""
"@
callf %C0
call %2,%0"
[(set_attr "length" "4,2")
(set_attr "psw_operand" "clobber")])
(define_insn "*call_value_internal"
[(set (match_operand 3 "register_operand" "=r,r")
(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
(match_operand 1 "" "")))
(use (match_operand:HI 2 "nonmemory_operand" "X,z"))]
""
"@
callf %C0
call %2,%0"
[(set_attr "length" "4,2")
(set_attr "psw_operand" "clobber")])
;; Subroutine return
(define_expand "return"
[(return)]
"direct_return()"
"")
(define_insn "return_internal"
[(return)]
""
"ret"
[(set_attr "psw_operand" "nop")])
(define_insn "return_internal_interrupt"
[(return)
(unspec_volatile [(const_int 0)] 1)]
""
"iret"
[(set_attr "psw_operand" "clobber")])
;; Normal unconditional jump
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
"*
{
return xstormy16_output_cbranch_hi (NULL_RTX, \"%l0\", 0, insn);
}"
[(set_attr "branch_class" "br12")
(set_attr "psw_operand" "nop")])
;; 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" ""))
(use (match_dup 1))])]
""
"operands[1] = gen_reg_rtx (HImode);")
(define_insn ""
[(set (pc) (match_operand:HI 0 "register_operand" "r"))
(use (match_operand:HI 1 "register_operand" "z"))]
""
"jmp %1,%0"
[(set_attr "length" "4")
(set_attr "psw_operand" "nop")])
;; Table-based switch statements.
(define_expand "casesi"
[(use (match_operand:SI 0 "register_operand" ""))
(use (match_operand:SI 1 "immediate_operand" ""))
(use (match_operand:SI 2 "immediate_operand" ""))
(use (label_ref (match_operand 3 "" "")))
(use (label_ref (match_operand 4 "" "")))]
""
"
{
xstormy16_expand_casesi (operands[0], operands[1], operands[2],
operands[3], operands[4]);
DONE;
}")
(define_insn "tablejump_pcrel"
[(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")])
;; ::::::::::::::::::::
;; ::
;; :: Prologue and Epilogue instructions
;; ::
;; ::::::::::::::::::::
;; Called after register allocation to add any instructions needed for
;; the prologue. Using a prologue insn is favored compared to putting
;; all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro,
;; since it allows the scheduler to intermix instructions with the
;; saves of the caller saved registers. In some cases, it might be
;; necessary to emit a barrier instruction as the last insn to prevent
;; such scheduling.
(define_expand "prologue"
[(const_int 1)]
""
{
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
;; 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;
})
;; ::::::::::::::::::::
;; ::
;; :: Miscellaneous instructions
;; ::
;; ::::::::::::::::::::
;; No operation, needed in case the user uses -g but not -O.
(define_insn "nop"
[(const_int 0)]
""
"nop"
[(set_attr "psw_operand" "nop")])
;; Pseudo instruction that prevents the scheduler from moving code above this
;; point.
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] 0)]
""
""
[(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")])