;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
;; Copyright (C) 1990-2015 Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
;; 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
;; .
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;
;; REGNOS
;;
(define_constants
[(FIRST_GPR_REGNO 0)
(STACK_POINTER_REGNUM 1)
(TOC_REGNUM 2)
(STATIC_CHAIN_REGNUM 11)
(HARD_FRAME_POINTER_REGNUM 31)
(LAST_GPR_REGNO 31)
(FIRST_FPR_REGNO 32)
(LAST_FPR_REGNO 63)
(LR_REGNO 65)
(CTR_REGNO 66)
(ARG_POINTER_REGNUM 67)
(CR0_REGNO 68)
(CR1_REGNO 69)
(CR2_REGNO 70)
(CR3_REGNO 71)
(CR4_REGNO 72)
(CR5_REGNO 73)
(CR6_REGNO 74)
(CR7_REGNO 75)
(MAX_CR_REGNO 75)
(CA_REGNO 76)
(FIRST_ALTIVEC_REGNO 77)
(LAST_ALTIVEC_REGNO 108)
(VRSAVE_REGNO 109)
(VSCR_REGNO 110)
(SPE_ACC_REGNO 111)
(SPEFSCR_REGNO 112)
(FRAME_POINTER_REGNUM 113)
(TFHAR_REGNO 114)
(TFIAR_REGNO 115)
(TEXASR_REGNO 116)
(FIRST_SPE_HIGH_REGNO 117)
(LAST_SPE_HIGH_REGNO 148)
])
;;
;; UNSPEC usage
;;
(define_c_enum "unspec"
[UNSPEC_FRSP ; frsp for POWER machines
UNSPEC_PROBE_STACK ; probe stack memory reference
UNSPEC_TOCPTR ; address of a word pointing to the TOC
UNSPEC_TOC ; address of the TOC (more-or-less)
UNSPEC_TOCSLOT ; offset from r1 of toc pointer save slot
UNSPEC_MOVSI_GOT
UNSPEC_MV_CR_OV ; move_from_CR_ov_bit
UNSPEC_FCTIWZ
UNSPEC_FRIM
UNSPEC_FRIN
UNSPEC_FRIP
UNSPEC_FRIZ
UNSPEC_LD_MPIC ; load_macho_picbase
UNSPEC_RELD_MPIC ; re-load_macho_picbase
UNSPEC_MPIC_CORRECT ; macho_correct_pic
UNSPEC_TLSGD
UNSPEC_TLSLD
UNSPEC_MOVESI_FROM_CR
UNSPEC_MOVESI_TO_CR
UNSPEC_TLSDTPREL
UNSPEC_TLSDTPRELHA
UNSPEC_TLSDTPRELLO
UNSPEC_TLSGOTDTPREL
UNSPEC_TLSTPREL
UNSPEC_TLSTPRELHA
UNSPEC_TLSTPRELLO
UNSPEC_TLSGOTTPREL
UNSPEC_TLSTLS
UNSPEC_FIX_TRUNC_TF ; fadd, rounding towards zero
UNSPEC_MV_CR_GT ; move_from_CR_gt_bit
UNSPEC_STFIWX
UNSPEC_POPCNTB
UNSPEC_FRES
UNSPEC_SP_SET
UNSPEC_SP_TEST
UNSPEC_SYNC
UNSPEC_LWSYNC
UNSPEC_SYNC_OP
UNSPEC_ATOMIC
UNSPEC_CMPXCHG
UNSPEC_XCHG
UNSPEC_AND
UNSPEC_DLMZB
UNSPEC_DLMZB_CR
UNSPEC_DLMZB_STRLEN
UNSPEC_RSQRT
UNSPEC_TOCREL
UNSPEC_MACHOPIC_OFFSET
UNSPEC_BPERM
UNSPEC_COPYSIGN
UNSPEC_PARITY
UNSPEC_FCTIW
UNSPEC_FCTID
UNSPEC_LFIWAX
UNSPEC_LFIWZX
UNSPEC_FCTIWUZ
UNSPEC_GRP_END_NOP
UNSPEC_P8V_FMRGOW
UNSPEC_P8V_MTVSRWZ
UNSPEC_P8V_RELOAD_FROM_GPR
UNSPEC_P8V_MTVSRD
UNSPEC_P8V_XXPERMDI
UNSPEC_P8V_RELOAD_FROM_VSX
UNSPEC_ADDG6S
UNSPEC_CDTBCD
UNSPEC_CBCDTD
UNSPEC_DIVE
UNSPEC_DIVEO
UNSPEC_DIVEU
UNSPEC_DIVEUO
UNSPEC_UNPACK_128BIT
UNSPEC_PACK_128BIT
UNSPEC_LSQ
UNSPEC_FUSION_GPR
])
;;
;; UNSPEC_VOLATILE usage
;;
(define_c_enum "unspecv"
[UNSPECV_BLOCK
UNSPECV_LL ; load-locked
UNSPECV_SC ; store-conditional
UNSPECV_PROBE_STACK_RANGE ; probe range of stack addresses
UNSPECV_EH_RR ; eh_reg_restore
UNSPECV_ISYNC ; isync instruction
UNSPECV_MFTB ; move from time base
UNSPECV_NLGR ; non-local goto receiver
UNSPECV_MFFS ; Move from FPSCR
UNSPECV_MTFSF ; Move to FPSCR Fields
])
;; Define an insn type attribute. This is used in function unit delay
;; computations.
(define_attr "type"
"integer,two,three,
add,logical,shift,insert,
mul,halfmul,div,
exts,cntlz,popcnt,isel,
load,store,fpload,fpstore,vecload,vecstore,
cmp,
branch,jmpreg,mfjmpr,mtjmpr,trap,isync,sync,load_l,store_c,
cr_logical,delayed_cr,mfcr,mfcrf,mtcr,
fpcompare,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,
brinc,
vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,
vecfloat,vecfdiv,vecdouble,mffgpr,mftgpr,crypto,
htm"
(const_string "integer"))
;; What data size does this instruction work on?
;; This is used for insert, mul.
(define_attr "size" "8,16,32,64" (const_string "32"))
;; Is this instruction record form ("dot", signed compare to 0, writing CR0)?
;; This is used for add, logical, shift, exts, mul.
(define_attr "dot" "no,yes" (const_string "no"))
;; Does this instruction sign-extend its result?
;; This is used for load insns.
(define_attr "sign_extend" "no,yes" (const_string "no"))
;; Does this instruction use indexed (that is, reg+reg) addressing?
;; This is used for load and store insns. If operand 0 or 1 is a MEM
;; it is automatically set based on that. If a load or store instruction
;; has fewer than two operands it needs to set this attribute manually
;; or the compiler will crash.
(define_attr "indexed" "no,yes"
(if_then_else (ior (match_operand 0 "indexed_address_mem")
(match_operand 1 "indexed_address_mem"))
(const_string "yes")
(const_string "no")))
;; Does this instruction use update addressing?
;; This is used for load and store insns. See the comments for "indexed".
(define_attr "update" "no,yes"
(if_then_else (ior (match_operand 0 "update_address_mem")
(match_operand 1 "update_address_mem"))
(const_string "yes")
(const_string "no")))
;; Is this instruction using operands[2] as shift amount, and can that be a
;; register?
;; This is used for shift insns.
(define_attr "maybe_var_shift" "no,yes" (const_string "no"))
;; Is this instruction using a shift amount from a register?
;; This is used for shift insns.
(define_attr "var_shift" "no,yes"
(if_then_else (and (eq_attr "type" "shift")
(eq_attr "maybe_var_shift" "yes"))
(if_then_else (match_operand 2 "gpc_reg_operand")
(const_string "yes")
(const_string "no"))
(const_string "no")))
;; Define floating point instruction sub-types for use with Xfpu.md
(define_attr "fp_type" "fp_default,fp_addsub_s,fp_addsub_d,fp_mul_s,fp_mul_d,fp_div_s,fp_div_d,fp_maddsub_s,fp_maddsub_d,fp_sqrt_s,fp_sqrt_d" (const_string "fp_default"))
;; Length (in bytes).
; '(pc)' in the following doesn't include the instruction itself; it is
; calculated as if the instruction had zero size.
(define_attr "length" ""
(if_then_else (eq_attr "type" "branch")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -32768))
(lt (minus (match_dup 0) (pc))
(const_int 32764)))
(const_int 4)
(const_int 8))
(const_int 4)))
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in rs6000-opts.h.
(define_attr "cpu"
"ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,
ppc750,ppc7400,ppc7450,
ppc403,ppc405,ppc440,ppc476,
ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,
power4,power5,power6,power7,power8,
rs64a,mpccore,cell,ppca2,titan"
(const (symbol_ref "rs6000_cpu_attr")))
;; If this instruction is microcoded on the CELL processor
; The default for load extended, the recorded instructions and rotate/shifts by a variable is always microcoded
(define_attr "cell_micro" "not,conditional,always"
(if_then_else (ior (and (eq_attr "type" "shift,exts,mul")
(eq_attr "dot" "yes"))
(and (eq_attr "type" "load")
(eq_attr "sign_extend" "yes"))
(and (eq_attr "type" "shift")
(eq_attr "var_shift" "yes")))
(const_string "always")
(const_string "not")))
(automata_option "ndfa")
(include "rs64.md")
(include "mpc.md")
(include "40x.md")
(include "440.md")
(include "476.md")
(include "601.md")
(include "603.md")
(include "6xx.md")
(include "7xx.md")
(include "7450.md")
(include "8540.md")
(include "e300c2c3.md")
(include "e500mc.md")
(include "e500mc64.md")
(include "e5500.md")
(include "e6500.md")
(include "power4.md")
(include "power5.md")
(include "power6.md")
(include "power7.md")
(include "power8.md")
(include "cell.md")
(include "xfpu.md")
(include "a2.md")
(include "titan.md")
(include "predicates.md")
(include "constraints.md")
(include "darwin.md")
;; Mode iterators
; This mode iterator allows :GPR to be used to indicate the allowable size
; of whole values in GPRs.
(define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")])
; Any supported integer mode.
(define_mode_iterator INT [QI HI SI DI TI PTI])
; Any supported integer mode that fits in one register.
(define_mode_iterator INT1 [QI HI SI (DI "TARGET_POWERPC64")])
; Everything we can extend QImode to.
(define_mode_iterator EXTQI [HI SI (DI "TARGET_POWERPC64")])
; Everything we can extend HImode to.
(define_mode_iterator EXTHI [SI (DI "TARGET_POWERPC64")])
; Everything we can extend SImode to.
(define_mode_iterator EXTSI [(DI "TARGET_POWERPC64")])
; QImode or HImode for small atomic ops
(define_mode_iterator QHI [QI HI])
; HImode or SImode for sign extended fusion ops
(define_mode_iterator HSI [HI SI])
; SImode or DImode, even if DImode doesn't fit in GPRs.
(define_mode_iterator SDI [SI DI])
; The size of a pointer. Also, the size of the value that a record-condition
; (one with a '.') will compare; and the size used for arithmetic carries.
(define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
; Iterator to add PTImode along with TImode (TImode can go in VSX registers,
; PTImode is GPR only)
(define_mode_iterator TI2 [TI PTI])
; Any hardware-supported floating-point mode
(define_mode_iterator FP [
(SF "TARGET_HARD_FLOAT
&& ((TARGET_FPRS && TARGET_SINGLE_FLOAT) || TARGET_E500_SINGLE)")
(DF "TARGET_HARD_FLOAT
&& ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)")
(TF "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128")
(DD "TARGET_DFP")
(TD "TARGET_DFP")])
; Any fma capable floating-point mode.
(define_mode_iterator FMA_F [
(SF "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT")
(DF "(TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
|| VECTOR_UNIT_VSX_P (DFmode)")
(V2SF "TARGET_PAIRED_FLOAT")
(V4SF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)")
(V2DF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)")
])
; Floating point move iterators to combine binary and decimal moves
(define_mode_iterator FMOVE32 [SF SD])
(define_mode_iterator FMOVE64 [DF DD])
(define_mode_iterator FMOVE64X [DI DF DD])
(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128")
(TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
; Iterators for 128 bit types for direct move
(define_mode_iterator FMOVE128_GPR [(TI "TARGET_VSX_TIMODE")
(V16QI "")
(V8HI "")
(V4SI "")
(V4SF "")
(V2DI "")
(V2DF "")
(V1TI "")])
; Whether a floating point move is ok, don't allow SD without hardware FP
(define_mode_attr fmove_ok [(SF "")
(DF "")
(SD "TARGET_HARD_FLOAT && TARGET_FPRS")
(DD "")])
; Convert REAL_VALUE to the appropriate bits
(define_mode_attr real_value_to_target [(SF "REAL_VALUE_TO_TARGET_SINGLE")
(DF "REAL_VALUE_TO_TARGET_DOUBLE")
(SD "REAL_VALUE_TO_TARGET_DECIMAL32")
(DD "REAL_VALUE_TO_TARGET_DECIMAL64")])
; Definitions for load to 32-bit fpr register
(define_mode_attr f32_lr [(SF "f") (SD "wz")])
(define_mode_attr f32_lm [(SF "m") (SD "Z")])
(define_mode_attr f32_li [(SF "lfs%U1%X1 %0,%1") (SD "lfiwzx %0,%y1")])
(define_mode_attr f32_lv [(SF "lxsspx %x0,%y1") (SD "lxsiwzx %x0,%y1")])
; Definitions for store from 32-bit fpr register
(define_mode_attr f32_sr [(SF "f") (SD "wx")])
(define_mode_attr f32_sm [(SF "m") (SD "Z")])
(define_mode_attr f32_si [(SF "stfs%U0%X0 %1,%0") (SD "stfiwx %1,%y0")])
(define_mode_attr f32_sv [(SF "stxsspx %x1,%y0") (SD "stxsiwzx %x1,%y0")])
; Definitions for 32-bit fpr direct move
; At present, the decimal modes are not allowed in the traditional altivec
; registers, so restrict the constraints to just the traditional FPRs.
(define_mode_attr f32_dm [(SF "wn") (SD "wh")])
; Definitions for 32-bit VSX
(define_mode_attr f32_vsx [(SF "ww") (SD "wn")])
; Definitions for 32-bit use of altivec registers
(define_mode_attr f32_av [(SF "wu") (SD "wn")])
; Definitions for 64-bit VSX
(define_mode_attr f64_vsx [(DF "ws") (DD "wn")])
; Definitions for 64-bit direct move
(define_mode_attr f64_dm [(DF "wk") (DD "wh")])
; Definitions for 64-bit use of altivec registers
(define_mode_attr f64_av [(DF "wv") (DD "wn")])
; These modes do not fit in integer registers in 32-bit mode.
; but on e500v2, the gpr are 64 bit registers
(define_mode_iterator DIFD [DI (DF "!TARGET_E500_DOUBLE") DD])
; Iterator for reciprocal estimate instructions
(define_mode_iterator RECIPF [SF DF V4SF V2DF])
; Iterator for just SF/DF
(define_mode_iterator SFDF [SF DF])
; SF/DF suffix for traditional floating instructions
(define_mode_attr Ftrad [(SF "s") (DF "")])
; SF/DF suffix for VSX instructions
(define_mode_attr Fvsx [(SF "sp") (DF "dp")])
; SF/DF constraint for arithmetic on traditional floating point registers
(define_mode_attr Ff [(SF "f") (DF "d")])
; SF/DF constraint for arithmetic on VSX registers
(define_mode_attr Fv [(SF "wy") (DF "ws")])
; SF/DF constraint for arithmetic on altivec registers
(define_mode_attr Fa [(SF "wu") (DF "wv")])
; s/d suffix for things like fp_addsub_s/fp_addsub_d
(define_mode_attr Fs [(SF "s") (DF "d")])
; FRE/FRES support
(define_mode_attr Ffre [(SF "fres") (DF "fre")])
(define_mode_attr FFRE [(SF "FRES") (DF "FRE")])
; Conditional returns.
(define_code_iterator any_return [return simple_return])
(define_code_attr return_pred [(return "direct_return ()")
(simple_return "1")])
(define_code_attr return_str [(return "") (simple_return "simple_")])
; Logical operators.
(define_code_iterator iorxor [ior xor])
; Signed/unsigned variants of ops.
(define_code_iterator any_extend [sign_extend zero_extend])
(define_code_attr u [(sign_extend "") (zero_extend "u")])
(define_code_attr su [(sign_extend "s") (zero_extend "u")])
; Various instructions that come in SI and DI forms.
; A generic w/d attribute, for things like cmpw/cmpd.
(define_mode_attr wd [(QI "b")
(HI "h")
(SI "w")
(DI "d")
(V16QI "b")
(V8HI "h")
(V4SI "w")
(V2DI "d")])
;; How many bits in this mode?
(define_mode_attr bits [(QI "8") (HI "16") (SI "32") (DI "64")])
; DImode bits
(define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
;; ISEL/ISEL64 target selection
(define_mode_attr sel [(SI "") (DI "64")])
;; Bitmask for shift instructions
(define_mode_attr hH [(SI "h") (DI "H")])
;; A mode twice the size of the given mode
(define_mode_attr dmode [(SI "di") (DI "ti")])
(define_mode_attr DMODE [(SI "DI") (DI "TI")])
;; Suffix for reload patterns
(define_mode_attr ptrsize [(SI "32bit")
(DI "64bit")])
(define_mode_attr tptrsize [(SI "TARGET_32BIT")
(DI "TARGET_64BIT")])
(define_mode_attr mptrsize [(SI "si")
(DI "di")])
(define_mode_attr ptrload [(SI "lwz")
(DI "ld")])
(define_mode_attr ptrm [(SI "m")
(DI "Y")])
(define_mode_attr rreg [(SF "f")
(DF "ws")
(TF "f")
(TD "f")
(V4SF "wf")
(V2DF "wd")])
(define_mode_attr rreg2 [(SF "f")
(DF "d")])
(define_mode_attr SI_CONVERT_FP [(SF "TARGET_FCFIDS")
(DF "TARGET_FCFID")])
(define_mode_attr E500_CONVERT [(SF "!TARGET_FPRS")
(DF "TARGET_E500_DOUBLE")])
(define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT")
(DF "TARGET_DOUBLE_FLOAT")])
;; Mode iterator for logical operations on 128-bit types
(define_mode_iterator BOOL_128 [TI
PTI
(V16QI "TARGET_ALTIVEC")
(V8HI "TARGET_ALTIVEC")
(V4SI "TARGET_ALTIVEC")
(V4SF "TARGET_ALTIVEC")
(V2DI "TARGET_ALTIVEC")
(V2DF "TARGET_ALTIVEC")
(V1TI "TARGET_ALTIVEC")])
;; For the GPRs we use 3 constraints for register outputs, two that are the
;; same as the output register, and a third where the output register is an
;; early clobber, so we don't have to deal with register overlaps. For the
;; vector types, we prefer to use the vector registers. For TI mode, allow
;; either.
;; Mode attribute for boolean operation register constraints for output
(define_mode_attr BOOL_REGS_OUTPUT [(TI "&r,r,r,wt,v")
(PTI "&r,r,r")
(V16QI "wa,v,&?r,?r,?r")
(V8HI "wa,v,&?r,?r,?r")
(V4SI "wa,v,&?r,?r,?r")
(V4SF "wa,v,&?r,?r,?r")
(V2DI "wa,v,&?r,?r,?r")
(V2DF "wa,v,&?r,?r,?r")
(V1TI "wa,v,&?r,?r,?r")])
;; Mode attribute for boolean operation register constraints for operand1
(define_mode_attr BOOL_REGS_OP1 [(TI "r,0,r,wt,v")
(PTI "r,0,r")
(V16QI "wa,v,r,0,r")
(V8HI "wa,v,r,0,r")
(V4SI "wa,v,r,0,r")
(V4SF "wa,v,r,0,r")
(V2DI "wa,v,r,0,r")
(V2DF "wa,v,r,0,r")
(V1TI "wa,v,r,0,r")])
;; Mode attribute for boolean operation register constraints for operand2
(define_mode_attr BOOL_REGS_OP2 [(TI "r,r,0,wt,v")
(PTI "r,r,0")
(V16QI "wa,v,r,r,0")
(V8HI "wa,v,r,r,0")
(V4SI "wa,v,r,r,0")
(V4SF "wa,v,r,r,0")
(V2DI "wa,v,r,r,0")
(V2DF "wa,v,r,r,0")
(V1TI "wa,v,r,r,0")])
;; Mode attribute for boolean operation register constraints for operand1
;; for one_cmpl. To simplify things, we repeat the constraint where 0
;; is used for operand1 or operand2
(define_mode_attr BOOL_REGS_UNARY [(TI "r,0,0,wt,v")
(PTI "r,0,0")
(V16QI "wa,v,r,0,0")
(V8HI "wa,v,r,0,0")
(V4SI "wa,v,r,0,0")
(V4SF "wa,v,r,0,0")
(V2DI "wa,v,r,0,0")
(V2DF "wa,v,r,0,0")
(V1TI "wa,v,r,0,0")])
;; Reload iterator for creating the function to allocate a base register to
;; supplement addressing modes.
(define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI
SF SD SI DF DD DI TI PTI])
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
(define_insn "zero_extendqi2"
[(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r")
(zero_extend:EXTQI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
""
"@
lbz%U1%X1 %0,%1
rlwinm %0,%1,0,0xff"
[(set_attr "type" "load,shift")])
(define_insn_and_split "*zero_extendqi2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:EXTQI 0 "=r,r"))]
"rs6000_gen_cell_microcode"
"@
andi. %0,%1,0xff
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(zero_extend:EXTQI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*zero_extendqi2_dot2"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r")
(zero_extend:EXTQI (match_dup 1)))]
"rs6000_gen_cell_microcode"
"@
andi. %0,%1,0xff
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(zero_extend:EXTQI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "zero_extendhi2"
[(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
(zero_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
""
"@
lhz%U1%X1 %0,%1
rlwinm %0,%1,0,0xffff"
[(set_attr "type" "load,shift")])
(define_insn_and_split "*zero_extendhi2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:EXTHI 0 "=r,r"))]
"rs6000_gen_cell_microcode"
"@
andi. %0,%1,0xffff
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(zero_extend:EXTHI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*zero_extendhi2_dot2"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
(zero_extend:EXTHI (match_dup 1)))]
"rs6000_gen_cell_microcode"
"@
andi. %0,%1,0xffff
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(zero_extend:EXTHI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "zero_extendsi2"
[(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,??wj,!wz,!wu")
(zero_extend:EXTSI (match_operand:SI 1 "reg_or_mem_operand" "m,r,r,Z,Z")))]
""
"@
lwz%U1%X1 %0,%1
rldicl %0,%1,0,32
mtvsrwz %x0,%1
lfiwzx %0,%y1
lxsiwzx %x0,%y1"
[(set_attr "type" "load,shift,mffgpr,fpload,fpload")])
(define_insn_and_split "*zero_extendsi2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:EXTSI 0 "=r,r"))]
"rs6000_gen_cell_microcode"
"@
rldicl. %0,%1,0,32
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(zero_extend:DI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "shift")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*zero_extendsi2_dot2"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r")
(zero_extend:EXTSI (match_dup 1)))]
"rs6000_gen_cell_microcode"
"@
rldicl. %0,%1,0,32
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(zero_extend:EXTSI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "shift")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "extendqi2"
[(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r")
(sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r")))]
""
"extsb %0,%1"
[(set_attr "type" "exts")])
(define_insn_and_split "*extendqi2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:EXTQI 0 "=r,r"))]
"rs6000_gen_cell_microcode"
"@
extsb. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(sign_extend:EXTQI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "exts")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*extendqi2_dot2"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r")
(sign_extend:EXTQI (match_dup 1)))]
"rs6000_gen_cell_microcode"
"@
extsb. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(sign_extend:EXTQI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "exts")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_expand "extendhi2"
[(set (match_operand:EXTHI 0 "gpc_reg_operand" "")
(sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "")))]
""
"")
(define_insn "*extendhi2"
[(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
(sign_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
"rs6000_gen_cell_microcode"
"@
lha%U1%X1 %0,%1
extsh %0,%1"
[(set_attr "type" "load,exts")
(set_attr "sign_extend" "yes")])
(define_insn "*extendhi2_noload"
[(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r")
(sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r")))]
"!rs6000_gen_cell_microcode"
"extsh %0,%1"
[(set_attr "type" "exts")])
(define_insn_and_split "*extendhi2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:EXTHI 0 "=r,r"))]
"rs6000_gen_cell_microcode"
"@
extsh. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(sign_extend:EXTHI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "exts")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*extendhi2_dot2"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (sign_extend:EXTHI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r")
(sign_extend:EXTHI (match_dup 1)))]
"rs6000_gen_cell_microcode"
"@
extsh. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(sign_extend:EXTHI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "exts")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "extendsi2"
[(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,??wj,!wl,!wu")
(sign_extend:EXTSI (match_operand:SI 1 "lwa_operand" "Y,r,r,Z,Z")))]
""
"@
lwa%U1%X1 %0,%1
extsw %0,%1
mtvsrwa %x0,%1
lfiwax %0,%y1
lxsiwax %x0,%y1"
[(set_attr "type" "load,exts,mffgpr,fpload,fpload")
(set_attr "sign_extend" "yes")])
(define_insn_and_split "*extendsi2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (sign_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:EXTSI 0 "=r,r"))]
"rs6000_gen_cell_microcode"
"@
extsw. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(sign_extend:EXTSI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "exts")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*extendsi2_dot2"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (sign_extend:EXTSI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r")
(sign_extend:EXTSI (match_dup 1)))]
"rs6000_gen_cell_microcode"
"@
extsw. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(sign_extend:EXTSI (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "exts")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
;; IBM 405, 440, 464 and 476 half-word multiplication operations.
(define_insn "*macchwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (plus:SI (mult:SI (ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r")))
(match_operand:SI 4 "gpc_reg_operand" "0"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (ashiftrt:SI
(match_dup 2)
(const_int 16))
(sign_extend:SI
(match_dup 1)))
(match_dup 4)))]
"TARGET_MULHW"
"macchw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*macchw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r")))
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"macchw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*macchwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (plus:SI (mult:SI (lshiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(zero_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r")))
(match_operand:SI 4 "gpc_reg_operand" "0"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (lshiftrt:SI
(match_dup 2)
(const_int 16))
(zero_extend:SI
(match_dup 1)))
(match_dup 4)))]
"TARGET_MULHW"
"macchwu. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*macchwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (lshiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(zero_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r")))
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"macchwu %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*machhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (plus:SI (mult:SI (ashiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16)))
(match_operand:SI 4 "gpc_reg_operand" "0"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (ashiftrt:SI
(match_dup 1)
(const_int 16))
(ashiftrt:SI
(match_dup 2)
(const_int 16)))
(match_dup 4)))]
"TARGET_MULHW"
"machhw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*machhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (ashiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16)))
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"machhw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*machhwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (plus:SI (mult:SI (lshiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(lshiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16)))
(match_operand:SI 4 "gpc_reg_operand" "0"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (lshiftrt:SI
(match_dup 1)
(const_int 16))
(lshiftrt:SI
(match_dup 2)
(const_int 16)))
(match_dup 4)))]
"TARGET_MULHW"
"machhwu. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*machhwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (lshiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(lshiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16)))
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"machhwu %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*maclhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (plus:SI (mult:SI (sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(sign_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r")))
(match_operand:SI 4 "gpc_reg_operand" "0"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (sign_extend:SI
(match_dup 1))
(sign_extend:SI
(match_dup 2)))
(match_dup 4)))]
"TARGET_MULHW"
"maclhw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*maclhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(sign_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r")))
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"maclhw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*maclhwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (plus:SI (mult:SI (zero_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(zero_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r")))
(match_operand:SI 4 "gpc_reg_operand" "0"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (zero_extend:SI
(match_dup 1))
(zero_extend:SI
(match_dup 2)))
(match_dup 4)))]
"TARGET_MULHW"
"maclhwu. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*maclhwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (mult:SI (zero_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(zero_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r")))
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"maclhwu %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*nmacchwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
(mult:SI (ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r"))))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(minus:SI (match_dup 4)
(mult:SI (ashiftrt:SI
(match_dup 2)
(const_int 16))
(sign_extend:SI
(match_dup 1)))))]
"TARGET_MULHW"
"nmacchw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*nmacchw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
(mult:SI (ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r")))))]
"TARGET_MULHW"
"nmacchw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*nmachhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
(mult:SI (ashiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(minus:SI (match_dup 4)
(mult:SI (ashiftrt:SI
(match_dup 1)
(const_int 16))
(ashiftrt:SI
(match_dup 2)
(const_int 16)))))]
"TARGET_MULHW"
"nmachhw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*nmachhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
(mult:SI (ashiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16)))))]
"TARGET_MULHW"
"nmachhw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*nmaclhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
(mult:SI (sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(sign_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r"))))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(minus:SI (match_dup 4)
(mult:SI (sign_extend:SI
(match_dup 1))
(sign_extend:SI
(match_dup 2)))))]
"TARGET_MULHW"
"nmaclhw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*nmaclhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
(mult:SI (sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(sign_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r")))))]
"TARGET_MULHW"
"nmaclhw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mulchwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (mult:SI (ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r")))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (ashiftrt:SI
(match_dup 2)
(const_int 16))
(sign_extend:SI
(match_dup 1))))]
"TARGET_MULHW"
"mulchw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mulchw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r"))))]
"TARGET_MULHW"
"mulchw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mulchwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (mult:SI (lshiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(zero_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r")))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (lshiftrt:SI
(match_dup 2)
(const_int 16))
(zero_extend:SI
(match_dup 1))))]
"TARGET_MULHW"
"mulchwu. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mulchwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (lshiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))
(zero_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "r"))))]
"TARGET_MULHW"
"mulchwu %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mulhhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (mult:SI (ashiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16)))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (ashiftrt:SI
(match_dup 1)
(const_int 16))
(ashiftrt:SI
(match_dup 2)
(const_int 16))))]
"TARGET_MULHW"
"mulhhw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mulhhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (ashiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(ashiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))))]
"TARGET_MULHW"
"mulhhw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mulhhwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (mult:SI (lshiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(lshiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16)))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (lshiftrt:SI
(match_dup 1)
(const_int 16))
(lshiftrt:SI
(match_dup 2)
(const_int 16))))]
"TARGET_MULHW"
"mulhhwu. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mulhhwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (lshiftrt:SI
(match_operand:SI 1 "gpc_reg_operand" "%r")
(const_int 16))
(lshiftrt:SI
(match_operand:SI 2 "gpc_reg_operand" "r")
(const_int 16))))]
"TARGET_MULHW"
"mulhhwu %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mullhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (mult:SI (sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(sign_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r")))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (sign_extend:SI
(match_dup 1))
(sign_extend:SI
(match_dup 2))))]
"TARGET_MULHW"
"mullhw. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mullhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (sign_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(sign_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r"))))]
"TARGET_MULHW"
"mullhw %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mullhwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(compare:CC (mult:SI (zero_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(zero_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r")))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (zero_extend:SI
(match_dup 1))
(zero_extend:SI
(match_dup 2))))]
"TARGET_MULHW"
"mullhwu. %0,%1,%2"
[(set_attr "type" "halfmul")])
(define_insn "*mullhwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mult:SI (zero_extend:SI
(match_operand:HI 1 "gpc_reg_operand" "%r"))
(zero_extend:SI
(match_operand:HI 2 "gpc_reg_operand" "r"))))]
"TARGET_MULHW"
"mullhwu %0,%1,%2"
[(set_attr "type" "halfmul")])
;; IBM 405, 440, 464 and 476 string-search dlmzb instruction support.
(define_insn "dlmzb"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "gpc_reg_operand" "r")]
UNSPEC_DLMZB_CR))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(unspec:SI [(match_dup 1)
(match_dup 2)]
UNSPEC_DLMZB))]
"TARGET_DLMZB"
"dlmzb. %0,%1,%2")
(define_expand "strlensi"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(unspec:SI [(match_operand:BLK 1 "general_operand" "")
(match_operand:QI 2 "const_int_operand" "")
(match_operand 3 "const_int_operand" "")]
UNSPEC_DLMZB_STRLEN))
(clobber (match_scratch:CC 4 "=x"))]
"TARGET_DLMZB && WORDS_BIG_ENDIAN && !optimize_size"
{
rtx result = operands[0];
rtx src = operands[1];
rtx search_char = operands[2];
rtx align = operands[3];
rtx addr, scratch_string, word1, word2, scratch_dlmzb;
rtx loop_label, end_label, mem, cr0, cond;
if (search_char != const0_rtx
|| GET_CODE (align) != CONST_INT
|| INTVAL (align) < 8)
FAIL;
word1 = gen_reg_rtx (SImode);
word2 = gen_reg_rtx (SImode);
scratch_dlmzb = gen_reg_rtx (SImode);
scratch_string = gen_reg_rtx (Pmode);
loop_label = gen_label_rtx ();
end_label = gen_label_rtx ();
addr = force_reg (Pmode, XEXP (src, 0));
emit_move_insn (scratch_string, addr);
emit_label (loop_label);
mem = change_address (src, SImode, scratch_string);
emit_move_insn (word1, mem);
emit_move_insn (word2, adjust_address (mem, SImode, 4));
cr0 = gen_rtx_REG (CCmode, CR0_REGNO);
emit_insn (gen_dlmzb (scratch_dlmzb, word1, word2, cr0));
cond = gen_rtx_NE (VOIDmode, cr0, const0_rtx);
emit_jump_insn (gen_rtx_SET (VOIDmode,
pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode,
cond,
gen_rtx_LABEL_REF
(VOIDmode,
end_label),
pc_rtx)));
emit_insn (gen_addsi3 (scratch_string, scratch_string, GEN_INT (8)));
emit_jump_insn (gen_rtx_SET (VOIDmode,
pc_rtx,
gen_rtx_LABEL_REF (VOIDmode, loop_label)));
emit_barrier ();
emit_label (end_label);
emit_insn (gen_addsi3 (scratch_string, scratch_string, scratch_dlmzb));
emit_insn (gen_subsi3 (result, scratch_string, addr));
emit_insn (gen_addsi3 (result, result, constm1_rtx));
DONE;
})
;; Fixed-point arithmetic insns.
(define_expand "add3"
[(set (match_operand:SDI 0 "gpc_reg_operand" "")
(plus:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
(match_operand:SDI 2 "reg_or_add_cint_operand" "")))]
""
{
if (mode == DImode && !TARGET_POWERPC64)
{
rtx lo0 = gen_lowpart (SImode, operands[0]);
rtx lo1 = gen_lowpart (SImode, operands[1]);
rtx lo2 = gen_lowpart (SImode, operands[2]);
rtx hi0 = gen_highpart (SImode, operands[0]);
rtx hi1 = gen_highpart (SImode, operands[1]);
rtx hi2 = gen_highpart_mode (SImode, DImode, operands[2]);
if (!reg_or_short_operand (lo2, SImode))
lo2 = force_reg (SImode, lo2);
if (!adde_operand (hi2, SImode))
hi2 = force_reg (SImode, hi2);
emit_insn (gen_addsi3_carry (lo0, lo1, lo2));
emit_insn (gen_addsi3_carry_in (hi0, hi1, hi2));
DONE;
}
if (CONST_INT_P (operands[2]) && !add_operand (operands[2], mode))
{
rtx tmp = ((!can_create_pseudo_p ()
|| rtx_equal_p (operands[0], operands[1]))
? operands[0] : gen_reg_rtx (mode));
HOST_WIDE_INT val = INTVAL (operands[2]);
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, mode);
if (mode == DImode && !satisfies_constraint_L (GEN_INT (rest)))
FAIL;
/* The ordering here is important for the prolog expander.
When space is allocated from the stack, adding 'low' first may
produce a temporary deallocation (which would be bad). */
emit_insn (gen_add3 (tmp, operands[1], GEN_INT (rest)));
emit_insn (gen_add3 (operands[0], tmp, GEN_INT (low)));
DONE;
}
})
(define_insn "*add3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
(match_operand:GPR 2 "add_operand" "r,I,L")))]
""
"@
add %0,%1,%2
addi %0,%1,%2
addis %0,%1,%v2"
[(set_attr "type" "add")])
(define_insn "addsi3_high"
[(set (match_operand:SI 0 "gpc_reg_operand" "=b")
(plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
(high:SI (match_operand 2 "" ""))))]
"TARGET_MACHO && !TARGET_64BIT"
"addis %0,%1,ha16(%2)"
[(set_attr "type" "add")])
(define_insn_and_split "*add3_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:GPR 2 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode"
"@
add. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(plus:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "add")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*add3_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:GPR 2 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(plus:GPR (match_dup 1)
(match_dup 2)))]
"mode == Pmode"
"@
add. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(plus:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "add")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*add3_imm_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b")
(match_operand:GPR 2 "short_cint_operand" "I,I"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))
(clobber (reg:GPR CA_REGNO))]
"mode == Pmode"
"@
addic. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(plus:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "add")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*add3_imm_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b")
(match_operand:GPR 2 "short_cint_operand" "I,I"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(plus:GPR (match_dup 1)
(match_dup 2)))
(clobber (reg:GPR CA_REGNO))]
"mode == Pmode"
"@
addic. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(plus:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "add")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
;; Split an add that we can't do in one insn into two insns, each of which
;; does one 16-bit part. This is used by combine. Note that the low-order
;; add should be last in case the result gets used in an address.
(define_split
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
(match_operand:GPR 2 "non_add_cint_operand" "")))]
""
[(set (match_dup 0) (plus:GPR (match_dup 1) (match_dup 3)))
(set (match_dup 0) (plus:GPR (match_dup 0) (match_dup 4)))]
{
HOST_WIDE_INT val = INTVAL (operands[2]);
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, mode);
operands[4] = GEN_INT (low);
if (mode == SImode || satisfies_constraint_L (GEN_INT (rest)))
operands[3] = GEN_INT (rest);
else if (can_create_pseudo_p ())
{
operands[3] = gen_reg_rtx (DImode);
emit_move_insn (operands[3], operands[2]);
emit_insn (gen_adddi3 (operands[0], operands[1], operands[3]));
DONE;
}
else
FAIL;
})
(define_insn "add3_carry"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
(match_operand:P 2 "reg_or_short_operand" "rI")))
(set (reg:P CA_REGNO)
(ltu:P (plus:P (match_dup 1)
(match_dup 2))
(match_dup 1)))]
""
"add%I2c %0,%1,%2"
[(set_attr "type" "add")])
(define_insn "*add3_imm_carry_pos"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
(match_operand:P 2 "short_cint_operand" "n")))
(set (reg:P CA_REGNO)
(geu:P (match_dup 1)
(match_operand:P 3 "const_int_operand" "n")))]
"INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) + INTVAL (operands[3]) == 0"
"addic %0,%1,%2"
[(set_attr "type" "add")])
(define_insn "*add3_imm_carry_0"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(match_operand:P 1 "gpc_reg_operand" "r"))
(set (reg:P CA_REGNO)
(const_int 0))]
""
"addic %0,%1,0"
[(set_attr "type" "add")])
(define_insn "*add3_imm_carry_m1"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
(const_int -1)))
(set (reg:P CA_REGNO)
(ne:P (match_dup 1)
(const_int 0)))]
""
"addic %0,%1,-1"
[(set_attr "type" "add")])
(define_insn "*add3_imm_carry_neg"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
(match_operand:P 2 "short_cint_operand" "n")))
(set (reg:P CA_REGNO)
(gtu:P (match_dup 1)
(match_operand:P 3 "const_int_operand" "n")))]
"INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) + INTVAL (operands[3]) == -1"
"addic %0,%1,%2"
[(set_attr "type" "add")])
(define_expand "add3_carry_in"
[(parallel [
(set (match_operand:GPR 0 "gpc_reg_operand")
(plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand")
(match_operand:GPR 2 "adde_operand"))
(reg:GPR CA_REGNO)))
(clobber (reg:GPR CA_REGNO))])]
""
{
if (operands[2] == const0_rtx)
{
emit_insn (gen_add3_carry_in_0 (operands[0], operands[1]));
DONE;
}
if (operands[2] == constm1_rtx)
{
emit_insn (gen_add3_carry_in_m1 (operands[0], operands[1]));
DONE;
}
})
(define_insn "*add3_carry_in_internal"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "gpc_reg_operand" "r"))
(reg:GPR CA_REGNO)))
(clobber (reg:GPR CA_REGNO))]
""
"adde %0,%1,%2"
[(set_attr "type" "add")])
(define_insn "add3_carry_in_0"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(reg:GPR CA_REGNO)))
(clobber (reg:GPR CA_REGNO))]
""
"addze %0,%1"
[(set_attr "type" "add")])
(define_insn "add3_carry_in_m1"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(reg:GPR CA_REGNO))
(const_int -1)))
(clobber (reg:GPR CA_REGNO))]
""
"addme %0,%1"
[(set_attr "type" "add")])
(define_expand "one_cmpl2"
[(set (match_operand:SDI 0 "gpc_reg_operand" "")
(not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
""
{
if (mode == DImode && !TARGET_POWERPC64)
{
rs6000_split_logical (operands, NOT, false, false, false);
DONE;
}
})
(define_insn "*one_cmpl2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
"not %0,%1")
(define_insn_and_split "*one_cmpl2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
not. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(not:GPR (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*one_cmpl2_dot2"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(not:GPR (match_dup 1)))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
not. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(not:GPR (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_expand "sub3"
[(set (match_operand:SDI 0 "gpc_reg_operand" "")
(minus:SDI (match_operand:SDI 1 "reg_or_short_operand" "")
(match_operand:SDI 2 "gpc_reg_operand" "")))]
""
{
if (mode == DImode && !TARGET_POWERPC64)
{
rtx lo0 = gen_lowpart (SImode, operands[0]);
rtx lo1 = gen_lowpart (SImode, operands[1]);
rtx lo2 = gen_lowpart (SImode, operands[2]);
rtx hi0 = gen_highpart (SImode, operands[0]);
rtx hi1 = gen_highpart_mode (SImode, DImode, operands[1]);
rtx hi2 = gen_highpart (SImode, operands[2]);
if (!reg_or_short_operand (lo1, SImode))
lo1 = force_reg (SImode, lo1);
if (!adde_operand (hi1, SImode))
hi1 = force_reg (SImode, hi1);
emit_insn (gen_subfsi3_carry (lo0, lo2, lo1));
emit_insn (gen_subfsi3_carry_in (hi0, hi2, hi1));
DONE;
}
if (short_cint_operand (operands[1], mode))
{
emit_insn (gen_subf3_imm (operands[0], operands[2], operands[1]));
DONE;
}
})
(define_insn "*subf3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r")
(match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
"subf %0,%1,%2"
[(set_attr "type" "add")])
(define_insn_and_split "*subf3_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r")
(match_operand:GPR 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode"
"@
subf. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(minus:GPR (match_dup 2)
(match_dup 1)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "add")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*subf3_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (minus:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r")
(match_operand:GPR 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(minus:GPR (match_dup 2)
(match_dup 1)))]
"mode == Pmode"
"@
subf. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(minus:GPR (match_dup 2)
(match_dup 1)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "add")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "subf3_imm"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(minus:GPR (match_operand:GPR 2 "short_cint_operand" "I")
(match_operand:GPR 1 "gpc_reg_operand" "r")))
(clobber (reg:GPR CA_REGNO))]
""
"subfic %0,%1,%2"
[(set_attr "type" "add")])
(define_insn "subf3_carry"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(minus:P (match_operand:P 2 "reg_or_short_operand" "rI")
(match_operand:P 1 "gpc_reg_operand" "r")))
(set (reg:P CA_REGNO)
(leu:P (match_dup 1)
(match_dup 2)))]
""
"subf%I2c %0,%1,%2"
[(set_attr "type" "add")])
(define_insn "*subf3_imm_carry_0"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(neg:P (match_operand:P 1 "gpc_reg_operand" "r")))
(set (reg:P CA_REGNO)
(eq:P (match_dup 1)
(const_int 0)))]
""
"subfic %0,%1,0"
[(set_attr "type" "add")])
(define_insn "*subf3_imm_carry_m1"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(not:P (match_operand:P 1 "gpc_reg_operand" "r")))
(set (reg:P CA_REGNO)
(const_int 1))]
""
"subfic %0,%1,-1"
[(set_attr "type" "add")])
(define_expand "subf3_carry_in"
[(parallel [
(set (match_operand:GPR 0 "gpc_reg_operand")
(plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand"))
(reg:GPR CA_REGNO))
(match_operand:GPR 2 "adde_operand")))
(clobber (reg:GPR CA_REGNO))])]
""
{
if (operands[2] == const0_rtx)
{
emit_insn (gen_subf3_carry_in_0 (operands[0], operands[1]));
DONE;
}
if (operands[2] == constm1_rtx)
{
emit_insn (gen_subf3_carry_in_m1 (operands[0], operands[1]));
DONE;
}
})
(define_insn "*subf3_carry_in_internal"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
(reg:GPR CA_REGNO))
(match_operand:GPR 2 "gpc_reg_operand" "r")))
(clobber (reg:GPR CA_REGNO))]
""
"subfe %0,%1,%2"
[(set_attr "type" "add")])
(define_insn "subf3_carry_in_0"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
(reg:GPR CA_REGNO)))
(clobber (reg:GPR CA_REGNO))]
""
"subfze %0,%1"
[(set_attr "type" "add")])
(define_insn "subf3_carry_in_m1"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(plus:GPR (minus:GPR (reg:GPR CA_REGNO)
(match_operand:GPR 1 "gpc_reg_operand" "r"))
(const_int -2)))
(clobber (reg:GPR CA_REGNO))]
""
"subfme %0,%1"
[(set_attr "type" "add")])
(define_insn "subf3_carry_in_xx"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(plus:GPR (reg:GPR CA_REGNO)
(const_int -1)))
(clobber (reg:GPR CA_REGNO))]
""
"subfe %0,%0,%0"
[(set_attr "type" "add")])
(define_insn "neg2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
"neg %0,%1"
[(set_attr "type" "add")])
(define_insn_and_split "*neg2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode"
"@
neg. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(neg:GPR (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "add")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*neg2_dot2"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(neg:GPR (match_dup 1)))]
"mode == Pmode"
"@
neg. %0,%1
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[2], CCmode)"
[(set (match_dup 0)
(neg:GPR (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "add")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "clz2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(clz:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
"cntlz %0,%1"
[(set_attr "type" "cntlz")])
(define_expand "ctz2"
[(set (match_dup 2)
(neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))
(set (match_dup 3)
(and:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 4)
(clz:GPR (match_dup 3)))
(parallel [(set (match_operand:GPR 0 "gpc_reg_operand" "")
(minus:GPR (match_dup 5)
(match_dup 4)))
(clobber (reg:GPR CA_REGNO))])]
""
{
operands[2] = gen_reg_rtx (mode);
operands[3] = gen_reg_rtx (mode);
operands[4] = gen_reg_rtx (mode);
operands[5] = GEN_INT (GET_MODE_BITSIZE (mode) - 1);
})
(define_expand "ffs2"
[(set (match_dup 2)
(neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))
(set (match_dup 3)
(and:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 4)
(clz:GPR (match_dup 3)))
(parallel [(set (match_operand:GPR 0 "gpc_reg_operand" "")
(minus:GPR (match_dup 5)
(match_dup 4)))
(clobber (reg:GPR CA_REGNO))])]
""
{
operands[2] = gen_reg_rtx (mode);
operands[3] = gen_reg_rtx (mode);
operands[4] = gen_reg_rtx (mode);
operands[5] = GEN_INT (GET_MODE_BITSIZE (mode));
})
(define_expand "popcount2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
(popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
"TARGET_POPCNTB || TARGET_POPCNTD"
{
rs6000_emit_popcount (operands[0], operands[1]);
DONE;
})
(define_insn "popcntb2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
UNSPEC_POPCNTB))]
"TARGET_POPCNTB"
"popcntb %0,%1"
[(set_attr "type" "popcnt")])
(define_insn "popcntd2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
"TARGET_POPCNTD"
"popcnt %0,%1"
[(set_attr "type" "popcnt")])
(define_expand "parity2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
(parity:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
"TARGET_POPCNTB"
{
rs6000_emit_parity (operands[0], operands[1]);
DONE;
})
(define_insn "parity2_cmpb"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")] UNSPEC_PARITY))]
"TARGET_CMPB && TARGET_POPCNTB"
"prty %0,%1"
[(set_attr "type" "popcnt")])
;; Since the hardware zeros the upper part of the register, save generating the
;; AND immediate if we are converting to unsigned
(define_insn "*bswaphi2_extenddi"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(zero_extend:DI
(bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
"TARGET_POWERPC64"
"lhbrx %0,%y1"
[(set_attr "length" "4")
(set_attr "type" "load")])
(define_insn "*bswaphi2_extendsi"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(zero_extend:SI
(bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
""
"lhbrx %0,%y1"
[(set_attr "length" "4")
(set_attr "type" "load")])
(define_expand "bswaphi2"
[(parallel [(set (match_operand:HI 0 "reg_or_mem_operand" "")
(bswap:HI
(match_operand:HI 1 "reg_or_mem_operand" "")))
(clobber (match_scratch:SI 2 ""))])]
""
{
if (!REG_P (operands[0]) && !REG_P (operands[1]))
operands[1] = force_reg (HImode, operands[1]);
})
(define_insn "bswaphi2_internal"
[(set (match_operand:HI 0 "reg_or_mem_operand" "=r,Z,&r")
(bswap:HI
(match_operand:HI 1 "reg_or_mem_operand" "Z,r,r")))
(clobber (match_scratch:SI 2 "=X,X,&r"))]
""
"@
lhbrx %0,%y1
sthbrx %1,%y0
#"
[(set_attr "length" "4,4,12")
(set_attr "type" "load,store,*")])
;; We are always BITS_BIG_ENDIAN, so the (const_int 16) below is
;; correct for -mlittle as well as -mbig.
(define_split
[(set (match_operand:HI 0 "gpc_reg_operand" "")
(bswap:HI (match_operand:HI 1 "gpc_reg_operand" "")))
(clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
"reload_completed"
[(set (match_dup 3)
(zero_extract:SI (match_dup 4)
(const_int 8)
(const_int 16)))
(set (match_dup 2)
(and:SI (ashift:SI (match_dup 4)
(const_int 8))
(const_int 65280))) ;; 0xff00
(set (match_dup 3)
(ior:SI (match_dup 3)
(match_dup 2)))]
"
{
operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
}")
(define_insn "*bswapsi2_extenddi"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(zero_extend:DI
(bswap:SI (match_operand:SI 1 "memory_operand" "Z"))))]
"TARGET_POWERPC64"
"lwbrx %0,%y1"
[(set_attr "length" "4")
(set_attr "type" "load")])
(define_expand "bswapsi2"
[(set (match_operand:SI 0 "reg_or_mem_operand" "")
(bswap:SI
(match_operand:SI 1 "reg_or_mem_operand" "")))]
""
{
if (!REG_P (operands[0]) && !REG_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
})
(define_insn "*bswapsi2_internal"
[(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Z,&r")
(bswap:SI
(match_operand:SI 1 "reg_or_mem_operand" "Z,r,r")))]
""
"@
lwbrx %0,%y1
stwbrx %1,%y0
#"
[(set_attr "length" "4,4,12")
(set_attr "type" "load,store,*")])
;; We are always BITS_BIG_ENDIAN, so the bit positions below in
;; zero_extract insns do not change for -mlittle.
(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(bswap:SI (match_operand:SI 1 "gpc_reg_operand" "")))]
"reload_completed"
[(set (match_dup 0)
(rotate:SI (match_dup 1) (const_int 8)))
(set (zero_extract:SI (match_dup 0)
(const_int 8)
(const_int 0))
(match_dup 1))
(set (zero_extract:SI (match_dup 0)
(const_int 8)
(const_int 16))
(rotate:SI (match_dup 1)
(const_int 16)))]
"")
(define_expand "bswapdi2"
[(parallel [(set (match_operand:DI 0 "reg_or_mem_operand" "")
(bswap:DI
(match_operand:DI 1 "reg_or_mem_operand" "")))
(clobber (match_scratch:DI 2 ""))
(clobber (match_scratch:DI 3 ""))])]
""
{
if (!REG_P (operands[0]) && !REG_P (operands[1]))
operands[1] = force_reg (DImode, operands[1]);
if (!TARGET_POWERPC64)
{
/* 32-bit mode needs fewer scratch registers, but 32-bit addressing mode
that uses 64-bit registers needs the same scratch registers as 64-bit
mode. */
emit_insn (gen_bswapdi2_32bit (operands[0], operands[1]));
DONE;
}
})
;; Power7/cell has ldbrx/stdbrx, so use it directly
(define_insn "*bswapdi2_ldbrx"
[(set (match_operand:DI 0 "reg_or_mem_operand" "=r,Z,&r")
(bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
(clobber (match_scratch:DI 2 "=X,X,&r"))
(clobber (match_scratch:DI 3 "=X,X,&r"))]
"TARGET_POWERPC64 && TARGET_LDBRX
&& (REG_P (operands[0]) || REG_P (operands[1]))"
"@
ldbrx %0,%y1
stdbrx %1,%y0
#"
[(set_attr "length" "4,4,36")
(set_attr "type" "load,store,*")])
;; Non-power7/cell, fall back to use lwbrx/stwbrx
(define_insn "*bswapdi2_64bit"
[(set (match_operand:DI 0 "reg_or_mem_operand" "=r,Z,&r")
(bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
(clobber (match_scratch:DI 2 "=&b,&b,&r"))
(clobber (match_scratch:DI 3 "=&r,&r,&r"))]
"TARGET_POWERPC64 && !TARGET_LDBRX
&& (REG_P (operands[0]) || REG_P (operands[1]))
&& !(MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
&& !(MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))"
"#"
[(set_attr "length" "16,12,36")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
(clobber (match_operand:DI 2 "gpc_reg_operand" ""))
(clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
"TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed"
[(const_int 0)]
"
{
rtx dest = operands[0];
rtx src = operands[1];
rtx op2 = operands[2];
rtx op3 = operands[3];
rtx op3_32 = simplify_gen_subreg (SImode, op3, DImode,
BYTES_BIG_ENDIAN ? 4 : 0);
rtx dest_32 = simplify_gen_subreg (SImode, dest, DImode,
BYTES_BIG_ENDIAN ? 4 : 0);
rtx addr1;
rtx addr2;
rtx word1;
rtx word2;
addr1 = XEXP (src, 0);
if (GET_CODE (addr1) == PLUS)
{
emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
if (TARGET_AVOID_XFORM)
{
emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2));
addr2 = op2;
}
else
addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1));
}
else if (TARGET_AVOID_XFORM)
{
emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4)));
addr2 = op2;
}
else
{
emit_move_insn (op2, GEN_INT (4));
addr2 = gen_rtx_PLUS (Pmode, op2, addr1);
}
word1 = change_address (src, SImode, addr1);
word2 = change_address (src, SImode, addr2);
if (BYTES_BIG_ENDIAN)
{
emit_insn (gen_bswapsi2 (op3_32, word2));
emit_insn (gen_bswapsi2 (dest_32, word1));
}
else
{
emit_insn (gen_bswapsi2 (op3_32, word1));
emit_insn (gen_bswapsi2 (dest_32, word2));
}
emit_insn (gen_ashldi3 (op3, op3, GEN_INT (32)));
emit_insn (gen_iordi3 (dest, dest, op3));
DONE;
}")
(define_split
[(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
(clobber (match_operand:DI 2 "gpc_reg_operand" ""))
(clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
"TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed"
[(const_int 0)]
"
{
rtx dest = operands[0];
rtx src = operands[1];
rtx op2 = operands[2];
rtx op3 = operands[3];
rtx src_si = simplify_gen_subreg (SImode, src, DImode,
BYTES_BIG_ENDIAN ? 4 : 0);
rtx op3_si = simplify_gen_subreg (SImode, op3, DImode,
BYTES_BIG_ENDIAN ? 4 : 0);
rtx addr1;
rtx addr2;
rtx word1;
rtx word2;
addr1 = XEXP (dest, 0);
if (GET_CODE (addr1) == PLUS)
{
emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
if (TARGET_AVOID_XFORM)
{
emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2));
addr2 = op2;
}
else
addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1));
}
else if (TARGET_AVOID_XFORM)
{
emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4)));
addr2 = op2;
}
else
{
emit_move_insn (op2, GEN_INT (4));
addr2 = gen_rtx_PLUS (Pmode, op2, addr1);
}
word1 = change_address (dest, SImode, addr1);
word2 = change_address (dest, SImode, addr2);
emit_insn (gen_lshrdi3 (op3, src, GEN_INT (32)));
if (BYTES_BIG_ENDIAN)
{
emit_insn (gen_bswapsi2 (word1, src_si));
emit_insn (gen_bswapsi2 (word2, op3_si));
}
else
{
emit_insn (gen_bswapsi2 (word2, src_si));
emit_insn (gen_bswapsi2 (word1, op3_si));
}
DONE;
}")
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
(clobber (match_operand:DI 2 "gpc_reg_operand" ""))
(clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
"TARGET_POWERPC64 && reload_completed"
[(const_int 0)]
"
{
rtx dest = operands[0];
rtx src = operands[1];
rtx op2 = operands[2];
rtx op3 = operands[3];
int lo_off = BYTES_BIG_ENDIAN ? 4 : 0;
rtx dest_si = simplify_gen_subreg (SImode, dest, DImode, lo_off);
rtx src_si = simplify_gen_subreg (SImode, src, DImode, lo_off);
rtx op2_si = simplify_gen_subreg (SImode, op2, DImode, lo_off);
rtx op3_si = simplify_gen_subreg (SImode, op3, DImode, lo_off);
emit_insn (gen_lshrdi3 (op2, src, GEN_INT (32)));
emit_insn (gen_bswapsi2 (dest_si, src_si));
emit_insn (gen_bswapsi2 (op3_si, op2_si));
emit_insn (gen_ashldi3 (dest, dest, GEN_INT (32)));
emit_insn (gen_iordi3 (dest, dest, op3));
DONE;
}")
(define_insn "bswapdi2_32bit"
[(set (match_operand:DI 0 "reg_or_mem_operand" "=r,Z,?&r")
(bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
(clobber (match_scratch:SI 2 "=&b,&b,X"))]
"!TARGET_POWERPC64 && (REG_P (operands[0]) || REG_P (operands[1]))"
"#"
[(set_attr "length" "16,12,36")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
(clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
"!TARGET_POWERPC64 && reload_completed"
[(const_int 0)]
"
{
rtx dest = operands[0];
rtx src = operands[1];
rtx op2 = operands[2];
rtx dest1 = simplify_gen_subreg (SImode, dest, DImode, 0);
rtx dest2 = simplify_gen_subreg (SImode, dest, DImode, 4);
rtx addr1;
rtx addr2;
rtx word1;
rtx word2;
addr1 = XEXP (src, 0);
if (GET_CODE (addr1) == PLUS)
{
emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
if (TARGET_AVOID_XFORM
|| REGNO (XEXP (addr1, 1)) == REGNO (dest2))
{
emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2));
addr2 = op2;
}
else
addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1));
}
else if (TARGET_AVOID_XFORM
|| REGNO (addr1) == REGNO (dest2))
{
emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4)));
addr2 = op2;
}
else
{
emit_move_insn (op2, GEN_INT (4));
addr2 = gen_rtx_PLUS (SImode, op2, addr1);
}
word1 = change_address (src, SImode, addr1);
word2 = change_address (src, SImode, addr2);
emit_insn (gen_bswapsi2 (dest2, word1));
/* The REGNO (dest2) tests above ensure that addr2 has not been trashed,
thus allowing us to omit an early clobber on the output. */
emit_insn (gen_bswapsi2 (dest1, word2));
DONE;
}")
(define_split
[(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
(clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
"!TARGET_POWERPC64 && reload_completed"
[(const_int 0)]
"
{
rtx dest = operands[0];
rtx src = operands[1];
rtx op2 = operands[2];
rtx src1 = simplify_gen_subreg (SImode, src, DImode, 0);
rtx src2 = simplify_gen_subreg (SImode, src, DImode, 4);
rtx addr1;
rtx addr2;
rtx word1;
rtx word2;
addr1 = XEXP (dest, 0);
if (GET_CODE (addr1) == PLUS)
{
emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
if (TARGET_AVOID_XFORM)
{
emit_insn (gen_add3_insn (op2, XEXP (addr1, 1), op2));
addr2 = op2;
}
else
addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1));
}
else if (TARGET_AVOID_XFORM)
{
emit_insn (gen_add3_insn (op2, addr1, GEN_INT (4)));
addr2 = op2;
}
else
{
emit_move_insn (op2, GEN_INT (4));
addr2 = gen_rtx_PLUS (SImode, op2, addr1);
}
word1 = change_address (dest, SImode, addr1);
word2 = change_address (dest, SImode, addr2);
emit_insn (gen_bswapsi2 (word2, src1));
emit_insn (gen_bswapsi2 (word1, src2));
DONE;
}")
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
(clobber (match_operand:SI 2 "" ""))]
"!TARGET_POWERPC64 && reload_completed"
[(const_int 0)]
"
{
rtx dest = operands[0];
rtx src = operands[1];
rtx src1 = simplify_gen_subreg (SImode, src, DImode, 0);
rtx src2 = simplify_gen_subreg (SImode, src, DImode, 4);
rtx dest1 = simplify_gen_subreg (SImode, dest, DImode, 0);
rtx dest2 = simplify_gen_subreg (SImode, dest, DImode, 4);
emit_insn (gen_bswapsi2 (dest1, src2));
emit_insn (gen_bswapsi2 (dest2, src1));
DONE;
}")
(define_insn "mul3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
(match_operand:GPR 2 "reg_or_short_operand" "r,I")))]
""
"@
mull %0,%1,%2
mulli %0,%1,%2"
[(set_attr "type" "mul")
(set (attr "size")
(cond [(match_operand:GPR 2 "s8bit_cint_operand" "")
(const_string "8")
(match_operand:GPR 2 "short_cint_operand" "")
(const_string "16")]
(const_string "")))])
(define_insn_and_split "*mul3_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:GPR 2 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
mull. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(mult:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "mul")
(set_attr "size" "")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*mul3_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:GPR 2 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(mult:GPR (match_dup 1)
(match_dup 2)))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
mull. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(mult:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "mul")
(set_attr "size" "")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_expand "mul3_highpart"
[(set (match_operand:GPR 0 "gpc_reg_operand")
(subreg:GPR
(mult: (any_extend:
(match_operand:GPR 1 "gpc_reg_operand"))
(any_extend:
(match_operand:GPR 2 "gpc_reg_operand")))
0))]
""
{
if (mode == SImode && TARGET_POWERPC64)
{
emit_insn (gen_mulsi3_highpart_64 (operands[0], operands[1],
operands[2]));
DONE;
}
if (!WORDS_BIG_ENDIAN)
{
emit_insn (gen_mul3_highpart_le (operands[0], operands[1],
operands[2]));
DONE;
}
})
(define_insn "*mul3_highpart"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(subreg:GPR
(mult: (any_extend:
(match_operand:GPR 1 "gpc_reg_operand" "r"))
(any_extend:
(match_operand:GPR 2 "gpc_reg_operand" "r")))
0))]
"WORDS_BIG_ENDIAN && !(mode == SImode && TARGET_POWERPC64)"
"mulh %0,%1,%2"
[(set_attr "type" "mul")
(set_attr "size" "")])
(define_insn "mulsi3_highpart_le"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(subreg:SI
(mult:DI (any_extend:DI
(match_operand:SI 1 "gpc_reg_operand" "r"))
(any_extend:DI
(match_operand:SI 2 "gpc_reg_operand" "r")))
4))]
"!WORDS_BIG_ENDIAN && !TARGET_POWERPC64"
"mulhw %0,%1,%2"
[(set_attr "type" "mul")])
(define_insn "muldi3_highpart_le"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(subreg:DI
(mult:TI (any_extend:TI
(match_operand:DI 1 "gpc_reg_operand" "r"))
(any_extend:TI
(match_operand:DI 2 "gpc_reg_operand" "r")))
8))]
"!WORDS_BIG_ENDIAN && TARGET_POWERPC64"
"mulhd %0,%1,%2"
[(set_attr "type" "mul")
(set_attr "size" "64")])
(define_insn "mulsi3_highpart_64"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(truncate:SI
(lshiftrt:DI
(mult:DI (any_extend:DI
(match_operand:SI 1 "gpc_reg_operand" "r"))
(any_extend:DI
(match_operand:SI 2 "gpc_reg_operand" "r")))
(const_int 32))))]
"TARGET_POWERPC64"
"mulhw %0,%1,%2"
[(set_attr "type" "mul")])
(define_expand "mul3"
[(set (match_operand: 0 "gpc_reg_operand")
(mult: (any_extend:
(match_operand:GPR 1 "gpc_reg_operand"))
(any_extend:
(match_operand:GPR 2 "gpc_reg_operand"))))]
"!(mode == SImode && TARGET_POWERPC64)"
{
rtx l = gen_reg_rtx (mode);
rtx h = gen_reg_rtx (mode);
emit_insn (gen_mul3 (l, operands[1], operands[2]));
emit_insn (gen_mul3_highpart (h, operands[1], operands[2]));
emit_move_insn (gen_lowpart (mode, operands[0]), l);
emit_move_insn (gen_highpart (mode, operands[0]), h);
DONE;
})
(define_insn "udiv3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "gpc_reg_operand" "r")))]
""
"divu %0,%1,%2"
[(set_attr "type" "div")
(set_attr "size" "")])
;; For powers of two we can do sra[wd]i/addze for divide and then adjust for
;; modulus. If it isn't a power of two, force operands into register and do
;; a normal divide.
(define_expand "div3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
(div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
(match_operand:GPR 2 "reg_or_cint_operand" "")))]
""
{
if (CONST_INT_P (operands[2])
&& INTVAL (operands[2]) > 0
&& exact_log2 (INTVAL (operands[2])) >= 0)
{
emit_insn (gen_div3_sra (operands[0], operands[1], operands[2]));
DONE;
}
operands[2] = force_reg (mode, operands[2]);
})
(define_insn "*div3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "gpc_reg_operand" "r")))]
""
"div %0,%1,%2"
[(set_attr "type" "div")
(set_attr "size" "")])
(define_insn "div3_sra"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "exact_log2_cint_operand" "N")))
(clobber (reg:GPR CA_REGNO))]
""
"srai %0,%1,%p2\;addze %0,%0"
[(set_attr "type" "two")
(set_attr "length" "8")])
(define_insn_and_split "*div3_sra_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:GPR 2 "exact_log2_cint_operand" "N,N"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))
(clobber (reg:GPR CA_REGNO))]
"mode == Pmode"
"@
srai %0,%1,%p2\;addze. %0,%0
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(parallel [(set (match_dup 0)
(div:GPR (match_dup 1)
(match_dup 2)))
(clobber (reg:GPR CA_REGNO))])
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "two")
(set_attr "length" "8,12")
(set_attr "cell_micro" "not")])
(define_insn_and_split "*div3_sra_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:GPR 2 "exact_log2_cint_operand" "N,N"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(div:GPR (match_dup 1)
(match_dup 2)))
(clobber (reg:GPR CA_REGNO))]
"mode == Pmode"
"@
srai %0,%1,%p2\;addze. %0,%0
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(parallel [(set (match_dup 0)
(div:GPR (match_dup 1)
(match_dup 2)))
(clobber (reg:GPR CA_REGNO))])
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "two")
(set_attr "length" "8,12")
(set_attr "cell_micro" "not")])
(define_expand "mod3"
[(use (match_operand:GPR 0 "gpc_reg_operand" ""))
(use (match_operand:GPR 1 "gpc_reg_operand" ""))
(use (match_operand:GPR 2 "reg_or_cint_operand" ""))]
""
{
int i;
rtx temp1;
rtx temp2;
if (GET_CODE (operands[2]) != CONST_INT
|| INTVAL (operands[2]) <= 0
|| (i = exact_log2 (INTVAL (operands[2]))) < 0)
FAIL;
temp1 = gen_reg_rtx (mode);
temp2 = gen_reg_rtx (mode);
emit_insn (gen_div3 (temp1, operands[1], operands[2]));
emit_insn (gen_ashl3 (temp2, temp1, GEN_INT (i)));
emit_insn (gen_sub3 (operands[0], operands[1], temp2));
DONE;
})
;; Logical instructions
;; The logical instructions are mostly combined by using match_operator,
;; but the plain AND insns are somewhat different because there is no
;; plain 'andi' (only 'andi.'), no plain 'andis', and there are all
;; those rotate-and-mask operations. Thus, the AND insns come first.
(define_expand "and3"
[(set (match_operand:SDI 0 "gpc_reg_operand" "")
(and:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
(match_operand:SDI 2 "reg_or_cint_operand" "")))]
""
{
if (mode == DImode && !TARGET_POWERPC64)
{
rs6000_split_logical (operands, AND, false, false, false);
DONE;
}
if (logical_const_operand (operands[2], mode)
&& !any_mask_operand (operands[2], mode))
{
if (rs6000_gen_cell_microcode)
{
emit_insn (gen_and3_imm (operands[0], operands[1], operands[2]));
DONE;
}
else
operands[2] = force_reg (mode, operands[2]);
}
if ((mode == DImode && !and64_2_operand (operands[2], mode))
|| (mode != DImode && !and_operand (operands[2], mode)))
operands[2] = force_reg (mode, operands[2]);
})
(define_insn "and3_imm"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r")
(match_operand:GPR 2 "logical_const_operand" "n")))
(clobber (match_scratch:CC 3 "=x"))]
"rs6000_gen_cell_microcode
&& !any_mask_operand (operands[2], mode)"
"andi%e2. %0,%1,%u2"
[(set_attr "type" "logical")
(set_attr "dot" "yes")])
(define_insn_and_split "*and3_imm_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
(match_operand:GPR 2 "logical_const_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))
(clobber (match_scratch:CC 4 "=X,x"))]
"(mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
&& rs6000_gen_cell_microcode
&& !any_mask_operand (operands[2], mode)"
"@
andi%e2. %0,%1,%u2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(parallel [(set (match_dup 0)
(and:GPR (match_dup 1)
(match_dup 2)))
(clobber (match_dup 4))])
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*and3_imm_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
(match_operand:GPR 2 "logical_const_operand" "n,n"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(and:GPR (match_dup 1)
(match_dup 2)))
(clobber (match_scratch:CC 4 "=X,x"))]
"(mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
&& rs6000_gen_cell_microcode
&& !any_mask_operand (operands[2], mode)"
"@
andi%e2. %0,%1,%u2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(parallel [(set (match_dup 0)
(and:GPR (match_dup 1)
(match_dup 2)))
(clobber (match_dup 4))])
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*and3_imm_mask_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
(match_operand:GPR 2 "logical_const_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"(mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
&& rs6000_gen_cell_microcode
&& any_mask_operand (operands[2], mode)"
"@
andi%e2. %0,%1,%u2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(and:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*and3_imm_mask_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
(match_operand:GPR 2 "logical_const_operand" "n,n"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(and:GPR (match_dup 1)
(match_dup 2)))]
"(mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
&& rs6000_gen_cell_microcode
&& any_mask_operand (operands[2], mode)"
"@
andi%e2. %0,%1,%u2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(and:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*and3_mask"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
(match_operand:GPR 2 "any_mask_operand" "S,T")))]
""
"@
rldic%B2 %0,%1,0,%S2
rlwinm %0,%1,0,%m2,%M2"
[(set_attr "type" "shift")])
(define_insn_and_split "*and3_mask_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")
(match_operand:GPR 2 "any_mask_operand" "S,T,S,T"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r,r,r"))]
"(mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
&& rs6000_gen_cell_microcode
&& !logical_const_operand (operands[2], mode)"
"@
rldic%B2. %0,%1,0,%S2
rlwinm. %0,%1,0,%m2,%M2
#
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(and:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "shift")
(set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn_and_split "*and3_mask_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r,r,r")
(match_operand:GPR 2 "any_mask_operand" "S,T,S,T"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r,r")
(and:GPR (match_dup 1)
(match_dup 2)))]
"(mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff)
&& rs6000_gen_cell_microcode
&& !logical_const_operand (operands[2], mode)"
"@
rldic%B2. %0,%1,0,%S2
rlwinm. %0,%1,0,%m2,%M2
#
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(and:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "shift")
(set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "andsi3_internal0_nomc"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
(match_operand:SI 2 "and_operand" "?r,T")))]
"!rs6000_gen_cell_microcode"
"@
and %0,%1,%2
rlwinm %0,%1,0,%m2,%M2"
[(set_attr "type" "logical,shift")])
;; Handle the PowerPC64 rlwinm corner case
(define_insn_and_split "*andsi3_internal6"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(and:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "mask_operand_wrap" "i")))]
"TARGET_POWERPC64"
"#"
"TARGET_POWERPC64"
[(set (match_dup 0)
(and:SI (rotate:SI (match_dup 1) (match_dup 3))
(match_dup 4)))
(set (match_dup 0)
(rotate:SI (match_dup 0) (match_dup 5)))]
"
{
int mb = extract_MB (operands[2]);
int me = extract_ME (operands[2]);
operands[3] = GEN_INT (me + 1);
operands[5] = GEN_INT (32 - (me + 1));
operands[4] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
}"
[(set_attr "length" "8")])
(define_expand "3"
[(set (match_operand:SDI 0 "gpc_reg_operand" "")
(iorxor:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
(match_operand:SDI 2 "reg_or_cint_operand" "")))]
""
{
if (mode == DImode && !TARGET_POWERPC64)
{
rs6000_split_logical (operands, , false, false, false);
DONE;
}
if (non_logical_cint_operand (operands[2], mode))
{
rtx tmp = ((!can_create_pseudo_p ()
|| rtx_equal_p (operands[0], operands[1]))
? operands[0] : gen_reg_rtx (mode));
HOST_WIDE_INT value = INTVAL (operands[2]);
HOST_WIDE_INT lo = value & 0xffff;
HOST_WIDE_INT hi = value - lo;
emit_insn (gen_3 (tmp, operands[1], GEN_INT (hi)));
emit_insn (gen_3 (operands[0], tmp, GEN_INT (lo)));
DONE;
}
if (!reg_or_logical_cint_operand (operands[2], mode))
operands[2] = force_reg (mode, operands[2]);
})
(define_split
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
(iorxor:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
(match_operand:GPR 2 "non_logical_cint_operand" "")))]
""
[(set (match_dup 3)
(iorxor:GPR (match_dup 1)
(match_dup 4)))
(set (match_dup 0)
(iorxor:GPR (match_dup 3)
(match_dup 5)))]
{
operands[3] = ((!can_create_pseudo_p ()
|| rtx_equal_p (operands[0], operands[1]))
? operands[0] : gen_reg_rtx (mode));
HOST_WIDE_INT value = INTVAL (operands[2]);
HOST_WIDE_INT lo = value & 0xffff;
HOST_WIDE_INT hi = value - lo;
operands[4] = GEN_INT (hi);
operands[5] = GEN_INT (lo);
})
(define_insn "*bool3_imm"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(match_operator:GPR 3 "boolean_or_operator"
[(match_operand:GPR 1 "gpc_reg_operand" "%r")
(match_operand:GPR 2 "logical_const_operand" "n")]))]
""
"%q3i%e2 %0,%1,%u2"
[(set_attr "type" "logical")])
(define_insn "*bool3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(match_operator:GPR 3 "boolean_operator"
[(match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "gpc_reg_operand" "r")]))]
""
"%q3 %0,%1,%2"
[(set_attr "type" "logical")])
(define_insn_and_split "*bool3_dot"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (match_operator:GPR 3 "boolean_operator"
[(match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:GPR 2 "gpc_reg_operand" "r,r")])
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
%q3. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
[(set (match_dup 0)
(match_dup 3))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*bool3_dot2"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (match_operator:GPR 3 "boolean_operator"
[(match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:GPR 2 "gpc_reg_operand" "r,r")])
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(match_dup 3))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
%q3. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
[(set (match_dup 0)
(match_dup 3))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*boolc3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(match_operator:GPR 3 "boolean_operator"
[(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r"))
(match_operand:GPR 1 "gpc_reg_operand" "r")]))]
""
"%q3 %0,%1,%2"
[(set_attr "type" "logical")])
(define_insn_and_split "*boolc3_dot"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (match_operator:GPR 3 "boolean_operator"
[(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
(match_operand:GPR 1 "gpc_reg_operand" "r,r")])
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
%q3. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
[(set (match_dup 0)
(match_dup 3))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*boolc3_dot2"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (match_operator:GPR 3 "boolean_operator"
[(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
(match_operand:GPR 1 "gpc_reg_operand" "r,r")])
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(match_dup 3))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
%q3. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
[(set (match_dup 0)
(match_dup 3))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*boolcc3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(match_operator:GPR 3 "boolean_operator"
[(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r"))]))]
""
"%q3 %0,%1,%2"
[(set_attr "type" "logical")])
(define_insn_and_split "*boolcc3_dot"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (match_operator:GPR 3 "boolean_operator"
[(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))])
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
%q3. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
[(set (match_dup 0)
(match_dup 3))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*boolcc3_dot2"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (match_operator:GPR 3 "boolean_operator"
[(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
(not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r,r"))])
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(match_dup 3))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
%q3. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[4], CCmode)"
[(set (match_dup 0)
(match_dup 3))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "logical")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
;; TODO: Should have dots of this as well.
(define_insn "*eqv3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(not:GPR (xor:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "gpc_reg_operand" "r"))))]
""
"eqv %0,%1,%2"
[(set_attr "type" "logical")])
;; Rotate and shift insns, in all their variants. These support shifts,
;; field inserts and extracts, and various combinations thereof.
(define_expand "insv"
[(set (zero_extract (match_operand 0 "gpc_reg_operand" "")
(match_operand:SI 1 "const_int_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand 3 "gpc_reg_operand" ""))]
""
"
{
/* Do not handle 16/8 bit structures that fit in HI/QI modes directly, since
the (SUBREG:SI (REG:HI xxx)) that is otherwise generated can confuse the
compiler if the address of the structure is taken later. Likewise, do
not handle invalid E500 subregs. */
if (GET_CODE (operands[0]) == SUBREG
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD
|| ((TARGET_E500_DOUBLE || TARGET_SPE)
&& invalid_e500_subreg (operands[0], GET_MODE (operands[0])))))
FAIL;
if (TARGET_POWERPC64 && GET_MODE (operands[0]) == DImode)
emit_insn (gen_insvdi_internal (operands[0], operands[1], operands[2],
operands[3]));
else
emit_insn (gen_insvsi_internal (operands[0], operands[1], operands[2],
operands[3]));
DONE;
}")
(define_insn "insvsi_internal"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:SI 3 "gpc_reg_operand" "r"))]
""
"*
{
int start = INTVAL (operands[2]) & 31;
int size = INTVAL (operands[1]) & 31;
operands[4] = GEN_INT (32 - start - size);
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
[(set_attr "type" "insert")])
(define_insn "*insvsi_internal1"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(rotate:SI (match_operand:SI 3 "gpc_reg_operand" "r")
(match_operand:SI 4 "const_int_operand" "i")))]
"(32 - (INTVAL (operands[4]) & 31)) >= INTVAL (operands[1])"
"*
{
int shift = INTVAL (operands[4]) & 31;
int start = INTVAL (operands[2]) & 31;
int size = INTVAL (operands[1]) & 31;
operands[4] = GEN_INT (shift - start - size);
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
[(set_attr "type" "insert")])
(define_insn "*insvsi_internal2"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(ashiftrt:SI (match_operand:SI 3 "gpc_reg_operand" "r")
(match_operand:SI 4 "const_int_operand" "i")))]
"(32 - (INTVAL (operands[4]) & 31)) >= INTVAL (operands[1])"
"*
{
int shift = INTVAL (operands[4]) & 31;
int start = INTVAL (operands[2]) & 31;
int size = INTVAL (operands[1]) & 31;
operands[4] = GEN_INT (32 - shift - start - size);
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
[(set_attr "type" "insert")])
(define_insn "*insvsi_internal3"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(lshiftrt:SI (match_operand:SI 3 "gpc_reg_operand" "r")
(match_operand:SI 4 "const_int_operand" "i")))]
"(32 - (INTVAL (operands[4]) & 31)) >= INTVAL (operands[1])"
"*
{
int shift = INTVAL (operands[4]) & 31;
int start = INTVAL (operands[2]) & 31;
int size = INTVAL (operands[1]) & 31;
operands[4] = GEN_INT (32 - shift - start - size);
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
[(set_attr "type" "insert")])
(define_insn "*insvsi_internal4"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(zero_extract:SI (match_operand:SI 3 "gpc_reg_operand" "r")
(match_operand:SI 4 "const_int_operand" "i")
(match_operand:SI 5 "const_int_operand" "i")))]
"INTVAL (operands[4]) >= INTVAL (operands[1])"
"*
{
int extract_start = INTVAL (operands[5]) & 31;
int extract_size = INTVAL (operands[4]) & 31;
int insert_start = INTVAL (operands[2]) & 31;
int insert_size = INTVAL (operands[1]) & 31;
/* Align extract field with insert field */
operands[5] = GEN_INT (extract_start + extract_size - insert_start - insert_size);
operands[1] = GEN_INT (insert_start + insert_size - 1);
return \"rlwimi %0,%3,%h5,%h2,%h1\";
}"
[(set_attr "type" "insert")])
;; combine patterns for rlwimi
(define_insn "*insvsi_internal5"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(ior:SI (and:SI (match_operand:SI 4 "gpc_reg_operand" "0")
(match_operand:SI 1 "mask_operand" "i"))
(and:SI (lshiftrt:SI (match_operand:SI 3 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:SI 5 "mask_operand" "i"))))]
"INTVAL(operands[1]) == ~INTVAL(operands[5])"
"*
{
int me = extract_ME(operands[5]);
int mb = extract_MB(operands[5]);
operands[4] = GEN_INT(32 - INTVAL(operands[2]));
operands[2] = GEN_INT(mb);
operands[1] = GEN_INT(me);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
[(set_attr "type" "insert")])
(define_insn "*insvsi_internal6"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(ior:SI (and:SI (lshiftrt:SI (match_operand:SI 3 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:SI 5 "mask_operand" "i"))
(and:SI (match_operand:SI 4 "gpc_reg_operand" "0")
(match_operand:SI 1 "mask_operand" "i"))))]
"INTVAL(operands[1]) == ~INTVAL(operands[5])"
"*
{
int me = extract_ME(operands[5]);
int mb = extract_MB(operands[5]);
operands[4] = GEN_INT(32 - INTVAL(operands[2]));
operands[2] = GEN_INT(mb);
operands[1] = GEN_INT(me);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
[(set_attr "type" "insert")])
(define_insn "insvdi_internal"
[(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:DI 3 "gpc_reg_operand" "r"))]
"TARGET_POWERPC64"
"*
{
int start = INTVAL (operands[2]) & 63;
int size = INTVAL (operands[1]) & 63;
operands[1] = GEN_INT (64 - start - size);
return \"rldimi %0,%3,%H1,%H2\";
}"
[(set_attr "type" "insert")
(set_attr "size" "64")])
(define_insn "*insvdi_internal2"
[(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(ashiftrt:DI (match_operand:DI 3 "gpc_reg_operand" "r")
(match_operand:SI 4 "const_int_operand" "i")))]
"TARGET_POWERPC64
&& insvdi_rshift_rlwimi_p (operands[1], operands[2], operands[4])"
"*
{
int shift = INTVAL (operands[4]) & 63;
int start = (INTVAL (operands[2]) & 63) - 32;
int size = INTVAL (operands[1]) & 63;
operands[4] = GEN_INT (64 - shift - start - size);
operands[2] = GEN_INT (start);
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}")
(define_insn "*insvdi_internal3"
[(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(lshiftrt:DI (match_operand:DI 3 "gpc_reg_operand" "r")
(match_operand:SI 4 "const_int_operand" "i")))]
"TARGET_POWERPC64
&& insvdi_rshift_rlwimi_p (operands[1], operands[2], operands[4])"
"*
{
int shift = INTVAL (operands[4]) & 63;
int start = (INTVAL (operands[2]) & 63) - 32;
int size = INTVAL (operands[1]) & 63;
operands[4] = GEN_INT (64 - shift - start - size);
operands[2] = GEN_INT (start);
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}")
(define_expand "extzv"
[(set (match_operand 0 "gpc_reg_operand" "")
(zero_extract (match_operand 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" "")))]
""
"
{
/* Do not handle 16/8 bit structures that fit in HI/QI modes directly, since
the (SUBREG:SI (REG:HI xxx)) that is otherwise generated can confuse the
compiler if the address of the structure is taken later. */
if (GET_CODE (operands[0]) == SUBREG
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD))
FAIL;
if (TARGET_POWERPC64 && GET_MODE (operands[1]) == DImode)
emit_insn (gen_extzvdi_internal (operands[0], operands[1], operands[2],
operands[3]));
else
emit_insn (gen_extzvsi_internal (operands[0], operands[1], operands[2],
operands[3]));
DONE;
}")
(define_insn "extzvsi_internal"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i")))]
""
"*
{
int start = INTVAL (operands[3]) & 31;
int size = INTVAL (operands[2]) & 31;
if (start + size >= 32)
operands[3] = const0_rtx;
else
operands[3] = GEN_INT (start + size);
return \"rlwinm %0,%1,%3,%s2,31\";
}"
[(set_attr "type" "shift")])
(define_insn "*extzvsi_internal1"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i")
(match_operand:SI 3 "const_int_operand" "i,i"))
(const_int 0)))
(clobber (match_scratch:SI 4 "=r,r"))]
""
"*
{
int start = INTVAL (operands[3]) & 31;
int size = INTVAL (operands[2]) & 31;
/* Force split for non-cc0 compare. */
if (which_alternative == 1)
return \"#\";
/* If the bit-field being tested fits in the upper or lower half of a
word, it is possible to use andiu. or andil. to test it. This is
useful because the condition register set-use delay is smaller for
andi[ul]. than for rlinm. This doesn't work when the starting bit
position is 0 because the LT and GT bits may be set wrong. */
if ((start > 0 && start + size <= 16) || start >= 16)
{
operands[3] = GEN_INT (((1 << (16 - (start & 15)))
- (1 << (16 - (start & 15) - size))));
if (start < 16)
return \"andis. %4,%1,%3\";
else
return \"andi. %4,%1,%3\";
}
if (start + size >= 32)
operands[3] = const0_rtx;
else
operands[3] = GEN_INT (start + size);
return \"rlwinm. %4,%1,%3,%s2,31\";
}"
[(set_attr "type" "shift")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 4 ""))]
"reload_completed"
[(set (match_dup 4)
(zero_extract:SI (match_dup 1) (match_dup 2)
(match_dup 3)))
(set (match_dup 0)
(compare:CC (match_dup 4)
(const_int 0)))]
"")
(define_insn "*extzvsi_internal2"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i")
(match_operand:SI 3 "const_int_operand" "i,i"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
""
"*
{
int start = INTVAL (operands[3]) & 31;
int size = INTVAL (operands[2]) & 31;
/* Force split for non-cc0 compare. */
if (which_alternative == 1)
return \"#\";
/* Since we are using the output value, we can't ignore any need for
a shift. The bit-field must end at the LSB. */
if (start >= 16 && start + size == 32)
{
operands[3] = GEN_INT ((1 << size) - 1);
return \"andi. %0,%1,%3\";
}
if (start + size >= 32)
operands[3] = const0_rtx;
else
operands[3] = GEN_INT (start + size);
return \"rlwinm. %0,%1,%3,%s2,31\";
}"
[(set_attr "type" "shift")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" ""))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
"reload_completed"
[(set (match_dup 0)
(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
(define_insn "extzvdi_internal"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(zero_extract:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i")))]
"TARGET_POWERPC64"
"*
{
int start = INTVAL (operands[3]) & 63;
int size = INTVAL (operands[2]) & 63;
if (start + size >= 64)
operands[3] = const0_rtx;
else
operands[3] = GEN_INT (start + size);
operands[2] = GEN_INT (64 - size);
return \"rldicl %0,%1,%3,%2\";
}"
[(set_attr "type" "shift")])
(define_insn "*extzvdi_internal1"
[(set (match_operand:CC 0 "gpc_reg_operand" "=x")
(compare:CC (zero_extract:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r"))]
"TARGET_64BIT && rs6000_gen_cell_microcode"
"*
{
int start = INTVAL (operands[3]) & 63;
int size = INTVAL (operands[2]) & 63;
if (start + size >= 64)
operands[3] = const0_rtx;
else
operands[3] = GEN_INT (start + size);
operands[2] = GEN_INT (64 - size);
return \"rldicl. %4,%1,%3,%2\";
}"
[(set_attr "type" "shift")
(set_attr "dot" "yes")])
(define_insn "*extzvdi_internal2"
[(set (match_operand:CC 4 "gpc_reg_operand" "=x")
(compare:CC (zero_extract:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(zero_extract:DI (match_dup 1) (match_dup 2) (match_dup 3)))]
"TARGET_64BIT && rs6000_gen_cell_microcode"
"*
{
int start = INTVAL (operands[3]) & 63;
int size = INTVAL (operands[2]) & 63;
if (start + size >= 64)
operands[3] = const0_rtx;
else
operands[3] = GEN_INT (start + size);
operands[2] = GEN_INT (64 - size);
return \"rldicl. %0,%1,%3,%2\";
}"
[(set_attr "type" "shift")
(set_attr "dot" "yes")])
(define_insn "rotl3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "rn")))]
""
"rotl%I2 %0,%1,%2"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")])
(define_insn "*rotlsi3_64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(zero_extend:DI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
"TARGET_POWERPC64"
"rotlw%I2 %0,%1,%h2"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")])
(define_insn_and_split "*rotl3_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
rotl%I2. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(rotate:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*rotl3_dot2"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
(const_int 0)))
(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(rotate:GPR (match_dup 1)
(match_dup 2)))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
rotl%I2. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(rotate:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*rotlsi3_internal4"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(and:SI (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "rn"))
(match_operand:SI 3 "mask_operand" "n")))]
""
"rlw%I2nm %0,%1,%h2,%m3,%M3"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")])
(define_insn "*rotlsi3_internal5"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC (and:SI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
(match_operand:SI 3 "mask_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:SI 4 "=r,r"))]
""
"@
rlw%I2nm. %4,%1,%h2,%m3,%M3
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (and:SI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" ""))
(match_operand:SI 3 "mask_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 4 ""))]
"reload_completed"
[(set (match_dup 4)
(and:SI (rotate:SI (match_dup 1)
(match_dup 2))
(match_dup 3)))
(set (match_dup 0)
(compare:CC (match_dup 4)
(const_int 0)))]
"")
(define_insn "*rotlsi3_internal6"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC (and:SI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
(match_operand:SI 3 "mask_operand" "n,n"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(and:SI (rotate:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
""
"@
rlw%I2nm. %0,%1,%h2,%m3,%M3
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (and:SI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" ""))
(match_operand:SI 3 "mask_operand" ""))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(and:SI (rotate:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
"reload_completed"
[(set (match_dup 0)
(and:SI (rotate:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
(set (match_dup 4)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
(define_insn "*rotlsi3_internal7le"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "ri")) 0)))]
"!BYTES_BIG_ENDIAN"
"rlw%I2nm %0,%1,%h2,0xff"
[(set (attr "cell_micro")
(if_then_else (match_operand:SI 2 "const_int_operand" "")
(const_string "not")
(const_string "always")))
(set_attr "type" "shift")])
(define_insn "*rotlsi3_internal7be"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "ri")) 3)))]
"BYTES_BIG_ENDIAN"
"rlw%I2nm %0,%1,%h2,0xff"
[(set (attr "cell_micro")
(if_then_else (match_operand:SI 2 "const_int_operand" "")
(const_string "not")
(const_string "always")))
(set_attr "type" "shift")])
(define_insn "*rotlsi3_internal8le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 0))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
"!BYTES_BIG_ENDIAN"
"@
rlw%I2nm. %3,%1,%h2,0xff
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*rotlsi3_internal8be"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 3))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
"BYTES_BIG_ENDIAN"
"@
rlw%I2nm. %3,%1,%h2,0xff
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")) 0))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
"!BYTES_BIG_ENDIAN && reload_completed"
[(set (match_dup 3)
(zero_extend:SI (subreg:QI
(rotate:SI (match_dup 1)
(match_dup 2)) 0)))
(set (match_dup 0)
(compare:CC (match_dup 3)
(const_int 0)))]
"")
(define_split
[(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")) 3))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
"BYTES_BIG_ENDIAN && reload_completed"
[(set (match_dup 3)
(zero_extend:SI (subreg:QI
(rotate:SI (match_dup 1)
(match_dup 2)) 3)))
(set (match_dup 0)
(compare:CC (match_dup 3)
(const_int 0)))]
"")
(define_insn "*rotlsi3_internal9le"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 0))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 0)))]
"!BYTES_BIG_ENDIAN"
"@
rlw%I2nm. %0,%1,%h2,0xff
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*rotlsi3_internal9be"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 3))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 3)))]
"BYTES_BIG_ENDIAN"
"@
rlw%I2nm. %0,%1,%h2,0xff
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")) 0))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 0)))]
"!BYTES_BIG_ENDIAN && reload_completed"
[(set (match_dup 0)
(zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 0)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
(define_split
[(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extend:SI
(subreg:QI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")) 3))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 3)))]
"BYTES_BIG_ENDIAN && reload_completed"
[(set (match_dup 0)
(zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 3)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
(define_insn "*rotlsi3_internal10le"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "rn")) 0)))]
"!BYTES_BIG_ENDIAN"
"rlw%I2nm %0,%1,%h2,0xffff"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")])
(define_insn "*rotlsi3_internal10be"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "rn")) 2)))]
"BYTES_BIG_ENDIAN"
"rlw%I2nm %0,%1,%h2,0xffff"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")])
(define_insn "*rotlsi3_internal11le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 0))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
"!BYTES_BIG_ENDIAN"
"@
rlw%I2nm. %3,%1,%h2,0xffff
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*rotlsi3_internal11be"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 2))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
"BYTES_BIG_ENDIAN"
"@
rlw%I2nm. %3,%1,%h2,0xffff
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")) 0))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
"!BYTES_BIG_ENDIAN && reload_completed"
[(set (match_dup 3)
(zero_extend:SI (subreg:HI
(rotate:SI (match_dup 1)
(match_dup 2)) 0)))
(set (match_dup 0)
(compare:CC (match_dup 3)
(const_int 0)))]
"")
(define_split
[(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")) 2))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
"BYTES_BIG_ENDIAN && reload_completed"
[(set (match_dup 3)
(zero_extend:SI (subreg:HI
(rotate:SI (match_dup 1)
(match_dup 2)) 2)))
(set (match_dup 0)
(compare:CC (match_dup 3)
(const_int 0)))]
"")
(define_insn "*rotlsi3_internal12le"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 0))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 0)))]
"!BYTES_BIG_ENDIAN"
"@
rlw%I2nm. %0,%1,%h2,0xffff
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*rotlsi3_internal12be"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn")) 2))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 2)))]
"BYTES_BIG_ENDIAN"
"@
rlw%I2nm. %0,%1,%h2,0xffff
#"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")) 0))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 0)))]
"!BYTES_BIG_ENDIAN && reload_completed"
[(set (match_dup 0)
(zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 0)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
(define_split
[(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (zero_extend:SI
(subreg:HI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")) 2))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 2)))]
"BYTES_BIG_ENDIAN && reload_completed"
[(set (match_dup 0)
(zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
(define_insn "ashl3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "rn")))]
""
"sl%I2 %0,%1,%2"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")])
(define_insn "*ashlsi3_64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(zero_extend:DI
(ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "rn"))))]
"TARGET_POWERPC64"
"slw%I2 %0,%1,%h2"
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")])
(define_insn_and_split "*ashl3_dot"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
(const_int 0)))
(clobber (match_scratch:GPR 0 "=r,r"))]
"mode == Pmode && rs6000_gen_cell_microcode"
"@
sl%I2. %0,%1,%2
#"
"&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
[(set (match_dup 0)
(ashift:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
""
[(set_attr "type" "shift")
(set_attr "maybe_var_shift" "yes")
(set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn_and_split "*ashl