arm.md revision 169689
190075Sobrien;;- Machine description for ARM for GNU compiler 290075Sobrien;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000, 3169689Skan;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 490075Sobrien;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) 590075Sobrien;; and Martin Simmons (@harleqn.co.uk). 690075Sobrien;; More major hacks by Richard Earnshaw (rearnsha@arm.com). 790075Sobrien 8132718Skan;; This file is part of GCC. 990075Sobrien 10132718Skan;; GCC is free software; you can redistribute it and/or modify it 11132718Skan;; under the terms of the GNU General Public License as published 12132718Skan;; by the Free Software Foundation; either version 2, or (at your 13132718Skan;; option) any later version. 1490075Sobrien 15132718Skan;; GCC is distributed in the hope that it will be useful, but WITHOUT 16132718Skan;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17132718Skan;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 18132718Skan;; License for more details. 1990075Sobrien 2090075Sobrien;; You should have received a copy of the GNU General Public License 21132718Skan;; along with GCC; see the file COPYING. If not, write to 22169689Skan;; the Free Software Foundation, 51 Franklin Street, Fifth Floor, 23169689Skan;; Boston, MA 02110-1301, USA. 2490075Sobrien 2590075Sobrien;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. 2690075Sobrien 2790075Sobrien 2890075Sobrien;;--------------------------------------------------------------------------- 2990075Sobrien;; Constants 3090075Sobrien 3190075Sobrien;; Register numbers 3290075Sobrien(define_constants 33169689Skan [(R0_REGNUM 0) ; First CORE register 34169689Skan (IP_REGNUM 12) ; Scratch register 3590075Sobrien (SP_REGNUM 13) ; Stack pointer 3690075Sobrien (LR_REGNUM 14) ; Return address register 3790075Sobrien (PC_REGNUM 15) ; Program counter 3890075Sobrien (CC_REGNUM 24) ; Condition code pseudo register 39169689Skan (LAST_ARM_REGNUM 15) ; 40169689Skan (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM 41169689Skan (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM 4290075Sobrien ] 4390075Sobrien) 44132718Skan;; 3rd operand to select_dominance_cc_mode 45132718Skan(define_constants 46132718Skan [(DOM_CC_X_AND_Y 0) 47132718Skan (DOM_CC_NX_OR_Y 1) 48132718Skan (DOM_CC_X_OR_Y 2) 49132718Skan ] 50132718Skan) 5190075Sobrien 5290075Sobrien;; UNSPEC Usage: 5390075Sobrien;; Note: sin and cos are no-longer used. 5490075Sobrien 5590075Sobrien(define_constants 5690075Sobrien [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT): 5790075Sobrien ; operand 0 is the result, 5890075Sobrien ; operand 1 the parameter. 5990075Sobrien (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT): 6090075Sobrien ; operand 0 is the result, 6190075Sobrien ; operand 1 the parameter. 6290075Sobrien (UNSPEC_PUSH_MULT 2) ; `push multiple' operation: 6390075Sobrien ; operand 0 is the first register, 6490075Sobrien ; subsequent registers are in parallel (use ...) 6590075Sobrien ; expressions. 6690075Sobrien (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic 6790075Sobrien ; usage, that is, we will add the pic_register 6890075Sobrien ; value to it before trying to dereference it. 69117395Skan (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the 70117395Skan ; GLOBAL_OFFSET_TABLE. The operation is fully 71117395Skan ; described by the RTL but must be wrapped to 72117395Skan ; prevent combine from trying to rip it apart. 73117395Skan (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses 7490075Sobrien ; being scheduled before the stack adjustment insn. 7590075Sobrien (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload, 7690075Sobrien ; this unspec is used to prevent the deletion of 7790075Sobrien ; instructions setting registers for EH handling 7890075Sobrien ; and stack frame generation. Operand 0 is the 7990075Sobrien ; register to "use". 80117395Skan (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode. 81132718Skan (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction. 82132718Skan (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction. 83132718Skan (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction. 84132718Skan (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction. 85132718Skan (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction. 86132718Skan (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction. 87132718Skan (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction. 88132718Skan (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction. 89132718Skan (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction. 90132718Skan (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction. 91132718Skan (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction. 92132718Skan (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction. 93169689Skan (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage. 94169689Skan (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the 95169689Skan ; instruction stream. 9690075Sobrien ] 9790075Sobrien) 9890075Sobrien 9990075Sobrien;; UNSPEC_VOLATILE Usage: 10090075Sobrien 10190075Sobrien(define_constants 10290075Sobrien [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an 10390075Sobrien ; insn in the code. 10490075Sobrien (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the 10590075Sobrien ; instruction epilogue sequence that isn't expanded 10690075Sobrien ; into normal RTL. Used for both normal and sibcall 10790075Sobrien ; epilogues. 10890075Sobrien (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table 10990075Sobrien ; for inlined constants. 11090075Sobrien (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool 11190075Sobrien ; table. 11290075Sobrien (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for 11390075Sobrien ; an 8-bit object. 11490075Sobrien (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for 11590075Sobrien ; a 16-bit object. 11690075Sobrien (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for 11790075Sobrien ; a 32-bit object. 11890075Sobrien (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for 11990075Sobrien ; a 64-bit object. 120132718Skan (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction. 121132718Skan (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction. 122132718Skan (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN 123132718Skan (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions 124132718Skan (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions 125132718Skan (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions 126169689Skan (VUNSPEC_EH_RETURN 20); Use to override the return address for exception 127169689Skan ; handling. 12890075Sobrien ] 12990075Sobrien) 13090075Sobrien 13190075Sobrien;;--------------------------------------------------------------------------- 13290075Sobrien;; Attributes 13390075Sobrien 13490075Sobrien; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when 13590075Sobrien; generating ARM code. This is used to control the length of some insn 13690075Sobrien; patterns that share the same RTL in both ARM and Thumb code. 13790075Sobrien(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) 13890075Sobrien 13990075Sobrien; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects 14090075Sobrien; scheduling decisions for the load unit and the multiplier. 141169689Skan(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm"))) 14290075Sobrien 143169689Skan; IS_XSCALE is set to 'yes' when compiling for XScale. 144169689Skan(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale"))) 145169689Skan 14690075Sobrien;; Operand number of an input operand that is shifted. Zero if the 14790075Sobrien;; given instruction does not shift one of its input operands. 14890075Sobrien(define_attr "shift" "" (const_int 0)) 14990075Sobrien 15090075Sobrien; Floating Point Unit. If we only have floating point emulation, then there 15190075Sobrien; is no point in scheduling the floating point insns. (Well, for best 15290075Sobrien; performance we should try and group them together). 153169689Skan(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp" 154132718Skan (const (symbol_ref "arm_fpu_attr"))) 15590075Sobrien 15690075Sobrien; LENGTH of an instruction (in bytes) 15790075Sobrien(define_attr "length" "" (const_int 4)) 15890075Sobrien 15990075Sobrien; POOL_RANGE is how far away from a constant pool entry that this insn 16090075Sobrien; can be placed. If the distance is zero, then this insn will never 16190075Sobrien; reference the pool. 16290075Sobrien; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry 16390075Sobrien; before its address. 16490075Sobrien(define_attr "pool_range" "" (const_int 0)) 16590075Sobrien(define_attr "neg_pool_range" "" (const_int 0)) 16690075Sobrien 16790075Sobrien; An assembler sequence may clobber the condition codes without us knowing. 16896263Sobrien; If such an insn references the pool, then we have no way of knowing how, 16996263Sobrien; so use the most conservative value for pool_range. 17090075Sobrien(define_asm_attributes 17196263Sobrien [(set_attr "conds" "clob") 17296263Sobrien (set_attr "length" "4") 17396263Sobrien (set_attr "pool_range" "250")]) 17490075Sobrien 175169689Skan;; The instruction used to implement a particular pattern. This 176169689Skan;; information is used by pipeline descriptions to provide accurate 177169689Skan;; scheduling information. 178169689Skan 179169689Skan(define_attr "insn" 180169689Skan "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other" 181169689Skan (const_string "other")) 182169689Skan 18390075Sobrien; TYPE attribute is used to detect floating point instructions which, if 18490075Sobrien; running on a co-processor can run in parallel with other, basic instructions 18590075Sobrien; If write-buffer scheduling is enabled then it can also be used in the 18690075Sobrien; scheduling of writes. 18790075Sobrien 18890075Sobrien; Classification of each insn 189169689Skan; alu any alu instruction that doesn't hit memory or fp 190169689Skan; regs or have a shifted source operand 191169689Skan; alu_shift any data instruction that doesn't hit memory or fp 192169689Skan; regs, but has a source operand shifted by a constant 193169689Skan; alu_shift_reg any data instruction that doesn't hit memory or fp 194169689Skan; regs, but has a source operand shifted by a register value 19590075Sobrien; mult a multiply instruction 19690075Sobrien; block blockage insn, this blocks all functional units 19790075Sobrien; float a floating point arithmetic operation (subject to expansion) 19890075Sobrien; fdivd DFmode floating point division 19990075Sobrien; fdivs SFmode floating point division 20090075Sobrien; fmul Floating point multiply 20190075Sobrien; ffmul Fast floating point multiply 20290075Sobrien; farith Floating point arithmetic (4 cycle) 20390075Sobrien; ffarith Fast floating point arithmetic (2 cycle) 20490075Sobrien; float_em a floating point arithmetic operation that is normally emulated 20590075Sobrien; even on a machine with an fpa. 20690075Sobrien; f_load a floating point load from memory 20790075Sobrien; f_store a floating point store to memory 208169689Skan; f_load[sd] single/double load from memory 209169689Skan; f_store[sd] single/double store to memory 210169689Skan; f_flag a transfer of co-processor flags to the CPSR 21190075Sobrien; f_mem_r a transfer of a floating point register to a real reg via mem 21290075Sobrien; r_mem_f the reverse of f_mem_r 21390075Sobrien; f_2_r fast transfer float to arm (no memory needed) 21490075Sobrien; r_2_f fast transfer arm to float 215169689Skan; f_cvt convert floating<->integral 216169689Skan; branch a branch 21790075Sobrien; call a subroutine call 218169689Skan; load_byte load byte(s) from memory to arm registers 219169689Skan; load1 load 1 word from memory to arm registers 220169689Skan; load2 load 2 words from memory to arm registers 221169689Skan; load3 load 3 words from memory to arm registers 222169689Skan; load4 load 4 words from memory to arm registers 223169689Skan; store store 1 word to memory from arm registers 22490075Sobrien; store2 store 2 words 22590075Sobrien; store3 store 3 words 226169689Skan; store4 store 4 (or more) words 227132718Skan; Additions for Cirrus Maverick co-processor: 228132718Skan; mav_farith Floating point arithmetic (4 cycle) 229132718Skan; mav_dmult Double multiplies (7 cycle) 23090075Sobrien; 23190075Sobrien(define_attr "type" 232169689Skan "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 233169689Skan (if_then_else 234169689Skan (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals") 235169689Skan (const_string "mult") 236169689Skan (const_string "alu"))) 23790075Sobrien 23890075Sobrien; Load scheduling, set from the arm_ld_sched variable 239117395Skan; initialized by arm_override_options() 24090075Sobrien(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched"))) 24190075Sobrien 24290075Sobrien; condition codes: this one is used by final_prescan_insn to speed up 24390075Sobrien; conditionalizing instructions. It saves having to scan the rtl to see if 24490075Sobrien; it uses or alters the condition codes. 24590075Sobrien; 24690075Sobrien; USE means that the condition codes are used by the insn in the process of 24790075Sobrien; outputting code, this means (at present) that we can't use the insn in 24890075Sobrien; inlined branches 24990075Sobrien; 25090075Sobrien; SET means that the purpose of the insn is to set the condition codes in a 25190075Sobrien; well defined manner. 25290075Sobrien; 25390075Sobrien; CLOB means that the condition codes are altered in an undefined manner, if 25490075Sobrien; they are altered at all 25590075Sobrien; 25690075Sobrien; JUMP_CLOB is used when the condition cannot be represented by a single 25790075Sobrien; instruction (UNEQ and LTGT). These cannot be predicated. 25890075Sobrien; 25990075Sobrien; NOCOND means that the condition codes are neither altered nor affect the 26090075Sobrien; output of this insn 26190075Sobrien 26290075Sobrien(define_attr "conds" "use,set,clob,jump_clob,nocond" 26390075Sobrien (if_then_else (eq_attr "type" "call") 264169689Skan (const_string "clob") 26590075Sobrien (const_string "nocond"))) 26690075Sobrien 26790075Sobrien; Predicable means that the insn can be conditionally executed based on 26890075Sobrien; an automatically added predicate (additional patterns are generated by 26990075Sobrien; gen...). We default to 'no' because no Thumb patterns match this rule 27090075Sobrien; and not all ARM patterns do. 27190075Sobrien(define_attr "predicable" "no,yes" (const_string "no")) 27290075Sobrien 27390075Sobrien; Only model the write buffer for ARM6 and ARM7. Earlier processors don't 27490075Sobrien; have one. Later ones, such as StrongARM, have write-back caches, so don't 275132718Skan; suffer blockages enough to warrant modelling this (and it can adversely 27690075Sobrien; affect the schedule). 277169689Skan(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf"))) 27890075Sobrien 27990075Sobrien; WRITE_CONFLICT implies that a read following an unrelated write is likely 28090075Sobrien; to stall the processor. Used with model_wbuf above. 28190075Sobrien(define_attr "write_conflict" "no,yes" 28290075Sobrien (if_then_else (eq_attr "type" 283169689Skan "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1") 28490075Sobrien (const_string "yes") 28590075Sobrien (const_string "no"))) 28690075Sobrien 28790075Sobrien; Classify the insns into those that take one cycle and those that take more 28890075Sobrien; than one on the main cpu execution unit. 28990075Sobrien(define_attr "core_cycles" "single,multi" 29090075Sobrien (if_then_else (eq_attr "type" 291169689Skan "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith") 29290075Sobrien (const_string "single") 29390075Sobrien (const_string "multi"))) 29490075Sobrien 29590075Sobrien;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a 29690075Sobrien;; distant label. Only applicable to Thumb code. 29790075Sobrien(define_attr "far_jump" "yes,no" (const_string "no")) 29890075Sobrien 29990075Sobrien 300169689Skan;;--------------------------------------------------------------------------- 301169689Skan;; Mode macros 30290075Sobrien 303169689Skan; A list of modes that are exactly 64 bits in size. We use this to expand 304169689Skan; some splits that are the same for all modes when operating on ARM 305169689Skan; registers. 306169689Skan(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF]) 30790075Sobrien 308169689Skan;;--------------------------------------------------------------------------- 309169689Skan;; Predicates 31090075Sobrien 311169689Skan(include "predicates.md") 312169689Skan(include "constraints.md") 31390075Sobrien 314169689Skan;;--------------------------------------------------------------------------- 315169689Skan;; Pipeline descriptions 31690075Sobrien 317169689Skan;; Processor type. This is created automatically from arm-cores.def. 318169689Skan(include "arm-tune.md") 31990075Sobrien 320169689Skan;; True if the generic scheduling description should be used. 32190075Sobrien 322169689Skan(define_attr "generic_sched" "yes,no" 323169689Skan (const (if_then_else 324169689Skan (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 325169689Skan (const_string "no") 326169689Skan (const_string "yes")))) 32790075Sobrien 328169689Skan(define_attr "generic_vfp" "yes,no" 329169689Skan (const (if_then_else 330169689Skan (and (eq_attr "fpu" "vfp") 331169689Skan (eq_attr "tune" "!arm1020e,arm1022e")) 332169689Skan (const_string "yes") 333169689Skan (const_string "no")))) 33490075Sobrien 335169689Skan(include "arm-generic.md") 336169689Skan(include "arm926ejs.md") 337169689Skan(include "arm1020e.md") 338169689Skan(include "arm1026ejs.md") 339169689Skan(include "arm1136jfs.md") 34090075Sobrien 34190075Sobrien 34290075Sobrien;;--------------------------------------------------------------------------- 34390075Sobrien;; Insn patterns 34490075Sobrien;; 34590075Sobrien;; Addition insns. 34690075Sobrien 34790075Sobrien;; Note: For DImode insns, there is normally no reason why operands should 34890075Sobrien;; not be in the same register, what we don't want is for something being 34990075Sobrien;; written to partially overlap something that is an input. 350132718Skan;; Cirrus 64bit additions should not be split because we have a native 351132718Skan;; 64bit addition instructions. 35290075Sobrien 35390075Sobrien(define_expand "adddi3" 35490075Sobrien [(parallel 35590075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 35690075Sobrien (plus:DI (match_operand:DI 1 "s_register_operand" "") 35790075Sobrien (match_operand:DI 2 "s_register_operand" ""))) 35890075Sobrien (clobber (reg:CC CC_REGNUM))])] 35990075Sobrien "TARGET_EITHER" 36090075Sobrien " 361169689Skan if (TARGET_HARD_FLOAT && TARGET_MAVERICK) 362132718Skan { 363132718Skan if (!cirrus_fp_register (operands[0], DImode)) 364132718Skan operands[0] = force_reg (DImode, operands[0]); 365132718Skan if (!cirrus_fp_register (operands[1], DImode)) 366132718Skan operands[1] = force_reg (DImode, operands[1]); 367132718Skan emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2])); 368132718Skan DONE; 369132718Skan } 370132718Skan 37190075Sobrien if (TARGET_THUMB) 37290075Sobrien { 37390075Sobrien if (GET_CODE (operands[1]) != REG) 37490075Sobrien operands[1] = force_reg (SImode, operands[1]); 37590075Sobrien if (GET_CODE (operands[2]) != REG) 37690075Sobrien operands[2] = force_reg (SImode, operands[2]); 37790075Sobrien } 37890075Sobrien " 37990075Sobrien) 38090075Sobrien 38190075Sobrien(define_insn "*thumb_adddi3" 38290075Sobrien [(set (match_operand:DI 0 "register_operand" "=l") 38390075Sobrien (plus:DI (match_operand:DI 1 "register_operand" "%0") 38490075Sobrien (match_operand:DI 2 "register_operand" "l"))) 38590075Sobrien (clobber (reg:CC CC_REGNUM)) 38690075Sobrien ] 38790075Sobrien "TARGET_THUMB" 38890075Sobrien "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2" 38990075Sobrien [(set_attr "length" "4")] 39090075Sobrien) 39190075Sobrien 39290075Sobrien(define_insn_and_split "*arm_adddi3" 39390075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 39490075Sobrien (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0") 39590075Sobrien (match_operand:DI 2 "s_register_operand" "r, 0"))) 39690075Sobrien (clobber (reg:CC CC_REGNUM))] 397169689Skan "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" 39890075Sobrien "#" 39990075Sobrien "TARGET_ARM && reload_completed" 40090075Sobrien [(parallel [(set (reg:CC_C CC_REGNUM) 40190075Sobrien (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 40290075Sobrien (match_dup 1))) 40390075Sobrien (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 40490075Sobrien (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 40590075Sobrien (plus:SI (match_dup 4) (match_dup 5))))] 40690075Sobrien " 40790075Sobrien { 40890075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 40990075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 41090075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 41190075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 41290075Sobrien operands[5] = gen_highpart (SImode, operands[2]); 41390075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 41490075Sobrien }" 41590075Sobrien [(set_attr "conds" "clob") 41690075Sobrien (set_attr "length" "8")] 41790075Sobrien) 41890075Sobrien 41990075Sobrien(define_insn_and_split "*adddi_sesidi_di" 42090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 42190075Sobrien (plus:DI (sign_extend:DI 42290075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 42390075Sobrien (match_operand:DI 1 "s_register_operand" "r,0"))) 42490075Sobrien (clobber (reg:CC CC_REGNUM))] 425169689Skan "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" 42690075Sobrien "#" 42790075Sobrien "TARGET_ARM && reload_completed" 42890075Sobrien [(parallel [(set (reg:CC_C CC_REGNUM) 42990075Sobrien (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 43090075Sobrien (match_dup 1))) 43190075Sobrien (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 43290075Sobrien (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 43390075Sobrien (plus:SI (ashiftrt:SI (match_dup 2) 43490075Sobrien (const_int 31)) 43590075Sobrien (match_dup 4))))] 43690075Sobrien " 43790075Sobrien { 43890075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 43990075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 44090075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 44190075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 44290075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 44390075Sobrien }" 44490075Sobrien [(set_attr "conds" "clob") 44590075Sobrien (set_attr "length" "8")] 44690075Sobrien) 44790075Sobrien 44890075Sobrien(define_insn_and_split "*adddi_zesidi_di" 44990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 45090075Sobrien (plus:DI (zero_extend:DI 45190075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 45290075Sobrien (match_operand:DI 1 "s_register_operand" "r,0"))) 45390075Sobrien (clobber (reg:CC CC_REGNUM))] 454169689Skan "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" 45590075Sobrien "#" 45690075Sobrien "TARGET_ARM && reload_completed" 45790075Sobrien [(parallel [(set (reg:CC_C CC_REGNUM) 45890075Sobrien (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 45990075Sobrien (match_dup 1))) 46090075Sobrien (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 46190075Sobrien (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 46290075Sobrien (plus:SI (match_dup 4) (const_int 0))))] 46390075Sobrien " 46490075Sobrien { 46590075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 46690075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 46790075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 46890075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 46990075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 47090075Sobrien }" 47190075Sobrien [(set_attr "conds" "clob") 47290075Sobrien (set_attr "length" "8")] 47390075Sobrien) 47490075Sobrien 47590075Sobrien(define_expand "addsi3" 47690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 47790075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "") 47890075Sobrien (match_operand:SI 2 "reg_or_int_operand" "")))] 47990075Sobrien "TARGET_EITHER" 48090075Sobrien " 48190075Sobrien if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT) 48290075Sobrien { 483169689Skan arm_split_constant (PLUS, SImode, NULL_RTX, 484169689Skan INTVAL (operands[2]), operands[0], operands[1], 485169689Skan optimize && !no_new_pseudos); 48690075Sobrien DONE; 48790075Sobrien } 48890075Sobrien " 48990075Sobrien) 49090075Sobrien 491132718Skan; If there is a scratch available, this will be faster than synthesizing the 49290075Sobrien; addition. 49390075Sobrien(define_peephole2 49490075Sobrien [(match_scratch:SI 3 "r") 495169689Skan (set (match_operand:SI 0 "arm_general_register_operand" "") 496169689Skan (plus:SI (match_operand:SI 1 "arm_general_register_operand" "") 49790075Sobrien (match_operand:SI 2 "const_int_operand" "")))] 49890075Sobrien "TARGET_ARM && 49990075Sobrien !(const_ok_for_arm (INTVAL (operands[2])) 50090075Sobrien || const_ok_for_arm (-INTVAL (operands[2]))) 50190075Sobrien && const_ok_for_arm (~INTVAL (operands[2]))" 50290075Sobrien [(set (match_dup 3) (match_dup 2)) 50390075Sobrien (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))] 50490075Sobrien "" 50590075Sobrien) 50690075Sobrien 50790075Sobrien(define_insn_and_split "*arm_addsi3" 50890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 50990075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r") 51090075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))] 51190075Sobrien "TARGET_ARM" 51290075Sobrien "@ 51390075Sobrien add%?\\t%0, %1, %2 51490075Sobrien sub%?\\t%0, %1, #%n2 51590075Sobrien #" 51690075Sobrien "TARGET_ARM && 51790075Sobrien GET_CODE (operands[2]) == CONST_INT 51890075Sobrien && !(const_ok_for_arm (INTVAL (operands[2])) 51990075Sobrien || const_ok_for_arm (-INTVAL (operands[2])))" 52090075Sobrien [(clobber (const_int 0))] 52190075Sobrien " 522169689Skan arm_split_constant (PLUS, SImode, curr_insn, 523169689Skan INTVAL (operands[2]), operands[0], 52490075Sobrien operands[1], 0); 52590075Sobrien DONE; 52690075Sobrien " 52790075Sobrien [(set_attr "length" "4,4,16") 52890075Sobrien (set_attr "predicable" "yes")] 52990075Sobrien) 53090075Sobrien 53190075Sobrien;; Register group 'k' is a single register group containing only the stack 53290075Sobrien;; register. Trying to reload it will always fail catastrophically, 53390075Sobrien;; so never allow those alternatives to match if reloading is needed. 53490075Sobrien 53590075Sobrien(define_insn "*thumb_addsi3" 53690075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k") 53790075Sobrien (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k") 53890075Sobrien (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))] 53990075Sobrien "TARGET_THUMB" 54090075Sobrien "* 54190075Sobrien static const char * const asms[] = 54290075Sobrien { 54390075Sobrien \"add\\t%0, %0, %2\", 54490075Sobrien \"sub\\t%0, %0, #%n2\", 54590075Sobrien \"add\\t%0, %1, %2\", 54690075Sobrien \"add\\t%0, %0, %2\", 54790075Sobrien \"add\\t%0, %0, %2\", 54890075Sobrien \"add\\t%0, %1, %2\", 54990075Sobrien \"add\\t%0, %1, %2\" 55090075Sobrien }; 55190075Sobrien if ((which_alternative == 2 || which_alternative == 6) 55290075Sobrien && GET_CODE (operands[2]) == CONST_INT 55390075Sobrien && INTVAL (operands[2]) < 0) 55490075Sobrien return \"sub\\t%0, %1, #%n2\"; 55590075Sobrien return asms[which_alternative]; 55690075Sobrien " 55790075Sobrien [(set_attr "length" "2")] 55890075Sobrien) 55990075Sobrien 56090075Sobrien;; Reloading and elimination of the frame pointer can 56190075Sobrien;; sometimes cause this optimization to be missed. 56290075Sobrien(define_peephole2 563169689Skan [(set (match_operand:SI 0 "arm_general_register_operand" "") 564117395Skan (match_operand:SI 1 "const_int_operand" "")) 56590075Sobrien (set (match_dup 0) 566169689Skan (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))] 56790075Sobrien "TARGET_THUMB 56890075Sobrien && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024 56990075Sobrien && (INTVAL (operands[1]) & 3) == 0" 570169689Skan [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))] 57190075Sobrien "" 57290075Sobrien) 57390075Sobrien 57490075Sobrien(define_insn "*addsi3_compare0" 57590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 57690075Sobrien (compare:CC_NOOV 57790075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r, r") 57890075Sobrien (match_operand:SI 2 "arm_add_operand" "rI,L")) 57990075Sobrien (const_int 0))) 58090075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 58190075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 58290075Sobrien "TARGET_ARM" 58390075Sobrien "@ 58490075Sobrien add%?s\\t%0, %1, %2 58590075Sobrien sub%?s\\t%0, %1, #%n2" 58690075Sobrien [(set_attr "conds" "set")] 58790075Sobrien) 58890075Sobrien 58990075Sobrien(define_insn "*addsi3_compare0_scratch" 59090075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 59190075Sobrien (compare:CC_NOOV 59290075Sobrien (plus:SI (match_operand:SI 0 "s_register_operand" "r, r") 59390075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L")) 59490075Sobrien (const_int 0)))] 59590075Sobrien "TARGET_ARM" 59690075Sobrien "@ 59790075Sobrien cmn%?\\t%0, %1 59890075Sobrien cmp%?\\t%0, #%n1" 59990075Sobrien [(set_attr "conds" "set")] 60090075Sobrien) 60190075Sobrien 602169689Skan(define_insn "*compare_negsi_si" 603169689Skan [(set (reg:CC_Z CC_REGNUM) 604169689Skan (compare:CC_Z 605169689Skan (neg:SI (match_operand:SI 0 "s_register_operand" "r")) 606169689Skan (match_operand:SI 1 "s_register_operand" "r")))] 60790075Sobrien "TARGET_ARM" 608169689Skan "cmn%?\\t%1, %0" 60990075Sobrien [(set_attr "conds" "set")] 61090075Sobrien) 61190075Sobrien 612132718Skan;; This is the canonicalization of addsi3_compare0_for_combiner when the 613132718Skan;; addend is a constant. 614132718Skan(define_insn "*cmpsi2_addneg" 615132718Skan [(set (reg:CC CC_REGNUM) 616132718Skan (compare:CC 617132718Skan (match_operand:SI 1 "s_register_operand" "r,r") 618132718Skan (match_operand:SI 2 "arm_addimm_operand" "I,L"))) 619132718Skan (set (match_operand:SI 0 "s_register_operand" "=r,r") 620132718Skan (plus:SI (match_dup 1) 621132718Skan (match_operand:SI 3 "arm_addimm_operand" "L,I")))] 622132718Skan "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])" 623132718Skan "@ 624132718Skan sub%?s\\t%0, %1, %2 625132718Skan add%?s\\t%0, %1, #%n2" 626132718Skan [(set_attr "conds" "set")] 627132718Skan) 628132718Skan 629132718Skan;; Convert the sequence 630132718Skan;; sub rd, rn, #1 631132718Skan;; cmn rd, #1 (equivalent to cmp rd, #-1) 632132718Skan;; bne dest 633132718Skan;; into 634132718Skan;; subs rd, rn, #1 635132718Skan;; bcs dest ((unsigned)rn >= 1) 636132718Skan;; similarly for the beq variant using bcc. 637132718Skan;; This is a common looping idiom (while (n--)) 638132718Skan(define_peephole2 639169689Skan [(set (match_operand:SI 0 "arm_general_register_operand" "") 640169689Skan (plus:SI (match_operand:SI 1 "arm_general_register_operand" "") 641132718Skan (const_int -1))) 642132718Skan (set (match_operand 2 "cc_register" "") 643132718Skan (compare (match_dup 0) (const_int -1))) 644132718Skan (set (pc) 645132718Skan (if_then_else (match_operator 3 "equality_operator" 646132718Skan [(match_dup 2) (const_int 0)]) 647132718Skan (match_operand 4 "" "") 648132718Skan (match_operand 5 "" "")))] 649132718Skan "TARGET_ARM && peep2_reg_dead_p (3, operands[2])" 650132718Skan [(parallel[ 651132718Skan (set (match_dup 2) 652132718Skan (compare:CC 653132718Skan (match_dup 1) (const_int 1))) 654132718Skan (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))]) 655132718Skan (set (pc) 656132718Skan (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)]) 657132718Skan (match_dup 4) 658132718Skan (match_dup 5)))] 659132718Skan "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM); 660132718Skan operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE 661132718Skan ? GEU : LTU), 662132718Skan VOIDmode, 663132718Skan operands[2], const0_rtx);" 664132718Skan) 665132718Skan 66690075Sobrien;; The next four insns work because they compare the result with one of 66790075Sobrien;; the operands, and we know that the use of the condition code is 66890075Sobrien;; either GEU or LTU, so we can use the carry flag from the addition 66990075Sobrien;; instead of doing the compare a second time. 67090075Sobrien(define_insn "*addsi3_compare_op1" 67190075Sobrien [(set (reg:CC_C CC_REGNUM) 67290075Sobrien (compare:CC_C 67390075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 67490075Sobrien (match_operand:SI 2 "arm_add_operand" "rI,L")) 67590075Sobrien (match_dup 1))) 67690075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 67790075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 67890075Sobrien "TARGET_ARM" 67990075Sobrien "@ 68090075Sobrien add%?s\\t%0, %1, %2 68190075Sobrien sub%?s\\t%0, %1, #%n2" 68290075Sobrien [(set_attr "conds" "set")] 68390075Sobrien) 68490075Sobrien 68590075Sobrien(define_insn "*addsi3_compare_op2" 68690075Sobrien [(set (reg:CC_C CC_REGNUM) 68790075Sobrien (compare:CC_C 68890075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 68990075Sobrien (match_operand:SI 2 "arm_add_operand" "rI,L")) 69090075Sobrien (match_dup 2))) 69190075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 69290075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 69390075Sobrien "TARGET_ARM" 69490075Sobrien "@ 69590075Sobrien add%?s\\t%0, %1, %2 69690075Sobrien sub%?s\\t%0, %1, #%n2" 69790075Sobrien [(set_attr "conds" "set")] 69890075Sobrien) 69990075Sobrien 70090075Sobrien(define_insn "*compare_addsi2_op0" 70190075Sobrien [(set (reg:CC_C CC_REGNUM) 70290075Sobrien (compare:CC_C 70390075Sobrien (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 70490075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L")) 70590075Sobrien (match_dup 0)))] 70690075Sobrien "TARGET_ARM" 70790075Sobrien "@ 70890075Sobrien cmn%?\\t%0, %1 70990075Sobrien cmp%?\\t%0, #%n1" 71090075Sobrien [(set_attr "conds" "set")] 71190075Sobrien) 71290075Sobrien 71390075Sobrien(define_insn "*compare_addsi2_op1" 71490075Sobrien [(set (reg:CC_C CC_REGNUM) 71590075Sobrien (compare:CC_C 71690075Sobrien (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 71790075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L")) 71890075Sobrien (match_dup 1)))] 71990075Sobrien "TARGET_ARM" 72090075Sobrien "@ 72190075Sobrien cmn%?\\t%0, %1 72290075Sobrien cmp%?\\t%0, #%n1" 72390075Sobrien [(set_attr "conds" "set")] 72490075Sobrien) 72590075Sobrien 72690075Sobrien(define_insn "*addsi3_carryin" 72790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 72890075Sobrien (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 72990075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r") 73090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI"))))] 73190075Sobrien "TARGET_ARM" 73290075Sobrien "adc%?\\t%0, %1, %2" 73390075Sobrien [(set_attr "conds" "use")] 73490075Sobrien) 73590075Sobrien 73690075Sobrien(define_insn "*addsi3_carryin_shift" 737132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 73890075Sobrien (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 73990075Sobrien (plus:SI 74090075Sobrien (match_operator:SI 2 "shift_operator" 741132718Skan [(match_operand:SI 3 "s_register_operand" "r") 742132718Skan (match_operand:SI 4 "reg_or_int_operand" "rM")]) 743132718Skan (match_operand:SI 1 "s_register_operand" "r"))))] 74490075Sobrien "TARGET_ARM" 74590075Sobrien "adc%?\\t%0, %1, %3%S2" 746169689Skan [(set_attr "conds" "use") 747169689Skan (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") 748169689Skan (const_string "alu_shift") 749169689Skan (const_string "alu_shift_reg")))] 75090075Sobrien) 75190075Sobrien 75290075Sobrien(define_insn "*addsi3_carryin_alt1" 75390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 75490075Sobrien (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") 75590075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 75690075Sobrien (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] 75790075Sobrien "TARGET_ARM" 75890075Sobrien "adc%?\\t%0, %1, %2" 75990075Sobrien [(set_attr "conds" "use")] 76090075Sobrien) 76190075Sobrien 76290075Sobrien(define_insn "*addsi3_carryin_alt2" 76390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 76490075Sobrien (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 76590075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 76690075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")))] 76790075Sobrien "TARGET_ARM" 76890075Sobrien "adc%?\\t%0, %1, %2" 76990075Sobrien [(set_attr "conds" "use")] 77090075Sobrien) 77190075Sobrien 77290075Sobrien(define_insn "*addsi3_carryin_alt3" 77390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 77490075Sobrien (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 77590075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 77690075Sobrien (match_operand:SI 1 "s_register_operand" "r")))] 77790075Sobrien "TARGET_ARM" 77890075Sobrien "adc%?\\t%0, %1, %2" 77990075Sobrien [(set_attr "conds" "use")] 78090075Sobrien) 78190075Sobrien 78290075Sobrien(define_insn "incscc" 78390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 78490075Sobrien (plus:SI (match_operator:SI 2 "arm_comparison_operator" 78590075Sobrien [(match_operand:CC 3 "cc_register" "") (const_int 0)]) 78690075Sobrien (match_operand:SI 1 "s_register_operand" "0,?r")))] 78790075Sobrien "TARGET_ARM" 78890075Sobrien "@ 78990075Sobrien add%d2\\t%0, %1, #1 79090075Sobrien mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1" 79190075Sobrien [(set_attr "conds" "use") 79290075Sobrien (set_attr "length" "4,8")] 79390075Sobrien) 79490075Sobrien 795132718Skan; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant. 796132718Skan(define_split 797132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 798132718Skan (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "") 799132718Skan (match_operand:SI 2 "s_register_operand" "")) 800132718Skan (const_int -1))) 801132718Skan (clobber (match_operand:SI 3 "s_register_operand" ""))] 802132718Skan "TARGET_ARM" 803132718Skan [(set (match_dup 3) (match_dup 1)) 804132718Skan (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))] 805132718Skan " 806132718Skan operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1)); 807132718Skan") 80890075Sobrien 809132718Skan(define_expand "addsf3" 810132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 811132718Skan (plus:SF (match_operand:SF 1 "s_register_operand" "") 812169689Skan (match_operand:SF 2 "arm_float_add_operand" "")))] 813169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 814132718Skan " 815169689Skan if (TARGET_MAVERICK 816132718Skan && !cirrus_fp_register (operands[2], SFmode)) 817132718Skan operands[2] = force_reg (SFmode, operands[2]); 818132718Skan") 81990075Sobrien 820132718Skan(define_expand "adddf3" 821132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 822132718Skan (plus:DF (match_operand:DF 1 "s_register_operand" "") 823169689Skan (match_operand:DF 2 "arm_float_add_operand" "")))] 824169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 825132718Skan " 826169689Skan if (TARGET_MAVERICK 827132718Skan && !cirrus_fp_register (operands[2], DFmode)) 828132718Skan operands[2] = force_reg (DFmode, operands[2]); 829132718Skan") 83090075Sobrien 83190075Sobrien(define_expand "subdi3" 83290075Sobrien [(parallel 83390075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 83490075Sobrien (minus:DI (match_operand:DI 1 "s_register_operand" "") 83590075Sobrien (match_operand:DI 2 "s_register_operand" ""))) 83690075Sobrien (clobber (reg:CC CC_REGNUM))])] 83790075Sobrien "TARGET_EITHER" 83890075Sobrien " 839169689Skan if (TARGET_HARD_FLOAT && TARGET_MAVERICK 840132718Skan && TARGET_ARM 841132718Skan && cirrus_fp_register (operands[0], DImode) 842132718Skan && cirrus_fp_register (operands[1], DImode)) 843132718Skan { 844132718Skan emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2])); 845132718Skan DONE; 846132718Skan } 847132718Skan 84890075Sobrien if (TARGET_THUMB) 84990075Sobrien { 85090075Sobrien if (GET_CODE (operands[1]) != REG) 85190075Sobrien operands[1] = force_reg (SImode, operands[1]); 85290075Sobrien if (GET_CODE (operands[2]) != REG) 85390075Sobrien operands[2] = force_reg (SImode, operands[2]); 85490075Sobrien } 85590075Sobrien " 85690075Sobrien) 85790075Sobrien 85890075Sobrien(define_insn "*arm_subdi3" 85990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r") 86090075Sobrien (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0") 86190075Sobrien (match_operand:DI 2 "s_register_operand" "r,0,0"))) 86290075Sobrien (clobber (reg:CC CC_REGNUM))] 86390075Sobrien "TARGET_ARM" 86490075Sobrien "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2" 86590075Sobrien [(set_attr "conds" "clob") 86690075Sobrien (set_attr "length" "8")] 86790075Sobrien) 86890075Sobrien 86990075Sobrien(define_insn "*thumb_subdi3" 87090075Sobrien [(set (match_operand:DI 0 "register_operand" "=l") 87190075Sobrien (minus:DI (match_operand:DI 1 "register_operand" "0") 87290075Sobrien (match_operand:DI 2 "register_operand" "l"))) 87390075Sobrien (clobber (reg:CC CC_REGNUM))] 87490075Sobrien "TARGET_THUMB" 87590075Sobrien "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2" 87690075Sobrien [(set_attr "length" "4")] 87790075Sobrien) 87890075Sobrien 87990075Sobrien(define_insn "*subdi_di_zesidi" 88090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 88190075Sobrien (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0") 88290075Sobrien (zero_extend:DI 88390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")))) 88490075Sobrien (clobber (reg:CC CC_REGNUM))] 88590075Sobrien "TARGET_ARM" 88690075Sobrien "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0" 88790075Sobrien [(set_attr "conds" "clob") 88890075Sobrien (set_attr "length" "8")] 88990075Sobrien) 89090075Sobrien 89190075Sobrien(define_insn "*subdi_di_sesidi" 89290075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 89390075Sobrien (minus:DI (match_operand:DI 1 "s_register_operand" "r,0") 89490075Sobrien (sign_extend:DI 89590075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")))) 89690075Sobrien (clobber (reg:CC CC_REGNUM))] 89790075Sobrien "TARGET_ARM" 89890075Sobrien "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31" 89990075Sobrien [(set_attr "conds" "clob") 90090075Sobrien (set_attr "length" "8")] 90190075Sobrien) 90290075Sobrien 90390075Sobrien(define_insn "*subdi_zesidi_di" 90490075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 90590075Sobrien (minus:DI (zero_extend:DI 90690075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 90790075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0"))) 90890075Sobrien (clobber (reg:CC CC_REGNUM))] 90990075Sobrien "TARGET_ARM" 91090075Sobrien "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0" 91190075Sobrien [(set_attr "conds" "clob") 91290075Sobrien (set_attr "length" "8")] 91390075Sobrien) 91490075Sobrien 91590075Sobrien(define_insn "*subdi_sesidi_di" 91690075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 91790075Sobrien (minus:DI (sign_extend:DI 91890075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 91990075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0"))) 92090075Sobrien (clobber (reg:CC CC_REGNUM))] 92190075Sobrien "TARGET_ARM" 92290075Sobrien "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31" 92390075Sobrien [(set_attr "conds" "clob") 92490075Sobrien (set_attr "length" "8")] 92590075Sobrien) 92690075Sobrien 92790075Sobrien(define_insn "*subdi_zesidi_zesidi" 92890075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r") 92990075Sobrien (minus:DI (zero_extend:DI 93090075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 93190075Sobrien (zero_extend:DI 93290075Sobrien (match_operand:SI 2 "s_register_operand" "r")))) 93390075Sobrien (clobber (reg:CC CC_REGNUM))] 93490075Sobrien "TARGET_ARM" 93590075Sobrien "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1" 93690075Sobrien [(set_attr "conds" "clob") 93790075Sobrien (set_attr "length" "8")] 93890075Sobrien) 93990075Sobrien 94090075Sobrien(define_expand "subsi3" 94190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 94290075Sobrien (minus:SI (match_operand:SI 1 "reg_or_int_operand" "") 94390075Sobrien (match_operand:SI 2 "s_register_operand" "")))] 94490075Sobrien "TARGET_EITHER" 94590075Sobrien " 94690075Sobrien if (GET_CODE (operands[1]) == CONST_INT) 94790075Sobrien { 94890075Sobrien if (TARGET_ARM) 94990075Sobrien { 950169689Skan arm_split_constant (MINUS, SImode, NULL_RTX, 951169689Skan INTVAL (operands[1]), operands[0], 952169689Skan operands[2], optimize && !no_new_pseudos); 95390075Sobrien DONE; 95490075Sobrien } 95590075Sobrien else /* TARGET_THUMB */ 95690075Sobrien operands[1] = force_reg (SImode, operands[1]); 95790075Sobrien } 95890075Sobrien " 95990075Sobrien) 96090075Sobrien 96190075Sobrien(define_insn "*thumb_subsi3_insn" 96290075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 96390075Sobrien (minus:SI (match_operand:SI 1 "register_operand" "l") 96490075Sobrien (match_operand:SI 2 "register_operand" "l")))] 96590075Sobrien "TARGET_THUMB" 96690075Sobrien "sub\\t%0, %1, %2" 96790075Sobrien [(set_attr "length" "2")] 96890075Sobrien) 96990075Sobrien 97090075Sobrien(define_insn_and_split "*arm_subsi3_insn" 97190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 97290075Sobrien (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n") 97390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")))] 97490075Sobrien "TARGET_ARM" 97590075Sobrien "@ 97690075Sobrien rsb%?\\t%0, %2, %1 97790075Sobrien #" 97890075Sobrien "TARGET_ARM 97990075Sobrien && GET_CODE (operands[1]) == CONST_INT 98090075Sobrien && !const_ok_for_arm (INTVAL (operands[1]))" 98190075Sobrien [(clobber (const_int 0))] 98290075Sobrien " 983169689Skan arm_split_constant (MINUS, SImode, curr_insn, 984169689Skan INTVAL (operands[1]), operands[0], operands[2], 0); 98590075Sobrien DONE; 98690075Sobrien " 98790075Sobrien [(set_attr "length" "4,16") 98890075Sobrien (set_attr "predicable" "yes")] 98990075Sobrien) 99090075Sobrien 99190075Sobrien(define_peephole2 99290075Sobrien [(match_scratch:SI 3 "r") 993169689Skan (set (match_operand:SI 0 "arm_general_register_operand" "") 99490075Sobrien (minus:SI (match_operand:SI 1 "const_int_operand" "") 995169689Skan (match_operand:SI 2 "arm_general_register_operand" "")))] 99690075Sobrien "TARGET_ARM 99790075Sobrien && !const_ok_for_arm (INTVAL (operands[1])) 99890075Sobrien && const_ok_for_arm (~INTVAL (operands[1]))" 99990075Sobrien [(set (match_dup 3) (match_dup 1)) 100090075Sobrien (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))] 100190075Sobrien "" 100290075Sobrien) 100390075Sobrien 100490075Sobrien(define_insn "*subsi3_compare0" 100590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 100690075Sobrien (compare:CC_NOOV 100790075Sobrien (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I") 100890075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,r")) 100990075Sobrien (const_int 0))) 101090075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 101190075Sobrien (minus:SI (match_dup 1) (match_dup 2)))] 101290075Sobrien "TARGET_ARM" 101390075Sobrien "@ 101490075Sobrien sub%?s\\t%0, %1, %2 101590075Sobrien rsb%?s\\t%0, %2, %1" 101690075Sobrien [(set_attr "conds" "set")] 101790075Sobrien) 101890075Sobrien 101990075Sobrien(define_insn "decscc" 102090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 102190075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 102290075Sobrien (match_operator:SI 2 "arm_comparison_operator" 102390075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)])))] 102490075Sobrien "TARGET_ARM" 102590075Sobrien "@ 102690075Sobrien sub%d2\\t%0, %1, #1 102790075Sobrien mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1" 102890075Sobrien [(set_attr "conds" "use") 102990075Sobrien (set_attr "length" "*,8")] 103090075Sobrien) 103190075Sobrien 1032132718Skan(define_expand "subsf3" 1033132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 1034169689Skan (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "") 1035169689Skan (match_operand:SF 2 "arm_float_rhs_operand" "")))] 1036169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 1037132718Skan " 1038169689Skan if (TARGET_MAVERICK) 1039132718Skan { 1040132718Skan if (!cirrus_fp_register (operands[1], SFmode)) 1041132718Skan operands[1] = force_reg (SFmode, operands[1]); 1042132718Skan if (!cirrus_fp_register (operands[2], SFmode)) 1043132718Skan operands[2] = force_reg (SFmode, operands[2]); 1044132718Skan } 1045132718Skan") 104690075Sobrien 1047132718Skan(define_expand "subdf3" 1048132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 1049169689Skan (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "") 1050169689Skan (match_operand:DF 2 "arm_float_rhs_operand" "")))] 1051169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 1052132718Skan " 1053169689Skan if (TARGET_MAVERICK) 1054132718Skan { 1055132718Skan if (!cirrus_fp_register (operands[1], DFmode)) 1056132718Skan operands[1] = force_reg (DFmode, operands[1]); 1057132718Skan if (!cirrus_fp_register (operands[2], DFmode)) 1058132718Skan operands[2] = force_reg (DFmode, operands[2]); 1059132718Skan } 1060132718Skan") 106190075Sobrien 106290075Sobrien 106390075Sobrien;; Multiplication insns 106490075Sobrien 106590075Sobrien(define_expand "mulsi3" 106690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 106790075Sobrien (mult:SI (match_operand:SI 2 "s_register_operand" "") 106890075Sobrien (match_operand:SI 1 "s_register_operand" "")))] 106990075Sobrien "TARGET_EITHER" 107090075Sobrien "" 107190075Sobrien) 107290075Sobrien 107390075Sobrien;; Use `&' and then `0' to prevent the operands 0 and 1 being the same 107490075Sobrien(define_insn "*arm_mulsi3" 107590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 107690075Sobrien (mult:SI (match_operand:SI 2 "s_register_operand" "r,r") 107790075Sobrien (match_operand:SI 1 "s_register_operand" "%?r,0")))] 107890075Sobrien "TARGET_ARM" 107990075Sobrien "mul%?\\t%0, %2, %1" 1080169689Skan [(set_attr "insn" "mul") 108190075Sobrien (set_attr "predicable" "yes")] 108290075Sobrien) 108390075Sobrien 108490075Sobrien; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 108590075Sobrien; 1 and 2; are the same, because reload will make operand 0 match 108690075Sobrien; operand 1 without realizing that this conflicts with operand 2. We fix 108790075Sobrien; this by adding another alternative to match this case, and then `reload' 108890075Sobrien; it ourselves. This alternative must come first. 108990075Sobrien(define_insn "*thumb_mulsi3" 109090075Sobrien [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l") 109190075Sobrien (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0") 109290075Sobrien (match_operand:SI 2 "register_operand" "l,l,l")))] 109390075Sobrien "TARGET_THUMB" 109490075Sobrien "* 109590075Sobrien if (which_alternative < 2) 1096169689Skan return \"mov\\t%0, %1\;mul\\t%0, %2\"; 109790075Sobrien else 1098169689Skan return \"mul\\t%0, %2\"; 109990075Sobrien " 110090075Sobrien [(set_attr "length" "4,4,2") 1101169689Skan (set_attr "insn" "mul")] 110290075Sobrien) 110390075Sobrien 110490075Sobrien(define_insn "*mulsi3_compare0" 110590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 110690075Sobrien (compare:CC_NOOV (mult:SI 110790075Sobrien (match_operand:SI 2 "s_register_operand" "r,r") 110890075Sobrien (match_operand:SI 1 "s_register_operand" "%?r,0")) 110990075Sobrien (const_int 0))) 111090075Sobrien (set (match_operand:SI 0 "s_register_operand" "=&r,&r") 111190075Sobrien (mult:SI (match_dup 2) (match_dup 1)))] 1112169689Skan "TARGET_ARM" 111390075Sobrien "mul%?s\\t%0, %2, %1" 111490075Sobrien [(set_attr "conds" "set") 1115169689Skan (set_attr "insn" "muls")] 111690075Sobrien) 111790075Sobrien 111890075Sobrien(define_insn "*mulsi_compare0_scratch" 111990075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 112090075Sobrien (compare:CC_NOOV (mult:SI 112190075Sobrien (match_operand:SI 2 "s_register_operand" "r,r") 112290075Sobrien (match_operand:SI 1 "s_register_operand" "%?r,0")) 112390075Sobrien (const_int 0))) 112490075Sobrien (clobber (match_scratch:SI 0 "=&r,&r"))] 1125169689Skan "TARGET_ARM" 112690075Sobrien "mul%?s\\t%0, %2, %1" 112790075Sobrien [(set_attr "conds" "set") 1128169689Skan (set_attr "insn" "muls")] 112990075Sobrien) 113090075Sobrien 113190075Sobrien;; Unnamed templates to match MLA instruction. 113290075Sobrien 113390075Sobrien(define_insn "*mulsi3addsi" 113490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 113590075Sobrien (plus:SI 113690075Sobrien (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r") 113790075Sobrien (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 113890075Sobrien (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))] 113990075Sobrien "TARGET_ARM" 114090075Sobrien "mla%?\\t%0, %2, %1, %3" 1141169689Skan [(set_attr "insn" "mla") 114290075Sobrien (set_attr "predicable" "yes")] 114390075Sobrien) 114490075Sobrien 114590075Sobrien(define_insn "*mulsi3addsi_compare0" 114690075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 114790075Sobrien (compare:CC_NOOV 114890075Sobrien (plus:SI (mult:SI 114990075Sobrien (match_operand:SI 2 "s_register_operand" "r,r,r,r") 115090075Sobrien (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 115190075Sobrien (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 115290075Sobrien (const_int 0))) 115390075Sobrien (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 115490075Sobrien (plus:SI (mult:SI (match_dup 2) (match_dup 1)) 115590075Sobrien (match_dup 3)))] 1156169689Skan "TARGET_ARM" 115790075Sobrien "mla%?s\\t%0, %2, %1, %3" 115890075Sobrien [(set_attr "conds" "set") 1159169689Skan (set_attr "insn" "mlas")] 116090075Sobrien) 116190075Sobrien 116290075Sobrien(define_insn "*mulsi3addsi_compare0_scratch" 116390075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 116490075Sobrien (compare:CC_NOOV 116590075Sobrien (plus:SI (mult:SI 116690075Sobrien (match_operand:SI 2 "s_register_operand" "r,r,r,r") 116790075Sobrien (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 116890075Sobrien (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 116990075Sobrien (const_int 0))) 117090075Sobrien (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))] 1171169689Skan "TARGET_ARM" 117290075Sobrien "mla%?s\\t%0, %2, %1, %3" 117390075Sobrien [(set_attr "conds" "set") 1174169689Skan (set_attr "insn" "mlas")] 117590075Sobrien) 117690075Sobrien 1177132718Skan;; Unnamed template to match long long multiply-accumulate (smlal) 117890075Sobrien 117990075Sobrien(define_insn "*mulsidi3adddi" 118090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r") 118190075Sobrien (plus:DI 118290075Sobrien (mult:DI 118390075Sobrien (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r")) 118490075Sobrien (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r"))) 118590075Sobrien (match_operand:DI 1 "s_register_operand" "0")))] 1186169689Skan "TARGET_ARM && arm_arch3m" 118790075Sobrien "smlal%?\\t%Q0, %R0, %3, %2" 1188169689Skan [(set_attr "insn" "smlal") 118990075Sobrien (set_attr "predicable" "yes")] 119090075Sobrien) 119190075Sobrien 119290075Sobrien(define_insn "mulsidi3" 119390075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r") 119490075Sobrien (mult:DI 119590075Sobrien (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r")) 119690075Sobrien (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))] 1197169689Skan "TARGET_ARM && arm_arch3m" 119890075Sobrien "smull%?\\t%Q0, %R0, %1, %2" 1199169689Skan [(set_attr "insn" "smull") 120090075Sobrien (set_attr "predicable" "yes")] 120190075Sobrien) 120290075Sobrien 120390075Sobrien(define_insn "umulsidi3" 120490075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r") 120590075Sobrien (mult:DI 120690075Sobrien (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r")) 120790075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))] 1208169689Skan "TARGET_ARM && arm_arch3m" 120990075Sobrien "umull%?\\t%Q0, %R0, %1, %2" 1210169689Skan [(set_attr "insn" "umull") 121190075Sobrien (set_attr "predicable" "yes")] 121290075Sobrien) 121390075Sobrien 1214132718Skan;; Unnamed template to match long long unsigned multiply-accumulate (umlal) 121590075Sobrien 121690075Sobrien(define_insn "*umulsidi3adddi" 121790075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r") 121890075Sobrien (plus:DI 121990075Sobrien (mult:DI 122090075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r")) 122190075Sobrien (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r"))) 122290075Sobrien (match_operand:DI 1 "s_register_operand" "0")))] 1223169689Skan "TARGET_ARM && arm_arch3m" 122490075Sobrien "umlal%?\\t%Q0, %R0, %3, %2" 1225169689Skan [(set_attr "insn" "umlal") 122690075Sobrien (set_attr "predicable" "yes")] 122790075Sobrien) 122890075Sobrien 122990075Sobrien(define_insn "smulsi3_highpart" 123090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 123190075Sobrien (truncate:SI 123290075Sobrien (lshiftrt:DI 123390075Sobrien (mult:DI 123490075Sobrien (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0")) 123590075Sobrien (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) 123690075Sobrien (const_int 32)))) 123790075Sobrien (clobber (match_scratch:SI 3 "=&r,&r"))] 1238169689Skan "TARGET_ARM && arm_arch3m" 123990075Sobrien "smull%?\\t%3, %0, %2, %1" 1240169689Skan [(set_attr "insn" "smull") 124190075Sobrien (set_attr "predicable" "yes")] 124290075Sobrien) 124390075Sobrien 124490075Sobrien(define_insn "umulsi3_highpart" 124590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 124690075Sobrien (truncate:SI 124790075Sobrien (lshiftrt:DI 124890075Sobrien (mult:DI 124990075Sobrien (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0")) 125090075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) 125190075Sobrien (const_int 32)))) 125290075Sobrien (clobber (match_scratch:SI 3 "=&r,&r"))] 1253169689Skan "TARGET_ARM && arm_arch3m" 125490075Sobrien "umull%?\\t%3, %0, %2, %1" 1255169689Skan [(set_attr "insn" "umull") 125690075Sobrien (set_attr "predicable" "yes")] 125790075Sobrien) 125890075Sobrien 125990075Sobrien(define_insn "mulhisi3" 126090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 126190075Sobrien (mult:SI (sign_extend:SI 126290075Sobrien (match_operand:HI 1 "s_register_operand" "%r")) 126390075Sobrien (sign_extend:SI 126490075Sobrien (match_operand:HI 2 "s_register_operand" "r"))))] 1265132718Skan "TARGET_ARM && arm_arch5e" 126690075Sobrien "smulbb%?\\t%0, %1, %2" 1267169689Skan [(set_attr "insn" "smulxy") 1268132718Skan (set_attr "predicable" "yes")] 126990075Sobrien) 127090075Sobrien 1271132718Skan(define_insn "*mulhisi3tb" 1272132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1273132718Skan (mult:SI (ashiftrt:SI 1274132718Skan (match_operand:SI 1 "s_register_operand" "r") 1275132718Skan (const_int 16)) 1276132718Skan (sign_extend:SI 1277132718Skan (match_operand:HI 2 "s_register_operand" "r"))))] 1278132718Skan "TARGET_ARM && arm_arch5e" 1279132718Skan "smultb%?\\t%0, %1, %2" 1280169689Skan [(set_attr "insn" "smulxy") 1281132718Skan (set_attr "predicable" "yes")] 1282132718Skan) 1283132718Skan 1284132718Skan(define_insn "*mulhisi3bt" 1285132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1286132718Skan (mult:SI (sign_extend:SI 1287132718Skan (match_operand:HI 1 "s_register_operand" "r")) 1288132718Skan (ashiftrt:SI 1289132718Skan (match_operand:SI 2 "s_register_operand" "r") 1290132718Skan (const_int 16))))] 1291132718Skan "TARGET_ARM && arm_arch5e" 1292132718Skan "smulbt%?\\t%0, %1, %2" 1293169689Skan [(set_attr "insn" "smulxy") 1294132718Skan (set_attr "predicable" "yes")] 1295132718Skan) 1296132718Skan 1297132718Skan(define_insn "*mulhisi3tt" 1298132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1299132718Skan (mult:SI (ashiftrt:SI 1300132718Skan (match_operand:SI 1 "s_register_operand" "r") 1301132718Skan (const_int 16)) 1302132718Skan (ashiftrt:SI 1303132718Skan (match_operand:SI 2 "s_register_operand" "r") 1304132718Skan (const_int 16))))] 1305132718Skan "TARGET_ARM && arm_arch5e" 1306132718Skan "smultt%?\\t%0, %1, %2" 1307169689Skan [(set_attr "insn" "smulxy") 1308132718Skan (set_attr "predicable" "yes")] 1309132718Skan) 1310132718Skan 131190075Sobrien(define_insn "*mulhisi3addsi" 131290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 131390075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r") 131490075Sobrien (mult:SI (sign_extend:SI 131590075Sobrien (match_operand:HI 2 "s_register_operand" "%r")) 131690075Sobrien (sign_extend:SI 131790075Sobrien (match_operand:HI 3 "s_register_operand" "r")))))] 1318132718Skan "TARGET_ARM && arm_arch5e" 131990075Sobrien "smlabb%?\\t%0, %2, %3, %1" 1320169689Skan [(set_attr "insn" "smlaxy") 1321132718Skan (set_attr "predicable" "yes")] 132290075Sobrien) 132390075Sobrien 132490075Sobrien(define_insn "*mulhidi3adddi" 132590075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r") 132690075Sobrien (plus:DI 132790075Sobrien (match_operand:DI 1 "s_register_operand" "0") 132890075Sobrien (mult:DI (sign_extend:DI 132990075Sobrien (match_operand:HI 2 "s_register_operand" "%r")) 133090075Sobrien (sign_extend:DI 133190075Sobrien (match_operand:HI 3 "s_register_operand" "r")))))] 1332132718Skan "TARGET_ARM && arm_arch5e" 133390075Sobrien "smlalbb%?\\t%Q0, %R0, %2, %3" 1334169689Skan [(set_attr "insn" "smlalxy") 1335132718Skan (set_attr "predicable" "yes")]) 133690075Sobrien 1337132718Skan(define_expand "mulsf3" 1338132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 1339132718Skan (mult:SF (match_operand:SF 1 "s_register_operand" "") 1340169689Skan (match_operand:SF 2 "arm_float_rhs_operand" "")))] 1341169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 1342132718Skan " 1343169689Skan if (TARGET_MAVERICK 1344132718Skan && !cirrus_fp_register (operands[2], SFmode)) 1345132718Skan operands[2] = force_reg (SFmode, operands[2]); 1346132718Skan") 134790075Sobrien 1348132718Skan(define_expand "muldf3" 1349132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 1350132718Skan (mult:DF (match_operand:DF 1 "s_register_operand" "") 1351169689Skan (match_operand:DF 2 "arm_float_rhs_operand" "")))] 1352169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 1353132718Skan " 1354169689Skan if (TARGET_MAVERICK 1355132718Skan && !cirrus_fp_register (operands[2], DFmode)) 1356132718Skan operands[2] = force_reg (DFmode, operands[2]); 1357132718Skan") 135890075Sobrien 135990075Sobrien;; Division insns 136090075Sobrien 1361132718Skan(define_expand "divsf3" 1362132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 1363169689Skan (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "") 1364169689Skan (match_operand:SF 2 "arm_float_rhs_operand" "")))] 1365169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 1366132718Skan "") 136790075Sobrien 1368132718Skan(define_expand "divdf3" 1369132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 1370169689Skan (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "") 1371169689Skan (match_operand:DF 2 "arm_float_rhs_operand" "")))] 1372169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 1373132718Skan "") 137490075Sobrien 137590075Sobrien;; Modulo insns 137690075Sobrien 1377132718Skan(define_expand "modsf3" 1378132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 1379132718Skan (mod:SF (match_operand:SF 1 "s_register_operand" "") 1380169689Skan (match_operand:SF 2 "arm_float_rhs_operand" "")))] 1381169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA" 1382132718Skan "") 138390075Sobrien 1384132718Skan(define_expand "moddf3" 1385132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 1386132718Skan (mod:DF (match_operand:DF 1 "s_register_operand" "") 1387169689Skan (match_operand:DF 2 "arm_float_rhs_operand" "")))] 1388169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA" 1389132718Skan "") 139090075Sobrien 139190075Sobrien;; Boolean and,ior,xor insns 139290075Sobrien 139390075Sobrien;; Split up double word logical operations 139490075Sobrien 139590075Sobrien;; Split up simple DImode logical operations. Simply perform the logical 139690075Sobrien;; operation on the upper and lower halves of the registers. 139790075Sobrien(define_split 139890075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 139990075Sobrien (match_operator:DI 6 "logical_binary_operator" 140090075Sobrien [(match_operand:DI 1 "s_register_operand" "") 140190075Sobrien (match_operand:DI 2 "s_register_operand" "")]))] 1402132718Skan "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))" 140390075Sobrien [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)])) 140490075Sobrien (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))] 140590075Sobrien " 140690075Sobrien { 140790075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 140890075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 140990075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 141090075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 141190075Sobrien operands[5] = gen_highpart (SImode, operands[2]); 141290075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 141390075Sobrien }" 141490075Sobrien) 141590075Sobrien 141690075Sobrien(define_split 141790075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 141890075Sobrien (match_operator:DI 6 "logical_binary_operator" 141990075Sobrien [(sign_extend:DI (match_operand:SI 2 "s_register_operand" "")) 142090075Sobrien (match_operand:DI 1 "s_register_operand" "")]))] 142190075Sobrien "TARGET_ARM && reload_completed" 142290075Sobrien [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)])) 142390075Sobrien (set (match_dup 3) (match_op_dup:SI 6 142490075Sobrien [(ashiftrt:SI (match_dup 2) (const_int 31)) 142590075Sobrien (match_dup 4)]))] 142690075Sobrien " 142790075Sobrien { 142890075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 142990075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 143090075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 143190075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 143290075Sobrien operands[5] = gen_highpart (SImode, operands[2]); 143390075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 143490075Sobrien }" 143590075Sobrien) 143690075Sobrien 143790075Sobrien;; The zero extend of operand 2 means we can just copy the high part of 143890075Sobrien;; operand1 into operand0. 143990075Sobrien(define_split 144090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 144190075Sobrien (ior:DI 144290075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")) 144390075Sobrien (match_operand:DI 1 "s_register_operand" "")))] 144490075Sobrien "TARGET_ARM && operands[0] != operands[1] && reload_completed" 144590075Sobrien [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2))) 144690075Sobrien (set (match_dup 3) (match_dup 4))] 144790075Sobrien " 144890075Sobrien { 144990075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 145090075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 145190075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 145290075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 145390075Sobrien }" 145490075Sobrien) 145590075Sobrien 145690075Sobrien;; The zero extend of operand 2 means we can just copy the high part of 145790075Sobrien;; operand1 into operand0. 145890075Sobrien(define_split 145990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 146090075Sobrien (xor:DI 146190075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")) 146290075Sobrien (match_operand:DI 1 "s_register_operand" "")))] 146390075Sobrien "TARGET_ARM && operands[0] != operands[1] && reload_completed" 146490075Sobrien [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) 146590075Sobrien (set (match_dup 3) (match_dup 4))] 146690075Sobrien " 146790075Sobrien { 146890075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 146990075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 147090075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 147190075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 147290075Sobrien }" 147390075Sobrien) 147490075Sobrien 147590075Sobrien(define_insn "anddi3" 147690075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 147790075Sobrien (and:DI (match_operand:DI 1 "s_register_operand" "%0,r") 147890075Sobrien (match_operand:DI 2 "s_register_operand" "r,r")))] 1479132718Skan "TARGET_ARM && ! TARGET_IWMMXT" 148090075Sobrien "#" 148190075Sobrien [(set_attr "length" "8")] 148290075Sobrien) 148390075Sobrien 148490075Sobrien(define_insn_and_split "*anddi_zesidi_di" 148590075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 148690075Sobrien (and:DI (zero_extend:DI 148790075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 148890075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0")))] 148990075Sobrien "TARGET_ARM" 149090075Sobrien "#" 149190075Sobrien "TARGET_ARM && reload_completed" 149290075Sobrien ; The zero extend of operand 2 clears the high word of the output 149390075Sobrien ; operand. 149490075Sobrien [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2))) 149590075Sobrien (set (match_dup 3) (const_int 0))] 149690075Sobrien " 149790075Sobrien { 149890075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 149990075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 150090075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 150190075Sobrien }" 150290075Sobrien [(set_attr "length" "8")] 150390075Sobrien) 150490075Sobrien 150590075Sobrien(define_insn "*anddi_sesdi_di" 150690075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 150790075Sobrien (and:DI (sign_extend:DI 150890075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 150990075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0")))] 151090075Sobrien "TARGET_ARM" 151190075Sobrien "#" 151290075Sobrien [(set_attr "length" "8")] 151390075Sobrien) 151490075Sobrien 151590075Sobrien(define_expand "andsi3" 151690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 151790075Sobrien (and:SI (match_operand:SI 1 "s_register_operand" "") 151890075Sobrien (match_operand:SI 2 "reg_or_int_operand" "")))] 151990075Sobrien "TARGET_EITHER" 152090075Sobrien " 152190075Sobrien if (TARGET_ARM) 152290075Sobrien { 152390075Sobrien if (GET_CODE (operands[2]) == CONST_INT) 152490075Sobrien { 1525169689Skan arm_split_constant (AND, SImode, NULL_RTX, 1526169689Skan INTVAL (operands[2]), operands[0], 1527169689Skan operands[1], optimize && !no_new_pseudos); 1528169689Skan 152990075Sobrien DONE; 153090075Sobrien } 153190075Sobrien } 153290075Sobrien else /* TARGET_THUMB */ 153390075Sobrien { 153490075Sobrien if (GET_CODE (operands[2]) != CONST_INT) 153590075Sobrien operands[2] = force_reg (SImode, operands[2]); 153690075Sobrien else 153790075Sobrien { 153890075Sobrien int i; 153990075Sobrien 154090075Sobrien if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256) 154190075Sobrien { 154290075Sobrien operands[2] = force_reg (SImode, 154390075Sobrien GEN_INT (~INTVAL (operands[2]))); 154490075Sobrien 154590075Sobrien emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1])); 154690075Sobrien 154790075Sobrien DONE; 154890075Sobrien } 154990075Sobrien 155090075Sobrien for (i = 9; i <= 31; i++) 155190075Sobrien { 155290075Sobrien if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2])) 155390075Sobrien { 155490075Sobrien emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i), 155590075Sobrien const0_rtx)); 155690075Sobrien DONE; 155790075Sobrien } 155890075Sobrien else if ((((HOST_WIDE_INT) 1) << i) - 1 155990075Sobrien == ~INTVAL (operands[2])) 156090075Sobrien { 156190075Sobrien rtx shift = GEN_INT (i); 156290075Sobrien rtx reg = gen_reg_rtx (SImode); 156390075Sobrien 156490075Sobrien emit_insn (gen_lshrsi3 (reg, operands[1], shift)); 156590075Sobrien emit_insn (gen_ashlsi3 (operands[0], reg, shift)); 156690075Sobrien 156790075Sobrien DONE; 156890075Sobrien } 156990075Sobrien } 157090075Sobrien 157190075Sobrien operands[2] = force_reg (SImode, operands[2]); 157290075Sobrien } 157390075Sobrien } 157490075Sobrien " 157590075Sobrien) 157690075Sobrien 157790075Sobrien(define_insn_and_split "*arm_andsi3_insn" 157890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 157990075Sobrien (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r") 158090075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] 158190075Sobrien "TARGET_ARM" 158290075Sobrien "@ 158390075Sobrien and%?\\t%0, %1, %2 158490075Sobrien bic%?\\t%0, %1, #%B2 158590075Sobrien #" 158690075Sobrien "TARGET_ARM 158790075Sobrien && GET_CODE (operands[2]) == CONST_INT 158890075Sobrien && !(const_ok_for_arm (INTVAL (operands[2])) 158990075Sobrien || const_ok_for_arm (~INTVAL (operands[2])))" 159090075Sobrien [(clobber (const_int 0))] 159190075Sobrien " 1592169689Skan arm_split_constant (AND, SImode, curr_insn, 1593169689Skan INTVAL (operands[2]), operands[0], operands[1], 0); 159490075Sobrien DONE; 159590075Sobrien " 159690075Sobrien [(set_attr "length" "4,4,16") 159790075Sobrien (set_attr "predicable" "yes")] 159890075Sobrien) 159990075Sobrien 160090075Sobrien(define_insn "*thumb_andsi3_insn" 160190075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 160290075Sobrien (and:SI (match_operand:SI 1 "register_operand" "%0") 160390075Sobrien (match_operand:SI 2 "register_operand" "l")))] 160490075Sobrien "TARGET_THUMB" 160590075Sobrien "and\\t%0, %0, %2" 160690075Sobrien [(set_attr "length" "2")] 160790075Sobrien) 160890075Sobrien 160990075Sobrien(define_insn "*andsi3_compare0" 161090075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 161190075Sobrien (compare:CC_NOOV 161290075Sobrien (and:SI (match_operand:SI 1 "s_register_operand" "r,r") 161390075Sobrien (match_operand:SI 2 "arm_not_operand" "rI,K")) 161490075Sobrien (const_int 0))) 161590075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 161690075Sobrien (and:SI (match_dup 1) (match_dup 2)))] 161790075Sobrien "TARGET_ARM" 161890075Sobrien "@ 161990075Sobrien and%?s\\t%0, %1, %2 162090075Sobrien bic%?s\\t%0, %1, #%B2" 162190075Sobrien [(set_attr "conds" "set")] 162290075Sobrien) 162390075Sobrien 162490075Sobrien(define_insn "*andsi3_compare0_scratch" 162590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 162690075Sobrien (compare:CC_NOOV 162790075Sobrien (and:SI (match_operand:SI 0 "s_register_operand" "r,r") 162890075Sobrien (match_operand:SI 1 "arm_not_operand" "rI,K")) 162990075Sobrien (const_int 0))) 163090075Sobrien (clobber (match_scratch:SI 2 "=X,r"))] 163190075Sobrien "TARGET_ARM" 163290075Sobrien "@ 163390075Sobrien tst%?\\t%0, %1 163490075Sobrien bic%?s\\t%2, %0, #%B1" 163590075Sobrien [(set_attr "conds" "set")] 163690075Sobrien) 163790075Sobrien 163890075Sobrien(define_insn "*zeroextractsi_compare0_scratch" 163990075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 164090075Sobrien (compare:CC_NOOV (zero_extract:SI 164190075Sobrien (match_operand:SI 0 "s_register_operand" "r") 164290075Sobrien (match_operand 1 "const_int_operand" "n") 164390075Sobrien (match_operand 2 "const_int_operand" "n")) 164490075Sobrien (const_int 0)))] 164590075Sobrien "TARGET_ARM 164690075Sobrien && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32 164790075Sobrien && INTVAL (operands[1]) > 0 164890075Sobrien && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8 164990075Sobrien && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)" 165090075Sobrien "* 165190075Sobrien operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1) 165290075Sobrien << INTVAL (operands[2])); 165390075Sobrien output_asm_insn (\"tst%?\\t%0, %1\", operands); 165490075Sobrien return \"\"; 165590075Sobrien " 165690075Sobrien [(set_attr "conds" "set")] 165790075Sobrien) 165890075Sobrien 1659169689Skan(define_insn_and_split "*ne_zeroextractsi" 166090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 166190075Sobrien (ne:SI (zero_extract:SI 166290075Sobrien (match_operand:SI 1 "s_register_operand" "r") 166390075Sobrien (match_operand:SI 2 "const_int_operand" "n") 166490075Sobrien (match_operand:SI 3 "const_int_operand" "n")) 1665104752Skan (const_int 0))) 1666104752Skan (clobber (reg:CC CC_REGNUM))] 166790075Sobrien "TARGET_ARM 166890075Sobrien && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 166990075Sobrien && INTVAL (operands[2]) > 0 167090075Sobrien && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 167190075Sobrien && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)" 1672169689Skan "#" 1673169689Skan "TARGET_ARM 1674169689Skan && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 1675169689Skan && INTVAL (operands[2]) > 0 1676169689Skan && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 1677169689Skan && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)" 1678169689Skan [(parallel [(set (reg:CC_NOOV CC_REGNUM) 1679169689Skan (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2)) 1680169689Skan (const_int 0))) 1681169689Skan (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))]) 1682169689Skan (set (match_dup 0) 1683169689Skan (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0)) 1684169689Skan (match_dup 0) (const_int 1)))] 1685169689Skan " 168690075Sobrien operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1) 1687169689Skan << INTVAL (operands[3])); 168890075Sobrien " 168990075Sobrien [(set_attr "conds" "clob") 169090075Sobrien (set_attr "length" "8")] 169190075Sobrien) 169290075Sobrien 1693169689Skan(define_insn_and_split "*ne_zeroextractsi_shifted" 1694169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1695169689Skan (ne:SI (zero_extract:SI 1696169689Skan (match_operand:SI 1 "s_register_operand" "r") 1697169689Skan (match_operand:SI 2 "const_int_operand" "n") 1698169689Skan (const_int 0)) 1699169689Skan (const_int 0))) 1700169689Skan (clobber (reg:CC CC_REGNUM))] 1701169689Skan "TARGET_ARM" 1702169689Skan "#" 1703169689Skan "TARGET_ARM" 1704169689Skan [(parallel [(set (reg:CC_NOOV CC_REGNUM) 1705169689Skan (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2)) 1706169689Skan (const_int 0))) 1707169689Skan (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))]) 1708169689Skan (set (match_dup 0) 1709169689Skan (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0)) 1710169689Skan (match_dup 0) (const_int 1)))] 1711169689Skan " 1712169689Skan operands[2] = GEN_INT (32 - INTVAL (operands[2])); 1713169689Skan " 1714169689Skan [(set_attr "conds" "clob") 1715169689Skan (set_attr "length" "8")] 1716169689Skan) 1717169689Skan 1718169689Skan(define_insn_and_split "*ite_ne_zeroextractsi" 1719169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1720169689Skan (if_then_else:SI (ne (zero_extract:SI 1721169689Skan (match_operand:SI 1 "s_register_operand" "r") 1722169689Skan (match_operand:SI 2 "const_int_operand" "n") 1723169689Skan (match_operand:SI 3 "const_int_operand" "n")) 1724169689Skan (const_int 0)) 1725169689Skan (match_operand:SI 4 "arm_not_operand" "rIK") 1726169689Skan (const_int 0))) 1727169689Skan (clobber (reg:CC CC_REGNUM))] 1728169689Skan "TARGET_ARM 1729169689Skan && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 1730169689Skan && INTVAL (operands[2]) > 0 1731169689Skan && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 1732169689Skan && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32) 1733169689Skan && !reg_overlap_mentioned_p (operands[0], operands[4])" 1734169689Skan "#" 1735169689Skan "TARGET_ARM 1736169689Skan && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 1737169689Skan && INTVAL (operands[2]) > 0 1738169689Skan && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 1739169689Skan && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32) 1740169689Skan && !reg_overlap_mentioned_p (operands[0], operands[4])" 1741169689Skan [(parallel [(set (reg:CC_NOOV CC_REGNUM) 1742169689Skan (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2)) 1743169689Skan (const_int 0))) 1744169689Skan (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))]) 1745169689Skan (set (match_dup 0) 1746169689Skan (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0)) 1747169689Skan (match_dup 0) (match_dup 4)))] 1748169689Skan " 1749169689Skan operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1) 1750169689Skan << INTVAL (operands[3])); 1751169689Skan " 1752169689Skan [(set_attr "conds" "clob") 1753169689Skan (set_attr "length" "8")] 1754169689Skan) 1755169689Skan 1756169689Skan(define_insn_and_split "*ite_ne_zeroextractsi_shifted" 1757169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1758169689Skan (if_then_else:SI (ne (zero_extract:SI 1759169689Skan (match_operand:SI 1 "s_register_operand" "r") 1760169689Skan (match_operand:SI 2 "const_int_operand" "n") 1761169689Skan (const_int 0)) 1762169689Skan (const_int 0)) 1763169689Skan (match_operand:SI 3 "arm_not_operand" "rIK") 1764169689Skan (const_int 0))) 1765169689Skan (clobber (reg:CC CC_REGNUM))] 1766169689Skan "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])" 1767169689Skan "#" 1768169689Skan "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])" 1769169689Skan [(parallel [(set (reg:CC_NOOV CC_REGNUM) 1770169689Skan (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2)) 1771169689Skan (const_int 0))) 1772169689Skan (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))]) 1773169689Skan (set (match_dup 0) 1774169689Skan (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0)) 1775169689Skan (match_dup 0) (match_dup 3)))] 1776169689Skan " 1777169689Skan operands[2] = GEN_INT (32 - INTVAL (operands[2])); 1778169689Skan " 1779169689Skan [(set_attr "conds" "clob") 1780169689Skan (set_attr "length" "8")] 1781169689Skan) 1782169689Skan 1783132718Skan(define_split 1784132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 1785132718Skan (zero_extract:SI (match_operand:SI 1 "s_register_operand" "") 1786132718Skan (match_operand:SI 2 "const_int_operand" "") 1787132718Skan (match_operand:SI 3 "const_int_operand" ""))) 1788132718Skan (clobber (match_operand:SI 4 "s_register_operand" ""))] 1789132718Skan "TARGET_THUMB" 1790132718Skan [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2))) 1791132718Skan (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))] 1792132718Skan "{ 1793132718Skan HOST_WIDE_INT temp = INTVAL (operands[2]); 1794132718Skan 1795132718Skan operands[2] = GEN_INT (32 - temp - INTVAL (operands[3])); 1796132718Skan operands[3] = GEN_INT (32 - temp); 1797132718Skan }" 1798132718Skan) 1799132718Skan 1800132718Skan(define_split 1801132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 1802132718Skan (match_operator:SI 1 "shiftable_operator" 1803132718Skan [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 1804132718Skan (match_operand:SI 3 "const_int_operand" "") 1805132718Skan (match_operand:SI 4 "const_int_operand" "")) 1806132718Skan (match_operand:SI 5 "s_register_operand" "")])) 1807132718Skan (clobber (match_operand:SI 6 "s_register_operand" ""))] 1808132718Skan "TARGET_ARM" 1809132718Skan [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3))) 1810132718Skan (set (match_dup 0) 1811132718Skan (match_op_dup 1 1812132718Skan [(lshiftrt:SI (match_dup 6) (match_dup 4)) 1813132718Skan (match_dup 5)]))] 1814132718Skan "{ 1815132718Skan HOST_WIDE_INT temp = INTVAL (operands[3]); 1816132718Skan 1817132718Skan operands[3] = GEN_INT (32 - temp - INTVAL (operands[4])); 1818132718Skan operands[4] = GEN_INT (32 - temp); 1819132718Skan }" 1820132718Skan) 1821132718Skan 1822132718Skan(define_split 1823132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 1824132718Skan (sign_extract:SI (match_operand:SI 1 "s_register_operand" "") 1825132718Skan (match_operand:SI 2 "const_int_operand" "") 1826132718Skan (match_operand:SI 3 "const_int_operand" "")))] 1827132718Skan "TARGET_THUMB" 1828132718Skan [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) 1829132718Skan (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))] 1830132718Skan "{ 1831132718Skan HOST_WIDE_INT temp = INTVAL (operands[2]); 1832132718Skan 1833132718Skan operands[2] = GEN_INT (32 - temp - INTVAL (operands[3])); 1834132718Skan operands[3] = GEN_INT (32 - temp); 1835132718Skan }" 1836132718Skan) 1837132718Skan 1838132718Skan(define_split 1839132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 1840132718Skan (match_operator:SI 1 "shiftable_operator" 1841132718Skan [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 1842132718Skan (match_operand:SI 3 "const_int_operand" "") 1843132718Skan (match_operand:SI 4 "const_int_operand" "")) 1844132718Skan (match_operand:SI 5 "s_register_operand" "")])) 1845132718Skan (clobber (match_operand:SI 6 "s_register_operand" ""))] 1846132718Skan "TARGET_ARM" 1847132718Skan [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3))) 1848132718Skan (set (match_dup 0) 1849132718Skan (match_op_dup 1 1850132718Skan [(ashiftrt:SI (match_dup 6) (match_dup 4)) 1851132718Skan (match_dup 5)]))] 1852132718Skan "{ 1853132718Skan HOST_WIDE_INT temp = INTVAL (operands[3]); 1854132718Skan 1855132718Skan operands[3] = GEN_INT (32 - temp - INTVAL (operands[4])); 1856132718Skan operands[4] = GEN_INT (32 - temp); 1857132718Skan }" 1858132718Skan) 1859132718Skan 186090075Sobrien;;; ??? This pattern is bogus. If operand3 has bits outside the range 186190075Sobrien;;; represented by the bitfield, then this will produce incorrect results. 186290075Sobrien;;; Somewhere, the value needs to be truncated. On targets like the m68k, 1863117395Skan;;; which have a real bit-field insert instruction, the truncation happens 1864117395Skan;;; in the bit-field insert instruction itself. Since arm does not have a 1865117395Skan;;; bit-field insert instruction, we would have to emit code here to truncate 186690075Sobrien;;; the value before we insert. This loses some of the advantage of having 186790075Sobrien;;; this insv pattern, so this pattern needs to be reevalutated. 186890075Sobrien 186990075Sobrien(define_expand "insv" 187090075Sobrien [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "") 187190075Sobrien (match_operand:SI 1 "general_operand" "") 187290075Sobrien (match_operand:SI 2 "general_operand" "")) 1873117395Skan (match_operand:SI 3 "reg_or_int_operand" ""))] 187490075Sobrien "TARGET_ARM" 187590075Sobrien " 187690075Sobrien { 187790075Sobrien int start_bit = INTVAL (operands[2]); 187890075Sobrien int width = INTVAL (operands[1]); 187990075Sobrien HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1; 188090075Sobrien rtx target, subtarget; 188190075Sobrien 188290075Sobrien target = operands[0]; 188390075Sobrien /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 188490075Sobrien subreg as the final target. */ 188590075Sobrien if (GET_CODE (target) == SUBREG) 188690075Sobrien { 188790075Sobrien subtarget = gen_reg_rtx (SImode); 188890075Sobrien if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target))) 188990075Sobrien < GET_MODE_SIZE (SImode)) 189090075Sobrien target = SUBREG_REG (target); 189190075Sobrien } 189290075Sobrien else 189390075Sobrien subtarget = target; 189490075Sobrien 189590075Sobrien if (GET_CODE (operands[3]) == CONST_INT) 189690075Sobrien { 189790075Sobrien /* Since we are inserting a known constant, we may be able to 189890075Sobrien reduce the number of bits that we have to clear so that 189990075Sobrien the mask becomes simple. */ 190090075Sobrien /* ??? This code does not check to see if the new mask is actually 190190075Sobrien simpler. It may not be. */ 190290075Sobrien rtx op1 = gen_reg_rtx (SImode); 190390075Sobrien /* ??? Truncate operand3 to fit in the bitfield. See comment before 190490075Sobrien start of this pattern. */ 190590075Sobrien HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]); 190690075Sobrien HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit); 190790075Sobrien 1908169689Skan emit_insn (gen_andsi3 (op1, operands[0], 1909169689Skan gen_int_mode (~mask2, SImode))); 191090075Sobrien emit_insn (gen_iorsi3 (subtarget, op1, 1911169689Skan gen_int_mode (op3_value << start_bit, SImode))); 191290075Sobrien } 191390075Sobrien else if (start_bit == 0 191490075Sobrien && !(const_ok_for_arm (mask) 191590075Sobrien || const_ok_for_arm (~mask))) 191690075Sobrien { 191790075Sobrien /* A Trick, since we are setting the bottom bits in the word, 191890075Sobrien we can shift operand[3] up, operand[0] down, OR them together 191990075Sobrien and rotate the result back again. This takes 3 insns, and 1920132718Skan the third might be mergeable into another op. */ 192190075Sobrien /* The shift up copes with the possibility that operand[3] is 192290075Sobrien wider than the bitfield. */ 192390075Sobrien rtx op0 = gen_reg_rtx (SImode); 192490075Sobrien rtx op1 = gen_reg_rtx (SImode); 192590075Sobrien 192690075Sobrien emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 192790075Sobrien emit_insn (gen_lshrsi3 (op1, operands[0], operands[1])); 192890075Sobrien emit_insn (gen_iorsi3 (op1, op1, op0)); 192990075Sobrien emit_insn (gen_rotlsi3 (subtarget, op1, operands[1])); 193090075Sobrien } 193190075Sobrien else if ((width + start_bit == 32) 193290075Sobrien && !(const_ok_for_arm (mask) 193390075Sobrien || const_ok_for_arm (~mask))) 193490075Sobrien { 193590075Sobrien /* Similar trick, but slightly less efficient. */ 193690075Sobrien 193790075Sobrien rtx op0 = gen_reg_rtx (SImode); 193890075Sobrien rtx op1 = gen_reg_rtx (SImode); 193990075Sobrien 194090075Sobrien emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 194190075Sobrien emit_insn (gen_ashlsi3 (op1, operands[0], operands[1])); 194290075Sobrien emit_insn (gen_lshrsi3 (op1, op1, operands[1])); 194390075Sobrien emit_insn (gen_iorsi3 (subtarget, op1, op0)); 194490075Sobrien } 194590075Sobrien else 194690075Sobrien { 1947169689Skan rtx op0 = gen_int_mode (mask, SImode); 194890075Sobrien rtx op1 = gen_reg_rtx (SImode); 194990075Sobrien rtx op2 = gen_reg_rtx (SImode); 195090075Sobrien 195190075Sobrien if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask))) 195290075Sobrien { 195390075Sobrien rtx tmp = gen_reg_rtx (SImode); 195490075Sobrien 195590075Sobrien emit_insn (gen_movsi (tmp, op0)); 195690075Sobrien op0 = tmp; 195790075Sobrien } 195890075Sobrien 195990075Sobrien /* Mask out any bits in operand[3] that are not needed. */ 196090075Sobrien emit_insn (gen_andsi3 (op1, operands[3], op0)); 196190075Sobrien 196290075Sobrien if (GET_CODE (op0) == CONST_INT 196390075Sobrien && (const_ok_for_arm (mask << start_bit) 196490075Sobrien || const_ok_for_arm (~(mask << start_bit)))) 196590075Sobrien { 1966169689Skan op0 = gen_int_mode (~(mask << start_bit), SImode); 196790075Sobrien emit_insn (gen_andsi3 (op2, operands[0], op0)); 196890075Sobrien } 196990075Sobrien else 197090075Sobrien { 197190075Sobrien if (GET_CODE (op0) == CONST_INT) 197290075Sobrien { 197390075Sobrien rtx tmp = gen_reg_rtx (SImode); 197490075Sobrien 197590075Sobrien emit_insn (gen_movsi (tmp, op0)); 197690075Sobrien op0 = tmp; 197790075Sobrien } 197890075Sobrien 197990075Sobrien if (start_bit != 0) 198090075Sobrien emit_insn (gen_ashlsi3 (op0, op0, operands[2])); 198190075Sobrien 198290075Sobrien emit_insn (gen_andsi_notsi_si (op2, operands[0], op0)); 198390075Sobrien } 198490075Sobrien 198590075Sobrien if (start_bit != 0) 198690075Sobrien emit_insn (gen_ashlsi3 (op1, op1, operands[2])); 198790075Sobrien 198890075Sobrien emit_insn (gen_iorsi3 (subtarget, op1, op2)); 198990075Sobrien } 199090075Sobrien 199190075Sobrien if (subtarget != target) 199290075Sobrien { 199390075Sobrien /* If TARGET is still a SUBREG, then it must be wider than a word, 199490075Sobrien so we must be careful only to set the subword we were asked to. */ 199590075Sobrien if (GET_CODE (target) == SUBREG) 199690075Sobrien emit_move_insn (target, subtarget); 199790075Sobrien else 199890075Sobrien emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget)); 199990075Sobrien } 200090075Sobrien 200190075Sobrien DONE; 200290075Sobrien }" 200390075Sobrien) 200490075Sobrien 200590075Sobrien; constants for op 2 will never be given to these patterns. 200690075Sobrien(define_insn_and_split "*anddi_notdi_di" 200790075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 200890075Sobrien (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0")) 200990075Sobrien (match_operand:DI 2 "s_register_operand" "0,r")))] 201090075Sobrien "TARGET_ARM" 201190075Sobrien "#" 2012132718Skan "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))" 201390075Sobrien [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2))) 201490075Sobrien (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))] 201590075Sobrien " 201690075Sobrien { 201790075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 201890075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 201990075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 202090075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 202190075Sobrien operands[5] = gen_highpart (SImode, operands[2]); 202290075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 202390075Sobrien }" 202490075Sobrien [(set_attr "length" "8") 202590075Sobrien (set_attr "predicable" "yes")] 202690075Sobrien) 202790075Sobrien 202890075Sobrien(define_insn_and_split "*anddi_notzesidi_di" 202990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 203090075Sobrien (and:DI (not:DI (zero_extend:DI 203190075Sobrien (match_operand:SI 2 "s_register_operand" "r,r"))) 203290075Sobrien (match_operand:DI 1 "s_register_operand" "0,?r")))] 203390075Sobrien "TARGET_ARM" 203490075Sobrien "@ 203590075Sobrien bic%?\\t%Q0, %Q1, %2 203690075Sobrien #" 203790075Sobrien ; (not (zero_extend ...)) allows us to just copy the high word from 203890075Sobrien ; operand1 to operand0. 203990075Sobrien "TARGET_ARM 204090075Sobrien && reload_completed 204190075Sobrien && operands[0] != operands[1]" 2042117395Skan [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) 204390075Sobrien (set (match_dup 3) (match_dup 4))] 204490075Sobrien " 204590075Sobrien { 204690075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 204790075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 204890075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 204990075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 205090075Sobrien }" 205190075Sobrien [(set_attr "length" "4,8") 205290075Sobrien (set_attr "predicable" "yes")] 205390075Sobrien) 205490075Sobrien 205590075Sobrien(define_insn_and_split "*anddi_notsesidi_di" 205690075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 205790075Sobrien (and:DI (not:DI (sign_extend:DI 205890075Sobrien (match_operand:SI 2 "s_register_operand" "r,r"))) 2059117395Skan (match_operand:DI 1 "s_register_operand" "0,r")))] 206090075Sobrien "TARGET_ARM" 206190075Sobrien "#" 206290075Sobrien "TARGET_ARM && reload_completed" 2063117395Skan [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) 206490075Sobrien (set (match_dup 3) (and:SI (not:SI 206590075Sobrien (ashiftrt:SI (match_dup 2) (const_int 31))) 206690075Sobrien (match_dup 4)))] 206790075Sobrien " 206890075Sobrien { 206990075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 207090075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 207190075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 207290075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 207390075Sobrien }" 207490075Sobrien [(set_attr "length" "8") 207590075Sobrien (set_attr "predicable" "yes")] 207690075Sobrien) 207790075Sobrien 207890075Sobrien(define_insn "andsi_notsi_si" 207990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 208090075Sobrien (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 208190075Sobrien (match_operand:SI 1 "s_register_operand" "r")))] 208290075Sobrien "TARGET_ARM" 208390075Sobrien "bic%?\\t%0, %1, %2" 208490075Sobrien [(set_attr "predicable" "yes")] 208590075Sobrien) 208690075Sobrien 208790075Sobrien(define_insn "bicsi3" 208890075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 208990075Sobrien (and:SI (not:SI (match_operand:SI 1 "register_operand" "l")) 209090075Sobrien (match_operand:SI 2 "register_operand" "0")))] 209190075Sobrien "TARGET_THUMB" 209290075Sobrien "bic\\t%0, %0, %1" 209390075Sobrien [(set_attr "length" "2")] 209490075Sobrien) 209590075Sobrien 209690075Sobrien(define_insn "andsi_not_shiftsi_si" 2097169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 2098169689Skan (and:SI (not:SI (match_operator:SI 4 "shift_operator" 2099169689Skan [(match_operand:SI 2 "s_register_operand" "r") 2100169689Skan (match_operand:SI 3 "arm_rhs_operand" "rM")])) 2101169689Skan (match_operand:SI 1 "s_register_operand" "r")))] 210290075Sobrien "TARGET_ARM" 210390075Sobrien "bic%?\\t%0, %1, %2%S4" 210490075Sobrien [(set_attr "predicable" "yes") 210590075Sobrien (set_attr "shift" "2") 2106169689Skan (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "") 2107169689Skan (const_string "alu_shift") 2108169689Skan (const_string "alu_shift_reg")))] 210990075Sobrien) 211090075Sobrien 211190075Sobrien(define_insn "*andsi_notsi_si_compare0" 211290075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 211390075Sobrien (compare:CC_NOOV 211490075Sobrien (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 211590075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 211690075Sobrien (const_int 0))) 211790075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 211890075Sobrien (and:SI (not:SI (match_dup 2)) (match_dup 1)))] 211990075Sobrien "TARGET_ARM" 212090075Sobrien "bic%?s\\t%0, %1, %2" 212190075Sobrien [(set_attr "conds" "set")] 212290075Sobrien) 212390075Sobrien 212490075Sobrien(define_insn "*andsi_notsi_si_compare0_scratch" 212590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 212690075Sobrien (compare:CC_NOOV 212790075Sobrien (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 212890075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 212990075Sobrien (const_int 0))) 213090075Sobrien (clobber (match_scratch:SI 0 "=r"))] 213190075Sobrien "TARGET_ARM" 213290075Sobrien "bic%?s\\t%0, %1, %2" 213390075Sobrien [(set_attr "conds" "set")] 213490075Sobrien) 213590075Sobrien 213690075Sobrien(define_insn "iordi3" 213790075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 213890075Sobrien (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r") 213990075Sobrien (match_operand:DI 2 "s_register_operand" "r,r")))] 2140132718Skan "TARGET_ARM && ! TARGET_IWMMXT" 214190075Sobrien "#" 214290075Sobrien [(set_attr "length" "8") 214390075Sobrien (set_attr "predicable" "yes")] 214490075Sobrien) 214590075Sobrien 214690075Sobrien(define_insn "*iordi_zesidi_di" 214790075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 214890075Sobrien (ior:DI (zero_extend:DI 214990075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 215090075Sobrien (match_operand:DI 1 "s_register_operand" "0,?r")))] 215190075Sobrien "TARGET_ARM" 215290075Sobrien "@ 215390075Sobrien orr%?\\t%Q0, %Q1, %2 215490075Sobrien #" 215590075Sobrien [(set_attr "length" "4,8") 215690075Sobrien (set_attr "predicable" "yes")] 215790075Sobrien) 215890075Sobrien 215990075Sobrien(define_insn "*iordi_sesidi_di" 216090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 216190075Sobrien (ior:DI (sign_extend:DI 216290075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 216390075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0")))] 216490075Sobrien "TARGET_ARM" 216590075Sobrien "#" 216690075Sobrien [(set_attr "length" "8") 216790075Sobrien (set_attr "predicable" "yes")] 216890075Sobrien) 216990075Sobrien 217090075Sobrien(define_expand "iorsi3" 217190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 217290075Sobrien (ior:SI (match_operand:SI 1 "s_register_operand" "") 217390075Sobrien (match_operand:SI 2 "reg_or_int_operand" "")))] 217490075Sobrien "TARGET_EITHER" 217590075Sobrien " 217690075Sobrien if (GET_CODE (operands[2]) == CONST_INT) 217790075Sobrien { 217890075Sobrien if (TARGET_ARM) 217990075Sobrien { 2180169689Skan arm_split_constant (IOR, SImode, NULL_RTX, 2181169689Skan INTVAL (operands[2]), operands[0], operands[1], 2182169689Skan optimize && !no_new_pseudos); 218390075Sobrien DONE; 218490075Sobrien } 218590075Sobrien else /* TARGET_THUMB */ 218690075Sobrien operands [2] = force_reg (SImode, operands [2]); 218790075Sobrien } 218890075Sobrien " 218990075Sobrien) 219090075Sobrien 219190075Sobrien(define_insn_and_split "*arm_iorsi3" 219290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 219390075Sobrien (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") 219490075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] 219590075Sobrien "TARGET_ARM" 219690075Sobrien "@ 219790075Sobrien orr%?\\t%0, %1, %2 219890075Sobrien #" 219990075Sobrien "TARGET_ARM 220090075Sobrien && GET_CODE (operands[2]) == CONST_INT 220190075Sobrien && !const_ok_for_arm (INTVAL (operands[2]))" 220290075Sobrien [(clobber (const_int 0))] 220390075Sobrien " 2204169689Skan arm_split_constant (IOR, SImode, curr_insn, 2205169689Skan INTVAL (operands[2]), operands[0], operands[1], 0); 220690075Sobrien DONE; 220790075Sobrien " 220890075Sobrien [(set_attr "length" "4,16") 220990075Sobrien (set_attr "predicable" "yes")] 221090075Sobrien) 221190075Sobrien 221290075Sobrien(define_insn "*thumb_iorsi3" 221390075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 221490075Sobrien (ior:SI (match_operand:SI 1 "register_operand" "%0") 221590075Sobrien (match_operand:SI 2 "register_operand" "l")))] 221690075Sobrien "TARGET_THUMB" 221790075Sobrien "orr\\t%0, %0, %2" 221890075Sobrien [(set_attr "length" "2")] 221990075Sobrien) 222090075Sobrien 222190075Sobrien(define_peephole2 222290075Sobrien [(match_scratch:SI 3 "r") 2223169689Skan (set (match_operand:SI 0 "arm_general_register_operand" "") 2224169689Skan (ior:SI (match_operand:SI 1 "arm_general_register_operand" "") 222590075Sobrien (match_operand:SI 2 "const_int_operand" "")))] 222690075Sobrien "TARGET_ARM 222790075Sobrien && !const_ok_for_arm (INTVAL (operands[2])) 222890075Sobrien && const_ok_for_arm (~INTVAL (operands[2]))" 222990075Sobrien [(set (match_dup 3) (match_dup 2)) 223090075Sobrien (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))] 223190075Sobrien "" 223290075Sobrien) 223390075Sobrien 223490075Sobrien(define_insn "*iorsi3_compare0" 223590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 223690075Sobrien (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 223790075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 223890075Sobrien (const_int 0))) 223990075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 224090075Sobrien (ior:SI (match_dup 1) (match_dup 2)))] 224190075Sobrien "TARGET_ARM" 224290075Sobrien "orr%?s\\t%0, %1, %2" 224390075Sobrien [(set_attr "conds" "set")] 224490075Sobrien) 224590075Sobrien 224690075Sobrien(define_insn "*iorsi3_compare0_scratch" 224790075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 224890075Sobrien (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 224990075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 225090075Sobrien (const_int 0))) 225190075Sobrien (clobber (match_scratch:SI 0 "=r"))] 225290075Sobrien "TARGET_ARM" 225390075Sobrien "orr%?s\\t%0, %1, %2" 225490075Sobrien [(set_attr "conds" "set")] 225590075Sobrien) 225690075Sobrien 225790075Sobrien(define_insn "xordi3" 225890075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 225990075Sobrien (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r") 226090075Sobrien (match_operand:DI 2 "s_register_operand" "r,r")))] 2261132718Skan "TARGET_ARM && !TARGET_IWMMXT" 226290075Sobrien "#" 226390075Sobrien [(set_attr "length" "8") 226490075Sobrien (set_attr "predicable" "yes")] 226590075Sobrien) 226690075Sobrien 226790075Sobrien(define_insn "*xordi_zesidi_di" 226890075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 226990075Sobrien (xor:DI (zero_extend:DI 227090075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 227190075Sobrien (match_operand:DI 1 "s_register_operand" "0,?r")))] 227290075Sobrien "TARGET_ARM" 227390075Sobrien "@ 227490075Sobrien eor%?\\t%Q0, %Q1, %2 227590075Sobrien #" 227690075Sobrien [(set_attr "length" "4,8") 227790075Sobrien (set_attr "predicable" "yes")] 227890075Sobrien) 227990075Sobrien 228090075Sobrien(define_insn "*xordi_sesidi_di" 228190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 228290075Sobrien (xor:DI (sign_extend:DI 228390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 228490075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0")))] 228590075Sobrien "TARGET_ARM" 228690075Sobrien "#" 228790075Sobrien [(set_attr "length" "8") 228890075Sobrien (set_attr "predicable" "yes")] 228990075Sobrien) 229090075Sobrien 229190075Sobrien(define_expand "xorsi3" 229290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 229390075Sobrien (xor:SI (match_operand:SI 1 "s_register_operand" "") 229490075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 229590075Sobrien "TARGET_EITHER" 229690075Sobrien "if (TARGET_THUMB) 229790075Sobrien if (GET_CODE (operands[2]) == CONST_INT) 229890075Sobrien operands[2] = force_reg (SImode, operands[2]); 229990075Sobrien " 230090075Sobrien) 230190075Sobrien 230290075Sobrien(define_insn "*arm_xorsi3" 230390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 230490075Sobrien (xor:SI (match_operand:SI 1 "s_register_operand" "r") 230590075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")))] 230690075Sobrien "TARGET_ARM" 230790075Sobrien "eor%?\\t%0, %1, %2" 230890075Sobrien [(set_attr "predicable" "yes")] 230990075Sobrien) 231090075Sobrien 231190075Sobrien(define_insn "*thumb_xorsi3" 231290075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 231390075Sobrien (xor:SI (match_operand:SI 1 "register_operand" "%0") 231490075Sobrien (match_operand:SI 2 "register_operand" "l")))] 231590075Sobrien "TARGET_THUMB" 231690075Sobrien "eor\\t%0, %0, %2" 231790075Sobrien [(set_attr "length" "2")] 231890075Sobrien) 231990075Sobrien 232090075Sobrien(define_insn "*xorsi3_compare0" 232190075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 232290075Sobrien (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r") 232390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 232490075Sobrien (const_int 0))) 232590075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 232690075Sobrien (xor:SI (match_dup 1) (match_dup 2)))] 232790075Sobrien "TARGET_ARM" 232890075Sobrien "eor%?s\\t%0, %1, %2" 232990075Sobrien [(set_attr "conds" "set")] 233090075Sobrien) 233190075Sobrien 233290075Sobrien(define_insn "*xorsi3_compare0_scratch" 233390075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 233490075Sobrien (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r") 233590075Sobrien (match_operand:SI 1 "arm_rhs_operand" "rI")) 233690075Sobrien (const_int 0)))] 233790075Sobrien "TARGET_ARM" 233890075Sobrien "teq%?\\t%0, %1" 233990075Sobrien [(set_attr "conds" "set")] 234090075Sobrien) 234190075Sobrien 234290075Sobrien; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 234390075Sobrien; (NOT D) we can sometimes merge the final NOT into one of the following 234490075Sobrien; insns. 234590075Sobrien 234690075Sobrien(define_split 2347117395Skan [(set (match_operand:SI 0 "s_register_operand" "") 2348117395Skan (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "")) 2349117395Skan (not:SI (match_operand:SI 2 "arm_rhs_operand" ""))) 2350117395Skan (match_operand:SI 3 "arm_rhs_operand" ""))) 2351117395Skan (clobber (match_operand:SI 4 "s_register_operand" ""))] 235290075Sobrien "TARGET_ARM" 235390075Sobrien [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2)) 235490075Sobrien (not:SI (match_dup 3)))) 235590075Sobrien (set (match_dup 0) (not:SI (match_dup 4)))] 235690075Sobrien "" 235790075Sobrien) 235890075Sobrien 235990075Sobrien(define_insn "*andsi_iorsi3_notsi" 236090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 236190075Sobrien (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0") 236290075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")) 236390075Sobrien (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))] 236490075Sobrien "TARGET_ARM" 236590075Sobrien "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3" 236690075Sobrien [(set_attr "length" "8") 236790075Sobrien (set_attr "predicable" "yes")] 236890075Sobrien) 236990075Sobrien 2370132718Skan(define_split 2371132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2372132718Skan (match_operator:SI 1 "logical_binary_operator" 2373132718Skan [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 2374132718Skan (match_operand:SI 3 "const_int_operand" "") 2375132718Skan (match_operand:SI 4 "const_int_operand" "")) 2376132718Skan (match_operator:SI 9 "logical_binary_operator" 2377132718Skan [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2378132718Skan (match_operand:SI 6 "const_int_operand" "")) 2379132718Skan (match_operand:SI 7 "s_register_operand" "")])])) 2380132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 2381132718Skan "TARGET_ARM 2382132718Skan && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2383132718Skan && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2384132718Skan [(set (match_dup 8) 2385132718Skan (match_op_dup 1 2386132718Skan [(ashift:SI (match_dup 2) (match_dup 4)) 2387132718Skan (match_dup 5)])) 2388132718Skan (set (match_dup 0) 2389132718Skan (match_op_dup 1 2390132718Skan [(lshiftrt:SI (match_dup 8) (match_dup 6)) 2391132718Skan (match_dup 7)]))] 2392132718Skan " 2393132718Skan operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2394132718Skan") 2395132718Skan 2396132718Skan(define_split 2397132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2398132718Skan (match_operator:SI 1 "logical_binary_operator" 2399132718Skan [(match_operator:SI 9 "logical_binary_operator" 2400132718Skan [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2401132718Skan (match_operand:SI 6 "const_int_operand" "")) 2402132718Skan (match_operand:SI 7 "s_register_operand" "")]) 2403132718Skan (zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 2404132718Skan (match_operand:SI 3 "const_int_operand" "") 2405132718Skan (match_operand:SI 4 "const_int_operand" ""))])) 2406132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 2407132718Skan "TARGET_ARM 2408132718Skan && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2409132718Skan && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2410132718Skan [(set (match_dup 8) 2411132718Skan (match_op_dup 1 2412132718Skan [(ashift:SI (match_dup 2) (match_dup 4)) 2413132718Skan (match_dup 5)])) 2414132718Skan (set (match_dup 0) 2415132718Skan (match_op_dup 1 2416132718Skan [(lshiftrt:SI (match_dup 8) (match_dup 6)) 2417132718Skan (match_dup 7)]))] 2418132718Skan " 2419132718Skan operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2420132718Skan") 2421132718Skan 2422132718Skan(define_split 2423132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2424132718Skan (match_operator:SI 1 "logical_binary_operator" 2425132718Skan [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 2426132718Skan (match_operand:SI 3 "const_int_operand" "") 2427132718Skan (match_operand:SI 4 "const_int_operand" "")) 2428132718Skan (match_operator:SI 9 "logical_binary_operator" 2429132718Skan [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2430132718Skan (match_operand:SI 6 "const_int_operand" "")) 2431132718Skan (match_operand:SI 7 "s_register_operand" "")])])) 2432132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 2433132718Skan "TARGET_ARM 2434132718Skan && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2435132718Skan && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2436132718Skan [(set (match_dup 8) 2437132718Skan (match_op_dup 1 2438132718Skan [(ashift:SI (match_dup 2) (match_dup 4)) 2439132718Skan (match_dup 5)])) 2440132718Skan (set (match_dup 0) 2441132718Skan (match_op_dup 1 2442132718Skan [(ashiftrt:SI (match_dup 8) (match_dup 6)) 2443132718Skan (match_dup 7)]))] 2444132718Skan " 2445132718Skan operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2446132718Skan") 2447132718Skan 2448132718Skan(define_split 2449132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2450132718Skan (match_operator:SI 1 "logical_binary_operator" 2451132718Skan [(match_operator:SI 9 "logical_binary_operator" 2452132718Skan [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2453132718Skan (match_operand:SI 6 "const_int_operand" "")) 2454132718Skan (match_operand:SI 7 "s_register_operand" "")]) 2455132718Skan (sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 2456132718Skan (match_operand:SI 3 "const_int_operand" "") 2457132718Skan (match_operand:SI 4 "const_int_operand" ""))])) 2458132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 2459132718Skan "TARGET_ARM 2460132718Skan && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2461132718Skan && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2462132718Skan [(set (match_dup 8) 2463132718Skan (match_op_dup 1 2464132718Skan [(ashift:SI (match_dup 2) (match_dup 4)) 2465132718Skan (match_dup 5)])) 2466132718Skan (set (match_dup 0) 2467132718Skan (match_op_dup 1 2468132718Skan [(ashiftrt:SI (match_dup 8) (match_dup 6)) 2469132718Skan (match_dup 7)]))] 2470132718Skan " 2471132718Skan operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2472132718Skan") 247390075Sobrien 247490075Sobrien 247590075Sobrien;; Minimum and maximum insns 247690075Sobrien 2477169689Skan(define_expand "smaxsi3" 2478169689Skan [(parallel [ 2479169689Skan (set (match_operand:SI 0 "s_register_operand" "") 2480169689Skan (smax:SI (match_operand:SI 1 "s_register_operand" "") 2481169689Skan (match_operand:SI 2 "arm_rhs_operand" ""))) 2482169689Skan (clobber (reg:CC CC_REGNUM))])] 2483169689Skan "TARGET_ARM" 2484169689Skan " 2485169689Skan if (operands[2] == const0_rtx || operands[2] == constm1_rtx) 2486169689Skan { 2487169689Skan /* No need for a clobber of the condition code register here. */ 2488169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 2489169689Skan gen_rtx_SMAX (SImode, operands[1], 2490169689Skan operands[2]))); 2491169689Skan DONE; 2492169689Skan } 2493169689Skan") 2494169689Skan 2495169689Skan(define_insn "*smax_0" 2496169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 2497169689Skan (smax:SI (match_operand:SI 1 "s_register_operand" "r") 2498169689Skan (const_int 0)))] 2499169689Skan "TARGET_ARM" 2500169689Skan "bic%?\\t%0, %1, %1, asr #31" 2501169689Skan [(set_attr "predicable" "yes")] 2502169689Skan) 2503169689Skan 2504169689Skan(define_insn "*smax_m1" 2505169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 2506169689Skan (smax:SI (match_operand:SI 1 "s_register_operand" "r") 2507169689Skan (const_int -1)))] 2508169689Skan "TARGET_ARM" 2509169689Skan "orr%?\\t%0, %1, %1, asr #31" 2510169689Skan [(set_attr "predicable" "yes")] 2511169689Skan) 2512169689Skan 2513169689Skan(define_insn "*smax_insn" 2514169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r,r") 2515169689Skan (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r") 2516169689Skan (match_operand:SI 2 "arm_rhs_operand" "rI,rI"))) 251790075Sobrien (clobber (reg:CC CC_REGNUM))] 251890075Sobrien "TARGET_ARM" 251990075Sobrien "@ 252090075Sobrien cmp\\t%1, %2\;movlt\\t%0, %2 252190075Sobrien cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2" 252290075Sobrien [(set_attr "conds" "clob") 2523169689Skan (set_attr "length" "8,12")] 252490075Sobrien) 252590075Sobrien 2526169689Skan(define_expand "sminsi3" 2527169689Skan [(parallel [ 2528169689Skan (set (match_operand:SI 0 "s_register_operand" "") 2529169689Skan (smin:SI (match_operand:SI 1 "s_register_operand" "") 2530169689Skan (match_operand:SI 2 "arm_rhs_operand" ""))) 2531169689Skan (clobber (reg:CC CC_REGNUM))])] 2532169689Skan "TARGET_ARM" 2533169689Skan " 2534169689Skan if (operands[2] == const0_rtx) 2535169689Skan { 2536169689Skan /* No need for a clobber of the condition code register here. */ 2537169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 2538169689Skan gen_rtx_SMIN (SImode, operands[1], 2539169689Skan operands[2]))); 2540169689Skan DONE; 2541169689Skan } 2542169689Skan") 2543169689Skan 2544169689Skan(define_insn "*smin_0" 2545169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 2546169689Skan (smin:SI (match_operand:SI 1 "s_register_operand" "r") 2547169689Skan (const_int 0)))] 2548169689Skan "TARGET_ARM" 2549169689Skan "and%?\\t%0, %1, %1, asr #31" 2550169689Skan [(set_attr "predicable" "yes")] 2551169689Skan) 2552169689Skan 2553169689Skan(define_insn "*smin_insn" 2554169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r,r") 2555169689Skan (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r") 2556169689Skan (match_operand:SI 2 "arm_rhs_operand" "rI,rI"))) 255790075Sobrien (clobber (reg:CC CC_REGNUM))] 255890075Sobrien "TARGET_ARM" 255990075Sobrien "@ 256090075Sobrien cmp\\t%1, %2\;movge\\t%0, %2 256190075Sobrien cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2" 256290075Sobrien [(set_attr "conds" "clob") 2563169689Skan (set_attr "length" "8,12")] 256490075Sobrien) 256590075Sobrien 256690075Sobrien(define_insn "umaxsi3" 256790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 256890075Sobrien (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 256990075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 257090075Sobrien (clobber (reg:CC CC_REGNUM))] 257190075Sobrien "TARGET_ARM" 257290075Sobrien "@ 257390075Sobrien cmp\\t%1, %2\;movcc\\t%0, %2 257490075Sobrien cmp\\t%1, %2\;movcs\\t%0, %1 257590075Sobrien cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2" 257690075Sobrien [(set_attr "conds" "clob") 257790075Sobrien (set_attr "length" "8,8,12")] 257890075Sobrien) 257990075Sobrien 258090075Sobrien(define_insn "uminsi3" 258190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 258290075Sobrien (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 258390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 258490075Sobrien (clobber (reg:CC CC_REGNUM))] 258590075Sobrien "TARGET_ARM" 258690075Sobrien "@ 258790075Sobrien cmp\\t%1, %2\;movcs\\t%0, %2 258890075Sobrien cmp\\t%1, %2\;movcc\\t%0, %1 258990075Sobrien cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2" 259090075Sobrien [(set_attr "conds" "clob") 259190075Sobrien (set_attr "length" "8,8,12")] 259290075Sobrien) 259390075Sobrien 259490075Sobrien(define_insn "*store_minmaxsi" 259590075Sobrien [(set (match_operand:SI 0 "memory_operand" "=m") 259690075Sobrien (match_operator:SI 3 "minmax_operator" 259790075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 259890075Sobrien (match_operand:SI 2 "s_register_operand" "r")])) 259990075Sobrien (clobber (reg:CC CC_REGNUM))] 260090075Sobrien "TARGET_ARM" 260190075Sobrien "* 2602169689Skan operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode, 2603169689Skan operands[1], operands[2]); 260490075Sobrien output_asm_insn (\"cmp\\t%1, %2\", operands); 260590075Sobrien output_asm_insn (\"str%d3\\t%1, %0\", operands); 260690075Sobrien output_asm_insn (\"str%D3\\t%2, %0\", operands); 260790075Sobrien return \"\"; 260890075Sobrien " 260990075Sobrien [(set_attr "conds" "clob") 261090075Sobrien (set_attr "length" "12") 261190075Sobrien (set_attr "type" "store1")] 261290075Sobrien) 261390075Sobrien 261490075Sobrien; Reject the frame pointer in operand[1], since reloading this after 261590075Sobrien; it has been eliminated can cause carnage. 261690075Sobrien(define_insn "*minmax_arithsi" 261790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 261890075Sobrien (match_operator:SI 4 "shiftable_operator" 261990075Sobrien [(match_operator:SI 5 "minmax_operator" 262090075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 262190075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 262290075Sobrien (match_operand:SI 1 "s_register_operand" "0,?r")])) 262390075Sobrien (clobber (reg:CC CC_REGNUM))] 2624169689Skan "TARGET_ARM && !arm_eliminable_register (operands[1])" 262590075Sobrien "* 262690075Sobrien { 262790075Sobrien enum rtx_code code = GET_CODE (operands[4]); 262890075Sobrien 2629169689Skan operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode, 2630169689Skan operands[2], operands[3]); 263190075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 263290075Sobrien output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands); 263390075Sobrien if (which_alternative != 0 || operands[3] != const0_rtx 263490075Sobrien || (code != PLUS && code != MINUS && code != IOR && code != XOR)) 263590075Sobrien output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands); 263690075Sobrien return \"\"; 263790075Sobrien }" 263890075Sobrien [(set_attr "conds" "clob") 263990075Sobrien (set_attr "length" "12")] 264090075Sobrien) 264190075Sobrien 264290075Sobrien 264390075Sobrien;; Shift and rotation insns 264490075Sobrien 2645169689Skan(define_expand "ashldi3" 2646169689Skan [(set (match_operand:DI 0 "s_register_operand" "") 2647169689Skan (ashift:DI (match_operand:DI 1 "s_register_operand" "") 2648169689Skan (match_operand:SI 2 "reg_or_int_operand" "")))] 2649169689Skan "TARGET_ARM" 2650169689Skan " 2651169689Skan if (GET_CODE (operands[2]) == CONST_INT) 2652169689Skan { 2653169689Skan if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1) 2654169689Skan { 2655169689Skan emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1])); 2656169689Skan DONE; 2657169689Skan } 2658169689Skan /* Ideally we shouldn't fail here if we could know that operands[1] 2659169689Skan ends up already living in an iwmmxt register. Otherwise it's 2660169689Skan cheaper to have the alternate code being generated than moving 2661169689Skan values to iwmmxt regs and back. */ 2662169689Skan FAIL; 2663169689Skan } 2664169689Skan else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)) 2665169689Skan FAIL; 2666169689Skan " 2667169689Skan) 2668169689Skan 2669169689Skan(define_insn "arm_ashldi3_1bit" 2670169689Skan [(set (match_operand:DI 0 "s_register_operand" "=&r,r") 2671169689Skan (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0") 2672169689Skan (const_int 1))) 2673169689Skan (clobber (reg:CC CC_REGNUM))] 2674169689Skan "TARGET_ARM" 2675169689Skan "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1" 2676169689Skan [(set_attr "conds" "clob") 2677169689Skan (set_attr "length" "8")] 2678169689Skan) 2679169689Skan 268090075Sobrien(define_expand "ashlsi3" 268190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 268290075Sobrien (ashift:SI (match_operand:SI 1 "s_register_operand" "") 268390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 268490075Sobrien "TARGET_EITHER" 268590075Sobrien " 268690075Sobrien if (GET_CODE (operands[2]) == CONST_INT 268790075Sobrien && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 268890075Sobrien { 268990075Sobrien emit_insn (gen_movsi (operands[0], const0_rtx)); 269090075Sobrien DONE; 269190075Sobrien } 269290075Sobrien " 269390075Sobrien) 269490075Sobrien 269590075Sobrien(define_insn "*thumb_ashlsi3" 269690075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l") 269790075Sobrien (ashift:SI (match_operand:SI 1 "register_operand" "l,0") 269890075Sobrien (match_operand:SI 2 "nonmemory_operand" "N,l")))] 269990075Sobrien "TARGET_THUMB" 270090075Sobrien "lsl\\t%0, %1, %2" 270190075Sobrien [(set_attr "length" "2")] 270290075Sobrien) 270390075Sobrien 2704169689Skan(define_expand "ashrdi3" 2705169689Skan [(set (match_operand:DI 0 "s_register_operand" "") 2706169689Skan (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "") 2707169689Skan (match_operand:SI 2 "reg_or_int_operand" "")))] 2708169689Skan "TARGET_ARM" 2709169689Skan " 2710169689Skan if (GET_CODE (operands[2]) == CONST_INT) 2711169689Skan { 2712169689Skan if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1) 2713169689Skan { 2714169689Skan emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1])); 2715169689Skan DONE; 2716169689Skan } 2717169689Skan /* Ideally we shouldn't fail here if we could know that operands[1] 2718169689Skan ends up already living in an iwmmxt register. Otherwise it's 2719169689Skan cheaper to have the alternate code being generated than moving 2720169689Skan values to iwmmxt regs and back. */ 2721169689Skan FAIL; 2722169689Skan } 2723169689Skan else if (!TARGET_REALLY_IWMMXT) 2724169689Skan FAIL; 2725169689Skan " 2726169689Skan) 2727169689Skan 2728169689Skan(define_insn "arm_ashrdi3_1bit" 2729169689Skan [(set (match_operand:DI 0 "s_register_operand" "=&r,r") 2730169689Skan (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0") 2731169689Skan (const_int 1))) 2732169689Skan (clobber (reg:CC CC_REGNUM))] 2733169689Skan "TARGET_ARM" 2734169689Skan "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx" 2735169689Skan [(set_attr "conds" "clob") 2736169689Skan (set_attr "length" "8")] 2737169689Skan) 2738169689Skan 273990075Sobrien(define_expand "ashrsi3" 274090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 274190075Sobrien (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "") 274290075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 274390075Sobrien "TARGET_EITHER" 274490075Sobrien " 274590075Sobrien if (GET_CODE (operands[2]) == CONST_INT 274690075Sobrien && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 274790075Sobrien operands[2] = GEN_INT (31); 274890075Sobrien " 274990075Sobrien) 275090075Sobrien 275190075Sobrien(define_insn "*thumb_ashrsi3" 275290075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l") 275390075Sobrien (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 275490075Sobrien (match_operand:SI 2 "nonmemory_operand" "N,l")))] 275590075Sobrien "TARGET_THUMB" 275690075Sobrien "asr\\t%0, %1, %2" 275790075Sobrien [(set_attr "length" "2")] 275890075Sobrien) 275990075Sobrien 2760169689Skan(define_expand "lshrdi3" 2761169689Skan [(set (match_operand:DI 0 "s_register_operand" "") 2762169689Skan (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "") 2763169689Skan (match_operand:SI 2 "reg_or_int_operand" "")))] 2764169689Skan "TARGET_ARM" 2765169689Skan " 2766169689Skan if (GET_CODE (operands[2]) == CONST_INT) 2767169689Skan { 2768169689Skan if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1) 2769169689Skan { 2770169689Skan emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1])); 2771169689Skan DONE; 2772169689Skan } 2773169689Skan /* Ideally we shouldn't fail here if we could know that operands[1] 2774169689Skan ends up already living in an iwmmxt register. Otherwise it's 2775169689Skan cheaper to have the alternate code being generated than moving 2776169689Skan values to iwmmxt regs and back. */ 2777169689Skan FAIL; 2778169689Skan } 2779169689Skan else if (!TARGET_REALLY_IWMMXT) 2780169689Skan FAIL; 2781169689Skan " 2782169689Skan) 2783169689Skan 2784169689Skan(define_insn "arm_lshrdi3_1bit" 2785169689Skan [(set (match_operand:DI 0 "s_register_operand" "=&r,r") 2786169689Skan (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0") 2787169689Skan (const_int 1))) 2788169689Skan (clobber (reg:CC CC_REGNUM))] 2789169689Skan "TARGET_ARM" 2790169689Skan "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx" 2791169689Skan [(set_attr "conds" "clob") 2792169689Skan (set_attr "length" "8")] 2793169689Skan) 2794169689Skan 279590075Sobrien(define_expand "lshrsi3" 279690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 279790075Sobrien (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "") 279890075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 279990075Sobrien "TARGET_EITHER" 280090075Sobrien " 280190075Sobrien if (GET_CODE (operands[2]) == CONST_INT 280290075Sobrien && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 280390075Sobrien { 280490075Sobrien emit_insn (gen_movsi (operands[0], const0_rtx)); 280590075Sobrien DONE; 280690075Sobrien } 280790075Sobrien " 280890075Sobrien) 280990075Sobrien 281090075Sobrien(define_insn "*thumb_lshrsi3" 281190075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l") 281290075Sobrien (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 281390075Sobrien (match_operand:SI 2 "nonmemory_operand" "N,l")))] 281490075Sobrien "TARGET_THUMB" 281590075Sobrien "lsr\\t%0, %1, %2" 281690075Sobrien [(set_attr "length" "2")] 281790075Sobrien) 281890075Sobrien 281990075Sobrien(define_expand "rotlsi3" 282090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 282190075Sobrien (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 282290075Sobrien (match_operand:SI 2 "reg_or_int_operand" "")))] 282390075Sobrien "TARGET_ARM" 282490075Sobrien " 282590075Sobrien if (GET_CODE (operands[2]) == CONST_INT) 282690075Sobrien operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32); 282790075Sobrien else 282890075Sobrien { 282990075Sobrien rtx reg = gen_reg_rtx (SImode); 283090075Sobrien emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2])); 283190075Sobrien operands[2] = reg; 283290075Sobrien } 283390075Sobrien " 283490075Sobrien) 283590075Sobrien 283690075Sobrien(define_expand "rotrsi3" 283790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 283890075Sobrien (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 283990075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 284090075Sobrien "TARGET_EITHER" 284190075Sobrien " 284290075Sobrien if (TARGET_ARM) 284390075Sobrien { 284490075Sobrien if (GET_CODE (operands[2]) == CONST_INT 284590075Sobrien && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 284690075Sobrien operands[2] = GEN_INT (INTVAL (operands[2]) % 32); 284790075Sobrien } 284890075Sobrien else /* TARGET_THUMB */ 284990075Sobrien { 285090075Sobrien if (GET_CODE (operands [2]) == CONST_INT) 285190075Sobrien operands [2] = force_reg (SImode, operands[2]); 285290075Sobrien } 285390075Sobrien " 285490075Sobrien) 285590075Sobrien 285690075Sobrien(define_insn "*thumb_rotrsi3" 285790075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 285890075Sobrien (rotatert:SI (match_operand:SI 1 "register_operand" "0") 285990075Sobrien (match_operand:SI 2 "register_operand" "l")))] 286090075Sobrien "TARGET_THUMB" 286190075Sobrien "ror\\t%0, %0, %2" 286290075Sobrien [(set_attr "length" "2")] 286390075Sobrien) 286490075Sobrien 286590075Sobrien(define_insn "*arm_shiftsi3" 286690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 286790075Sobrien (match_operator:SI 3 "shift_operator" 286890075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 286990075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rM")]))] 287090075Sobrien "TARGET_ARM" 287190075Sobrien "mov%?\\t%0, %1%S3" 287290075Sobrien [(set_attr "predicable" "yes") 287390075Sobrien (set_attr "shift" "1") 2874169689Skan (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 2875169689Skan (const_string "alu_shift") 2876169689Skan (const_string "alu_shift_reg")))] 287790075Sobrien) 287890075Sobrien 287990075Sobrien(define_insn "*shiftsi3_compare0" 288090075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 288190075Sobrien (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 288290075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 288390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]) 288490075Sobrien (const_int 0))) 288590075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 288690075Sobrien (match_op_dup 3 [(match_dup 1) (match_dup 2)]))] 288790075Sobrien "TARGET_ARM" 288890075Sobrien "mov%?s\\t%0, %1%S3" 288990075Sobrien [(set_attr "conds" "set") 289090075Sobrien (set_attr "shift" "1") 2891169689Skan (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 2892169689Skan (const_string "alu_shift") 2893169689Skan (const_string "alu_shift_reg")))] 289490075Sobrien) 289590075Sobrien 289690075Sobrien(define_insn "*shiftsi3_compare0_scratch" 289790075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 289890075Sobrien (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 289990075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 290090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]) 290190075Sobrien (const_int 0))) 290290075Sobrien (clobber (match_scratch:SI 0 "=r"))] 290390075Sobrien "TARGET_ARM" 290490075Sobrien "mov%?s\\t%0, %1%S3" 290590075Sobrien [(set_attr "conds" "set") 2906169689Skan (set_attr "shift" "1")] 290790075Sobrien) 290890075Sobrien 290990075Sobrien(define_insn "*notsi_shiftsi" 291090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 291190075Sobrien (not:SI (match_operator:SI 3 "shift_operator" 291290075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 291390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 291490075Sobrien "TARGET_ARM" 291590075Sobrien "mvn%?\\t%0, %1%S3" 291690075Sobrien [(set_attr "predicable" "yes") 291790075Sobrien (set_attr "shift" "1") 2918169689Skan (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 2919169689Skan (const_string "alu_shift") 2920169689Skan (const_string "alu_shift_reg")))] 292190075Sobrien) 292290075Sobrien 292390075Sobrien(define_insn "*notsi_shiftsi_compare0" 292490075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 292590075Sobrien (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 292690075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 292790075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")])) 292890075Sobrien (const_int 0))) 292990075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 293090075Sobrien (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] 293190075Sobrien "TARGET_ARM" 293290075Sobrien "mvn%?s\\t%0, %1%S3" 293390075Sobrien [(set_attr "conds" "set") 293490075Sobrien (set_attr "shift" "1") 2935169689Skan (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 2936169689Skan (const_string "alu_shift") 2937169689Skan (const_string "alu_shift_reg")))] 293890075Sobrien) 293990075Sobrien 294090075Sobrien(define_insn "*not_shiftsi_compare0_scratch" 294190075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 294290075Sobrien (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 294390075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 294490075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")])) 294590075Sobrien (const_int 0))) 294690075Sobrien (clobber (match_scratch:SI 0 "=r"))] 294790075Sobrien "TARGET_ARM" 294890075Sobrien "mvn%?s\\t%0, %1%S3" 294990075Sobrien [(set_attr "conds" "set") 295090075Sobrien (set_attr "shift" "1") 2951169689Skan (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 2952169689Skan (const_string "alu_shift") 2953169689Skan (const_string "alu_shift_reg")))] 295490075Sobrien) 295590075Sobrien 295690075Sobrien;; We don't really have extzv, but defining this using shifts helps 295790075Sobrien;; to reduce register pressure later on. 295890075Sobrien 295990075Sobrien(define_expand "extzv" 296090075Sobrien [(set (match_dup 4) 296190075Sobrien (ashift:SI (match_operand:SI 1 "register_operand" "") 296290075Sobrien (match_operand:SI 2 "const_int_operand" ""))) 296390075Sobrien (set (match_operand:SI 0 "register_operand" "") 296490075Sobrien (lshiftrt:SI (match_dup 4) 296590075Sobrien (match_operand:SI 3 "const_int_operand" "")))] 296690075Sobrien "TARGET_THUMB" 296790075Sobrien " 296890075Sobrien { 296990075Sobrien HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]); 297090075Sobrien HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]); 297190075Sobrien 297290075Sobrien operands[3] = GEN_INT (rshift); 297390075Sobrien 297490075Sobrien if (lshift == 0) 297590075Sobrien { 297690075Sobrien emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3])); 297790075Sobrien DONE; 297890075Sobrien } 297990075Sobrien 298090075Sobrien operands[2] = GEN_INT (lshift); 298190075Sobrien operands[4] = gen_reg_rtx (SImode); 298290075Sobrien }" 298390075Sobrien) 298490075Sobrien 298590075Sobrien 298690075Sobrien;; Unary arithmetic insns 298790075Sobrien 298890075Sobrien(define_expand "negdi2" 298990075Sobrien [(parallel 299090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 299190075Sobrien (neg:DI (match_operand:DI 1 "s_register_operand" ""))) 299290075Sobrien (clobber (reg:CC CC_REGNUM))])] 299390075Sobrien "TARGET_EITHER" 299490075Sobrien " 299590075Sobrien if (TARGET_THUMB) 299690075Sobrien { 299790075Sobrien if (GET_CODE (operands[1]) != REG) 299890075Sobrien operands[1] = force_reg (SImode, operands[1]); 299990075Sobrien } 300090075Sobrien " 300190075Sobrien) 300290075Sobrien 300390075Sobrien;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1). 300490075Sobrien;; The second alternative is to allow the common case of a *full* overlap. 300590075Sobrien(define_insn "*arm_negdi2" 300690075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,r") 300790075Sobrien (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0"))) 300890075Sobrien (clobber (reg:CC CC_REGNUM))] 300990075Sobrien "TARGET_ARM" 301090075Sobrien "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0" 301190075Sobrien [(set_attr "conds" "clob") 301290075Sobrien (set_attr "length" "8")] 301390075Sobrien) 301490075Sobrien 301590075Sobrien(define_insn "*thumb_negdi2" 301690075Sobrien [(set (match_operand:DI 0 "register_operand" "=&l") 301790075Sobrien (neg:DI (match_operand:DI 1 "register_operand" "l"))) 301890075Sobrien (clobber (reg:CC CC_REGNUM))] 301990075Sobrien "TARGET_THUMB" 302090075Sobrien "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1" 302190075Sobrien [(set_attr "length" "6")] 302290075Sobrien) 302390075Sobrien 302490075Sobrien(define_expand "negsi2" 302590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 302690075Sobrien (neg:SI (match_operand:SI 1 "s_register_operand" "")))] 302790075Sobrien "TARGET_EITHER" 302890075Sobrien "" 302990075Sobrien) 303090075Sobrien 303190075Sobrien(define_insn "*arm_negsi2" 303290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 303390075Sobrien (neg:SI (match_operand:SI 1 "s_register_operand" "r")))] 303490075Sobrien "TARGET_ARM" 303590075Sobrien "rsb%?\\t%0, %1, #0" 303690075Sobrien [(set_attr "predicable" "yes")] 303790075Sobrien) 303890075Sobrien 303990075Sobrien(define_insn "*thumb_negsi2" 304090075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 304190075Sobrien (neg:SI (match_operand:SI 1 "register_operand" "l")))] 304290075Sobrien "TARGET_THUMB" 304390075Sobrien "neg\\t%0, %1" 304490075Sobrien [(set_attr "length" "2")] 304590075Sobrien) 304690075Sobrien 3047132718Skan(define_expand "negsf2" 3048132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 3049132718Skan (neg:SF (match_operand:SF 1 "s_register_operand" "")))] 3050169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 3051132718Skan "" 305290075Sobrien) 305390075Sobrien 3054132718Skan(define_expand "negdf2" 3055132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 3056132718Skan (neg:DF (match_operand:DF 1 "s_register_operand" "")))] 3057169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 3058132718Skan "") 305990075Sobrien 306090075Sobrien;; abssi2 doesn't really clobber the condition codes if a different register 306190075Sobrien;; is being set. To keep things simple, assume during rtl manipulations that 306290075Sobrien;; it does, but tell the final scan operator the truth. Similarly for 306390075Sobrien;; (neg (abs...)) 306490075Sobrien 3065132718Skan(define_expand "abssi2" 3066132718Skan [(parallel 3067132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 3068132718Skan (abs:SI (match_operand:SI 1 "s_register_operand" ""))) 3069132718Skan (clobber (reg:CC CC_REGNUM))])] 3070132718Skan "TARGET_ARM" 3071132718Skan "") 3072132718Skan 3073132718Skan(define_insn "*arm_abssi2" 307490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 307590075Sobrien (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) 307690075Sobrien (clobber (reg:CC CC_REGNUM))] 307790075Sobrien "TARGET_ARM" 307890075Sobrien "@ 307990075Sobrien cmp\\t%0, #0\;rsblt\\t%0, %0, #0 308090075Sobrien eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" 308190075Sobrien [(set_attr "conds" "clob,*") 308290075Sobrien (set_attr "shift" "1") 308390075Sobrien ;; predicable can't be set based on the variant, so left as no 308490075Sobrien (set_attr "length" "8")] 308590075Sobrien) 308690075Sobrien 308790075Sobrien(define_insn "*neg_abssi2" 308890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 308990075Sobrien (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) 309090075Sobrien (clobber (reg:CC CC_REGNUM))] 309190075Sobrien "TARGET_ARM" 309290075Sobrien "@ 309390075Sobrien cmp\\t%0, #0\;rsbgt\\t%0, %0, #0 309490075Sobrien eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" 309590075Sobrien [(set_attr "conds" "clob,*") 309690075Sobrien (set_attr "shift" "1") 309790075Sobrien ;; predicable can't be set based on the variant, so left as no 309890075Sobrien (set_attr "length" "8")] 309990075Sobrien) 310090075Sobrien 3101132718Skan(define_expand "abssf2" 3102132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 3103132718Skan (abs:SF (match_operand:SF 1 "s_register_operand" "")))] 3104169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 3105132718Skan "") 310690075Sobrien 3107132718Skan(define_expand "absdf2" 3108132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 3109132718Skan (abs:DF (match_operand:DF 1 "s_register_operand" "")))] 3110169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 3111132718Skan "") 311290075Sobrien 3113132718Skan(define_expand "sqrtsf2" 3114132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 3115132718Skan (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))] 3116169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 3117132718Skan "") 311890075Sobrien 3119132718Skan(define_expand "sqrtdf2" 3120132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 3121132718Skan (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))] 3122169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 3123132718Skan "") 312490075Sobrien 312590075Sobrien(define_insn_and_split "one_cmpldi2" 312690075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 312790075Sobrien (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))] 312890075Sobrien "TARGET_ARM" 312990075Sobrien "#" 313090075Sobrien "TARGET_ARM && reload_completed" 313190075Sobrien [(set (match_dup 0) (not:SI (match_dup 1))) 313290075Sobrien (set (match_dup 2) (not:SI (match_dup 3)))] 313390075Sobrien " 313490075Sobrien { 313590075Sobrien operands[2] = gen_highpart (SImode, operands[0]); 313690075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 313790075Sobrien operands[3] = gen_highpart (SImode, operands[1]); 313890075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 313990075Sobrien }" 314090075Sobrien [(set_attr "length" "8") 314190075Sobrien (set_attr "predicable" "yes")] 314290075Sobrien) 314390075Sobrien 314490075Sobrien(define_expand "one_cmplsi2" 314590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 314690075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "")))] 314790075Sobrien "TARGET_EITHER" 314890075Sobrien "" 314990075Sobrien) 315090075Sobrien 315190075Sobrien(define_insn "*arm_one_cmplsi2" 315290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 315390075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r")))] 315490075Sobrien "TARGET_ARM" 315590075Sobrien "mvn%?\\t%0, %1" 315690075Sobrien [(set_attr "predicable" "yes")] 315790075Sobrien) 315890075Sobrien 315990075Sobrien(define_insn "*thumb_one_cmplsi2" 316090075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 316190075Sobrien (not:SI (match_operand:SI 1 "register_operand" "l")))] 316290075Sobrien "TARGET_THUMB" 316390075Sobrien "mvn\\t%0, %1" 316490075Sobrien [(set_attr "length" "2")] 316590075Sobrien) 316690075Sobrien 316790075Sobrien(define_insn "*notsi_compare0" 316890075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 316990075Sobrien (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 317090075Sobrien (const_int 0))) 317190075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 317290075Sobrien (not:SI (match_dup 1)))] 317390075Sobrien "TARGET_ARM" 317490075Sobrien "mvn%?s\\t%0, %1" 317590075Sobrien [(set_attr "conds" "set")] 317690075Sobrien) 317790075Sobrien 317890075Sobrien(define_insn "*notsi_compare0_scratch" 317990075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 318090075Sobrien (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 318190075Sobrien (const_int 0))) 318290075Sobrien (clobber (match_scratch:SI 0 "=r"))] 318390075Sobrien "TARGET_ARM" 318490075Sobrien "mvn%?s\\t%0, %1" 318590075Sobrien [(set_attr "conds" "set")] 318690075Sobrien) 318790075Sobrien 318890075Sobrien;; Fixed <--> Floating conversion insns 318990075Sobrien 3190132718Skan(define_expand "floatsisf2" 3191132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 3192132718Skan (float:SF (match_operand:SI 1 "s_register_operand" "")))] 3193169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 3194132718Skan " 3195169689Skan if (TARGET_MAVERICK) 3196132718Skan { 3197132718Skan emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1])); 3198132718Skan DONE; 3199132718Skan } 3200132718Skan") 320190075Sobrien 3202132718Skan(define_expand "floatsidf2" 3203132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 3204132718Skan (float:DF (match_operand:SI 1 "s_register_operand" "")))] 3205169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 3206132718Skan " 3207169689Skan if (TARGET_MAVERICK) 3208132718Skan { 3209132718Skan emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1])); 3210132718Skan DONE; 3211132718Skan } 3212132718Skan") 321390075Sobrien 3214132718Skan(define_expand "fix_truncsfsi2" 3215132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 3216132718Skan (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))] 3217169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 3218132718Skan " 3219169689Skan if (TARGET_MAVERICK) 3220132718Skan { 3221132718Skan if (!cirrus_fp_register (operands[0], SImode)) 3222132718Skan operands[0] = force_reg (SImode, operands[0]); 3223132718Skan if (!cirrus_fp_register (operands[1], SFmode)) 3224132718Skan operands[1] = force_reg (SFmode, operands[0]); 3225132718Skan emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1])); 3226132718Skan DONE; 3227132718Skan } 3228132718Skan") 322990075Sobrien 3230132718Skan(define_expand "fix_truncdfsi2" 3231132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 3232132718Skan (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))] 3233169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 3234132718Skan " 3235169689Skan if (TARGET_MAVERICK) 3236132718Skan { 3237132718Skan if (!cirrus_fp_register (operands[1], DFmode)) 3238132718Skan operands[1] = force_reg (DFmode, operands[0]); 3239132718Skan emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1])); 3240132718Skan DONE; 3241132718Skan } 3242132718Skan") 324390075Sobrien 324490075Sobrien;; Truncation insns 324590075Sobrien 3246132718Skan(define_expand "truncdfsf2" 3247132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 324890075Sobrien (float_truncate:SF 3249132718Skan (match_operand:DF 1 "s_register_operand" "")))] 3250169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 3251132718Skan "" 325290075Sobrien) 325390075Sobrien 325490075Sobrien;; Zero and sign extension instructions. 325590075Sobrien 325690075Sobrien(define_insn "zero_extendsidi2" 325790075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r") 325890075Sobrien (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 325990075Sobrien "TARGET_ARM" 326090075Sobrien "* 326190075Sobrien if (REGNO (operands[1]) 326290075Sobrien != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 326390075Sobrien output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 326490075Sobrien return \"mov%?\\t%R0, #0\"; 326590075Sobrien " 326690075Sobrien [(set_attr "length" "8") 326790075Sobrien (set_attr "predicable" "yes")] 326890075Sobrien) 326990075Sobrien 327090075Sobrien(define_insn "zero_extendqidi2" 327190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r,r") 327290075Sobrien (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 327390075Sobrien "TARGET_ARM" 327490075Sobrien "@ 327590075Sobrien and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0 327690075Sobrien ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0" 327790075Sobrien [(set_attr "length" "8") 327890075Sobrien (set_attr "predicable" "yes") 3279169689Skan (set_attr "type" "*,load_byte") 328090075Sobrien (set_attr "pool_range" "*,4092") 328190075Sobrien (set_attr "neg_pool_range" "*,4084")] 328290075Sobrien) 328390075Sobrien 328490075Sobrien(define_insn "extendsidi2" 328590075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r") 328690075Sobrien (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 328790075Sobrien "TARGET_ARM" 328890075Sobrien "* 328990075Sobrien if (REGNO (operands[1]) 329090075Sobrien != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 329190075Sobrien output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 329290075Sobrien return \"mov%?\\t%R0, %Q0, asr #31\"; 329390075Sobrien " 329490075Sobrien [(set_attr "length" "8") 329590075Sobrien (set_attr "shift" "1") 329690075Sobrien (set_attr "predicable" "yes")] 329790075Sobrien) 329890075Sobrien 329990075Sobrien(define_expand "zero_extendhisi2" 330090075Sobrien [(set (match_dup 2) 330190075Sobrien (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 330290075Sobrien (const_int 16))) 330390075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 330490075Sobrien (lshiftrt:SI (match_dup 2) (const_int 16)))] 330590075Sobrien "TARGET_EITHER" 330690075Sobrien " 330790075Sobrien { 3308169689Skan if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM) 330990075Sobrien { 3310169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3311169689Skan gen_rtx_ZERO_EXTEND (SImode, operands[1]))); 3312169689Skan DONE; 331390075Sobrien } 3314169689Skan 3315169689Skan if (TARGET_ARM && GET_CODE (operands[1]) == MEM) 331690075Sobrien { 3317169689Skan emit_insn (gen_movhi_bytes (operands[0], operands[1])); 3318169689Skan DONE; 3319169689Skan } 332090075Sobrien 3321169689Skan if (!s_register_operand (operands[1], HImode)) 3322169689Skan operands[1] = copy_to_mode_reg (HImode, operands[1]); 332390075Sobrien 3324169689Skan if (arm_arch6) 3325169689Skan { 3326169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3327169689Skan gen_rtx_ZERO_EXTEND (SImode, operands[1]))); 3328169689Skan DONE; 3329169689Skan } 333090075Sobrien 3331169689Skan operands[1] = gen_lowpart (SImode, operands[1]); 3332169689Skan operands[2] = gen_reg_rtx (SImode); 333390075Sobrien }" 333490075Sobrien) 333590075Sobrien 333690075Sobrien(define_insn "*thumb_zero_extendhisi2" 3337169689Skan [(set (match_operand:SI 0 "register_operand" "=l") 3338169689Skan (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3339169689Skan "TARGET_THUMB && !arm_arch6" 334090075Sobrien "* 334190075Sobrien rtx mem = XEXP (operands[1], 0); 334290075Sobrien 334390075Sobrien if (GET_CODE (mem) == CONST) 334490075Sobrien mem = XEXP (mem, 0); 334590075Sobrien 334690075Sobrien if (GET_CODE (mem) == LABEL_REF) 334790075Sobrien return \"ldr\\t%0, %1\"; 334890075Sobrien 334990075Sobrien if (GET_CODE (mem) == PLUS) 335090075Sobrien { 335190075Sobrien rtx a = XEXP (mem, 0); 335290075Sobrien rtx b = XEXP (mem, 1); 335390075Sobrien 335490075Sobrien /* This can happen due to bugs in reload. */ 335590075Sobrien if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM) 335690075Sobrien { 335790075Sobrien rtx ops[2]; 335890075Sobrien ops[0] = operands[0]; 335990075Sobrien ops[1] = a; 336090075Sobrien 336190075Sobrien output_asm_insn (\"mov %0, %1\", ops); 336290075Sobrien 336390075Sobrien XEXP (mem, 0) = operands[0]; 336490075Sobrien } 336590075Sobrien 336690075Sobrien else if ( GET_CODE (a) == LABEL_REF 336790075Sobrien && GET_CODE (b) == CONST_INT) 336890075Sobrien return \"ldr\\t%0, %1\"; 336990075Sobrien } 337090075Sobrien 337190075Sobrien return \"ldrh\\t%0, %1\"; 337290075Sobrien " 337390075Sobrien [(set_attr "length" "4") 3374169689Skan (set_attr "type" "load_byte") 337590075Sobrien (set_attr "pool_range" "60")] 337690075Sobrien) 337790075Sobrien 3378169689Skan(define_insn "*thumb_zero_extendhisi2_v6" 3379169689Skan [(set (match_operand:SI 0 "register_operand" "=l,l") 3380169689Skan (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))] 3381169689Skan "TARGET_THUMB && arm_arch6" 3382169689Skan "* 3383169689Skan rtx mem; 3384169689Skan 3385169689Skan if (which_alternative == 0) 3386169689Skan return \"uxth\\t%0, %1\"; 3387169689Skan 3388169689Skan mem = XEXP (operands[1], 0); 3389169689Skan 3390169689Skan if (GET_CODE (mem) == CONST) 3391169689Skan mem = XEXP (mem, 0); 3392169689Skan 3393169689Skan if (GET_CODE (mem) == LABEL_REF) 3394169689Skan return \"ldr\\t%0, %1\"; 3395169689Skan 3396169689Skan if (GET_CODE (mem) == PLUS) 3397169689Skan { 3398169689Skan rtx a = XEXP (mem, 0); 3399169689Skan rtx b = XEXP (mem, 1); 3400169689Skan 3401169689Skan /* This can happen due to bugs in reload. */ 3402169689Skan if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM) 3403169689Skan { 3404169689Skan rtx ops[2]; 3405169689Skan ops[0] = operands[0]; 3406169689Skan ops[1] = a; 3407169689Skan 3408169689Skan output_asm_insn (\"mov %0, %1\", ops); 3409169689Skan 3410169689Skan XEXP (mem, 0) = operands[0]; 3411169689Skan } 3412169689Skan 3413169689Skan else if ( GET_CODE (a) == LABEL_REF 3414169689Skan && GET_CODE (b) == CONST_INT) 3415169689Skan return \"ldr\\t%0, %1\"; 3416169689Skan } 3417169689Skan 3418169689Skan return \"ldrh\\t%0, %1\"; 3419169689Skan " 3420169689Skan [(set_attr "length" "2,4") 3421169689Skan (set_attr "type" "alu_shift,load_byte") 3422169689Skan (set_attr "pool_range" "*,60")] 3423169689Skan) 3424169689Skan 342590075Sobrien(define_insn "*arm_zero_extendhisi2" 3426169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 3427169689Skan (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3428169689Skan "TARGET_ARM && arm_arch4 && !arm_arch6" 342990075Sobrien "ldr%?h\\t%0, %1" 3430169689Skan [(set_attr "type" "load_byte") 343190075Sobrien (set_attr "predicable" "yes") 343290075Sobrien (set_attr "pool_range" "256") 343390075Sobrien (set_attr "neg_pool_range" "244")] 343490075Sobrien) 343590075Sobrien 3436169689Skan(define_insn "*arm_zero_extendhisi2_v6" 3437169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r,r") 3438169689Skan (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] 3439169689Skan "TARGET_ARM && arm_arch6" 3440169689Skan "@ 3441169689Skan uxth%?\\t%0, %1 3442169689Skan ldr%?h\\t%0, %1" 3443169689Skan [(set_attr "type" "alu_shift,load_byte") 3444169689Skan (set_attr "predicable" "yes") 3445169689Skan (set_attr "pool_range" "*,256") 3446169689Skan (set_attr "neg_pool_range" "*,244")] 344790075Sobrien) 344890075Sobrien 3449169689Skan(define_insn "*arm_zero_extendhisi2addsi" 3450169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 3451169689Skan (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r")) 3452169689Skan (match_operand:SI 2 "s_register_operand" "r")))] 3453169689Skan "TARGET_ARM && arm_arch6" 3454169689Skan "uxtah%?\\t%0, %2, %1" 3455169689Skan [(set_attr "type" "alu_shift") 3456169689Skan (set_attr "predicable" "yes")] 345790075Sobrien) 345890075Sobrien 345990075Sobrien(define_expand "zero_extendqisi2" 346090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 346190075Sobrien (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] 346290075Sobrien "TARGET_EITHER" 346390075Sobrien " 3464169689Skan if (!arm_arch6 && GET_CODE (operands[1]) != MEM) 346590075Sobrien { 346690075Sobrien if (TARGET_ARM) 346790075Sobrien { 346890075Sobrien emit_insn (gen_andsi3 (operands[0], 346990075Sobrien gen_lowpart (SImode, operands[1]), 347090075Sobrien GEN_INT (255))); 347190075Sobrien } 347290075Sobrien else /* TARGET_THUMB */ 347390075Sobrien { 347490075Sobrien rtx temp = gen_reg_rtx (SImode); 347590075Sobrien rtx ops[3]; 347690075Sobrien 347790075Sobrien operands[1] = copy_to_mode_reg (QImode, operands[1]); 347890075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 347990075Sobrien 348090075Sobrien ops[0] = temp; 348190075Sobrien ops[1] = operands[1]; 348290075Sobrien ops[2] = GEN_INT (24); 348390075Sobrien 348490075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 348590075Sobrien gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 348690075Sobrien 348790075Sobrien ops[0] = operands[0]; 348890075Sobrien ops[1] = temp; 348990075Sobrien ops[2] = GEN_INT (24); 349090075Sobrien 349190075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 349290075Sobrien gen_rtx_LSHIFTRT (SImode, ops[1], ops[2]))); 349390075Sobrien } 349490075Sobrien DONE; 349590075Sobrien } 349690075Sobrien " 349790075Sobrien) 349890075Sobrien 349990075Sobrien(define_insn "*thumb_zero_extendqisi2" 3500169689Skan [(set (match_operand:SI 0 "register_operand" "=l") 3501169689Skan (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 3502169689Skan "TARGET_THUMB && !arm_arch6" 350390075Sobrien "ldrb\\t%0, %1" 350490075Sobrien [(set_attr "length" "2") 3505169689Skan (set_attr "type" "load_byte") 350690075Sobrien (set_attr "pool_range" "32")] 350790075Sobrien) 350890075Sobrien 3509169689Skan(define_insn "*thumb_zero_extendqisi2_v6" 3510169689Skan [(set (match_operand:SI 0 "register_operand" "=l,l") 3511169689Skan (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))] 3512169689Skan "TARGET_THUMB && arm_arch6" 3513169689Skan "@ 3514169689Skan uxtb\\t%0, %1 3515169689Skan ldrb\\t%0, %1" 3516169689Skan [(set_attr "length" "2,2") 3517169689Skan (set_attr "type" "alu_shift,load_byte") 3518169689Skan (set_attr "pool_range" "*,32")] 3519169689Skan) 3520169689Skan 352190075Sobrien(define_insn "*arm_zero_extendqisi2" 3522169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 3523169689Skan (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 3524169689Skan "TARGET_ARM && !arm_arch6" 352590075Sobrien "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2" 3526169689Skan [(set_attr "type" "load_byte") 352790075Sobrien (set_attr "predicable" "yes") 352890075Sobrien (set_attr "pool_range" "4096") 352990075Sobrien (set_attr "neg_pool_range" "4084")] 353090075Sobrien) 353190075Sobrien 3532169689Skan(define_insn "*arm_zero_extendqisi2_v6" 3533169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r,r") 3534169689Skan (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 3535169689Skan "TARGET_ARM && arm_arch6" 3536169689Skan "@ 3537169689Skan uxtb%?\\t%0, %1 3538169689Skan ldr%?b\\t%0, %1\\t%@ zero_extendqisi2" 3539169689Skan [(set_attr "type" "alu_shift,load_byte") 3540169689Skan (set_attr "predicable" "yes") 3541169689Skan (set_attr "pool_range" "*,4096") 3542169689Skan (set_attr "neg_pool_range" "*,4084")] 3543169689Skan) 3544169689Skan 3545169689Skan(define_insn "*arm_zero_extendqisi2addsi" 3546169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 3547169689Skan (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r")) 3548169689Skan (match_operand:SI 2 "s_register_operand" "r")))] 3549169689Skan "TARGET_ARM && arm_arch6" 3550169689Skan "uxtab%?\\t%0, %2, %1" 3551169689Skan [(set_attr "predicable" "yes") 3552169689Skan (set_attr "type" "alu_shift")] 3553169689Skan) 3554169689Skan 355590075Sobrien(define_split 355690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 355790075Sobrien (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0))) 355890075Sobrien (clobber (match_operand:SI 2 "s_register_operand" ""))] 3559102780Skan "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN" 356090075Sobrien [(set (match_dup 2) (match_dup 1)) 356190075Sobrien (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))] 356290075Sobrien "" 356390075Sobrien) 356490075Sobrien 3565169689Skan(define_split 3566169689Skan [(set (match_operand:SI 0 "s_register_operand" "") 3567169689Skan (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3))) 3568169689Skan (clobber (match_operand:SI 2 "s_register_operand" ""))] 3569169689Skan "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN" 3570169689Skan [(set (match_dup 2) (match_dup 1)) 3571169689Skan (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))] 3572169689Skan "" 3573169689Skan) 3574169689Skan 357590075Sobrien(define_insn "*compareqi_eq0" 357690075Sobrien [(set (reg:CC_Z CC_REGNUM) 357790075Sobrien (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r") 357890075Sobrien (const_int 0)))] 357990075Sobrien "TARGET_ARM" 358090075Sobrien "tst\\t%0, #255" 358190075Sobrien [(set_attr "conds" "set")] 358290075Sobrien) 358390075Sobrien 358490075Sobrien(define_expand "extendhisi2" 358590075Sobrien [(set (match_dup 2) 358690075Sobrien (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 358790075Sobrien (const_int 16))) 358890075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 358990075Sobrien (ashiftrt:SI (match_dup 2) 359090075Sobrien (const_int 16)))] 359190075Sobrien "TARGET_EITHER" 359290075Sobrien " 359390075Sobrien { 3594169689Skan if (GET_CODE (operands[1]) == MEM) 359590075Sobrien { 3596169689Skan if (TARGET_THUMB) 3597169689Skan { 3598169689Skan emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1])); 3599169689Skan DONE; 3600169689Skan } 3601169689Skan else if (arm_arch4) 3602169689Skan { 3603169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3604169689Skan gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 3605169689Skan DONE; 3606169689Skan } 360790075Sobrien } 360890075Sobrien 3609169689Skan if (TARGET_ARM && GET_CODE (operands[1]) == MEM) 361090075Sobrien { 361190075Sobrien emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); 361290075Sobrien DONE; 361390075Sobrien } 3614169689Skan 361590075Sobrien if (!s_register_operand (operands[1], HImode)) 361690075Sobrien operands[1] = copy_to_mode_reg (HImode, operands[1]); 361790075Sobrien 3618169689Skan if (arm_arch6) 361990075Sobrien { 3620169689Skan if (TARGET_THUMB) 3621169689Skan emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1])); 3622169689Skan else 3623169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3624169689Skan gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 3625169689Skan 362690075Sobrien DONE; 362790075Sobrien } 3628169689Skan 3629169689Skan operands[1] = gen_lowpart (SImode, operands[1]); 3630169689Skan operands[2] = gen_reg_rtx (SImode); 363190075Sobrien }" 363290075Sobrien) 363390075Sobrien 3634169689Skan(define_insn "thumb_extendhisi2" 3635169689Skan [(set (match_operand:SI 0 "register_operand" "=l") 3636169689Skan (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) 3637169689Skan (clobber (match_scratch:SI 2 "=&l"))] 3638169689Skan "TARGET_THUMB && !arm_arch6" 363990075Sobrien "* 364090075Sobrien { 364190075Sobrien rtx ops[4]; 364290075Sobrien rtx mem = XEXP (operands[1], 0); 364390075Sobrien 364490075Sobrien /* This code used to try to use 'V', and fix the address only if it was 364590075Sobrien offsettable, but this fails for e.g. REG+48 because 48 is outside the 364690075Sobrien range of QImode offsets, and offsettable_address_p does a QImode 364790075Sobrien address check. */ 364890075Sobrien 364990075Sobrien if (GET_CODE (mem) == CONST) 365090075Sobrien mem = XEXP (mem, 0); 365190075Sobrien 365290075Sobrien if (GET_CODE (mem) == LABEL_REF) 365390075Sobrien return \"ldr\\t%0, %1\"; 365490075Sobrien 365590075Sobrien if (GET_CODE (mem) == PLUS) 365690075Sobrien { 365790075Sobrien rtx a = XEXP (mem, 0); 365890075Sobrien rtx b = XEXP (mem, 1); 365990075Sobrien 366090075Sobrien if (GET_CODE (a) == LABEL_REF 366190075Sobrien && GET_CODE (b) == CONST_INT) 366290075Sobrien return \"ldr\\t%0, %1\"; 366390075Sobrien 366490075Sobrien if (GET_CODE (b) == REG) 366590075Sobrien return \"ldrsh\\t%0, %1\"; 366690075Sobrien 366790075Sobrien ops[1] = a; 366890075Sobrien ops[2] = b; 366990075Sobrien } 367090075Sobrien else 367190075Sobrien { 367290075Sobrien ops[1] = mem; 367390075Sobrien ops[2] = const0_rtx; 367490075Sobrien } 367590075Sobrien 3676169689Skan gcc_assert (GET_CODE (ops[1]) == REG); 3677169689Skan 367890075Sobrien ops[0] = operands[0]; 367990075Sobrien ops[3] = operands[2]; 368090075Sobrien output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); 368190075Sobrien return \"\"; 368290075Sobrien }" 368390075Sobrien [(set_attr "length" "4") 3684169689Skan (set_attr "type" "load_byte") 368590075Sobrien (set_attr "pool_range" "1020")] 368690075Sobrien) 368790075Sobrien 3688169689Skan;; We used to have an early-clobber on the scratch register here. 3689169689Skan;; However, there's a bug somewhere in reload which means that this 3690169689Skan;; can be partially ignored during spill allocation if the memory 3691169689Skan;; address also needs reloading; this causes us to die later on when 3692169689Skan;; we try to verify the operands. Fortunately, we don't really need 3693169689Skan;; the early-clobber: we can always use operand 0 if operand 2 3694169689Skan;; overlaps the address. 3695169689Skan(define_insn "*thumb_extendhisi2_insn_v6" 3696169689Skan [(set (match_operand:SI 0 "register_operand" "=l,l") 3697169689Skan (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m"))) 3698169689Skan (clobber (match_scratch:SI 2 "=X,l"))] 3699169689Skan "TARGET_THUMB && arm_arch6" 3700169689Skan "* 3701169689Skan { 3702169689Skan rtx ops[4]; 3703169689Skan rtx mem; 3704169689Skan 3705169689Skan if (which_alternative == 0) 3706169689Skan return \"sxth\\t%0, %1\"; 3707169689Skan 3708169689Skan mem = XEXP (operands[1], 0); 3709169689Skan 3710169689Skan /* This code used to try to use 'V', and fix the address only if it was 3711169689Skan offsettable, but this fails for e.g. REG+48 because 48 is outside the 3712169689Skan range of QImode offsets, and offsettable_address_p does a QImode 3713169689Skan address check. */ 3714169689Skan 3715169689Skan if (GET_CODE (mem) == CONST) 3716169689Skan mem = XEXP (mem, 0); 3717169689Skan 3718169689Skan if (GET_CODE (mem) == LABEL_REF) 3719169689Skan return \"ldr\\t%0, %1\"; 3720169689Skan 3721169689Skan if (GET_CODE (mem) == PLUS) 3722169689Skan { 3723169689Skan rtx a = XEXP (mem, 0); 3724169689Skan rtx b = XEXP (mem, 1); 3725169689Skan 3726169689Skan if (GET_CODE (a) == LABEL_REF 3727169689Skan && GET_CODE (b) == CONST_INT) 3728169689Skan return \"ldr\\t%0, %1\"; 3729169689Skan 3730169689Skan if (GET_CODE (b) == REG) 3731169689Skan return \"ldrsh\\t%0, %1\"; 3732169689Skan 3733169689Skan ops[1] = a; 3734169689Skan ops[2] = b; 3735169689Skan } 3736169689Skan else 3737169689Skan { 3738169689Skan ops[1] = mem; 3739169689Skan ops[2] = const0_rtx; 3740169689Skan } 3741169689Skan 3742169689Skan gcc_assert (GET_CODE (ops[1]) == REG); 3743169689Skan 3744169689Skan ops[0] = operands[0]; 3745169689Skan if (reg_mentioned_p (operands[2], ops[1])) 3746169689Skan ops[3] = ops[0]; 3747169689Skan else 3748169689Skan ops[3] = operands[2]; 3749169689Skan output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); 3750169689Skan return \"\"; 3751169689Skan }" 3752169689Skan [(set_attr "length" "2,4") 3753169689Skan (set_attr "type" "alu_shift,load_byte") 3754169689Skan (set_attr "pool_range" "*,1020")] 3755169689Skan) 3756169689Skan 375790075Sobrien(define_expand "extendhisi2_mem" 375890075Sobrien [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 375990075Sobrien (set (match_dup 3) 376090075Sobrien (zero_extend:SI (match_dup 7))) 376190075Sobrien (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24))) 376290075Sobrien (set (match_operand:SI 0 "" "") 376390075Sobrien (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))] 376490075Sobrien "TARGET_ARM" 376590075Sobrien " 376690075Sobrien { 376790075Sobrien rtx mem1, mem2; 376890075Sobrien rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 376990075Sobrien 3770169689Skan mem1 = change_address (operands[1], QImode, addr); 3771169689Skan mem2 = change_address (operands[1], QImode, plus_constant (addr, 1)); 377290075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 377390075Sobrien operands[1] = mem1; 377490075Sobrien operands[2] = gen_reg_rtx (SImode); 377590075Sobrien operands[3] = gen_reg_rtx (SImode); 377690075Sobrien operands[6] = gen_reg_rtx (SImode); 377790075Sobrien operands[7] = mem2; 377890075Sobrien 377990075Sobrien if (BYTES_BIG_ENDIAN) 378090075Sobrien { 378190075Sobrien operands[4] = operands[2]; 378290075Sobrien operands[5] = operands[3]; 378390075Sobrien } 378490075Sobrien else 378590075Sobrien { 378690075Sobrien operands[4] = operands[3]; 378790075Sobrien operands[5] = operands[2]; 378890075Sobrien } 378990075Sobrien }" 379090075Sobrien) 379190075Sobrien 3792169689Skan(define_insn "*arm_extendhisi2" 3793169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 3794169689Skan (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 3795169689Skan "TARGET_ARM && arm_arch4 && !arm_arch6" 379690075Sobrien "ldr%?sh\\t%0, %1" 3797169689Skan [(set_attr "type" "load_byte") 379890075Sobrien (set_attr "predicable" "yes") 379990075Sobrien (set_attr "pool_range" "256") 380090075Sobrien (set_attr "neg_pool_range" "244")] 380190075Sobrien) 380290075Sobrien 3803169689Skan(define_insn "*arm_extendhisi2_v6" 3804169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r,r") 3805169689Skan (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] 3806169689Skan "TARGET_ARM && arm_arch6" 3807169689Skan "@ 3808169689Skan sxth%?\\t%0, %1 3809169689Skan ldr%?sh\\t%0, %1" 3810169689Skan [(set_attr "type" "alu_shift,load_byte") 3811169689Skan (set_attr "predicable" "yes") 3812169689Skan (set_attr "pool_range" "*,256") 3813169689Skan (set_attr "neg_pool_range" "*,244")] 381490075Sobrien) 381590075Sobrien 3816169689Skan(define_insn "*arm_extendhisi2addsi" 3817169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 3818169689Skan (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r")) 3819169689Skan (match_operand:SI 2 "s_register_operand" "r")))] 3820169689Skan "TARGET_ARM && arm_arch6" 3821169689Skan "sxtah%?\\t%0, %2, %1" 382290075Sobrien) 382390075Sobrien 382490075Sobrien(define_expand "extendqihi2" 382590075Sobrien [(set (match_dup 2) 382690075Sobrien (ashift:SI (match_operand:QI 1 "general_operand" "") 382790075Sobrien (const_int 24))) 382890075Sobrien (set (match_operand:HI 0 "s_register_operand" "") 382990075Sobrien (ashiftrt:SI (match_dup 2) 383090075Sobrien (const_int 24)))] 383190075Sobrien "TARGET_ARM" 383290075Sobrien " 383390075Sobrien { 383490075Sobrien if (arm_arch4 && GET_CODE (operands[1]) == MEM) 383590075Sobrien { 383690075Sobrien emit_insn (gen_rtx_SET (VOIDmode, 383790075Sobrien operands[0], 383890075Sobrien gen_rtx_SIGN_EXTEND (HImode, operands[1]))); 383990075Sobrien DONE; 384090075Sobrien } 384190075Sobrien if (!s_register_operand (operands[1], QImode)) 384290075Sobrien operands[1] = copy_to_mode_reg (QImode, operands[1]); 384390075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 384490075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 384590075Sobrien operands[2] = gen_reg_rtx (SImode); 384690075Sobrien }" 384790075Sobrien) 384890075Sobrien 384990075Sobrien(define_insn "*extendqihi_insn" 3850169689Skan [(set (match_operand:HI 0 "s_register_operand" "=r") 3851169689Skan (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))] 385290075Sobrien "TARGET_ARM && arm_arch4" 3853169689Skan "ldr%?sb\\t%0, %1" 3854169689Skan [(set_attr "type" "load_byte") 385590075Sobrien (set_attr "predicable" "yes") 385690075Sobrien (set_attr "pool_range" "256") 385790075Sobrien (set_attr "neg_pool_range" "244")] 385890075Sobrien) 385990075Sobrien 386090075Sobrien(define_expand "extendqisi2" 386190075Sobrien [(set (match_dup 2) 386290075Sobrien (ashift:SI (match_operand:QI 1 "general_operand" "") 386390075Sobrien (const_int 24))) 386490075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 386590075Sobrien (ashiftrt:SI (match_dup 2) 386690075Sobrien (const_int 24)))] 386790075Sobrien "TARGET_EITHER" 386890075Sobrien " 386990075Sobrien { 3870169689Skan if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM) 387190075Sobrien { 3872169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 387390075Sobrien gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 387490075Sobrien DONE; 387590075Sobrien } 3876169689Skan 387790075Sobrien if (!s_register_operand (operands[1], QImode)) 387890075Sobrien operands[1] = copy_to_mode_reg (QImode, operands[1]); 3879169689Skan 3880169689Skan if (arm_arch6) 3881169689Skan { 3882169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3883169689Skan gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 3884169689Skan DONE; 3885169689Skan } 3886169689Skan 388790075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 388890075Sobrien operands[2] = gen_reg_rtx (SImode); 388990075Sobrien }" 389090075Sobrien) 389190075Sobrien 3892169689Skan(define_insn "*arm_extendqisi" 3893169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 3894169689Skan (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))] 3895169689Skan "TARGET_ARM && arm_arch4 && !arm_arch6" 3896169689Skan "ldr%?sb\\t%0, %1" 3897169689Skan [(set_attr "type" "load_byte") 389890075Sobrien (set_attr "predicable" "yes") 389990075Sobrien (set_attr "pool_range" "256") 390090075Sobrien (set_attr "neg_pool_range" "244")] 390190075Sobrien) 390290075Sobrien 3903169689Skan(define_insn "*arm_extendqisi_v6" 3904169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r,r") 3905169689Skan (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))] 3906169689Skan "TARGET_ARM && arm_arch6" 3907169689Skan "@ 3908169689Skan sxtb%?\\t%0, %1 3909169689Skan ldr%?sb\\t%0, %1" 3910169689Skan [(set_attr "type" "alu_shift,load_byte") 3911169689Skan (set_attr "predicable" "yes") 3912169689Skan (set_attr "pool_range" "*,256") 3913169689Skan (set_attr "neg_pool_range" "*,244")] 3914169689Skan) 391590075Sobrien 3916169689Skan(define_insn "*arm_extendqisi2addsi" 3917169689Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 3918169689Skan (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r")) 3919169689Skan (match_operand:SI 2 "s_register_operand" "r")))] 3920169689Skan "TARGET_ARM && arm_arch6" 3921169689Skan "sxtab%?\\t%0, %2, %1" 3922169689Skan [(set_attr "type" "alu_shift") 3923169689Skan (set_attr "predicable" "yes")] 392490075Sobrien) 392590075Sobrien 3926169689Skan(define_insn "*thumb_extendqisi2" 3927169689Skan [(set (match_operand:SI 0 "register_operand" "=l,l") 3928169689Skan (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] 3929169689Skan "TARGET_THUMB && !arm_arch6" 393090075Sobrien "* 393190075Sobrien { 393290075Sobrien rtx ops[3]; 393390075Sobrien rtx mem = XEXP (operands[1], 0); 393490075Sobrien 393590075Sobrien if (GET_CODE (mem) == CONST) 393690075Sobrien mem = XEXP (mem, 0); 393790075Sobrien 393890075Sobrien if (GET_CODE (mem) == LABEL_REF) 393990075Sobrien return \"ldr\\t%0, %1\"; 394090075Sobrien 394190075Sobrien if (GET_CODE (mem) == PLUS 394290075Sobrien && GET_CODE (XEXP (mem, 0)) == LABEL_REF) 394390075Sobrien return \"ldr\\t%0, %1\"; 394490075Sobrien 394590075Sobrien if (which_alternative == 0) 394690075Sobrien return \"ldrsb\\t%0, %1\"; 394790075Sobrien 394890075Sobrien ops[0] = operands[0]; 394990075Sobrien 395090075Sobrien if (GET_CODE (mem) == PLUS) 395190075Sobrien { 395290075Sobrien rtx a = XEXP (mem, 0); 395390075Sobrien rtx b = XEXP (mem, 1); 395490075Sobrien 395590075Sobrien ops[1] = a; 395690075Sobrien ops[2] = b; 395790075Sobrien 395890075Sobrien if (GET_CODE (a) == REG) 395990075Sobrien { 396090075Sobrien if (GET_CODE (b) == REG) 396190075Sobrien output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); 396290075Sobrien else if (REGNO (a) == REGNO (ops[0])) 396390075Sobrien { 396490075Sobrien output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); 396590075Sobrien output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 396690075Sobrien output_asm_insn (\"asr\\t%0, %0, #24\", ops); 396790075Sobrien } 396890075Sobrien else 396990075Sobrien output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 397090075Sobrien } 397190075Sobrien else 397290075Sobrien { 3973169689Skan gcc_assert (GET_CODE (b) == REG); 397490075Sobrien if (REGNO (b) == REGNO (ops[0])) 397590075Sobrien { 397690075Sobrien output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); 397790075Sobrien output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 397890075Sobrien output_asm_insn (\"asr\\t%0, %0, #24\", ops); 397990075Sobrien } 398090075Sobrien else 398190075Sobrien output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 398290075Sobrien } 398390075Sobrien } 398490075Sobrien else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) 398590075Sobrien { 398690075Sobrien output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); 398790075Sobrien output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 398890075Sobrien output_asm_insn (\"asr\\t%0, %0, #24\", ops); 398990075Sobrien } 399090075Sobrien else 399190075Sobrien { 399290075Sobrien ops[1] = mem; 399390075Sobrien ops[2] = const0_rtx; 399490075Sobrien 399590075Sobrien output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 399690075Sobrien } 399790075Sobrien return \"\"; 399890075Sobrien }" 399990075Sobrien [(set_attr "length" "2,6") 4000169689Skan (set_attr "type" "load_byte,load_byte") 400190075Sobrien (set_attr "pool_range" "32,32")] 400290075Sobrien) 400390075Sobrien 4004169689Skan(define_insn "*thumb_extendqisi2_v6" 4005169689Skan [(set (match_operand:SI 0 "register_operand" "=l,l,l") 4006169689Skan (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))] 4007169689Skan "TARGET_THUMB && arm_arch6" 4008169689Skan "* 4009169689Skan { 4010169689Skan rtx ops[3]; 4011169689Skan rtx mem; 4012169689Skan 4013169689Skan if (which_alternative == 0) 4014169689Skan return \"sxtb\\t%0, %1\"; 4015169689Skan 4016169689Skan mem = XEXP (operands[1], 0); 4017169689Skan 4018169689Skan if (GET_CODE (mem) == CONST) 4019169689Skan mem = XEXP (mem, 0); 4020169689Skan 4021169689Skan if (GET_CODE (mem) == LABEL_REF) 4022169689Skan return \"ldr\\t%0, %1\"; 4023169689Skan 4024169689Skan if (GET_CODE (mem) == PLUS 4025169689Skan && GET_CODE (XEXP (mem, 0)) == LABEL_REF) 4026169689Skan return \"ldr\\t%0, %1\"; 4027169689Skan 4028169689Skan if (which_alternative == 0) 4029169689Skan return \"ldrsb\\t%0, %1\"; 4030169689Skan 4031169689Skan ops[0] = operands[0]; 4032169689Skan 4033169689Skan if (GET_CODE (mem) == PLUS) 4034169689Skan { 4035169689Skan rtx a = XEXP (mem, 0); 4036169689Skan rtx b = XEXP (mem, 1); 4037169689Skan 4038169689Skan ops[1] = a; 4039169689Skan ops[2] = b; 4040169689Skan 4041169689Skan if (GET_CODE (a) == REG) 4042169689Skan { 4043169689Skan if (GET_CODE (b) == REG) 4044169689Skan output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); 4045169689Skan else if (REGNO (a) == REGNO (ops[0])) 4046169689Skan { 4047169689Skan output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); 4048169689Skan output_asm_insn (\"sxtb\\t%0, %0\", ops); 4049169689Skan } 4050169689Skan else 4051169689Skan output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 4052169689Skan } 4053169689Skan else 4054169689Skan { 4055169689Skan gcc_assert (GET_CODE (b) == REG); 4056169689Skan if (REGNO (b) == REGNO (ops[0])) 4057169689Skan { 4058169689Skan output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); 4059169689Skan output_asm_insn (\"sxtb\\t%0, %0\", ops); 4060169689Skan } 4061169689Skan else 4062169689Skan output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 4063169689Skan } 4064169689Skan } 4065169689Skan else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) 4066169689Skan { 4067169689Skan output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); 4068169689Skan output_asm_insn (\"sxtb\\t%0, %0\", ops); 4069169689Skan } 4070169689Skan else 4071169689Skan { 4072169689Skan ops[1] = mem; 4073169689Skan ops[2] = const0_rtx; 4074169689Skan 4075169689Skan output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 4076169689Skan } 4077169689Skan return \"\"; 4078169689Skan }" 4079169689Skan [(set_attr "length" "2,2,4") 4080169689Skan (set_attr "type" "alu_shift,load_byte,load_byte") 4081169689Skan (set_attr "pool_range" "*,32,32")] 4082169689Skan) 4083169689Skan 4084132718Skan(define_expand "extendsfdf2" 4085132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 4086132718Skan (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))] 4087169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 4088132718Skan "" 408990075Sobrien) 409090075Sobrien 409190075Sobrien;; Move insns (including loads and stores) 409290075Sobrien 409390075Sobrien;; XXX Just some ideas about movti. 409490075Sobrien;; I don't think these are a good idea on the arm, there just aren't enough 409590075Sobrien;; registers 409690075Sobrien;;(define_expand "loadti" 409790075Sobrien;; [(set (match_operand:TI 0 "s_register_operand" "") 409890075Sobrien;; (mem:TI (match_operand:SI 1 "address_operand" "")))] 409990075Sobrien;; "" "") 410090075Sobrien 410190075Sobrien;;(define_expand "storeti" 410290075Sobrien;; [(set (mem:TI (match_operand:TI 0 "address_operand" "")) 410390075Sobrien;; (match_operand:TI 1 "s_register_operand" ""))] 410490075Sobrien;; "" "") 410590075Sobrien 410690075Sobrien;;(define_expand "movti" 410790075Sobrien;; [(set (match_operand:TI 0 "general_operand" "") 410890075Sobrien;; (match_operand:TI 1 "general_operand" ""))] 410990075Sobrien;; "" 411090075Sobrien;; " 411190075Sobrien;;{ 411290075Sobrien;; rtx insn; 411390075Sobrien;; 411490075Sobrien;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 411590075Sobrien;; operands[1] = copy_to_reg (operands[1]); 411690075Sobrien;; if (GET_CODE (operands[0]) == MEM) 411790075Sobrien;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]); 411890075Sobrien;; else if (GET_CODE (operands[1]) == MEM) 411990075Sobrien;; insn = gen_loadti (operands[0], XEXP (operands[1], 0)); 412090075Sobrien;; else 412190075Sobrien;; FAIL; 412290075Sobrien;; 412390075Sobrien;; emit_insn (insn); 412490075Sobrien;; DONE; 412590075Sobrien;;}") 412690075Sobrien 4127117395Skan;; Recognize garbage generated above. 412890075Sobrien 412990075Sobrien;;(define_insn "" 413090075Sobrien;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m") 413190075Sobrien;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))] 413290075Sobrien;; "" 413390075Sobrien;; "* 413490075Sobrien;; { 413590075Sobrien;; register mem = (which_alternative < 3); 413690075Sobrien;; register const char *template; 413790075Sobrien;; 413890075Sobrien;; operands[mem] = XEXP (operands[mem], 0); 413990075Sobrien;; switch (which_alternative) 414090075Sobrien;; { 414190075Sobrien;; case 0: template = \"ldmdb\\t%1!, %M0\"; break; 414290075Sobrien;; case 1: template = \"ldmia\\t%1!, %M0\"; break; 414390075Sobrien;; case 2: template = \"ldmia\\t%1, %M0\"; break; 414490075Sobrien;; case 3: template = \"stmdb\\t%0!, %M1\"; break; 414590075Sobrien;; case 4: template = \"stmia\\t%0!, %M1\"; break; 414690075Sobrien;; case 5: template = \"stmia\\t%0, %M1\"; break; 414790075Sobrien;; } 414890075Sobrien;; output_asm_insn (template, operands); 414990075Sobrien;; return \"\"; 415090075Sobrien;; }") 415190075Sobrien 415290075Sobrien(define_expand "movdi" 415390075Sobrien [(set (match_operand:DI 0 "general_operand" "") 415490075Sobrien (match_operand:DI 1 "general_operand" ""))] 415590075Sobrien "TARGET_EITHER" 415690075Sobrien " 4157169689Skan if (!no_new_pseudos) 415890075Sobrien { 4159169689Skan if (GET_CODE (operands[0]) != REG) 4160169689Skan operands[1] = force_reg (DImode, operands[1]); 416190075Sobrien } 416290075Sobrien " 416390075Sobrien) 416490075Sobrien 416590075Sobrien(define_insn "*arm_movdi" 4166169689Skan [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m") 4167169689Skan (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))] 4168169689Skan "TARGET_ARM 4169169689Skan && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP)) 4170169689Skan && !TARGET_IWMMXT 4171169689Skan && ( register_operand (operands[0], DImode) 4172169689Skan || register_operand (operands[1], DImode))" 417390075Sobrien "* 4174169689Skan switch (which_alternative) 4175169689Skan { 4176169689Skan case 0: 4177169689Skan case 1: 4178169689Skan case 2: 4179169689Skan return \"#\"; 4180169689Skan default: 4181169689Skan return output_move_double (operands); 4182169689Skan } 418390075Sobrien " 4184169689Skan [(set_attr "length" "8,12,16,8,8") 4185169689Skan (set_attr "type" "*,*,*,load2,store2") 4186169689Skan (set_attr "pool_range" "*,*,*,1020,*") 4187169689Skan (set_attr "neg_pool_range" "*,*,*,1008,*")] 418890075Sobrien) 418990075Sobrien 4190169689Skan(define_split 4191169689Skan [(set (match_operand:ANY64 0 "arm_general_register_operand" "") 4192169689Skan (match_operand:ANY64 1 "const_double_operand" ""))] 4193169689Skan "TARGET_ARM 4194169689Skan && reload_completed 4195169689Skan && (arm_const_double_inline_cost (operands[1]) 4196169689Skan <= ((optimize_size || arm_ld_sched) ? 3 : 4))" 4197169689Skan [(const_int 0)] 4198169689Skan " 4199169689Skan arm_split_constant (SET, SImode, curr_insn, 4200169689Skan INTVAL (gen_lowpart (SImode, operands[1])), 4201169689Skan gen_lowpart (SImode, operands[0]), NULL_RTX, 0); 4202169689Skan arm_split_constant (SET, SImode, curr_insn, 4203169689Skan INTVAL (gen_highpart_mode (SImode, 4204169689Skan GET_MODE (operands[0]), 4205169689Skan operands[1])), 4206169689Skan gen_highpart (SImode, operands[0]), NULL_RTX, 0); 4207169689Skan DONE; 4208169689Skan " 4209169689Skan) 4210169689Skan 4211169689Skan; If optimizing for size, or if we have load delay slots, then 4212169689Skan; we want to split the constant into two separate operations. 4213169689Skan; In both cases this may split a trivial part into a single data op 4214169689Skan; leaving a single complex constant to load. We can also get longer 4215169689Skan; offsets in a LDR which means we get better chances of sharing the pool 4216169689Skan; entries. Finally, we can normally do a better job of scheduling 4217169689Skan; LDR instructions than we can with LDM. 4218169689Skan; This pattern will only match if the one above did not. 4219169689Skan(define_split 4220169689Skan [(set (match_operand:ANY64 0 "arm_general_register_operand" "") 4221169689Skan (match_operand:ANY64 1 "const_double_operand" ""))] 4222169689Skan "TARGET_ARM && reload_completed 4223169689Skan && arm_const_double_by_parts (operands[1])" 4224169689Skan [(set (match_dup 0) (match_dup 1)) 4225169689Skan (set (match_dup 2) (match_dup 3))] 4226169689Skan " 4227169689Skan operands[2] = gen_highpart (SImode, operands[0]); 4228169689Skan operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]), 4229169689Skan operands[1]); 4230169689Skan operands[0] = gen_lowpart (SImode, operands[0]); 4231169689Skan operands[1] = gen_lowpart (SImode, operands[1]); 4232169689Skan " 4233169689Skan) 4234169689Skan 4235169689Skan(define_split 4236169689Skan [(set (match_operand:ANY64 0 "arm_general_register_operand" "") 4237169689Skan (match_operand:ANY64 1 "arm_general_register_operand" ""))] 4238169689Skan "TARGET_EITHER && reload_completed" 4239169689Skan [(set (match_dup 0) (match_dup 1)) 4240169689Skan (set (match_dup 2) (match_dup 3))] 4241169689Skan " 4242169689Skan operands[2] = gen_highpart (SImode, operands[0]); 4243169689Skan operands[3] = gen_highpart (SImode, operands[1]); 4244169689Skan operands[0] = gen_lowpart (SImode, operands[0]); 4245169689Skan operands[1] = gen_lowpart (SImode, operands[1]); 4246169689Skan 4247169689Skan /* Handle a partial overlap. */ 4248169689Skan if (rtx_equal_p (operands[0], operands[3])) 4249169689Skan { 4250169689Skan rtx tmp0 = operands[0]; 4251169689Skan rtx tmp1 = operands[1]; 4252169689Skan 4253169689Skan operands[0] = operands[2]; 4254169689Skan operands[1] = operands[3]; 4255169689Skan operands[2] = tmp0; 4256169689Skan operands[3] = tmp1; 4257169689Skan } 4258169689Skan " 4259169689Skan) 4260169689Skan 4261169689Skan;; We can't actually do base+index doubleword loads if the index and 4262169689Skan;; destination overlap. Split here so that we at least have chance to 4263169689Skan;; schedule. 4264169689Skan(define_split 4265169689Skan [(set (match_operand:DI 0 "s_register_operand" "") 4266169689Skan (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "") 4267169689Skan (match_operand:SI 2 "s_register_operand" ""))))] 4268169689Skan "TARGET_LDRD 4269169689Skan && reg_overlap_mentioned_p (operands[0], operands[1]) 4270169689Skan && reg_overlap_mentioned_p (operands[0], operands[2])" 4271169689Skan [(set (match_dup 4) 4272169689Skan (plus:SI (match_dup 1) 4273169689Skan (match_dup 2))) 4274169689Skan (set (match_dup 0) 4275169689Skan (mem:DI (match_dup 4)))] 4276169689Skan " 4277169689Skan operands[4] = gen_rtx_REG (SImode, REGNO(operands[0])); 4278169689Skan " 4279169689Skan) 4280169689Skan 428190075Sobrien;;; ??? This should have alternatives for constants. 428290075Sobrien;;; ??? This was originally identical to the movdf_insn pattern. 428390075Sobrien;;; ??? The 'i' constraint looks funny, but it should always be replaced by 428490075Sobrien;;; thumb_reorg with a memory reference. 428590075Sobrien(define_insn "*thumb_movdi_insn" 428690075Sobrien [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r") 428790075Sobrien (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))] 428890075Sobrien "TARGET_THUMB 4289169689Skan && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) 429090075Sobrien && ( register_operand (operands[0], DImode) 429190075Sobrien || register_operand (operands[1], DImode))" 429290075Sobrien "* 429390075Sobrien { 429490075Sobrien switch (which_alternative) 429590075Sobrien { 429690075Sobrien default: 429790075Sobrien case 0: 429890075Sobrien if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 429990075Sobrien return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 430090075Sobrien return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 430190075Sobrien case 1: 430290075Sobrien return \"mov\\t%Q0, %1\;mov\\t%R0, #0\"; 430390075Sobrien case 2: 430490075Sobrien operands[1] = GEN_INT (- INTVAL (operands[1])); 430590075Sobrien return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\"; 430690075Sobrien case 3: 430790075Sobrien return \"ldmia\\t%1, {%0, %H0}\"; 430890075Sobrien case 4: 430990075Sobrien return \"stmia\\t%0, {%1, %H1}\"; 431090075Sobrien case 5: 431190075Sobrien return thumb_load_double_from_address (operands); 431290075Sobrien case 6: 4313169689Skan operands[2] = gen_rtx_MEM (SImode, 431490075Sobrien plus_constant (XEXP (operands[0], 0), 4)); 431590075Sobrien output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 431690075Sobrien return \"\"; 431790075Sobrien case 7: 431890075Sobrien if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 431990075Sobrien return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 432090075Sobrien return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 432190075Sobrien } 432290075Sobrien }" 432390075Sobrien [(set_attr "length" "4,4,6,2,2,6,4,4") 4324169689Skan (set_attr "type" "*,*,*,load2,store2,load2,store2,*") 432590075Sobrien (set_attr "pool_range" "*,*,*,*,*,1020,*,*")] 432690075Sobrien) 432790075Sobrien 432890075Sobrien(define_expand "movsi" 432990075Sobrien [(set (match_operand:SI 0 "general_operand" "") 433090075Sobrien (match_operand:SI 1 "general_operand" ""))] 433190075Sobrien "TARGET_EITHER" 433290075Sobrien " 433390075Sobrien if (TARGET_ARM) 433490075Sobrien { 4335132718Skan /* Everything except mem = const or mem = mem can be done easily. */ 433690075Sobrien if (GET_CODE (operands[0]) == MEM) 433790075Sobrien operands[1] = force_reg (SImode, operands[1]); 4338169689Skan if (arm_general_register_operand (operands[0], SImode) 4339169689Skan && GET_CODE (operands[1]) == CONST_INT 434090075Sobrien && !(const_ok_for_arm (INTVAL (operands[1])) 434190075Sobrien || const_ok_for_arm (~INTVAL (operands[1])))) 434290075Sobrien { 4343169689Skan arm_split_constant (SET, SImode, NULL_RTX, 4344169689Skan INTVAL (operands[1]), operands[0], NULL_RTX, 4345169689Skan optimize && !no_new_pseudos); 434690075Sobrien DONE; 434790075Sobrien } 434890075Sobrien } 4349132718Skan else /* TARGET_THUMB.... */ 435090075Sobrien { 435190075Sobrien if (!no_new_pseudos) 435290075Sobrien { 435390075Sobrien if (GET_CODE (operands[0]) != REG) 435490075Sobrien operands[1] = force_reg (SImode, operands[1]); 435590075Sobrien } 435690075Sobrien } 4357169689Skan 4358169689Skan /* Recognize the case where operand[1] is a reference to thread-local 4359169689Skan data and load its address to a register. */ 4360169689Skan if (arm_tls_referenced_p (operands[1])) 4361169689Skan { 4362169689Skan rtx tmp = operands[1]; 4363169689Skan rtx addend = NULL; 4364169689Skan 4365169689Skan if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS) 4366169689Skan { 4367169689Skan addend = XEXP (XEXP (tmp, 0), 1); 4368169689Skan tmp = XEXP (XEXP (tmp, 0), 0); 4369169689Skan } 4370169689Skan 4371169689Skan gcc_assert (GET_CODE (tmp) == SYMBOL_REF); 4372169689Skan gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0); 4373169689Skan 4374169689Skan tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0); 4375169689Skan if (addend) 4376169689Skan { 4377169689Skan tmp = gen_rtx_PLUS (SImode, tmp, addend); 4378169689Skan tmp = force_operand (tmp, operands[0]); 4379169689Skan } 4380169689Skan operands[1] = tmp; 4381169689Skan } 4382169689Skan else if (flag_pic 4383169689Skan && (CONSTANT_P (operands[1]) 4384169689Skan || symbol_mentioned_p (operands[1]) 4385169689Skan || label_mentioned_p (operands[1]))) 4386169689Skan operands[1] = legitimize_pic_address (operands[1], SImode, 4387169689Skan (no_new_pseudos ? operands[0] : 0)); 438890075Sobrien " 438990075Sobrien) 439090075Sobrien 439190075Sobrien(define_insn "*arm_movsi_insn" 439290075Sobrien [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m") 439390075Sobrien (match_operand:SI 1 "general_operand" "rI,K,mi,r"))] 4394132718Skan "TARGET_ARM && ! TARGET_IWMMXT 4395169689Skan && !(TARGET_HARD_FLOAT && TARGET_VFP) 439690075Sobrien && ( register_operand (operands[0], SImode) 439790075Sobrien || register_operand (operands[1], SImode))" 439890075Sobrien "@ 439990075Sobrien mov%?\\t%0, %1 440090075Sobrien mvn%?\\t%0, #%B1 440190075Sobrien ldr%?\\t%0, %1 440290075Sobrien str%?\\t%1, %0" 4403169689Skan [(set_attr "type" "*,*,load1,store1") 440490075Sobrien (set_attr "predicable" "yes") 440590075Sobrien (set_attr "pool_range" "*,*,4096,*") 440690075Sobrien (set_attr "neg_pool_range" "*,*,4084,*")] 440790075Sobrien) 440890075Sobrien 440990075Sobrien(define_split 4410169689Skan [(set (match_operand:SI 0 "arm_general_register_operand" "") 441190075Sobrien (match_operand:SI 1 "const_int_operand" ""))] 441290075Sobrien "TARGET_ARM 441390075Sobrien && (!(const_ok_for_arm (INTVAL (operands[1])) 441490075Sobrien || const_ok_for_arm (~INTVAL (operands[1]))))" 441590075Sobrien [(clobber (const_int 0))] 441690075Sobrien " 4417169689Skan arm_split_constant (SET, SImode, NULL_RTX, 4418169689Skan INTVAL (operands[1]), operands[0], NULL_RTX, 0); 441990075Sobrien DONE; 442090075Sobrien " 442190075Sobrien) 442290075Sobrien 442390075Sobrien(define_insn "*thumb_movsi_insn" 442490075Sobrien [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh") 442590075Sobrien (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))] 442690075Sobrien "TARGET_THUMB 442790075Sobrien && ( register_operand (operands[0], SImode) 442890075Sobrien || register_operand (operands[1], SImode))" 442990075Sobrien "@ 443090075Sobrien mov %0, %1 443190075Sobrien mov %0, %1 443290075Sobrien # 443390075Sobrien # 443490075Sobrien ldmia\\t%1, {%0} 443590075Sobrien stmia\\t%0, {%1} 443690075Sobrien ldr\\t%0, %1 443790075Sobrien str\\t%1, %0 443890075Sobrien mov\\t%0, %1" 443990075Sobrien [(set_attr "length" "2,2,4,4,2,2,2,2,2") 4440169689Skan (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*") 444190075Sobrien (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")] 444290075Sobrien) 444390075Sobrien 444490075Sobrien(define_split 444590075Sobrien [(set (match_operand:SI 0 "register_operand" "") 444690075Sobrien (match_operand:SI 1 "const_int_operand" ""))] 4447169689Skan "TARGET_THUMB && satisfies_constraint_J (operands[1])" 444890075Sobrien [(set (match_dup 0) (match_dup 1)) 444990075Sobrien (set (match_dup 0) (neg:SI (match_dup 0)))] 445090075Sobrien "operands[1] = GEN_INT (- INTVAL (operands[1]));" 445190075Sobrien) 445290075Sobrien 445390075Sobrien(define_split 445490075Sobrien [(set (match_operand:SI 0 "register_operand" "") 445590075Sobrien (match_operand:SI 1 "const_int_operand" ""))] 4456169689Skan "TARGET_THUMB && satisfies_constraint_K (operands[1])" 445790075Sobrien [(set (match_dup 0) (match_dup 1)) 445890075Sobrien (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))] 445990075Sobrien " 446090075Sobrien { 446190075Sobrien unsigned HOST_WIDE_INT val = INTVAL (operands[1]); 446290075Sobrien unsigned HOST_WIDE_INT mask = 0xff; 446390075Sobrien int i; 446490075Sobrien 446590075Sobrien for (i = 0; i < 25; i++) 446690075Sobrien if ((val & (mask << i)) == val) 446790075Sobrien break; 446890075Sobrien 4469117395Skan /* Shouldn't happen, but we don't want to split if the shift is zero. */ 447090075Sobrien if (i == 0) 447190075Sobrien FAIL; 447290075Sobrien 447390075Sobrien operands[1] = GEN_INT (val >> i); 447490075Sobrien operands[2] = GEN_INT (i); 447590075Sobrien }" 447690075Sobrien) 447790075Sobrien 447890075Sobrien;; When generating pic, we need to load the symbol offset into a register. 447990075Sobrien;; So that the optimizer does not confuse this with a normal symbol load 448090075Sobrien;; we use an unspec. The offset will be loaded from a constant pool entry, 448190075Sobrien;; since that is the only type of relocation we can use. 448290075Sobrien 448390075Sobrien;; The rather odd constraints on the following are to force reload to leave 448490075Sobrien;; the insn alone, and to force the minipool generation pass to then move 448590075Sobrien;; the GOT symbol to memory. 448690075Sobrien 448790075Sobrien(define_insn "pic_load_addr_arm" 448890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 448990075Sobrien (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] 449090075Sobrien "TARGET_ARM && flag_pic" 449190075Sobrien "ldr%?\\t%0, %1" 4492169689Skan [(set_attr "type" "load1") 449390075Sobrien (set (attr "pool_range") (const_int 4096)) 449490075Sobrien (set (attr "neg_pool_range") (const_int 4084))] 449590075Sobrien) 449690075Sobrien 449790075Sobrien(define_insn "pic_load_addr_thumb" 449890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=l") 449990075Sobrien (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] 450090075Sobrien "TARGET_THUMB && flag_pic" 450190075Sobrien "ldr\\t%0, %1" 4502169689Skan [(set_attr "type" "load1") 450390075Sobrien (set (attr "pool_range") (const_int 1024))] 450490075Sobrien) 450590075Sobrien 450690075Sobrien;; This variant is used for AOF assembly, since it needs to mention the 450790075Sobrien;; pic register in the rtl. 450890075Sobrien(define_expand "pic_load_addr_based" 4509132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 451090075Sobrien (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))] 451190075Sobrien "TARGET_ARM && flag_pic" 4512169689Skan "operands[2] = cfun->machine->pic_reg;" 451390075Sobrien) 451490075Sobrien 451590075Sobrien(define_insn "*pic_load_addr_based_insn" 451690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 451790075Sobrien (unspec:SI [(match_operand 1 "" "") 451890075Sobrien (match_operand 2 "s_register_operand" "r")] 451990075Sobrien UNSPEC_PIC_SYM))] 4520169689Skan "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg" 452190075Sobrien "* 452290075Sobrien#ifdef AOF_ASSEMBLER 452390075Sobrien operands[1] = aof_pic_entry (operands[1]); 452490075Sobrien#endif 452590075Sobrien output_asm_insn (\"ldr%?\\t%0, %a1\", operands); 452690075Sobrien return \"\"; 452790075Sobrien " 4528169689Skan [(set_attr "type" "load1") 452990075Sobrien (set (attr "pool_range") 453090075Sobrien (if_then_else (eq_attr "is_thumb" "yes") 453190075Sobrien (const_int 1024) 453290075Sobrien (const_int 4096))) 453390075Sobrien (set (attr "neg_pool_range") 453490075Sobrien (if_then_else (eq_attr "is_thumb" "yes") 453590075Sobrien (const_int 0) 453690075Sobrien (const_int 4084)))] 453790075Sobrien) 453890075Sobrien 453990075Sobrien(define_insn "pic_add_dot_plus_four" 4540169689Skan [(set (match_operand:SI 0 "register_operand" "=r") 4541169689Skan (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0") 4542117395Skan (const (plus:SI (pc) (const_int 4))))] 4543117395Skan UNSPEC_PIC_BASE)) 4544169689Skan (use (match_operand 2 "" ""))] 4545169689Skan "TARGET_THUMB" 454690075Sobrien "* 4547169689Skan (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\", 4548169689Skan INTVAL (operands[2])); 454990075Sobrien return \"add\\t%0, %|pc\"; 455090075Sobrien " 455190075Sobrien [(set_attr "length" "2")] 455290075Sobrien) 455390075Sobrien 455490075Sobrien(define_insn "pic_add_dot_plus_eight" 4555169689Skan [(set (match_operand:SI 0 "register_operand" "=r") 4556169689Skan (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r") 4557117395Skan (const (plus:SI (pc) (const_int 8))))] 4558117395Skan UNSPEC_PIC_BASE)) 4559169689Skan (use (match_operand 2 "" ""))] 4560169689Skan "TARGET_ARM" 456190075Sobrien "* 4562169689Skan (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\", 4563169689Skan INTVAL (operands[2])); 4564169689Skan return \"add%?\\t%0, %|pc, %1\"; 456590075Sobrien " 456690075Sobrien [(set_attr "predicable" "yes")] 456790075Sobrien) 456890075Sobrien 4569169689Skan(define_insn "tls_load_dot_plus_eight" 4570169689Skan [(set (match_operand:SI 0 "register_operand" "+r") 4571169689Skan (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r") 4572169689Skan (const (plus:SI (pc) (const_int 8))))] 4573169689Skan UNSPEC_PIC_BASE))) 4574169689Skan (use (match_operand 2 "" ""))] 4575169689Skan "TARGET_ARM" 4576169689Skan "* 4577169689Skan (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\", 4578169689Skan INTVAL (operands[2])); 4579169689Skan return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\"; 4580169689Skan " 4581169689Skan [(set_attr "predicable" "yes")] 4582169689Skan) 4583169689Skan 4584169689Skan;; PIC references to local variables can generate pic_add_dot_plus_eight 4585169689Skan;; followed by a load. These sequences can be crunched down to 4586169689Skan;; tls_load_dot_plus_eight by a peephole. 4587169689Skan 4588169689Skan(define_peephole2 4589169689Skan [(parallel [(set (match_operand:SI 0 "register_operand" "") 4590169689Skan (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "") 4591169689Skan (const (plus:SI (pc) (const_int 8))))] 4592169689Skan UNSPEC_PIC_BASE)) 4593169689Skan (use (label_ref (match_operand 1 "" "")))]) 4594169689Skan (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))] 4595169689Skan "TARGET_ARM && peep2_reg_dead_p (2, operands[0])" 4596169689Skan [(parallel [(set (match_dup 2) 4597169689Skan (mem:SI (unspec:SI [(plus:SI (match_dup 3) 4598169689Skan (const (plus:SI (pc) (const_int 8))))] 4599169689Skan UNSPEC_PIC_BASE))) 4600169689Skan (use (label_ref (match_dup 1)))])] 4601169689Skan "" 4602169689Skan) 4603169689Skan 460490075Sobrien(define_expand "builtin_setjmp_receiver" 460590075Sobrien [(label_ref (match_operand 0 "" ""))] 460690075Sobrien "flag_pic" 460790075Sobrien " 460890075Sobrien{ 4609169689Skan /* r3 is clobbered by set/longjmp, so we can use it as a scratch 4610169689Skan register. */ 4611169689Skan if (arm_pic_register != INVALID_REGNUM) 4612169689Skan arm_load_pic_register (1UL << 3); 461390075Sobrien DONE; 461490075Sobrien}") 461590075Sobrien 461690075Sobrien;; If copying one reg to another we can set the condition codes according to 461790075Sobrien;; its value. Such a move is common after a return from subroutine and the 461890075Sobrien;; result is being tested against zero. 461990075Sobrien 462090075Sobrien(define_insn "*movsi_compare0" 462190075Sobrien [(set (reg:CC CC_REGNUM) 462290075Sobrien (compare:CC (match_operand:SI 1 "s_register_operand" "0,r") 462390075Sobrien (const_int 0))) 462490075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 462590075Sobrien (match_dup 1))] 462690075Sobrien "TARGET_ARM" 462790075Sobrien "@ 462890075Sobrien cmp%?\\t%0, #0 462990075Sobrien sub%?s\\t%0, %1, #0" 463090075Sobrien [(set_attr "conds" "set")] 463190075Sobrien) 463290075Sobrien 463390075Sobrien;; Subroutine to store a half word from a register into memory. 463490075Sobrien;; Operand 0 is the source register (HImode) 463590075Sobrien;; Operand 1 is the destination address in a register (SImode) 463690075Sobrien 463790075Sobrien;; In both this routine and the next, we must be careful not to spill 463890075Sobrien;; a memory address of reg+large_const into a separate PLUS insn, since this 463990075Sobrien;; can generate unrecognizable rtl. 464090075Sobrien 464190075Sobrien(define_expand "storehi" 464290075Sobrien [;; store the low byte 464390075Sobrien (set (match_operand 1 "" "") (match_dup 3)) 464490075Sobrien ;; extract the high byte 464590075Sobrien (set (match_dup 2) 464690075Sobrien (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 464790075Sobrien ;; store the high byte 4648132718Skan (set (match_dup 4) (match_dup 5))] 464990075Sobrien "TARGET_ARM" 465090075Sobrien " 465190075Sobrien { 465290075Sobrien rtx op1 = operands[1]; 465390075Sobrien rtx addr = XEXP (op1, 0); 465490075Sobrien enum rtx_code code = GET_CODE (addr); 465590075Sobrien 465690075Sobrien if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 465790075Sobrien || code == MINUS) 465890075Sobrien op1 = replace_equiv_address (operands[1], force_reg (SImode, addr)); 465990075Sobrien 466090075Sobrien operands[4] = adjust_address (op1, QImode, 1); 466190075Sobrien operands[1] = adjust_address (operands[1], QImode, 0); 466290075Sobrien operands[3] = gen_lowpart (QImode, operands[0]); 466390075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 4664132718Skan operands[2] = gen_reg_rtx (SImode); 4665132718Skan operands[5] = gen_lowpart (QImode, operands[2]); 466690075Sobrien }" 466790075Sobrien) 466890075Sobrien 466990075Sobrien(define_expand "storehi_bigend" 467090075Sobrien [(set (match_dup 4) (match_dup 3)) 467190075Sobrien (set (match_dup 2) 467290075Sobrien (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 4673132718Skan (set (match_operand 1 "" "") (match_dup 5))] 467490075Sobrien "TARGET_ARM" 467590075Sobrien " 467690075Sobrien { 467790075Sobrien rtx op1 = operands[1]; 467890075Sobrien rtx addr = XEXP (op1, 0); 467990075Sobrien enum rtx_code code = GET_CODE (addr); 468090075Sobrien 468190075Sobrien if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 468290075Sobrien || code == MINUS) 468390075Sobrien op1 = replace_equiv_address (op1, force_reg (SImode, addr)); 468490075Sobrien 468590075Sobrien operands[4] = adjust_address (op1, QImode, 1); 468690075Sobrien operands[1] = adjust_address (operands[1], QImode, 0); 468790075Sobrien operands[3] = gen_lowpart (QImode, operands[0]); 468890075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 468990075Sobrien operands[2] = gen_reg_rtx (SImode); 4690132718Skan operands[5] = gen_lowpart (QImode, operands[2]); 469190075Sobrien }" 469290075Sobrien) 469390075Sobrien 469490075Sobrien;; Subroutine to store a half word integer constant into memory. 469590075Sobrien(define_expand "storeinthi" 469690075Sobrien [(set (match_operand 0 "" "") 4697132718Skan (match_operand 1 "" "")) 4698102780Skan (set (match_dup 3) (match_dup 2))] 469990075Sobrien "TARGET_ARM" 470090075Sobrien " 470190075Sobrien { 470290075Sobrien HOST_WIDE_INT value = INTVAL (operands[1]); 470390075Sobrien rtx addr = XEXP (operands[0], 0); 470490075Sobrien rtx op0 = operands[0]; 470590075Sobrien enum rtx_code code = GET_CODE (addr); 470690075Sobrien 470790075Sobrien if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 470890075Sobrien || code == MINUS) 470990075Sobrien op0 = replace_equiv_address (op0, force_reg (SImode, addr)); 471090075Sobrien 471190075Sobrien operands[1] = gen_reg_rtx (SImode); 471290075Sobrien if (BYTES_BIG_ENDIAN) 471390075Sobrien { 471490075Sobrien emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255))); 471590075Sobrien if ((value & 255) == ((value >> 8) & 255)) 471690075Sobrien operands[2] = operands[1]; 471790075Sobrien else 471890075Sobrien { 471990075Sobrien operands[2] = gen_reg_rtx (SImode); 472090075Sobrien emit_insn (gen_movsi (operands[2], GEN_INT (value & 255))); 472190075Sobrien } 472290075Sobrien } 472390075Sobrien else 472490075Sobrien { 472590075Sobrien emit_insn (gen_movsi (operands[1], GEN_INT (value & 255))); 472690075Sobrien if ((value & 255) == ((value >> 8) & 255)) 472790075Sobrien operands[2] = operands[1]; 472890075Sobrien else 472990075Sobrien { 473090075Sobrien operands[2] = gen_reg_rtx (SImode); 473190075Sobrien emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255))); 473290075Sobrien } 473390075Sobrien } 473490075Sobrien 473590075Sobrien operands[3] = adjust_address (op0, QImode, 1); 473690075Sobrien operands[0] = adjust_address (operands[0], QImode, 0); 4737102780Skan operands[2] = gen_lowpart (QImode, operands[2]); 4738132718Skan operands[1] = gen_lowpart (QImode, operands[1]); 473990075Sobrien }" 474090075Sobrien) 474190075Sobrien 474290075Sobrien(define_expand "storehi_single_op" 474390075Sobrien [(set (match_operand:HI 0 "memory_operand" "") 474490075Sobrien (match_operand:HI 1 "general_operand" ""))] 474590075Sobrien "TARGET_ARM && arm_arch4" 474690075Sobrien " 474790075Sobrien if (!s_register_operand (operands[1], HImode)) 474890075Sobrien operands[1] = copy_to_mode_reg (HImode, operands[1]); 474990075Sobrien " 475090075Sobrien) 475190075Sobrien 475290075Sobrien(define_expand "movhi" 475390075Sobrien [(set (match_operand:HI 0 "general_operand" "") 475490075Sobrien (match_operand:HI 1 "general_operand" ""))] 475590075Sobrien "TARGET_EITHER" 475690075Sobrien " 475790075Sobrien if (TARGET_ARM) 475890075Sobrien { 475990075Sobrien if (!no_new_pseudos) 476090075Sobrien { 476190075Sobrien if (GET_CODE (operands[0]) == MEM) 476290075Sobrien { 476390075Sobrien if (arm_arch4) 476490075Sobrien { 476590075Sobrien emit_insn (gen_storehi_single_op (operands[0], operands[1])); 476690075Sobrien DONE; 476790075Sobrien } 476890075Sobrien if (GET_CODE (operands[1]) == CONST_INT) 476990075Sobrien emit_insn (gen_storeinthi (operands[0], operands[1])); 477090075Sobrien else 477190075Sobrien { 477290075Sobrien if (GET_CODE (operands[1]) == MEM) 477390075Sobrien operands[1] = force_reg (HImode, operands[1]); 477490075Sobrien if (BYTES_BIG_ENDIAN) 477590075Sobrien emit_insn (gen_storehi_bigend (operands[1], operands[0])); 477690075Sobrien else 477790075Sobrien emit_insn (gen_storehi (operands[1], operands[0])); 477890075Sobrien } 477990075Sobrien DONE; 478090075Sobrien } 478190075Sobrien /* Sign extend a constant, and keep it in an SImode reg. */ 478290075Sobrien else if (GET_CODE (operands[1]) == CONST_INT) 478390075Sobrien { 478490075Sobrien rtx reg = gen_reg_rtx (SImode); 478590075Sobrien HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff; 478690075Sobrien 478790075Sobrien /* If the constant is already valid, leave it alone. */ 478890075Sobrien if (!const_ok_for_arm (val)) 478990075Sobrien { 479090075Sobrien /* If setting all the top bits will make the constant 479190075Sobrien loadable in a single instruction, then set them. 479290075Sobrien Otherwise, sign extend the number. */ 479390075Sobrien 479490075Sobrien if (const_ok_for_arm (~(val | ~0xffff))) 479590075Sobrien val |= ~0xffff; 479690075Sobrien else if (val & 0x8000) 479790075Sobrien val |= ~0xffff; 479890075Sobrien } 479990075Sobrien 480090075Sobrien emit_insn (gen_movsi (reg, GEN_INT (val))); 4801102780Skan operands[1] = gen_lowpart (HImode, reg); 480290075Sobrien } 4803169689Skan else if (arm_arch4 && optimize && !no_new_pseudos 4804117395Skan && GET_CODE (operands[1]) == MEM) 4805117395Skan { 4806117395Skan rtx reg = gen_reg_rtx (SImode); 4807117395Skan 4808117395Skan emit_insn (gen_zero_extendhisi2 (reg, operands[1])); 4809117395Skan operands[1] = gen_lowpart (HImode, reg); 4810117395Skan } 481190075Sobrien else if (!arm_arch4) 481290075Sobrien { 481390075Sobrien if (GET_CODE (operands[1]) == MEM) 481490075Sobrien { 4815169689Skan rtx base; 4816169689Skan rtx offset = const0_rtx; 4817169689Skan rtx reg = gen_reg_rtx (SImode); 4818169689Skan 4819169689Skan if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 4820169689Skan || (GET_CODE (base) == PLUS 4821169689Skan && (GET_CODE (offset = XEXP (base, 1)) 4822169689Skan == CONST_INT) 4823169689Skan && ((INTVAL(offset) & 1) != 1) 4824169689Skan && GET_CODE (base = XEXP (base, 0)) == REG)) 4825169689Skan && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 482690075Sobrien { 4827169689Skan rtx new; 482890075Sobrien 4829169689Skan new = widen_memory_access (operands[1], SImode, 4830169689Skan ((INTVAL (offset) & ~3) 4831169689Skan - INTVAL (offset))); 4832169689Skan emit_insn (gen_movsi (reg, new)); 4833169689Skan if (((INTVAL (offset) & 2) != 0) 4834169689Skan ^ (BYTES_BIG_ENDIAN ? 1 : 0)) 4835169689Skan { 4836169689Skan rtx reg2 = gen_reg_rtx (SImode); 483790075Sobrien 4838169689Skan emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16))); 4839169689Skan reg = reg2; 4840169689Skan } 484190075Sobrien } 4842169689Skan else 4843169689Skan emit_insn (gen_movhi_bytes (reg, operands[1])); 484490075Sobrien 4845169689Skan operands[1] = gen_lowpart (HImode, reg); 484690075Sobrien } 484790075Sobrien } 484890075Sobrien } 4849132718Skan /* Handle loading a large integer during reload. */ 485090075Sobrien else if (GET_CODE (operands[1]) == CONST_INT 485190075Sobrien && !const_ok_for_arm (INTVAL (operands[1])) 485290075Sobrien && !const_ok_for_arm (~INTVAL (operands[1]))) 485390075Sobrien { 485490075Sobrien /* Writing a constant to memory needs a scratch, which should 485590075Sobrien be handled with SECONDARY_RELOADs. */ 4856169689Skan gcc_assert (GET_CODE (operands[0]) == REG); 485790075Sobrien 485890075Sobrien operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 485990075Sobrien emit_insn (gen_movsi (operands[0], operands[1])); 486090075Sobrien DONE; 486190075Sobrien } 486290075Sobrien } 486390075Sobrien else /* TARGET_THUMB */ 486490075Sobrien { 486590075Sobrien if (!no_new_pseudos) 486690075Sobrien { 4867169689Skan if (GET_CODE (operands[1]) == CONST_INT) 4868169689Skan { 4869169689Skan rtx reg = gen_reg_rtx (SImode); 487090075Sobrien 4871169689Skan emit_insn (gen_movsi (reg, operands[1])); 4872169689Skan operands[1] = gen_lowpart (HImode, reg); 4873169689Skan } 4874169689Skan 487590075Sobrien /* ??? We shouldn't really get invalid addresses here, but this can 487690075Sobrien happen if we are passed a SP (never OK for HImode/QImode) or 487790075Sobrien virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 487890075Sobrien HImode/QImode) relative address. */ 487990075Sobrien /* ??? This should perhaps be fixed elsewhere, for instance, in 488090075Sobrien fixup_stack_1, by checking for other kinds of invalid addresses, 488190075Sobrien e.g. a bare reference to a virtual register. This may confuse the 488290075Sobrien alpha though, which must handle this case differently. */ 488390075Sobrien if (GET_CODE (operands[0]) == MEM 488490075Sobrien && !memory_address_p (GET_MODE (operands[0]), 488590075Sobrien XEXP (operands[0], 0))) 488690075Sobrien operands[0] 488790075Sobrien = replace_equiv_address (operands[0], 488890075Sobrien copy_to_reg (XEXP (operands[0], 0))); 488990075Sobrien 489090075Sobrien if (GET_CODE (operands[1]) == MEM 489190075Sobrien && !memory_address_p (GET_MODE (operands[1]), 489290075Sobrien XEXP (operands[1], 0))) 489390075Sobrien operands[1] 489490075Sobrien = replace_equiv_address (operands[1], 489590075Sobrien copy_to_reg (XEXP (operands[1], 0))); 4896169689Skan 4897169689Skan if (GET_CODE (operands[1]) == MEM && optimize > 0) 4898169689Skan { 4899169689Skan rtx reg = gen_reg_rtx (SImode); 4900169689Skan 4901169689Skan emit_insn (gen_zero_extendhisi2 (reg, operands[1])); 4902169689Skan operands[1] = gen_lowpart (HImode, reg); 4903169689Skan } 4904169689Skan 4905169689Skan if (GET_CODE (operands[0]) == MEM) 4906169689Skan operands[1] = force_reg (HImode, operands[1]); 490790075Sobrien } 490890075Sobrien else if (GET_CODE (operands[1]) == CONST_INT 4909169689Skan && !satisfies_constraint_I (operands[1])) 491090075Sobrien { 4911169689Skan /* Handle loading a large integer during reload. */ 4912169689Skan 491390075Sobrien /* Writing a constant to memory needs a scratch, which should 491490075Sobrien be handled with SECONDARY_RELOADs. */ 4915169689Skan gcc_assert (GET_CODE (operands[0]) == REG); 491690075Sobrien 4917169689Skan operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 491890075Sobrien emit_insn (gen_movsi (operands[0], operands[1])); 491990075Sobrien DONE; 492090075Sobrien } 492190075Sobrien } 492290075Sobrien " 492390075Sobrien) 492490075Sobrien 492590075Sobrien(define_insn "*thumb_movhi_insn" 4926132718Skan [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l") 4927132718Skan (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))] 492890075Sobrien "TARGET_THUMB 492990075Sobrien && ( register_operand (operands[0], HImode) 493090075Sobrien || register_operand (operands[1], HImode))" 493190075Sobrien "* 493290075Sobrien switch (which_alternative) 493390075Sobrien { 493490075Sobrien case 0: return \"add %0, %1, #0\"; 493590075Sobrien case 2: return \"strh %1, %0\"; 493690075Sobrien case 3: return \"mov %0, %1\"; 493790075Sobrien case 4: return \"mov %0, %1\"; 493890075Sobrien case 5: return \"mov %0, %1\"; 4939169689Skan default: gcc_unreachable (); 494090075Sobrien case 1: 494190075Sobrien /* The stack pointer can end up being taken as an index register. 494290075Sobrien Catch this case here and deal with it. */ 494390075Sobrien if (GET_CODE (XEXP (operands[1], 0)) == PLUS 494490075Sobrien && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG 494590075Sobrien && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM) 494690075Sobrien { 494790075Sobrien rtx ops[2]; 494890075Sobrien ops[0] = operands[0]; 494990075Sobrien ops[1] = XEXP (XEXP (operands[1], 0), 0); 495090075Sobrien 495190075Sobrien output_asm_insn (\"mov %0, %1\", ops); 495290075Sobrien 495390075Sobrien XEXP (XEXP (operands[1], 0), 0) = operands[0]; 495490075Sobrien 495590075Sobrien } 495690075Sobrien return \"ldrh %0, %1\"; 495790075Sobrien }" 495890075Sobrien [(set_attr "length" "2,4,2,2,2,2") 4959169689Skan (set_attr "type" "*,load1,store1,*,*,*")] 496090075Sobrien) 496190075Sobrien 496290075Sobrien 496390075Sobrien(define_expand "movhi_bytes" 496490075Sobrien [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 496590075Sobrien (set (match_dup 3) 496690075Sobrien (zero_extend:SI (match_dup 6))) 496790075Sobrien (set (match_operand:SI 0 "" "") 496890075Sobrien (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))] 496990075Sobrien "TARGET_ARM" 497090075Sobrien " 497190075Sobrien { 497290075Sobrien rtx mem1, mem2; 497390075Sobrien rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 497490075Sobrien 4975169689Skan mem1 = change_address (operands[1], QImode, addr); 4976169689Skan mem2 = change_address (operands[1], QImode, plus_constant (addr, 1)); 497790075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 497890075Sobrien operands[1] = mem1; 497990075Sobrien operands[2] = gen_reg_rtx (SImode); 498090075Sobrien operands[3] = gen_reg_rtx (SImode); 498190075Sobrien operands[6] = mem2; 498290075Sobrien 498390075Sobrien if (BYTES_BIG_ENDIAN) 498490075Sobrien { 498590075Sobrien operands[4] = operands[2]; 498690075Sobrien operands[5] = operands[3]; 498790075Sobrien } 498890075Sobrien else 498990075Sobrien { 499090075Sobrien operands[4] = operands[3]; 499190075Sobrien operands[5] = operands[2]; 499290075Sobrien } 499390075Sobrien }" 499490075Sobrien) 499590075Sobrien 499690075Sobrien(define_expand "movhi_bigend" 499790075Sobrien [(set (match_dup 2) 499890075Sobrien (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0) 499990075Sobrien (const_int 16))) 500090075Sobrien (set (match_dup 3) 500190075Sobrien (ashiftrt:SI (match_dup 2) (const_int 16))) 500290075Sobrien (set (match_operand:HI 0 "s_register_operand" "") 5003132718Skan (match_dup 4))] 500490075Sobrien "TARGET_ARM" 500590075Sobrien " 500690075Sobrien operands[2] = gen_reg_rtx (SImode); 500790075Sobrien operands[3] = gen_reg_rtx (SImode); 5008132718Skan operands[4] = gen_lowpart (HImode, operands[3]); 500990075Sobrien " 501090075Sobrien) 501190075Sobrien 5012117395Skan;; Pattern to recognize insn generated default case above 501390075Sobrien(define_insn "*movhi_insn_arch4" 501490075Sobrien [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") 501590075Sobrien (match_operand:HI 1 "general_operand" "rI,K,r,m"))] 501690075Sobrien "TARGET_ARM 501790075Sobrien && arm_arch4 501890075Sobrien && (GET_CODE (operands[1]) != CONST_INT 501990075Sobrien || const_ok_for_arm (INTVAL (operands[1])) 502090075Sobrien || const_ok_for_arm (~INTVAL (operands[1])))" 502190075Sobrien "@ 502290075Sobrien mov%?\\t%0, %1\\t%@ movhi 502390075Sobrien mvn%?\\t%0, #%B1\\t%@ movhi 5024169689Skan str%?h\\t%1, %0\\t%@ movhi 502590075Sobrien ldr%?h\\t%0, %1\\t%@ movhi" 5026169689Skan [(set_attr "type" "*,*,store1,load1") 502790075Sobrien (set_attr "predicable" "yes") 502890075Sobrien (set_attr "pool_range" "*,*,*,256") 502990075Sobrien (set_attr "neg_pool_range" "*,*,*,244")] 503090075Sobrien) 503190075Sobrien 503290075Sobrien(define_insn "*movhi_bytes" 503390075Sobrien [(set (match_operand:HI 0 "s_register_operand" "=r,r") 503490075Sobrien (match_operand:HI 1 "arm_rhs_operand" "rI,K"))] 5035169689Skan "TARGET_ARM" 503690075Sobrien "@ 503790075Sobrien mov%?\\t%0, %1\\t%@ movhi 503890075Sobrien mvn%?\\t%0, #%B1\\t%@ movhi" 503990075Sobrien [(set_attr "predicable" "yes")] 504090075Sobrien) 504190075Sobrien 5042169689Skan(define_expand "thumb_movhi_clobber" 5043169689Skan [(set (match_operand:HI 0 "memory_operand" "") 5044169689Skan (match_operand:HI 1 "register_operand" "")) 5045169689Skan (clobber (match_operand:DI 2 "register_operand" ""))] 504690075Sobrien "TARGET_THUMB" 5047169689Skan " 5048169689Skan if (strict_memory_address_p (HImode, XEXP (operands[0], 0)) 5049169689Skan && REGNO (operands[1]) <= LAST_LO_REGNUM) 5050169689Skan { 5051169689Skan emit_insn (gen_movhi (operands[0], operands[1])); 5052169689Skan DONE; 5053169689Skan } 5054169689Skan /* XXX Fixme, need to handle other cases here as well. */ 5055169689Skan gcc_unreachable (); 5056169689Skan " 505790075Sobrien) 505890075Sobrien 505990075Sobrien;; We use a DImode scratch because we may occasionally need an additional 506090075Sobrien;; temporary if the address isn't offsettable -- push_reload doesn't seem 506190075Sobrien;; to take any notice of the "o" constraints on reload_memory_operand operand. 506290075Sobrien(define_expand "reload_outhi" 506390075Sobrien [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o") 506490075Sobrien (match_operand:HI 1 "s_register_operand" "r") 506590075Sobrien (match_operand:DI 2 "s_register_operand" "=&l")])] 506690075Sobrien "TARGET_EITHER" 506790075Sobrien "if (TARGET_ARM) 506890075Sobrien arm_reload_out_hi (operands); 506990075Sobrien else 507090075Sobrien thumb_reload_out_hi (operands); 507190075Sobrien DONE; 507290075Sobrien " 507390075Sobrien) 507490075Sobrien 507590075Sobrien(define_expand "reload_inhi" 507690075Sobrien [(parallel [(match_operand:HI 0 "s_register_operand" "=r") 507790075Sobrien (match_operand:HI 1 "arm_reload_memory_operand" "o") 507890075Sobrien (match_operand:DI 2 "s_register_operand" "=&r")])] 5079169689Skan "TARGET_EITHER" 508090075Sobrien " 508190075Sobrien if (TARGET_ARM) 508290075Sobrien arm_reload_in_hi (operands); 508390075Sobrien else 508490075Sobrien thumb_reload_out_hi (operands); 508590075Sobrien DONE; 508690075Sobrien") 508790075Sobrien 508890075Sobrien(define_expand "movqi" 508990075Sobrien [(set (match_operand:QI 0 "general_operand" "") 509090075Sobrien (match_operand:QI 1 "general_operand" ""))] 509190075Sobrien "TARGET_EITHER" 509290075Sobrien " 5093169689Skan /* Everything except mem = const or mem = mem can be done easily */ 5094169689Skan 5095169689Skan if (!no_new_pseudos) 509690075Sobrien { 5097169689Skan if (GET_CODE (operands[1]) == CONST_INT) 5098169689Skan { 5099169689Skan rtx reg = gen_reg_rtx (SImode); 510090075Sobrien 5101169689Skan emit_insn (gen_movsi (reg, operands[1])); 5102169689Skan operands[1] = gen_lowpart (QImode, reg); 5103169689Skan } 510490075Sobrien 5105169689Skan if (TARGET_THUMB) 5106169689Skan { 510790075Sobrien /* ??? We shouldn't really get invalid addresses here, but this can 510890075Sobrien happen if we are passed a SP (never OK for HImode/QImode) or 510990075Sobrien virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 511090075Sobrien HImode/QImode) relative address. */ 511190075Sobrien /* ??? This should perhaps be fixed elsewhere, for instance, in 511290075Sobrien fixup_stack_1, by checking for other kinds of invalid addresses, 511390075Sobrien e.g. a bare reference to a virtual register. This may confuse the 511490075Sobrien alpha though, which must handle this case differently. */ 511590075Sobrien if (GET_CODE (operands[0]) == MEM 511690075Sobrien && !memory_address_p (GET_MODE (operands[0]), 511790075Sobrien XEXP (operands[0], 0))) 511890075Sobrien operands[0] 511990075Sobrien = replace_equiv_address (operands[0], 512090075Sobrien copy_to_reg (XEXP (operands[0], 0))); 512190075Sobrien if (GET_CODE (operands[1]) == MEM 512290075Sobrien && !memory_address_p (GET_MODE (operands[1]), 512390075Sobrien XEXP (operands[1], 0))) 512490075Sobrien operands[1] 512590075Sobrien = replace_equiv_address (operands[1], 512690075Sobrien copy_to_reg (XEXP (operands[1], 0))); 5127169689Skan } 5128169689Skan 5129169689Skan if (GET_CODE (operands[1]) == MEM && optimize > 0) 5130169689Skan { 5131169689Skan rtx reg = gen_reg_rtx (SImode); 5132169689Skan 5133169689Skan emit_insn (gen_zero_extendqisi2 (reg, operands[1])); 5134169689Skan operands[1] = gen_lowpart (QImode, reg); 5135169689Skan } 5136169689Skan 5137169689Skan if (GET_CODE (operands[0]) == MEM) 5138169689Skan operands[1] = force_reg (QImode, operands[1]); 5139169689Skan } 5140169689Skan else if (TARGET_THUMB 5141169689Skan && GET_CODE (operands[1]) == CONST_INT 5142169689Skan && !satisfies_constraint_I (operands[1])) 5143169689Skan { 5144132718Skan /* Handle loading a large integer during reload. */ 514590075Sobrien 5146169689Skan /* Writing a constant to memory needs a scratch, which should 5147169689Skan be handled with SECONDARY_RELOADs. */ 5148169689Skan gcc_assert (GET_CODE (operands[0]) == REG); 5149169689Skan 5150169689Skan operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 5151169689Skan emit_insn (gen_movsi (operands[0], operands[1])); 5152169689Skan DONE; 515390075Sobrien } 515490075Sobrien " 515590075Sobrien) 515690075Sobrien 515790075Sobrien 515890075Sobrien(define_insn "*arm_movqi_insn" 515990075Sobrien [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m") 516090075Sobrien (match_operand:QI 1 "general_operand" "rI,K,m,r"))] 516190075Sobrien "TARGET_ARM 516290075Sobrien && ( register_operand (operands[0], QImode) 516390075Sobrien || register_operand (operands[1], QImode))" 516490075Sobrien "@ 516590075Sobrien mov%?\\t%0, %1 516690075Sobrien mvn%?\\t%0, #%B1 516790075Sobrien ldr%?b\\t%0, %1 516890075Sobrien str%?b\\t%1, %0" 5169169689Skan [(set_attr "type" "*,*,load1,store1") 517090075Sobrien (set_attr "predicable" "yes")] 517190075Sobrien) 517290075Sobrien 517390075Sobrien(define_insn "*thumb_movqi_insn" 517490075Sobrien [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l") 517590075Sobrien (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))] 517690075Sobrien "TARGET_THUMB 517790075Sobrien && ( register_operand (operands[0], QImode) 517890075Sobrien || register_operand (operands[1], QImode))" 517990075Sobrien "@ 518090075Sobrien add\\t%0, %1, #0 518190075Sobrien ldrb\\t%0, %1 518290075Sobrien strb\\t%1, %0 518390075Sobrien mov\\t%0, %1 518490075Sobrien mov\\t%0, %1 518590075Sobrien mov\\t%0, %1" 518690075Sobrien [(set_attr "length" "2") 5187169689Skan (set_attr "type" "*,load1,store1,*,*,*") 518890075Sobrien (set_attr "pool_range" "*,32,*,*,*,*")] 518990075Sobrien) 519090075Sobrien 519190075Sobrien(define_expand "movsf" 519290075Sobrien [(set (match_operand:SF 0 "general_operand" "") 519390075Sobrien (match_operand:SF 1 "general_operand" ""))] 519490075Sobrien "TARGET_EITHER" 519590075Sobrien " 519690075Sobrien if (TARGET_ARM) 519790075Sobrien { 519890075Sobrien if (GET_CODE (operands[0]) == MEM) 519990075Sobrien operands[1] = force_reg (SFmode, operands[1]); 520090075Sobrien } 520190075Sobrien else /* TARGET_THUMB */ 520290075Sobrien { 520390075Sobrien if (!no_new_pseudos) 520490075Sobrien { 520590075Sobrien if (GET_CODE (operands[0]) != REG) 520690075Sobrien operands[1] = force_reg (SFmode, operands[1]); 520790075Sobrien } 520890075Sobrien } 520990075Sobrien " 521090075Sobrien) 521190075Sobrien 5212169689Skan;; Transform a floating-point move of a constant into a core register into 5213169689Skan;; an SImode operation. 521490075Sobrien(define_split 5215169689Skan [(set (match_operand:SF 0 "arm_general_register_operand" "") 521690075Sobrien (match_operand:SF 1 "immediate_operand" ""))] 521790075Sobrien "TARGET_ARM 521890075Sobrien && reload_completed 521990075Sobrien && GET_CODE (operands[1]) == CONST_DOUBLE" 522090075Sobrien [(set (match_dup 2) (match_dup 3))] 522190075Sobrien " 522290075Sobrien operands[2] = gen_lowpart (SImode, operands[0]); 522390075Sobrien operands[3] = gen_lowpart (SImode, operands[1]); 522490075Sobrien if (operands[2] == 0 || operands[3] == 0) 522590075Sobrien FAIL; 522690075Sobrien " 522790075Sobrien) 522890075Sobrien 522990075Sobrien(define_insn "*arm_movsf_soft_insn" 523090075Sobrien [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") 523190075Sobrien (match_operand:SF 1 "general_operand" "r,mE,r"))] 523290075Sobrien "TARGET_ARM 523390075Sobrien && TARGET_SOFT_FLOAT 523490075Sobrien && (GET_CODE (operands[0]) != MEM 523590075Sobrien || register_operand (operands[1], SFmode))" 523690075Sobrien "@ 523790075Sobrien mov%?\\t%0, %1 523890075Sobrien ldr%?\\t%0, %1\\t%@ float 523990075Sobrien str%?\\t%1, %0\\t%@ float" 524090075Sobrien [(set_attr "length" "4,4,4") 524190075Sobrien (set_attr "predicable" "yes") 5242169689Skan (set_attr "type" "*,load1,store1") 524390075Sobrien (set_attr "pool_range" "*,4096,*") 524490075Sobrien (set_attr "neg_pool_range" "*,4084,*")] 524590075Sobrien) 524690075Sobrien 524790075Sobrien;;; ??? This should have alternatives for constants. 524890075Sobrien(define_insn "*thumb_movsf_insn" 524990075Sobrien [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h") 525090075Sobrien (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))] 525190075Sobrien "TARGET_THUMB 525290075Sobrien && ( register_operand (operands[0], SFmode) 525390075Sobrien || register_operand (operands[1], SFmode))" 525490075Sobrien "@ 525590075Sobrien add\\t%0, %1, #0 525690075Sobrien ldmia\\t%1, {%0} 525790075Sobrien stmia\\t%0, {%1} 525890075Sobrien ldr\\t%0, %1 525990075Sobrien str\\t%1, %0 526090075Sobrien mov\\t%0, %1 526190075Sobrien mov\\t%0, %1" 526290075Sobrien [(set_attr "length" "2") 5263169689Skan (set_attr "type" "*,load1,store1,load1,store1,*,*") 526490075Sobrien (set_attr "pool_range" "*,*,*,1020,*,*,*")] 526590075Sobrien) 526690075Sobrien 526790075Sobrien(define_expand "movdf" 526890075Sobrien [(set (match_operand:DF 0 "general_operand" "") 526990075Sobrien (match_operand:DF 1 "general_operand" ""))] 527090075Sobrien "TARGET_EITHER" 527190075Sobrien " 527290075Sobrien if (TARGET_ARM) 527390075Sobrien { 527490075Sobrien if (GET_CODE (operands[0]) == MEM) 527590075Sobrien operands[1] = force_reg (DFmode, operands[1]); 527690075Sobrien } 527790075Sobrien else /* TARGET_THUMB */ 527890075Sobrien { 527990075Sobrien if (!no_new_pseudos) 528090075Sobrien { 528190075Sobrien if (GET_CODE (operands[0]) != REG) 528290075Sobrien operands[1] = force_reg (DFmode, operands[1]); 528390075Sobrien } 528490075Sobrien } 528590075Sobrien " 528690075Sobrien) 528790075Sobrien 528890075Sobrien;; Reloading a df mode value stored in integer regs to memory can require a 528990075Sobrien;; scratch reg. 529090075Sobrien(define_expand "reload_outdf" 529190075Sobrien [(match_operand:DF 0 "arm_reload_memory_operand" "=o") 529290075Sobrien (match_operand:DF 1 "s_register_operand" "r") 529390075Sobrien (match_operand:SI 2 "s_register_operand" "=&r")] 529490075Sobrien "TARGET_ARM" 529590075Sobrien " 529690075Sobrien { 529790075Sobrien enum rtx_code code = GET_CODE (XEXP (operands[0], 0)); 529890075Sobrien 529990075Sobrien if (code == REG) 530090075Sobrien operands[2] = XEXP (operands[0], 0); 530190075Sobrien else if (code == POST_INC || code == PRE_DEC) 530290075Sobrien { 530390075Sobrien operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); 530490075Sobrien operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0); 530590075Sobrien emit_insn (gen_movdi (operands[0], operands[1])); 530690075Sobrien DONE; 530790075Sobrien } 530890075Sobrien else if (code == PRE_INC) 530990075Sobrien { 531090075Sobrien rtx reg = XEXP (XEXP (operands[0], 0), 0); 531190075Sobrien 531290075Sobrien emit_insn (gen_addsi3 (reg, reg, GEN_INT (8))); 531390075Sobrien operands[2] = reg; 531490075Sobrien } 531590075Sobrien else if (code == POST_DEC) 531690075Sobrien operands[2] = XEXP (XEXP (operands[0], 0), 0); 531790075Sobrien else 531890075Sobrien emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0), 531990075Sobrien XEXP (XEXP (operands[0], 0), 1))); 532090075Sobrien 5321169689Skan emit_insn (gen_rtx_SET (VOIDmode, 5322169689Skan replace_equiv_address (operands[0], operands[2]), 532390075Sobrien operands[1])); 532490075Sobrien 532590075Sobrien if (code == POST_DEC) 532690075Sobrien emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8))); 532790075Sobrien 532890075Sobrien DONE; 532990075Sobrien }" 533090075Sobrien) 533190075Sobrien 533290075Sobrien(define_insn "*movdf_soft_insn" 5333169689Skan [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m") 5334169689Skan (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))] 533590075Sobrien "TARGET_ARM && TARGET_SOFT_FLOAT 5336169689Skan && ( register_operand (operands[0], DFmode) 5337169689Skan || register_operand (operands[1], DFmode))" 5338169689Skan "* 5339169689Skan switch (which_alternative) 5340169689Skan { 5341169689Skan case 0: 5342169689Skan case 1: 5343169689Skan case 2: 5344169689Skan return \"#\"; 5345169689Skan default: 5346169689Skan return output_move_double (operands); 5347169689Skan } 534890075Sobrien " 5349169689Skan [(set_attr "length" "8,12,16,8,8") 5350169689Skan (set_attr "type" "*,*,*,load2,store2") 535196263Sobrien (set_attr "pool_range" "1020") 535296263Sobrien (set_attr "neg_pool_range" "1008")] 535390075Sobrien) 535490075Sobrien 535590075Sobrien;;; ??? This should have alternatives for constants. 535690075Sobrien;;; ??? This was originally identical to the movdi_insn pattern. 535790075Sobrien;;; ??? The 'F' constraint looks funny, but it should always be replaced by 535890075Sobrien;;; thumb_reorg with a memory reference. 535990075Sobrien(define_insn "*thumb_movdf_insn" 536090075Sobrien [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r") 536190075Sobrien (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))] 536290075Sobrien "TARGET_THUMB 536390075Sobrien && ( register_operand (operands[0], DFmode) 536490075Sobrien || register_operand (operands[1], DFmode))" 536590075Sobrien "* 536690075Sobrien switch (which_alternative) 536790075Sobrien { 536890075Sobrien default: 536990075Sobrien case 0: 537090075Sobrien if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 537190075Sobrien return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 537290075Sobrien return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 537390075Sobrien case 1: 537490075Sobrien return \"ldmia\\t%1, {%0, %H0}\"; 537590075Sobrien case 2: 537690075Sobrien return \"stmia\\t%0, {%1, %H1}\"; 537790075Sobrien case 3: 537890075Sobrien return thumb_load_double_from_address (operands); 537990075Sobrien case 4: 5380169689Skan operands[2] = gen_rtx_MEM (SImode, 5381169689Skan plus_constant (XEXP (operands[0], 0), 4)); 538290075Sobrien output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 538390075Sobrien return \"\"; 538490075Sobrien case 5: 538590075Sobrien if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 538690075Sobrien return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 538790075Sobrien return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 538890075Sobrien } 538990075Sobrien " 539090075Sobrien [(set_attr "length" "4,2,2,6,4,4") 5391169689Skan (set_attr "type" "*,load2,store2,load2,store2,*") 539290075Sobrien (set_attr "pool_range" "*,*,*,1020,*,*")] 539390075Sobrien) 539490075Sobrien 5395169689Skan(define_expand "movxf" 5396169689Skan [(set (match_operand:XF 0 "general_operand" "") 5397169689Skan (match_operand:XF 1 "general_operand" ""))] 5398169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA" 5399169689Skan " 5400169689Skan if (GET_CODE (operands[0]) == MEM) 5401169689Skan operands[1] = force_reg (XFmode, operands[1]); 5402169689Skan " 5403169689Skan) 5404169689Skan 5405132718Skan;; Vector Moves 5406132718Skan(define_expand "movv2si" 5407132718Skan [(set (match_operand:V2SI 0 "nonimmediate_operand" "") 5408132718Skan (match_operand:V2SI 1 "general_operand" ""))] 5409132718Skan "TARGET_REALLY_IWMMXT" 5410132718Skan{ 5411132718Skan}) 541290075Sobrien 5413132718Skan(define_expand "movv4hi" 5414132718Skan [(set (match_operand:V4HI 0 "nonimmediate_operand" "") 5415132718Skan (match_operand:V4HI 1 "general_operand" ""))] 5416132718Skan "TARGET_REALLY_IWMMXT" 5417132718Skan{ 5418132718Skan}) 541990075Sobrien 5420132718Skan(define_expand "movv8qi" 5421132718Skan [(set (match_operand:V8QI 0 "nonimmediate_operand" "") 5422132718Skan (match_operand:V8QI 1 "general_operand" ""))] 5423132718Skan "TARGET_REALLY_IWMMXT" 5424132718Skan{ 5425132718Skan}) 542690075Sobrien 542790075Sobrien 542890075Sobrien;; load- and store-multiple insns 542990075Sobrien;; The arm can load/store any set of registers, provided that they are in 543090075Sobrien;; ascending order; but that is beyond GCC so stick with what it knows. 543190075Sobrien 543290075Sobrien(define_expand "load_multiple" 543390075Sobrien [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 543490075Sobrien (match_operand:SI 1 "" "")) 543590075Sobrien (use (match_operand:SI 2 "" ""))])] 543690075Sobrien "TARGET_ARM" 5437161651Skan{ 5438161651Skan HOST_WIDE_INT offset = 0; 5439169689Skan 544090075Sobrien /* Support only fixed point registers. */ 544190075Sobrien if (GET_CODE (operands[2]) != CONST_INT 544290075Sobrien || INTVAL (operands[2]) > 14 544390075Sobrien || INTVAL (operands[2]) < 2 544490075Sobrien || GET_CODE (operands[1]) != MEM 544590075Sobrien || GET_CODE (operands[0]) != REG 544690075Sobrien || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1) 544790075Sobrien || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 544890075Sobrien FAIL; 544990075Sobrien 545090075Sobrien operands[3] 545190075Sobrien = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]), 545290075Sobrien force_reg (SImode, XEXP (operands[1], 0)), 5453161651Skan TRUE, FALSE, operands[1], &offset); 5454161651Skan}) 5455161651Skan 545690075Sobrien;; Load multiple with write-back 545790075Sobrien 545890075Sobrien(define_insn "*ldmsi_postinc4" 545990075Sobrien [(match_parallel 0 "load_multiple_operation" 546090075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 546190075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 546290075Sobrien (const_int 16))) 546390075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 546490075Sobrien (mem:SI (match_dup 2))) 546590075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 546690075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 546790075Sobrien (set (match_operand:SI 5 "arm_hard_register_operand" "") 546890075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 8)))) 546990075Sobrien (set (match_operand:SI 6 "arm_hard_register_operand" "") 547090075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 12))))])] 547190075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 547290075Sobrien "ldm%?ia\\t%1!, {%3, %4, %5, %6}" 5473169689Skan [(set_attr "type" "load4") 547490075Sobrien (set_attr "predicable" "yes")] 547590075Sobrien) 547690075Sobrien 5477169689Skan(define_insn "*ldmsi_postinc4_thumb" 5478169689Skan [(match_parallel 0 "load_multiple_operation" 5479169689Skan [(set (match_operand:SI 1 "s_register_operand" "=l") 5480169689Skan (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5481169689Skan (const_int 16))) 5482169689Skan (set (match_operand:SI 3 "arm_hard_register_operand" "") 5483169689Skan (mem:SI (match_dup 2))) 5484169689Skan (set (match_operand:SI 4 "arm_hard_register_operand" "") 5485169689Skan (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 5486169689Skan (set (match_operand:SI 5 "arm_hard_register_operand" "") 5487169689Skan (mem:SI (plus:SI (match_dup 2) (const_int 8)))) 5488169689Skan (set (match_operand:SI 6 "arm_hard_register_operand" "") 5489169689Skan (mem:SI (plus:SI (match_dup 2) (const_int 12))))])] 5490169689Skan "TARGET_THUMB && XVECLEN (operands[0], 0) == 5" 5491169689Skan "ldmia\\t%1!, {%3, %4, %5, %6}" 5492169689Skan [(set_attr "type" "load4")] 5493169689Skan) 5494169689Skan 549590075Sobrien(define_insn "*ldmsi_postinc3" 549690075Sobrien [(match_parallel 0 "load_multiple_operation" 549790075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 549890075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 549990075Sobrien (const_int 12))) 550090075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 550190075Sobrien (mem:SI (match_dup 2))) 550290075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 550390075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 550490075Sobrien (set (match_operand:SI 5 "arm_hard_register_operand" "") 550590075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 8))))])] 550690075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 550790075Sobrien "ldm%?ia\\t%1!, {%3, %4, %5}" 5508169689Skan [(set_attr "type" "load3") 550990075Sobrien (set_attr "predicable" "yes")] 551090075Sobrien) 551190075Sobrien 551290075Sobrien(define_insn "*ldmsi_postinc2" 551390075Sobrien [(match_parallel 0 "load_multiple_operation" 551490075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 551590075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 551690075Sobrien (const_int 8))) 551790075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 551890075Sobrien (mem:SI (match_dup 2))) 551990075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 552090075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 4))))])] 552190075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 552290075Sobrien "ldm%?ia\\t%1!, {%3, %4}" 5523169689Skan [(set_attr "type" "load2") 552490075Sobrien (set_attr "predicable" "yes")] 552590075Sobrien) 552690075Sobrien 552790075Sobrien;; Ordinary load multiple 552890075Sobrien 552990075Sobrien(define_insn "*ldmsi4" 553090075Sobrien [(match_parallel 0 "load_multiple_operation" 553190075Sobrien [(set (match_operand:SI 2 "arm_hard_register_operand" "") 553290075Sobrien (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 553390075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 553490075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 553590075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 553690075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 8)))) 553790075Sobrien (set (match_operand:SI 5 "arm_hard_register_operand" "") 553890075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] 553990075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 554090075Sobrien "ldm%?ia\\t%1, {%2, %3, %4, %5}" 5541169689Skan [(set_attr "type" "load4") 554290075Sobrien (set_attr "predicable" "yes")] 554390075Sobrien) 554490075Sobrien 554590075Sobrien(define_insn "*ldmsi3" 554690075Sobrien [(match_parallel 0 "load_multiple_operation" 554790075Sobrien [(set (match_operand:SI 2 "arm_hard_register_operand" "") 554890075Sobrien (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 554990075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 555090075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 555190075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 555290075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] 555390075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 555490075Sobrien "ldm%?ia\\t%1, {%2, %3, %4}" 5555169689Skan [(set_attr "type" "load3") 555690075Sobrien (set_attr "predicable" "yes")] 555790075Sobrien) 555890075Sobrien 555990075Sobrien(define_insn "*ldmsi2" 556090075Sobrien [(match_parallel 0 "load_multiple_operation" 556190075Sobrien [(set (match_operand:SI 2 "arm_hard_register_operand" "") 556290075Sobrien (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 556390075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 556490075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] 556590075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 556690075Sobrien "ldm%?ia\\t%1, {%2, %3}" 5567169689Skan [(set_attr "type" "load2") 556890075Sobrien (set_attr "predicable" "yes")] 556990075Sobrien) 557090075Sobrien 557190075Sobrien(define_expand "store_multiple" 557290075Sobrien [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 557390075Sobrien (match_operand:SI 1 "" "")) 557490075Sobrien (use (match_operand:SI 2 "" ""))])] 557590075Sobrien "TARGET_ARM" 5576161651Skan{ 5577161651Skan HOST_WIDE_INT offset = 0; 5578161651Skan 5579132718Skan /* Support only fixed point registers. */ 558090075Sobrien if (GET_CODE (operands[2]) != CONST_INT 558190075Sobrien || INTVAL (operands[2]) > 14 558290075Sobrien || INTVAL (operands[2]) < 2 558390075Sobrien || GET_CODE (operands[1]) != REG 558490075Sobrien || GET_CODE (operands[0]) != MEM 558590075Sobrien || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1) 558690075Sobrien || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 558790075Sobrien FAIL; 558890075Sobrien 558990075Sobrien operands[3] 559090075Sobrien = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]), 559190075Sobrien force_reg (SImode, XEXP (operands[0], 0)), 5592161651Skan TRUE, FALSE, operands[0], &offset); 5593161651Skan}) 559490075Sobrien 559590075Sobrien;; Store multiple with write-back 559690075Sobrien 559790075Sobrien(define_insn "*stmsi_postinc4" 559890075Sobrien [(match_parallel 0 "store_multiple_operation" 559990075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 560090075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 560190075Sobrien (const_int 16))) 560290075Sobrien (set (mem:SI (match_dup 2)) 560390075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 560490075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 560590075Sobrien (match_operand:SI 4 "arm_hard_register_operand" "")) 560690075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 560790075Sobrien (match_operand:SI 5 "arm_hard_register_operand" "")) 560890075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) 560990075Sobrien (match_operand:SI 6 "arm_hard_register_operand" ""))])] 561090075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 561190075Sobrien "stm%?ia\\t%1!, {%3, %4, %5, %6}" 561290075Sobrien [(set_attr "predicable" "yes") 561390075Sobrien (set_attr "type" "store4")] 561490075Sobrien) 561590075Sobrien 5616169689Skan(define_insn "*stmsi_postinc4_thumb" 5617169689Skan [(match_parallel 0 "store_multiple_operation" 5618169689Skan [(set (match_operand:SI 1 "s_register_operand" "=l") 5619169689Skan (plus:SI (match_operand:SI 2 "s_register_operand" "1") 5620169689Skan (const_int 16))) 5621169689Skan (set (mem:SI (match_dup 2)) 5622169689Skan (match_operand:SI 3 "arm_hard_register_operand" "")) 5623169689Skan (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 5624169689Skan (match_operand:SI 4 "arm_hard_register_operand" "")) 5625169689Skan (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 5626169689Skan (match_operand:SI 5 "arm_hard_register_operand" "")) 5627169689Skan (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) 5628169689Skan (match_operand:SI 6 "arm_hard_register_operand" ""))])] 5629169689Skan "TARGET_THUMB && XVECLEN (operands[0], 0) == 5" 5630169689Skan "stmia\\t%1!, {%3, %4, %5, %6}" 5631169689Skan [(set_attr "type" "store4")] 5632169689Skan) 5633169689Skan 563490075Sobrien(define_insn "*stmsi_postinc3" 563590075Sobrien [(match_parallel 0 "store_multiple_operation" 563690075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 563790075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 563890075Sobrien (const_int 12))) 563990075Sobrien (set (mem:SI (match_dup 2)) 564090075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 564190075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 564290075Sobrien (match_operand:SI 4 "arm_hard_register_operand" "")) 564390075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 564490075Sobrien (match_operand:SI 5 "arm_hard_register_operand" ""))])] 564590075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 564690075Sobrien "stm%?ia\\t%1!, {%3, %4, %5}" 564790075Sobrien [(set_attr "predicable" "yes") 564890075Sobrien (set_attr "type" "store3")] 564990075Sobrien) 565090075Sobrien 565190075Sobrien(define_insn "*stmsi_postinc2" 565290075Sobrien [(match_parallel 0 "store_multiple_operation" 565390075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 565490075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 565590075Sobrien (const_int 8))) 565690075Sobrien (set (mem:SI (match_dup 2)) 565790075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 565890075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 565990075Sobrien (match_operand:SI 4 "arm_hard_register_operand" ""))])] 566090075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 566190075Sobrien "stm%?ia\\t%1!, {%3, %4}" 566290075Sobrien [(set_attr "predicable" "yes") 566390075Sobrien (set_attr "type" "store2")] 566490075Sobrien) 566590075Sobrien 566690075Sobrien;; Ordinary store multiple 566790075Sobrien 566890075Sobrien(define_insn "*stmsi4" 566990075Sobrien [(match_parallel 0 "store_multiple_operation" 567090075Sobrien [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 567190075Sobrien (match_operand:SI 2 "arm_hard_register_operand" "")) 567290075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 567390075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 567490075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 567590075Sobrien (match_operand:SI 4 "arm_hard_register_operand" "")) 567690075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) 567790075Sobrien (match_operand:SI 5 "arm_hard_register_operand" ""))])] 567890075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 567990075Sobrien "stm%?ia\\t%1, {%2, %3, %4, %5}" 568090075Sobrien [(set_attr "predicable" "yes") 568190075Sobrien (set_attr "type" "store4")] 568290075Sobrien) 568390075Sobrien 568490075Sobrien(define_insn "*stmsi3" 568590075Sobrien [(match_parallel 0 "store_multiple_operation" 568690075Sobrien [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 568790075Sobrien (match_operand:SI 2 "arm_hard_register_operand" "")) 568890075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 568990075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 569090075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 569190075Sobrien (match_operand:SI 4 "arm_hard_register_operand" ""))])] 569290075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 569390075Sobrien "stm%?ia\\t%1, {%2, %3, %4}" 569490075Sobrien [(set_attr "predicable" "yes") 569590075Sobrien (set_attr "type" "store3")] 569690075Sobrien) 569790075Sobrien 569890075Sobrien(define_insn "*stmsi2" 569990075Sobrien [(match_parallel 0 "store_multiple_operation" 570090075Sobrien [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 570190075Sobrien (match_operand:SI 2 "arm_hard_register_operand" "")) 570290075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 570390075Sobrien (match_operand:SI 3 "arm_hard_register_operand" ""))])] 570490075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 570590075Sobrien "stm%?ia\\t%1, {%2, %3}" 570690075Sobrien [(set_attr "predicable" "yes") 570790075Sobrien (set_attr "type" "store2")] 570890075Sobrien) 570990075Sobrien 571090075Sobrien;; Move a block of memory if it is word aligned and MORE than 2 words long. 571190075Sobrien;; We could let this apply for blocks of less than this, but it clobbers so 571290075Sobrien;; many registers that there is then probably a better way. 571390075Sobrien 5714169689Skan(define_expand "movmemqi" 571590075Sobrien [(match_operand:BLK 0 "general_operand" "") 571690075Sobrien (match_operand:BLK 1 "general_operand" "") 571790075Sobrien (match_operand:SI 2 "const_int_operand" "") 571890075Sobrien (match_operand:SI 3 "const_int_operand" "")] 571990075Sobrien "TARGET_EITHER" 572090075Sobrien " 572190075Sobrien if (TARGET_ARM) 572290075Sobrien { 5723169689Skan if (arm_gen_movmemqi (operands)) 572490075Sobrien DONE; 572590075Sobrien FAIL; 572690075Sobrien } 572790075Sobrien else /* TARGET_THUMB */ 572890075Sobrien { 572990075Sobrien if ( INTVAL (operands[3]) != 4 573090075Sobrien || INTVAL (operands[2]) > 48) 573190075Sobrien FAIL; 573290075Sobrien 5733169689Skan thumb_expand_movmemqi (operands); 573490075Sobrien DONE; 573590075Sobrien } 573690075Sobrien " 573790075Sobrien) 573890075Sobrien 573990075Sobrien;; Thumb block-move insns 574090075Sobrien 574190075Sobrien(define_insn "movmem12b" 574290075Sobrien [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 574390075Sobrien (mem:SI (match_operand:SI 3 "register_operand" "1"))) 574490075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 574590075Sobrien (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 574690075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 574790075Sobrien (mem:SI (plus:SI (match_dup 3) (const_int 8)))) 574890075Sobrien (set (match_operand:SI 0 "register_operand" "=l") 574990075Sobrien (plus:SI (match_dup 2) (const_int 12))) 575090075Sobrien (set (match_operand:SI 1 "register_operand" "=l") 575190075Sobrien (plus:SI (match_dup 3) (const_int 12))) 575290075Sobrien (clobber (match_scratch:SI 4 "=&l")) 575390075Sobrien (clobber (match_scratch:SI 5 "=&l")) 575490075Sobrien (clobber (match_scratch:SI 6 "=&l"))] 575590075Sobrien "TARGET_THUMB" 575690075Sobrien "* return thumb_output_move_mem_multiple (3, operands);" 575790075Sobrien [(set_attr "length" "4") 575890075Sobrien ; This isn't entirely accurate... It loads as well, but in terms of 575990075Sobrien ; scheduling the following insn it is better to consider it as a store 576090075Sobrien (set_attr "type" "store3")] 576190075Sobrien) 576290075Sobrien 576390075Sobrien(define_insn "movmem8b" 576490075Sobrien [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 576590075Sobrien (mem:SI (match_operand:SI 3 "register_operand" "1"))) 576690075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 576790075Sobrien (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 576890075Sobrien (set (match_operand:SI 0 "register_operand" "=l") 576990075Sobrien (plus:SI (match_dup 2) (const_int 8))) 577090075Sobrien (set (match_operand:SI 1 "register_operand" "=l") 577190075Sobrien (plus:SI (match_dup 3) (const_int 8))) 577290075Sobrien (clobber (match_scratch:SI 4 "=&l")) 577390075Sobrien (clobber (match_scratch:SI 5 "=&l"))] 577490075Sobrien "TARGET_THUMB" 577590075Sobrien "* return thumb_output_move_mem_multiple (2, operands);" 577690075Sobrien [(set_attr "length" "4") 577790075Sobrien ; This isn't entirely accurate... It loads as well, but in terms of 577890075Sobrien ; scheduling the following insn it is better to consider it as a store 577990075Sobrien (set_attr "type" "store2")] 578090075Sobrien) 578190075Sobrien 578290075Sobrien 578390075Sobrien 578490075Sobrien;; Compare & branch insns 5785132718Skan;; The range calculations are based as follows: 578690075Sobrien;; For forward branches, the address calculation returns the address of 578790075Sobrien;; the next instruction. This is 2 beyond the branch instruction. 578890075Sobrien;; For backward branches, the address calculation returns the address of 578990075Sobrien;; the first instruction in this pattern (cmp). This is 2 before the branch 579090075Sobrien;; instruction for the shortest sequence, and 4 before the branch instruction 579190075Sobrien;; if we have to jump around an unconditional branch. 579290075Sobrien;; To the basic branch range the PC offset must be added (this is +4). 579390075Sobrien;; So for forward branches we have 579490075Sobrien;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4). 579590075Sobrien;; And for backward branches we have 579690075Sobrien;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4). 579790075Sobrien;; 579890075Sobrien;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048). 579990075Sobrien;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256). 580090075Sobrien 5801132718Skan(define_expand "cbranchsi4" 5802132718Skan [(set (pc) (if_then_else 5803132718Skan (match_operator 0 "arm_comparison_operator" 5804132718Skan [(match_operand:SI 1 "s_register_operand" "") 5805132718Skan (match_operand:SI 2 "nonmemory_operand" "")]) 5806132718Skan (label_ref (match_operand 3 "" "")) 5807132718Skan (pc)))] 580890075Sobrien "TARGET_THUMB" 5809132718Skan " 5810132718Skan if (thumb_cmpneg_operand (operands[2], SImode)) 5811132718Skan { 5812132718Skan emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2], 5813132718Skan operands[3], operands[0])); 5814132718Skan DONE; 5815132718Skan } 5816132718Skan if (!thumb_cmp_operand (operands[2], SImode)) 5817132718Skan operands[2] = force_reg (SImode, operands[2]); 5818132718Skan ") 5819132718Skan 5820132718Skan(define_insn "*cbranchsi4_insn" 5821132718Skan [(set (pc) (if_then_else 5822132718Skan (match_operator 0 "arm_comparison_operator" 5823132718Skan [(match_operand:SI 1 "s_register_operand" "l,*h") 5824132718Skan (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")]) 5825132718Skan (label_ref (match_operand 3 "" "")) 5826132718Skan (pc)))] 5827132718Skan "TARGET_THUMB" 582890075Sobrien "* 582990075Sobrien output_asm_insn (\"cmp\\t%1, %2\", operands); 5830132718Skan 583190075Sobrien switch (get_attr_length (insn)) 583290075Sobrien { 583390075Sobrien case 4: return \"b%d0\\t%l3\"; 583490075Sobrien case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 583590075Sobrien default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 583690075Sobrien } 583790075Sobrien " 583890075Sobrien [(set (attr "far_jump") 583990075Sobrien (if_then_else 584090075Sobrien (eq_attr "length" "8") 584190075Sobrien (const_string "yes") 584290075Sobrien (const_string "no"))) 584390075Sobrien (set (attr "length") 584490075Sobrien (if_then_else 584590075Sobrien (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 584690075Sobrien (le (minus (match_dup 3) (pc)) (const_int 256))) 584790075Sobrien (const_int 4) 584890075Sobrien (if_then_else 584990075Sobrien (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 585090075Sobrien (le (minus (match_dup 3) (pc)) (const_int 2048))) 585190075Sobrien (const_int 6) 585290075Sobrien (const_int 8))))] 585390075Sobrien) 585490075Sobrien 5855132718Skan(define_insn "cbranchsi4_scratch" 5856132718Skan [(set (pc) (if_then_else 5857132718Skan (match_operator 4 "arm_comparison_operator" 5858132718Skan [(match_operand:SI 1 "s_register_operand" "l,0") 5859132718Skan (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")]) 5860132718Skan (label_ref (match_operand 3 "" "")) 5861132718Skan (pc))) 5862132718Skan (clobber (match_scratch:SI 0 "=l,l"))] 5863132718Skan "TARGET_THUMB" 5864132718Skan "* 5865132718Skan output_asm_insn (\"add\\t%0, %1, #%n2\", operands); 5866132718Skan 5867132718Skan switch (get_attr_length (insn)) 5868132718Skan { 5869132718Skan case 4: return \"b%d4\\t%l3\"; 5870132718Skan case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5871132718Skan default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5872132718Skan } 5873132718Skan " 5874132718Skan [(set (attr "far_jump") 5875132718Skan (if_then_else 5876132718Skan (eq_attr "length" "8") 5877132718Skan (const_string "yes") 5878132718Skan (const_string "no"))) 5879132718Skan (set (attr "length") 5880132718Skan (if_then_else 5881132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5882132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 5883132718Skan (const_int 4) 5884132718Skan (if_then_else 5885132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5886132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 5887132718Skan (const_int 6) 5888132718Skan (const_int 8))))] 5889132718Skan) 5890132718Skan(define_insn "*movsi_cbranchsi4" 5891132718Skan [(set (pc) 5892132718Skan (if_then_else 5893132718Skan (match_operator 3 "arm_comparison_operator" 5894132718Skan [(match_operand:SI 1 "s_register_operand" "0,l,l,l") 5895132718Skan (const_int 0)]) 5896132718Skan (label_ref (match_operand 2 "" "")) 5897132718Skan (pc))) 5898132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m") 5899132718Skan (match_dup 1))] 5900132718Skan "TARGET_THUMB" 5901132718Skan "*{ 5902132718Skan if (which_alternative == 0) 5903132718Skan output_asm_insn (\"cmp\t%0, #0\", operands); 5904132718Skan else if (which_alternative == 1) 5905132718Skan output_asm_insn (\"sub\t%0, %1, #0\", operands); 5906132718Skan else 5907132718Skan { 5908132718Skan output_asm_insn (\"cmp\t%1, #0\", operands); 5909132718Skan if (which_alternative == 2) 5910132718Skan output_asm_insn (\"mov\t%0, %1\", operands); 5911132718Skan else 5912132718Skan output_asm_insn (\"str\t%1, %0\", operands); 5913132718Skan } 5914132718Skan switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0)) 5915132718Skan { 5916132718Skan case 4: return \"b%d3\\t%l2\"; 5917132718Skan case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\"; 5918132718Skan default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\"; 5919132718Skan } 5920132718Skan }" 5921132718Skan [(set (attr "far_jump") 5922132718Skan (if_then_else 5923132718Skan (ior (and (gt (symbol_ref ("which_alternative")) 5924132718Skan (const_int 1)) 5925132718Skan (eq_attr "length" "8")) 5926132718Skan (eq_attr "length" "10")) 5927132718Skan (const_string "yes") 5928132718Skan (const_string "no"))) 5929132718Skan (set (attr "length") 5930132718Skan (if_then_else 5931132718Skan (le (symbol_ref ("which_alternative")) 5932132718Skan (const_int 1)) 5933132718Skan (if_then_else 5934132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 5935132718Skan (le (minus (match_dup 2) (pc)) (const_int 256))) 5936132718Skan (const_int 4) 5937132718Skan (if_then_else 5938132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) 5939132718Skan (le (minus (match_dup 2) (pc)) (const_int 2048))) 5940132718Skan (const_int 6) 5941132718Skan (const_int 8))) 5942132718Skan (if_then_else 5943132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -248)) 5944132718Skan (le (minus (match_dup 2) (pc)) (const_int 256))) 5945132718Skan (const_int 6) 5946132718Skan (if_then_else 5947132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -2038)) 5948132718Skan (le (minus (match_dup 2) (pc)) (const_int 2048))) 5949132718Skan (const_int 8) 5950132718Skan (const_int 10)))))] 5951132718Skan) 5952132718Skan 595390075Sobrien(define_insn "*negated_cbranchsi4" 595490075Sobrien [(set (pc) 595590075Sobrien (if_then_else 5956169689Skan (match_operator 0 "equality_operator" 5957132718Skan [(match_operand:SI 1 "s_register_operand" "l") 5958132718Skan (neg:SI (match_operand:SI 2 "s_register_operand" "l"))]) 5959132718Skan (label_ref (match_operand 3 "" "")) 596090075Sobrien (pc)))] 596190075Sobrien "TARGET_THUMB" 596290075Sobrien "* 596390075Sobrien output_asm_insn (\"cmn\\t%1, %2\", operands); 596490075Sobrien switch (get_attr_length (insn)) 596590075Sobrien { 596690075Sobrien case 4: return \"b%d0\\t%l3\"; 596790075Sobrien case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 596890075Sobrien default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 596990075Sobrien } 597090075Sobrien " 597190075Sobrien [(set (attr "far_jump") 597290075Sobrien (if_then_else 597390075Sobrien (eq_attr "length" "8") 597490075Sobrien (const_string "yes") 597590075Sobrien (const_string "no"))) 597690075Sobrien (set (attr "length") 597790075Sobrien (if_then_else 597890075Sobrien (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 597990075Sobrien (le (minus (match_dup 3) (pc)) (const_int 256))) 598090075Sobrien (const_int 4) 598190075Sobrien (if_then_else 598290075Sobrien (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 598390075Sobrien (le (minus (match_dup 3) (pc)) (const_int 2048))) 598490075Sobrien (const_int 6) 598590075Sobrien (const_int 8))))] 598690075Sobrien) 598790075Sobrien 5988132718Skan(define_insn "*tbit_cbranch" 5989132718Skan [(set (pc) 5990132718Skan (if_then_else 5991132718Skan (match_operator 0 "equality_operator" 5992132718Skan [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l") 5993132718Skan (const_int 1) 5994132718Skan (match_operand:SI 2 "const_int_operand" "i")) 5995132718Skan (const_int 0)]) 5996132718Skan (label_ref (match_operand 3 "" "")) 5997132718Skan (pc))) 5998132718Skan (clobber (match_scratch:SI 4 "=l"))] 5999132718Skan "TARGET_THUMB" 6000132718Skan "* 6001132718Skan { 6002132718Skan rtx op[3]; 6003132718Skan op[0] = operands[4]; 6004132718Skan op[1] = operands[1]; 6005132718Skan op[2] = GEN_INT (32 - 1 - INTVAL (operands[2])); 600690075Sobrien 6007132718Skan output_asm_insn (\"lsl\\t%0, %1, %2\", op); 6008132718Skan switch (get_attr_length (insn)) 6009132718Skan { 6010132718Skan case 4: return \"b%d0\\t%l3\"; 6011132718Skan case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6012132718Skan default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6013132718Skan } 6014132718Skan }" 6015132718Skan [(set (attr "far_jump") 6016132718Skan (if_then_else 6017132718Skan (eq_attr "length" "8") 6018132718Skan (const_string "yes") 6019132718Skan (const_string "no"))) 6020132718Skan (set (attr "length") 6021132718Skan (if_then_else 6022132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6023132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 6024132718Skan (const_int 4) 6025132718Skan (if_then_else 6026132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6027132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 6028132718Skan (const_int 6) 6029132718Skan (const_int 8))))] 6030132718Skan) 6031132718Skan 6032169689Skan(define_insn "*tlobits_cbranch" 6033169689Skan [(set (pc) 6034169689Skan (if_then_else 6035169689Skan (match_operator 0 "equality_operator" 6036169689Skan [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l") 6037169689Skan (match_operand:SI 2 "const_int_operand" "i") 6038169689Skan (const_int 0)) 6039169689Skan (const_int 0)]) 6040169689Skan (label_ref (match_operand 3 "" "")) 6041169689Skan (pc))) 6042169689Skan (clobber (match_scratch:SI 4 "=l"))] 6043169689Skan "TARGET_THUMB" 6044169689Skan "* 6045169689Skan { 6046169689Skan rtx op[3]; 6047169689Skan op[0] = operands[4]; 6048169689Skan op[1] = operands[1]; 6049169689Skan op[2] = GEN_INT (32 - INTVAL (operands[2])); 6050169689Skan 6051169689Skan output_asm_insn (\"lsl\\t%0, %1, %2\", op); 6052169689Skan switch (get_attr_length (insn)) 6053169689Skan { 6054169689Skan case 4: return \"b%d0\\t%l3\"; 6055169689Skan case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6056169689Skan default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6057169689Skan } 6058169689Skan }" 6059169689Skan [(set (attr "far_jump") 6060169689Skan (if_then_else 6061169689Skan (eq_attr "length" "8") 6062169689Skan (const_string "yes") 6063169689Skan (const_string "no"))) 6064169689Skan (set (attr "length") 6065169689Skan (if_then_else 6066169689Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6067169689Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 6068169689Skan (const_int 4) 6069169689Skan (if_then_else 6070169689Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6071169689Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 6072169689Skan (const_int 6) 6073169689Skan (const_int 8))))] 6074169689Skan) 6075169689Skan 6076132718Skan(define_insn "*tstsi3_cbranch" 6077132718Skan [(set (pc) 6078132718Skan (if_then_else 6079132718Skan (match_operator 3 "equality_operator" 6080132718Skan [(and:SI (match_operand:SI 0 "s_register_operand" "%l") 6081132718Skan (match_operand:SI 1 "s_register_operand" "l")) 6082132718Skan (const_int 0)]) 6083132718Skan (label_ref (match_operand 2 "" "")) 6084132718Skan (pc)))] 6085132718Skan "TARGET_THUMB" 6086132718Skan "* 6087132718Skan { 6088132718Skan output_asm_insn (\"tst\\t%0, %1\", operands); 6089132718Skan switch (get_attr_length (insn)) 6090132718Skan { 6091132718Skan case 4: return \"b%d3\\t%l2\"; 6092132718Skan case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\"; 6093132718Skan default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\"; 6094132718Skan } 6095132718Skan }" 6096132718Skan [(set (attr "far_jump") 6097132718Skan (if_then_else 6098132718Skan (eq_attr "length" "8") 6099132718Skan (const_string "yes") 6100132718Skan (const_string "no"))) 6101132718Skan (set (attr "length") 6102132718Skan (if_then_else 6103132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 6104132718Skan (le (minus (match_dup 2) (pc)) (const_int 256))) 6105132718Skan (const_int 4) 6106132718Skan (if_then_else 6107132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) 6108132718Skan (le (minus (match_dup 2) (pc)) (const_int 2048))) 6109132718Skan (const_int 6) 6110132718Skan (const_int 8))))] 6111132718Skan) 6112132718Skan 6113132718Skan(define_insn "*andsi3_cbranch" 6114132718Skan [(set (pc) 6115132718Skan (if_then_else 6116132718Skan (match_operator 5 "equality_operator" 6117132718Skan [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 6118132718Skan (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 6119132718Skan (const_int 0)]) 6120132718Skan (label_ref (match_operand 4 "" "")) 6121132718Skan (pc))) 6122132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6123132718Skan (and:SI (match_dup 2) (match_dup 3))) 6124132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6125132718Skan "TARGET_THUMB" 6126132718Skan "* 6127132718Skan { 6128132718Skan if (which_alternative == 0) 6129132718Skan output_asm_insn (\"and\\t%0, %3\", operands); 6130132718Skan else if (which_alternative == 1) 6131132718Skan { 6132132718Skan output_asm_insn (\"and\\t%1, %3\", operands); 6133132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6134132718Skan } 6135132718Skan else 6136132718Skan { 6137132718Skan output_asm_insn (\"and\\t%1, %3\", operands); 6138132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6139132718Skan } 6140132718Skan 6141132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 6142132718Skan { 6143132718Skan case 4: return \"b%d5\\t%l4\"; 6144132718Skan case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6145132718Skan default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6146132718Skan } 6147132718Skan }" 6148132718Skan [(set (attr "far_jump") 6149132718Skan (if_then_else 6150132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 6151132718Skan (const_int 0)) 6152132718Skan (eq_attr "length" "8")) 6153132718Skan (eq_attr "length" "10")) 6154132718Skan (const_string "yes") 6155132718Skan (const_string "no"))) 6156132718Skan (set (attr "length") 6157132718Skan (if_then_else 6158132718Skan (eq (symbol_ref ("which_alternative")) 6159132718Skan (const_int 0)) 6160132718Skan (if_then_else 6161132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6162132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6163132718Skan (const_int 4) 6164132718Skan (if_then_else 6165132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6166132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6167132718Skan (const_int 6) 6168132718Skan (const_int 8))) 6169132718Skan (if_then_else 6170132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6171132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6172132718Skan (const_int 6) 6173132718Skan (if_then_else 6174132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6175132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6176132718Skan (const_int 8) 6177132718Skan (const_int 10)))))] 6178132718Skan) 6179132718Skan 6180132718Skan(define_insn "*orrsi3_cbranch_scratch" 6181132718Skan [(set (pc) 6182132718Skan (if_then_else 6183132718Skan (match_operator 4 "equality_operator" 6184132718Skan [(ior:SI (match_operand:SI 1 "s_register_operand" "%0") 6185132718Skan (match_operand:SI 2 "s_register_operand" "l")) 6186132718Skan (const_int 0)]) 6187132718Skan (label_ref (match_operand 3 "" "")) 6188132718Skan (pc))) 6189132718Skan (clobber (match_scratch:SI 0 "=l"))] 6190132718Skan "TARGET_THUMB" 6191132718Skan "* 6192132718Skan { 6193132718Skan output_asm_insn (\"orr\\t%0, %2\", operands); 6194132718Skan switch (get_attr_length (insn)) 6195132718Skan { 6196132718Skan case 4: return \"b%d4\\t%l3\"; 6197132718Skan case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6198132718Skan default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6199132718Skan } 6200132718Skan }" 6201132718Skan [(set (attr "far_jump") 6202132718Skan (if_then_else 6203132718Skan (eq_attr "length" "8") 6204132718Skan (const_string "yes") 6205132718Skan (const_string "no"))) 6206132718Skan (set (attr "length") 6207132718Skan (if_then_else 6208132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6209132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 6210132718Skan (const_int 4) 6211132718Skan (if_then_else 6212132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6213132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 6214132718Skan (const_int 6) 6215132718Skan (const_int 8))))] 6216132718Skan) 6217132718Skan 6218132718Skan(define_insn "*orrsi3_cbranch" 6219132718Skan [(set (pc) 6220132718Skan (if_then_else 6221132718Skan (match_operator 5 "equality_operator" 6222132718Skan [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 6223132718Skan (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 6224132718Skan (const_int 0)]) 6225132718Skan (label_ref (match_operand 4 "" "")) 6226132718Skan (pc))) 6227132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6228132718Skan (ior:SI (match_dup 2) (match_dup 3))) 6229132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6230132718Skan "TARGET_THUMB" 6231132718Skan "* 6232132718Skan { 6233132718Skan if (which_alternative == 0) 6234132718Skan output_asm_insn (\"orr\\t%0, %3\", operands); 6235132718Skan else if (which_alternative == 1) 6236132718Skan { 6237132718Skan output_asm_insn (\"orr\\t%1, %3\", operands); 6238132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6239132718Skan } 6240132718Skan else 6241132718Skan { 6242132718Skan output_asm_insn (\"orr\\t%1, %3\", operands); 6243132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6244132718Skan } 6245132718Skan 6246132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 6247132718Skan { 6248132718Skan case 4: return \"b%d5\\t%l4\"; 6249132718Skan case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6250132718Skan default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6251132718Skan } 6252132718Skan }" 6253132718Skan [(set (attr "far_jump") 6254132718Skan (if_then_else 6255132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 6256132718Skan (const_int 0)) 6257132718Skan (eq_attr "length" "8")) 6258132718Skan (eq_attr "length" "10")) 6259132718Skan (const_string "yes") 6260132718Skan (const_string "no"))) 6261132718Skan (set (attr "length") 6262132718Skan (if_then_else 6263132718Skan (eq (symbol_ref ("which_alternative")) 6264132718Skan (const_int 0)) 6265132718Skan (if_then_else 6266132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6267132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6268132718Skan (const_int 4) 6269132718Skan (if_then_else 6270132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6271132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6272132718Skan (const_int 6) 6273132718Skan (const_int 8))) 6274132718Skan (if_then_else 6275132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6276132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6277132718Skan (const_int 6) 6278132718Skan (if_then_else 6279132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6280132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6281132718Skan (const_int 8) 6282132718Skan (const_int 10)))))] 6283132718Skan) 6284132718Skan 6285132718Skan(define_insn "*xorsi3_cbranch_scratch" 6286132718Skan [(set (pc) 6287132718Skan (if_then_else 6288132718Skan (match_operator 4 "equality_operator" 6289132718Skan [(xor:SI (match_operand:SI 1 "s_register_operand" "%0") 6290132718Skan (match_operand:SI 2 "s_register_operand" "l")) 6291132718Skan (const_int 0)]) 6292132718Skan (label_ref (match_operand 3 "" "")) 6293132718Skan (pc))) 6294132718Skan (clobber (match_scratch:SI 0 "=l"))] 6295132718Skan "TARGET_THUMB" 6296132718Skan "* 6297132718Skan { 6298132718Skan output_asm_insn (\"eor\\t%0, %2\", operands); 6299132718Skan switch (get_attr_length (insn)) 6300132718Skan { 6301132718Skan case 4: return \"b%d4\\t%l3\"; 6302132718Skan case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6303132718Skan default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6304132718Skan } 6305132718Skan }" 6306132718Skan [(set (attr "far_jump") 6307132718Skan (if_then_else 6308132718Skan (eq_attr "length" "8") 6309132718Skan (const_string "yes") 6310132718Skan (const_string "no"))) 6311132718Skan (set (attr "length") 6312132718Skan (if_then_else 6313132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6314132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 6315132718Skan (const_int 4) 6316132718Skan (if_then_else 6317132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6318132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 6319132718Skan (const_int 6) 6320132718Skan (const_int 8))))] 6321132718Skan) 6322132718Skan 6323132718Skan(define_insn "*xorsi3_cbranch" 6324132718Skan [(set (pc) 6325132718Skan (if_then_else 6326132718Skan (match_operator 5 "equality_operator" 6327132718Skan [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 6328132718Skan (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 6329132718Skan (const_int 0)]) 6330132718Skan (label_ref (match_operand 4 "" "")) 6331132718Skan (pc))) 6332132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6333132718Skan (xor:SI (match_dup 2) (match_dup 3))) 6334132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6335132718Skan "TARGET_THUMB" 6336132718Skan "* 6337132718Skan { 6338132718Skan if (which_alternative == 0) 6339132718Skan output_asm_insn (\"eor\\t%0, %3\", operands); 6340132718Skan else if (which_alternative == 1) 6341132718Skan { 6342132718Skan output_asm_insn (\"eor\\t%1, %3\", operands); 6343132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6344132718Skan } 6345132718Skan else 6346132718Skan { 6347132718Skan output_asm_insn (\"eor\\t%1, %3\", operands); 6348132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6349132718Skan } 6350132718Skan 6351132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 6352132718Skan { 6353132718Skan case 4: return \"b%d5\\t%l4\"; 6354132718Skan case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6355132718Skan default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6356132718Skan } 6357132718Skan }" 6358132718Skan [(set (attr "far_jump") 6359132718Skan (if_then_else 6360132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 6361132718Skan (const_int 0)) 6362132718Skan (eq_attr "length" "8")) 6363132718Skan (eq_attr "length" "10")) 6364132718Skan (const_string "yes") 6365132718Skan (const_string "no"))) 6366132718Skan (set (attr "length") 6367132718Skan (if_then_else 6368132718Skan (eq (symbol_ref ("which_alternative")) 6369132718Skan (const_int 0)) 6370132718Skan (if_then_else 6371132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6372132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6373132718Skan (const_int 4) 6374132718Skan (if_then_else 6375132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6376132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6377132718Skan (const_int 6) 6378132718Skan (const_int 8))) 6379132718Skan (if_then_else 6380132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6381132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6382132718Skan (const_int 6) 6383132718Skan (if_then_else 6384132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6385132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6386132718Skan (const_int 8) 6387132718Skan (const_int 10)))))] 6388132718Skan) 6389132718Skan 6390132718Skan(define_insn "*bicsi3_cbranch_scratch" 6391132718Skan [(set (pc) 6392132718Skan (if_then_else 6393132718Skan (match_operator 4 "equality_operator" 6394132718Skan [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l")) 6395132718Skan (match_operand:SI 1 "s_register_operand" "0")) 6396132718Skan (const_int 0)]) 6397132718Skan (label_ref (match_operand 3 "" "")) 6398132718Skan (pc))) 6399132718Skan (clobber (match_scratch:SI 0 "=l"))] 6400132718Skan "TARGET_THUMB" 6401132718Skan "* 6402132718Skan { 6403132718Skan output_asm_insn (\"bic\\t%0, %2\", operands); 6404132718Skan switch (get_attr_length (insn)) 6405132718Skan { 6406132718Skan case 4: return \"b%d4\\t%l3\"; 6407132718Skan case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6408132718Skan default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6409132718Skan } 6410132718Skan }" 6411132718Skan [(set (attr "far_jump") 6412132718Skan (if_then_else 6413132718Skan (eq_attr "length" "8") 6414132718Skan (const_string "yes") 6415132718Skan (const_string "no"))) 6416132718Skan (set (attr "length") 6417132718Skan (if_then_else 6418132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6419132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 6420132718Skan (const_int 4) 6421132718Skan (if_then_else 6422132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6423132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 6424132718Skan (const_int 6) 6425132718Skan (const_int 8))))] 6426132718Skan) 6427132718Skan 6428132718Skan(define_insn "*bicsi3_cbranch" 6429132718Skan [(set (pc) 6430132718Skan (if_then_else 6431132718Skan (match_operator 5 "equality_operator" 6432146895Skan [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l")) 6433146895Skan (match_operand:SI 2 "s_register_operand" "0,1,1,1,1")) 6434132718Skan (const_int 0)]) 6435132718Skan (label_ref (match_operand 4 "" "")) 6436132718Skan (pc))) 6437146895Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m") 6438132718Skan (and:SI (not:SI (match_dup 3)) (match_dup 2))) 6439146895Skan (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))] 6440132718Skan "TARGET_THUMB" 6441132718Skan "* 6442132718Skan { 6443132718Skan if (which_alternative == 0) 6444132718Skan output_asm_insn (\"bic\\t%0, %3\", operands); 6445146895Skan else if (which_alternative <= 2) 6446132718Skan { 6447132718Skan output_asm_insn (\"bic\\t%1, %3\", operands); 6448146895Skan /* It's ok if OP0 is a lo-reg, even though the mov will set the 6449146895Skan conditions again, since we're only testing for equality. */ 6450132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6451132718Skan } 6452132718Skan else 6453132718Skan { 6454132718Skan output_asm_insn (\"bic\\t%1, %3\", operands); 6455132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6456132718Skan } 6457132718Skan 6458132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 6459132718Skan { 6460132718Skan case 4: return \"b%d5\\t%l4\"; 6461132718Skan case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6462132718Skan default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6463132718Skan } 6464132718Skan }" 6465132718Skan [(set (attr "far_jump") 6466132718Skan (if_then_else 6467132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 6468132718Skan (const_int 0)) 6469132718Skan (eq_attr "length" "8")) 6470132718Skan (eq_attr "length" "10")) 6471132718Skan (const_string "yes") 6472132718Skan (const_string "no"))) 6473132718Skan (set (attr "length") 6474132718Skan (if_then_else 6475132718Skan (eq (symbol_ref ("which_alternative")) 6476132718Skan (const_int 0)) 6477132718Skan (if_then_else 6478132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6479132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6480132718Skan (const_int 4) 6481132718Skan (if_then_else 6482132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6483132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6484132718Skan (const_int 6) 6485132718Skan (const_int 8))) 6486132718Skan (if_then_else 6487132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6488132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6489132718Skan (const_int 6) 6490132718Skan (if_then_else 6491132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6492132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6493132718Skan (const_int 8) 6494132718Skan (const_int 10)))))] 6495132718Skan) 6496132718Skan 6497132718Skan(define_insn "*cbranchne_decr1" 6498132718Skan [(set (pc) 6499132718Skan (if_then_else (match_operator 3 "equality_operator" 6500132718Skan [(match_operand:SI 2 "s_register_operand" "l,l,1,l") 6501132718Skan (const_int 0)]) 6502132718Skan (label_ref (match_operand 4 "" "")) 6503132718Skan (pc))) 6504132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6505132718Skan (plus:SI (match_dup 2) (const_int -1))) 6506132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6507132718Skan "TARGET_THUMB" 6508132718Skan "* 6509132718Skan { 6510132718Skan rtx cond[2]; 6511132718Skan cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE 6512132718Skan ? GEU : LTU), 6513132718Skan VOIDmode, operands[2], const1_rtx); 6514132718Skan cond[1] = operands[4]; 6515132718Skan 6516132718Skan if (which_alternative == 0) 6517132718Skan output_asm_insn (\"sub\\t%0, %2, #1\", operands); 6518132718Skan else if (which_alternative == 1) 6519132718Skan { 6520132718Skan /* We must provide an alternative for a hi reg because reload 6521132718Skan cannot handle output reloads on a jump instruction, but we 6522132718Skan can't subtract into that. Fortunately a mov from lo to hi 6523132718Skan does not clobber the condition codes. */ 6524132718Skan output_asm_insn (\"sub\\t%1, %2, #1\", operands); 6525132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6526132718Skan } 6527132718Skan else 6528132718Skan { 6529132718Skan /* Similarly, but the target is memory. */ 6530132718Skan output_asm_insn (\"sub\\t%1, %2, #1\", operands); 6531132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6532132718Skan } 6533132718Skan 6534132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 6535132718Skan { 6536132718Skan case 4: 6537132718Skan output_asm_insn (\"b%d0\\t%l1\", cond); 6538132718Skan return \"\"; 6539132718Skan case 6: 6540132718Skan output_asm_insn (\"b%D0\\t.LCB%=\", cond); 6541132718Skan return \"b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6542132718Skan default: 6543132718Skan output_asm_insn (\"b%D0\\t.LCB%=\", cond); 6544132718Skan return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6545132718Skan } 6546132718Skan } 6547132718Skan " 6548132718Skan [(set (attr "far_jump") 6549132718Skan (if_then_else 6550132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 6551132718Skan (const_int 0)) 6552132718Skan (eq_attr "length" "8")) 6553132718Skan (eq_attr "length" "10")) 6554132718Skan (const_string "yes") 6555132718Skan (const_string "no"))) 6556132718Skan (set_attr_alternative "length" 6557132718Skan [ 6558132718Skan ;; Alternative 0 6559132718Skan (if_then_else 6560132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6561132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6562132718Skan (const_int 4) 6563132718Skan (if_then_else 6564132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6565132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6566132718Skan (const_int 6) 6567132718Skan (const_int 8))) 6568132718Skan ;; Alternative 1 6569132718Skan (if_then_else 6570132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6571132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6572132718Skan (const_int 6) 6573132718Skan (if_then_else 6574132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6575132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6576132718Skan (const_int 8) 6577132718Skan (const_int 10))) 6578132718Skan ;; Alternative 2 6579132718Skan (if_then_else 6580132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6581132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6582132718Skan (const_int 6) 6583132718Skan (if_then_else 6584132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6585132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6586132718Skan (const_int 8) 6587132718Skan (const_int 10))) 6588132718Skan ;; Alternative 3 6589132718Skan (if_then_else 6590132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6591132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6592132718Skan (const_int 6) 6593132718Skan (if_then_else 6594132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6595132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6596132718Skan (const_int 8) 6597132718Skan (const_int 10)))])] 6598132718Skan) 6599132718Skan 6600132718Skan(define_insn "*addsi3_cbranch" 6601132718Skan [(set (pc) 6602132718Skan (if_then_else 6603132718Skan (match_operator 4 "comparison_operator" 6604132718Skan [(plus:SI 6605132718Skan (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1") 6606132718Skan (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ")) 6607132718Skan (const_int 0)]) 6608132718Skan (label_ref (match_operand 5 "" "")) 6609132718Skan (pc))) 6610132718Skan (set 6611132718Skan (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m") 6612132718Skan (plus:SI (match_dup 2) (match_dup 3))) 6613132718Skan (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))] 6614132718Skan "TARGET_THUMB 6615132718Skan && (GET_CODE (operands[4]) == EQ 6616132718Skan || GET_CODE (operands[4]) == NE 6617132718Skan || GET_CODE (operands[4]) == GE 6618132718Skan || GET_CODE (operands[4]) == LT)" 6619132718Skan "* 6620132718Skan { 6621132718Skan rtx cond[3]; 6622132718Skan 6623132718Skan 6624132718Skan cond[0] = (which_alternative < 3) ? operands[0] : operands[1]; 6625132718Skan cond[1] = operands[2]; 6626132718Skan cond[2] = operands[3]; 6627132718Skan 6628132718Skan if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0) 6629132718Skan output_asm_insn (\"sub\\t%0, %1, #%n2\", cond); 6630132718Skan else 6631132718Skan output_asm_insn (\"add\\t%0, %1, %2\", cond); 6632132718Skan 6633132718Skan if (which_alternative >= 3 6634132718Skan && which_alternative < 4) 6635132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6636132718Skan else if (which_alternative >= 4) 6637132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6638132718Skan 6639132718Skan switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0)) 6640132718Skan { 6641132718Skan case 4: 6642132718Skan return \"b%d4\\t%l5\"; 6643132718Skan case 6: 6644132718Skan return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 6645132718Skan default: 6646132718Skan return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 6647132718Skan } 6648132718Skan } 6649132718Skan " 6650132718Skan [(set (attr "far_jump") 6651132718Skan (if_then_else 6652132718Skan (ior (and (lt (symbol_ref ("which_alternative")) 6653132718Skan (const_int 3)) 6654132718Skan (eq_attr "length" "8")) 6655132718Skan (eq_attr "length" "10")) 6656132718Skan (const_string "yes") 6657132718Skan (const_string "no"))) 6658132718Skan (set (attr "length") 6659132718Skan (if_then_else 6660132718Skan (lt (symbol_ref ("which_alternative")) 6661132718Skan (const_int 3)) 6662132718Skan (if_then_else 6663132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 6664132718Skan (le (minus (match_dup 5) (pc)) (const_int 256))) 6665132718Skan (const_int 4) 6666132718Skan (if_then_else 6667132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 6668132718Skan (le (minus (match_dup 5) (pc)) (const_int 2048))) 6669132718Skan (const_int 6) 6670132718Skan (const_int 8))) 6671132718Skan (if_then_else 6672132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 6673132718Skan (le (minus (match_dup 5) (pc)) (const_int 256))) 6674132718Skan (const_int 6) 6675132718Skan (if_then_else 6676132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 6677132718Skan (le (minus (match_dup 5) (pc)) (const_int 2048))) 6678132718Skan (const_int 8) 6679132718Skan (const_int 10)))))] 6680132718Skan) 6681132718Skan 6682132718Skan(define_insn "*addsi3_cbranch_scratch" 6683132718Skan [(set (pc) 6684132718Skan (if_then_else 6685132718Skan (match_operator 3 "comparison_operator" 6686132718Skan [(plus:SI 6687132718Skan (match_operand:SI 1 "s_register_operand" "%l,l,l,0") 6688169689Skan (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ")) 6689132718Skan (const_int 0)]) 6690132718Skan (label_ref (match_operand 4 "" "")) 6691132718Skan (pc))) 6692132718Skan (clobber (match_scratch:SI 0 "=X,X,l,l"))] 6693132718Skan "TARGET_THUMB 6694132718Skan && (GET_CODE (operands[3]) == EQ 6695132718Skan || GET_CODE (operands[3]) == NE 6696132718Skan || GET_CODE (operands[3]) == GE 6697132718Skan || GET_CODE (operands[3]) == LT)" 6698132718Skan "* 6699132718Skan { 6700132718Skan switch (which_alternative) 6701132718Skan { 6702132718Skan case 0: 6703132718Skan output_asm_insn (\"cmp\t%1, #%n2\", operands); 6704132718Skan break; 6705132718Skan case 1: 6706132718Skan output_asm_insn (\"cmn\t%1, %2\", operands); 6707132718Skan break; 6708146895Skan case 2: 6709169689Skan if (INTVAL (operands[2]) < 0) 6710169689Skan output_asm_insn (\"sub\t%0, %1, %2\", operands); 6711169689Skan else 6712169689Skan output_asm_insn (\"add\t%0, %1, %2\", operands); 6713132718Skan break; 6714146895Skan case 3: 6715169689Skan if (INTVAL (operands[2]) < 0) 6716169689Skan output_asm_insn (\"sub\t%0, %0, %2\", operands); 6717169689Skan else 6718169689Skan output_asm_insn (\"add\t%0, %0, %2\", operands); 6719132718Skan break; 6720132718Skan } 6721132718Skan 6722132718Skan switch (get_attr_length (insn)) 6723132718Skan { 6724132718Skan case 4: 6725132718Skan return \"b%d3\\t%l4\"; 6726132718Skan case 6: 6727132718Skan return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6728132718Skan default: 6729132718Skan return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6730132718Skan } 6731132718Skan } 6732132718Skan " 6733132718Skan [(set (attr "far_jump") 6734132718Skan (if_then_else 6735132718Skan (eq_attr "length" "8") 6736132718Skan (const_string "yes") 6737132718Skan (const_string "no"))) 6738132718Skan (set (attr "length") 6739132718Skan (if_then_else 6740132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6741132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6742132718Skan (const_int 4) 6743132718Skan (if_then_else 6744132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6745132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6746132718Skan (const_int 6) 6747132718Skan (const_int 8))))] 6748132718Skan) 6749132718Skan 6750132718Skan(define_insn "*subsi3_cbranch" 6751132718Skan [(set (pc) 6752132718Skan (if_then_else 6753132718Skan (match_operator 4 "comparison_operator" 6754132718Skan [(minus:SI 6755132718Skan (match_operand:SI 2 "s_register_operand" "l,l,1,l") 6756132718Skan (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 6757132718Skan (const_int 0)]) 6758132718Skan (label_ref (match_operand 5 "" "")) 6759132718Skan (pc))) 6760132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6761132718Skan (minus:SI (match_dup 2) (match_dup 3))) 6762132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6763132718Skan "TARGET_THUMB 6764132718Skan && (GET_CODE (operands[4]) == EQ 6765132718Skan || GET_CODE (operands[4]) == NE 6766132718Skan || GET_CODE (operands[4]) == GE 6767132718Skan || GET_CODE (operands[4]) == LT)" 6768132718Skan "* 6769132718Skan { 6770132718Skan if (which_alternative == 0) 6771132718Skan output_asm_insn (\"sub\\t%0, %2, %3\", operands); 6772132718Skan else if (which_alternative == 1) 6773132718Skan { 6774132718Skan /* We must provide an alternative for a hi reg because reload 6775132718Skan cannot handle output reloads on a jump instruction, but we 6776132718Skan can't subtract into that. Fortunately a mov from lo to hi 6777132718Skan does not clobber the condition codes. */ 6778132718Skan output_asm_insn (\"sub\\t%1, %2, %3\", operands); 6779132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6780132718Skan } 6781132718Skan else 6782132718Skan { 6783132718Skan /* Similarly, but the target is memory. */ 6784132718Skan output_asm_insn (\"sub\\t%1, %2, %3\", operands); 6785132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6786132718Skan } 6787132718Skan 6788132718Skan switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0)) 6789132718Skan { 6790132718Skan case 4: 6791132718Skan return \"b%d4\\t%l5\"; 6792132718Skan case 6: 6793132718Skan return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 6794132718Skan default: 6795132718Skan return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 6796132718Skan } 6797132718Skan } 6798132718Skan " 6799132718Skan [(set (attr "far_jump") 6800132718Skan (if_then_else 6801132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 6802132718Skan (const_int 0)) 6803132718Skan (eq_attr "length" "8")) 6804132718Skan (eq_attr "length" "10")) 6805132718Skan (const_string "yes") 6806132718Skan (const_string "no"))) 6807132718Skan (set (attr "length") 6808132718Skan (if_then_else 6809132718Skan (eq (symbol_ref ("which_alternative")) 6810132718Skan (const_int 0)) 6811132718Skan (if_then_else 6812132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 6813132718Skan (le (minus (match_dup 5) (pc)) (const_int 256))) 6814132718Skan (const_int 4) 6815132718Skan (if_then_else 6816132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 6817132718Skan (le (minus (match_dup 5) (pc)) (const_int 2048))) 6818132718Skan (const_int 6) 6819132718Skan (const_int 8))) 6820132718Skan (if_then_else 6821132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 6822132718Skan (le (minus (match_dup 5) (pc)) (const_int 256))) 6823132718Skan (const_int 6) 6824132718Skan (if_then_else 6825132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 6826132718Skan (le (minus (match_dup 5) (pc)) (const_int 2048))) 6827132718Skan (const_int 8) 6828132718Skan (const_int 10)))))] 6829132718Skan) 6830132718Skan 6831132718Skan(define_insn "*subsi3_cbranch_scratch" 6832132718Skan [(set (pc) 6833132718Skan (if_then_else 6834132718Skan (match_operator 0 "arm_comparison_operator" 6835132718Skan [(minus:SI (match_operand:SI 1 "register_operand" "l") 6836132718Skan (match_operand:SI 2 "nonmemory_operand" "l")) 6837132718Skan (const_int 0)]) 6838132718Skan (label_ref (match_operand 3 "" "")) 6839132718Skan (pc)))] 6840132718Skan "TARGET_THUMB 6841132718Skan && (GET_CODE (operands[0]) == EQ 6842132718Skan || GET_CODE (operands[0]) == NE 6843132718Skan || GET_CODE (operands[0]) == GE 6844132718Skan || GET_CODE (operands[0]) == LT)" 6845132718Skan "* 6846132718Skan output_asm_insn (\"cmp\\t%1, %2\", operands); 6847132718Skan switch (get_attr_length (insn)) 6848132718Skan { 6849132718Skan case 4: return \"b%d0\\t%l3\"; 6850132718Skan case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6851132718Skan default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6852132718Skan } 6853132718Skan " 6854132718Skan [(set (attr "far_jump") 6855132718Skan (if_then_else 6856132718Skan (eq_attr "length" "8") 6857132718Skan (const_string "yes") 6858132718Skan (const_string "no"))) 6859132718Skan (set (attr "length") 6860132718Skan (if_then_else 6861132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6862132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 6863132718Skan (const_int 4) 6864132718Skan (if_then_else 6865132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6866132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 6867132718Skan (const_int 6) 6868132718Skan (const_int 8))))] 6869132718Skan) 6870132718Skan 687190075Sobrien;; Comparison and test insns 687290075Sobrien 687390075Sobrien(define_expand "cmpsi" 687490075Sobrien [(match_operand:SI 0 "s_register_operand" "") 687590075Sobrien (match_operand:SI 1 "arm_add_operand" "")] 687690075Sobrien "TARGET_ARM" 687790075Sobrien "{ 687890075Sobrien arm_compare_op0 = operands[0]; 687990075Sobrien arm_compare_op1 = operands[1]; 688090075Sobrien DONE; 688190075Sobrien }" 688290075Sobrien) 688390075Sobrien 688490075Sobrien(define_expand "cmpsf" 688590075Sobrien [(match_operand:SF 0 "s_register_operand" "") 6886169689Skan (match_operand:SF 1 "arm_float_compare_operand" "")] 6887169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 688890075Sobrien " 688990075Sobrien arm_compare_op0 = operands[0]; 689090075Sobrien arm_compare_op1 = operands[1]; 689190075Sobrien DONE; 689290075Sobrien " 689390075Sobrien) 689490075Sobrien 689590075Sobrien(define_expand "cmpdf" 689690075Sobrien [(match_operand:DF 0 "s_register_operand" "") 6897169689Skan (match_operand:DF 1 "arm_float_compare_operand" "")] 6898169689Skan "TARGET_ARM && TARGET_HARD_FLOAT" 689990075Sobrien " 690090075Sobrien arm_compare_op0 = operands[0]; 690190075Sobrien arm_compare_op1 = operands[1]; 690290075Sobrien DONE; 690390075Sobrien " 690490075Sobrien) 690590075Sobrien 690690075Sobrien(define_insn "*arm_cmpsi_insn" 690790075Sobrien [(set (reg:CC CC_REGNUM) 690890075Sobrien (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") 690990075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L")))] 691090075Sobrien "TARGET_ARM" 691190075Sobrien "@ 691290075Sobrien cmp%?\\t%0, %1 691390075Sobrien cmn%?\\t%0, #%n1" 691490075Sobrien [(set_attr "conds" "set")] 691590075Sobrien) 691690075Sobrien 691790075Sobrien(define_insn "*cmpsi_shiftsi" 691890075Sobrien [(set (reg:CC CC_REGNUM) 691990075Sobrien (compare:CC (match_operand:SI 0 "s_register_operand" "r") 692090075Sobrien (match_operator:SI 3 "shift_operator" 692190075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 692290075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 692390075Sobrien "TARGET_ARM" 692490075Sobrien "cmp%?\\t%0, %1%S3" 692590075Sobrien [(set_attr "conds" "set") 692690075Sobrien (set_attr "shift" "1") 6927169689Skan (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 6928169689Skan (const_string "alu_shift") 6929169689Skan (const_string "alu_shift_reg")))] 693090075Sobrien) 693190075Sobrien 693290075Sobrien(define_insn "*cmpsi_shiftsi_swp" 693390075Sobrien [(set (reg:CC_SWP CC_REGNUM) 693490075Sobrien (compare:CC_SWP (match_operator:SI 3 "shift_operator" 693590075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 693690075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rM")]) 693790075Sobrien (match_operand:SI 0 "s_register_operand" "r")))] 693890075Sobrien "TARGET_ARM" 693990075Sobrien "cmp%?\\t%0, %1%S3" 694090075Sobrien [(set_attr "conds" "set") 694190075Sobrien (set_attr "shift" "1") 6942169689Skan (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 6943169689Skan (const_string "alu_shift") 6944169689Skan (const_string "alu_shift_reg")))] 694590075Sobrien) 694690075Sobrien 6947169689Skan(define_insn "*cmpsi_negshiftsi_si" 6948169689Skan [(set (reg:CC_Z CC_REGNUM) 6949169689Skan (compare:CC_Z 6950169689Skan (neg:SI (match_operator:SI 1 "shift_operator" 6951169689Skan [(match_operand:SI 2 "s_register_operand" "r") 6952169689Skan (match_operand:SI 3 "reg_or_int_operand" "rM")])) 6953169689Skan (match_operand:SI 0 "s_register_operand" "r")))] 695490075Sobrien "TARGET_ARM" 6955169689Skan "cmn%?\\t%0, %2%S1" 695690075Sobrien [(set_attr "conds" "set") 6957169689Skan (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "") 6958169689Skan (const_string "alu_shift") 6959169689Skan (const_string "alu_shift_reg")))] 696090075Sobrien) 696190075Sobrien 6962132718Skan;; Cirrus SF compare instruction 6963132718Skan(define_insn "*cirrus_cmpsf" 696490075Sobrien [(set (reg:CCFP CC_REGNUM) 6965132718Skan (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v") 6966132718Skan (match_operand:SF 1 "cirrus_fp_register" "v")))] 6967169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" 6968132718Skan "cfcmps%?\\tr15, %V0, %V1" 6969132718Skan [(set_attr "type" "mav_farith") 6970132718Skan (set_attr "cirrus" "compare")] 697190075Sobrien) 697290075Sobrien 6973132718Skan;; Cirrus DF compare instruction 6974132718Skan(define_insn "*cirrus_cmpdf" 697590075Sobrien [(set (reg:CCFP CC_REGNUM) 6976132718Skan (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v") 6977132718Skan (match_operand:DF 1 "cirrus_fp_register" "v")))] 6978169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" 6979132718Skan "cfcmpd%?\\tr15, %V0, %V1" 6980132718Skan [(set_attr "type" "mav_farith") 6981132718Skan (set_attr "cirrus" "compare")] 698290075Sobrien) 698390075Sobrien 6984132718Skan;; Cirrus DI compare instruction 6985132718Skan(define_expand "cmpdi" 6986132718Skan [(match_operand:DI 0 "cirrus_fp_register" "") 6987132718Skan (match_operand:DI 1 "cirrus_fp_register" "")] 6988169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" 6989132718Skan "{ 6990132718Skan arm_compare_op0 = operands[0]; 6991132718Skan arm_compare_op1 = operands[1]; 6992132718Skan DONE; 6993132718Skan }") 699490075Sobrien 6995132718Skan(define_insn "*cirrus_cmpdi" 6996132718Skan [(set (reg:CC CC_REGNUM) 6997132718Skan (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v") 6998132718Skan (match_operand:DI 1 "cirrus_fp_register" "v")))] 6999169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" 7000132718Skan "cfcmp64%?\\tr15, %V0, %V1" 7001132718Skan [(set_attr "type" "mav_farith") 7002132718Skan (set_attr "cirrus" "compare")] 700390075Sobrien) 700490075Sobrien 700590075Sobrien; This insn allows redundant compares to be removed by cse, nothing should 700690075Sobrien; ever appear in the output file since (set (reg x) (reg x)) is a no-op that 700790075Sobrien; is deleted later on. The match_dup will match the mode here, so that 700890075Sobrien; mode changes of the condition codes aren't lost by this even though we don't 700990075Sobrien; specify what they are. 701090075Sobrien 701190075Sobrien(define_insn "*deleted_compare" 701290075Sobrien [(set (match_operand 0 "cc_register" "") (match_dup 0))] 701390075Sobrien "TARGET_ARM" 701490075Sobrien "\\t%@ deleted compare" 701590075Sobrien [(set_attr "conds" "set") 701690075Sobrien (set_attr "length" "0")] 701790075Sobrien) 701890075Sobrien 701990075Sobrien 702090075Sobrien;; Conditional branch insns 702190075Sobrien 702290075Sobrien(define_expand "beq" 702390075Sobrien [(set (pc) 702490075Sobrien (if_then_else (eq (match_dup 1) (const_int 0)) 702590075Sobrien (label_ref (match_operand 0 "" "")) 702690075Sobrien (pc)))] 702790075Sobrien "TARGET_ARM" 702890075Sobrien "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 702990075Sobrien) 703090075Sobrien 703190075Sobrien(define_expand "bne" 703290075Sobrien [(set (pc) 703390075Sobrien (if_then_else (ne (match_dup 1) (const_int 0)) 703490075Sobrien (label_ref (match_operand 0 "" "")) 703590075Sobrien (pc)))] 703690075Sobrien "TARGET_ARM" 703790075Sobrien "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 703890075Sobrien) 703990075Sobrien 704090075Sobrien(define_expand "bgt" 704190075Sobrien [(set (pc) 704290075Sobrien (if_then_else (gt (match_dup 1) (const_int 0)) 704390075Sobrien (label_ref (match_operand 0 "" "")) 704490075Sobrien (pc)))] 704590075Sobrien "TARGET_ARM" 704690075Sobrien "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 704790075Sobrien) 704890075Sobrien 704990075Sobrien(define_expand "ble" 705090075Sobrien [(set (pc) 705190075Sobrien (if_then_else (le (match_dup 1) (const_int 0)) 705290075Sobrien (label_ref (match_operand 0 "" "")) 705390075Sobrien (pc)))] 705490075Sobrien "TARGET_ARM" 705590075Sobrien "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 705690075Sobrien) 705790075Sobrien 705890075Sobrien(define_expand "bge" 705990075Sobrien [(set (pc) 706090075Sobrien (if_then_else (ge (match_dup 1) (const_int 0)) 706190075Sobrien (label_ref (match_operand 0 "" "")) 706290075Sobrien (pc)))] 706390075Sobrien "TARGET_ARM" 706490075Sobrien "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 706590075Sobrien) 706690075Sobrien 706790075Sobrien(define_expand "blt" 706890075Sobrien [(set (pc) 706990075Sobrien (if_then_else (lt (match_dup 1) (const_int 0)) 707090075Sobrien (label_ref (match_operand 0 "" "")) 707190075Sobrien (pc)))] 707290075Sobrien "TARGET_ARM" 707390075Sobrien "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 707490075Sobrien) 707590075Sobrien 707690075Sobrien(define_expand "bgtu" 707790075Sobrien [(set (pc) 707890075Sobrien (if_then_else (gtu (match_dup 1) (const_int 0)) 707990075Sobrien (label_ref (match_operand 0 "" "")) 708090075Sobrien (pc)))] 708190075Sobrien "TARGET_ARM" 708290075Sobrien "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 708390075Sobrien) 708490075Sobrien 708590075Sobrien(define_expand "bleu" 708690075Sobrien [(set (pc) 708790075Sobrien (if_then_else (leu (match_dup 1) (const_int 0)) 708890075Sobrien (label_ref (match_operand 0 "" "")) 708990075Sobrien (pc)))] 709090075Sobrien "TARGET_ARM" 709190075Sobrien "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 709290075Sobrien) 709390075Sobrien 709490075Sobrien(define_expand "bgeu" 709590075Sobrien [(set (pc) 709690075Sobrien (if_then_else (geu (match_dup 1) (const_int 0)) 709790075Sobrien (label_ref (match_operand 0 "" "")) 709890075Sobrien (pc)))] 709990075Sobrien "TARGET_ARM" 710090075Sobrien "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 710190075Sobrien) 710290075Sobrien 710390075Sobrien(define_expand "bltu" 710490075Sobrien [(set (pc) 710590075Sobrien (if_then_else (ltu (match_dup 1) (const_int 0)) 710690075Sobrien (label_ref (match_operand 0 "" "")) 710790075Sobrien (pc)))] 710890075Sobrien "TARGET_ARM" 710990075Sobrien "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 711090075Sobrien) 711190075Sobrien 711290075Sobrien(define_expand "bunordered" 711390075Sobrien [(set (pc) 711490075Sobrien (if_then_else (unordered (match_dup 1) (const_int 0)) 711590075Sobrien (label_ref (match_operand 0 "" "")) 711690075Sobrien (pc)))] 7117169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 711890075Sobrien "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 711990075Sobrien arm_compare_op1);" 712090075Sobrien) 712190075Sobrien 712290075Sobrien(define_expand "bordered" 712390075Sobrien [(set (pc) 712490075Sobrien (if_then_else (ordered (match_dup 1) (const_int 0)) 712590075Sobrien (label_ref (match_operand 0 "" "")) 712690075Sobrien (pc)))] 7127169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 712890075Sobrien "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 712990075Sobrien arm_compare_op1);" 713090075Sobrien) 713190075Sobrien 713290075Sobrien(define_expand "bungt" 713390075Sobrien [(set (pc) 713490075Sobrien (if_then_else (ungt (match_dup 1) (const_int 0)) 713590075Sobrien (label_ref (match_operand 0 "" "")) 713690075Sobrien (pc)))] 7137169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 713890075Sobrien "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" 713990075Sobrien) 714090075Sobrien 714190075Sobrien(define_expand "bunlt" 714290075Sobrien [(set (pc) 714390075Sobrien (if_then_else (unlt (match_dup 1) (const_int 0)) 714490075Sobrien (label_ref (match_operand 0 "" "")) 714590075Sobrien (pc)))] 7146169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 714790075Sobrien "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" 714890075Sobrien) 714990075Sobrien 715090075Sobrien(define_expand "bunge" 715190075Sobrien [(set (pc) 715290075Sobrien (if_then_else (unge (match_dup 1) (const_int 0)) 715390075Sobrien (label_ref (match_operand 0 "" "")) 715490075Sobrien (pc)))] 7155169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 715690075Sobrien "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" 715790075Sobrien) 715890075Sobrien 715990075Sobrien(define_expand "bunle" 716090075Sobrien [(set (pc) 716190075Sobrien (if_then_else (unle (match_dup 1) (const_int 0)) 716290075Sobrien (label_ref (match_operand 0 "" "")) 716390075Sobrien (pc)))] 7164169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 716590075Sobrien "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" 716690075Sobrien) 716790075Sobrien 716890075Sobrien;; The following two patterns need two branch instructions, since there is 716990075Sobrien;; no single instruction that will handle all cases. 717090075Sobrien(define_expand "buneq" 717190075Sobrien [(set (pc) 717290075Sobrien (if_then_else (uneq (match_dup 1) (const_int 0)) 717390075Sobrien (label_ref (match_operand 0 "" "")) 717490075Sobrien (pc)))] 7175169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 717690075Sobrien "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" 717790075Sobrien) 717890075Sobrien 717990075Sobrien(define_expand "bltgt" 718090075Sobrien [(set (pc) 718190075Sobrien (if_then_else (ltgt (match_dup 1) (const_int 0)) 718290075Sobrien (label_ref (match_operand 0 "" "")) 718390075Sobrien (pc)))] 7184169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 718590075Sobrien "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" 718690075Sobrien) 718790075Sobrien 718890075Sobrien;; 718990075Sobrien;; Patterns to match conditional branch insns. 719090075Sobrien;; 719190075Sobrien 719290075Sobrien; Special pattern to match UNEQ. 719390075Sobrien(define_insn "*arm_buneq" 719490075Sobrien [(set (pc) 719590075Sobrien (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 719690075Sobrien (label_ref (match_operand 0 "" "")) 719790075Sobrien (pc)))] 7198169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 719990075Sobrien "* 7200169689Skan gcc_assert (!arm_ccfsm_state); 720190075Sobrien 7202117395Skan return \"bvs\\t%l0\;beq\\t%l0\"; 720390075Sobrien " 720490075Sobrien [(set_attr "conds" "jump_clob") 720590075Sobrien (set_attr "length" "8")] 720690075Sobrien) 720790075Sobrien 720890075Sobrien; Special pattern to match LTGT. 720990075Sobrien(define_insn "*arm_bltgt" 721090075Sobrien [(set (pc) 721190075Sobrien (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 721290075Sobrien (label_ref (match_operand 0 "" "")) 721390075Sobrien (pc)))] 7214169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 721590075Sobrien "* 7216169689Skan gcc_assert (!arm_ccfsm_state); 721790075Sobrien 7218117395Skan return \"bmi\\t%l0\;bgt\\t%l0\"; 721990075Sobrien " 722090075Sobrien [(set_attr "conds" "jump_clob") 722190075Sobrien (set_attr "length" "8")] 722290075Sobrien) 722390075Sobrien 722490075Sobrien(define_insn "*arm_cond_branch" 722590075Sobrien [(set (pc) 722690075Sobrien (if_then_else (match_operator 1 "arm_comparison_operator" 722790075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)]) 722890075Sobrien (label_ref (match_operand 0 "" "")) 722990075Sobrien (pc)))] 723090075Sobrien "TARGET_ARM" 723190075Sobrien "* 723290075Sobrien if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 723390075Sobrien { 723490075Sobrien arm_ccfsm_state += 2; 723590075Sobrien return \"\"; 723690075Sobrien } 723790075Sobrien return \"b%d1\\t%l0\"; 723890075Sobrien " 7239169689Skan [(set_attr "conds" "use") 7240169689Skan (set_attr "type" "branch")] 724190075Sobrien) 724290075Sobrien 724390075Sobrien; Special pattern to match reversed UNEQ. 724490075Sobrien(define_insn "*arm_buneq_reversed" 724590075Sobrien [(set (pc) 724690075Sobrien (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 724790075Sobrien (pc) 724890075Sobrien (label_ref (match_operand 0 "" ""))))] 7249169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 725090075Sobrien "* 7251169689Skan gcc_assert (!arm_ccfsm_state); 725290075Sobrien 7253117395Skan return \"bmi\\t%l0\;bgt\\t%l0\"; 725490075Sobrien " 725590075Sobrien [(set_attr "conds" "jump_clob") 725690075Sobrien (set_attr "length" "8")] 725790075Sobrien) 725890075Sobrien 725990075Sobrien; Special pattern to match reversed LTGT. 726090075Sobrien(define_insn "*arm_bltgt_reversed" 726190075Sobrien [(set (pc) 726290075Sobrien (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 726390075Sobrien (pc) 726490075Sobrien (label_ref (match_operand 0 "" ""))))] 7265169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 726690075Sobrien "* 7267169689Skan gcc_assert (!arm_ccfsm_state); 726890075Sobrien 7269117395Skan return \"bvs\\t%l0\;beq\\t%l0\"; 727090075Sobrien " 727190075Sobrien [(set_attr "conds" "jump_clob") 727290075Sobrien (set_attr "length" "8")] 727390075Sobrien) 727490075Sobrien 727590075Sobrien(define_insn "*arm_cond_branch_reversed" 727690075Sobrien [(set (pc) 727790075Sobrien (if_then_else (match_operator 1 "arm_comparison_operator" 727890075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)]) 727990075Sobrien (pc) 728090075Sobrien (label_ref (match_operand 0 "" ""))))] 728190075Sobrien "TARGET_ARM" 728290075Sobrien "* 728390075Sobrien if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 728490075Sobrien { 728590075Sobrien arm_ccfsm_state += 2; 728690075Sobrien return \"\"; 728790075Sobrien } 728890075Sobrien return \"b%D1\\t%l0\"; 728990075Sobrien " 7290169689Skan [(set_attr "conds" "use") 7291169689Skan (set_attr "type" "branch")] 729290075Sobrien) 729390075Sobrien 729490075Sobrien 729590075Sobrien 729690075Sobrien; scc insns 729790075Sobrien 729890075Sobrien(define_expand "seq" 7299132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 730090075Sobrien (eq:SI (match_dup 1) (const_int 0)))] 730190075Sobrien "TARGET_ARM" 730290075Sobrien "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 730390075Sobrien) 730490075Sobrien 730590075Sobrien(define_expand "sne" 7306132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 730790075Sobrien (ne:SI (match_dup 1) (const_int 0)))] 730890075Sobrien "TARGET_ARM" 730990075Sobrien "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 731090075Sobrien) 731190075Sobrien 731290075Sobrien(define_expand "sgt" 7313132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 731490075Sobrien (gt:SI (match_dup 1) (const_int 0)))] 731590075Sobrien "TARGET_ARM" 731690075Sobrien "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 731790075Sobrien) 731890075Sobrien 731990075Sobrien(define_expand "sle" 7320132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 732190075Sobrien (le:SI (match_dup 1) (const_int 0)))] 732290075Sobrien "TARGET_ARM" 732390075Sobrien "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 732490075Sobrien) 732590075Sobrien 732690075Sobrien(define_expand "sge" 7327132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 732890075Sobrien (ge:SI (match_dup 1) (const_int 0)))] 732990075Sobrien "TARGET_ARM" 733090075Sobrien "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 733190075Sobrien) 733290075Sobrien 733390075Sobrien(define_expand "slt" 7334132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 733590075Sobrien (lt:SI (match_dup 1) (const_int 0)))] 733690075Sobrien "TARGET_ARM" 733790075Sobrien "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 733890075Sobrien) 733990075Sobrien 734090075Sobrien(define_expand "sgtu" 7341132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 734290075Sobrien (gtu:SI (match_dup 1) (const_int 0)))] 734390075Sobrien "TARGET_ARM" 734490075Sobrien "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 734590075Sobrien) 734690075Sobrien 734790075Sobrien(define_expand "sleu" 7348132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 734990075Sobrien (leu:SI (match_dup 1) (const_int 0)))] 735090075Sobrien "TARGET_ARM" 735190075Sobrien "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 735290075Sobrien) 735390075Sobrien 735490075Sobrien(define_expand "sgeu" 7355132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 735690075Sobrien (geu:SI (match_dup 1) (const_int 0)))] 735790075Sobrien "TARGET_ARM" 735890075Sobrien "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 735990075Sobrien) 736090075Sobrien 736190075Sobrien(define_expand "sltu" 7362132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 736390075Sobrien (ltu:SI (match_dup 1) (const_int 0)))] 736490075Sobrien "TARGET_ARM" 736590075Sobrien "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 736690075Sobrien) 736790075Sobrien 736890075Sobrien(define_expand "sunordered" 7369132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 737090075Sobrien (unordered:SI (match_dup 1) (const_int 0)))] 7371169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 737290075Sobrien "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 737390075Sobrien arm_compare_op1);" 737490075Sobrien) 737590075Sobrien 737690075Sobrien(define_expand "sordered" 7377132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 737890075Sobrien (ordered:SI (match_dup 1) (const_int 0)))] 7379169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 738090075Sobrien "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 738190075Sobrien arm_compare_op1);" 738290075Sobrien) 738390075Sobrien 738490075Sobrien(define_expand "sungt" 7385132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 738690075Sobrien (ungt:SI (match_dup 1) (const_int 0)))] 7387169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 738890075Sobrien "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, 738990075Sobrien arm_compare_op1);" 739090075Sobrien) 739190075Sobrien 739290075Sobrien(define_expand "sunge" 7393132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 739490075Sobrien (unge:SI (match_dup 1) (const_int 0)))] 7395169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 739690075Sobrien "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, 739790075Sobrien arm_compare_op1);" 739890075Sobrien) 739990075Sobrien 740090075Sobrien(define_expand "sunlt" 7401132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 740290075Sobrien (unlt:SI (match_dup 1) (const_int 0)))] 7403169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 740490075Sobrien "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, 740590075Sobrien arm_compare_op1);" 740690075Sobrien) 740790075Sobrien 740890075Sobrien(define_expand "sunle" 7409132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 741090075Sobrien (unle:SI (match_dup 1) (const_int 0)))] 7411169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 741290075Sobrien "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, 741390075Sobrien arm_compare_op1);" 741490075Sobrien) 741590075Sobrien 741690075Sobrien;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with 741790075Sobrien;;; simple ARM instructions. 741890075Sobrien; 741990075Sobrien; (define_expand "suneq" 7420132718Skan; [(set (match_operand:SI 0 "s_register_operand" "") 742190075Sobrien; (uneq:SI (match_dup 1) (const_int 0)))] 7422169689Skan; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 7423169689Skan; "gcc_unreachable ();" 742490075Sobrien; ) 742590075Sobrien; 742690075Sobrien; (define_expand "sltgt" 7427132718Skan; [(set (match_operand:SI 0 "s_register_operand" "") 742890075Sobrien; (ltgt:SI (match_dup 1) (const_int 0)))] 7429169689Skan; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 7430169689Skan; "gcc_unreachable ();" 743190075Sobrien; ) 743290075Sobrien 743390075Sobrien(define_insn "*mov_scc" 743490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 743590075Sobrien (match_operator:SI 1 "arm_comparison_operator" 743690075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)]))] 743790075Sobrien "TARGET_ARM" 743890075Sobrien "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 743990075Sobrien [(set_attr "conds" "use") 744090075Sobrien (set_attr "length" "8")] 744190075Sobrien) 744290075Sobrien 744390075Sobrien(define_insn "*mov_negscc" 744490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 744590075Sobrien (neg:SI (match_operator:SI 1 "arm_comparison_operator" 744690075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)])))] 744790075Sobrien "TARGET_ARM" 744890075Sobrien "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 744990075Sobrien [(set_attr "conds" "use") 745090075Sobrien (set_attr "length" "8")] 745190075Sobrien) 745290075Sobrien 745390075Sobrien(define_insn "*mov_notscc" 745490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 745590075Sobrien (not:SI (match_operator:SI 1 "arm_comparison_operator" 745690075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)])))] 745790075Sobrien "TARGET_ARM" 745890075Sobrien "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" 745990075Sobrien [(set_attr "conds" "use") 746090075Sobrien (set_attr "length" "8")] 746190075Sobrien) 746290075Sobrien 746390075Sobrien 746490075Sobrien;; Conditional move insns 746590075Sobrien 746690075Sobrien(define_expand "movsicc" 746790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 746890075Sobrien (if_then_else:SI (match_operand 1 "arm_comparison_operator" "") 746990075Sobrien (match_operand:SI 2 "arm_not_operand" "") 747090075Sobrien (match_operand:SI 3 "arm_not_operand" "")))] 747190075Sobrien "TARGET_ARM" 747290075Sobrien " 747390075Sobrien { 747490075Sobrien enum rtx_code code = GET_CODE (operands[1]); 7475117395Skan rtx ccreg; 747690075Sobrien 7477117395Skan if (code == UNEQ || code == LTGT) 7478117395Skan FAIL; 7479117395Skan 7480117395Skan ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7481169689Skan operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); 748290075Sobrien }" 748390075Sobrien) 748490075Sobrien 748590075Sobrien(define_expand "movsfcc" 748690075Sobrien [(set (match_operand:SF 0 "s_register_operand" "") 748790075Sobrien (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") 748890075Sobrien (match_operand:SF 2 "s_register_operand" "") 748990075Sobrien (match_operand:SF 3 "nonmemory_operand" "")))] 749090075Sobrien "TARGET_ARM" 749190075Sobrien " 749290075Sobrien { 749390075Sobrien enum rtx_code code = GET_CODE (operands[1]); 749490075Sobrien rtx ccreg; 749590075Sobrien 7496117395Skan if (code == UNEQ || code == LTGT) 7497117395Skan FAIL; 7498117395Skan 749990075Sobrien /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 7500169689Skan Otherwise, ensure it is a valid FP add operand */ 7501169689Skan if ((!(TARGET_HARD_FLOAT && TARGET_FPA)) 7502169689Skan || (!arm_float_add_operand (operands[3], SFmode))) 750390075Sobrien operands[3] = force_reg (SFmode, operands[3]); 750490075Sobrien 750590075Sobrien ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7506169689Skan operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); 750790075Sobrien }" 750890075Sobrien) 750990075Sobrien 751090075Sobrien(define_expand "movdfcc" 751190075Sobrien [(set (match_operand:DF 0 "s_register_operand" "") 751290075Sobrien (if_then_else:DF (match_operand 1 "arm_comparison_operator" "") 751390075Sobrien (match_operand:DF 2 "s_register_operand" "") 7514169689Skan (match_operand:DF 3 "arm_float_add_operand" "")))] 7515169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" 751690075Sobrien " 751790075Sobrien { 751890075Sobrien enum rtx_code code = GET_CODE (operands[1]); 7519117395Skan rtx ccreg; 752090075Sobrien 7521117395Skan if (code == UNEQ || code == LTGT) 7522117395Skan FAIL; 7523117395Skan 7524117395Skan ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7525169689Skan operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); 752690075Sobrien }" 752790075Sobrien) 752890075Sobrien 752990075Sobrien(define_insn "*movsicc_insn" 753090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") 753190075Sobrien (if_then_else:SI 753290075Sobrien (match_operator 3 "arm_comparison_operator" 753390075Sobrien [(match_operand 4 "cc_register" "") (const_int 0)]) 753490075Sobrien (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") 753590075Sobrien (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] 753690075Sobrien "TARGET_ARM" 753790075Sobrien "@ 753890075Sobrien mov%D3\\t%0, %2 753990075Sobrien mvn%D3\\t%0, #%B2 754090075Sobrien mov%d3\\t%0, %1 754190075Sobrien mvn%d3\\t%0, #%B1 754290075Sobrien mov%d3\\t%0, %1\;mov%D3\\t%0, %2 754390075Sobrien mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 754490075Sobrien mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 754590075Sobrien mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" 754690075Sobrien [(set_attr "length" "4,4,4,4,8,8,8,8") 754790075Sobrien (set_attr "conds" "use")] 754890075Sobrien) 754990075Sobrien 755090075Sobrien(define_insn "*movsfcc_soft_insn" 755190075Sobrien [(set (match_operand:SF 0 "s_register_operand" "=r,r") 755290075Sobrien (if_then_else:SF (match_operator 3 "arm_comparison_operator" 755390075Sobrien [(match_operand 4 "cc_register" "") (const_int 0)]) 755490075Sobrien (match_operand:SF 1 "s_register_operand" "0,r") 755590075Sobrien (match_operand:SF 2 "s_register_operand" "r,0")))] 755690075Sobrien "TARGET_ARM && TARGET_SOFT_FLOAT" 755790075Sobrien "@ 755890075Sobrien mov%D3\\t%0, %2 755990075Sobrien mov%d3\\t%0, %1" 756090075Sobrien [(set_attr "conds" "use")] 756190075Sobrien) 756290075Sobrien 756390075Sobrien 756490075Sobrien;; Jump and linkage insns 756590075Sobrien 756690075Sobrien(define_expand "jump" 756790075Sobrien [(set (pc) 756890075Sobrien (label_ref (match_operand 0 "" "")))] 756990075Sobrien "TARGET_EITHER" 757090075Sobrien "" 757190075Sobrien) 757290075Sobrien 757390075Sobrien(define_insn "*arm_jump" 757490075Sobrien [(set (pc) 757590075Sobrien (label_ref (match_operand 0 "" "")))] 757690075Sobrien "TARGET_ARM" 757790075Sobrien "* 757890075Sobrien { 757990075Sobrien if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 758090075Sobrien { 758190075Sobrien arm_ccfsm_state += 2; 758290075Sobrien return \"\"; 758390075Sobrien } 758490075Sobrien return \"b%?\\t%l0\"; 758590075Sobrien } 758690075Sobrien " 758790075Sobrien [(set_attr "predicable" "yes")] 758890075Sobrien) 758990075Sobrien 759090075Sobrien(define_insn "*thumb_jump" 759190075Sobrien [(set (pc) 759290075Sobrien (label_ref (match_operand 0 "" "")))] 759390075Sobrien "TARGET_THUMB" 759490075Sobrien "* 759590075Sobrien if (get_attr_length (insn) == 2) 759690075Sobrien return \"b\\t%l0\"; 759790075Sobrien return \"bl\\t%l0\\t%@ far jump\"; 759890075Sobrien " 759990075Sobrien [(set (attr "far_jump") 760090075Sobrien (if_then_else 760190075Sobrien (eq_attr "length" "4") 760290075Sobrien (const_string "yes") 760390075Sobrien (const_string "no"))) 760490075Sobrien (set (attr "length") 760590075Sobrien (if_then_else 7606146895Skan (and (ge (minus (match_dup 0) (pc)) (const_int -2044)) 7607146895Skan (le (minus (match_dup 0) (pc)) (const_int 2048))) 760890075Sobrien (const_int 2) 760990075Sobrien (const_int 4)))] 761090075Sobrien) 761190075Sobrien 761290075Sobrien(define_expand "call" 761390075Sobrien [(parallel [(call (match_operand 0 "memory_operand" "") 761490075Sobrien (match_operand 1 "general_operand" "")) 761590075Sobrien (use (match_operand 2 "" "")) 761690075Sobrien (clobber (reg:SI LR_REGNUM))])] 761790075Sobrien "TARGET_EITHER" 761890075Sobrien " 761990075Sobrien { 762090075Sobrien rtx callee; 762190075Sobrien 762290075Sobrien /* In an untyped call, we can get NULL for operand 2. */ 762390075Sobrien if (operands[2] == NULL_RTX) 762490075Sobrien operands[2] = const0_rtx; 762590075Sobrien 762690075Sobrien /* This is to decide if we should generate indirect calls by loading the 762790075Sobrien 32 bit address of the callee into a register before performing the 762890075Sobrien branch and link. operand[2] encodes the long_call/short_call 762990075Sobrien attribute of the function being called. This attribute is set whenever 763090075Sobrien __attribute__((long_call/short_call)) or #pragma long_call/no_long_call 763190075Sobrien is used, and the short_call attribute can also be set if function is 763290075Sobrien declared as static or if it has already been defined in the current 763390075Sobrien compilation unit. See arm.c and arm.h for info about this. The third 763490075Sobrien parameter to arm_is_longcall_p is used to tell it which pattern 763590075Sobrien invoked it. */ 763690075Sobrien callee = XEXP (operands[0], 0); 763790075Sobrien 7638169689Skan if ((GET_CODE (callee) == SYMBOL_REF 7639169689Skan && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0)) 7640169689Skan || (GET_CODE (callee) != SYMBOL_REF 7641169689Skan && GET_CODE (callee) != REG)) 764290075Sobrien XEXP (operands[0], 0) = force_reg (Pmode, callee); 764390075Sobrien }" 764490075Sobrien) 764590075Sobrien 7646169689Skan(define_insn "*call_reg_armv5" 764790075Sobrien [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 764890075Sobrien (match_operand 1 "" "")) 764990075Sobrien (use (match_operand 2 "" "")) 765090075Sobrien (clobber (reg:SI LR_REGNUM))] 7651169689Skan "TARGET_ARM && arm_arch5" 7652169689Skan "blx%?\\t%0" 7653169689Skan [(set_attr "type" "call")] 7654169689Skan) 7655169689Skan 7656169689Skan(define_insn "*call_reg_arm" 7657169689Skan [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 7658169689Skan (match_operand 1 "" "")) 7659169689Skan (use (match_operand 2 "" "")) 7660169689Skan (clobber (reg:SI LR_REGNUM))] 7661169689Skan "TARGET_ARM && !arm_arch5" 766290075Sobrien "* 766390075Sobrien return output_call (operands); 766490075Sobrien " 766590075Sobrien ;; length is worst case, normally it is only two 766690075Sobrien [(set_attr "length" "12") 766790075Sobrien (set_attr "type" "call")] 766890075Sobrien) 766990075Sobrien 767090075Sobrien(define_insn "*call_mem" 7671169689Skan [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m")) 767290075Sobrien (match_operand 1 "" "")) 767390075Sobrien (use (match_operand 2 "" "")) 767490075Sobrien (clobber (reg:SI LR_REGNUM))] 767590075Sobrien "TARGET_ARM" 767690075Sobrien "* 767790075Sobrien return output_call_mem (operands); 767890075Sobrien " 767990075Sobrien [(set_attr "length" "12") 768090075Sobrien (set_attr "type" "call")] 768190075Sobrien) 768290075Sobrien 7683169689Skan(define_insn "*call_reg_thumb_v5" 768490075Sobrien [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 768590075Sobrien (match_operand 1 "" "")) 768690075Sobrien (use (match_operand 2 "" "")) 768790075Sobrien (clobber (reg:SI LR_REGNUM))] 7688169689Skan "TARGET_THUMB && arm_arch5" 7689169689Skan "blx\\t%0" 7690169689Skan [(set_attr "length" "2") 7691169689Skan (set_attr "type" "call")] 769290075Sobrien) 769390075Sobrien 7694169689Skan(define_insn "*call_reg_thumb" 7695169689Skan [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 7696169689Skan (match_operand 1 "" "")) 7697169689Skan (use (match_operand 2 "" "")) 769890075Sobrien (clobber (reg:SI LR_REGNUM))] 7699169689Skan "TARGET_THUMB && !arm_arch5" 770090075Sobrien "* 770190075Sobrien { 7702169689Skan if (!TARGET_CALLER_INTERWORKING) 7703169689Skan return thumb_call_via_reg (operands[0]); 7704169689Skan else if (operands[1] == const0_rtx) 7705169689Skan return \"bl\\t%__interwork_call_via_%0\"; 7706169689Skan else if (frame_pointer_needed) 7707169689Skan return \"bl\\t%__interwork_r7_call_via_%0\"; 770890075Sobrien else 7709169689Skan return \"bl\\t%__interwork_r11_call_via_%0\"; 771090075Sobrien }" 771190075Sobrien [(set_attr "type" "call")] 771290075Sobrien) 771390075Sobrien 771490075Sobrien(define_expand "call_value" 771590075Sobrien [(parallel [(set (match_operand 0 "" "") 771690075Sobrien (call (match_operand 1 "memory_operand" "") 771790075Sobrien (match_operand 2 "general_operand" ""))) 771890075Sobrien (use (match_operand 3 "" "")) 771990075Sobrien (clobber (reg:SI LR_REGNUM))])] 772090075Sobrien "TARGET_EITHER" 772190075Sobrien " 772290075Sobrien { 772390075Sobrien rtx callee = XEXP (operands[1], 0); 772490075Sobrien 772590075Sobrien /* In an untyped call, we can get NULL for operand 2. */ 772690075Sobrien if (operands[3] == 0) 772790075Sobrien operands[3] = const0_rtx; 772890075Sobrien 772990075Sobrien /* See the comment in define_expand \"call\". */ 7730169689Skan if ((GET_CODE (callee) == SYMBOL_REF 7731169689Skan && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0)) 7732169689Skan || (GET_CODE (callee) != SYMBOL_REF 7733169689Skan && GET_CODE (callee) != REG)) 773490075Sobrien XEXP (operands[1], 0) = force_reg (Pmode, callee); 773590075Sobrien }" 773690075Sobrien) 773790075Sobrien 7738169689Skan(define_insn "*call_value_reg_armv5" 7739132718Skan [(set (match_operand 0 "" "") 7740132718Skan (call (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 774190075Sobrien (match_operand 2 "" ""))) 774290075Sobrien (use (match_operand 3 "" "")) 774390075Sobrien (clobber (reg:SI LR_REGNUM))] 7744169689Skan "TARGET_ARM && arm_arch5" 7745169689Skan "blx%?\\t%1" 7746169689Skan [(set_attr "type" "call")] 7747169689Skan) 7748169689Skan 7749169689Skan(define_insn "*call_value_reg_arm" 7750169689Skan [(set (match_operand 0 "" "") 7751169689Skan (call (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 7752169689Skan (match_operand 2 "" ""))) 7753169689Skan (use (match_operand 3 "" "")) 7754169689Skan (clobber (reg:SI LR_REGNUM))] 7755169689Skan "TARGET_ARM && !arm_arch5" 775690075Sobrien "* 775790075Sobrien return output_call (&operands[1]); 775890075Sobrien " 775990075Sobrien [(set_attr "length" "12") 776090075Sobrien (set_attr "type" "call")] 776190075Sobrien) 776290075Sobrien 776390075Sobrien(define_insn "*call_value_mem" 7764132718Skan [(set (match_operand 0 "" "") 7765169689Skan (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m")) 776690075Sobrien (match_operand 2 "" ""))) 776790075Sobrien (use (match_operand 3 "" "")) 776890075Sobrien (clobber (reg:SI LR_REGNUM))] 776990075Sobrien "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))" 777090075Sobrien "* 777190075Sobrien return output_call_mem (&operands[1]); 777290075Sobrien " 777390075Sobrien [(set_attr "length" "12") 777490075Sobrien (set_attr "type" "call")] 777590075Sobrien) 777690075Sobrien 7777169689Skan(define_insn "*call_value_reg_thumb_v5" 7778169689Skan [(set (match_operand 0 "" "") 7779169689Skan (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 7780169689Skan (match_operand 2 "" ""))) 7781169689Skan (use (match_operand 3 "" "")) 7782169689Skan (clobber (reg:SI LR_REGNUM))] 7783169689Skan "TARGET_THUMB && arm_arch5" 7784169689Skan "blx\\t%1" 7785169689Skan [(set_attr "length" "2") 7786169689Skan (set_attr "type" "call")] 7787169689Skan) 7788169689Skan 7789169689Skan(define_insn "*call_value_reg_thumb" 7790169689Skan [(set (match_operand 0 "" "") 7791169689Skan (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 7792169689Skan (match_operand 2 "" ""))) 7793169689Skan (use (match_operand 3 "" "")) 7794169689Skan (clobber (reg:SI LR_REGNUM))] 7795169689Skan "TARGET_THUMB && !arm_arch5" 7796169689Skan "* 7797169689Skan { 7798169689Skan if (!TARGET_CALLER_INTERWORKING) 7799169689Skan return thumb_call_via_reg (operands[1]); 7800169689Skan else if (operands[2] == const0_rtx) 7801169689Skan return \"bl\\t%__interwork_call_via_%1\"; 7802169689Skan else if (frame_pointer_needed) 7803169689Skan return \"bl\\t%__interwork_r7_call_via_%1\"; 7804169689Skan else 7805169689Skan return \"bl\\t%__interwork_r11_call_via_%1\"; 7806169689Skan }" 7807169689Skan [(set_attr "type" "call")] 7808169689Skan) 7809169689Skan 781090075Sobrien;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses 781190075Sobrien;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. 781290075Sobrien 781390075Sobrien(define_insn "*call_symbol" 7814132718Skan [(call (mem:SI (match_operand:SI 0 "" "")) 781590075Sobrien (match_operand 1 "" "")) 781690075Sobrien (use (match_operand 2 "" "")) 781790075Sobrien (clobber (reg:SI LR_REGNUM))] 781890075Sobrien "TARGET_ARM 781990075Sobrien && (GET_CODE (operands[0]) == SYMBOL_REF) 782090075Sobrien && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 782190075Sobrien "* 782290075Sobrien { 782390075Sobrien return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\"; 782490075Sobrien }" 782590075Sobrien [(set_attr "type" "call")] 782690075Sobrien) 782790075Sobrien 782890075Sobrien(define_insn "*call_value_symbol" 7829169689Skan [(set (match_operand 0 "" "") 7830132718Skan (call (mem:SI (match_operand:SI 1 "" "")) 783190075Sobrien (match_operand:SI 2 "" ""))) 783290075Sobrien (use (match_operand 3 "" "")) 783390075Sobrien (clobber (reg:SI LR_REGNUM))] 783490075Sobrien "TARGET_ARM 783590075Sobrien && (GET_CODE (operands[1]) == SYMBOL_REF) 783690075Sobrien && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 783790075Sobrien "* 783890075Sobrien { 783990075Sobrien return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\"; 784090075Sobrien }" 784190075Sobrien [(set_attr "type" "call")] 784290075Sobrien) 784390075Sobrien 784490075Sobrien(define_insn "*call_insn" 7845132718Skan [(call (mem:SI (match_operand:SI 0 "" "")) 784690075Sobrien (match_operand:SI 1 "" "")) 784790075Sobrien (use (match_operand 2 "" "")) 784890075Sobrien (clobber (reg:SI LR_REGNUM))] 784990075Sobrien "TARGET_THUMB 785096263Sobrien && GET_CODE (operands[0]) == SYMBOL_REF 785196263Sobrien && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 785290075Sobrien "bl\\t%a0" 785390075Sobrien [(set_attr "length" "4") 785490075Sobrien (set_attr "type" "call")] 785590075Sobrien) 785690075Sobrien 785790075Sobrien(define_insn "*call_value_insn" 7858169689Skan [(set (match_operand 0 "" "") 7859132718Skan (call (mem:SI (match_operand 1 "" "")) 786090075Sobrien (match_operand 2 "" ""))) 786190075Sobrien (use (match_operand 3 "" "")) 786290075Sobrien (clobber (reg:SI LR_REGNUM))] 786390075Sobrien "TARGET_THUMB 786496263Sobrien && GET_CODE (operands[1]) == SYMBOL_REF 786596263Sobrien && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 786690075Sobrien "bl\\t%a1" 786790075Sobrien [(set_attr "length" "4") 786890075Sobrien (set_attr "type" "call")] 786990075Sobrien) 787090075Sobrien 787190075Sobrien;; We may also be able to do sibcalls for Thumb, but it's much harder... 787290075Sobrien(define_expand "sibcall" 787390075Sobrien [(parallel [(call (match_operand 0 "memory_operand" "") 787490075Sobrien (match_operand 1 "general_operand" "")) 7875117395Skan (return) 7876117395Skan (use (match_operand 2 "" ""))])] 787790075Sobrien "TARGET_ARM" 787890075Sobrien " 787990075Sobrien { 788090075Sobrien if (operands[2] == NULL_RTX) 788190075Sobrien operands[2] = const0_rtx; 788290075Sobrien }" 788390075Sobrien) 788490075Sobrien 788590075Sobrien(define_expand "sibcall_value" 7886169689Skan [(parallel [(set (match_operand 0 "" "") 788790075Sobrien (call (match_operand 1 "memory_operand" "") 788890075Sobrien (match_operand 2 "general_operand" ""))) 7889117395Skan (return) 7890117395Skan (use (match_operand 3 "" ""))])] 789190075Sobrien "TARGET_ARM" 789290075Sobrien " 789390075Sobrien { 789490075Sobrien if (operands[3] == NULL_RTX) 789590075Sobrien operands[3] = const0_rtx; 789690075Sobrien }" 789790075Sobrien) 789890075Sobrien 789990075Sobrien(define_insn "*sibcall_insn" 790090075Sobrien [(call (mem:SI (match_operand:SI 0 "" "X")) 790190075Sobrien (match_operand 1 "" "")) 7902117395Skan (return) 7903117395Skan (use (match_operand 2 "" ""))] 790490075Sobrien "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF" 790590075Sobrien "* 790690075Sobrien return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; 790790075Sobrien " 790890075Sobrien [(set_attr "type" "call")] 790990075Sobrien) 791090075Sobrien 791190075Sobrien(define_insn "*sibcall_value_insn" 7912169689Skan [(set (match_operand 0 "" "") 7913132718Skan (call (mem:SI (match_operand:SI 1 "" "X")) 791490075Sobrien (match_operand 2 "" ""))) 7915117395Skan (return) 7916117395Skan (use (match_operand 3 "" ""))] 791790075Sobrien "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF" 791890075Sobrien "* 791990075Sobrien return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; 792090075Sobrien " 792190075Sobrien [(set_attr "type" "call")] 792290075Sobrien) 792390075Sobrien 792490075Sobrien;; Often the return insn will be the same as loading from memory, so set attr 792590075Sobrien(define_insn "return" 792690075Sobrien [(return)] 792790075Sobrien "TARGET_ARM && USE_RETURN_INSN (FALSE)" 792890075Sobrien "* 792990075Sobrien { 793090075Sobrien if (arm_ccfsm_state == 2) 793190075Sobrien { 793290075Sobrien arm_ccfsm_state += 2; 793390075Sobrien return \"\"; 793490075Sobrien } 7935117395Skan return output_return_instruction (const_true_rtx, TRUE, FALSE); 793690075Sobrien }" 7937169689Skan [(set_attr "type" "load1") 7938132718Skan (set_attr "length" "12") 793990075Sobrien (set_attr "predicable" "yes")] 794090075Sobrien) 794190075Sobrien 794290075Sobrien(define_insn "*cond_return" 794390075Sobrien [(set (pc) 794490075Sobrien (if_then_else (match_operator 0 "arm_comparison_operator" 794590075Sobrien [(match_operand 1 "cc_register" "") (const_int 0)]) 794690075Sobrien (return) 794790075Sobrien (pc)))] 794890075Sobrien "TARGET_ARM && USE_RETURN_INSN (TRUE)" 794990075Sobrien "* 795090075Sobrien { 795190075Sobrien if (arm_ccfsm_state == 2) 795290075Sobrien { 795390075Sobrien arm_ccfsm_state += 2; 795490075Sobrien return \"\"; 795590075Sobrien } 795690075Sobrien return output_return_instruction (operands[0], TRUE, FALSE); 795790075Sobrien }" 795890075Sobrien [(set_attr "conds" "use") 7959132718Skan (set_attr "length" "12") 7960169689Skan (set_attr "type" "load1")] 796190075Sobrien) 796290075Sobrien 796390075Sobrien(define_insn "*cond_return_inverted" 796490075Sobrien [(set (pc) 796590075Sobrien (if_then_else (match_operator 0 "arm_comparison_operator" 796690075Sobrien [(match_operand 1 "cc_register" "") (const_int 0)]) 796790075Sobrien (pc) 796890075Sobrien (return)))] 796990075Sobrien "TARGET_ARM && USE_RETURN_INSN (TRUE)" 797090075Sobrien "* 797190075Sobrien { 797290075Sobrien if (arm_ccfsm_state == 2) 797390075Sobrien { 797490075Sobrien arm_ccfsm_state += 2; 797590075Sobrien return \"\"; 797690075Sobrien } 797790075Sobrien return output_return_instruction (operands[0], TRUE, TRUE); 797890075Sobrien }" 797990075Sobrien [(set_attr "conds" "use") 7980169689Skan (set_attr "length" "12") 7981169689Skan (set_attr "type" "load1")] 798290075Sobrien) 798390075Sobrien 7984117395Skan;; Generate a sequence of instructions to determine if the processor is 7985117395Skan;; in 26-bit or 32-bit mode, and return the appropriate return address 7986117395Skan;; mask. 7987117395Skan 7988117395Skan(define_expand "return_addr_mask" 7989117395Skan [(set (match_dup 1) 7990117395Skan (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 7991117395Skan (const_int 0))) 7992117395Skan (set (match_operand:SI 0 "s_register_operand" "") 7993117395Skan (if_then_else:SI (eq (match_dup 1) (const_int 0)) 7994117395Skan (const_int -1) 7995117395Skan (const_int 67108860)))] ; 0x03fffffc 7996117395Skan "TARGET_ARM" 7997117395Skan " 7998132718Skan operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM); 7999117395Skan ") 8000117395Skan 8001117395Skan(define_insn "*check_arch2" 8002117395Skan [(set (match_operand:CC_NOOV 0 "cc_register" "") 8003117395Skan (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 8004117395Skan (const_int 0)))] 8005117395Skan "TARGET_ARM" 8006117395Skan "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc" 8007117395Skan [(set_attr "length" "8") 8008117395Skan (set_attr "conds" "set")] 8009117395Skan) 8010117395Skan 801190075Sobrien;; Call subroutine returning any type. 801290075Sobrien 801390075Sobrien(define_expand "untyped_call" 801490075Sobrien [(parallel [(call (match_operand 0 "" "") 801590075Sobrien (const_int 0)) 801690075Sobrien (match_operand 1 "" "") 801790075Sobrien (match_operand 2 "" "")])] 8018169689Skan "TARGET_EITHER" 801990075Sobrien " 802090075Sobrien { 802190075Sobrien int i; 8022169689Skan rtx par = gen_rtx_PARALLEL (VOIDmode, 8023169689Skan rtvec_alloc (XVECLEN (operands[2], 0))); 8024169689Skan rtx addr = gen_reg_rtx (Pmode); 8025169689Skan rtx mem; 8026169689Skan int size = 0; 802790075Sobrien 8028169689Skan emit_move_insn (addr, XEXP (operands[1], 0)); 8029169689Skan mem = change_address (operands[1], BLKmode, addr); 803090075Sobrien 803190075Sobrien for (i = 0; i < XVECLEN (operands[2], 0); i++) 803290075Sobrien { 8033169689Skan rtx src = SET_SRC (XVECEXP (operands[2], 0, i)); 803490075Sobrien 8035169689Skan /* Default code only uses r0 as a return value, but we could 8036169689Skan be using anything up to 4 registers. */ 8037169689Skan if (REGNO (src) == R0_REGNUM) 8038169689Skan src = gen_rtx_REG (TImode, R0_REGNUM); 8039169689Skan 8040169689Skan XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src, 8041169689Skan GEN_INT (size)); 8042169689Skan size += GET_MODE_SIZE (GET_MODE (src)); 804390075Sobrien } 804490075Sobrien 8045169689Skan emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL, 8046169689Skan const0_rtx)); 8047169689Skan 8048169689Skan size = 0; 8049169689Skan 8050169689Skan for (i = 0; i < XVECLEN (par, 0); i++) 8051169689Skan { 8052169689Skan HOST_WIDE_INT offset = 0; 8053169689Skan rtx reg = XEXP (XVECEXP (par, 0, i), 0); 8054169689Skan 8055169689Skan if (size != 0) 8056169689Skan emit_move_insn (addr, plus_constant (addr, size)); 8057169689Skan 8058169689Skan mem = change_address (mem, GET_MODE (reg), NULL); 8059169689Skan if (REGNO (reg) == R0_REGNUM) 8060169689Skan { 8061169689Skan /* On thumb we have to use a write-back instruction. */ 8062169689Skan emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE, 8063169689Skan TARGET_THUMB ? TRUE : FALSE, mem, &offset)); 8064169689Skan size = TARGET_ARM ? 16 : 0; 8065169689Skan } 8066169689Skan else 8067169689Skan { 8068169689Skan emit_move_insn (mem, reg); 8069169689Skan size = GET_MODE_SIZE (GET_MODE (reg)); 8070169689Skan } 8071169689Skan } 8072169689Skan 807390075Sobrien /* The optimizer does not know that the call sets the function value 807490075Sobrien registers we stored in the result block. We avoid problems by 807590075Sobrien claiming that all hard registers are used and clobbered at this 807690075Sobrien point. */ 807790075Sobrien emit_insn (gen_blockage ()); 807890075Sobrien 807990075Sobrien DONE; 808090075Sobrien }" 808190075Sobrien) 808290075Sobrien 8083169689Skan(define_expand "untyped_return" 8084169689Skan [(match_operand:BLK 0 "memory_operand" "") 8085169689Skan (match_operand 1 "" "")] 8086169689Skan "TARGET_EITHER" 8087169689Skan " 8088169689Skan { 8089169689Skan int i; 8090169689Skan rtx addr = gen_reg_rtx (Pmode); 8091169689Skan rtx mem; 8092169689Skan int size = 0; 8093169689Skan 8094169689Skan emit_move_insn (addr, XEXP (operands[0], 0)); 8095169689Skan mem = change_address (operands[0], BLKmode, addr); 8096169689Skan 8097169689Skan for (i = 0; i < XVECLEN (operands[1], 0); i++) 8098169689Skan { 8099169689Skan HOST_WIDE_INT offset = 0; 8100169689Skan rtx reg = SET_DEST (XVECEXP (operands[1], 0, i)); 8101169689Skan 8102169689Skan if (size != 0) 8103169689Skan emit_move_insn (addr, plus_constant (addr, size)); 8104169689Skan 8105169689Skan mem = change_address (mem, GET_MODE (reg), NULL); 8106169689Skan if (REGNO (reg) == R0_REGNUM) 8107169689Skan { 8108169689Skan /* On thumb we have to use a write-back instruction. */ 8109169689Skan emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE, 8110169689Skan TARGET_THUMB ? TRUE : FALSE, mem, &offset)); 8111169689Skan size = TARGET_ARM ? 16 : 0; 8112169689Skan } 8113169689Skan else 8114169689Skan { 8115169689Skan emit_move_insn (reg, mem); 8116169689Skan size = GET_MODE_SIZE (GET_MODE (reg)); 8117169689Skan } 8118169689Skan } 8119169689Skan 8120169689Skan /* Emit USE insns before the return. */ 8121169689Skan for (i = 0; i < XVECLEN (operands[1], 0); i++) 8122169689Skan emit_insn (gen_rtx_USE (VOIDmode, 8123169689Skan SET_DEST (XVECEXP (operands[1], 0, i)))); 8124169689Skan 8125169689Skan /* Construct the return. */ 8126169689Skan expand_naked_return (); 8127169689Skan 8128169689Skan DONE; 8129169689Skan }" 8130169689Skan) 8131169689Skan 813290075Sobrien;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 813390075Sobrien;; all of memory. This blocks insns from being moved across this point. 813490075Sobrien 813590075Sobrien(define_insn "blockage" 813690075Sobrien [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)] 813790075Sobrien "TARGET_EITHER" 813890075Sobrien "" 813990075Sobrien [(set_attr "length" "0") 814090075Sobrien (set_attr "type" "block")] 814190075Sobrien) 814290075Sobrien 814390075Sobrien(define_expand "casesi" 814490075Sobrien [(match_operand:SI 0 "s_register_operand" "") ; index to jump on 814590075Sobrien (match_operand:SI 1 "const_int_operand" "") ; lower bound 814690075Sobrien (match_operand:SI 2 "const_int_operand" "") ; total range 814790075Sobrien (match_operand:SI 3 "" "") ; table label 814890075Sobrien (match_operand:SI 4 "" "")] ; Out of range label 814990075Sobrien "TARGET_ARM" 815090075Sobrien " 815190075Sobrien { 815290075Sobrien rtx reg; 815390075Sobrien if (operands[1] != const0_rtx) 815490075Sobrien { 815590075Sobrien reg = gen_reg_rtx (SImode); 815690075Sobrien 815790075Sobrien emit_insn (gen_addsi3 (reg, operands[0], 815890075Sobrien GEN_INT (-INTVAL (operands[1])))); 815990075Sobrien operands[0] = reg; 816090075Sobrien } 816190075Sobrien 816290075Sobrien if (!const_ok_for_arm (INTVAL (operands[2]))) 816390075Sobrien operands[2] = force_reg (SImode, operands[2]); 816490075Sobrien 816590075Sobrien emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3], 816690075Sobrien operands[4])); 816790075Sobrien DONE; 816890075Sobrien }" 816990075Sobrien) 817090075Sobrien 817190075Sobrien;; The USE in this pattern is needed to tell flow analysis that this is 817290075Sobrien;; a CASESI insn. It has no other purpose. 817390075Sobrien(define_insn "casesi_internal" 817490075Sobrien [(parallel [(set (pc) 817590075Sobrien (if_then_else 817690075Sobrien (leu (match_operand:SI 0 "s_register_operand" "r") 817790075Sobrien (match_operand:SI 1 "arm_rhs_operand" "rI")) 817890075Sobrien (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 817990075Sobrien (label_ref (match_operand 2 "" "")))) 818090075Sobrien (label_ref (match_operand 3 "" "")))) 818190075Sobrien (clobber (reg:CC CC_REGNUM)) 818290075Sobrien (use (label_ref (match_dup 2)))])] 818390075Sobrien "TARGET_ARM" 818490075Sobrien "* 818590075Sobrien if (flag_pic) 818690075Sobrien return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\"; 818790075Sobrien return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\"; 818890075Sobrien " 818990075Sobrien [(set_attr "conds" "clob") 819090075Sobrien (set_attr "length" "12")] 819190075Sobrien) 819290075Sobrien 819390075Sobrien(define_expand "indirect_jump" 819490075Sobrien [(set (pc) 819590075Sobrien (match_operand:SI 0 "s_register_operand" ""))] 819690075Sobrien "TARGET_EITHER" 819790075Sobrien "" 819890075Sobrien) 819990075Sobrien 8200169689Skan;; NB Never uses BX. 820190075Sobrien(define_insn "*arm_indirect_jump" 820290075Sobrien [(set (pc) 820390075Sobrien (match_operand:SI 0 "s_register_operand" "r"))] 820490075Sobrien "TARGET_ARM" 820590075Sobrien "mov%?\\t%|pc, %0\\t%@ indirect register jump" 820690075Sobrien [(set_attr "predicable" "yes")] 820790075Sobrien) 820890075Sobrien 820990075Sobrien(define_insn "*load_indirect_jump" 821090075Sobrien [(set (pc) 821190075Sobrien (match_operand:SI 0 "memory_operand" "m"))] 821290075Sobrien "TARGET_ARM" 821390075Sobrien "ldr%?\\t%|pc, %0\\t%@ indirect memory jump" 8214169689Skan [(set_attr "type" "load1") 821590075Sobrien (set_attr "pool_range" "4096") 821690075Sobrien (set_attr "neg_pool_range" "4084") 821790075Sobrien (set_attr "predicable" "yes")] 821890075Sobrien) 821990075Sobrien 8220169689Skan;; NB Never uses BX. 822190075Sobrien(define_insn "*thumb_indirect_jump" 822290075Sobrien [(set (pc) 822390075Sobrien (match_operand:SI 0 "register_operand" "l*r"))] 822490075Sobrien "TARGET_THUMB" 822590075Sobrien "mov\\tpc, %0" 822690075Sobrien [(set_attr "conds" "clob") 822790075Sobrien (set_attr "length" "2")] 822890075Sobrien) 822990075Sobrien 823090075Sobrien 823190075Sobrien;; Misc insns 823290075Sobrien 823390075Sobrien(define_insn "nop" 823490075Sobrien [(const_int 0)] 823590075Sobrien "TARGET_EITHER" 823690075Sobrien "* 823790075Sobrien if (TARGET_ARM) 823890075Sobrien return \"mov%?\\t%|r0, %|r0\\t%@ nop\"; 823990075Sobrien return \"mov\\tr8, r8\"; 824090075Sobrien " 824190075Sobrien [(set (attr "length") 824290075Sobrien (if_then_else (eq_attr "is_thumb" "yes") 824390075Sobrien (const_int 2) 824490075Sobrien (const_int 4)))] 824590075Sobrien) 824690075Sobrien 824790075Sobrien 824890075Sobrien;; Patterns to allow combination of arithmetic, cond code and shifts 824990075Sobrien 825090075Sobrien(define_insn "*arith_shiftsi" 825190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 825290075Sobrien (match_operator:SI 1 "shiftable_operator" 825390075Sobrien [(match_operator:SI 3 "shift_operator" 825490075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 825590075Sobrien (match_operand:SI 5 "reg_or_int_operand" "rI")]) 825690075Sobrien (match_operand:SI 2 "s_register_operand" "r")]))] 825790075Sobrien "TARGET_ARM" 825890075Sobrien "%i1%?\\t%0, %2, %4%S3" 825990075Sobrien [(set_attr "predicable" "yes") 826090075Sobrien (set_attr "shift" "4") 8261169689Skan (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") 8262169689Skan (const_string "alu_shift") 8263169689Skan (const_string "alu_shift_reg")))] 826490075Sobrien) 826590075Sobrien 8266132718Skan(define_split 8267132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 8268132718Skan (match_operator:SI 1 "shiftable_operator" 8269132718Skan [(match_operator:SI 2 "shiftable_operator" 8270132718Skan [(match_operator:SI 3 "shift_operator" 8271132718Skan [(match_operand:SI 4 "s_register_operand" "") 8272132718Skan (match_operand:SI 5 "reg_or_int_operand" "")]) 8273132718Skan (match_operand:SI 6 "s_register_operand" "")]) 8274132718Skan (match_operand:SI 7 "arm_rhs_operand" "")])) 8275132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 8276132718Skan "TARGET_ARM" 8277132718Skan [(set (match_dup 8) 8278132718Skan (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 8279132718Skan (match_dup 6)])) 8280132718Skan (set (match_dup 0) 8281132718Skan (match_op_dup 1 [(match_dup 8) (match_dup 7)]))] 8282132718Skan "") 8283132718Skan 828490075Sobrien(define_insn "*arith_shiftsi_compare0" 828590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 828690075Sobrien (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 828790075Sobrien [(match_operator:SI 3 "shift_operator" 828890075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 828990075Sobrien (match_operand:SI 5 "reg_or_int_operand" "rI")]) 829090075Sobrien (match_operand:SI 2 "s_register_operand" "r")]) 829190075Sobrien (const_int 0))) 829290075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 829390075Sobrien (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 829490075Sobrien (match_dup 2)]))] 829590075Sobrien "TARGET_ARM" 829690075Sobrien "%i1%?s\\t%0, %2, %4%S3" 829790075Sobrien [(set_attr "conds" "set") 829890075Sobrien (set_attr "shift" "4") 8299169689Skan (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") 8300169689Skan (const_string "alu_shift") 8301169689Skan (const_string "alu_shift_reg")))] 830290075Sobrien) 830390075Sobrien 830490075Sobrien(define_insn "*arith_shiftsi_compare0_scratch" 830590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 830690075Sobrien (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 830790075Sobrien [(match_operator:SI 3 "shift_operator" 830890075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 830990075Sobrien (match_operand:SI 5 "reg_or_int_operand" "rI")]) 831090075Sobrien (match_operand:SI 2 "s_register_operand" "r")]) 831190075Sobrien (const_int 0))) 831290075Sobrien (clobber (match_scratch:SI 0 "=r"))] 831390075Sobrien "TARGET_ARM" 831490075Sobrien "%i1%?s\\t%0, %2, %4%S3" 831590075Sobrien [(set_attr "conds" "set") 831690075Sobrien (set_attr "shift" "4") 8317169689Skan (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") 8318169689Skan (const_string "alu_shift") 8319169689Skan (const_string "alu_shift_reg")))] 832090075Sobrien) 832190075Sobrien 832290075Sobrien(define_insn "*sub_shiftsi" 832390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 832490075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "r") 832590075Sobrien (match_operator:SI 2 "shift_operator" 832690075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 832790075Sobrien (match_operand:SI 4 "reg_or_int_operand" "rM")])))] 832890075Sobrien "TARGET_ARM" 832990075Sobrien "sub%?\\t%0, %1, %3%S2" 833090075Sobrien [(set_attr "predicable" "yes") 833190075Sobrien (set_attr "shift" "3") 8332169689Skan (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") 8333169689Skan (const_string "alu_shift") 8334169689Skan (const_string "alu_shift_reg")))] 833590075Sobrien) 833690075Sobrien 833790075Sobrien(define_insn "*sub_shiftsi_compare0" 833890075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 833990075Sobrien (compare:CC_NOOV 834090075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "r") 834190075Sobrien (match_operator:SI 2 "shift_operator" 834290075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 834390075Sobrien (match_operand:SI 4 "reg_or_int_operand" "rM")])) 834490075Sobrien (const_int 0))) 834590075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 834690075Sobrien (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 834790075Sobrien (match_dup 4)])))] 834890075Sobrien "TARGET_ARM" 834990075Sobrien "sub%?s\\t%0, %1, %3%S2" 835090075Sobrien [(set_attr "conds" "set") 8351169689Skan (set_attr "shift" "3") 8352169689Skan (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") 8353169689Skan (const_string "alu_shift") 8354169689Skan (const_string "alu_shift_reg")))] 835590075Sobrien) 835690075Sobrien 835790075Sobrien(define_insn "*sub_shiftsi_compare0_scratch" 835890075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 835990075Sobrien (compare:CC_NOOV 836090075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "r") 836190075Sobrien (match_operator:SI 2 "shift_operator" 836290075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 836390075Sobrien (match_operand:SI 4 "reg_or_int_operand" "rM")])) 836490075Sobrien (const_int 0))) 836590075Sobrien (clobber (match_scratch:SI 0 "=r"))] 836690075Sobrien "TARGET_ARM" 836790075Sobrien "sub%?s\\t%0, %1, %3%S2" 836890075Sobrien [(set_attr "conds" "set") 8369169689Skan (set_attr "shift" "3") 8370169689Skan (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") 8371169689Skan (const_string "alu_shift") 8372169689Skan (const_string "alu_shift_reg")))] 837390075Sobrien) 837490075Sobrien 837590075Sobrien 837690075Sobrien 837790075Sobrien(define_insn "*and_scc" 837890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 837990075Sobrien (and:SI (match_operator:SI 1 "arm_comparison_operator" 838090075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 838190075Sobrien (match_operand:SI 2 "s_register_operand" "r")))] 838290075Sobrien "TARGET_ARM" 838390075Sobrien "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" 838490075Sobrien [(set_attr "conds" "use") 838590075Sobrien (set_attr "length" "8")] 838690075Sobrien) 838790075Sobrien 838890075Sobrien(define_insn "*ior_scc" 838990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 839090075Sobrien (ior:SI (match_operator:SI 2 "arm_comparison_operator" 839190075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 839290075Sobrien (match_operand:SI 1 "s_register_operand" "0,?r")))] 839390075Sobrien "TARGET_ARM" 839490075Sobrien "@ 839590075Sobrien orr%d2\\t%0, %1, #1 839690075Sobrien mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" 839790075Sobrien [(set_attr "conds" "use") 839890075Sobrien (set_attr "length" "4,8")] 839990075Sobrien) 840090075Sobrien 840190075Sobrien(define_insn "*compare_scc" 840290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 840390075Sobrien (match_operator:SI 1 "arm_comparison_operator" 840490075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 840590075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,L")])) 840690075Sobrien (clobber (reg:CC CC_REGNUM))] 840790075Sobrien "TARGET_ARM" 840890075Sobrien "* 8409132718Skan if (operands[3] == const0_rtx) 8410132718Skan { 8411132718Skan if (GET_CODE (operands[1]) == LT) 8412132718Skan return \"mov\\t%0, %2, lsr #31\"; 841390075Sobrien 8414132718Skan if (GET_CODE (operands[1]) == GE) 8415132718Skan return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; 841690075Sobrien 8417132718Skan if (GET_CODE (operands[1]) == EQ) 8418132718Skan return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\"; 8419132718Skan } 8420132718Skan 842190075Sobrien if (GET_CODE (operands[1]) == NE) 842290075Sobrien { 842390075Sobrien if (which_alternative == 1) 842490075Sobrien return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; 842590075Sobrien return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; 842690075Sobrien } 842790075Sobrien if (which_alternative == 1) 842890075Sobrien output_asm_insn (\"cmn\\t%2, #%n3\", operands); 842990075Sobrien else 843090075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 843190075Sobrien return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; 843290075Sobrien " 843390075Sobrien [(set_attr "conds" "clob") 843490075Sobrien (set_attr "length" "12")] 843590075Sobrien) 843690075Sobrien 843790075Sobrien(define_insn "*cond_move" 843890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 843990075Sobrien (if_then_else:SI (match_operator 3 "equality_operator" 844090075Sobrien [(match_operator 4 "arm_comparison_operator" 844190075Sobrien [(match_operand 5 "cc_register" "") (const_int 0)]) 844290075Sobrien (const_int 0)]) 844390075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 844490075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 844590075Sobrien "TARGET_ARM" 844690075Sobrien "* 844790075Sobrien if (GET_CODE (operands[3]) == NE) 844890075Sobrien { 844990075Sobrien if (which_alternative != 1) 845090075Sobrien output_asm_insn (\"mov%D4\\t%0, %2\", operands); 845190075Sobrien if (which_alternative != 0) 845290075Sobrien output_asm_insn (\"mov%d4\\t%0, %1\", operands); 845390075Sobrien return \"\"; 845490075Sobrien } 845590075Sobrien if (which_alternative != 0) 845690075Sobrien output_asm_insn (\"mov%D4\\t%0, %1\", operands); 845790075Sobrien if (which_alternative != 1) 845890075Sobrien output_asm_insn (\"mov%d4\\t%0, %2\", operands); 845990075Sobrien return \"\"; 846090075Sobrien " 846190075Sobrien [(set_attr "conds" "use") 846290075Sobrien (set_attr "length" "4,4,8")] 846390075Sobrien) 846490075Sobrien 846590075Sobrien(define_insn "*cond_arith" 846690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 846790075Sobrien (match_operator:SI 5 "shiftable_operator" 846890075Sobrien [(match_operator:SI 4 "arm_comparison_operator" 846990075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 847090075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 847190075Sobrien (match_operand:SI 1 "s_register_operand" "0,?r")])) 847290075Sobrien (clobber (reg:CC CC_REGNUM))] 847390075Sobrien "TARGET_ARM" 847490075Sobrien "* 847590075Sobrien if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 847690075Sobrien return \"%i5\\t%0, %1, %2, lsr #31\"; 847790075Sobrien 847890075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 847990075Sobrien if (GET_CODE (operands[5]) == AND) 848090075Sobrien output_asm_insn (\"mov%D4\\t%0, #0\", operands); 848190075Sobrien else if (GET_CODE (operands[5]) == MINUS) 848290075Sobrien output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 848390075Sobrien else if (which_alternative != 0) 848490075Sobrien output_asm_insn (\"mov%D4\\t%0, %1\", operands); 848590075Sobrien return \"%i5%d4\\t%0, %1, #1\"; 848690075Sobrien " 848790075Sobrien [(set_attr "conds" "clob") 848890075Sobrien (set_attr "length" "12")] 848990075Sobrien) 849090075Sobrien 849190075Sobrien(define_insn "*cond_sub" 849290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 849390075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 849490075Sobrien (match_operator:SI 4 "arm_comparison_operator" 849590075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 849690075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 849790075Sobrien (clobber (reg:CC CC_REGNUM))] 849890075Sobrien "TARGET_ARM" 849990075Sobrien "* 850090075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 850190075Sobrien if (which_alternative != 0) 850290075Sobrien output_asm_insn (\"mov%D4\\t%0, %1\", operands); 850390075Sobrien return \"sub%d4\\t%0, %1, #1\"; 850490075Sobrien " 850590075Sobrien [(set_attr "conds" "clob") 850690075Sobrien (set_attr "length" "8,12")] 850790075Sobrien) 850890075Sobrien 850990075Sobrien(define_insn "*cmp_ite0" 851090075Sobrien [(set (match_operand 6 "dominant_cc_register" "") 851190075Sobrien (compare 851290075Sobrien (if_then_else:SI 851390075Sobrien (match_operator 4 "arm_comparison_operator" 851490075Sobrien [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 851590075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 851690075Sobrien (match_operator:SI 5 "arm_comparison_operator" 851790075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 851890075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 851990075Sobrien (const_int 0)) 852090075Sobrien (const_int 0)))] 852190075Sobrien "TARGET_ARM" 852290075Sobrien "* 852390075Sobrien { 852490075Sobrien static const char * const opcodes[4][2] = 852590075Sobrien { 852690075Sobrien {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 852790075Sobrien \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 852890075Sobrien {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 852990075Sobrien \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 853090075Sobrien {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 853190075Sobrien \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 853290075Sobrien {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 853390075Sobrien \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 853490075Sobrien }; 853590075Sobrien int swap = 853690075Sobrien comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 853790075Sobrien 853890075Sobrien return opcodes[which_alternative][swap]; 853990075Sobrien }" 854090075Sobrien [(set_attr "conds" "set") 854190075Sobrien (set_attr "length" "8")] 854290075Sobrien) 854390075Sobrien 854490075Sobrien(define_insn "*cmp_ite1" 854590075Sobrien [(set (match_operand 6 "dominant_cc_register" "") 854690075Sobrien (compare 854790075Sobrien (if_then_else:SI 854890075Sobrien (match_operator 4 "arm_comparison_operator" 854990075Sobrien [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 855090075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 855190075Sobrien (match_operator:SI 5 "arm_comparison_operator" 855290075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 855390075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 855490075Sobrien (const_int 1)) 855590075Sobrien (const_int 0)))] 855690075Sobrien "TARGET_ARM" 855790075Sobrien "* 855890075Sobrien { 855990075Sobrien static const char * const opcodes[4][2] = 856090075Sobrien { 856190075Sobrien {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", 856290075Sobrien \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 856390075Sobrien {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", 856490075Sobrien \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 856590075Sobrien {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", 856690075Sobrien \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 856790075Sobrien {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\", 856890075Sobrien \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 856990075Sobrien }; 857090075Sobrien int swap = 857190075Sobrien comparison_dominates_p (GET_CODE (operands[5]), 857290075Sobrien reverse_condition (GET_CODE (operands[4]))); 857390075Sobrien 857490075Sobrien return opcodes[which_alternative][swap]; 857590075Sobrien }" 857690075Sobrien [(set_attr "conds" "set") 857790075Sobrien (set_attr "length" "8")] 857890075Sobrien) 857990075Sobrien 858090075Sobrien(define_insn "*cmp_and" 858190075Sobrien [(set (match_operand 6 "dominant_cc_register" "") 858290075Sobrien (compare 858390075Sobrien (and:SI 858490075Sobrien (match_operator 4 "arm_comparison_operator" 858590075Sobrien [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 858690075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 858790075Sobrien (match_operator:SI 5 "arm_comparison_operator" 858890075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 858990075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 859090075Sobrien (const_int 0)))] 859190075Sobrien "TARGET_ARM" 859290075Sobrien "* 859390075Sobrien { 859490075Sobrien static const char *const opcodes[4][2] = 859590075Sobrien { 859690075Sobrien {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 859790075Sobrien \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 859890075Sobrien {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 859990075Sobrien \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 860090075Sobrien {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 860190075Sobrien \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 860290075Sobrien {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 860390075Sobrien \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 860490075Sobrien }; 860590075Sobrien int swap = 860690075Sobrien comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 860790075Sobrien 860890075Sobrien return opcodes[which_alternative][swap]; 860990075Sobrien }" 861090075Sobrien [(set_attr "conds" "set") 861190075Sobrien (set_attr "predicable" "no") 861290075Sobrien (set_attr "length" "8")] 861390075Sobrien) 861490075Sobrien 861590075Sobrien(define_insn "*cmp_ior" 861690075Sobrien [(set (match_operand 6 "dominant_cc_register" "") 861790075Sobrien (compare 861890075Sobrien (ior:SI 861990075Sobrien (match_operator 4 "arm_comparison_operator" 862090075Sobrien [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 862190075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 862290075Sobrien (match_operator:SI 5 "arm_comparison_operator" 862390075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 862490075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 862590075Sobrien (const_int 0)))] 862690075Sobrien "TARGET_ARM" 862790075Sobrien "* 862890075Sobrien{ 862990075Sobrien static const char *const opcodes[4][2] = 863090075Sobrien { 863190075Sobrien {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\", 863290075Sobrien \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 863390075Sobrien {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\", 863490075Sobrien \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 863590075Sobrien {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\", 863690075Sobrien \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 863790075Sobrien {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\", 863890075Sobrien \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 863990075Sobrien }; 864090075Sobrien int swap = 864190075Sobrien comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 864290075Sobrien 864390075Sobrien return opcodes[which_alternative][swap]; 864490075Sobrien} 864590075Sobrien" 864690075Sobrien [(set_attr "conds" "set") 864790075Sobrien (set_attr "length" "8")] 864890075Sobrien) 864990075Sobrien 8650132718Skan(define_insn_and_split "*ior_scc_scc" 8651132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 8652132718Skan (ior:SI (match_operator:SI 3 "arm_comparison_operator" 8653132718Skan [(match_operand:SI 1 "s_register_operand" "r") 8654132718Skan (match_operand:SI 2 "arm_add_operand" "rIL")]) 8655132718Skan (match_operator:SI 6 "arm_comparison_operator" 8656132718Skan [(match_operand:SI 4 "s_register_operand" "r") 8657132718Skan (match_operand:SI 5 "arm_add_operand" "rIL")]))) 8658132718Skan (clobber (reg:CC CC_REGNUM))] 8659132718Skan "TARGET_ARM 8660132718Skan && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y) 8661132718Skan != CCmode)" 8662132718Skan "#" 8663132718Skan "TARGET_ARM && reload_completed" 8664132718Skan [(set (match_dup 7) 8665132718Skan (compare 8666132718Skan (ior:SI 8667132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8668132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8669132718Skan (const_int 0))) 8670132718Skan (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))] 8671132718Skan "operands[7] 8672132718Skan = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6], 8673132718Skan DOM_CC_X_OR_Y), 8674132718Skan CC_REGNUM);" 8675132718Skan [(set_attr "conds" "clob") 8676132718Skan (set_attr "length" "16")]) 8677132718Skan 8678132718Skan; If the above pattern is followed by a CMP insn, then the compare is 8679132718Skan; redundant, since we can rework the conditional instruction that follows. 8680132718Skan(define_insn_and_split "*ior_scc_scc_cmp" 8681132718Skan [(set (match_operand 0 "dominant_cc_register" "") 8682132718Skan (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator" 8683132718Skan [(match_operand:SI 1 "s_register_operand" "r") 8684132718Skan (match_operand:SI 2 "arm_add_operand" "rIL")]) 8685132718Skan (match_operator:SI 6 "arm_comparison_operator" 8686132718Skan [(match_operand:SI 4 "s_register_operand" "r") 8687132718Skan (match_operand:SI 5 "arm_add_operand" "rIL")])) 8688132718Skan (const_int 0))) 8689132718Skan (set (match_operand:SI 7 "s_register_operand" "=r") 8690132718Skan (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8691132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])))] 8692132718Skan "TARGET_ARM" 8693132718Skan "#" 8694132718Skan "TARGET_ARM && reload_completed" 8695132718Skan [(set (match_dup 0) 8696132718Skan (compare 8697132718Skan (ior:SI 8698132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8699132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8700132718Skan (const_int 0))) 8701132718Skan (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))] 8702132718Skan "" 8703132718Skan [(set_attr "conds" "set") 8704132718Skan (set_attr "length" "16")]) 8705132718Skan 8706132718Skan(define_insn_and_split "*and_scc_scc" 8707132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 8708132718Skan (and:SI (match_operator:SI 3 "arm_comparison_operator" 8709132718Skan [(match_operand:SI 1 "s_register_operand" "r") 8710132718Skan (match_operand:SI 2 "arm_add_operand" "rIL")]) 8711132718Skan (match_operator:SI 6 "arm_comparison_operator" 8712132718Skan [(match_operand:SI 4 "s_register_operand" "r") 8713132718Skan (match_operand:SI 5 "arm_add_operand" "rIL")]))) 8714132718Skan (clobber (reg:CC CC_REGNUM))] 8715132718Skan "TARGET_ARM 8716132718Skan && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8717132718Skan != CCmode)" 8718132718Skan "#" 8719132718Skan "TARGET_ARM && reload_completed 8720132718Skan && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8721132718Skan != CCmode)" 8722132718Skan [(set (match_dup 7) 8723132718Skan (compare 8724132718Skan (and:SI 8725132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8726132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8727132718Skan (const_int 0))) 8728132718Skan (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))] 8729132718Skan "operands[7] 8730132718Skan = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6], 8731132718Skan DOM_CC_X_AND_Y), 8732132718Skan CC_REGNUM);" 8733132718Skan [(set_attr "conds" "clob") 8734132718Skan (set_attr "length" "16")]) 8735132718Skan 8736132718Skan; If the above pattern is followed by a CMP insn, then the compare is 8737132718Skan; redundant, since we can rework the conditional instruction that follows. 8738132718Skan(define_insn_and_split "*and_scc_scc_cmp" 8739132718Skan [(set (match_operand 0 "dominant_cc_register" "") 8740132718Skan (compare (and:SI (match_operator:SI 3 "arm_comparison_operator" 8741132718Skan [(match_operand:SI 1 "s_register_operand" "r") 8742132718Skan (match_operand:SI 2 "arm_add_operand" "rIL")]) 8743132718Skan (match_operator:SI 6 "arm_comparison_operator" 8744132718Skan [(match_operand:SI 4 "s_register_operand" "r") 8745132718Skan (match_operand:SI 5 "arm_add_operand" "rIL")])) 8746132718Skan (const_int 0))) 8747132718Skan (set (match_operand:SI 7 "s_register_operand" "=r") 8748132718Skan (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8749132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])))] 8750132718Skan "TARGET_ARM" 8751132718Skan "#" 8752132718Skan "TARGET_ARM && reload_completed" 8753132718Skan [(set (match_dup 0) 8754132718Skan (compare 8755132718Skan (and:SI 8756132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8757132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8758132718Skan (const_int 0))) 8759132718Skan (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))] 8760132718Skan "" 8761132718Skan [(set_attr "conds" "set") 8762132718Skan (set_attr "length" "16")]) 8763132718Skan 8764132718Skan;; If there is no dominance in the comparison, then we can still save an 8765132718Skan;; instruction in the AND case, since we can know that the second compare 8766132718Skan;; need only zero the value if false (if true, then the value is already 8767132718Skan;; correct). 8768132718Skan(define_insn_and_split "*and_scc_scc_nodom" 8769132718Skan [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 8770132718Skan (and:SI (match_operator:SI 3 "arm_comparison_operator" 8771132718Skan [(match_operand:SI 1 "s_register_operand" "r,r,0") 8772132718Skan (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")]) 8773132718Skan (match_operator:SI 6 "arm_comparison_operator" 8774132718Skan [(match_operand:SI 4 "s_register_operand" "r,r,r") 8775132718Skan (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")]))) 8776132718Skan (clobber (reg:CC CC_REGNUM))] 8777132718Skan "TARGET_ARM 8778132718Skan && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8779132718Skan == CCmode)" 8780132718Skan "#" 8781132718Skan "TARGET_ARM && reload_completed" 8782132718Skan [(parallel [(set (match_dup 0) 8783132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)])) 8784132718Skan (clobber (reg:CC CC_REGNUM))]) 8785132718Skan (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)])) 8786132718Skan (set (match_dup 0) 8787132718Skan (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)]) 8788132718Skan (match_dup 0) 8789132718Skan (const_int 0)))] 8790132718Skan "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]), 8791132718Skan operands[4], operands[5]), 8792132718Skan CC_REGNUM); 8793132718Skan operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4], 8794132718Skan operands[5]);" 8795132718Skan [(set_attr "conds" "clob") 8796132718Skan (set_attr "length" "20")]) 8797132718Skan 8798132718Skan(define_split 8799132718Skan [(set (reg:CC_NOOV CC_REGNUM) 8800132718Skan (compare:CC_NOOV (ior:SI 8801132718Skan (and:SI (match_operand:SI 0 "s_register_operand" "") 8802132718Skan (const_int 1)) 8803132718Skan (match_operator:SI 1 "comparison_operator" 8804132718Skan [(match_operand:SI 2 "s_register_operand" "") 8805132718Skan (match_operand:SI 3 "arm_add_operand" "")])) 8806132718Skan (const_int 0))) 8807132718Skan (clobber (match_operand:SI 4 "s_register_operand" ""))] 8808132718Skan "TARGET_ARM" 8809132718Skan [(set (match_dup 4) 8810132718Skan (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)]) 8811132718Skan (match_dup 0))) 8812132718Skan (set (reg:CC_NOOV CC_REGNUM) 8813132718Skan (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1)) 8814132718Skan (const_int 0)))] 8815132718Skan "") 8816132718Skan 8817132718Skan(define_split 8818132718Skan [(set (reg:CC_NOOV CC_REGNUM) 8819132718Skan (compare:CC_NOOV (ior:SI 8820132718Skan (match_operator:SI 1 "comparison_operator" 8821132718Skan [(match_operand:SI 2 "s_register_operand" "") 8822132718Skan (match_operand:SI 3 "arm_add_operand" "")]) 8823132718Skan (and:SI (match_operand:SI 0 "s_register_operand" "") 8824132718Skan (const_int 1))) 8825132718Skan (const_int 0))) 8826132718Skan (clobber (match_operand:SI 4 "s_register_operand" ""))] 8827132718Skan "TARGET_ARM" 8828132718Skan [(set (match_dup 4) 8829132718Skan (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)]) 8830132718Skan (match_dup 0))) 8831132718Skan (set (reg:CC_NOOV CC_REGNUM) 8832132718Skan (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1)) 8833132718Skan (const_int 0)))] 8834132718Skan "") 8835132718Skan 883690075Sobrien(define_insn "*negscc" 883790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 883890075Sobrien (neg:SI (match_operator 3 "arm_comparison_operator" 883990075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 884090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 884190075Sobrien (clobber (reg:CC CC_REGNUM))] 884290075Sobrien "TARGET_ARM" 884390075Sobrien "* 884490075Sobrien if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx) 884590075Sobrien return \"mov\\t%0, %1, asr #31\"; 884690075Sobrien 884790075Sobrien if (GET_CODE (operands[3]) == NE) 884890075Sobrien return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\"; 884990075Sobrien 885090075Sobrien if (GET_CODE (operands[3]) == GT) 885190075Sobrien return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\"; 885290075Sobrien 885390075Sobrien output_asm_insn (\"cmp\\t%1, %2\", operands); 885490075Sobrien output_asm_insn (\"mov%D3\\t%0, #0\", operands); 885590075Sobrien return \"mvn%d3\\t%0, #0\"; 885690075Sobrien " 885790075Sobrien [(set_attr "conds" "clob") 885890075Sobrien (set_attr "length" "12")] 885990075Sobrien) 886090075Sobrien 886190075Sobrien(define_insn "movcond" 886290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 886390075Sobrien (if_then_else:SI 886490075Sobrien (match_operator 5 "arm_comparison_operator" 886590075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r,r") 886690075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 886790075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 886890075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 886990075Sobrien (clobber (reg:CC CC_REGNUM))] 887090075Sobrien "TARGET_ARM" 887190075Sobrien "* 887290075Sobrien if (GET_CODE (operands[5]) == LT 887390075Sobrien && (operands[4] == const0_rtx)) 887490075Sobrien { 887590075Sobrien if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 887690075Sobrien { 887790075Sobrien if (operands[2] == const0_rtx) 887890075Sobrien return \"and\\t%0, %1, %3, asr #31\"; 887990075Sobrien return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\"; 888090075Sobrien } 888190075Sobrien else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 888290075Sobrien { 888390075Sobrien if (operands[1] == const0_rtx) 888490075Sobrien return \"bic\\t%0, %2, %3, asr #31\"; 888590075Sobrien return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\"; 888690075Sobrien } 888790075Sobrien /* The only case that falls through to here is when both ops 1 & 2 8888132718Skan are constants. */ 888990075Sobrien } 889090075Sobrien 889190075Sobrien if (GET_CODE (operands[5]) == GE 889290075Sobrien && (operands[4] == const0_rtx)) 889390075Sobrien { 889490075Sobrien if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 889590075Sobrien { 889690075Sobrien if (operands[2] == const0_rtx) 889790075Sobrien return \"bic\\t%0, %1, %3, asr #31\"; 889890075Sobrien return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\"; 889990075Sobrien } 890090075Sobrien else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 890190075Sobrien { 890290075Sobrien if (operands[1] == const0_rtx) 890390075Sobrien return \"and\\t%0, %2, %3, asr #31\"; 890490075Sobrien return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\"; 890590075Sobrien } 890690075Sobrien /* The only case that falls through to here is when both ops 1 & 2 8907132718Skan are constants. */ 890890075Sobrien } 890990075Sobrien if (GET_CODE (operands[4]) == CONST_INT 891090075Sobrien && !const_ok_for_arm (INTVAL (operands[4]))) 891190075Sobrien output_asm_insn (\"cmn\\t%3, #%n4\", operands); 891290075Sobrien else 891390075Sobrien output_asm_insn (\"cmp\\t%3, %4\", operands); 891490075Sobrien if (which_alternative != 0) 891590075Sobrien output_asm_insn (\"mov%d5\\t%0, %1\", operands); 891690075Sobrien if (which_alternative != 1) 891790075Sobrien output_asm_insn (\"mov%D5\\t%0, %2\", operands); 891890075Sobrien return \"\"; 891990075Sobrien " 892090075Sobrien [(set_attr "conds" "clob") 892190075Sobrien (set_attr "length" "8,8,12")] 892290075Sobrien) 892390075Sobrien 892490075Sobrien(define_insn "*ifcompare_plus_move" 892590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 892690075Sobrien (if_then_else:SI (match_operator 6 "arm_comparison_operator" 892790075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 892890075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 892990075Sobrien (plus:SI 893090075Sobrien (match_operand:SI 2 "s_register_operand" "r,r") 893190075Sobrien (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) 893290075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 893390075Sobrien (clobber (reg:CC CC_REGNUM))] 893490075Sobrien "TARGET_ARM" 893590075Sobrien "#" 893690075Sobrien [(set_attr "conds" "clob") 893790075Sobrien (set_attr "length" "8,12")] 893890075Sobrien) 893990075Sobrien 894090075Sobrien(define_insn "*if_plus_move" 894190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 894290075Sobrien (if_then_else:SI 894390075Sobrien (match_operator 4 "arm_comparison_operator" 894490075Sobrien [(match_operand 5 "cc_register" "") (const_int 0)]) 894590075Sobrien (plus:SI 894690075Sobrien (match_operand:SI 2 "s_register_operand" "r,r,r,r") 894790075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")) 894890075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))] 894990075Sobrien "TARGET_ARM" 895090075Sobrien "@ 895190075Sobrien add%d4\\t%0, %2, %3 895290075Sobrien sub%d4\\t%0, %2, #%n3 895390075Sobrien add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 895490075Sobrien sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1" 895590075Sobrien [(set_attr "conds" "use") 895690075Sobrien (set_attr "length" "4,4,8,8") 895790075Sobrien (set_attr "type" "*,*,*,*")] 895890075Sobrien) 895990075Sobrien 896090075Sobrien(define_insn "*ifcompare_move_plus" 896190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 896290075Sobrien (if_then_else:SI (match_operator 6 "arm_comparison_operator" 896390075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 896490075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 896590075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 896690075Sobrien (plus:SI 896790075Sobrien (match_operand:SI 2 "s_register_operand" "r,r") 896890075Sobrien (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) 896990075Sobrien (clobber (reg:CC CC_REGNUM))] 897090075Sobrien "TARGET_ARM" 897190075Sobrien "#" 897290075Sobrien [(set_attr "conds" "clob") 897390075Sobrien (set_attr "length" "8,12")] 897490075Sobrien) 897590075Sobrien 897690075Sobrien(define_insn "*if_move_plus" 897790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 897890075Sobrien (if_then_else:SI 897990075Sobrien (match_operator 4 "arm_comparison_operator" 898090075Sobrien [(match_operand 5 "cc_register" "") (const_int 0)]) 898190075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI") 898290075Sobrien (plus:SI 898390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r,r,r") 898490075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))] 898590075Sobrien "TARGET_ARM" 898690075Sobrien "@ 898790075Sobrien add%D4\\t%0, %2, %3 898890075Sobrien sub%D4\\t%0, %2, #%n3 898990075Sobrien add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 899090075Sobrien sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1" 899190075Sobrien [(set_attr "conds" "use") 899290075Sobrien (set_attr "length" "4,4,8,8") 899390075Sobrien (set_attr "type" "*,*,*,*")] 899490075Sobrien) 899590075Sobrien 899690075Sobrien(define_insn "*ifcompare_arith_arith" 899790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 899890075Sobrien (if_then_else:SI (match_operator 9 "arm_comparison_operator" 899990075Sobrien [(match_operand:SI 5 "s_register_operand" "r") 900090075Sobrien (match_operand:SI 6 "arm_add_operand" "rIL")]) 900190075Sobrien (match_operator:SI 8 "shiftable_operator" 900290075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 900390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")]) 900490075Sobrien (match_operator:SI 7 "shiftable_operator" 900590075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 900690075Sobrien (match_operand:SI 4 "arm_rhs_operand" "rI")]))) 900790075Sobrien (clobber (reg:CC CC_REGNUM))] 900890075Sobrien "TARGET_ARM" 900990075Sobrien "#" 901090075Sobrien [(set_attr "conds" "clob") 901190075Sobrien (set_attr "length" "12")] 901290075Sobrien) 901390075Sobrien 901490075Sobrien(define_insn "*if_arith_arith" 901590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 901690075Sobrien (if_then_else:SI (match_operator 5 "arm_comparison_operator" 901790075Sobrien [(match_operand 8 "cc_register" "") (const_int 0)]) 901890075Sobrien (match_operator:SI 6 "shiftable_operator" 901990075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 902090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")]) 902190075Sobrien (match_operator:SI 7 "shiftable_operator" 902290075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 902390075Sobrien (match_operand:SI 4 "arm_rhs_operand" "rI")])))] 902490075Sobrien "TARGET_ARM" 902590075Sobrien "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4" 902690075Sobrien [(set_attr "conds" "use") 902790075Sobrien (set_attr "length" "8")] 902890075Sobrien) 902990075Sobrien 903090075Sobrien(define_insn "*ifcompare_arith_move" 903190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 903290075Sobrien (if_then_else:SI (match_operator 6 "arm_comparison_operator" 903390075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 903490075Sobrien (match_operand:SI 3 "arm_add_operand" "rIL,rIL")]) 903590075Sobrien (match_operator:SI 7 "shiftable_operator" 903690075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 903790075Sobrien (match_operand:SI 5 "arm_rhs_operand" "rI,rI")]) 903890075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 903990075Sobrien (clobber (reg:CC CC_REGNUM))] 904090075Sobrien "TARGET_ARM" 904190075Sobrien "* 904290075Sobrien /* If we have an operation where (op x 0) is the identity operation and 904390075Sobrien the conditional operator is LT or GE and we are comparing against zero and 9044132718Skan everything is in registers then we can do this in two instructions. */ 904590075Sobrien if (operands[3] == const0_rtx 904690075Sobrien && GET_CODE (operands[7]) != AND 904790075Sobrien && GET_CODE (operands[5]) == REG 904890075Sobrien && GET_CODE (operands[1]) == REG 904990075Sobrien && REGNO (operands[1]) == REGNO (operands[4]) 905090075Sobrien && REGNO (operands[4]) != REGNO (operands[0])) 905190075Sobrien { 905290075Sobrien if (GET_CODE (operands[6]) == LT) 905390075Sobrien return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 905490075Sobrien else if (GET_CODE (operands[6]) == GE) 905590075Sobrien return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 905690075Sobrien } 905790075Sobrien if (GET_CODE (operands[3]) == CONST_INT 905890075Sobrien && !const_ok_for_arm (INTVAL (operands[3]))) 905990075Sobrien output_asm_insn (\"cmn\\t%2, #%n3\", operands); 906090075Sobrien else 906190075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 906290075Sobrien output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands); 906390075Sobrien if (which_alternative != 0) 906490075Sobrien return \"mov%D6\\t%0, %1\"; 906590075Sobrien return \"\"; 906690075Sobrien " 906790075Sobrien [(set_attr "conds" "clob") 906890075Sobrien (set_attr "length" "8,12")] 906990075Sobrien) 907090075Sobrien 907190075Sobrien(define_insn "*if_arith_move" 907290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 907390075Sobrien (if_then_else:SI (match_operator 4 "arm_comparison_operator" 907490075Sobrien [(match_operand 6 "cc_register" "") (const_int 0)]) 907590075Sobrien (match_operator:SI 5 "shiftable_operator" 907690075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 907790075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 907890075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))] 907990075Sobrien "TARGET_ARM" 908090075Sobrien "@ 908190075Sobrien %I5%d4\\t%0, %2, %3 908290075Sobrien %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1" 908390075Sobrien [(set_attr "conds" "use") 908490075Sobrien (set_attr "length" "4,8") 908590075Sobrien (set_attr "type" "*,*")] 908690075Sobrien) 908790075Sobrien 908890075Sobrien(define_insn "*ifcompare_move_arith" 908990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 909090075Sobrien (if_then_else:SI (match_operator 6 "arm_comparison_operator" 909190075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 909290075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 909390075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 909490075Sobrien (match_operator:SI 7 "shiftable_operator" 909590075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 909690075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 909790075Sobrien (clobber (reg:CC CC_REGNUM))] 909890075Sobrien "TARGET_ARM" 909990075Sobrien "* 910090075Sobrien /* If we have an operation where (op x 0) is the identity operation and 910190075Sobrien the conditional operator is LT or GE and we are comparing against zero and 910290075Sobrien everything is in registers then we can do this in two instructions */ 910390075Sobrien if (operands[5] == const0_rtx 910490075Sobrien && GET_CODE (operands[7]) != AND 910590075Sobrien && GET_CODE (operands[3]) == REG 910690075Sobrien && GET_CODE (operands[1]) == REG 910790075Sobrien && REGNO (operands[1]) == REGNO (operands[2]) 910890075Sobrien && REGNO (operands[2]) != REGNO (operands[0])) 910990075Sobrien { 911090075Sobrien if (GET_CODE (operands[6]) == GE) 911190075Sobrien return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 911290075Sobrien else if (GET_CODE (operands[6]) == LT) 911390075Sobrien return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 911490075Sobrien } 911590075Sobrien 911690075Sobrien if (GET_CODE (operands[5]) == CONST_INT 911790075Sobrien && !const_ok_for_arm (INTVAL (operands[5]))) 911890075Sobrien output_asm_insn (\"cmn\\t%4, #%n5\", operands); 911990075Sobrien else 912090075Sobrien output_asm_insn (\"cmp\\t%4, %5\", operands); 912190075Sobrien 912290075Sobrien if (which_alternative != 0) 912390075Sobrien output_asm_insn (\"mov%d6\\t%0, %1\", operands); 912490075Sobrien return \"%I7%D6\\t%0, %2, %3\"; 912590075Sobrien " 912690075Sobrien [(set_attr "conds" "clob") 912790075Sobrien (set_attr "length" "8,12")] 912890075Sobrien) 912990075Sobrien 913090075Sobrien(define_insn "*if_move_arith" 913190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 913290075Sobrien (if_then_else:SI 913390075Sobrien (match_operator 4 "arm_comparison_operator" 913490075Sobrien [(match_operand 6 "cc_register" "") (const_int 0)]) 913590075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 913690075Sobrien (match_operator:SI 5 "shiftable_operator" 913790075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 913890075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))] 913990075Sobrien "TARGET_ARM" 914090075Sobrien "@ 914190075Sobrien %I5%D4\\t%0, %2, %3 914290075Sobrien %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1" 914390075Sobrien [(set_attr "conds" "use") 914490075Sobrien (set_attr "length" "4,8") 914590075Sobrien (set_attr "type" "*,*")] 914690075Sobrien) 914790075Sobrien 914890075Sobrien(define_insn "*ifcompare_move_not" 914990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 915090075Sobrien (if_then_else:SI 915190075Sobrien (match_operator 5 "arm_comparison_operator" 915290075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r") 915390075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 915490075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK") 915590075Sobrien (not:SI 915690075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")))) 915790075Sobrien (clobber (reg:CC CC_REGNUM))] 915890075Sobrien "TARGET_ARM" 915990075Sobrien "#" 916090075Sobrien [(set_attr "conds" "clob") 916190075Sobrien (set_attr "length" "8,12")] 916290075Sobrien) 916390075Sobrien 916490075Sobrien(define_insn "*if_move_not" 916590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 916690075Sobrien (if_then_else:SI 916790075Sobrien (match_operator 4 "arm_comparison_operator" 916890075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 916990075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 917090075Sobrien (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 917190075Sobrien "TARGET_ARM" 917290075Sobrien "@ 917390075Sobrien mvn%D4\\t%0, %2 917490075Sobrien mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 917590075Sobrien mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" 917690075Sobrien [(set_attr "conds" "use") 917790075Sobrien (set_attr "length" "4,8,8")] 917890075Sobrien) 917990075Sobrien 918090075Sobrien(define_insn "*ifcompare_not_move" 918190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 918290075Sobrien (if_then_else:SI 918390075Sobrien (match_operator 5 "arm_comparison_operator" 918490075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r") 918590075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 918690075Sobrien (not:SI 918790075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 918890075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 918990075Sobrien (clobber (reg:CC CC_REGNUM))] 919090075Sobrien "TARGET_ARM" 919190075Sobrien "#" 919290075Sobrien [(set_attr "conds" "clob") 919390075Sobrien (set_attr "length" "8,12")] 919490075Sobrien) 919590075Sobrien 919690075Sobrien(define_insn "*if_not_move" 919790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 919890075Sobrien (if_then_else:SI 919990075Sobrien (match_operator 4 "arm_comparison_operator" 920090075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 920190075Sobrien (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 920290075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 920390075Sobrien "TARGET_ARM" 920490075Sobrien "@ 920590075Sobrien mvn%d4\\t%0, %2 920690075Sobrien mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 920790075Sobrien mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" 920890075Sobrien [(set_attr "conds" "use") 920990075Sobrien (set_attr "length" "4,8,8")] 921090075Sobrien) 921190075Sobrien 921290075Sobrien(define_insn "*ifcompare_shift_move" 921390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 921490075Sobrien (if_then_else:SI 921590075Sobrien (match_operator 6 "arm_comparison_operator" 921690075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 921790075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 921890075Sobrien (match_operator:SI 7 "shift_operator" 921990075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 922090075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) 922190075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 922290075Sobrien (clobber (reg:CC CC_REGNUM))] 922390075Sobrien "TARGET_ARM" 922490075Sobrien "#" 922590075Sobrien [(set_attr "conds" "clob") 922690075Sobrien (set_attr "length" "8,12")] 922790075Sobrien) 922890075Sobrien 922990075Sobrien(define_insn "*if_shift_move" 923090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 923190075Sobrien (if_then_else:SI 923290075Sobrien (match_operator 5 "arm_comparison_operator" 923390075Sobrien [(match_operand 6 "cc_register" "") (const_int 0)]) 923490075Sobrien (match_operator:SI 4 "shift_operator" 923590075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r") 923690075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")]) 923790075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 923890075Sobrien "TARGET_ARM" 923990075Sobrien "@ 924090075Sobrien mov%d5\\t%0, %2%S4 924190075Sobrien mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4 924290075Sobrien mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" 924390075Sobrien [(set_attr "conds" "use") 924490075Sobrien (set_attr "shift" "2") 9245169689Skan (set_attr "length" "4,8,8") 9246169689Skan (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "") 9247169689Skan (const_string "alu_shift") 9248169689Skan (const_string "alu_shift_reg")))] 924990075Sobrien) 925090075Sobrien 925190075Sobrien(define_insn "*ifcompare_move_shift" 925290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 925390075Sobrien (if_then_else:SI 925490075Sobrien (match_operator 6 "arm_comparison_operator" 925590075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 925690075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 925790075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK") 925890075Sobrien (match_operator:SI 7 "shift_operator" 925990075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 926090075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) 926190075Sobrien (clobber (reg:CC CC_REGNUM))] 926290075Sobrien "TARGET_ARM" 926390075Sobrien "#" 926490075Sobrien [(set_attr "conds" "clob") 926590075Sobrien (set_attr "length" "8,12")] 926690075Sobrien) 926790075Sobrien 926890075Sobrien(define_insn "*if_move_shift" 926990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 927090075Sobrien (if_then_else:SI 927190075Sobrien (match_operator 5 "arm_comparison_operator" 927290075Sobrien [(match_operand 6 "cc_register" "") (const_int 0)]) 927390075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 927490075Sobrien (match_operator:SI 4 "shift_operator" 927590075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r") 927690075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))] 927790075Sobrien "TARGET_ARM" 927890075Sobrien "@ 927990075Sobrien mov%D5\\t%0, %2%S4 928090075Sobrien mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4 928190075Sobrien mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" 928290075Sobrien [(set_attr "conds" "use") 928390075Sobrien (set_attr "shift" "2") 9284169689Skan (set_attr "length" "4,8,8") 9285169689Skan (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "") 9286169689Skan (const_string "alu_shift") 9287169689Skan (const_string "alu_shift_reg")))] 928890075Sobrien) 928990075Sobrien 929090075Sobrien(define_insn "*ifcompare_shift_shift" 929190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 929290075Sobrien (if_then_else:SI 929390075Sobrien (match_operator 7 "arm_comparison_operator" 929490075Sobrien [(match_operand:SI 5 "s_register_operand" "r") 929590075Sobrien (match_operand:SI 6 "arm_add_operand" "rIL")]) 929690075Sobrien (match_operator:SI 8 "shift_operator" 929790075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 929890075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]) 929990075Sobrien (match_operator:SI 9 "shift_operator" 930090075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 930190075Sobrien (match_operand:SI 4 "arm_rhs_operand" "rM")]))) 930290075Sobrien (clobber (reg:CC CC_REGNUM))] 930390075Sobrien "TARGET_ARM" 930490075Sobrien "#" 930590075Sobrien [(set_attr "conds" "clob") 930690075Sobrien (set_attr "length" "12")] 930790075Sobrien) 930890075Sobrien 930990075Sobrien(define_insn "*if_shift_shift" 931090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 931190075Sobrien (if_then_else:SI 931290075Sobrien (match_operator 5 "arm_comparison_operator" 931390075Sobrien [(match_operand 8 "cc_register" "") (const_int 0)]) 931490075Sobrien (match_operator:SI 6 "shift_operator" 931590075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 931690075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]) 931790075Sobrien (match_operator:SI 7 "shift_operator" 931890075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 931990075Sobrien (match_operand:SI 4 "arm_rhs_operand" "rM")])))] 932090075Sobrien "TARGET_ARM" 932190075Sobrien "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" 932290075Sobrien [(set_attr "conds" "use") 932390075Sobrien (set_attr "shift" "1") 9324169689Skan (set_attr "length" "8") 9325169689Skan (set (attr "type") (if_then_else 9326169689Skan (and (match_operand 2 "const_int_operand" "") 9327169689Skan (match_operand 4 "const_int_operand" "")) 9328169689Skan (const_string "alu_shift") 9329169689Skan (const_string "alu_shift_reg")))] 933090075Sobrien) 933190075Sobrien 933290075Sobrien(define_insn "*ifcompare_not_arith" 933390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 933490075Sobrien (if_then_else:SI 933590075Sobrien (match_operator 6 "arm_comparison_operator" 933690075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 933790075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL")]) 933890075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r")) 933990075Sobrien (match_operator:SI 7 "shiftable_operator" 934090075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 934190075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI")]))) 934290075Sobrien (clobber (reg:CC CC_REGNUM))] 934390075Sobrien "TARGET_ARM" 934490075Sobrien "#" 934590075Sobrien [(set_attr "conds" "clob") 934690075Sobrien (set_attr "length" "12")] 934790075Sobrien) 934890075Sobrien 934990075Sobrien(define_insn "*if_not_arith" 935090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 935190075Sobrien (if_then_else:SI 935290075Sobrien (match_operator 5 "arm_comparison_operator" 935390075Sobrien [(match_operand 4 "cc_register" "") (const_int 0)]) 935490075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r")) 935590075Sobrien (match_operator:SI 6 "shiftable_operator" 935690075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 935790075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI")])))] 935890075Sobrien "TARGET_ARM" 935990075Sobrien "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" 936090075Sobrien [(set_attr "conds" "use") 936190075Sobrien (set_attr "length" "8")] 936290075Sobrien) 936390075Sobrien 936490075Sobrien(define_insn "*ifcompare_arith_not" 936590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 936690075Sobrien (if_then_else:SI 936790075Sobrien (match_operator 6 "arm_comparison_operator" 936890075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 936990075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL")]) 937090075Sobrien (match_operator:SI 7 "shiftable_operator" 937190075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 937290075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI")]) 937390075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r")))) 937490075Sobrien (clobber (reg:CC CC_REGNUM))] 937590075Sobrien "TARGET_ARM" 937690075Sobrien "#" 937790075Sobrien [(set_attr "conds" "clob") 937890075Sobrien (set_attr "length" "12")] 937990075Sobrien) 938090075Sobrien 938190075Sobrien(define_insn "*if_arith_not" 938290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 938390075Sobrien (if_then_else:SI 938490075Sobrien (match_operator 5 "arm_comparison_operator" 938590075Sobrien [(match_operand 4 "cc_register" "") (const_int 0)]) 938690075Sobrien (match_operator:SI 6 "shiftable_operator" 938790075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 938890075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI")]) 938990075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r"))))] 939090075Sobrien "TARGET_ARM" 939190075Sobrien "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" 939290075Sobrien [(set_attr "conds" "use") 939390075Sobrien (set_attr "length" "8")] 939490075Sobrien) 939590075Sobrien 939690075Sobrien(define_insn "*ifcompare_neg_move" 939790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 939890075Sobrien (if_then_else:SI 939990075Sobrien (match_operator 5 "arm_comparison_operator" 940090075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r") 940190075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 940290075Sobrien (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) 940390075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 940490075Sobrien (clobber (reg:CC CC_REGNUM))] 940590075Sobrien "TARGET_ARM" 940690075Sobrien "#" 940790075Sobrien [(set_attr "conds" "clob") 940890075Sobrien (set_attr "length" "8,12")] 940990075Sobrien) 941090075Sobrien 941190075Sobrien(define_insn "*if_neg_move" 941290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 941390075Sobrien (if_then_else:SI 941490075Sobrien (match_operator 4 "arm_comparison_operator" 941590075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 941690075Sobrien (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 941790075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 941890075Sobrien "TARGET_ARM" 941990075Sobrien "@ 942090075Sobrien rsb%d4\\t%0, %2, #0 942190075Sobrien mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0 942290075Sobrien mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0" 942390075Sobrien [(set_attr "conds" "use") 942490075Sobrien (set_attr "length" "4,8,8")] 942590075Sobrien) 942690075Sobrien 942790075Sobrien(define_insn "*ifcompare_move_neg" 942890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 942990075Sobrien (if_then_else:SI 943090075Sobrien (match_operator 5 "arm_comparison_operator" 943190075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r") 943290075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 943390075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK") 943490075Sobrien (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) 943590075Sobrien (clobber (reg:CC CC_REGNUM))] 943690075Sobrien "TARGET_ARM" 943790075Sobrien "#" 943890075Sobrien [(set_attr "conds" "clob") 943990075Sobrien (set_attr "length" "8,12")] 944090075Sobrien) 944190075Sobrien 944290075Sobrien(define_insn "*if_move_neg" 944390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 944490075Sobrien (if_then_else:SI 944590075Sobrien (match_operator 4 "arm_comparison_operator" 944690075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 944790075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 944890075Sobrien (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 944990075Sobrien "TARGET_ARM" 945090075Sobrien "@ 945190075Sobrien rsb%D4\\t%0, %2, #0 945290075Sobrien mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0 945390075Sobrien mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0" 945490075Sobrien [(set_attr "conds" "use") 945590075Sobrien (set_attr "length" "4,8,8")] 945690075Sobrien) 945790075Sobrien 945890075Sobrien(define_insn "*arith_adjacentmem" 945990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 946090075Sobrien (match_operator:SI 1 "shiftable_operator" 946190075Sobrien [(match_operand:SI 2 "memory_operand" "m") 946290075Sobrien (match_operand:SI 3 "memory_operand" "m")])) 946390075Sobrien (clobber (match_scratch:SI 4 "=r"))] 946490075Sobrien "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])" 946590075Sobrien "* 946690075Sobrien { 946790075Sobrien rtx ldm[3]; 946890075Sobrien rtx arith[4]; 9469169689Skan rtx base_reg; 9470169689Skan HOST_WIDE_INT val1 = 0, val2 = 0; 947190075Sobrien 947290075Sobrien if (REGNO (operands[0]) > REGNO (operands[4])) 947390075Sobrien { 947490075Sobrien ldm[1] = operands[4]; 947590075Sobrien ldm[2] = operands[0]; 947690075Sobrien } 947790075Sobrien else 947890075Sobrien { 947990075Sobrien ldm[1] = operands[0]; 948090075Sobrien ldm[2] = operands[4]; 948190075Sobrien } 9482169689Skan 9483169689Skan base_reg = XEXP (operands[2], 0); 9484169689Skan 9485169689Skan if (!REG_P (base_reg)) 9486169689Skan { 9487169689Skan val1 = INTVAL (XEXP (base_reg, 1)); 9488169689Skan base_reg = XEXP (base_reg, 0); 9489169689Skan } 9490169689Skan 9491169689Skan if (!REG_P (XEXP (operands[3], 0))) 949290075Sobrien val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); 9493169689Skan 949490075Sobrien arith[0] = operands[0]; 949590075Sobrien arith[3] = operands[1]; 9496169689Skan 949790075Sobrien if (val1 < val2) 949890075Sobrien { 949990075Sobrien arith[1] = ldm[1]; 950090075Sobrien arith[2] = ldm[2]; 950190075Sobrien } 950290075Sobrien else 950390075Sobrien { 950490075Sobrien arith[1] = ldm[2]; 950590075Sobrien arith[2] = ldm[1]; 950690075Sobrien } 9507169689Skan 9508169689Skan ldm[0] = base_reg; 9509169689Skan if (val1 !=0 && val2 != 0) 951090075Sobrien { 951190075Sobrien rtx ops[3]; 9512169689Skan 9513169689Skan if (val1 == 4 || val2 == 4) 9514169689Skan /* Other val must be 8, since we know they are adjacent and neither 9515169689Skan is zero. */ 9516169689Skan output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm); 9517169689Skan else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1)) 9518169689Skan { 9519169689Skan ldm[0] = ops[0] = operands[4]; 9520169689Skan ops[1] = base_reg; 9521169689Skan ops[2] = GEN_INT (val1); 9522169689Skan output_add_immediate (ops); 9523169689Skan if (val1 < val2) 9524169689Skan output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 9525169689Skan else 9526169689Skan output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 9527169689Skan } 952890075Sobrien else 9529169689Skan { 9530169689Skan /* Offset is out of range for a single add, so use two ldr. */ 9531169689Skan ops[0] = ldm[1]; 9532169689Skan ops[1] = base_reg; 9533169689Skan ops[2] = GEN_INT (val1); 9534169689Skan output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops); 9535169689Skan ops[0] = ldm[2]; 9536169689Skan ops[2] = GEN_INT (val2); 9537169689Skan output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops); 9538169689Skan } 953990075Sobrien } 9540169689Skan else if (val1 != 0) 954190075Sobrien { 954290075Sobrien if (val1 < val2) 954390075Sobrien output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 954490075Sobrien else 954590075Sobrien output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 954690075Sobrien } 954790075Sobrien else 954890075Sobrien { 954990075Sobrien if (val1 < val2) 955090075Sobrien output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 955190075Sobrien else 955290075Sobrien output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 955390075Sobrien } 955490075Sobrien output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); 955590075Sobrien return \"\"; 955690075Sobrien }" 955790075Sobrien [(set_attr "length" "12") 955890075Sobrien (set_attr "predicable" "yes") 9559169689Skan (set_attr "type" "load1")] 956090075Sobrien) 956190075Sobrien 956290075Sobrien; This pattern is never tried by combine, so do it as a peephole 956390075Sobrien 956490075Sobrien(define_peephole2 9565169689Skan [(set (match_operand:SI 0 "arm_general_register_operand" "") 9566169689Skan (match_operand:SI 1 "arm_general_register_operand" "")) 956790075Sobrien (set (reg:CC CC_REGNUM) 956890075Sobrien (compare:CC (match_dup 1) (const_int 0)))] 9569169689Skan "TARGET_ARM" 957090075Sobrien [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) 957190075Sobrien (set (match_dup 0) (match_dup 1))])] 957290075Sobrien "" 957390075Sobrien) 957490075Sobrien 957590075Sobrien; Peepholes to spot possible load- and store-multiples, if the ordering is 957690075Sobrien; reversed, check that the memory references aren't volatile. 957790075Sobrien 957890075Sobrien(define_peephole 957990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 958090075Sobrien (match_operand:SI 4 "memory_operand" "m")) 958190075Sobrien (set (match_operand:SI 1 "s_register_operand" "=r") 958290075Sobrien (match_operand:SI 5 "memory_operand" "m")) 958390075Sobrien (set (match_operand:SI 2 "s_register_operand" "=r") 958490075Sobrien (match_operand:SI 6 "memory_operand" "m")) 958590075Sobrien (set (match_operand:SI 3 "s_register_operand" "=r") 958690075Sobrien (match_operand:SI 7 "memory_operand" "m"))] 958790075Sobrien "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)" 958890075Sobrien "* 958990075Sobrien return emit_ldm_seq (operands, 4); 959090075Sobrien " 959190075Sobrien) 959290075Sobrien 959390075Sobrien(define_peephole 959490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 959590075Sobrien (match_operand:SI 3 "memory_operand" "m")) 959690075Sobrien (set (match_operand:SI 1 "s_register_operand" "=r") 959790075Sobrien (match_operand:SI 4 "memory_operand" "m")) 959890075Sobrien (set (match_operand:SI 2 "s_register_operand" "=r") 959990075Sobrien (match_operand:SI 5 "memory_operand" "m"))] 960090075Sobrien "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)" 960190075Sobrien "* 960290075Sobrien return emit_ldm_seq (operands, 3); 960390075Sobrien " 960490075Sobrien) 960590075Sobrien 960690075Sobrien(define_peephole 960790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 960890075Sobrien (match_operand:SI 2 "memory_operand" "m")) 960990075Sobrien (set (match_operand:SI 1 "s_register_operand" "=r") 961090075Sobrien (match_operand:SI 3 "memory_operand" "m"))] 961190075Sobrien "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)" 961290075Sobrien "* 961390075Sobrien return emit_ldm_seq (operands, 2); 961490075Sobrien " 961590075Sobrien) 961690075Sobrien 961790075Sobrien(define_peephole 961890075Sobrien [(set (match_operand:SI 4 "memory_operand" "=m") 961990075Sobrien (match_operand:SI 0 "s_register_operand" "r")) 962090075Sobrien (set (match_operand:SI 5 "memory_operand" "=m") 962190075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 962290075Sobrien (set (match_operand:SI 6 "memory_operand" "=m") 962390075Sobrien (match_operand:SI 2 "s_register_operand" "r")) 962490075Sobrien (set (match_operand:SI 7 "memory_operand" "=m") 962590075Sobrien (match_operand:SI 3 "s_register_operand" "r"))] 962690075Sobrien "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)" 962790075Sobrien "* 962890075Sobrien return emit_stm_seq (operands, 4); 962990075Sobrien " 963090075Sobrien) 963190075Sobrien 963290075Sobrien(define_peephole 963390075Sobrien [(set (match_operand:SI 3 "memory_operand" "=m") 963490075Sobrien (match_operand:SI 0 "s_register_operand" "r")) 963590075Sobrien (set (match_operand:SI 4 "memory_operand" "=m") 963690075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 963790075Sobrien (set (match_operand:SI 5 "memory_operand" "=m") 963890075Sobrien (match_operand:SI 2 "s_register_operand" "r"))] 963990075Sobrien "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)" 964090075Sobrien "* 964190075Sobrien return emit_stm_seq (operands, 3); 964290075Sobrien " 964390075Sobrien) 964490075Sobrien 964590075Sobrien(define_peephole 964690075Sobrien [(set (match_operand:SI 2 "memory_operand" "=m") 964790075Sobrien (match_operand:SI 0 "s_register_operand" "r")) 964890075Sobrien (set (match_operand:SI 3 "memory_operand" "=m") 964990075Sobrien (match_operand:SI 1 "s_register_operand" "r"))] 965090075Sobrien "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)" 965190075Sobrien "* 965290075Sobrien return emit_stm_seq (operands, 2); 965390075Sobrien " 965490075Sobrien) 965590075Sobrien 965690075Sobrien(define_split 965790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 965890075Sobrien (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "") 965990075Sobrien (const_int 0)) 966090075Sobrien (neg:SI (match_operator:SI 2 "arm_comparison_operator" 966190075Sobrien [(match_operand:SI 3 "s_register_operand" "") 966290075Sobrien (match_operand:SI 4 "arm_rhs_operand" "")])))) 966390075Sobrien (clobber (match_operand:SI 5 "s_register_operand" ""))] 966490075Sobrien "TARGET_ARM" 966590075Sobrien [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31)))) 966690075Sobrien (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 966790075Sobrien (match_dup 5)))] 966890075Sobrien "" 966990075Sobrien) 967090075Sobrien 967190075Sobrien;; This split can be used because CC_Z mode implies that the following 967290075Sobrien;; branch will be an equality, or an unsigned inequality, so the sign 967390075Sobrien;; extension is not needed. 967490075Sobrien 967590075Sobrien(define_split 967690075Sobrien [(set (reg:CC_Z CC_REGNUM) 967790075Sobrien (compare:CC_Z 967890075Sobrien (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0) 967990075Sobrien (const_int 24)) 968090075Sobrien (match_operand 1 "const_int_operand" ""))) 968190075Sobrien (clobber (match_scratch:SI 2 ""))] 968290075Sobrien "TARGET_ARM 968390075Sobrien && (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) 968490075Sobrien == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)" 968590075Sobrien [(set (match_dup 2) (zero_extend:SI (match_dup 0))) 968690075Sobrien (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))] 968790075Sobrien " 968890075Sobrien operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24); 968990075Sobrien " 969090075Sobrien) 969190075Sobrien 969290075Sobrien(define_expand "prologue" 969390075Sobrien [(clobber (const_int 0))] 969490075Sobrien "TARGET_EITHER" 969590075Sobrien "if (TARGET_ARM) 969690075Sobrien arm_expand_prologue (); 969790075Sobrien else 969890075Sobrien thumb_expand_prologue (); 969990075Sobrien DONE; 970090075Sobrien " 970190075Sobrien) 970290075Sobrien 970390075Sobrien(define_expand "epilogue" 9704169689Skan [(clobber (const_int 0))] 970590075Sobrien "TARGET_EITHER" 970690075Sobrien " 9707169689Skan if (current_function_calls_eh_return) 9708169689Skan emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2))); 970990075Sobrien if (TARGET_THUMB) 971090075Sobrien thumb_expand_epilogue (); 971190075Sobrien else if (USE_RETURN_INSN (FALSE)) 971290075Sobrien { 971390075Sobrien emit_jump_insn (gen_return ()); 971490075Sobrien DONE; 971590075Sobrien } 971690075Sobrien emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode, 971790075Sobrien gen_rtvec (1, 971890075Sobrien gen_rtx_RETURN (VOIDmode)), 971990075Sobrien VUNSPEC_EPILOGUE)); 972090075Sobrien DONE; 972190075Sobrien " 972290075Sobrien) 972390075Sobrien 9724117395Skan;; Note - although unspec_volatile's USE all hard registers, 9725117395Skan;; USEs are ignored after relaod has completed. Thus we need 9726117395Skan;; to add an unspec of the link register to ensure that flow 9727117395Skan;; does not think that it is unused by the sibcall branch that 9728117395Skan;; will replace the standard function epilogue. 972990075Sobrien(define_insn "sibcall_epilogue" 9730117395Skan [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE) 9731117395Skan (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])] 973290075Sobrien "TARGET_ARM" 973390075Sobrien "* 9734132718Skan if (use_return_insn (FALSE, next_nonnote_insn (insn))) 9735117395Skan return output_return_instruction (const_true_rtx, FALSE, FALSE); 9736132718Skan return arm_output_epilogue (next_nonnote_insn (insn)); 973790075Sobrien " 973890075Sobrien;; Length is absolute worst case 973990075Sobrien [(set_attr "length" "44") 9740117395Skan (set_attr "type" "block") 9741117395Skan ;; We don't clobber the conditions, but the potential length of this 9742117395Skan ;; operation is sufficient to make conditionalizing the sequence 9743117395Skan ;; unlikely to be profitable. 9744117395Skan (set_attr "conds" "clob")] 974590075Sobrien) 974690075Sobrien 974790075Sobrien(define_insn "*epilogue_insns" 974890075Sobrien [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 974990075Sobrien "TARGET_EITHER" 975090075Sobrien "* 975190075Sobrien if (TARGET_ARM) 9752132718Skan return arm_output_epilogue (NULL); 975390075Sobrien else /* TARGET_THUMB */ 975490075Sobrien return thumb_unexpanded_epilogue (); 975590075Sobrien " 975690075Sobrien ; Length is absolute worst case 975790075Sobrien [(set_attr "length" "44") 9758117395Skan (set_attr "type" "block") 9759117395Skan ;; We don't clobber the conditions, but the potential length of this 9760117395Skan ;; operation is sufficient to make conditionalizing the sequence 9761117395Skan ;; unlikely to be profitable. 9762117395Skan (set_attr "conds" "clob")] 976390075Sobrien) 976490075Sobrien 976590075Sobrien(define_expand "eh_epilogue" 9766132718Skan [(use (match_operand:SI 0 "register_operand" "")) 9767132718Skan (use (match_operand:SI 1 "register_operand" "")) 9768132718Skan (use (match_operand:SI 2 "register_operand" ""))] 976990075Sobrien "TARGET_EITHER" 977090075Sobrien " 977190075Sobrien { 977290075Sobrien cfun->machine->eh_epilogue_sp_ofs = operands[1]; 977390075Sobrien if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2) 977490075Sobrien { 977590075Sobrien rtx ra = gen_rtx_REG (Pmode, 2); 977690075Sobrien 977790075Sobrien emit_move_insn (ra, operands[2]); 977890075Sobrien operands[2] = ra; 977990075Sobrien } 978090075Sobrien /* This is a hack -- we may have crystalized the function type too 978190075Sobrien early. */ 978290075Sobrien cfun->machine->func_type = 0; 978390075Sobrien }" 978490075Sobrien) 978590075Sobrien 978690075Sobrien;; This split is only used during output to reduce the number of patterns 978790075Sobrien;; that need assembler instructions adding to them. We allowed the setting 978890075Sobrien;; of the conditions to be implicit during rtl generation so that 978990075Sobrien;; the conditional compare patterns would work. However this conflicts to 979090075Sobrien;; some extent with the conditional data operations, so we have to split them 979190075Sobrien;; up again here. 979290075Sobrien 979390075Sobrien(define_split 979490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 979590075Sobrien (if_then_else:SI (match_operator 1 "arm_comparison_operator" 979690075Sobrien [(match_operand 2 "" "") (match_operand 3 "" "")]) 979790075Sobrien (match_dup 0) 979890075Sobrien (match_operand 4 "" ""))) 979990075Sobrien (clobber (reg:CC CC_REGNUM))] 980090075Sobrien "TARGET_ARM && reload_completed" 980190075Sobrien [(set (match_dup 5) (match_dup 6)) 980290075Sobrien (cond_exec (match_dup 7) 980390075Sobrien (set (match_dup 0) (match_dup 4)))] 980490075Sobrien " 980590075Sobrien { 980690075Sobrien enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 980790075Sobrien operands[2], operands[3]); 980890075Sobrien enum rtx_code rc = GET_CODE (operands[1]); 980990075Sobrien 981090075Sobrien operands[5] = gen_rtx_REG (mode, CC_REGNUM); 981190075Sobrien operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 981290075Sobrien if (mode == CCFPmode || mode == CCFPEmode) 981390075Sobrien rc = reverse_condition_maybe_unordered (rc); 981490075Sobrien else 981590075Sobrien rc = reverse_condition (rc); 981690075Sobrien 981790075Sobrien operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx); 981890075Sobrien }" 981990075Sobrien) 982090075Sobrien 982190075Sobrien(define_split 982290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 982390075Sobrien (if_then_else:SI (match_operator 1 "arm_comparison_operator" 982490075Sobrien [(match_operand 2 "" "") (match_operand 3 "" "")]) 982590075Sobrien (match_operand 4 "" "") 982690075Sobrien (match_dup 0))) 982790075Sobrien (clobber (reg:CC CC_REGNUM))] 982890075Sobrien "TARGET_ARM && reload_completed" 982990075Sobrien [(set (match_dup 5) (match_dup 6)) 983090075Sobrien (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)]) 983190075Sobrien (set (match_dup 0) (match_dup 4)))] 983290075Sobrien " 983390075Sobrien { 983490075Sobrien enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 983590075Sobrien operands[2], operands[3]); 983690075Sobrien 983790075Sobrien operands[5] = gen_rtx_REG (mode, CC_REGNUM); 983890075Sobrien operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 983990075Sobrien }" 984090075Sobrien) 984190075Sobrien 984290075Sobrien(define_split 984390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 984490075Sobrien (if_then_else:SI (match_operator 1 "arm_comparison_operator" 984590075Sobrien [(match_operand 2 "" "") (match_operand 3 "" "")]) 984690075Sobrien (match_operand 4 "" "") 984790075Sobrien (match_operand 5 "" ""))) 984890075Sobrien (clobber (reg:CC CC_REGNUM))] 984990075Sobrien "TARGET_ARM && reload_completed" 985090075Sobrien [(set (match_dup 6) (match_dup 7)) 985190075Sobrien (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 985290075Sobrien (set (match_dup 0) (match_dup 4))) 985390075Sobrien (cond_exec (match_dup 8) 985490075Sobrien (set (match_dup 0) (match_dup 5)))] 985590075Sobrien " 985690075Sobrien { 985790075Sobrien enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 985890075Sobrien operands[2], operands[3]); 985990075Sobrien enum rtx_code rc = GET_CODE (operands[1]); 986090075Sobrien 986190075Sobrien operands[6] = gen_rtx_REG (mode, CC_REGNUM); 986290075Sobrien operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 986390075Sobrien if (mode == CCFPmode || mode == CCFPEmode) 986490075Sobrien rc = reverse_condition_maybe_unordered (rc); 986590075Sobrien else 986690075Sobrien rc = reverse_condition (rc); 986790075Sobrien 986890075Sobrien operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 986990075Sobrien }" 987090075Sobrien) 987190075Sobrien 987290075Sobrien(define_split 987390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 987490075Sobrien (if_then_else:SI (match_operator 1 "arm_comparison_operator" 987590075Sobrien [(match_operand:SI 2 "s_register_operand" "") 987690075Sobrien (match_operand:SI 3 "arm_add_operand" "")]) 987790075Sobrien (match_operand:SI 4 "arm_rhs_operand" "") 987890075Sobrien (not:SI 987990075Sobrien (match_operand:SI 5 "s_register_operand" "")))) 988090075Sobrien (clobber (reg:CC CC_REGNUM))] 988190075Sobrien "TARGET_ARM && reload_completed" 988290075Sobrien [(set (match_dup 6) (match_dup 7)) 988390075Sobrien (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 988490075Sobrien (set (match_dup 0) (match_dup 4))) 988590075Sobrien (cond_exec (match_dup 8) 988690075Sobrien (set (match_dup 0) (not:SI (match_dup 5))))] 988790075Sobrien " 988890075Sobrien { 988990075Sobrien enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 989090075Sobrien operands[2], operands[3]); 989190075Sobrien enum rtx_code rc = GET_CODE (operands[1]); 989290075Sobrien 989390075Sobrien operands[6] = gen_rtx_REG (mode, CC_REGNUM); 9894169689Skan operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 989590075Sobrien if (mode == CCFPmode || mode == CCFPEmode) 989690075Sobrien rc = reverse_condition_maybe_unordered (rc); 989790075Sobrien else 989890075Sobrien rc = reverse_condition (rc); 989990075Sobrien 990090075Sobrien operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 990190075Sobrien }" 990290075Sobrien) 990390075Sobrien 990490075Sobrien(define_insn "*cond_move_not" 990590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 990690075Sobrien (if_then_else:SI (match_operator 4 "arm_comparison_operator" 990790075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 990890075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 990990075Sobrien (not:SI 991090075Sobrien (match_operand:SI 2 "s_register_operand" "r,r"))))] 991190075Sobrien "TARGET_ARM" 991290075Sobrien "@ 991390075Sobrien mvn%D4\\t%0, %2 991490075Sobrien mov%d4\\t%0, %1\;mvn%D4\\t%0, %2" 991590075Sobrien [(set_attr "conds" "use") 991690075Sobrien (set_attr "length" "4,8")] 991790075Sobrien) 991890075Sobrien 991990075Sobrien;; The next two patterns occur when an AND operation is followed by a 992090075Sobrien;; scc insn sequence 992190075Sobrien 992290075Sobrien(define_insn "*sign_extract_onebit" 992390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 992490075Sobrien (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 992590075Sobrien (const_int 1) 9926104752Skan (match_operand:SI 2 "const_int_operand" "n"))) 9927104752Skan (clobber (reg:CC CC_REGNUM))] 992890075Sobrien "TARGET_ARM" 992990075Sobrien "* 993090075Sobrien operands[2] = GEN_INT (1 << INTVAL (operands[2])); 993190075Sobrien output_asm_insn (\"ands\\t%0, %1, %2\", operands); 993290075Sobrien return \"mvnne\\t%0, #0\"; 993390075Sobrien " 993490075Sobrien [(set_attr "conds" "clob") 993590075Sobrien (set_attr "length" "8")] 993690075Sobrien) 993790075Sobrien 993890075Sobrien(define_insn "*not_signextract_onebit" 993990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 994090075Sobrien (not:SI 994190075Sobrien (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 994290075Sobrien (const_int 1) 9943104752Skan (match_operand:SI 2 "const_int_operand" "n")))) 9944104752Skan (clobber (reg:CC CC_REGNUM))] 994590075Sobrien "TARGET_ARM" 994690075Sobrien "* 994790075Sobrien operands[2] = GEN_INT (1 << INTVAL (operands[2])); 994890075Sobrien output_asm_insn (\"tst\\t%1, %2\", operands); 994990075Sobrien output_asm_insn (\"mvneq\\t%0, #0\", operands); 995090075Sobrien return \"movne\\t%0, #0\"; 995190075Sobrien " 995290075Sobrien [(set_attr "conds" "clob") 995390075Sobrien (set_attr "length" "12")] 995490075Sobrien) 995590075Sobrien 995690075Sobrien;; Push multiple registers to the stack. Registers are in parallel (use ...) 995790075Sobrien;; expressions. For simplicity, the first register is also in the unspec 995890075Sobrien;; part. 995990075Sobrien(define_insn "*push_multi" 996090075Sobrien [(match_parallel 2 "multi_register_push" 996190075Sobrien [(set (match_operand:BLK 0 "memory_operand" "=m") 996290075Sobrien (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 996390075Sobrien UNSPEC_PUSH_MULT))])] 996490075Sobrien "TARGET_ARM" 996590075Sobrien "* 996690075Sobrien { 996790075Sobrien int num_saves = XVECLEN (operands[2], 0); 996890075Sobrien 996990075Sobrien /* For the StrongARM at least it is faster to 997090075Sobrien use STR to store only a single register. */ 997190075Sobrien if (num_saves == 1) 997290075Sobrien output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands); 997390075Sobrien else 997490075Sobrien { 997590075Sobrien int i; 997690075Sobrien char pattern[100]; 997790075Sobrien 997890075Sobrien strcpy (pattern, \"stmfd\\t%m0!, {%1\"); 997990075Sobrien 998090075Sobrien for (i = 1; i < num_saves; i++) 998190075Sobrien { 998290075Sobrien strcat (pattern, \", %|\"); 998390075Sobrien strcat (pattern, 998490075Sobrien reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]); 998590075Sobrien } 998690075Sobrien 998790075Sobrien strcat (pattern, \"}\"); 998890075Sobrien output_asm_insn (pattern, operands); 998990075Sobrien } 999090075Sobrien 999190075Sobrien return \"\"; 999290075Sobrien }" 999390075Sobrien [(set_attr "type" "store4")] 999490075Sobrien) 999590075Sobrien 9996117395Skan(define_insn "stack_tie" 9997117395Skan [(set (mem:BLK (scratch)) 9998117395Skan (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r") 9999117395Skan (match_operand:SI 1 "s_register_operand" "r")] 10000117395Skan UNSPEC_PRLG_STK))] 10001117395Skan "" 10002117395Skan "" 10003117395Skan [(set_attr "length" "0")] 10004117395Skan) 10005117395Skan 1000690075Sobrien;; Similarly for the floating point registers 1000790075Sobrien(define_insn "*push_fp_multi" 1000890075Sobrien [(match_parallel 2 "multi_register_push" 1000990075Sobrien [(set (match_operand:BLK 0 "memory_operand" "=m") 1001090075Sobrien (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 1001190075Sobrien UNSPEC_PUSH_MULT))])] 10012169689Skan "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA" 1001390075Sobrien "* 1001490075Sobrien { 1001590075Sobrien char pattern[100]; 1001690075Sobrien 1001790075Sobrien sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0)); 1001890075Sobrien output_asm_insn (pattern, operands); 1001990075Sobrien return \"\"; 1002090075Sobrien }" 1002190075Sobrien [(set_attr "type" "f_store")] 1002290075Sobrien) 1002390075Sobrien 1002490075Sobrien;; Special patterns for dealing with the constant pool 1002590075Sobrien 1002690075Sobrien(define_insn "align_4" 1002790075Sobrien [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)] 1002890075Sobrien "TARGET_EITHER" 1002990075Sobrien "* 1003090075Sobrien assemble_align (32); 1003190075Sobrien return \"\"; 1003290075Sobrien " 1003390075Sobrien) 1003490075Sobrien 10035132718Skan(define_insn "align_8" 10036132718Skan [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)] 10037169689Skan "TARGET_EITHER" 10038132718Skan "* 10039132718Skan assemble_align (64); 10040132718Skan return \"\"; 10041132718Skan " 10042132718Skan) 10043132718Skan 1004490075Sobrien(define_insn "consttable_end" 1004590075Sobrien [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)] 1004690075Sobrien "TARGET_EITHER" 1004790075Sobrien "* 1004890075Sobrien making_const_table = FALSE; 1004990075Sobrien return \"\"; 1005090075Sobrien " 1005190075Sobrien) 1005290075Sobrien 1005390075Sobrien(define_insn "consttable_1" 1005490075Sobrien [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)] 1005590075Sobrien "TARGET_THUMB" 1005690075Sobrien "* 1005790075Sobrien making_const_table = TRUE; 1005890075Sobrien assemble_integer (operands[0], 1, BITS_PER_WORD, 1); 1005990075Sobrien assemble_zeros (3); 1006090075Sobrien return \"\"; 1006190075Sobrien " 1006290075Sobrien [(set_attr "length" "4")] 1006390075Sobrien) 1006490075Sobrien 1006590075Sobrien(define_insn "consttable_2" 1006690075Sobrien [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)] 1006790075Sobrien "TARGET_THUMB" 1006890075Sobrien "* 1006990075Sobrien making_const_table = TRUE; 1007090075Sobrien assemble_integer (operands[0], 2, BITS_PER_WORD, 1); 1007190075Sobrien assemble_zeros (2); 1007290075Sobrien return \"\"; 1007390075Sobrien " 1007490075Sobrien [(set_attr "length" "4")] 1007590075Sobrien) 1007690075Sobrien 1007790075Sobrien(define_insn "consttable_4" 1007890075Sobrien [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)] 1007990075Sobrien "TARGET_EITHER" 1008090075Sobrien "* 1008190075Sobrien { 1008290075Sobrien making_const_table = TRUE; 1008390075Sobrien switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 1008490075Sobrien { 1008590075Sobrien case MODE_FLOAT: 1008690075Sobrien { 10087117395Skan REAL_VALUE_TYPE r; 10088117395Skan REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 10089117395Skan assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 1009090075Sobrien break; 1009190075Sobrien } 1009290075Sobrien default: 1009390075Sobrien assemble_integer (operands[0], 4, BITS_PER_WORD, 1); 1009490075Sobrien break; 1009590075Sobrien } 1009690075Sobrien return \"\"; 1009790075Sobrien }" 1009890075Sobrien [(set_attr "length" "4")] 1009990075Sobrien) 1010090075Sobrien 1010190075Sobrien(define_insn "consttable_8" 1010290075Sobrien [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)] 1010390075Sobrien "TARGET_EITHER" 1010490075Sobrien "* 1010590075Sobrien { 1010690075Sobrien making_const_table = TRUE; 1010790075Sobrien switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 1010890075Sobrien { 1010990075Sobrien case MODE_FLOAT: 1011090075Sobrien { 10111117395Skan REAL_VALUE_TYPE r; 10112117395Skan REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 10113117395Skan assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 1011490075Sobrien break; 1011590075Sobrien } 1011690075Sobrien default: 1011790075Sobrien assemble_integer (operands[0], 8, BITS_PER_WORD, 1); 1011890075Sobrien break; 1011990075Sobrien } 1012090075Sobrien return \"\"; 1012190075Sobrien }" 1012290075Sobrien [(set_attr "length" "8")] 1012390075Sobrien) 1012490075Sobrien 1012590075Sobrien;; Miscellaneous Thumb patterns 1012690075Sobrien 1012796263Sobrien(define_expand "tablejump" 10128132718Skan [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "")) 1012996263Sobrien (use (label_ref (match_operand 1 "" "")))])] 1013096263Sobrien "TARGET_THUMB" 1013196263Sobrien " 1013296263Sobrien if (flag_pic) 1013396263Sobrien { 1013496263Sobrien /* Hopefully, CSE will eliminate this copy. */ 1013596263Sobrien rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); 1013696263Sobrien rtx reg2 = gen_reg_rtx (SImode); 1013796263Sobrien 1013896263Sobrien emit_insn (gen_addsi3 (reg2, operands[0], reg1)); 1013996263Sobrien operands[0] = reg2; 1014096263Sobrien } 1014196263Sobrien " 1014296263Sobrien) 1014396263Sobrien 10144169689Skan;; NB never uses BX. 1014596263Sobrien(define_insn "*thumb_tablejump" 1014690075Sobrien [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 1014790075Sobrien (use (label_ref (match_operand 1 "" "")))] 1014890075Sobrien "TARGET_THUMB" 1014996263Sobrien "mov\\t%|pc, %0" 1015090075Sobrien [(set_attr "length" "2")] 1015190075Sobrien) 1015290075Sobrien 1015390075Sobrien;; V5 Instructions, 1015490075Sobrien 10155132718Skan(define_insn "clzsi2" 10156132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 10157132718Skan (clz:SI (match_operand:SI 1 "s_register_operand" "r")))] 1015890075Sobrien "TARGET_ARM && arm_arch5" 10159132718Skan "clz%?\\t%0, %1" 10160132718Skan [(set_attr "predicable" "yes")]) 1016190075Sobrien 1016290075Sobrien(define_expand "ffssi2" 1016390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 1016490075Sobrien (ffs:SI (match_operand:SI 1 "s_register_operand" "")))] 1016590075Sobrien "TARGET_ARM && arm_arch5" 1016690075Sobrien " 1016790075Sobrien { 1016890075Sobrien rtx t1, t2, t3; 1016990075Sobrien 1017090075Sobrien t1 = gen_reg_rtx (SImode); 1017190075Sobrien t2 = gen_reg_rtx (SImode); 1017290075Sobrien t3 = gen_reg_rtx (SImode); 1017390075Sobrien 1017490075Sobrien emit_insn (gen_negsi2 (t1, operands[1])); 1017590075Sobrien emit_insn (gen_andsi3 (t2, operands[1], t1)); 10176132718Skan emit_insn (gen_clzsi2 (t3, t2)); 1017790075Sobrien emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3)); 1017890075Sobrien DONE; 1017990075Sobrien }" 1018090075Sobrien) 1018190075Sobrien 10182132718Skan(define_expand "ctzsi2" 10183132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 10184132718Skan (ctz:SI (match_operand:SI 1 "s_register_operand" "")))] 10185132718Skan "TARGET_ARM && arm_arch5" 10186132718Skan " 10187132718Skan { 10188132718Skan rtx t1, t2, t3; 10189132718Skan 10190132718Skan t1 = gen_reg_rtx (SImode); 10191132718Skan t2 = gen_reg_rtx (SImode); 10192132718Skan t3 = gen_reg_rtx (SImode); 10193132718Skan 10194132718Skan emit_insn (gen_negsi2 (t1, operands[1])); 10195132718Skan emit_insn (gen_andsi3 (t2, operands[1], t1)); 10196132718Skan emit_insn (gen_clzsi2 (t3, t2)); 10197132718Skan emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3)); 10198132718Skan DONE; 10199132718Skan }" 10200132718Skan) 10201132718Skan 1020290075Sobrien;; V5E instructions. 1020390075Sobrien 1020490075Sobrien(define_insn "prefetch" 1020590075Sobrien [(prefetch (match_operand:SI 0 "address_operand" "p") 1020690075Sobrien (match_operand:SI 1 "" "") 1020790075Sobrien (match_operand:SI 2 "" ""))] 1020890075Sobrien "TARGET_ARM && arm_arch5e" 1020990075Sobrien "pld\\t%a0") 1021090075Sobrien 1021190075Sobrien;; General predication pattern 1021290075Sobrien 1021390075Sobrien(define_cond_exec 1021490075Sobrien [(match_operator 0 "arm_comparison_operator" 1021590075Sobrien [(match_operand 1 "cc_register" "") 1021690075Sobrien (const_int 0)])] 1021790075Sobrien "TARGET_ARM" 1021890075Sobrien "" 1021990075Sobrien) 1022090075Sobrien 1022190075Sobrien(define_insn "prologue_use" 1022290075Sobrien [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)] 1022390075Sobrien "" 1022490075Sobrien "%@ %0 needed for prologue" 1022590075Sobrien) 10226132718Skan 10227169689Skan 10228169689Skan;; Patterns for exception handling 10229169689Skan 10230169689Skan(define_expand "eh_return" 10231169689Skan [(use (match_operand 0 "general_operand" ""))] 10232169689Skan "TARGET_EITHER" 10233169689Skan " 10234169689Skan { 10235169689Skan if (TARGET_ARM) 10236169689Skan emit_insn (gen_arm_eh_return (operands[0])); 10237169689Skan else 10238169689Skan emit_insn (gen_thumb_eh_return (operands[0])); 10239169689Skan DONE; 10240169689Skan }" 10241169689Skan) 10242169689Skan 10243169689Skan;; We can't expand this before we know where the link register is stored. 10244169689Skan(define_insn_and_split "arm_eh_return" 10245169689Skan [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")] 10246169689Skan VUNSPEC_EH_RETURN) 10247169689Skan (clobber (match_scratch:SI 1 "=&r"))] 10248169689Skan "TARGET_ARM" 10249169689Skan "#" 10250169689Skan "&& reload_completed" 10251169689Skan [(const_int 0)] 10252169689Skan " 10253169689Skan { 10254169689Skan arm_set_return_address (operands[0], operands[1]); 10255169689Skan DONE; 10256169689Skan }" 10257169689Skan) 10258169689Skan 10259169689Skan(define_insn_and_split "thumb_eh_return" 10260169689Skan [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")] 10261169689Skan VUNSPEC_EH_RETURN) 10262169689Skan (clobber (match_scratch:SI 1 "=&l"))] 10263169689Skan "TARGET_THUMB" 10264169689Skan "#" 10265169689Skan "&& reload_completed" 10266169689Skan [(const_int 0)] 10267169689Skan " 10268169689Skan { 10269169689Skan thumb_set_return_address (operands[0], operands[1]); 10270169689Skan DONE; 10271169689Skan }" 10272169689Skan) 10273169689Skan 10274169689Skan 10275169689Skan;; TLS support 10276169689Skan 10277169689Skan(define_insn "load_tp_hard" 10278169689Skan [(set (match_operand:SI 0 "register_operand" "=r") 10279169689Skan (unspec:SI [(const_int 0)] UNSPEC_TLS))] 10280169689Skan "TARGET_HARD_TP" 10281169689Skan "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard" 10282169689Skan [(set_attr "predicable" "yes")] 10283169689Skan) 10284169689Skan 10285169689Skan;; Doesn't clobber R1-R3. Must use r0 for the first operand. 10286169689Skan(define_insn "load_tp_soft" 10287169689Skan [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS)) 10288169689Skan (clobber (reg:SI LR_REGNUM)) 10289169689Skan (clobber (reg:SI IP_REGNUM)) 10290169689Skan (clobber (reg:CC CC_REGNUM))] 10291169689Skan "TARGET_SOFT_TP" 10292169689Skan "bl\\t__aeabi_read_tp\\t@ load_tp_soft" 10293169689Skan [(set_attr "conds" "clob")] 10294169689Skan) 10295169689Skan 10296132718Skan;; Load the FPA co-processor patterns 10297132718Skan(include "fpa.md") 10298132718Skan;; Load the Maverick co-processor patterns 10299132718Skan(include "cirrus.md") 10300132718Skan;; Load the Intel Wireless Multimedia Extension patterns 10301132718Skan(include "iwmmxt.md") 10302169689Skan;; Load the VFP co-processor patterns 10303169689Skan(include "vfp.md") 10304169689Skan 10305