arm.md revision 132718
190075Sobrien;;- Machine description for ARM for GNU compiler 290075Sobrien;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000, 3132718Skan;; 2001, 2002, 2003 2004 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 2290075Sobrien;; the Free Software Foundation, 59 Temple Place - Suite 330, 2390075Sobrien;; Boston, MA 02111-1307, 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 3390075Sobrien [(IP_REGNUM 12) ; Scratch register 3490075Sobrien (SP_REGNUM 13) ; Stack pointer 3590075Sobrien (LR_REGNUM 14) ; Return address register 3690075Sobrien (PC_REGNUM 15) ; Program counter 3790075Sobrien (CC_REGNUM 24) ; Condition code pseudo register 3890075Sobrien (LAST_ARM_REGNUM 15) 3990075Sobrien ] 4090075Sobrien) 41132718Skan;; 3rd operand to select_dominance_cc_mode 42132718Skan(define_constants 43132718Skan [(DOM_CC_X_AND_Y 0) 44132718Skan (DOM_CC_NX_OR_Y 1) 45132718Skan (DOM_CC_X_OR_Y 2) 46132718Skan ] 47132718Skan) 4890075Sobrien 4990075Sobrien;; UNSPEC Usage: 5090075Sobrien;; Note: sin and cos are no-longer used. 5190075Sobrien 5290075Sobrien(define_constants 5390075Sobrien [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT): 5490075Sobrien ; operand 0 is the result, 5590075Sobrien ; operand 1 the parameter. 5690075Sobrien (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT): 5790075Sobrien ; operand 0 is the result, 5890075Sobrien ; operand 1 the parameter. 5990075Sobrien (UNSPEC_PUSH_MULT 2) ; `push multiple' operation: 6090075Sobrien ; operand 0 is the first register, 6190075Sobrien ; subsequent registers are in parallel (use ...) 6290075Sobrien ; expressions. 6390075Sobrien (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic 6490075Sobrien ; usage, that is, we will add the pic_register 6590075Sobrien ; value to it before trying to dereference it. 66117395Skan (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the 67117395Skan ; GLOBAL_OFFSET_TABLE. The operation is fully 68117395Skan ; described by the RTL but must be wrapped to 69117395Skan ; prevent combine from trying to rip it apart. 70117395Skan (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses 7190075Sobrien ; being scheduled before the stack adjustment insn. 7290075Sobrien (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload, 7390075Sobrien ; this unspec is used to prevent the deletion of 7490075Sobrien ; instructions setting registers for EH handling 7590075Sobrien ; and stack frame generation. Operand 0 is the 7690075Sobrien ; register to "use". 77117395Skan (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode. 78132718Skan (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction. 79132718Skan (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction. 80132718Skan (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction. 81132718Skan (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction. 82132718Skan (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction. 83132718Skan (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction. 84132718Skan (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction. 85132718Skan (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction. 86132718Skan (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction. 87132718Skan (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction. 88132718Skan (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction. 89132718Skan (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction. 9090075Sobrien ] 9190075Sobrien) 9290075Sobrien 9390075Sobrien;; UNSPEC_VOLATILE Usage: 9490075Sobrien 9590075Sobrien(define_constants 9690075Sobrien [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an 9790075Sobrien ; insn in the code. 9890075Sobrien (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the 9990075Sobrien ; instruction epilogue sequence that isn't expanded 10090075Sobrien ; into normal RTL. Used for both normal and sibcall 10190075Sobrien ; epilogues. 10290075Sobrien (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table 10390075Sobrien ; for inlined constants. 10490075Sobrien (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool 10590075Sobrien ; table. 10690075Sobrien (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for 10790075Sobrien ; an 8-bit object. 10890075Sobrien (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for 10990075Sobrien ; a 16-bit object. 11090075Sobrien (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for 11190075Sobrien ; a 32-bit object. 11290075Sobrien (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for 11390075Sobrien ; a 64-bit object. 114132718Skan (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction. 115132718Skan (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction. 116132718Skan (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN 117132718Skan (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions 118132718Skan (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions 119132718Skan (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions 12090075Sobrien ] 12190075Sobrien) 12290075Sobrien 12390075Sobrien;;--------------------------------------------------------------------------- 12490075Sobrien;; Attributes 12590075Sobrien 12690075Sobrien; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when 12790075Sobrien; generating ARM code. This is used to control the length of some insn 12890075Sobrien; patterns that share the same RTL in both ARM and Thumb code. 12990075Sobrien(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) 13090075Sobrien 13190075Sobrien; PROG_MODE attribute is used to determine whether condition codes are 13290075Sobrien; clobbered by a call insn: they are if in prog32 mode. This is controlled 13390075Sobrien; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option. 13490075Sobrien(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode"))) 13590075Sobrien 13690075Sobrien; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects 13790075Sobrien; scheduling decisions for the load unit and the multiplier. 13890075Sobrien(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong"))) 13990075Sobrien 14090075Sobrien;; Operand number of an input operand that is shifted. Zero if the 14190075Sobrien;; given instruction does not shift one of its input operands. 142132718Skan(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale"))) 14390075Sobrien(define_attr "shift" "" (const_int 0)) 14490075Sobrien 14590075Sobrien; Floating Point Unit. If we only have floating point emulation, then there 14690075Sobrien; is no point in scheduling the floating point insns. (Well, for best 14790075Sobrien; performance we should try and group them together). 148132718Skan(define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick" 149132718Skan (const (symbol_ref "arm_fpu_attr"))) 15090075Sobrien 15190075Sobrien; LENGTH of an instruction (in bytes) 15290075Sobrien(define_attr "length" "" (const_int 4)) 15390075Sobrien 15490075Sobrien; POOL_RANGE is how far away from a constant pool entry that this insn 15590075Sobrien; can be placed. If the distance is zero, then this insn will never 15690075Sobrien; reference the pool. 15790075Sobrien; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry 15890075Sobrien; before its address. 15990075Sobrien(define_attr "pool_range" "" (const_int 0)) 16090075Sobrien(define_attr "neg_pool_range" "" (const_int 0)) 16190075Sobrien 16290075Sobrien; An assembler sequence may clobber the condition codes without us knowing. 16396263Sobrien; If such an insn references the pool, then we have no way of knowing how, 16496263Sobrien; so use the most conservative value for pool_range. 16590075Sobrien(define_asm_attributes 16696263Sobrien [(set_attr "conds" "clob") 16796263Sobrien (set_attr "length" "4") 16896263Sobrien (set_attr "pool_range" "250")]) 16990075Sobrien 17090075Sobrien; TYPE attribute is used to detect floating point instructions which, if 17190075Sobrien; running on a co-processor can run in parallel with other, basic instructions 17290075Sobrien; If write-buffer scheduling is enabled then it can also be used in the 17390075Sobrien; scheduling of writes. 17490075Sobrien 17590075Sobrien; Classification of each insn 17690075Sobrien; normal any data instruction that doesn't hit memory or fp regs 17790075Sobrien; mult a multiply instruction 17890075Sobrien; block blockage insn, this blocks all functional units 17990075Sobrien; float a floating point arithmetic operation (subject to expansion) 18090075Sobrien; fdivd DFmode floating point division 18190075Sobrien; fdivs SFmode floating point division 18290075Sobrien; fmul Floating point multiply 18390075Sobrien; ffmul Fast floating point multiply 18490075Sobrien; farith Floating point arithmetic (4 cycle) 18590075Sobrien; ffarith Fast floating point arithmetic (2 cycle) 18690075Sobrien; float_em a floating point arithmetic operation that is normally emulated 18790075Sobrien; even on a machine with an fpa. 18890075Sobrien; f_load a floating point load from memory 18990075Sobrien; f_store a floating point store to memory 19090075Sobrien; f_mem_r a transfer of a floating point register to a real reg via mem 19190075Sobrien; r_mem_f the reverse of f_mem_r 19290075Sobrien; f_2_r fast transfer float to arm (no memory needed) 19390075Sobrien; r_2_f fast transfer arm to float 19490075Sobrien; call a subroutine call 19590075Sobrien; load any load from memory 19690075Sobrien; store1 store 1 word to memory from arm registers 19790075Sobrien; store2 store 2 words 19890075Sobrien; store3 store 3 words 19990075Sobrien; store4 store 4 words 200132718Skan; Additions for Cirrus Maverick co-processor: 201132718Skan; mav_farith Floating point arithmetic (4 cycle) 202132718Skan; mav_dmult Double multiplies (7 cycle) 20390075Sobrien; 20490075Sobrien(define_attr "type" 205132718Skan "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult" 20690075Sobrien (const_string "normal")) 20790075Sobrien 20890075Sobrien; Load scheduling, set from the arm_ld_sched variable 209117395Skan; initialized by arm_override_options() 21090075Sobrien(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched"))) 21190075Sobrien 21290075Sobrien; condition codes: this one is used by final_prescan_insn to speed up 21390075Sobrien; conditionalizing instructions. It saves having to scan the rtl to see if 21490075Sobrien; it uses or alters the condition codes. 21590075Sobrien; 21690075Sobrien; USE means that the condition codes are used by the insn in the process of 21790075Sobrien; outputting code, this means (at present) that we can't use the insn in 21890075Sobrien; inlined branches 21990075Sobrien; 22090075Sobrien; SET means that the purpose of the insn is to set the condition codes in a 22190075Sobrien; well defined manner. 22290075Sobrien; 22390075Sobrien; CLOB means that the condition codes are altered in an undefined manner, if 22490075Sobrien; they are altered at all 22590075Sobrien; 22690075Sobrien; JUMP_CLOB is used when the condition cannot be represented by a single 22790075Sobrien; instruction (UNEQ and LTGT). These cannot be predicated. 22890075Sobrien; 22990075Sobrien; NOCOND means that the condition codes are neither altered nor affect the 23090075Sobrien; output of this insn 23190075Sobrien 23290075Sobrien(define_attr "conds" "use,set,clob,jump_clob,nocond" 23390075Sobrien (if_then_else (eq_attr "type" "call") 23490075Sobrien (if_then_else (eq_attr "prog_mode" "prog32") 23590075Sobrien (const_string "clob") (const_string "nocond")) 23690075Sobrien (const_string "nocond"))) 23790075Sobrien 23890075Sobrien; Predicable means that the insn can be conditionally executed based on 23990075Sobrien; an automatically added predicate (additional patterns are generated by 24090075Sobrien; gen...). We default to 'no' because no Thumb patterns match this rule 24190075Sobrien; and not all ARM patterns do. 24290075Sobrien(define_attr "predicable" "no,yes" (const_string "no")) 24390075Sobrien 24490075Sobrien; Only model the write buffer for ARM6 and ARM7. Earlier processors don't 24590075Sobrien; have one. Later ones, such as StrongARM, have write-back caches, so don't 246132718Skan; suffer blockages enough to warrant modelling this (and it can adversely 24790075Sobrien; affect the schedule). 24890075Sobrien(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7"))) 24990075Sobrien 25090075Sobrien; WRITE_CONFLICT implies that a read following an unrelated write is likely 25190075Sobrien; to stall the processor. Used with model_wbuf above. 25290075Sobrien(define_attr "write_conflict" "no,yes" 25390075Sobrien (if_then_else (eq_attr "type" 25490075Sobrien "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load") 25590075Sobrien (const_string "yes") 25690075Sobrien (const_string "no"))) 25790075Sobrien 25890075Sobrien; Classify the insns into those that take one cycle and those that take more 25990075Sobrien; than one on the main cpu execution unit. 26090075Sobrien(define_attr "core_cycles" "single,multi" 26190075Sobrien (if_then_else (eq_attr "type" 26290075Sobrien "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith") 26390075Sobrien (const_string "single") 26490075Sobrien (const_string "multi"))) 26590075Sobrien 26690075Sobrien;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a 26790075Sobrien;; distant label. Only applicable to Thumb code. 26890075Sobrien(define_attr "far_jump" "yes,no" (const_string "no")) 26990075Sobrien 270132718Skan(define_automaton "arm") 27190075Sobrien 27290075Sobrien;; Write buffer 273132718Skan; 27490075Sobrien; Strictly, we should model a 4-deep write buffer for ARM7xx based chips 27590075Sobrien; 27690075Sobrien; The write buffer on some of the arm6 processors is hard to model exactly. 27790075Sobrien; There is room in the buffer for up to two addresses and up to eight words 27890075Sobrien; of memory, but the two needn't be split evenly. When writing the two 27990075Sobrien; addresses are fully pipelined. However, a read from memory that is not 28090075Sobrien; currently in the cache will block until the writes have completed. 28190075Sobrien; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so 28290075Sobrien; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous 28390075Sobrien; (they aren't allowed to be at present) then there is a startup cost of 1MCLK 28490075Sobrien; cycle to add as well. 285132718Skan(define_cpu_unit "write_buf" "arm") 28690075Sobrien 28790075Sobrien;; Write blockage unit 288132718Skan; 28990075Sobrien; The write_blockage unit models (partially), the fact that reads will stall 29090075Sobrien; until the write buffer empties. 29190075Sobrien; The f_mem_r and r_mem_f could also block, but they are to the stack, 29290075Sobrien; so we don't model them here 293132718Skan(define_cpu_unit "write_blockage" "arm") 29490075Sobrien 295132718Skan;; Core 296132718Skan; 297132718Skan(define_cpu_unit "core" "arm") 29890075Sobrien 299132718Skan(define_insn_reservation "r_mem_f_wbuf" 5 300132718Skan (and (eq_attr "model_wbuf" "yes") 301132718Skan (eq_attr "type" "r_mem_f")) 302132718Skan "core+write_buf*3") 30390075Sobrien 304132718Skan(define_insn_reservation "store1_wbuf" 5 305132718Skan (and (eq_attr "model_wbuf" "yes") 306132718Skan (eq_attr "type" "store1")) 307132718Skan "core+write_buf*3+write_blockage*5") 30890075Sobrien 309132718Skan(define_insn_reservation "store2_wbuf" 7 310132718Skan (and (eq_attr "model_wbuf" "yes") 311132718Skan (eq_attr "type" "store2")) 312132718Skan "core+write_buf*4+write_blockage*7") 31390075Sobrien 314132718Skan(define_insn_reservation "store3_wbuf" 9 315132718Skan (and (eq_attr "model_wbuf" "yes") 316132718Skan (eq_attr "type" "store3")) 317132718Skan "core+write_buf*5+write_blockage*9") 31890075Sobrien 319132718Skan(define_insn_reservation "store4_wbuf" 11 320132718Skan (and (eq_attr "model_wbuf" "yes") 321132718Skan (eq_attr "type" "store4")) 322132718Skan "core+write_buf*6+write_blockage*11") 32390075Sobrien 324132718Skan(define_insn_reservation "store2" 3 325132718Skan (and (eq_attr "model_wbuf" "no") 326132718Skan (eq_attr "type" "store2")) 327132718Skan "core*3") 32890075Sobrien 329132718Skan(define_insn_reservation "store3" 4 330132718Skan (and (eq_attr "model_wbuf" "no") 331132718Skan (eq_attr "type" "store3")) 332132718Skan "core*4") 33390075Sobrien 334132718Skan(define_insn_reservation "store4" 5 335132718Skan (and (eq_attr "model_wbuf" "no") 336132718Skan (eq_attr "type" "store4")) 337132718Skan "core*5") 33890075Sobrien 339132718Skan(define_insn_reservation "store1_ldsched" 1 340132718Skan (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 341132718Skan "core") 34290075Sobrien 343132718Skan(define_insn_reservation "load_ldsched_xscale" 3 344132718Skan (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 345132718Skan (eq_attr "is_xscale" "yes")) 346132718Skan "core") 34790075Sobrien 348132718Skan(define_insn_reservation "load_ldsched" 2 349132718Skan (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 350132718Skan (eq_attr "is_xscale" "no")) 351132718Skan "core") 35290075Sobrien 353132718Skan(define_insn_reservation "load_or_store" 2 354132718Skan (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 355132718Skan "core*2") 356132718Skan 357132718Skan(define_insn_reservation "mult" 16 358132718Skan (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 359132718Skan "core*16") 360132718Skan 361132718Skan(define_insn_reservation "mult_ldsched_strongarm" 3 36290075Sobrien (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes")) 363132718Skan (eq_attr "type" "mult")) 364132718Skan "core*2") 36590075Sobrien 366132718Skan(define_insn_reservation "mult_ldsched" 4 367132718Skan (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no")) 368132718Skan (eq_attr "type" "mult")) 369132718Skan "core*4") 37090075Sobrien 371132718Skan(define_insn_reservation "multi_cycle" 32 372132718Skan (and (eq_attr "core_cycles" "multi") 373132718Skan (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 374132718Skan "core*32") 37590075Sobrien 376132718Skan(define_insn_reservation "single_cycle" 1 377132718Skan (eq_attr "core_cycles" "single") 378132718Skan "core") 37990075Sobrien 38090075Sobrien 38190075Sobrien;;--------------------------------------------------------------------------- 38290075Sobrien;; Insn patterns 38390075Sobrien;; 38490075Sobrien;; Addition insns. 38590075Sobrien 38690075Sobrien;; Note: For DImode insns, there is normally no reason why operands should 38790075Sobrien;; not be in the same register, what we don't want is for something being 38890075Sobrien;; written to partially overlap something that is an input. 389132718Skan;; Cirrus 64bit additions should not be split because we have a native 390132718Skan;; 64bit addition instructions. 39190075Sobrien 39290075Sobrien(define_expand "adddi3" 39390075Sobrien [(parallel 39490075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 39590075Sobrien (plus:DI (match_operand:DI 1 "s_register_operand" "") 39690075Sobrien (match_operand:DI 2 "s_register_operand" ""))) 39790075Sobrien (clobber (reg:CC CC_REGNUM))])] 39890075Sobrien "TARGET_EITHER" 39990075Sobrien " 400132718Skan if (TARGET_CIRRUS) 401132718Skan { 402132718Skan if (!cirrus_fp_register (operands[0], DImode)) 403132718Skan operands[0] = force_reg (DImode, operands[0]); 404132718Skan if (!cirrus_fp_register (operands[1], DImode)) 405132718Skan operands[1] = force_reg (DImode, operands[1]); 406132718Skan emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2])); 407132718Skan DONE; 408132718Skan } 409132718Skan 41090075Sobrien if (TARGET_THUMB) 41190075Sobrien { 41290075Sobrien if (GET_CODE (operands[1]) != REG) 41390075Sobrien operands[1] = force_reg (SImode, operands[1]); 41490075Sobrien if (GET_CODE (operands[2]) != REG) 41590075Sobrien operands[2] = force_reg (SImode, operands[2]); 41690075Sobrien } 41790075Sobrien " 41890075Sobrien) 41990075Sobrien 42090075Sobrien(define_insn "*thumb_adddi3" 42190075Sobrien [(set (match_operand:DI 0 "register_operand" "=l") 42290075Sobrien (plus:DI (match_operand:DI 1 "register_operand" "%0") 42390075Sobrien (match_operand:DI 2 "register_operand" "l"))) 42490075Sobrien (clobber (reg:CC CC_REGNUM)) 42590075Sobrien ] 42690075Sobrien "TARGET_THUMB" 42790075Sobrien "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2" 42890075Sobrien [(set_attr "length" "4")] 42990075Sobrien) 43090075Sobrien 43190075Sobrien(define_insn_and_split "*arm_adddi3" 43290075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 43390075Sobrien (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0") 43490075Sobrien (match_operand:DI 2 "s_register_operand" "r, 0"))) 43590075Sobrien (clobber (reg:CC CC_REGNUM))] 436132718Skan "TARGET_ARM && !TARGET_CIRRUS" 43790075Sobrien "#" 43890075Sobrien "TARGET_ARM && reload_completed" 43990075Sobrien [(parallel [(set (reg:CC_C CC_REGNUM) 44090075Sobrien (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 44190075Sobrien (match_dup 1))) 44290075Sobrien (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 44390075Sobrien (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 44490075Sobrien (plus:SI (match_dup 4) (match_dup 5))))] 44590075Sobrien " 44690075Sobrien { 44790075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 44890075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 44990075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 45090075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 45190075Sobrien operands[5] = gen_highpart (SImode, operands[2]); 45290075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 45390075Sobrien }" 45490075Sobrien [(set_attr "conds" "clob") 45590075Sobrien (set_attr "length" "8")] 45690075Sobrien) 45790075Sobrien 45890075Sobrien(define_insn_and_split "*adddi_sesidi_di" 45990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 46090075Sobrien (plus:DI (sign_extend:DI 46190075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 46290075Sobrien (match_operand:DI 1 "s_register_operand" "r,0"))) 46390075Sobrien (clobber (reg:CC CC_REGNUM))] 464132718Skan "TARGET_ARM && !TARGET_CIRRUS" 46590075Sobrien "#" 46690075Sobrien "TARGET_ARM && reload_completed" 46790075Sobrien [(parallel [(set (reg:CC_C CC_REGNUM) 46890075Sobrien (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 46990075Sobrien (match_dup 1))) 47090075Sobrien (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 47190075Sobrien (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 47290075Sobrien (plus:SI (ashiftrt:SI (match_dup 2) 47390075Sobrien (const_int 31)) 47490075Sobrien (match_dup 4))))] 47590075Sobrien " 47690075Sobrien { 47790075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 47890075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 47990075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 48090075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 48190075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 48290075Sobrien }" 48390075Sobrien [(set_attr "conds" "clob") 48490075Sobrien (set_attr "length" "8")] 48590075Sobrien) 48690075Sobrien 48790075Sobrien(define_insn_and_split "*adddi_zesidi_di" 48890075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 48990075Sobrien (plus:DI (zero_extend:DI 49090075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 49190075Sobrien (match_operand:DI 1 "s_register_operand" "r,0"))) 49290075Sobrien (clobber (reg:CC CC_REGNUM))] 493132718Skan "TARGET_ARM && !TARGET_CIRRUS" 49490075Sobrien "#" 49590075Sobrien "TARGET_ARM && reload_completed" 49690075Sobrien [(parallel [(set (reg:CC_C CC_REGNUM) 49790075Sobrien (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) 49890075Sobrien (match_dup 1))) 49990075Sobrien (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) 50090075Sobrien (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 50190075Sobrien (plus:SI (match_dup 4) (const_int 0))))] 50290075Sobrien " 50390075Sobrien { 50490075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 50590075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 50690075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 50790075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 50890075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 50990075Sobrien }" 51090075Sobrien [(set_attr "conds" "clob") 51190075Sobrien (set_attr "length" "8")] 51290075Sobrien) 51390075Sobrien 51490075Sobrien(define_expand "addsi3" 51590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 51690075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "") 51790075Sobrien (match_operand:SI 2 "reg_or_int_operand" "")))] 51890075Sobrien "TARGET_EITHER" 51990075Sobrien " 52090075Sobrien if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT) 52190075Sobrien { 52290075Sobrien arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], 52390075Sobrien operands[1], 52490075Sobrien (no_new_pseudos ? 0 : preserve_subexpressions_p ())); 52590075Sobrien DONE; 52690075Sobrien } 52790075Sobrien " 52890075Sobrien) 52990075Sobrien 530132718Skan; If there is a scratch available, this will be faster than synthesizing the 53190075Sobrien; addition. 53290075Sobrien(define_peephole2 53390075Sobrien [(match_scratch:SI 3 "r") 53490075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 53590075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "") 53690075Sobrien (match_operand:SI 2 "const_int_operand" "")))] 53790075Sobrien "TARGET_ARM && 53890075Sobrien !(const_ok_for_arm (INTVAL (operands[2])) 53990075Sobrien || const_ok_for_arm (-INTVAL (operands[2]))) 54090075Sobrien && const_ok_for_arm (~INTVAL (operands[2]))" 54190075Sobrien [(set (match_dup 3) (match_dup 2)) 54290075Sobrien (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))] 54390075Sobrien "" 54490075Sobrien) 54590075Sobrien 54690075Sobrien(define_insn_and_split "*arm_addsi3" 54790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 54890075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r") 54990075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))] 55090075Sobrien "TARGET_ARM" 55190075Sobrien "@ 55290075Sobrien add%?\\t%0, %1, %2 55390075Sobrien sub%?\\t%0, %1, #%n2 55490075Sobrien #" 55590075Sobrien "TARGET_ARM && 55690075Sobrien GET_CODE (operands[2]) == CONST_INT 55790075Sobrien && !(const_ok_for_arm (INTVAL (operands[2])) 55890075Sobrien || const_ok_for_arm (-INTVAL (operands[2])))" 55990075Sobrien [(clobber (const_int 0))] 56090075Sobrien " 56190075Sobrien arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0], 56290075Sobrien operands[1], 0); 56390075Sobrien DONE; 56490075Sobrien " 56590075Sobrien [(set_attr "length" "4,4,16") 56690075Sobrien (set_attr "predicable" "yes")] 56790075Sobrien) 56890075Sobrien 56990075Sobrien;; Register group 'k' is a single register group containing only the stack 57090075Sobrien;; register. Trying to reload it will always fail catastrophically, 57190075Sobrien;; so never allow those alternatives to match if reloading is needed. 57290075Sobrien 57390075Sobrien(define_insn "*thumb_addsi3" 57490075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k") 57590075Sobrien (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k") 57690075Sobrien (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))] 57790075Sobrien "TARGET_THUMB" 57890075Sobrien "* 57990075Sobrien static const char * const asms[] = 58090075Sobrien { 58190075Sobrien \"add\\t%0, %0, %2\", 58290075Sobrien \"sub\\t%0, %0, #%n2\", 58390075Sobrien \"add\\t%0, %1, %2\", 58490075Sobrien \"add\\t%0, %0, %2\", 58590075Sobrien \"add\\t%0, %0, %2\", 58690075Sobrien \"add\\t%0, %1, %2\", 58790075Sobrien \"add\\t%0, %1, %2\" 58890075Sobrien }; 58990075Sobrien if ((which_alternative == 2 || which_alternative == 6) 59090075Sobrien && GET_CODE (operands[2]) == CONST_INT 59190075Sobrien && INTVAL (operands[2]) < 0) 59290075Sobrien return \"sub\\t%0, %1, #%n2\"; 59390075Sobrien return asms[which_alternative]; 59490075Sobrien " 59590075Sobrien [(set_attr "length" "2")] 59690075Sobrien) 59790075Sobrien 59890075Sobrien;; Reloading and elimination of the frame pointer can 59990075Sobrien;; sometimes cause this optimization to be missed. 60090075Sobrien(define_peephole2 601117395Skan [(set (match_operand:SI 0 "register_operand" "") 602117395Skan (match_operand:SI 1 "const_int_operand" "")) 60390075Sobrien (set (match_dup 0) 604117395Skan (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))] 60590075Sobrien "TARGET_THUMB 60690075Sobrien && REGNO (operands[2]) == STACK_POINTER_REGNUM 60790075Sobrien && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024 60890075Sobrien && (INTVAL (operands[1]) & 3) == 0" 60990075Sobrien [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))] 61090075Sobrien "" 61190075Sobrien) 61290075Sobrien 61390075Sobrien(define_insn "*addsi3_compare0" 61490075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 61590075Sobrien (compare:CC_NOOV 61690075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r, r") 61790075Sobrien (match_operand:SI 2 "arm_add_operand" "rI,L")) 61890075Sobrien (const_int 0))) 61990075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 62090075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 62190075Sobrien "TARGET_ARM" 62290075Sobrien "@ 62390075Sobrien add%?s\\t%0, %1, %2 62490075Sobrien sub%?s\\t%0, %1, #%n2" 62590075Sobrien [(set_attr "conds" "set")] 62690075Sobrien) 62790075Sobrien 62890075Sobrien(define_insn "*addsi3_compare0_scratch" 62990075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 63090075Sobrien (compare:CC_NOOV 63190075Sobrien (plus:SI (match_operand:SI 0 "s_register_operand" "r, r") 63290075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L")) 63390075Sobrien (const_int 0)))] 63490075Sobrien "TARGET_ARM" 63590075Sobrien "@ 63690075Sobrien cmn%?\\t%0, %1 63790075Sobrien cmp%?\\t%0, #%n1" 63890075Sobrien [(set_attr "conds" "set")] 63990075Sobrien) 64090075Sobrien 64190075Sobrien;; These patterns are the same ones as the two regular addsi3_compare0 64290075Sobrien;; patterns, except we write them slightly different - the combiner 64390075Sobrien;; tends to generate them this way. 64490075Sobrien(define_insn "*addsi3_compare0_for_combiner" 64590075Sobrien [(set (reg:CC CC_REGNUM) 64690075Sobrien (compare:CC 64790075Sobrien (match_operand:SI 1 "s_register_operand" "r,r") 64890075Sobrien (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L")))) 64990075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 65090075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 65190075Sobrien "TARGET_ARM" 65290075Sobrien "@ 65390075Sobrien add%?s\\t%0, %1, %2 65490075Sobrien sub%?s\\t%0, %1, #%n2" 65590075Sobrien [(set_attr "conds" "set")] 65690075Sobrien) 65790075Sobrien 65890075Sobrien(define_insn "*addsi3_compare0_scratch_for_combiner" 65990075Sobrien [(set (reg:CC CC_REGNUM) 66090075Sobrien (compare:CC 66190075Sobrien (match_operand:SI 0 "s_register_operand" "r,r") 66290075Sobrien (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))] 66390075Sobrien "TARGET_ARM" 66490075Sobrien "@ 66590075Sobrien cmn%?\\t%0, %1 66690075Sobrien cmp%?\\t%0, #%n1" 66790075Sobrien [(set_attr "conds" "set")] 66890075Sobrien) 66990075Sobrien 670132718Skan;; This is the canonicalization of addsi3_compare0_for_combiner when the 671132718Skan;; addend is a constant. 672132718Skan(define_insn "*cmpsi2_addneg" 673132718Skan [(set (reg:CC CC_REGNUM) 674132718Skan (compare:CC 675132718Skan (match_operand:SI 1 "s_register_operand" "r,r") 676132718Skan (match_operand:SI 2 "arm_addimm_operand" "I,L"))) 677132718Skan (set (match_operand:SI 0 "s_register_operand" "=r,r") 678132718Skan (plus:SI (match_dup 1) 679132718Skan (match_operand:SI 3 "arm_addimm_operand" "L,I")))] 680132718Skan "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])" 681132718Skan "@ 682132718Skan sub%?s\\t%0, %1, %2 683132718Skan add%?s\\t%0, %1, #%n2" 684132718Skan [(set_attr "conds" "set")] 685132718Skan) 686132718Skan 687132718Skan;; Convert the sequence 688132718Skan;; sub rd, rn, #1 689132718Skan;; cmn rd, #1 (equivalent to cmp rd, #-1) 690132718Skan;; bne dest 691132718Skan;; into 692132718Skan;; subs rd, rn, #1 693132718Skan;; bcs dest ((unsigned)rn >= 1) 694132718Skan;; similarly for the beq variant using bcc. 695132718Skan;; This is a common looping idiom (while (n--)) 696132718Skan(define_peephole2 697132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 698132718Skan (plus:SI (match_operand:SI 1 "s_register_operand" "") 699132718Skan (const_int -1))) 700132718Skan (set (match_operand 2 "cc_register" "") 701132718Skan (compare (match_dup 0) (const_int -1))) 702132718Skan (set (pc) 703132718Skan (if_then_else (match_operator 3 "equality_operator" 704132718Skan [(match_dup 2) (const_int 0)]) 705132718Skan (match_operand 4 "" "") 706132718Skan (match_operand 5 "" "")))] 707132718Skan "TARGET_ARM && peep2_reg_dead_p (3, operands[2])" 708132718Skan [(parallel[ 709132718Skan (set (match_dup 2) 710132718Skan (compare:CC 711132718Skan (match_dup 1) (const_int 1))) 712132718Skan (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))]) 713132718Skan (set (pc) 714132718Skan (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)]) 715132718Skan (match_dup 4) 716132718Skan (match_dup 5)))] 717132718Skan "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM); 718132718Skan operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE 719132718Skan ? GEU : LTU), 720132718Skan VOIDmode, 721132718Skan operands[2], const0_rtx);" 722132718Skan) 723132718Skan 72490075Sobrien;; The next four insns work because they compare the result with one of 72590075Sobrien;; the operands, and we know that the use of the condition code is 72690075Sobrien;; either GEU or LTU, so we can use the carry flag from the addition 72790075Sobrien;; instead of doing the compare a second time. 72890075Sobrien(define_insn "*addsi3_compare_op1" 72990075Sobrien [(set (reg:CC_C CC_REGNUM) 73090075Sobrien (compare:CC_C 73190075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 73290075Sobrien (match_operand:SI 2 "arm_add_operand" "rI,L")) 73390075Sobrien (match_dup 1))) 73490075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 73590075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 73690075Sobrien "TARGET_ARM" 73790075Sobrien "@ 73890075Sobrien add%?s\\t%0, %1, %2 73990075Sobrien sub%?s\\t%0, %1, #%n2" 74090075Sobrien [(set_attr "conds" "set")] 74190075Sobrien) 74290075Sobrien 74390075Sobrien(define_insn "*addsi3_compare_op2" 74490075Sobrien [(set (reg:CC_C CC_REGNUM) 74590075Sobrien (compare:CC_C 74690075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r,r") 74790075Sobrien (match_operand:SI 2 "arm_add_operand" "rI,L")) 74890075Sobrien (match_dup 2))) 74990075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 75090075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 75190075Sobrien "TARGET_ARM" 75290075Sobrien "@ 75390075Sobrien add%?s\\t%0, %1, %2 75490075Sobrien sub%?s\\t%0, %1, #%n2" 75590075Sobrien [(set_attr "conds" "set")] 75690075Sobrien) 75790075Sobrien 75890075Sobrien(define_insn "*compare_addsi2_op0" 75990075Sobrien [(set (reg:CC_C CC_REGNUM) 76090075Sobrien (compare:CC_C 76190075Sobrien (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 76290075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L")) 76390075Sobrien (match_dup 0)))] 76490075Sobrien "TARGET_ARM" 76590075Sobrien "@ 76690075Sobrien cmn%?\\t%0, %1 76790075Sobrien cmp%?\\t%0, #%n1" 76890075Sobrien [(set_attr "conds" "set")] 76990075Sobrien) 77090075Sobrien 77190075Sobrien(define_insn "*compare_addsi2_op1" 77290075Sobrien [(set (reg:CC_C CC_REGNUM) 77390075Sobrien (compare:CC_C 77490075Sobrien (plus:SI (match_operand:SI 0 "s_register_operand" "r,r") 77590075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L")) 77690075Sobrien (match_dup 1)))] 77790075Sobrien "TARGET_ARM" 77890075Sobrien "@ 77990075Sobrien cmn%?\\t%0, %1 78090075Sobrien cmp%?\\t%0, #%n1" 78190075Sobrien [(set_attr "conds" "set")] 78290075Sobrien) 78390075Sobrien 78490075Sobrien(define_insn "*addsi3_carryin" 78590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 78690075Sobrien (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 78790075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r") 78890075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI"))))] 78990075Sobrien "TARGET_ARM" 79090075Sobrien "adc%?\\t%0, %1, %2" 79190075Sobrien [(set_attr "conds" "use")] 79290075Sobrien) 79390075Sobrien 79490075Sobrien(define_insn "*addsi3_carryin_shift" 795132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 79690075Sobrien (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 79790075Sobrien (plus:SI 79890075Sobrien (match_operator:SI 2 "shift_operator" 799132718Skan [(match_operand:SI 3 "s_register_operand" "r") 800132718Skan (match_operand:SI 4 "reg_or_int_operand" "rM")]) 801132718Skan (match_operand:SI 1 "s_register_operand" "r"))))] 80290075Sobrien "TARGET_ARM" 80390075Sobrien "adc%?\\t%0, %1, %3%S2" 80490075Sobrien [(set_attr "conds" "use")] 80590075Sobrien) 80690075Sobrien 80790075Sobrien(define_insn "*addsi3_carryin_alt1" 80890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 80990075Sobrien (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") 81090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 81190075Sobrien (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] 81290075Sobrien "TARGET_ARM" 81390075Sobrien "adc%?\\t%0, %1, %2" 81490075Sobrien [(set_attr "conds" "use")] 81590075Sobrien) 81690075Sobrien 81790075Sobrien(define_insn "*addsi3_carryin_alt2" 81890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 81990075Sobrien (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 82090075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 82190075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")))] 82290075Sobrien "TARGET_ARM" 82390075Sobrien "adc%?\\t%0, %1, %2" 82490075Sobrien [(set_attr "conds" "use")] 82590075Sobrien) 82690075Sobrien 82790075Sobrien(define_insn "*addsi3_carryin_alt3" 82890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 82990075Sobrien (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) 83090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 83190075Sobrien (match_operand:SI 1 "s_register_operand" "r")))] 83290075Sobrien "TARGET_ARM" 83390075Sobrien "adc%?\\t%0, %1, %2" 83490075Sobrien [(set_attr "conds" "use")] 83590075Sobrien) 83690075Sobrien 83790075Sobrien(define_insn "incscc" 83890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 83990075Sobrien (plus:SI (match_operator:SI 2 "arm_comparison_operator" 84090075Sobrien [(match_operand:CC 3 "cc_register" "") (const_int 0)]) 84190075Sobrien (match_operand:SI 1 "s_register_operand" "0,?r")))] 84290075Sobrien "TARGET_ARM" 84390075Sobrien "@ 84490075Sobrien add%d2\\t%0, %1, #1 84590075Sobrien mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1" 84690075Sobrien [(set_attr "conds" "use") 84790075Sobrien (set_attr "length" "4,8")] 84890075Sobrien) 84990075Sobrien 850132718Skan; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant. 851132718Skan(define_split 852132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 853132718Skan (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "") 854132718Skan (match_operand:SI 2 "s_register_operand" "")) 855132718Skan (const_int -1))) 856132718Skan (clobber (match_operand:SI 3 "s_register_operand" ""))] 857132718Skan "TARGET_ARM" 858132718Skan [(set (match_dup 3) (match_dup 1)) 859132718Skan (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))] 860132718Skan " 861132718Skan operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1)); 862132718Skan") 86390075Sobrien 864132718Skan(define_expand "addsf3" 865132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 866132718Skan (plus:SF (match_operand:SF 1 "s_register_operand" "") 867132718Skan (match_operand:SF 2 "fpa_add_operand" "")))] 868132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 869132718Skan " 870132718Skan if (TARGET_CIRRUS 871132718Skan && !cirrus_fp_register (operands[2], SFmode)) 872132718Skan operands[2] = force_reg (SFmode, operands[2]); 873132718Skan") 87490075Sobrien 875132718Skan(define_expand "adddf3" 876132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 877132718Skan (plus:DF (match_operand:DF 1 "s_register_operand" "") 878132718Skan (match_operand:DF 2 "fpa_add_operand" "")))] 879132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 880132718Skan " 881132718Skan if (TARGET_CIRRUS 882132718Skan && !cirrus_fp_register (operands[2], DFmode)) 883132718Skan operands[2] = force_reg (DFmode, operands[2]); 884132718Skan") 88590075Sobrien 88690075Sobrien(define_expand "subdi3" 88790075Sobrien [(parallel 88890075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 88990075Sobrien (minus:DI (match_operand:DI 1 "s_register_operand" "") 89090075Sobrien (match_operand:DI 2 "s_register_operand" ""))) 89190075Sobrien (clobber (reg:CC CC_REGNUM))])] 89290075Sobrien "TARGET_EITHER" 89390075Sobrien " 894132718Skan if (TARGET_CIRRUS 895132718Skan && TARGET_ARM 896132718Skan && cirrus_fp_register (operands[0], DImode) 897132718Skan && cirrus_fp_register (operands[1], DImode)) 898132718Skan { 899132718Skan emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2])); 900132718Skan DONE; 901132718Skan } 902132718Skan 90390075Sobrien if (TARGET_THUMB) 90490075Sobrien { 90590075Sobrien if (GET_CODE (operands[1]) != REG) 90690075Sobrien operands[1] = force_reg (SImode, operands[1]); 90790075Sobrien if (GET_CODE (operands[2]) != REG) 90890075Sobrien operands[2] = force_reg (SImode, operands[2]); 90990075Sobrien } 91090075Sobrien " 91190075Sobrien) 91290075Sobrien 91390075Sobrien(define_insn "*arm_subdi3" 91490075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r") 91590075Sobrien (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0") 91690075Sobrien (match_operand:DI 2 "s_register_operand" "r,0,0"))) 91790075Sobrien (clobber (reg:CC CC_REGNUM))] 91890075Sobrien "TARGET_ARM" 91990075Sobrien "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2" 92090075Sobrien [(set_attr "conds" "clob") 92190075Sobrien (set_attr "length" "8")] 92290075Sobrien) 92390075Sobrien 92490075Sobrien(define_insn "*thumb_subdi3" 92590075Sobrien [(set (match_operand:DI 0 "register_operand" "=l") 92690075Sobrien (minus:DI (match_operand:DI 1 "register_operand" "0") 92790075Sobrien (match_operand:DI 2 "register_operand" "l"))) 92890075Sobrien (clobber (reg:CC CC_REGNUM))] 92990075Sobrien "TARGET_THUMB" 93090075Sobrien "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2" 93190075Sobrien [(set_attr "length" "4")] 93290075Sobrien) 93390075Sobrien 93490075Sobrien(define_insn "*subdi_di_zesidi" 93590075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 93690075Sobrien (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0") 93790075Sobrien (zero_extend:DI 93890075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")))) 93990075Sobrien (clobber (reg:CC CC_REGNUM))] 94090075Sobrien "TARGET_ARM" 94190075Sobrien "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0" 94290075Sobrien [(set_attr "conds" "clob") 94390075Sobrien (set_attr "length" "8")] 94490075Sobrien) 94590075Sobrien 94690075Sobrien(define_insn "*subdi_di_sesidi" 94790075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 94890075Sobrien (minus:DI (match_operand:DI 1 "s_register_operand" "r,0") 94990075Sobrien (sign_extend:DI 95090075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")))) 95190075Sobrien (clobber (reg:CC CC_REGNUM))] 95290075Sobrien "TARGET_ARM" 95390075Sobrien "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31" 95490075Sobrien [(set_attr "conds" "clob") 95590075Sobrien (set_attr "length" "8")] 95690075Sobrien) 95790075Sobrien 95890075Sobrien(define_insn "*subdi_zesidi_di" 95990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 96090075Sobrien (minus:DI (zero_extend:DI 96190075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 96290075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0"))) 96390075Sobrien (clobber (reg:CC CC_REGNUM))] 96490075Sobrien "TARGET_ARM" 96590075Sobrien "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0" 96690075Sobrien [(set_attr "conds" "clob") 96790075Sobrien (set_attr "length" "8")] 96890075Sobrien) 96990075Sobrien 97090075Sobrien(define_insn "*subdi_sesidi_di" 97190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 97290075Sobrien (minus:DI (sign_extend:DI 97390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 97490075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0"))) 97590075Sobrien (clobber (reg:CC CC_REGNUM))] 97690075Sobrien "TARGET_ARM" 97790075Sobrien "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31" 97890075Sobrien [(set_attr "conds" "clob") 97990075Sobrien (set_attr "length" "8")] 98090075Sobrien) 98190075Sobrien 98290075Sobrien(define_insn "*subdi_zesidi_zesidi" 98390075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r") 98490075Sobrien (minus:DI (zero_extend:DI 98590075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 98690075Sobrien (zero_extend:DI 98790075Sobrien (match_operand:SI 2 "s_register_operand" "r")))) 98890075Sobrien (clobber (reg:CC CC_REGNUM))] 98990075Sobrien "TARGET_ARM" 99090075Sobrien "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1" 99190075Sobrien [(set_attr "conds" "clob") 99290075Sobrien (set_attr "length" "8")] 99390075Sobrien) 99490075Sobrien 99590075Sobrien(define_expand "subsi3" 99690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 99790075Sobrien (minus:SI (match_operand:SI 1 "reg_or_int_operand" "") 99890075Sobrien (match_operand:SI 2 "s_register_operand" "")))] 99990075Sobrien "TARGET_EITHER" 100090075Sobrien " 100190075Sobrien if (GET_CODE (operands[1]) == CONST_INT) 100290075Sobrien { 100390075Sobrien if (TARGET_ARM) 100490075Sobrien { 100590075Sobrien arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], 100690075Sobrien operands[2], 100790075Sobrien (no_new_pseudos ? 0 100890075Sobrien : preserve_subexpressions_p ())); 100990075Sobrien DONE; 101090075Sobrien } 101190075Sobrien else /* TARGET_THUMB */ 101290075Sobrien operands[1] = force_reg (SImode, operands[1]); 101390075Sobrien } 101490075Sobrien " 101590075Sobrien) 101690075Sobrien 101790075Sobrien(define_insn "*thumb_subsi3_insn" 101890075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 101990075Sobrien (minus:SI (match_operand:SI 1 "register_operand" "l") 102090075Sobrien (match_operand:SI 2 "register_operand" "l")))] 102190075Sobrien "TARGET_THUMB" 102290075Sobrien "sub\\t%0, %1, %2" 102390075Sobrien [(set_attr "length" "2")] 102490075Sobrien) 102590075Sobrien 102690075Sobrien(define_insn_and_split "*arm_subsi3_insn" 102790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 102890075Sobrien (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n") 102990075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")))] 103090075Sobrien "TARGET_ARM" 103190075Sobrien "@ 103290075Sobrien rsb%?\\t%0, %2, %1 103390075Sobrien #" 103490075Sobrien "TARGET_ARM 103590075Sobrien && GET_CODE (operands[1]) == CONST_INT 103690075Sobrien && !const_ok_for_arm (INTVAL (operands[1]))" 103790075Sobrien [(clobber (const_int 0))] 103890075Sobrien " 103990075Sobrien arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0], 104090075Sobrien operands[2], 0); 104190075Sobrien DONE; 104290075Sobrien " 104390075Sobrien [(set_attr "length" "4,16") 104490075Sobrien (set_attr "predicable" "yes")] 104590075Sobrien) 104690075Sobrien 104790075Sobrien(define_peephole2 104890075Sobrien [(match_scratch:SI 3 "r") 104990075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 105090075Sobrien (minus:SI (match_operand:SI 1 "const_int_operand" "") 105190075Sobrien (match_operand:SI 2 "s_register_operand" "")))] 105290075Sobrien "TARGET_ARM 105390075Sobrien && !const_ok_for_arm (INTVAL (operands[1])) 105490075Sobrien && const_ok_for_arm (~INTVAL (operands[1]))" 105590075Sobrien [(set (match_dup 3) (match_dup 1)) 105690075Sobrien (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))] 105790075Sobrien "" 105890075Sobrien) 105990075Sobrien 106090075Sobrien(define_insn "*subsi3_compare0" 106190075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 106290075Sobrien (compare:CC_NOOV 106390075Sobrien (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I") 106490075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,r")) 106590075Sobrien (const_int 0))) 106690075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 106790075Sobrien (minus:SI (match_dup 1) (match_dup 2)))] 106890075Sobrien "TARGET_ARM" 106990075Sobrien "@ 107090075Sobrien sub%?s\\t%0, %1, %2 107190075Sobrien rsb%?s\\t%0, %2, %1" 107290075Sobrien [(set_attr "conds" "set")] 107390075Sobrien) 107490075Sobrien 107590075Sobrien(define_insn "decscc" 107690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 107790075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 107890075Sobrien (match_operator:SI 2 "arm_comparison_operator" 107990075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)])))] 108090075Sobrien "TARGET_ARM" 108190075Sobrien "@ 108290075Sobrien sub%d2\\t%0, %1, #1 108390075Sobrien mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1" 108490075Sobrien [(set_attr "conds" "use") 108590075Sobrien (set_attr "length" "*,8")] 108690075Sobrien) 108790075Sobrien 1088132718Skan(define_expand "subsf3" 1089132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 1090132718Skan (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "") 1091132718Skan (match_operand:SF 2 "fpa_rhs_operand" "")))] 1092132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 1093132718Skan " 1094132718Skan if (TARGET_CIRRUS) 1095132718Skan { 1096132718Skan if (!cirrus_fp_register (operands[1], SFmode)) 1097132718Skan operands[1] = force_reg (SFmode, operands[1]); 1098132718Skan if (!cirrus_fp_register (operands[2], SFmode)) 1099132718Skan operands[2] = force_reg (SFmode, operands[2]); 1100132718Skan } 1101132718Skan") 110290075Sobrien 1103132718Skan(define_expand "subdf3" 1104132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 1105132718Skan (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "") 1106132718Skan (match_operand:DF 2 "fpa_rhs_operand" "")))] 1107132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 1108132718Skan " 1109132718Skan if (TARGET_CIRRUS) 1110132718Skan { 1111132718Skan if (!cirrus_fp_register (operands[1], DFmode)) 1112132718Skan operands[1] = force_reg (DFmode, operands[1]); 1113132718Skan if (!cirrus_fp_register (operands[2], DFmode)) 1114132718Skan operands[2] = force_reg (DFmode, operands[2]); 1115132718Skan } 1116132718Skan") 111790075Sobrien 111890075Sobrien 111990075Sobrien;; Multiplication insns 112090075Sobrien 112190075Sobrien(define_expand "mulsi3" 112290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 112390075Sobrien (mult:SI (match_operand:SI 2 "s_register_operand" "") 112490075Sobrien (match_operand:SI 1 "s_register_operand" "")))] 112590075Sobrien "TARGET_EITHER" 112690075Sobrien "" 112790075Sobrien) 112890075Sobrien 112990075Sobrien;; Use `&' and then `0' to prevent the operands 0 and 1 being the same 113090075Sobrien(define_insn "*arm_mulsi3" 113190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 113290075Sobrien (mult:SI (match_operand:SI 2 "s_register_operand" "r,r") 113390075Sobrien (match_operand:SI 1 "s_register_operand" "%?r,0")))] 113490075Sobrien "TARGET_ARM" 113590075Sobrien "mul%?\\t%0, %2, %1" 113690075Sobrien [(set_attr "type" "mult") 113790075Sobrien (set_attr "predicable" "yes")] 113890075Sobrien) 113990075Sobrien 114090075Sobrien; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 114190075Sobrien; 1 and 2; are the same, because reload will make operand 0 match 114290075Sobrien; operand 1 without realizing that this conflicts with operand 2. We fix 114390075Sobrien; this by adding another alternative to match this case, and then `reload' 114490075Sobrien; it ourselves. This alternative must come first. 114590075Sobrien(define_insn "*thumb_mulsi3" 114690075Sobrien [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l") 114790075Sobrien (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0") 114890075Sobrien (match_operand:SI 2 "register_operand" "l,l,l")))] 114990075Sobrien "TARGET_THUMB" 115090075Sobrien "* 115190075Sobrien if (which_alternative < 2) 115290075Sobrien return \"mov\\t%0, %1\;mul\\t%0, %0, %2\"; 115390075Sobrien else 115490075Sobrien return \"mul\\t%0, %0, %2\"; 115590075Sobrien " 115690075Sobrien [(set_attr "length" "4,4,2") 115790075Sobrien (set_attr "type" "mult")] 115890075Sobrien) 115990075Sobrien 116090075Sobrien(define_insn "*mulsi3_compare0" 116190075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 116290075Sobrien (compare:CC_NOOV (mult:SI 116390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r") 116490075Sobrien (match_operand:SI 1 "s_register_operand" "%?r,0")) 116590075Sobrien (const_int 0))) 116690075Sobrien (set (match_operand:SI 0 "s_register_operand" "=&r,&r") 116790075Sobrien (mult:SI (match_dup 2) (match_dup 1)))] 1168132718Skan "TARGET_ARM && !arm_arch_xscale" 116990075Sobrien "mul%?s\\t%0, %2, %1" 117090075Sobrien [(set_attr "conds" "set") 117190075Sobrien (set_attr "type" "mult")] 117290075Sobrien) 117390075Sobrien 117490075Sobrien(define_insn "*mulsi_compare0_scratch" 117590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 117690075Sobrien (compare:CC_NOOV (mult:SI 117790075Sobrien (match_operand:SI 2 "s_register_operand" "r,r") 117890075Sobrien (match_operand:SI 1 "s_register_operand" "%?r,0")) 117990075Sobrien (const_int 0))) 118090075Sobrien (clobber (match_scratch:SI 0 "=&r,&r"))] 1181132718Skan "TARGET_ARM && !arm_arch_xscale" 118290075Sobrien "mul%?s\\t%0, %2, %1" 118390075Sobrien [(set_attr "conds" "set") 118490075Sobrien (set_attr "type" "mult")] 118590075Sobrien) 118690075Sobrien 118790075Sobrien;; Unnamed templates to match MLA instruction. 118890075Sobrien 118990075Sobrien(define_insn "*mulsi3addsi" 119090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 119190075Sobrien (plus:SI 119290075Sobrien (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r") 119390075Sobrien (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 119490075Sobrien (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))] 119590075Sobrien "TARGET_ARM" 119690075Sobrien "mla%?\\t%0, %2, %1, %3" 119790075Sobrien [(set_attr "type" "mult") 119890075Sobrien (set_attr "predicable" "yes")] 119990075Sobrien) 120090075Sobrien 120190075Sobrien(define_insn "*mulsi3addsi_compare0" 120290075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 120390075Sobrien (compare:CC_NOOV 120490075Sobrien (plus:SI (mult:SI 120590075Sobrien (match_operand:SI 2 "s_register_operand" "r,r,r,r") 120690075Sobrien (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 120790075Sobrien (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 120890075Sobrien (const_int 0))) 120990075Sobrien (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r") 121090075Sobrien (plus:SI (mult:SI (match_dup 2) (match_dup 1)) 121190075Sobrien (match_dup 3)))] 1212132718Skan "TARGET_ARM && !arm_arch_xscale" 121390075Sobrien "mla%?s\\t%0, %2, %1, %3" 121490075Sobrien [(set_attr "conds" "set") 121590075Sobrien (set_attr "type" "mult")] 121690075Sobrien) 121790075Sobrien 121890075Sobrien(define_insn "*mulsi3addsi_compare0_scratch" 121990075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 122090075Sobrien (compare:CC_NOOV 122190075Sobrien (plus:SI (mult:SI 122290075Sobrien (match_operand:SI 2 "s_register_operand" "r,r,r,r") 122390075Sobrien (match_operand:SI 1 "s_register_operand" "%r,0,r,0")) 122490075Sobrien (match_operand:SI 3 "s_register_operand" "?r,r,0,0")) 122590075Sobrien (const_int 0))) 122690075Sobrien (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))] 1227132718Skan "TARGET_ARM && !arm_arch_xscale" 122890075Sobrien "mla%?s\\t%0, %2, %1, %3" 122990075Sobrien [(set_attr "conds" "set") 123090075Sobrien (set_attr "type" "mult")] 123190075Sobrien) 123290075Sobrien 1233132718Skan;; Unnamed template to match long long multiply-accumulate (smlal) 123490075Sobrien 123590075Sobrien(define_insn "*mulsidi3adddi" 123690075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r") 123790075Sobrien (plus:DI 123890075Sobrien (mult:DI 123990075Sobrien (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r")) 124090075Sobrien (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r"))) 124190075Sobrien (match_operand:DI 1 "s_register_operand" "0")))] 124290075Sobrien "TARGET_ARM && arm_fast_multiply" 124390075Sobrien "smlal%?\\t%Q0, %R0, %3, %2" 124490075Sobrien [(set_attr "type" "mult") 124590075Sobrien (set_attr "predicable" "yes")] 124690075Sobrien) 124790075Sobrien 124890075Sobrien(define_insn "mulsidi3" 124990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r") 125090075Sobrien (mult:DI 125190075Sobrien (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r")) 125290075Sobrien (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))] 125390075Sobrien "TARGET_ARM && arm_fast_multiply" 125490075Sobrien "smull%?\\t%Q0, %R0, %1, %2" 125590075Sobrien [(set_attr "type" "mult") 125690075Sobrien (set_attr "predicable" "yes")] 125790075Sobrien) 125890075Sobrien 125990075Sobrien(define_insn "umulsidi3" 126090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r") 126190075Sobrien (mult:DI 126290075Sobrien (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r")) 126390075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))] 126490075Sobrien "TARGET_ARM && arm_fast_multiply" 126590075Sobrien "umull%?\\t%Q0, %R0, %1, %2" 126690075Sobrien [(set_attr "type" "mult") 126790075Sobrien (set_attr "predicable" "yes")] 126890075Sobrien) 126990075Sobrien 1270132718Skan;; Unnamed template to match long long unsigned multiply-accumulate (umlal) 127190075Sobrien 127290075Sobrien(define_insn "*umulsidi3adddi" 127390075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r") 127490075Sobrien (plus:DI 127590075Sobrien (mult:DI 127690075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r")) 127790075Sobrien (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r"))) 127890075Sobrien (match_operand:DI 1 "s_register_operand" "0")))] 127990075Sobrien "TARGET_ARM && arm_fast_multiply" 128090075Sobrien "umlal%?\\t%Q0, %R0, %3, %2" 128190075Sobrien [(set_attr "type" "mult") 128290075Sobrien (set_attr "predicable" "yes")] 128390075Sobrien) 128490075Sobrien 128590075Sobrien(define_insn "smulsi3_highpart" 128690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 128790075Sobrien (truncate:SI 128890075Sobrien (lshiftrt:DI 128990075Sobrien (mult:DI 129090075Sobrien (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0")) 129190075Sobrien (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) 129290075Sobrien (const_int 32)))) 129390075Sobrien (clobber (match_scratch:SI 3 "=&r,&r"))] 129490075Sobrien "TARGET_ARM && arm_fast_multiply" 129590075Sobrien "smull%?\\t%3, %0, %2, %1" 129690075Sobrien [(set_attr "type" "mult") 129790075Sobrien (set_attr "predicable" "yes")] 129890075Sobrien) 129990075Sobrien 130090075Sobrien(define_insn "umulsi3_highpart" 130190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r") 130290075Sobrien (truncate:SI 130390075Sobrien (lshiftrt:DI 130490075Sobrien (mult:DI 130590075Sobrien (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0")) 130690075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) 130790075Sobrien (const_int 32)))) 130890075Sobrien (clobber (match_scratch:SI 3 "=&r,&r"))] 130990075Sobrien "TARGET_ARM && arm_fast_multiply" 131090075Sobrien "umull%?\\t%3, %0, %2, %1" 131190075Sobrien [(set_attr "type" "mult") 131290075Sobrien (set_attr "predicable" "yes")] 131390075Sobrien) 131490075Sobrien 131590075Sobrien(define_insn "mulhisi3" 131690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 131790075Sobrien (mult:SI (sign_extend:SI 131890075Sobrien (match_operand:HI 1 "s_register_operand" "%r")) 131990075Sobrien (sign_extend:SI 132090075Sobrien (match_operand:HI 2 "s_register_operand" "r"))))] 1321132718Skan "TARGET_ARM && arm_arch5e" 132290075Sobrien "smulbb%?\\t%0, %1, %2" 1323132718Skan [(set_attr "type" "mult") 1324132718Skan (set_attr "predicable" "yes")] 132590075Sobrien) 132690075Sobrien 1327132718Skan(define_insn "*mulhisi3tb" 1328132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1329132718Skan (mult:SI (ashiftrt:SI 1330132718Skan (match_operand:SI 1 "s_register_operand" "r") 1331132718Skan (const_int 16)) 1332132718Skan (sign_extend:SI 1333132718Skan (match_operand:HI 2 "s_register_operand" "r"))))] 1334132718Skan "TARGET_ARM && arm_arch5e" 1335132718Skan "smultb%?\\t%0, %1, %2" 1336132718Skan [(set_attr "type" "mult") 1337132718Skan (set_attr "predicable" "yes")] 1338132718Skan) 1339132718Skan 1340132718Skan(define_insn "*mulhisi3bt" 1341132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1342132718Skan (mult:SI (sign_extend:SI 1343132718Skan (match_operand:HI 1 "s_register_operand" "r")) 1344132718Skan (ashiftrt:SI 1345132718Skan (match_operand:SI 2 "s_register_operand" "r") 1346132718Skan (const_int 16))))] 1347132718Skan "TARGET_ARM && arm_arch5e" 1348132718Skan "smulbt%?\\t%0, %1, %2" 1349132718Skan [(set_attr "type" "mult") 1350132718Skan (set_attr "predicable" "yes")] 1351132718Skan) 1352132718Skan 1353132718Skan(define_insn "*mulhisi3tt" 1354132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 1355132718Skan (mult:SI (ashiftrt:SI 1356132718Skan (match_operand:SI 1 "s_register_operand" "r") 1357132718Skan (const_int 16)) 1358132718Skan (ashiftrt:SI 1359132718Skan (match_operand:SI 2 "s_register_operand" "r") 1360132718Skan (const_int 16))))] 1361132718Skan "TARGET_ARM && arm_arch5e" 1362132718Skan "smultt%?\\t%0, %1, %2" 1363132718Skan [(set_attr "type" "mult") 1364132718Skan (set_attr "predicable" "yes")] 1365132718Skan) 1366132718Skan 136790075Sobrien(define_insn "*mulhisi3addsi" 136890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 136990075Sobrien (plus:SI (match_operand:SI 1 "s_register_operand" "r") 137090075Sobrien (mult:SI (sign_extend:SI 137190075Sobrien (match_operand:HI 2 "s_register_operand" "%r")) 137290075Sobrien (sign_extend:SI 137390075Sobrien (match_operand:HI 3 "s_register_operand" "r")))))] 1374132718Skan "TARGET_ARM && arm_arch5e" 137590075Sobrien "smlabb%?\\t%0, %2, %3, %1" 1376132718Skan [(set_attr "type" "mult") 1377132718Skan (set_attr "predicable" "yes")] 137890075Sobrien) 137990075Sobrien 138090075Sobrien(define_insn "*mulhidi3adddi" 138190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r") 138290075Sobrien (plus:DI 138390075Sobrien (match_operand:DI 1 "s_register_operand" "0") 138490075Sobrien (mult:DI (sign_extend:DI 138590075Sobrien (match_operand:HI 2 "s_register_operand" "%r")) 138690075Sobrien (sign_extend:DI 138790075Sobrien (match_operand:HI 3 "s_register_operand" "r")))))] 1388132718Skan "TARGET_ARM && arm_arch5e" 138990075Sobrien "smlalbb%?\\t%Q0, %R0, %2, %3" 1390132718Skan [(set_attr "type" "mult") 1391132718Skan (set_attr "predicable" "yes")]) 139290075Sobrien 1393132718Skan(define_expand "mulsf3" 1394132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 1395132718Skan (mult:SF (match_operand:SF 1 "s_register_operand" "") 1396132718Skan (match_operand:SF 2 "fpa_rhs_operand" "")))] 1397132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 1398132718Skan " 1399132718Skan if (TARGET_CIRRUS 1400132718Skan && !cirrus_fp_register (operands[2], SFmode)) 1401132718Skan operands[2] = force_reg (SFmode, operands[2]); 1402132718Skan") 140390075Sobrien 1404132718Skan(define_expand "muldf3" 1405132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 1406132718Skan (mult:DF (match_operand:DF 1 "s_register_operand" "") 1407132718Skan (match_operand:DF 2 "fpa_rhs_operand" "")))] 1408132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 1409132718Skan " 1410132718Skan if (TARGET_CIRRUS 1411132718Skan && !cirrus_fp_register (operands[2], DFmode)) 1412132718Skan operands[2] = force_reg (DFmode, operands[2]); 1413132718Skan") 141490075Sobrien 141590075Sobrien;; Division insns 141690075Sobrien 1417132718Skan(define_expand "divsf3" 1418132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 1419132718Skan (div:SF (match_operand:SF 1 "fpa_rhs_operand" "") 1420132718Skan (match_operand:SF 2 "fpa_rhs_operand" "")))] 142190075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 1422132718Skan "") 142390075Sobrien 1424132718Skan(define_expand "divdf3" 1425132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 1426132718Skan (div:DF (match_operand:DF 1 "fpa_rhs_operand" "") 1427132718Skan (match_operand:DF 2 "fpa_rhs_operand" "")))] 142890075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 1429132718Skan "") 143090075Sobrien 143190075Sobrien;; Modulo insns 143290075Sobrien 1433132718Skan(define_expand "modsf3" 1434132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 1435132718Skan (mod:SF (match_operand:SF 1 "s_register_operand" "") 1436132718Skan (match_operand:SF 2 "fpa_rhs_operand" "")))] 143790075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 1438132718Skan "") 143990075Sobrien 1440132718Skan(define_expand "moddf3" 1441132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 1442132718Skan (mod:DF (match_operand:DF 1 "s_register_operand" "") 1443132718Skan (match_operand:DF 2 "fpa_rhs_operand" "")))] 144490075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 1445132718Skan "") 144690075Sobrien 144790075Sobrien;; Boolean and,ior,xor insns 144890075Sobrien 144990075Sobrien;; Split up double word logical operations 145090075Sobrien 145190075Sobrien;; Split up simple DImode logical operations. Simply perform the logical 145290075Sobrien;; operation on the upper and lower halves of the registers. 145390075Sobrien(define_split 145490075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 145590075Sobrien (match_operator:DI 6 "logical_binary_operator" 145690075Sobrien [(match_operand:DI 1 "s_register_operand" "") 145790075Sobrien (match_operand:DI 2 "s_register_operand" "")]))] 1458132718Skan "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))" 145990075Sobrien [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)])) 146090075Sobrien (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))] 146190075Sobrien " 146290075Sobrien { 146390075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 146490075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 146590075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 146690075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 146790075Sobrien operands[5] = gen_highpart (SImode, operands[2]); 146890075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 146990075Sobrien }" 147090075Sobrien) 147190075Sobrien 147290075Sobrien(define_split 147390075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 147490075Sobrien (match_operator:DI 6 "logical_binary_operator" 147590075Sobrien [(sign_extend:DI (match_operand:SI 2 "s_register_operand" "")) 147690075Sobrien (match_operand:DI 1 "s_register_operand" "")]))] 147790075Sobrien "TARGET_ARM && reload_completed" 147890075Sobrien [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)])) 147990075Sobrien (set (match_dup 3) (match_op_dup:SI 6 148090075Sobrien [(ashiftrt:SI (match_dup 2) (const_int 31)) 148190075Sobrien (match_dup 4)]))] 148290075Sobrien " 148390075Sobrien { 148490075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 148590075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 148690075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 148790075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 148890075Sobrien operands[5] = gen_highpart (SImode, operands[2]); 148990075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 149090075Sobrien }" 149190075Sobrien) 149290075Sobrien 149390075Sobrien;; The zero extend of operand 2 means we can just copy the high part of 149490075Sobrien;; operand1 into operand0. 149590075Sobrien(define_split 149690075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 149790075Sobrien (ior:DI 149890075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")) 149990075Sobrien (match_operand:DI 1 "s_register_operand" "")))] 150090075Sobrien "TARGET_ARM && operands[0] != operands[1] && reload_completed" 150190075Sobrien [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2))) 150290075Sobrien (set (match_dup 3) (match_dup 4))] 150390075Sobrien " 150490075Sobrien { 150590075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 150690075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 150790075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 150890075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 150990075Sobrien }" 151090075Sobrien) 151190075Sobrien 151290075Sobrien;; The zero extend of operand 2 means we can just copy the high part of 151390075Sobrien;; operand1 into operand0. 151490075Sobrien(define_split 151590075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 151690075Sobrien (xor:DI 151790075Sobrien (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")) 151890075Sobrien (match_operand:DI 1 "s_register_operand" "")))] 151990075Sobrien "TARGET_ARM && operands[0] != operands[1] && reload_completed" 152090075Sobrien [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) 152190075Sobrien (set (match_dup 3) (match_dup 4))] 152290075Sobrien " 152390075Sobrien { 152490075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 152590075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 152690075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 152790075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 152890075Sobrien }" 152990075Sobrien) 153090075Sobrien 153190075Sobrien(define_insn "anddi3" 153290075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 153390075Sobrien (and:DI (match_operand:DI 1 "s_register_operand" "%0,r") 153490075Sobrien (match_operand:DI 2 "s_register_operand" "r,r")))] 1535132718Skan "TARGET_ARM && ! TARGET_IWMMXT" 153690075Sobrien "#" 153790075Sobrien [(set_attr "length" "8")] 153890075Sobrien) 153990075Sobrien 154090075Sobrien(define_insn_and_split "*anddi_zesidi_di" 154190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 154290075Sobrien (and:DI (zero_extend:DI 154390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 154490075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0")))] 154590075Sobrien "TARGET_ARM" 154690075Sobrien "#" 154790075Sobrien "TARGET_ARM && reload_completed" 154890075Sobrien ; The zero extend of operand 2 clears the high word of the output 154990075Sobrien ; operand. 155090075Sobrien [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2))) 155190075Sobrien (set (match_dup 3) (const_int 0))] 155290075Sobrien " 155390075Sobrien { 155490075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 155590075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 155690075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 155790075Sobrien }" 155890075Sobrien [(set_attr "length" "8")] 155990075Sobrien) 156090075Sobrien 156190075Sobrien(define_insn "*anddi_sesdi_di" 156290075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 156390075Sobrien (and:DI (sign_extend:DI 156490075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 156590075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0")))] 156690075Sobrien "TARGET_ARM" 156790075Sobrien "#" 156890075Sobrien [(set_attr "length" "8")] 156990075Sobrien) 157090075Sobrien 157190075Sobrien(define_expand "andsi3" 157290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 157390075Sobrien (and:SI (match_operand:SI 1 "s_register_operand" "") 157490075Sobrien (match_operand:SI 2 "reg_or_int_operand" "")))] 157590075Sobrien "TARGET_EITHER" 157690075Sobrien " 157790075Sobrien if (TARGET_ARM) 157890075Sobrien { 157990075Sobrien if (GET_CODE (operands[2]) == CONST_INT) 158090075Sobrien { 158190075Sobrien arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], 158290075Sobrien operands[1], 158390075Sobrien (no_new_pseudos 158490075Sobrien ? 0 : preserve_subexpressions_p ())); 158590075Sobrien DONE; 158690075Sobrien } 158790075Sobrien } 158890075Sobrien else /* TARGET_THUMB */ 158990075Sobrien { 159090075Sobrien if (GET_CODE (operands[2]) != CONST_INT) 159190075Sobrien operands[2] = force_reg (SImode, operands[2]); 159290075Sobrien else 159390075Sobrien { 159490075Sobrien int i; 159590075Sobrien 159690075Sobrien if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256) 159790075Sobrien { 159890075Sobrien operands[2] = force_reg (SImode, 159990075Sobrien GEN_INT (~INTVAL (operands[2]))); 160090075Sobrien 160190075Sobrien emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1])); 160290075Sobrien 160390075Sobrien DONE; 160490075Sobrien } 160590075Sobrien 160690075Sobrien for (i = 9; i <= 31; i++) 160790075Sobrien { 160890075Sobrien if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2])) 160990075Sobrien { 161090075Sobrien emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i), 161190075Sobrien const0_rtx)); 161290075Sobrien DONE; 161390075Sobrien } 161490075Sobrien else if ((((HOST_WIDE_INT) 1) << i) - 1 161590075Sobrien == ~INTVAL (operands[2])) 161690075Sobrien { 161790075Sobrien rtx shift = GEN_INT (i); 161890075Sobrien rtx reg = gen_reg_rtx (SImode); 161990075Sobrien 162090075Sobrien emit_insn (gen_lshrsi3 (reg, operands[1], shift)); 162190075Sobrien emit_insn (gen_ashlsi3 (operands[0], reg, shift)); 162290075Sobrien 162390075Sobrien DONE; 162490075Sobrien } 162590075Sobrien } 162690075Sobrien 162790075Sobrien operands[2] = force_reg (SImode, operands[2]); 162890075Sobrien } 162990075Sobrien } 163090075Sobrien " 163190075Sobrien) 163290075Sobrien 163390075Sobrien(define_insn_and_split "*arm_andsi3_insn" 163490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 163590075Sobrien (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r") 163690075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] 163790075Sobrien "TARGET_ARM" 163890075Sobrien "@ 163990075Sobrien and%?\\t%0, %1, %2 164090075Sobrien bic%?\\t%0, %1, #%B2 164190075Sobrien #" 164290075Sobrien "TARGET_ARM 164390075Sobrien && GET_CODE (operands[2]) == CONST_INT 164490075Sobrien && !(const_ok_for_arm (INTVAL (operands[2])) 164590075Sobrien || const_ok_for_arm (~INTVAL (operands[2])))" 164690075Sobrien [(clobber (const_int 0))] 164790075Sobrien " 164890075Sobrien arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0], 164990075Sobrien operands[1], 0); 165090075Sobrien DONE; 165190075Sobrien " 165290075Sobrien [(set_attr "length" "4,4,16") 165390075Sobrien (set_attr "predicable" "yes")] 165490075Sobrien) 165590075Sobrien 165690075Sobrien(define_insn "*thumb_andsi3_insn" 165790075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 165890075Sobrien (and:SI (match_operand:SI 1 "register_operand" "%0") 165990075Sobrien (match_operand:SI 2 "register_operand" "l")))] 166090075Sobrien "TARGET_THUMB" 166190075Sobrien "and\\t%0, %0, %2" 166290075Sobrien [(set_attr "length" "2")] 166390075Sobrien) 166490075Sobrien 166590075Sobrien(define_insn "*andsi3_compare0" 166690075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 166790075Sobrien (compare:CC_NOOV 166890075Sobrien (and:SI (match_operand:SI 1 "s_register_operand" "r,r") 166990075Sobrien (match_operand:SI 2 "arm_not_operand" "rI,K")) 167090075Sobrien (const_int 0))) 167190075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 167290075Sobrien (and:SI (match_dup 1) (match_dup 2)))] 167390075Sobrien "TARGET_ARM" 167490075Sobrien "@ 167590075Sobrien and%?s\\t%0, %1, %2 167690075Sobrien bic%?s\\t%0, %1, #%B2" 167790075Sobrien [(set_attr "conds" "set")] 167890075Sobrien) 167990075Sobrien 168090075Sobrien(define_insn "*andsi3_compare0_scratch" 168190075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 168290075Sobrien (compare:CC_NOOV 168390075Sobrien (and:SI (match_operand:SI 0 "s_register_operand" "r,r") 168490075Sobrien (match_operand:SI 1 "arm_not_operand" "rI,K")) 168590075Sobrien (const_int 0))) 168690075Sobrien (clobber (match_scratch:SI 2 "=X,r"))] 168790075Sobrien "TARGET_ARM" 168890075Sobrien "@ 168990075Sobrien tst%?\\t%0, %1 169090075Sobrien bic%?s\\t%2, %0, #%B1" 169190075Sobrien [(set_attr "conds" "set")] 169290075Sobrien) 169390075Sobrien 169490075Sobrien(define_insn "*zeroextractsi_compare0_scratch" 169590075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 169690075Sobrien (compare:CC_NOOV (zero_extract:SI 169790075Sobrien (match_operand:SI 0 "s_register_operand" "r") 169890075Sobrien (match_operand 1 "const_int_operand" "n") 169990075Sobrien (match_operand 2 "const_int_operand" "n")) 170090075Sobrien (const_int 0)))] 170190075Sobrien "TARGET_ARM 170290075Sobrien && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32 170390075Sobrien && INTVAL (operands[1]) > 0 170490075Sobrien && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8 170590075Sobrien && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)" 170690075Sobrien "* 170790075Sobrien operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1) 170890075Sobrien << INTVAL (operands[2])); 170990075Sobrien output_asm_insn (\"tst%?\\t%0, %1\", operands); 171090075Sobrien return \"\"; 171190075Sobrien " 171290075Sobrien [(set_attr "conds" "set")] 171390075Sobrien) 171490075Sobrien 171590075Sobrien(define_insn "*ne_zeroextractsi" 171690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 171790075Sobrien (ne:SI (zero_extract:SI 171890075Sobrien (match_operand:SI 1 "s_register_operand" "r") 171990075Sobrien (match_operand:SI 2 "const_int_operand" "n") 172090075Sobrien (match_operand:SI 3 "const_int_operand" "n")) 1721104752Skan (const_int 0))) 1722104752Skan (clobber (reg:CC CC_REGNUM))] 172390075Sobrien "TARGET_ARM 172490075Sobrien && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 172590075Sobrien && INTVAL (operands[2]) > 0 172690075Sobrien && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8 172790075Sobrien && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)" 172890075Sobrien "* 172990075Sobrien operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1) 173090075Sobrien << INTVAL (operands[3])); 173190075Sobrien output_asm_insn (\"ands\\t%0, %1, %2\", operands); 173290075Sobrien return \"movne\\t%0, #1\"; 173390075Sobrien " 173490075Sobrien [(set_attr "conds" "clob") 173590075Sobrien (set_attr "length" "8")] 173690075Sobrien) 173790075Sobrien 1738132718Skan(define_split 1739132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 1740132718Skan (zero_extract:SI (match_operand:SI 1 "s_register_operand" "") 1741132718Skan (match_operand:SI 2 "const_int_operand" "") 1742132718Skan (match_operand:SI 3 "const_int_operand" ""))) 1743132718Skan (clobber (match_operand:SI 4 "s_register_operand" ""))] 1744132718Skan "TARGET_THUMB" 1745132718Skan [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2))) 1746132718Skan (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))] 1747132718Skan "{ 1748132718Skan HOST_WIDE_INT temp = INTVAL (operands[2]); 1749132718Skan 1750132718Skan operands[2] = GEN_INT (32 - temp - INTVAL (operands[3])); 1751132718Skan operands[3] = GEN_INT (32 - temp); 1752132718Skan }" 1753132718Skan) 1754132718Skan 1755132718Skan(define_split 1756132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 1757132718Skan (match_operator:SI 1 "shiftable_operator" 1758132718Skan [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 1759132718Skan (match_operand:SI 3 "const_int_operand" "") 1760132718Skan (match_operand:SI 4 "const_int_operand" "")) 1761132718Skan (match_operand:SI 5 "s_register_operand" "")])) 1762132718Skan (clobber (match_operand:SI 6 "s_register_operand" ""))] 1763132718Skan "TARGET_ARM" 1764132718Skan [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3))) 1765132718Skan (set (match_dup 0) 1766132718Skan (match_op_dup 1 1767132718Skan [(lshiftrt:SI (match_dup 6) (match_dup 4)) 1768132718Skan (match_dup 5)]))] 1769132718Skan "{ 1770132718Skan HOST_WIDE_INT temp = INTVAL (operands[3]); 1771132718Skan 1772132718Skan operands[3] = GEN_INT (32 - temp - INTVAL (operands[4])); 1773132718Skan operands[4] = GEN_INT (32 - temp); 1774132718Skan }" 1775132718Skan) 1776132718Skan 1777132718Skan(define_split 1778132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 1779132718Skan (sign_extract:SI (match_operand:SI 1 "s_register_operand" "") 1780132718Skan (match_operand:SI 2 "const_int_operand" "") 1781132718Skan (match_operand:SI 3 "const_int_operand" "")))] 1782132718Skan "TARGET_THUMB" 1783132718Skan [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) 1784132718Skan (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))] 1785132718Skan "{ 1786132718Skan HOST_WIDE_INT temp = INTVAL (operands[2]); 1787132718Skan 1788132718Skan operands[2] = GEN_INT (32 - temp - INTVAL (operands[3])); 1789132718Skan operands[3] = GEN_INT (32 - temp); 1790132718Skan }" 1791132718Skan) 1792132718Skan 1793132718Skan(define_split 1794132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 1795132718Skan (match_operator:SI 1 "shiftable_operator" 1796132718Skan [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 1797132718Skan (match_operand:SI 3 "const_int_operand" "") 1798132718Skan (match_operand:SI 4 "const_int_operand" "")) 1799132718Skan (match_operand:SI 5 "s_register_operand" "")])) 1800132718Skan (clobber (match_operand:SI 6 "s_register_operand" ""))] 1801132718Skan "TARGET_ARM" 1802132718Skan [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3))) 1803132718Skan (set (match_dup 0) 1804132718Skan (match_op_dup 1 1805132718Skan [(ashiftrt:SI (match_dup 6) (match_dup 4)) 1806132718Skan (match_dup 5)]))] 1807132718Skan "{ 1808132718Skan HOST_WIDE_INT temp = INTVAL (operands[3]); 1809132718Skan 1810132718Skan operands[3] = GEN_INT (32 - temp - INTVAL (operands[4])); 1811132718Skan operands[4] = GEN_INT (32 - temp); 1812132718Skan }" 1813132718Skan) 1814132718Skan 181590075Sobrien;;; ??? This pattern is bogus. If operand3 has bits outside the range 181690075Sobrien;;; represented by the bitfield, then this will produce incorrect results. 181790075Sobrien;;; Somewhere, the value needs to be truncated. On targets like the m68k, 1818117395Skan;;; which have a real bit-field insert instruction, the truncation happens 1819117395Skan;;; in the bit-field insert instruction itself. Since arm does not have a 1820117395Skan;;; bit-field insert instruction, we would have to emit code here to truncate 182190075Sobrien;;; the value before we insert. This loses some of the advantage of having 182290075Sobrien;;; this insv pattern, so this pattern needs to be reevalutated. 182390075Sobrien 182490075Sobrien(define_expand "insv" 182590075Sobrien [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "") 182690075Sobrien (match_operand:SI 1 "general_operand" "") 182790075Sobrien (match_operand:SI 2 "general_operand" "")) 1828117395Skan (match_operand:SI 3 "reg_or_int_operand" ""))] 182990075Sobrien "TARGET_ARM" 183090075Sobrien " 183190075Sobrien { 183290075Sobrien int start_bit = INTVAL (operands[2]); 183390075Sobrien int width = INTVAL (operands[1]); 183490075Sobrien HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1; 183590075Sobrien rtx target, subtarget; 183690075Sobrien 183790075Sobrien target = operands[0]; 183890075Sobrien /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 183990075Sobrien subreg as the final target. */ 184090075Sobrien if (GET_CODE (target) == SUBREG) 184190075Sobrien { 184290075Sobrien subtarget = gen_reg_rtx (SImode); 184390075Sobrien if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target))) 184490075Sobrien < GET_MODE_SIZE (SImode)) 184590075Sobrien target = SUBREG_REG (target); 184690075Sobrien } 184790075Sobrien else 184890075Sobrien subtarget = target; 184990075Sobrien 185090075Sobrien if (GET_CODE (operands[3]) == CONST_INT) 185190075Sobrien { 185290075Sobrien /* Since we are inserting a known constant, we may be able to 185390075Sobrien reduce the number of bits that we have to clear so that 185490075Sobrien the mask becomes simple. */ 185590075Sobrien /* ??? This code does not check to see if the new mask is actually 185690075Sobrien simpler. It may not be. */ 185790075Sobrien rtx op1 = gen_reg_rtx (SImode); 185890075Sobrien /* ??? Truncate operand3 to fit in the bitfield. See comment before 185990075Sobrien start of this pattern. */ 186090075Sobrien HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]); 186190075Sobrien HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit); 186290075Sobrien 186390075Sobrien emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2))); 186490075Sobrien emit_insn (gen_iorsi3 (subtarget, op1, 186590075Sobrien GEN_INT (op3_value << start_bit))); 186690075Sobrien } 186790075Sobrien else if (start_bit == 0 186890075Sobrien && !(const_ok_for_arm (mask) 186990075Sobrien || const_ok_for_arm (~mask))) 187090075Sobrien { 187190075Sobrien /* A Trick, since we are setting the bottom bits in the word, 187290075Sobrien we can shift operand[3] up, operand[0] down, OR them together 187390075Sobrien and rotate the result back again. This takes 3 insns, and 1874132718Skan the third might be mergeable into another op. */ 187590075Sobrien /* The shift up copes with the possibility that operand[3] is 187690075Sobrien wider than the bitfield. */ 187790075Sobrien rtx op0 = gen_reg_rtx (SImode); 187890075Sobrien rtx op1 = gen_reg_rtx (SImode); 187990075Sobrien 188090075Sobrien emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 188190075Sobrien emit_insn (gen_lshrsi3 (op1, operands[0], operands[1])); 188290075Sobrien emit_insn (gen_iorsi3 (op1, op1, op0)); 188390075Sobrien emit_insn (gen_rotlsi3 (subtarget, op1, operands[1])); 188490075Sobrien } 188590075Sobrien else if ((width + start_bit == 32) 188690075Sobrien && !(const_ok_for_arm (mask) 188790075Sobrien || const_ok_for_arm (~mask))) 188890075Sobrien { 188990075Sobrien /* Similar trick, but slightly less efficient. */ 189090075Sobrien 189190075Sobrien rtx op0 = gen_reg_rtx (SImode); 189290075Sobrien rtx op1 = gen_reg_rtx (SImode); 189390075Sobrien 189490075Sobrien emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width))); 189590075Sobrien emit_insn (gen_ashlsi3 (op1, operands[0], operands[1])); 189690075Sobrien emit_insn (gen_lshrsi3 (op1, op1, operands[1])); 189790075Sobrien emit_insn (gen_iorsi3 (subtarget, op1, op0)); 189890075Sobrien } 189990075Sobrien else 190090075Sobrien { 190190075Sobrien rtx op0 = GEN_INT (mask); 190290075Sobrien rtx op1 = gen_reg_rtx (SImode); 190390075Sobrien rtx op2 = gen_reg_rtx (SImode); 190490075Sobrien 190590075Sobrien if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask))) 190690075Sobrien { 190790075Sobrien rtx tmp = gen_reg_rtx (SImode); 190890075Sobrien 190990075Sobrien emit_insn (gen_movsi (tmp, op0)); 191090075Sobrien op0 = tmp; 191190075Sobrien } 191290075Sobrien 191390075Sobrien /* Mask out any bits in operand[3] that are not needed. */ 191490075Sobrien emit_insn (gen_andsi3 (op1, operands[3], op0)); 191590075Sobrien 191690075Sobrien if (GET_CODE (op0) == CONST_INT 191790075Sobrien && (const_ok_for_arm (mask << start_bit) 191890075Sobrien || const_ok_for_arm (~(mask << start_bit)))) 191990075Sobrien { 192090075Sobrien op0 = GEN_INT (~(mask << start_bit)); 192190075Sobrien emit_insn (gen_andsi3 (op2, operands[0], op0)); 192290075Sobrien } 192390075Sobrien else 192490075Sobrien { 192590075Sobrien if (GET_CODE (op0) == CONST_INT) 192690075Sobrien { 192790075Sobrien rtx tmp = gen_reg_rtx (SImode); 192890075Sobrien 192990075Sobrien emit_insn (gen_movsi (tmp, op0)); 193090075Sobrien op0 = tmp; 193190075Sobrien } 193290075Sobrien 193390075Sobrien if (start_bit != 0) 193490075Sobrien emit_insn (gen_ashlsi3 (op0, op0, operands[2])); 193590075Sobrien 193690075Sobrien emit_insn (gen_andsi_notsi_si (op2, operands[0], op0)); 193790075Sobrien } 193890075Sobrien 193990075Sobrien if (start_bit != 0) 194090075Sobrien emit_insn (gen_ashlsi3 (op1, op1, operands[2])); 194190075Sobrien 194290075Sobrien emit_insn (gen_iorsi3 (subtarget, op1, op2)); 194390075Sobrien } 194490075Sobrien 194590075Sobrien if (subtarget != target) 194690075Sobrien { 194790075Sobrien /* If TARGET is still a SUBREG, then it must be wider than a word, 194890075Sobrien so we must be careful only to set the subword we were asked to. */ 194990075Sobrien if (GET_CODE (target) == SUBREG) 195090075Sobrien emit_move_insn (target, subtarget); 195190075Sobrien else 195290075Sobrien emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget)); 195390075Sobrien } 195490075Sobrien 195590075Sobrien DONE; 195690075Sobrien }" 195790075Sobrien) 195890075Sobrien 195990075Sobrien; constants for op 2 will never be given to these patterns. 196090075Sobrien(define_insn_and_split "*anddi_notdi_di" 196190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 196290075Sobrien (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0")) 196390075Sobrien (match_operand:DI 2 "s_register_operand" "0,r")))] 196490075Sobrien "TARGET_ARM" 196590075Sobrien "#" 1966132718Skan "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))" 196790075Sobrien [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2))) 196890075Sobrien (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))] 196990075Sobrien " 197090075Sobrien { 197190075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 197290075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 197390075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 197490075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 197590075Sobrien operands[5] = gen_highpart (SImode, operands[2]); 197690075Sobrien operands[2] = gen_lowpart (SImode, operands[2]); 197790075Sobrien }" 197890075Sobrien [(set_attr "length" "8") 197990075Sobrien (set_attr "predicable" "yes")] 198090075Sobrien) 198190075Sobrien 198290075Sobrien(define_insn_and_split "*anddi_notzesidi_di" 198390075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 198490075Sobrien (and:DI (not:DI (zero_extend:DI 198590075Sobrien (match_operand:SI 2 "s_register_operand" "r,r"))) 198690075Sobrien (match_operand:DI 1 "s_register_operand" "0,?r")))] 198790075Sobrien "TARGET_ARM" 198890075Sobrien "@ 198990075Sobrien bic%?\\t%Q0, %Q1, %2 199090075Sobrien #" 199190075Sobrien ; (not (zero_extend ...)) allows us to just copy the high word from 199290075Sobrien ; operand1 to operand0. 199390075Sobrien "TARGET_ARM 199490075Sobrien && reload_completed 199590075Sobrien && operands[0] != operands[1]" 1996117395Skan [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) 199790075Sobrien (set (match_dup 3) (match_dup 4))] 199890075Sobrien " 199990075Sobrien { 200090075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 200190075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 200290075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 200390075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 200490075Sobrien }" 200590075Sobrien [(set_attr "length" "4,8") 200690075Sobrien (set_attr "predicable" "yes")] 200790075Sobrien) 200890075Sobrien 200990075Sobrien(define_insn_and_split "*anddi_notsesidi_di" 201090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 201190075Sobrien (and:DI (not:DI (sign_extend:DI 201290075Sobrien (match_operand:SI 2 "s_register_operand" "r,r"))) 2013117395Skan (match_operand:DI 1 "s_register_operand" "0,r")))] 201490075Sobrien "TARGET_ARM" 201590075Sobrien "#" 201690075Sobrien "TARGET_ARM && reload_completed" 2017117395Skan [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) 201890075Sobrien (set (match_dup 3) (and:SI (not:SI 201990075Sobrien (ashiftrt:SI (match_dup 2) (const_int 31))) 202090075Sobrien (match_dup 4)))] 202190075Sobrien " 202290075Sobrien { 202390075Sobrien operands[3] = gen_highpart (SImode, operands[0]); 202490075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 202590075Sobrien operands[4] = gen_highpart (SImode, operands[1]); 202690075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 202790075Sobrien }" 202890075Sobrien [(set_attr "length" "8") 202990075Sobrien (set_attr "predicable" "yes")] 203090075Sobrien) 203190075Sobrien 203290075Sobrien(define_insn "andsi_notsi_si" 203390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 203490075Sobrien (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 203590075Sobrien (match_operand:SI 1 "s_register_operand" "r")))] 203690075Sobrien "TARGET_ARM" 203790075Sobrien "bic%?\\t%0, %1, %2" 203890075Sobrien [(set_attr "predicable" "yes")] 203990075Sobrien) 204090075Sobrien 204190075Sobrien(define_insn "bicsi3" 204290075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 204390075Sobrien (and:SI (not:SI (match_operand:SI 1 "register_operand" "l")) 204490075Sobrien (match_operand:SI 2 "register_operand" "0")))] 204590075Sobrien "TARGET_THUMB" 204690075Sobrien "bic\\t%0, %0, %1" 204790075Sobrien [(set_attr "length" "2")] 204890075Sobrien) 204990075Sobrien 205090075Sobrien(define_insn "andsi_not_shiftsi_si" 205190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 205290075Sobrien (and:SI (not:SI (match_operator:SI 4 "shift_operator" 205390075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 205490075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM")])) 205590075Sobrien (match_operand:SI 1 "s_register_operand" "r")))] 205690075Sobrien "TARGET_ARM" 205790075Sobrien "bic%?\\t%0, %1, %2%S4" 205890075Sobrien [(set_attr "predicable" "yes") 205990075Sobrien (set_attr "shift" "2") 206090075Sobrien ] 206190075Sobrien) 206290075Sobrien 206390075Sobrien(define_insn "*andsi_notsi_si_compare0" 206490075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 206590075Sobrien (compare:CC_NOOV 206690075Sobrien (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 206790075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 206890075Sobrien (const_int 0))) 206990075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 207090075Sobrien (and:SI (not:SI (match_dup 2)) (match_dup 1)))] 207190075Sobrien "TARGET_ARM" 207290075Sobrien "bic%?s\\t%0, %1, %2" 207390075Sobrien [(set_attr "conds" "set")] 207490075Sobrien) 207590075Sobrien 207690075Sobrien(define_insn "*andsi_notsi_si_compare0_scratch" 207790075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 207890075Sobrien (compare:CC_NOOV 207990075Sobrien (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 208090075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 208190075Sobrien (const_int 0))) 208290075Sobrien (clobber (match_scratch:SI 0 "=r"))] 208390075Sobrien "TARGET_ARM" 208490075Sobrien "bic%?s\\t%0, %1, %2" 208590075Sobrien [(set_attr "conds" "set")] 208690075Sobrien) 208790075Sobrien 208890075Sobrien(define_insn "iordi3" 208990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 209090075Sobrien (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r") 209190075Sobrien (match_operand:DI 2 "s_register_operand" "r,r")))] 2092132718Skan "TARGET_ARM && ! TARGET_IWMMXT" 209390075Sobrien "#" 209490075Sobrien [(set_attr "length" "8") 209590075Sobrien (set_attr "predicable" "yes")] 209690075Sobrien) 209790075Sobrien 209890075Sobrien(define_insn "*iordi_zesidi_di" 209990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 210090075Sobrien (ior:DI (zero_extend:DI 210190075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 210290075Sobrien (match_operand:DI 1 "s_register_operand" "0,?r")))] 210390075Sobrien "TARGET_ARM" 210490075Sobrien "@ 210590075Sobrien orr%?\\t%Q0, %Q1, %2 210690075Sobrien #" 210790075Sobrien [(set_attr "length" "4,8") 210890075Sobrien (set_attr "predicable" "yes")] 210990075Sobrien) 211090075Sobrien 211190075Sobrien(define_insn "*iordi_sesidi_di" 211290075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 211390075Sobrien (ior:DI (sign_extend:DI 211490075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 211590075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0")))] 211690075Sobrien "TARGET_ARM" 211790075Sobrien "#" 211890075Sobrien [(set_attr "length" "8") 211990075Sobrien (set_attr "predicable" "yes")] 212090075Sobrien) 212190075Sobrien 212290075Sobrien(define_expand "iorsi3" 212390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 212490075Sobrien (ior:SI (match_operand:SI 1 "s_register_operand" "") 212590075Sobrien (match_operand:SI 2 "reg_or_int_operand" "")))] 212690075Sobrien "TARGET_EITHER" 212790075Sobrien " 212890075Sobrien if (GET_CODE (operands[2]) == CONST_INT) 212990075Sobrien { 213090075Sobrien if (TARGET_ARM) 213190075Sobrien { 213290075Sobrien arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], 213390075Sobrien operands[1], 213490075Sobrien (no_new_pseudos 213590075Sobrien ? 0 : preserve_subexpressions_p ())); 213690075Sobrien DONE; 213790075Sobrien } 213890075Sobrien else /* TARGET_THUMB */ 213990075Sobrien operands [2] = force_reg (SImode, operands [2]); 214090075Sobrien } 214190075Sobrien " 214290075Sobrien) 214390075Sobrien 214490075Sobrien(define_insn_and_split "*arm_iorsi3" 214590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 214690075Sobrien (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") 214790075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] 214890075Sobrien "TARGET_ARM" 214990075Sobrien "@ 215090075Sobrien orr%?\\t%0, %1, %2 215190075Sobrien #" 215290075Sobrien "TARGET_ARM 215390075Sobrien && GET_CODE (operands[2]) == CONST_INT 215490075Sobrien && !const_ok_for_arm (INTVAL (operands[2]))" 215590075Sobrien [(clobber (const_int 0))] 215690075Sobrien " 215790075Sobrien arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0], 215890075Sobrien operands[1], 0); 215990075Sobrien DONE; 216090075Sobrien " 216190075Sobrien [(set_attr "length" "4,16") 216290075Sobrien (set_attr "predicable" "yes")] 216390075Sobrien) 216490075Sobrien 216590075Sobrien(define_insn "*thumb_iorsi3" 216690075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 216790075Sobrien (ior:SI (match_operand:SI 1 "register_operand" "%0") 216890075Sobrien (match_operand:SI 2 "register_operand" "l")))] 216990075Sobrien "TARGET_THUMB" 217090075Sobrien "orr\\t%0, %0, %2" 217190075Sobrien [(set_attr "length" "2")] 217290075Sobrien) 217390075Sobrien 217490075Sobrien(define_peephole2 217590075Sobrien [(match_scratch:SI 3 "r") 217690075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 217790075Sobrien (ior:SI (match_operand:SI 1 "s_register_operand" "") 217890075Sobrien (match_operand:SI 2 "const_int_operand" "")))] 217990075Sobrien "TARGET_ARM 218090075Sobrien && !const_ok_for_arm (INTVAL (operands[2])) 218190075Sobrien && const_ok_for_arm (~INTVAL (operands[2]))" 218290075Sobrien [(set (match_dup 3) (match_dup 2)) 218390075Sobrien (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))] 218490075Sobrien "" 218590075Sobrien) 218690075Sobrien 218790075Sobrien(define_insn "*iorsi3_compare0" 218890075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 218990075Sobrien (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 219090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 219190075Sobrien (const_int 0))) 219290075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 219390075Sobrien (ior:SI (match_dup 1) (match_dup 2)))] 219490075Sobrien "TARGET_ARM" 219590075Sobrien "orr%?s\\t%0, %1, %2" 219690075Sobrien [(set_attr "conds" "set")] 219790075Sobrien) 219890075Sobrien 219990075Sobrien(define_insn "*iorsi3_compare0_scratch" 220090075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 220190075Sobrien (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r") 220290075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 220390075Sobrien (const_int 0))) 220490075Sobrien (clobber (match_scratch:SI 0 "=r"))] 220590075Sobrien "TARGET_ARM" 220690075Sobrien "orr%?s\\t%0, %1, %2" 220790075Sobrien [(set_attr "conds" "set")] 220890075Sobrien) 220990075Sobrien 221090075Sobrien(define_insn "xordi3" 221190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 221290075Sobrien (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r") 221390075Sobrien (match_operand:DI 2 "s_register_operand" "r,r")))] 2214132718Skan "TARGET_ARM && !TARGET_IWMMXT" 221590075Sobrien "#" 221690075Sobrien [(set_attr "length" "8") 221790075Sobrien (set_attr "predicable" "yes")] 221890075Sobrien) 221990075Sobrien 222090075Sobrien(define_insn "*xordi_zesidi_di" 222190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 222290075Sobrien (xor:DI (zero_extend:DI 222390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 222490075Sobrien (match_operand:DI 1 "s_register_operand" "0,?r")))] 222590075Sobrien "TARGET_ARM" 222690075Sobrien "@ 222790075Sobrien eor%?\\t%Q0, %Q1, %2 222890075Sobrien #" 222990075Sobrien [(set_attr "length" "4,8") 223090075Sobrien (set_attr "predicable" "yes")] 223190075Sobrien) 223290075Sobrien 223390075Sobrien(define_insn "*xordi_sesidi_di" 223490075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 223590075Sobrien (xor:DI (sign_extend:DI 223690075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 223790075Sobrien (match_operand:DI 1 "s_register_operand" "?r,0")))] 223890075Sobrien "TARGET_ARM" 223990075Sobrien "#" 224090075Sobrien [(set_attr "length" "8") 224190075Sobrien (set_attr "predicable" "yes")] 224290075Sobrien) 224390075Sobrien 224490075Sobrien(define_expand "xorsi3" 224590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 224690075Sobrien (xor:SI (match_operand:SI 1 "s_register_operand" "") 224790075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 224890075Sobrien "TARGET_EITHER" 224990075Sobrien "if (TARGET_THUMB) 225090075Sobrien if (GET_CODE (operands[2]) == CONST_INT) 225190075Sobrien operands[2] = force_reg (SImode, operands[2]); 225290075Sobrien " 225390075Sobrien) 225490075Sobrien 225590075Sobrien(define_insn "*arm_xorsi3" 225690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 225790075Sobrien (xor:SI (match_operand:SI 1 "s_register_operand" "r") 225890075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")))] 225990075Sobrien "TARGET_ARM" 226090075Sobrien "eor%?\\t%0, %1, %2" 226190075Sobrien [(set_attr "predicable" "yes")] 226290075Sobrien) 226390075Sobrien 226490075Sobrien(define_insn "*thumb_xorsi3" 226590075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 226690075Sobrien (xor:SI (match_operand:SI 1 "register_operand" "%0") 226790075Sobrien (match_operand:SI 2 "register_operand" "l")))] 226890075Sobrien "TARGET_THUMB" 226990075Sobrien "eor\\t%0, %0, %2" 227090075Sobrien [(set_attr "length" "2")] 227190075Sobrien) 227290075Sobrien 227390075Sobrien(define_insn "*xorsi3_compare0" 227490075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 227590075Sobrien (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r") 227690075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")) 227790075Sobrien (const_int 0))) 227890075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 227990075Sobrien (xor:SI (match_dup 1) (match_dup 2)))] 228090075Sobrien "TARGET_ARM" 228190075Sobrien "eor%?s\\t%0, %1, %2" 228290075Sobrien [(set_attr "conds" "set")] 228390075Sobrien) 228490075Sobrien 228590075Sobrien(define_insn "*xorsi3_compare0_scratch" 228690075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 228790075Sobrien (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r") 228890075Sobrien (match_operand:SI 1 "arm_rhs_operand" "rI")) 228990075Sobrien (const_int 0)))] 229090075Sobrien "TARGET_ARM" 229190075Sobrien "teq%?\\t%0, %1" 229290075Sobrien [(set_attr "conds" "set")] 229390075Sobrien) 229490075Sobrien 229590075Sobrien; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 229690075Sobrien; (NOT D) we can sometimes merge the final NOT into one of the following 229790075Sobrien; insns. 229890075Sobrien 229990075Sobrien(define_split 2300117395Skan [(set (match_operand:SI 0 "s_register_operand" "") 2301117395Skan (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "")) 2302117395Skan (not:SI (match_operand:SI 2 "arm_rhs_operand" ""))) 2303117395Skan (match_operand:SI 3 "arm_rhs_operand" ""))) 2304117395Skan (clobber (match_operand:SI 4 "s_register_operand" ""))] 230590075Sobrien "TARGET_ARM" 230690075Sobrien [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2)) 230790075Sobrien (not:SI (match_dup 3)))) 230890075Sobrien (set (match_dup 0) (not:SI (match_dup 4)))] 230990075Sobrien "" 231090075Sobrien) 231190075Sobrien 231290075Sobrien(define_insn "*andsi_iorsi3_notsi" 231390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 231490075Sobrien (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0") 231590075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")) 231690075Sobrien (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))] 231790075Sobrien "TARGET_ARM" 231890075Sobrien "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3" 231990075Sobrien [(set_attr "length" "8") 232090075Sobrien (set_attr "predicable" "yes")] 232190075Sobrien) 232290075Sobrien 2323132718Skan(define_split 2324132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2325132718Skan (match_operator:SI 1 "logical_binary_operator" 2326132718Skan [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 2327132718Skan (match_operand:SI 3 "const_int_operand" "") 2328132718Skan (match_operand:SI 4 "const_int_operand" "")) 2329132718Skan (match_operator:SI 9 "logical_binary_operator" 2330132718Skan [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2331132718Skan (match_operand:SI 6 "const_int_operand" "")) 2332132718Skan (match_operand:SI 7 "s_register_operand" "")])])) 2333132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 2334132718Skan "TARGET_ARM 2335132718Skan && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2336132718Skan && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2337132718Skan [(set (match_dup 8) 2338132718Skan (match_op_dup 1 2339132718Skan [(ashift:SI (match_dup 2) (match_dup 4)) 2340132718Skan (match_dup 5)])) 2341132718Skan (set (match_dup 0) 2342132718Skan (match_op_dup 1 2343132718Skan [(lshiftrt:SI (match_dup 8) (match_dup 6)) 2344132718Skan (match_dup 7)]))] 2345132718Skan " 2346132718Skan operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2347132718Skan") 2348132718Skan 2349132718Skan(define_split 2350132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2351132718Skan (match_operator:SI 1 "logical_binary_operator" 2352132718Skan [(match_operator:SI 9 "logical_binary_operator" 2353132718Skan [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2354132718Skan (match_operand:SI 6 "const_int_operand" "")) 2355132718Skan (match_operand:SI 7 "s_register_operand" "")]) 2356132718Skan (zero_extract:SI (match_operand:SI 2 "s_register_operand" "") 2357132718Skan (match_operand:SI 3 "const_int_operand" "") 2358132718Skan (match_operand:SI 4 "const_int_operand" ""))])) 2359132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 2360132718Skan "TARGET_ARM 2361132718Skan && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2362132718Skan && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2363132718Skan [(set (match_dup 8) 2364132718Skan (match_op_dup 1 2365132718Skan [(ashift:SI (match_dup 2) (match_dup 4)) 2366132718Skan (match_dup 5)])) 2367132718Skan (set (match_dup 0) 2368132718Skan (match_op_dup 1 2369132718Skan [(lshiftrt:SI (match_dup 8) (match_dup 6)) 2370132718Skan (match_dup 7)]))] 2371132718Skan " 2372132718Skan operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2373132718Skan") 2374132718Skan 2375132718Skan(define_split 2376132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2377132718Skan (match_operator:SI 1 "logical_binary_operator" 2378132718Skan [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 2379132718Skan (match_operand:SI 3 "const_int_operand" "") 2380132718Skan (match_operand:SI 4 "const_int_operand" "")) 2381132718Skan (match_operator:SI 9 "logical_binary_operator" 2382132718Skan [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2383132718Skan (match_operand:SI 6 "const_int_operand" "")) 2384132718Skan (match_operand:SI 7 "s_register_operand" "")])])) 2385132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 2386132718Skan "TARGET_ARM 2387132718Skan && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2388132718Skan && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2389132718Skan [(set (match_dup 8) 2390132718Skan (match_op_dup 1 2391132718Skan [(ashift:SI (match_dup 2) (match_dup 4)) 2392132718Skan (match_dup 5)])) 2393132718Skan (set (match_dup 0) 2394132718Skan (match_op_dup 1 2395132718Skan [(ashiftrt:SI (match_dup 8) (match_dup 6)) 2396132718Skan (match_dup 7)]))] 2397132718Skan " 2398132718Skan operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2399132718Skan") 2400132718Skan 2401132718Skan(define_split 2402132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2403132718Skan (match_operator:SI 1 "logical_binary_operator" 2404132718Skan [(match_operator:SI 9 "logical_binary_operator" 2405132718Skan [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "") 2406132718Skan (match_operand:SI 6 "const_int_operand" "")) 2407132718Skan (match_operand:SI 7 "s_register_operand" "")]) 2408132718Skan (sign_extract:SI (match_operand:SI 2 "s_register_operand" "") 2409132718Skan (match_operand:SI 3 "const_int_operand" "") 2410132718Skan (match_operand:SI 4 "const_int_operand" ""))])) 2411132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 2412132718Skan "TARGET_ARM 2413132718Skan && GET_CODE (operands[1]) == GET_CODE (operands[9]) 2414132718Skan && INTVAL (operands[3]) == 32 - INTVAL (operands[6])" 2415132718Skan [(set (match_dup 8) 2416132718Skan (match_op_dup 1 2417132718Skan [(ashift:SI (match_dup 2) (match_dup 4)) 2418132718Skan (match_dup 5)])) 2419132718Skan (set (match_dup 0) 2420132718Skan (match_op_dup 1 2421132718Skan [(ashiftrt:SI (match_dup 8) (match_dup 6)) 2422132718Skan (match_dup 7)]))] 2423132718Skan " 2424132718Skan operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4]))); 2425132718Skan") 242690075Sobrien 242790075Sobrien 242890075Sobrien;; Minimum and maximum insns 242990075Sobrien 243090075Sobrien(define_insn "smaxsi3" 243190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 243290075Sobrien (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 243390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 243490075Sobrien (clobber (reg:CC CC_REGNUM))] 243590075Sobrien "TARGET_ARM" 243690075Sobrien "@ 243790075Sobrien cmp\\t%1, %2\;movlt\\t%0, %2 243890075Sobrien cmp\\t%1, %2\;movge\\t%0, %1 243990075Sobrien cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2" 244090075Sobrien [(set_attr "conds" "clob") 244190075Sobrien (set_attr "length" "8,8,12")] 244290075Sobrien) 244390075Sobrien 244490075Sobrien(define_insn "sminsi3" 244590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 244690075Sobrien (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 244790075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 244890075Sobrien (clobber (reg:CC CC_REGNUM))] 244990075Sobrien "TARGET_ARM" 245090075Sobrien "@ 245190075Sobrien cmp\\t%1, %2\;movge\\t%0, %2 245290075Sobrien cmp\\t%1, %2\;movlt\\t%0, %1 245390075Sobrien cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2" 245490075Sobrien [(set_attr "conds" "clob") 245590075Sobrien (set_attr "length" "8,8,12")] 245690075Sobrien) 245790075Sobrien 245890075Sobrien(define_insn "umaxsi3" 245990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 246090075Sobrien (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 246190075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 246290075Sobrien (clobber (reg:CC CC_REGNUM))] 246390075Sobrien "TARGET_ARM" 246490075Sobrien "@ 246590075Sobrien cmp\\t%1, %2\;movcc\\t%0, %2 246690075Sobrien cmp\\t%1, %2\;movcs\\t%0, %1 246790075Sobrien cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2" 246890075Sobrien [(set_attr "conds" "clob") 246990075Sobrien (set_attr "length" "8,8,12")] 247090075Sobrien) 247190075Sobrien 247290075Sobrien(define_insn "uminsi3" 247390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 247490075Sobrien (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 247590075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 247690075Sobrien (clobber (reg:CC CC_REGNUM))] 247790075Sobrien "TARGET_ARM" 247890075Sobrien "@ 247990075Sobrien cmp\\t%1, %2\;movcs\\t%0, %2 248090075Sobrien cmp\\t%1, %2\;movcc\\t%0, %1 248190075Sobrien cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2" 248290075Sobrien [(set_attr "conds" "clob") 248390075Sobrien (set_attr "length" "8,8,12")] 248490075Sobrien) 248590075Sobrien 248690075Sobrien(define_insn "*store_minmaxsi" 248790075Sobrien [(set (match_operand:SI 0 "memory_operand" "=m") 248890075Sobrien (match_operator:SI 3 "minmax_operator" 248990075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 249090075Sobrien (match_operand:SI 2 "s_register_operand" "r")])) 249190075Sobrien (clobber (reg:CC CC_REGNUM))] 249290075Sobrien "TARGET_ARM" 249390075Sobrien "* 249490075Sobrien operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1], 249590075Sobrien operands[2]); 249690075Sobrien output_asm_insn (\"cmp\\t%1, %2\", operands); 249790075Sobrien output_asm_insn (\"str%d3\\t%1, %0\", operands); 249890075Sobrien output_asm_insn (\"str%D3\\t%2, %0\", operands); 249990075Sobrien return \"\"; 250090075Sobrien " 250190075Sobrien [(set_attr "conds" "clob") 250290075Sobrien (set_attr "length" "12") 250390075Sobrien (set_attr "type" "store1")] 250490075Sobrien) 250590075Sobrien 250690075Sobrien; Reject the frame pointer in operand[1], since reloading this after 250790075Sobrien; it has been eliminated can cause carnage. 250890075Sobrien(define_insn "*minmax_arithsi" 250990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 251090075Sobrien (match_operator:SI 4 "shiftable_operator" 251190075Sobrien [(match_operator:SI 5 "minmax_operator" 251290075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 251390075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 251490075Sobrien (match_operand:SI 1 "s_register_operand" "0,?r")])) 251590075Sobrien (clobber (reg:CC CC_REGNUM))] 251690075Sobrien "TARGET_ARM 251790075Sobrien && (GET_CODE (operands[1]) != REG 251890075Sobrien || (REGNO(operands[1]) != FRAME_POINTER_REGNUM 251990075Sobrien && REGNO(operands[1]) != ARG_POINTER_REGNUM))" 252090075Sobrien "* 252190075Sobrien { 252290075Sobrien enum rtx_code code = GET_CODE (operands[4]); 252390075Sobrien 252490075Sobrien operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2], 252590075Sobrien operands[3]); 252690075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 252790075Sobrien output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands); 252890075Sobrien if (which_alternative != 0 || operands[3] != const0_rtx 252990075Sobrien || (code != PLUS && code != MINUS && code != IOR && code != XOR)) 253090075Sobrien output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands); 253190075Sobrien return \"\"; 253290075Sobrien }" 253390075Sobrien [(set_attr "conds" "clob") 253490075Sobrien (set_attr "length" "12")] 253590075Sobrien) 253690075Sobrien 253790075Sobrien 253890075Sobrien;; Shift and rotation insns 253990075Sobrien 254090075Sobrien(define_expand "ashlsi3" 254190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 254290075Sobrien (ashift:SI (match_operand:SI 1 "s_register_operand" "") 254390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 254490075Sobrien "TARGET_EITHER" 254590075Sobrien " 254690075Sobrien if (GET_CODE (operands[2]) == CONST_INT 254790075Sobrien && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 254890075Sobrien { 254990075Sobrien emit_insn (gen_movsi (operands[0], const0_rtx)); 255090075Sobrien DONE; 255190075Sobrien } 255290075Sobrien " 255390075Sobrien) 255490075Sobrien 255590075Sobrien(define_insn "*thumb_ashlsi3" 255690075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l") 255790075Sobrien (ashift:SI (match_operand:SI 1 "register_operand" "l,0") 255890075Sobrien (match_operand:SI 2 "nonmemory_operand" "N,l")))] 255990075Sobrien "TARGET_THUMB" 256090075Sobrien "lsl\\t%0, %1, %2" 256190075Sobrien [(set_attr "length" "2")] 256290075Sobrien) 256390075Sobrien 256490075Sobrien(define_expand "ashrsi3" 256590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 256690075Sobrien (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "") 256790075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 256890075Sobrien "TARGET_EITHER" 256990075Sobrien " 257090075Sobrien if (GET_CODE (operands[2]) == CONST_INT 257190075Sobrien && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 257290075Sobrien operands[2] = GEN_INT (31); 257390075Sobrien " 257490075Sobrien) 257590075Sobrien 257690075Sobrien(define_insn "*thumb_ashrsi3" 257790075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l") 257890075Sobrien (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 257990075Sobrien (match_operand:SI 2 "nonmemory_operand" "N,l")))] 258090075Sobrien "TARGET_THUMB" 258190075Sobrien "asr\\t%0, %1, %2" 258290075Sobrien [(set_attr "length" "2")] 258390075Sobrien) 258490075Sobrien 258590075Sobrien(define_expand "lshrsi3" 258690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 258790075Sobrien (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "") 258890075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 258990075Sobrien "TARGET_EITHER" 259090075Sobrien " 259190075Sobrien if (GET_CODE (operands[2]) == CONST_INT 259290075Sobrien && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 259390075Sobrien { 259490075Sobrien emit_insn (gen_movsi (operands[0], const0_rtx)); 259590075Sobrien DONE; 259690075Sobrien } 259790075Sobrien " 259890075Sobrien) 259990075Sobrien 260090075Sobrien(define_insn "*thumb_lshrsi3" 260190075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l") 260290075Sobrien (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 260390075Sobrien (match_operand:SI 2 "nonmemory_operand" "N,l")))] 260490075Sobrien "TARGET_THUMB" 260590075Sobrien "lsr\\t%0, %1, %2" 260690075Sobrien [(set_attr "length" "2")] 260790075Sobrien) 260890075Sobrien 260990075Sobrien(define_expand "rotlsi3" 261090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 261190075Sobrien (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 261290075Sobrien (match_operand:SI 2 "reg_or_int_operand" "")))] 261390075Sobrien "TARGET_ARM" 261490075Sobrien " 261590075Sobrien if (GET_CODE (operands[2]) == CONST_INT) 261690075Sobrien operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32); 261790075Sobrien else 261890075Sobrien { 261990075Sobrien rtx reg = gen_reg_rtx (SImode); 262090075Sobrien emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2])); 262190075Sobrien operands[2] = reg; 262290075Sobrien } 262390075Sobrien " 262490075Sobrien) 262590075Sobrien 262690075Sobrien(define_expand "rotrsi3" 262790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 262890075Sobrien (rotatert:SI (match_operand:SI 1 "s_register_operand" "") 262990075Sobrien (match_operand:SI 2 "arm_rhs_operand" "")))] 263090075Sobrien "TARGET_EITHER" 263190075Sobrien " 263290075Sobrien if (TARGET_ARM) 263390075Sobrien { 263490075Sobrien if (GET_CODE (operands[2]) == CONST_INT 263590075Sobrien && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31) 263690075Sobrien operands[2] = GEN_INT (INTVAL (operands[2]) % 32); 263790075Sobrien } 263890075Sobrien else /* TARGET_THUMB */ 263990075Sobrien { 264090075Sobrien if (GET_CODE (operands [2]) == CONST_INT) 264190075Sobrien operands [2] = force_reg (SImode, operands[2]); 264290075Sobrien } 264390075Sobrien " 264490075Sobrien) 264590075Sobrien 264690075Sobrien(define_insn "*thumb_rotrsi3" 264790075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 264890075Sobrien (rotatert:SI (match_operand:SI 1 "register_operand" "0") 264990075Sobrien (match_operand:SI 2 "register_operand" "l")))] 265090075Sobrien "TARGET_THUMB" 265190075Sobrien "ror\\t%0, %0, %2" 265290075Sobrien [(set_attr "length" "2")] 265390075Sobrien) 265490075Sobrien 2655132718Skan(define_expand "ashldi3" 2656132718Skan [(set (match_operand:DI 0 "s_register_operand" "") 2657132718Skan (ashift:DI (match_operand:DI 1 "general_operand" "") 2658132718Skan (match_operand:SI 2 "general_operand" "")))] 2659132718Skan "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)" 2660132718Skan " 2661132718Skan if (! s_register_operand (operands[1], DImode)) 2662132718Skan operands[1] = copy_to_mode_reg (DImode, operands[1]); 2663132718Skan if (! s_register_operand (operands[2], SImode)) 2664132718Skan operands[2] = copy_to_mode_reg (SImode, operands[2]); 2665132718Skan " 2666132718Skan) 2667132718Skan 266890075Sobrien(define_insn "*arm_shiftsi3" 266990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 267090075Sobrien (match_operator:SI 3 "shift_operator" 267190075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 267290075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rM")]))] 267390075Sobrien "TARGET_ARM" 267490075Sobrien "mov%?\\t%0, %1%S3" 267590075Sobrien [(set_attr "predicable" "yes") 267690075Sobrien (set_attr "shift" "1") 267790075Sobrien ] 267890075Sobrien) 267990075Sobrien 268090075Sobrien(define_insn "*shiftsi3_compare0" 268190075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 268290075Sobrien (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 268390075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 268490075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]) 268590075Sobrien (const_int 0))) 268690075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 268790075Sobrien (match_op_dup 3 [(match_dup 1) (match_dup 2)]))] 268890075Sobrien "TARGET_ARM" 268990075Sobrien "mov%?s\\t%0, %1%S3" 269090075Sobrien [(set_attr "conds" "set") 269190075Sobrien (set_attr "shift" "1") 269290075Sobrien ] 269390075Sobrien) 269490075Sobrien 269590075Sobrien(define_insn "*shiftsi3_compare0_scratch" 269690075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 269790075Sobrien (compare:CC_NOOV (match_operator:SI 3 "shift_operator" 269890075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 269990075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]) 270090075Sobrien (const_int 0))) 270190075Sobrien (clobber (match_scratch:SI 0 "=r"))] 270290075Sobrien "TARGET_ARM" 270390075Sobrien "mov%?s\\t%0, %1%S3" 270490075Sobrien [(set_attr "conds" "set") 270590075Sobrien (set_attr "shift" "1") 270690075Sobrien ] 270790075Sobrien) 270890075Sobrien 270990075Sobrien(define_insn "*notsi_shiftsi" 271090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 271190075Sobrien (not:SI (match_operator:SI 3 "shift_operator" 271290075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 271390075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 271490075Sobrien "TARGET_ARM" 271590075Sobrien "mvn%?\\t%0, %1%S3" 271690075Sobrien [(set_attr "predicable" "yes") 271790075Sobrien (set_attr "shift" "1") 271890075Sobrien ] 271990075Sobrien) 272090075Sobrien 272190075Sobrien(define_insn "*notsi_shiftsi_compare0" 272290075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 272390075Sobrien (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 272490075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 272590075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")])) 272690075Sobrien (const_int 0))) 272790075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 272890075Sobrien (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] 272990075Sobrien "TARGET_ARM" 273090075Sobrien "mvn%?s\\t%0, %1%S3" 273190075Sobrien [(set_attr "conds" "set") 273290075Sobrien (set_attr "shift" "1") 273390075Sobrien ] 273490075Sobrien) 273590075Sobrien 273690075Sobrien(define_insn "*not_shiftsi_compare0_scratch" 273790075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 273890075Sobrien (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 273990075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 274090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")])) 274190075Sobrien (const_int 0))) 274290075Sobrien (clobber (match_scratch:SI 0 "=r"))] 274390075Sobrien "TARGET_ARM" 274490075Sobrien "mvn%?s\\t%0, %1%S3" 274590075Sobrien [(set_attr "conds" "set") 274690075Sobrien (set_attr "shift" "1") 274790075Sobrien ] 274890075Sobrien) 274990075Sobrien 275090075Sobrien;; We don't really have extzv, but defining this using shifts helps 275190075Sobrien;; to reduce register pressure later on. 275290075Sobrien 275390075Sobrien(define_expand "extzv" 275490075Sobrien [(set (match_dup 4) 275590075Sobrien (ashift:SI (match_operand:SI 1 "register_operand" "") 275690075Sobrien (match_operand:SI 2 "const_int_operand" ""))) 275790075Sobrien (set (match_operand:SI 0 "register_operand" "") 275890075Sobrien (lshiftrt:SI (match_dup 4) 275990075Sobrien (match_operand:SI 3 "const_int_operand" "")))] 276090075Sobrien "TARGET_THUMB" 276190075Sobrien " 276290075Sobrien { 276390075Sobrien HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]); 276490075Sobrien HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]); 276590075Sobrien 276690075Sobrien operands[3] = GEN_INT (rshift); 276790075Sobrien 276890075Sobrien if (lshift == 0) 276990075Sobrien { 277090075Sobrien emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3])); 277190075Sobrien DONE; 277290075Sobrien } 277390075Sobrien 277490075Sobrien operands[2] = GEN_INT (lshift); 277590075Sobrien operands[4] = gen_reg_rtx (SImode); 277690075Sobrien }" 277790075Sobrien) 277890075Sobrien 277990075Sobrien 278090075Sobrien;; Unary arithmetic insns 278190075Sobrien 278290075Sobrien(define_expand "negdi2" 278390075Sobrien [(parallel 278490075Sobrien [(set (match_operand:DI 0 "s_register_operand" "") 278590075Sobrien (neg:DI (match_operand:DI 1 "s_register_operand" ""))) 278690075Sobrien (clobber (reg:CC CC_REGNUM))])] 278790075Sobrien "TARGET_EITHER" 278890075Sobrien " 278990075Sobrien if (TARGET_THUMB) 279090075Sobrien { 279190075Sobrien if (GET_CODE (operands[1]) != REG) 279290075Sobrien operands[1] = force_reg (SImode, operands[1]); 279390075Sobrien } 279490075Sobrien " 279590075Sobrien) 279690075Sobrien 279790075Sobrien;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1). 279890075Sobrien;; The second alternative is to allow the common case of a *full* overlap. 279990075Sobrien(define_insn "*arm_negdi2" 280090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,r") 280190075Sobrien (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0"))) 280290075Sobrien (clobber (reg:CC CC_REGNUM))] 280390075Sobrien "TARGET_ARM" 280490075Sobrien "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0" 280590075Sobrien [(set_attr "conds" "clob") 280690075Sobrien (set_attr "length" "8")] 280790075Sobrien) 280890075Sobrien 280990075Sobrien(define_insn "*thumb_negdi2" 281090075Sobrien [(set (match_operand:DI 0 "register_operand" "=&l") 281190075Sobrien (neg:DI (match_operand:DI 1 "register_operand" "l"))) 281290075Sobrien (clobber (reg:CC CC_REGNUM))] 281390075Sobrien "TARGET_THUMB" 281490075Sobrien "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1" 281590075Sobrien [(set_attr "length" "6")] 281690075Sobrien) 281790075Sobrien 281890075Sobrien(define_expand "negsi2" 281990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 282090075Sobrien (neg:SI (match_operand:SI 1 "s_register_operand" "")))] 282190075Sobrien "TARGET_EITHER" 282290075Sobrien "" 282390075Sobrien) 282490075Sobrien 282590075Sobrien(define_insn "*arm_negsi2" 282690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 282790075Sobrien (neg:SI (match_operand:SI 1 "s_register_operand" "r")))] 282890075Sobrien "TARGET_ARM" 282990075Sobrien "rsb%?\\t%0, %1, #0" 283090075Sobrien [(set_attr "predicable" "yes")] 283190075Sobrien) 283290075Sobrien 283390075Sobrien(define_insn "*thumb_negsi2" 283490075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 283590075Sobrien (neg:SI (match_operand:SI 1 "register_operand" "l")))] 283690075Sobrien "TARGET_THUMB" 283790075Sobrien "neg\\t%0, %1" 283890075Sobrien [(set_attr "length" "2")] 283990075Sobrien) 284090075Sobrien 2841132718Skan(define_expand "negsf2" 2842132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 2843132718Skan (neg:SF (match_operand:SF 1 "s_register_operand" "")))] 2844132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2845132718Skan "" 284690075Sobrien) 284790075Sobrien 2848132718Skan(define_expand "negdf2" 2849132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 2850132718Skan (neg:DF (match_operand:DF 1 "s_register_operand" "")))] 2851132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2852132718Skan "") 285390075Sobrien 285490075Sobrien;; abssi2 doesn't really clobber the condition codes if a different register 285590075Sobrien;; is being set. To keep things simple, assume during rtl manipulations that 285690075Sobrien;; it does, but tell the final scan operator the truth. Similarly for 285790075Sobrien;; (neg (abs...)) 285890075Sobrien 2859132718Skan(define_expand "abssi2" 2860132718Skan [(parallel 2861132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 2862132718Skan (abs:SI (match_operand:SI 1 "s_register_operand" ""))) 2863132718Skan (clobber (reg:CC CC_REGNUM))])] 2864132718Skan "TARGET_ARM" 2865132718Skan "") 2866132718Skan 2867132718Skan(define_insn "*arm_abssi2" 286890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 286990075Sobrien (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) 287090075Sobrien (clobber (reg:CC CC_REGNUM))] 287190075Sobrien "TARGET_ARM" 287290075Sobrien "@ 287390075Sobrien cmp\\t%0, #0\;rsblt\\t%0, %0, #0 287490075Sobrien eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" 287590075Sobrien [(set_attr "conds" "clob,*") 287690075Sobrien (set_attr "shift" "1") 287790075Sobrien ;; predicable can't be set based on the variant, so left as no 287890075Sobrien (set_attr "length" "8")] 287990075Sobrien) 288090075Sobrien 288190075Sobrien(define_insn "*neg_abssi2" 288290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 288390075Sobrien (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) 288490075Sobrien (clobber (reg:CC CC_REGNUM))] 288590075Sobrien "TARGET_ARM" 288690075Sobrien "@ 288790075Sobrien cmp\\t%0, #0\;rsbgt\\t%0, %0, #0 288890075Sobrien eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" 288990075Sobrien [(set_attr "conds" "clob,*") 289090075Sobrien (set_attr "shift" "1") 289190075Sobrien ;; predicable can't be set based on the variant, so left as no 289290075Sobrien (set_attr "length" "8")] 289390075Sobrien) 289490075Sobrien 2895132718Skan(define_expand "abssf2" 2896132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 2897132718Skan (abs:SF (match_operand:SF 1 "s_register_operand" "")))] 2898132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2899132718Skan "") 290090075Sobrien 2901132718Skan(define_expand "absdf2" 2902132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 2903132718Skan (abs:DF (match_operand:DF 1 "s_register_operand" "")))] 2904132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2905132718Skan "") 290690075Sobrien 2907132718Skan(define_expand "sqrtsf2" 2908132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 2909132718Skan (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))] 291090075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 2911132718Skan "") 291290075Sobrien 2913132718Skan(define_expand "sqrtdf2" 2914132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 2915132718Skan (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))] 291690075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 2917132718Skan "") 291890075Sobrien 291990075Sobrien(define_insn_and_split "one_cmpldi2" 292090075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") 292190075Sobrien (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))] 292290075Sobrien "TARGET_ARM" 292390075Sobrien "#" 292490075Sobrien "TARGET_ARM && reload_completed" 292590075Sobrien [(set (match_dup 0) (not:SI (match_dup 1))) 292690075Sobrien (set (match_dup 2) (not:SI (match_dup 3)))] 292790075Sobrien " 292890075Sobrien { 292990075Sobrien operands[2] = gen_highpart (SImode, operands[0]); 293090075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 293190075Sobrien operands[3] = gen_highpart (SImode, operands[1]); 293290075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 293390075Sobrien }" 293490075Sobrien [(set_attr "length" "8") 293590075Sobrien (set_attr "predicable" "yes")] 293690075Sobrien) 293790075Sobrien 293890075Sobrien(define_expand "one_cmplsi2" 293990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 294090075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "")))] 294190075Sobrien "TARGET_EITHER" 294290075Sobrien "" 294390075Sobrien) 294490075Sobrien 294590075Sobrien(define_insn "*arm_one_cmplsi2" 294690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 294790075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r")))] 294890075Sobrien "TARGET_ARM" 294990075Sobrien "mvn%?\\t%0, %1" 295090075Sobrien [(set_attr "predicable" "yes")] 295190075Sobrien) 295290075Sobrien 295390075Sobrien(define_insn "*thumb_one_cmplsi2" 295490075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 295590075Sobrien (not:SI (match_operand:SI 1 "register_operand" "l")))] 295690075Sobrien "TARGET_THUMB" 295790075Sobrien "mvn\\t%0, %1" 295890075Sobrien [(set_attr "length" "2")] 295990075Sobrien) 296090075Sobrien 296190075Sobrien(define_insn "*notsi_compare0" 296290075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 296390075Sobrien (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 296490075Sobrien (const_int 0))) 296590075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 296690075Sobrien (not:SI (match_dup 1)))] 296790075Sobrien "TARGET_ARM" 296890075Sobrien "mvn%?s\\t%0, %1" 296990075Sobrien [(set_attr "conds" "set")] 297090075Sobrien) 297190075Sobrien 297290075Sobrien(define_insn "*notsi_compare0_scratch" 297390075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 297490075Sobrien (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r")) 297590075Sobrien (const_int 0))) 297690075Sobrien (clobber (match_scratch:SI 0 "=r"))] 297790075Sobrien "TARGET_ARM" 297890075Sobrien "mvn%?s\\t%0, %1" 297990075Sobrien [(set_attr "conds" "set")] 298090075Sobrien) 298190075Sobrien 298290075Sobrien;; Fixed <--> Floating conversion insns 298390075Sobrien 2984132718Skan(define_expand "floatsisf2" 2985132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 2986132718Skan (float:SF (match_operand:SI 1 "s_register_operand" "")))] 2987132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 2988132718Skan " 2989132718Skan if (TARGET_CIRRUS) 2990132718Skan { 2991132718Skan emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1])); 2992132718Skan DONE; 2993132718Skan } 2994132718Skan") 299590075Sobrien 2996132718Skan(define_expand "floatsidf2" 2997132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 2998132718Skan (float:DF (match_operand:SI 1 "s_register_operand" "")))] 2999132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3000132718Skan " 3001132718Skan if (TARGET_CIRRUS) 3002132718Skan { 3003132718Skan emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1])); 3004132718Skan DONE; 3005132718Skan } 3006132718Skan") 300790075Sobrien 3008132718Skan(define_expand "fix_truncsfsi2" 3009132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 3010132718Skan (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))] 3011132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3012132718Skan " 3013132718Skan if (TARGET_CIRRUS) 3014132718Skan { 3015132718Skan if (!cirrus_fp_register (operands[0], SImode)) 3016132718Skan operands[0] = force_reg (SImode, operands[0]); 3017132718Skan if (!cirrus_fp_register (operands[1], SFmode)) 3018132718Skan operands[1] = force_reg (SFmode, operands[0]); 3019132718Skan emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1])); 3020132718Skan DONE; 3021132718Skan } 3022132718Skan") 302390075Sobrien 3024132718Skan(define_expand "fix_truncdfsi2" 3025132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 3026132718Skan (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))] 3027132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3028132718Skan " 3029132718Skan if (TARGET_CIRRUS) 3030132718Skan { 3031132718Skan if (!cirrus_fp_register (operands[1], DFmode)) 3032132718Skan operands[1] = force_reg (DFmode, operands[0]); 3033132718Skan emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1])); 3034132718Skan DONE; 3035132718Skan } 3036132718Skan") 303790075Sobrien 303890075Sobrien;; Truncation insns 303990075Sobrien 3040132718Skan(define_expand "truncdfsf2" 3041132718Skan [(set (match_operand:SF 0 "s_register_operand" "") 304290075Sobrien (float_truncate:SF 3043132718Skan (match_operand:DF 1 "s_register_operand" "")))] 3044132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3045132718Skan "" 304690075Sobrien) 304790075Sobrien 304890075Sobrien;; Zero and sign extension instructions. 304990075Sobrien 305090075Sobrien(define_insn "zero_extendsidi2" 305190075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r") 305290075Sobrien (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 305390075Sobrien "TARGET_ARM" 305490075Sobrien "* 305590075Sobrien if (REGNO (operands[1]) 305690075Sobrien != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 305790075Sobrien output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 305890075Sobrien return \"mov%?\\t%R0, #0\"; 305990075Sobrien " 306090075Sobrien [(set_attr "length" "8") 306190075Sobrien (set_attr "predicable" "yes")] 306290075Sobrien) 306390075Sobrien 306490075Sobrien(define_insn "zero_extendqidi2" 306590075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r,r") 306690075Sobrien (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 306790075Sobrien "TARGET_ARM" 306890075Sobrien "@ 306990075Sobrien and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0 307090075Sobrien ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0" 307190075Sobrien [(set_attr "length" "8") 307290075Sobrien (set_attr "predicable" "yes") 307390075Sobrien (set_attr "type" "*,load") 307490075Sobrien (set_attr "pool_range" "*,4092") 307590075Sobrien (set_attr "neg_pool_range" "*,4084")] 307690075Sobrien) 307790075Sobrien 307890075Sobrien(define_insn "extendsidi2" 307990075Sobrien [(set (match_operand:DI 0 "s_register_operand" "=r") 308090075Sobrien (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 308190075Sobrien "TARGET_ARM" 308290075Sobrien "* 308390075Sobrien if (REGNO (operands[1]) 308490075Sobrien != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) 308590075Sobrien output_asm_insn (\"mov%?\\t%Q0, %1\", operands); 308690075Sobrien return \"mov%?\\t%R0, %Q0, asr #31\"; 308790075Sobrien " 308890075Sobrien [(set_attr "length" "8") 308990075Sobrien (set_attr "shift" "1") 309090075Sobrien (set_attr "predicable" "yes")] 309190075Sobrien) 309290075Sobrien 309390075Sobrien(define_expand "zero_extendhisi2" 309490075Sobrien [(set (match_dup 2) 309590075Sobrien (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 309690075Sobrien (const_int 16))) 309790075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 309890075Sobrien (lshiftrt:SI (match_dup 2) (const_int 16)))] 309990075Sobrien "TARGET_EITHER" 310090075Sobrien " 310190075Sobrien { 310290075Sobrien if (TARGET_ARM) 310390075Sobrien { 310490075Sobrien if (arm_arch4 && GET_CODE (operands[1]) == MEM) 310590075Sobrien { 310690075Sobrien /* Note: We do not have to worry about TARGET_MMU_TRAPS 310790075Sobrien here because the insn below will generate an LDRH instruction 310890075Sobrien rather than an LDR instruction, so we cannot get an unaligned 310990075Sobrien word access. */ 311090075Sobrien emit_insn (gen_rtx_SET (VOIDmode, operands[0], 311190075Sobrien gen_rtx_ZERO_EXTEND (SImode, 311290075Sobrien operands[1]))); 311390075Sobrien DONE; 311490075Sobrien } 311590075Sobrien if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM) 311690075Sobrien { 311790075Sobrien emit_insn (gen_movhi_bytes (operands[0], operands[1])); 311890075Sobrien DONE; 311990075Sobrien } 312090075Sobrien if (!s_register_operand (operands[1], HImode)) 312190075Sobrien operands[1] = copy_to_mode_reg (HImode, operands[1]); 312290075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 312390075Sobrien operands[2] = gen_reg_rtx (SImode); 312490075Sobrien } 312590075Sobrien else /* TARGET_THUMB */ 312690075Sobrien { 312790075Sobrien if (GET_CODE (operands[1]) == MEM) 312890075Sobrien { 312990075Sobrien rtx tmp; 313090075Sobrien 313190075Sobrien tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]); 313290075Sobrien tmp = gen_rtx_SET (VOIDmode, operands[0], tmp); 313390075Sobrien emit_insn (tmp); 313490075Sobrien } 313590075Sobrien else 313690075Sobrien { 313790075Sobrien rtx ops[3]; 313890075Sobrien 313990075Sobrien if (!s_register_operand (operands[1], HImode)) 314090075Sobrien operands[1] = copy_to_mode_reg (HImode, operands[1]); 314190075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 314290075Sobrien operands[2] = gen_reg_rtx (SImode); 314390075Sobrien 314490075Sobrien ops[0] = operands[2]; 314590075Sobrien ops[1] = operands[1]; 314690075Sobrien ops[2] = GEN_INT (16); 314790075Sobrien 314890075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 314990075Sobrien gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 315090075Sobrien 315190075Sobrien ops[0] = operands[0]; 315290075Sobrien ops[1] = operands[2]; 315390075Sobrien ops[2] = GEN_INT (16); 315490075Sobrien 315590075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 315690075Sobrien gen_rtx_LSHIFTRT (SImode, ops[1], 315790075Sobrien ops[2]))); 315890075Sobrien } 315990075Sobrien DONE; 316090075Sobrien } 316190075Sobrien }" 316290075Sobrien) 316390075Sobrien 316490075Sobrien(define_insn "*thumb_zero_extendhisi2" 316590075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 316690075Sobrien (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 316790075Sobrien "TARGET_THUMB" 316890075Sobrien "* 316990075Sobrien rtx mem = XEXP (operands[1], 0); 317090075Sobrien 317190075Sobrien if (GET_CODE (mem) == CONST) 317290075Sobrien mem = XEXP (mem, 0); 317390075Sobrien 317490075Sobrien if (GET_CODE (mem) == LABEL_REF) 317590075Sobrien return \"ldr\\t%0, %1\"; 317690075Sobrien 317790075Sobrien if (GET_CODE (mem) == PLUS) 317890075Sobrien { 317990075Sobrien rtx a = XEXP (mem, 0); 318090075Sobrien rtx b = XEXP (mem, 1); 318190075Sobrien 318290075Sobrien /* This can happen due to bugs in reload. */ 318390075Sobrien if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM) 318490075Sobrien { 318590075Sobrien rtx ops[2]; 318690075Sobrien ops[0] = operands[0]; 318790075Sobrien ops[1] = a; 318890075Sobrien 318990075Sobrien output_asm_insn (\"mov %0, %1\", ops); 319090075Sobrien 319190075Sobrien XEXP (mem, 0) = operands[0]; 319290075Sobrien } 319390075Sobrien 319490075Sobrien else if ( GET_CODE (a) == LABEL_REF 319590075Sobrien && GET_CODE (b) == CONST_INT) 319690075Sobrien return \"ldr\\t%0, %1\"; 319790075Sobrien } 319890075Sobrien 319990075Sobrien return \"ldrh\\t%0, %1\"; 320090075Sobrien " 320190075Sobrien [(set_attr "length" "4") 320290075Sobrien (set_attr "type" "load") 320390075Sobrien (set_attr "pool_range" "60")] 320490075Sobrien) 320590075Sobrien 320690075Sobrien(define_insn "*arm_zero_extendhisi2" 320790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 320890075Sobrien (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 320990075Sobrien "TARGET_ARM && arm_arch4" 321090075Sobrien "ldr%?h\\t%0, %1" 321190075Sobrien [(set_attr "type" "load") 321290075Sobrien (set_attr "predicable" "yes") 321390075Sobrien (set_attr "pool_range" "256") 321490075Sobrien (set_attr "neg_pool_range" "244")] 321590075Sobrien) 321690075Sobrien 321790075Sobrien(define_split 321890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 321990075Sobrien (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) 322090075Sobrien (clobber (match_operand:SI 2 "s_register_operand" ""))] 322190075Sobrien "TARGET_ARM && (!arm_arch4)" 322290075Sobrien [(set (match_dup 2) (match_dup 1)) 322390075Sobrien (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))] 322490075Sobrien " 322590075Sobrien if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 322690075Sobrien FAIL; 322790075Sobrien " 322890075Sobrien) 322990075Sobrien 323090075Sobrien(define_split 323190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 323290075Sobrien (match_operator:SI 3 "shiftable_operator" 323390075Sobrien [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) 323490075Sobrien (match_operand:SI 4 "s_register_operand" "")])) 323590075Sobrien (clobber (match_operand:SI 2 "s_register_operand" ""))] 323690075Sobrien "TARGET_ARM && (!arm_arch4)" 323790075Sobrien [(set (match_dup 2) (match_dup 1)) 323890075Sobrien (set (match_dup 0) 323990075Sobrien (match_op_dup 3 324090075Sobrien [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] 324190075Sobrien " 324290075Sobrien if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 324390075Sobrien FAIL; 324490075Sobrien " 324590075Sobrien) 324690075Sobrien 324790075Sobrien(define_expand "zero_extendqisi2" 324890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 324990075Sobrien (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] 325090075Sobrien "TARGET_EITHER" 325190075Sobrien " 325290075Sobrien if (GET_CODE (operands[1]) != MEM) 325390075Sobrien { 325490075Sobrien if (TARGET_ARM) 325590075Sobrien { 325690075Sobrien emit_insn (gen_andsi3 (operands[0], 325790075Sobrien gen_lowpart (SImode, operands[1]), 325890075Sobrien GEN_INT (255))); 325990075Sobrien } 326090075Sobrien else /* TARGET_THUMB */ 326190075Sobrien { 326290075Sobrien rtx temp = gen_reg_rtx (SImode); 326390075Sobrien rtx ops[3]; 326490075Sobrien 326590075Sobrien operands[1] = copy_to_mode_reg (QImode, operands[1]); 326690075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 326790075Sobrien 326890075Sobrien ops[0] = temp; 326990075Sobrien ops[1] = operands[1]; 327090075Sobrien ops[2] = GEN_INT (24); 327190075Sobrien 327290075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 327390075Sobrien gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 327490075Sobrien 327590075Sobrien ops[0] = operands[0]; 327690075Sobrien ops[1] = temp; 327790075Sobrien ops[2] = GEN_INT (24); 327890075Sobrien 327990075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 328090075Sobrien gen_rtx_LSHIFTRT (SImode, ops[1], ops[2]))); 328190075Sobrien } 328290075Sobrien DONE; 328390075Sobrien } 328490075Sobrien " 328590075Sobrien) 328690075Sobrien 328790075Sobrien(define_insn "*thumb_zero_extendqisi2" 328890075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 328990075Sobrien (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 329090075Sobrien "TARGET_THUMB" 329190075Sobrien "ldrb\\t%0, %1" 329290075Sobrien [(set_attr "length" "2") 329390075Sobrien (set_attr "type" "load") 329490075Sobrien (set_attr "pool_range" "32")] 329590075Sobrien) 329690075Sobrien 329790075Sobrien(define_insn "*arm_zero_extendqisi2" 329890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 329990075Sobrien (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 330090075Sobrien "TARGET_ARM" 330190075Sobrien "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2" 330290075Sobrien [(set_attr "type" "load") 330390075Sobrien (set_attr "predicable" "yes") 330490075Sobrien (set_attr "pool_range" "4096") 330590075Sobrien (set_attr "neg_pool_range" "4084")] 330690075Sobrien) 330790075Sobrien 330890075Sobrien(define_split 330990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 331090075Sobrien (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0))) 331190075Sobrien (clobber (match_operand:SI 2 "s_register_operand" ""))] 3312102780Skan "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN" 331390075Sobrien [(set (match_dup 2) (match_dup 1)) 331490075Sobrien (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))] 331590075Sobrien "" 331690075Sobrien) 331790075Sobrien 331890075Sobrien(define_insn "*compareqi_eq0" 331990075Sobrien [(set (reg:CC_Z CC_REGNUM) 332090075Sobrien (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r") 332190075Sobrien (const_int 0)))] 332290075Sobrien "TARGET_ARM" 332390075Sobrien "tst\\t%0, #255" 332490075Sobrien [(set_attr "conds" "set")] 332590075Sobrien) 332690075Sobrien 332790075Sobrien(define_expand "extendhisi2" 332890075Sobrien [(set (match_dup 2) 332990075Sobrien (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") 333090075Sobrien (const_int 16))) 333190075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 333290075Sobrien (ashiftrt:SI (match_dup 2) 333390075Sobrien (const_int 16)))] 333490075Sobrien "TARGET_EITHER" 333590075Sobrien " 333690075Sobrien { 333790075Sobrien if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM) 333890075Sobrien { 333990075Sobrien /* Note: We do not have to worry about TARGET_MMU_TRAPS 334090075Sobrien here because the insn below will generate an LDRH instruction 334190075Sobrien rather than an LDR instruction, so we cannot get an unaligned 334290075Sobrien word access. */ 334390075Sobrien emit_insn (gen_rtx_SET (VOIDmode, operands[0], 334490075Sobrien gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 334590075Sobrien DONE; 334690075Sobrien } 334790075Sobrien 334890075Sobrien if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM) 334990075Sobrien { 335090075Sobrien emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); 335190075Sobrien DONE; 335290075Sobrien } 335390075Sobrien if (!s_register_operand (operands[1], HImode)) 335490075Sobrien operands[1] = copy_to_mode_reg (HImode, operands[1]); 335590075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 335690075Sobrien operands[2] = gen_reg_rtx (SImode); 335790075Sobrien 335890075Sobrien if (TARGET_THUMB) 335990075Sobrien { 336090075Sobrien rtx ops[3]; 336190075Sobrien 336290075Sobrien ops[0] = operands[2]; 336390075Sobrien ops[1] = operands[1]; 336490075Sobrien ops[2] = GEN_INT (16); 336590075Sobrien 336690075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 336790075Sobrien gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 336890075Sobrien 336990075Sobrien ops[0] = operands[0]; 337090075Sobrien ops[1] = operands[2]; 337190075Sobrien ops[2] = GEN_INT (16); 337290075Sobrien 337390075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 337490075Sobrien gen_rtx_ASHIFTRT (SImode, ops[1], ops[2]))); 337590075Sobrien 337690075Sobrien DONE; 337790075Sobrien } 337890075Sobrien }" 337990075Sobrien) 338090075Sobrien 338190075Sobrien(define_insn "*thumb_extendhisi2_insn" 338290075Sobrien [(set (match_operand:SI 0 "register_operand" "=l") 338390075Sobrien (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) 338490075Sobrien (clobber (match_scratch:SI 2 "=&l"))] 338590075Sobrien "TARGET_THUMB" 338690075Sobrien "* 338790075Sobrien { 338890075Sobrien rtx ops[4]; 338990075Sobrien rtx mem = XEXP (operands[1], 0); 339090075Sobrien 339190075Sobrien /* This code used to try to use 'V', and fix the address only if it was 339290075Sobrien offsettable, but this fails for e.g. REG+48 because 48 is outside the 339390075Sobrien range of QImode offsets, and offsettable_address_p does a QImode 339490075Sobrien address check. */ 339590075Sobrien 339690075Sobrien if (GET_CODE (mem) == CONST) 339790075Sobrien mem = XEXP (mem, 0); 339890075Sobrien 339990075Sobrien if (GET_CODE (mem) == LABEL_REF) 340090075Sobrien return \"ldr\\t%0, %1\"; 340190075Sobrien 340290075Sobrien if (GET_CODE (mem) == PLUS) 340390075Sobrien { 340490075Sobrien rtx a = XEXP (mem, 0); 340590075Sobrien rtx b = XEXP (mem, 1); 340690075Sobrien 340790075Sobrien if (GET_CODE (a) == LABEL_REF 340890075Sobrien && GET_CODE (b) == CONST_INT) 340990075Sobrien return \"ldr\\t%0, %1\"; 341090075Sobrien 341190075Sobrien if (GET_CODE (b) == REG) 341290075Sobrien return \"ldrsh\\t%0, %1\"; 341390075Sobrien 341490075Sobrien ops[1] = a; 341590075Sobrien ops[2] = b; 341690075Sobrien } 341790075Sobrien else 341890075Sobrien { 341990075Sobrien ops[1] = mem; 342090075Sobrien ops[2] = const0_rtx; 342190075Sobrien } 342290075Sobrien 342390075Sobrien if (GET_CODE (ops[1]) != REG) 342490075Sobrien { 342590075Sobrien debug_rtx (ops[1]); 342690075Sobrien abort (); 342790075Sobrien } 342890075Sobrien 342990075Sobrien ops[0] = operands[0]; 343090075Sobrien ops[3] = operands[2]; 343190075Sobrien output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); 343290075Sobrien return \"\"; 343390075Sobrien }" 343490075Sobrien [(set_attr "length" "4") 343590075Sobrien (set_attr "type" "load") 343690075Sobrien (set_attr "pool_range" "1020")] 343790075Sobrien) 343890075Sobrien 343990075Sobrien(define_expand "extendhisi2_mem" 344090075Sobrien [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 344190075Sobrien (set (match_dup 3) 344290075Sobrien (zero_extend:SI (match_dup 7))) 344390075Sobrien (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24))) 344490075Sobrien (set (match_operand:SI 0 "" "") 344590075Sobrien (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))] 344690075Sobrien "TARGET_ARM" 344790075Sobrien " 344890075Sobrien { 344990075Sobrien rtx mem1, mem2; 345090075Sobrien rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 345190075Sobrien 345290075Sobrien mem1 = gen_rtx_MEM (QImode, addr); 345390075Sobrien MEM_COPY_ATTRIBUTES (mem1, operands[1]); 345490075Sobrien mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 345590075Sobrien MEM_COPY_ATTRIBUTES (mem2, operands[1]); 345690075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 345790075Sobrien operands[1] = mem1; 345890075Sobrien operands[2] = gen_reg_rtx (SImode); 345990075Sobrien operands[3] = gen_reg_rtx (SImode); 346090075Sobrien operands[6] = gen_reg_rtx (SImode); 346190075Sobrien operands[7] = mem2; 346290075Sobrien 346390075Sobrien if (BYTES_BIG_ENDIAN) 346490075Sobrien { 346590075Sobrien operands[4] = operands[2]; 346690075Sobrien operands[5] = operands[3]; 346790075Sobrien } 346890075Sobrien else 346990075Sobrien { 347090075Sobrien operands[4] = operands[3]; 347190075Sobrien operands[5] = operands[2]; 347290075Sobrien } 347390075Sobrien }" 347490075Sobrien) 347590075Sobrien 347690075Sobrien(define_insn "*arm_extendhisi_insn" 347790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 347890075Sobrien (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] 347990075Sobrien "TARGET_ARM && arm_arch4" 348090075Sobrien "ldr%?sh\\t%0, %1" 348190075Sobrien [(set_attr "type" "load") 348290075Sobrien (set_attr "predicable" "yes") 348390075Sobrien (set_attr "pool_range" "256") 348490075Sobrien (set_attr "neg_pool_range" "244")] 348590075Sobrien) 348690075Sobrien 348790075Sobrien(define_split 348890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 348990075Sobrien (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))) 349090075Sobrien (clobber (match_operand:SI 2 "s_register_operand" ""))] 349190075Sobrien "TARGET_ARM && (!arm_arch4)" 349290075Sobrien [(set (match_dup 2) (match_dup 1)) 349390075Sobrien (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))] 349490075Sobrien " 349590075Sobrien if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 349690075Sobrien FAIL; 349790075Sobrien " 349890075Sobrien) 349990075Sobrien 350090075Sobrien(define_split 350190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 350290075Sobrien (match_operator:SI 3 "shiftable_operator" 350390075Sobrien [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")) 350490075Sobrien (match_operand:SI 4 "s_register_operand" "")])) 350590075Sobrien (clobber (match_operand:SI 2 "s_register_operand" ""))] 350690075Sobrien "TARGET_ARM && (!arm_arch4)" 350790075Sobrien [(set (match_dup 2) (match_dup 1)) 350890075Sobrien (set (match_dup 0) 350990075Sobrien (match_op_dup 3 351090075Sobrien [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))] 351190075Sobrien "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL) 351290075Sobrien FAIL; 351390075Sobrien " 351490075Sobrien) 351590075Sobrien 351690075Sobrien(define_expand "extendqihi2" 351790075Sobrien [(set (match_dup 2) 351890075Sobrien (ashift:SI (match_operand:QI 1 "general_operand" "") 351990075Sobrien (const_int 24))) 352090075Sobrien (set (match_operand:HI 0 "s_register_operand" "") 352190075Sobrien (ashiftrt:SI (match_dup 2) 352290075Sobrien (const_int 24)))] 352390075Sobrien "TARGET_ARM" 352490075Sobrien " 352590075Sobrien { 352690075Sobrien if (arm_arch4 && GET_CODE (operands[1]) == MEM) 352790075Sobrien { 352890075Sobrien emit_insn (gen_rtx_SET (VOIDmode, 352990075Sobrien operands[0], 353090075Sobrien gen_rtx_SIGN_EXTEND (HImode, operands[1]))); 353190075Sobrien DONE; 353290075Sobrien } 353390075Sobrien if (!s_register_operand (operands[1], QImode)) 353490075Sobrien operands[1] = copy_to_mode_reg (QImode, operands[1]); 353590075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 353690075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 353790075Sobrien operands[2] = gen_reg_rtx (SImode); 353890075Sobrien }" 353990075Sobrien) 354090075Sobrien 354190075Sobrien; Rather than restricting all byte accesses to memory addresses that ldrsb 354290075Sobrien; can handle, we fix up the ones that ldrsb can't grok with a split. 354390075Sobrien(define_insn "*extendqihi_insn" 354490075Sobrien [(set (match_operand:HI 0 "s_register_operand" "=r") 354590075Sobrien (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] 354690075Sobrien "TARGET_ARM && arm_arch4" 354790075Sobrien "* 3548132718Skan /* If the address is invalid, this will split the instruction into two. */ 354990075Sobrien if (bad_signed_byte_operand (operands[1], VOIDmode)) 355090075Sobrien return \"#\"; 355190075Sobrien return \"ldr%?sb\\t%0, %1\"; 355290075Sobrien " 355390075Sobrien [(set_attr "type" "load") 355490075Sobrien (set_attr "predicable" "yes") 355590075Sobrien (set_attr "length" "8") 355690075Sobrien (set_attr "pool_range" "256") 355790075Sobrien (set_attr "neg_pool_range" "244")] 355890075Sobrien) 355990075Sobrien 356090075Sobrien(define_split 356190075Sobrien [(set (match_operand:HI 0 "s_register_operand" "") 356290075Sobrien (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))] 356390075Sobrien "TARGET_ARM && arm_arch4 && reload_completed" 356490075Sobrien [(set (match_dup 3) (match_dup 1)) 356590075Sobrien (set (match_dup 0) (sign_extend:HI (match_dup 2)))] 356690075Sobrien " 356790075Sobrien { 356890075Sobrien HOST_WIDE_INT offset; 356990075Sobrien 357090075Sobrien operands[3] = gen_rtx_REG (SImode, REGNO (operands[0])); 357190075Sobrien operands[2] = gen_rtx_MEM (QImode, operands[3]); 357290075Sobrien MEM_COPY_ATTRIBUTES (operands[2], operands[1]); 357390075Sobrien operands[1] = XEXP (operands[1], 0); 357490075Sobrien if (GET_CODE (operands[1]) == PLUS 357590075Sobrien && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 357690075Sobrien && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1))) 357790075Sobrien || const_ok_for_arm (-offset))) 357890075Sobrien { 357990075Sobrien HOST_WIDE_INT low = (offset > 0 358090075Sobrien ? (offset & 0xff) : -((-offset) & 0xff)); 358190075Sobrien XEXP (operands[2], 0) = plus_constant (operands[3], low); 358290075Sobrien operands[1] = plus_constant (XEXP (operands[1], 0), offset - low); 358390075Sobrien } 3584132718Skan /* Ensure the sum is in correct canonical form. */ 358590075Sobrien else if (GET_CODE (operands[1]) == PLUS 358690075Sobrien && GET_CODE (XEXP (operands[1], 1)) != CONST_INT 358790075Sobrien && !s_register_operand (XEXP (operands[1], 1), VOIDmode)) 358890075Sobrien operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), 358990075Sobrien XEXP (operands[1], 1), 359090075Sobrien XEXP (operands[1], 0)); 359190075Sobrien }" 359290075Sobrien) 359390075Sobrien 359490075Sobrien(define_expand "extendqisi2" 359590075Sobrien [(set (match_dup 2) 359690075Sobrien (ashift:SI (match_operand:QI 1 "general_operand" "") 359790075Sobrien (const_int 24))) 359890075Sobrien (set (match_operand:SI 0 "s_register_operand" "") 359990075Sobrien (ashiftrt:SI (match_dup 2) 360090075Sobrien (const_int 24)))] 360190075Sobrien "TARGET_EITHER" 360290075Sobrien " 360390075Sobrien { 360490075Sobrien if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM) 360590075Sobrien { 360690075Sobrien emit_insn (gen_rtx_SET (VOIDmode, 360790075Sobrien operands[0], 360890075Sobrien gen_rtx_SIGN_EXTEND (SImode, operands[1]))); 360990075Sobrien DONE; 361090075Sobrien } 361190075Sobrien if (!s_register_operand (operands[1], QImode)) 361290075Sobrien operands[1] = copy_to_mode_reg (QImode, operands[1]); 361390075Sobrien operands[1] = gen_lowpart (SImode, operands[1]); 361490075Sobrien operands[2] = gen_reg_rtx (SImode); 361590075Sobrien 361690075Sobrien if (TARGET_THUMB) 361790075Sobrien { 361890075Sobrien rtx ops[3]; 361990075Sobrien 362090075Sobrien ops[0] = operands[2]; 362190075Sobrien ops[1] = operands[1]; 362290075Sobrien ops[2] = GEN_INT (24); 362390075Sobrien 362490075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 362590075Sobrien gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); 362690075Sobrien 362790075Sobrien ops[0] = operands[0]; 362890075Sobrien ops[1] = operands[2]; 362990075Sobrien ops[2] = GEN_INT (24); 363090075Sobrien 363190075Sobrien emit_insn (gen_rtx_SET (VOIDmode, ops[0], 363290075Sobrien gen_rtx_ASHIFTRT (SImode, ops[1], ops[2]))); 363390075Sobrien 363490075Sobrien DONE; 363590075Sobrien } 363690075Sobrien }" 363790075Sobrien) 363890075Sobrien 363990075Sobrien; Rather than restricting all byte accesses to memory addresses that ldrsb 364090075Sobrien; can handle, we fix up the ones that ldrsb can't grok with a split. 364190075Sobrien(define_insn "*arm_extendqisi_insn" 364290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 364390075Sobrien (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] 364490075Sobrien "TARGET_ARM && arm_arch4" 364590075Sobrien "* 3646132718Skan /* If the address is invalid, this will split the instruction into two. */ 364790075Sobrien if (bad_signed_byte_operand (operands[1], VOIDmode)) 364890075Sobrien return \"#\"; 364990075Sobrien return \"ldr%?sb\\t%0, %1\"; 365090075Sobrien " 365190075Sobrien [(set_attr "type" "load") 365290075Sobrien (set_attr "predicable" "yes") 365390075Sobrien (set_attr "length" "8") 365490075Sobrien (set_attr "pool_range" "256") 365590075Sobrien (set_attr "neg_pool_range" "244")] 365690075Sobrien) 365790075Sobrien 365890075Sobrien(define_split 365990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 366090075Sobrien (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))] 366190075Sobrien "TARGET_ARM && arm_arch4 && reload_completed" 366290075Sobrien [(set (match_dup 0) (match_dup 1)) 366390075Sobrien (set (match_dup 0) (sign_extend:SI (match_dup 2)))] 366490075Sobrien " 366590075Sobrien { 366690075Sobrien HOST_WIDE_INT offset; 366790075Sobrien 366890075Sobrien operands[2] = gen_rtx_MEM (QImode, operands[0]); 366990075Sobrien MEM_COPY_ATTRIBUTES (operands[2], operands[1]); 367090075Sobrien operands[1] = XEXP (operands[1], 0); 367190075Sobrien if (GET_CODE (operands[1]) == PLUS 367290075Sobrien && GET_CODE (XEXP (operands[1], 1)) == CONST_INT 367390075Sobrien && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1))) 367490075Sobrien || const_ok_for_arm (-offset))) 367590075Sobrien { 367690075Sobrien HOST_WIDE_INT low = (offset > 0 367790075Sobrien ? (offset & 0xff) : -((-offset) & 0xff)); 367890075Sobrien XEXP (operands[2], 0) = plus_constant (operands[0], low); 367990075Sobrien operands[1] = plus_constant (XEXP (operands[1], 0), offset - low); 368090075Sobrien } 3681132718Skan /* Ensure the sum is in correct canonical form. */ 368290075Sobrien else if (GET_CODE (operands[1]) == PLUS 368390075Sobrien && GET_CODE (XEXP (operands[1], 1)) != CONST_INT 368490075Sobrien && !s_register_operand (XEXP (operands[1], 1), VOIDmode)) 368590075Sobrien operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), 368690075Sobrien XEXP (operands[1], 1), 368790075Sobrien XEXP (operands[1], 0)); 368890075Sobrien }" 368990075Sobrien) 369090075Sobrien 369190075Sobrien(define_insn "*thumb_extendqisi2_insn" 369290075Sobrien [(set (match_operand:SI 0 "register_operand" "=l,l") 369390075Sobrien (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] 369490075Sobrien "TARGET_THUMB" 369590075Sobrien "* 369690075Sobrien { 369790075Sobrien rtx ops[3]; 369890075Sobrien rtx mem = XEXP (operands[1], 0); 369990075Sobrien 370090075Sobrien if (GET_CODE (mem) == CONST) 370190075Sobrien mem = XEXP (mem, 0); 370290075Sobrien 370390075Sobrien if (GET_CODE (mem) == LABEL_REF) 370490075Sobrien return \"ldr\\t%0, %1\"; 370590075Sobrien 370690075Sobrien if (GET_CODE (mem) == PLUS 370790075Sobrien && GET_CODE (XEXP (mem, 0)) == LABEL_REF) 370890075Sobrien return \"ldr\\t%0, %1\"; 370990075Sobrien 371090075Sobrien if (which_alternative == 0) 371190075Sobrien return \"ldrsb\\t%0, %1\"; 371290075Sobrien 371390075Sobrien ops[0] = operands[0]; 371490075Sobrien 371590075Sobrien if (GET_CODE (mem) == PLUS) 371690075Sobrien { 371790075Sobrien rtx a = XEXP (mem, 0); 371890075Sobrien rtx b = XEXP (mem, 1); 371990075Sobrien 372090075Sobrien ops[1] = a; 372190075Sobrien ops[2] = b; 372290075Sobrien 372390075Sobrien if (GET_CODE (a) == REG) 372490075Sobrien { 372590075Sobrien if (GET_CODE (b) == REG) 372690075Sobrien output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); 372790075Sobrien else if (REGNO (a) == REGNO (ops[0])) 372890075Sobrien { 372990075Sobrien output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); 373090075Sobrien output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 373190075Sobrien output_asm_insn (\"asr\\t%0, %0, #24\", ops); 373290075Sobrien } 373390075Sobrien else 373490075Sobrien output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 373590075Sobrien } 373690075Sobrien else if (GET_CODE (b) != REG) 373790075Sobrien abort (); 373890075Sobrien else 373990075Sobrien { 374090075Sobrien if (REGNO (b) == REGNO (ops[0])) 374190075Sobrien { 374290075Sobrien output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); 374390075Sobrien output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 374490075Sobrien output_asm_insn (\"asr\\t%0, %0, #24\", ops); 374590075Sobrien } 374690075Sobrien else 374790075Sobrien output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 374890075Sobrien } 374990075Sobrien } 375090075Sobrien else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) 375190075Sobrien { 375290075Sobrien output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); 375390075Sobrien output_asm_insn (\"lsl\\t%0, %0, #24\", ops); 375490075Sobrien output_asm_insn (\"asr\\t%0, %0, #24\", ops); 375590075Sobrien } 375690075Sobrien else 375790075Sobrien { 375890075Sobrien ops[1] = mem; 375990075Sobrien ops[2] = const0_rtx; 376090075Sobrien 376190075Sobrien output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); 376290075Sobrien } 376390075Sobrien return \"\"; 376490075Sobrien }" 376590075Sobrien [(set_attr "length" "2,6") 376690075Sobrien (set_attr "type" "load,load") 376790075Sobrien (set_attr "pool_range" "32,32")] 376890075Sobrien) 376990075Sobrien 3770132718Skan(define_expand "extendsfdf2" 3771132718Skan [(set (match_operand:DF 0 "s_register_operand" "") 3772132718Skan (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))] 3773132718Skan "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 3774132718Skan "" 377590075Sobrien) 377690075Sobrien 377790075Sobrien;; Move insns (including loads and stores) 377890075Sobrien 377990075Sobrien;; XXX Just some ideas about movti. 378090075Sobrien;; I don't think these are a good idea on the arm, there just aren't enough 378190075Sobrien;; registers 378290075Sobrien;;(define_expand "loadti" 378390075Sobrien;; [(set (match_operand:TI 0 "s_register_operand" "") 378490075Sobrien;; (mem:TI (match_operand:SI 1 "address_operand" "")))] 378590075Sobrien;; "" "") 378690075Sobrien 378790075Sobrien;;(define_expand "storeti" 378890075Sobrien;; [(set (mem:TI (match_operand:TI 0 "address_operand" "")) 378990075Sobrien;; (match_operand:TI 1 "s_register_operand" ""))] 379090075Sobrien;; "" "") 379190075Sobrien 379290075Sobrien;;(define_expand "movti" 379390075Sobrien;; [(set (match_operand:TI 0 "general_operand" "") 379490075Sobrien;; (match_operand:TI 1 "general_operand" ""))] 379590075Sobrien;; "" 379690075Sobrien;; " 379790075Sobrien;;{ 379890075Sobrien;; rtx insn; 379990075Sobrien;; 380090075Sobrien;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) 380190075Sobrien;; operands[1] = copy_to_reg (operands[1]); 380290075Sobrien;; if (GET_CODE (operands[0]) == MEM) 380390075Sobrien;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]); 380490075Sobrien;; else if (GET_CODE (operands[1]) == MEM) 380590075Sobrien;; insn = gen_loadti (operands[0], XEXP (operands[1], 0)); 380690075Sobrien;; else 380790075Sobrien;; FAIL; 380890075Sobrien;; 380990075Sobrien;; emit_insn (insn); 381090075Sobrien;; DONE; 381190075Sobrien;;}") 381290075Sobrien 3813117395Skan;; Recognize garbage generated above. 381490075Sobrien 381590075Sobrien;;(define_insn "" 381690075Sobrien;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m") 381790075Sobrien;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))] 381890075Sobrien;; "" 381990075Sobrien;; "* 382090075Sobrien;; { 382190075Sobrien;; register mem = (which_alternative < 3); 382290075Sobrien;; register const char *template; 382390075Sobrien;; 382490075Sobrien;; operands[mem] = XEXP (operands[mem], 0); 382590075Sobrien;; switch (which_alternative) 382690075Sobrien;; { 382790075Sobrien;; case 0: template = \"ldmdb\\t%1!, %M0\"; break; 382890075Sobrien;; case 1: template = \"ldmia\\t%1!, %M0\"; break; 382990075Sobrien;; case 2: template = \"ldmia\\t%1, %M0\"; break; 383090075Sobrien;; case 3: template = \"stmdb\\t%0!, %M1\"; break; 383190075Sobrien;; case 4: template = \"stmia\\t%0!, %M1\"; break; 383290075Sobrien;; case 5: template = \"stmia\\t%0, %M1\"; break; 383390075Sobrien;; } 383490075Sobrien;; output_asm_insn (template, operands); 383590075Sobrien;; return \"\"; 383690075Sobrien;; }") 383790075Sobrien 383890075Sobrien(define_expand "movdi" 383990075Sobrien [(set (match_operand:DI 0 "general_operand" "") 384090075Sobrien (match_operand:DI 1 "general_operand" ""))] 384190075Sobrien "TARGET_EITHER" 384290075Sobrien " 384390075Sobrien if (TARGET_THUMB) 384490075Sobrien { 384590075Sobrien if (!no_new_pseudos) 384690075Sobrien { 384790075Sobrien if (GET_CODE (operands[0]) != REG) 384890075Sobrien operands[1] = force_reg (DImode, operands[1]); 384990075Sobrien } 385090075Sobrien } 385190075Sobrien " 385290075Sobrien) 385390075Sobrien 385490075Sobrien(define_insn "*arm_movdi" 385590075Sobrien [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>") 385690075Sobrien (match_operand:DI 1 "di_operand" "rIK,mi,r"))] 3857132718Skan "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT" 385890075Sobrien "* 385990075Sobrien return (output_move_double (operands)); 386090075Sobrien " 386190075Sobrien [(set_attr "length" "8") 386290075Sobrien (set_attr "type" "*,load,store2") 386390075Sobrien (set_attr "pool_range" "*,1020,*") 386496263Sobrien (set_attr "neg_pool_range" "*,1008,*")] 386590075Sobrien) 386690075Sobrien 386790075Sobrien;;; ??? This should have alternatives for constants. 386890075Sobrien;;; ??? This was originally identical to the movdf_insn pattern. 386990075Sobrien;;; ??? The 'i' constraint looks funny, but it should always be replaced by 387090075Sobrien;;; thumb_reorg with a memory reference. 387190075Sobrien(define_insn "*thumb_movdi_insn" 387290075Sobrien [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r") 387390075Sobrien (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))] 387490075Sobrien "TARGET_THUMB 3875132718Skan && !TARGET_CIRRUS 387690075Sobrien && ( register_operand (operands[0], DImode) 387790075Sobrien || register_operand (operands[1], DImode))" 387890075Sobrien "* 387990075Sobrien { 388090075Sobrien switch (which_alternative) 388190075Sobrien { 388290075Sobrien default: 388390075Sobrien case 0: 388490075Sobrien if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 388590075Sobrien return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 388690075Sobrien return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 388790075Sobrien case 1: 388890075Sobrien return \"mov\\t%Q0, %1\;mov\\t%R0, #0\"; 388990075Sobrien case 2: 389090075Sobrien operands[1] = GEN_INT (- INTVAL (operands[1])); 389190075Sobrien return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\"; 389290075Sobrien case 3: 389390075Sobrien return \"ldmia\\t%1, {%0, %H0}\"; 389490075Sobrien case 4: 389590075Sobrien return \"stmia\\t%0, {%1, %H1}\"; 389690075Sobrien case 5: 389790075Sobrien return thumb_load_double_from_address (operands); 389890075Sobrien case 6: 389990075Sobrien operands[2] = gen_rtx (MEM, SImode, 390090075Sobrien plus_constant (XEXP (operands[0], 0), 4)); 390190075Sobrien output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 390290075Sobrien return \"\"; 390390075Sobrien case 7: 390490075Sobrien if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 390590075Sobrien return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 390690075Sobrien return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 390790075Sobrien } 390890075Sobrien }" 390990075Sobrien [(set_attr "length" "4,4,6,2,2,6,4,4") 391090075Sobrien (set_attr "type" "*,*,*,load,store2,load,store2,*") 391190075Sobrien (set_attr "pool_range" "*,*,*,*,*,1020,*,*")] 391290075Sobrien) 391390075Sobrien 391490075Sobrien(define_expand "movsi" 391590075Sobrien [(set (match_operand:SI 0 "general_operand" "") 391690075Sobrien (match_operand:SI 1 "general_operand" ""))] 391790075Sobrien "TARGET_EITHER" 391890075Sobrien " 391990075Sobrien if (TARGET_ARM) 392090075Sobrien { 3921132718Skan /* Everything except mem = const or mem = mem can be done easily. */ 392290075Sobrien if (GET_CODE (operands[0]) == MEM) 392390075Sobrien operands[1] = force_reg (SImode, operands[1]); 392490075Sobrien if (GET_CODE (operands[1]) == CONST_INT 392590075Sobrien && !(const_ok_for_arm (INTVAL (operands[1])) 392690075Sobrien || const_ok_for_arm (~INTVAL (operands[1])))) 392790075Sobrien { 392890075Sobrien arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], 392990075Sobrien NULL_RTX, 393090075Sobrien (no_new_pseudos ? 0 393190075Sobrien : preserve_subexpressions_p ())); 393290075Sobrien DONE; 393390075Sobrien } 393490075Sobrien } 3935132718Skan else /* TARGET_THUMB.... */ 393690075Sobrien { 393790075Sobrien if (!no_new_pseudos) 393890075Sobrien { 393990075Sobrien if (GET_CODE (operands[0]) != REG) 394090075Sobrien operands[1] = force_reg (SImode, operands[1]); 394190075Sobrien } 394290075Sobrien } 394390075Sobrien 394490075Sobrien if (flag_pic 394590075Sobrien && (CONSTANT_P (operands[1]) 394690075Sobrien || symbol_mentioned_p (operands[1]) 394790075Sobrien || label_mentioned_p (operands[1]))) 394890075Sobrien operands[1] = legitimize_pic_address (operands[1], SImode, 394990075Sobrien (no_new_pseudos ? operands[0] : 0)); 395090075Sobrien " 395190075Sobrien) 395290075Sobrien 395390075Sobrien(define_insn "*arm_movsi_insn" 395490075Sobrien [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m") 395590075Sobrien (match_operand:SI 1 "general_operand" "rI,K,mi,r"))] 3956132718Skan "TARGET_ARM && ! TARGET_IWMMXT 395790075Sobrien && ( register_operand (operands[0], SImode) 395890075Sobrien || register_operand (operands[1], SImode))" 395990075Sobrien "@ 396090075Sobrien mov%?\\t%0, %1 396190075Sobrien mvn%?\\t%0, #%B1 396290075Sobrien ldr%?\\t%0, %1 396390075Sobrien str%?\\t%1, %0" 396490075Sobrien [(set_attr "type" "*,*,load,store1") 396590075Sobrien (set_attr "predicable" "yes") 396690075Sobrien (set_attr "pool_range" "*,*,4096,*") 396790075Sobrien (set_attr "neg_pool_range" "*,*,4084,*")] 396890075Sobrien) 396990075Sobrien 397090075Sobrien(define_split 397190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 397290075Sobrien (match_operand:SI 1 "const_int_operand" ""))] 397390075Sobrien "TARGET_ARM 397490075Sobrien && (!(const_ok_for_arm (INTVAL (operands[1])) 397590075Sobrien || const_ok_for_arm (~INTVAL (operands[1]))))" 397690075Sobrien [(clobber (const_int 0))] 397790075Sobrien " 397890075Sobrien arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0], 397990075Sobrien NULL_RTX, 0); 398090075Sobrien DONE; 398190075Sobrien " 398290075Sobrien) 398390075Sobrien 398490075Sobrien(define_insn "*thumb_movsi_insn" 398590075Sobrien [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh") 398690075Sobrien (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))] 398790075Sobrien "TARGET_THUMB 398890075Sobrien && ( register_operand (operands[0], SImode) 398990075Sobrien || register_operand (operands[1], SImode))" 399090075Sobrien "@ 399190075Sobrien mov %0, %1 399290075Sobrien mov %0, %1 399390075Sobrien # 399490075Sobrien # 399590075Sobrien ldmia\\t%1, {%0} 399690075Sobrien stmia\\t%0, {%1} 399790075Sobrien ldr\\t%0, %1 399890075Sobrien str\\t%1, %0 399990075Sobrien mov\\t%0, %1" 400090075Sobrien [(set_attr "length" "2,2,4,4,2,2,2,2,2") 400190075Sobrien (set_attr "type" "*,*,*,*,load,store1,load,store1,*") 400290075Sobrien (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")] 400390075Sobrien) 400490075Sobrien 400590075Sobrien(define_split 400690075Sobrien [(set (match_operand:SI 0 "register_operand" "") 400790075Sobrien (match_operand:SI 1 "const_int_operand" ""))] 400890075Sobrien "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')" 400990075Sobrien [(set (match_dup 0) (match_dup 1)) 401090075Sobrien (set (match_dup 0) (neg:SI (match_dup 0)))] 401190075Sobrien "operands[1] = GEN_INT (- INTVAL (operands[1]));" 401290075Sobrien) 401390075Sobrien 401490075Sobrien(define_split 401590075Sobrien [(set (match_operand:SI 0 "register_operand" "") 401690075Sobrien (match_operand:SI 1 "const_int_operand" ""))] 401790075Sobrien "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')" 401890075Sobrien [(set (match_dup 0) (match_dup 1)) 401990075Sobrien (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))] 402090075Sobrien " 402190075Sobrien { 402290075Sobrien unsigned HOST_WIDE_INT val = INTVAL (operands[1]); 402390075Sobrien unsigned HOST_WIDE_INT mask = 0xff; 402490075Sobrien int i; 402590075Sobrien 402690075Sobrien for (i = 0; i < 25; i++) 402790075Sobrien if ((val & (mask << i)) == val) 402890075Sobrien break; 402990075Sobrien 4030117395Skan /* Shouldn't happen, but we don't want to split if the shift is zero. */ 403190075Sobrien if (i == 0) 403290075Sobrien FAIL; 403390075Sobrien 403490075Sobrien operands[1] = GEN_INT (val >> i); 403590075Sobrien operands[2] = GEN_INT (i); 403690075Sobrien }" 403790075Sobrien) 403890075Sobrien 403990075Sobrien;; When generating pic, we need to load the symbol offset into a register. 404090075Sobrien;; So that the optimizer does not confuse this with a normal symbol load 404190075Sobrien;; we use an unspec. The offset will be loaded from a constant pool entry, 404290075Sobrien;; since that is the only type of relocation we can use. 404390075Sobrien 404490075Sobrien;; The rather odd constraints on the following are to force reload to leave 404590075Sobrien;; the insn alone, and to force the minipool generation pass to then move 404690075Sobrien;; the GOT symbol to memory. 404790075Sobrien 404890075Sobrien(define_insn "pic_load_addr_arm" 404990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 405090075Sobrien (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] 405190075Sobrien "TARGET_ARM && flag_pic" 405290075Sobrien "ldr%?\\t%0, %1" 405390075Sobrien [(set_attr "type" "load") 405490075Sobrien (set (attr "pool_range") (const_int 4096)) 405590075Sobrien (set (attr "neg_pool_range") (const_int 4084))] 405690075Sobrien) 405790075Sobrien 405890075Sobrien(define_insn "pic_load_addr_thumb" 405990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=l") 406090075Sobrien (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] 406190075Sobrien "TARGET_THUMB && flag_pic" 406290075Sobrien "ldr\\t%0, %1" 406390075Sobrien [(set_attr "type" "load") 406490075Sobrien (set (attr "pool_range") (const_int 1024))] 406590075Sobrien) 406690075Sobrien 406790075Sobrien;; This variant is used for AOF assembly, since it needs to mention the 406890075Sobrien;; pic register in the rtl. 406990075Sobrien(define_expand "pic_load_addr_based" 4070132718Skan [(set (match_operand:SI 0 "s_register_operand" "") 407190075Sobrien (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))] 407290075Sobrien "TARGET_ARM && flag_pic" 407390075Sobrien "operands[2] = pic_offset_table_rtx;" 407490075Sobrien) 407590075Sobrien 407690075Sobrien(define_insn "*pic_load_addr_based_insn" 407790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 407890075Sobrien (unspec:SI [(match_operand 1 "" "") 407990075Sobrien (match_operand 2 "s_register_operand" "r")] 408090075Sobrien UNSPEC_PIC_SYM))] 408190075Sobrien "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx" 408290075Sobrien "* 408390075Sobrien#ifdef AOF_ASSEMBLER 408490075Sobrien operands[1] = aof_pic_entry (operands[1]); 408590075Sobrien#endif 408690075Sobrien output_asm_insn (\"ldr%?\\t%0, %a1\", operands); 408790075Sobrien return \"\"; 408890075Sobrien " 408990075Sobrien [(set_attr "type" "load") 409090075Sobrien (set (attr "pool_range") 409190075Sobrien (if_then_else (eq_attr "is_thumb" "yes") 409290075Sobrien (const_int 1024) 409390075Sobrien (const_int 4096))) 409490075Sobrien (set (attr "neg_pool_range") 409590075Sobrien (if_then_else (eq_attr "is_thumb" "yes") 409690075Sobrien (const_int 0) 409790075Sobrien (const_int 4084)))] 409890075Sobrien) 409990075Sobrien 410090075Sobrien(define_insn "pic_add_dot_plus_four" 410190075Sobrien [(set (match_operand:SI 0 "register_operand" "+r") 4102117395Skan (unspec:SI [(plus:SI (match_dup 0) 4103117395Skan (const (plus:SI (pc) (const_int 4))))] 4104117395Skan UNSPEC_PIC_BASE)) 410590075Sobrien (use (label_ref (match_operand 1 "" "")))] 410690075Sobrien "TARGET_THUMB && flag_pic" 410790075Sobrien "* 4108132718Skan (*targetm.asm_out.internal_label) (asm_out_file, \"L\", 410990075Sobrien CODE_LABEL_NUMBER (operands[1])); 411090075Sobrien return \"add\\t%0, %|pc\"; 411190075Sobrien " 411290075Sobrien [(set_attr "length" "2")] 411390075Sobrien) 411490075Sobrien 411590075Sobrien(define_insn "pic_add_dot_plus_eight" 411690075Sobrien [(set (match_operand:SI 0 "register_operand" "+r") 4117117395Skan (unspec:SI [(plus:SI (match_dup 0) 4118117395Skan (const (plus:SI (pc) (const_int 8))))] 4119117395Skan UNSPEC_PIC_BASE)) 412090075Sobrien (use (label_ref (match_operand 1 "" "")))] 412190075Sobrien "TARGET_ARM && flag_pic" 412290075Sobrien "* 4123132718Skan (*targetm.asm_out.internal_label) (asm_out_file, \"L\", 412490075Sobrien CODE_LABEL_NUMBER (operands[1])); 412590075Sobrien return \"add%?\\t%0, %|pc, %0\"; 412690075Sobrien " 412790075Sobrien [(set_attr "predicable" "yes")] 412890075Sobrien) 412990075Sobrien 413090075Sobrien(define_expand "builtin_setjmp_receiver" 413190075Sobrien [(label_ref (match_operand 0 "" ""))] 413290075Sobrien "flag_pic" 413390075Sobrien " 413490075Sobrien{ 413590075Sobrien arm_finalize_pic (0); 413690075Sobrien DONE; 413790075Sobrien}") 413890075Sobrien 413990075Sobrien;; If copying one reg to another we can set the condition codes according to 414090075Sobrien;; its value. Such a move is common after a return from subroutine and the 414190075Sobrien;; result is being tested against zero. 414290075Sobrien 414390075Sobrien(define_insn "*movsi_compare0" 414490075Sobrien [(set (reg:CC CC_REGNUM) 414590075Sobrien (compare:CC (match_operand:SI 1 "s_register_operand" "0,r") 414690075Sobrien (const_int 0))) 414790075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r,r") 414890075Sobrien (match_dup 1))] 414990075Sobrien "TARGET_ARM" 415090075Sobrien "@ 415190075Sobrien cmp%?\\t%0, #0 415290075Sobrien sub%?s\\t%0, %1, #0" 415390075Sobrien [(set_attr "conds" "set")] 415490075Sobrien) 415590075Sobrien 415690075Sobrien;; Subroutine to store a half word from a register into memory. 415790075Sobrien;; Operand 0 is the source register (HImode) 415890075Sobrien;; Operand 1 is the destination address in a register (SImode) 415990075Sobrien 416090075Sobrien;; In both this routine and the next, we must be careful not to spill 416190075Sobrien;; a memory address of reg+large_const into a separate PLUS insn, since this 416290075Sobrien;; can generate unrecognizable rtl. 416390075Sobrien 416490075Sobrien(define_expand "storehi" 416590075Sobrien [;; store the low byte 416690075Sobrien (set (match_operand 1 "" "") (match_dup 3)) 416790075Sobrien ;; extract the high byte 416890075Sobrien (set (match_dup 2) 416990075Sobrien (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 417090075Sobrien ;; store the high byte 4171132718Skan (set (match_dup 4) (match_dup 5))] 417290075Sobrien "TARGET_ARM" 417390075Sobrien " 417490075Sobrien { 417590075Sobrien rtx op1 = operands[1]; 417690075Sobrien rtx addr = XEXP (op1, 0); 417790075Sobrien enum rtx_code code = GET_CODE (addr); 417890075Sobrien 417990075Sobrien if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 418090075Sobrien || code == MINUS) 418190075Sobrien op1 = replace_equiv_address (operands[1], force_reg (SImode, addr)); 418290075Sobrien 418390075Sobrien operands[4] = adjust_address (op1, QImode, 1); 418490075Sobrien operands[1] = adjust_address (operands[1], QImode, 0); 418590075Sobrien operands[3] = gen_lowpart (QImode, operands[0]); 418690075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 4187132718Skan operands[2] = gen_reg_rtx (SImode); 4188132718Skan operands[5] = gen_lowpart (QImode, operands[2]); 418990075Sobrien }" 419090075Sobrien) 419190075Sobrien 419290075Sobrien(define_expand "storehi_bigend" 419390075Sobrien [(set (match_dup 4) (match_dup 3)) 419490075Sobrien (set (match_dup 2) 419590075Sobrien (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) 4196132718Skan (set (match_operand 1 "" "") (match_dup 5))] 419790075Sobrien "TARGET_ARM" 419890075Sobrien " 419990075Sobrien { 420090075Sobrien rtx op1 = operands[1]; 420190075Sobrien rtx addr = XEXP (op1, 0); 420290075Sobrien enum rtx_code code = GET_CODE (addr); 420390075Sobrien 420490075Sobrien if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 420590075Sobrien || code == MINUS) 420690075Sobrien op1 = replace_equiv_address (op1, force_reg (SImode, addr)); 420790075Sobrien 420890075Sobrien operands[4] = adjust_address (op1, QImode, 1); 420990075Sobrien operands[1] = adjust_address (operands[1], QImode, 0); 421090075Sobrien operands[3] = gen_lowpart (QImode, operands[0]); 421190075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 421290075Sobrien operands[2] = gen_reg_rtx (SImode); 4213132718Skan operands[5] = gen_lowpart (QImode, operands[2]); 421490075Sobrien }" 421590075Sobrien) 421690075Sobrien 421790075Sobrien;; Subroutine to store a half word integer constant into memory. 421890075Sobrien(define_expand "storeinthi" 421990075Sobrien [(set (match_operand 0 "" "") 4220132718Skan (match_operand 1 "" "")) 4221102780Skan (set (match_dup 3) (match_dup 2))] 422290075Sobrien "TARGET_ARM" 422390075Sobrien " 422490075Sobrien { 422590075Sobrien HOST_WIDE_INT value = INTVAL (operands[1]); 422690075Sobrien rtx addr = XEXP (operands[0], 0); 422790075Sobrien rtx op0 = operands[0]; 422890075Sobrien enum rtx_code code = GET_CODE (addr); 422990075Sobrien 423090075Sobrien if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT) 423190075Sobrien || code == MINUS) 423290075Sobrien op0 = replace_equiv_address (op0, force_reg (SImode, addr)); 423390075Sobrien 423490075Sobrien operands[1] = gen_reg_rtx (SImode); 423590075Sobrien if (BYTES_BIG_ENDIAN) 423690075Sobrien { 423790075Sobrien emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255))); 423890075Sobrien if ((value & 255) == ((value >> 8) & 255)) 423990075Sobrien operands[2] = operands[1]; 424090075Sobrien else 424190075Sobrien { 424290075Sobrien operands[2] = gen_reg_rtx (SImode); 424390075Sobrien emit_insn (gen_movsi (operands[2], GEN_INT (value & 255))); 424490075Sobrien } 424590075Sobrien } 424690075Sobrien else 424790075Sobrien { 424890075Sobrien emit_insn (gen_movsi (operands[1], GEN_INT (value & 255))); 424990075Sobrien if ((value & 255) == ((value >> 8) & 255)) 425090075Sobrien operands[2] = operands[1]; 425190075Sobrien else 425290075Sobrien { 425390075Sobrien operands[2] = gen_reg_rtx (SImode); 425490075Sobrien emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255))); 425590075Sobrien } 425690075Sobrien } 425790075Sobrien 425890075Sobrien operands[3] = adjust_address (op0, QImode, 1); 425990075Sobrien operands[0] = adjust_address (operands[0], QImode, 0); 4260102780Skan operands[2] = gen_lowpart (QImode, operands[2]); 4261132718Skan operands[1] = gen_lowpart (QImode, operands[1]); 426290075Sobrien }" 426390075Sobrien) 426490075Sobrien 426590075Sobrien(define_expand "storehi_single_op" 426690075Sobrien [(set (match_operand:HI 0 "memory_operand" "") 426790075Sobrien (match_operand:HI 1 "general_operand" ""))] 426890075Sobrien "TARGET_ARM && arm_arch4" 426990075Sobrien " 427090075Sobrien if (!s_register_operand (operands[1], HImode)) 427190075Sobrien operands[1] = copy_to_mode_reg (HImode, operands[1]); 427290075Sobrien " 427390075Sobrien) 427490075Sobrien 427590075Sobrien(define_expand "movhi" 427690075Sobrien [(set (match_operand:HI 0 "general_operand" "") 427790075Sobrien (match_operand:HI 1 "general_operand" ""))] 427890075Sobrien "TARGET_EITHER" 427990075Sobrien " 428090075Sobrien if (TARGET_ARM) 428190075Sobrien { 428290075Sobrien if (!no_new_pseudos) 428390075Sobrien { 428490075Sobrien if (GET_CODE (operands[0]) == MEM) 428590075Sobrien { 428690075Sobrien if (arm_arch4) 428790075Sobrien { 428890075Sobrien emit_insn (gen_storehi_single_op (operands[0], operands[1])); 428990075Sobrien DONE; 429090075Sobrien } 429190075Sobrien if (GET_CODE (operands[1]) == CONST_INT) 429290075Sobrien emit_insn (gen_storeinthi (operands[0], operands[1])); 429390075Sobrien else 429490075Sobrien { 429590075Sobrien if (GET_CODE (operands[1]) == MEM) 429690075Sobrien operands[1] = force_reg (HImode, operands[1]); 429790075Sobrien if (BYTES_BIG_ENDIAN) 429890075Sobrien emit_insn (gen_storehi_bigend (operands[1], operands[0])); 429990075Sobrien else 430090075Sobrien emit_insn (gen_storehi (operands[1], operands[0])); 430190075Sobrien } 430290075Sobrien DONE; 430390075Sobrien } 430490075Sobrien /* Sign extend a constant, and keep it in an SImode reg. */ 430590075Sobrien else if (GET_CODE (operands[1]) == CONST_INT) 430690075Sobrien { 430790075Sobrien rtx reg = gen_reg_rtx (SImode); 430890075Sobrien HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff; 430990075Sobrien 431090075Sobrien /* If the constant is already valid, leave it alone. */ 431190075Sobrien if (!const_ok_for_arm (val)) 431290075Sobrien { 431390075Sobrien /* If setting all the top bits will make the constant 431490075Sobrien loadable in a single instruction, then set them. 431590075Sobrien Otherwise, sign extend the number. */ 431690075Sobrien 431790075Sobrien if (const_ok_for_arm (~(val | ~0xffff))) 431890075Sobrien val |= ~0xffff; 431990075Sobrien else if (val & 0x8000) 432090075Sobrien val |= ~0xffff; 432190075Sobrien } 432290075Sobrien 432390075Sobrien emit_insn (gen_movsi (reg, GEN_INT (val))); 4324102780Skan operands[1] = gen_lowpart (HImode, reg); 432590075Sobrien } 4326117395Skan else if (arm_arch4 && !no_new_pseudos && optimize > 0 4327117395Skan && GET_CODE (operands[1]) == MEM) 4328117395Skan { 4329117395Skan rtx reg = gen_reg_rtx (SImode); 4330117395Skan 4331117395Skan emit_insn (gen_zero_extendhisi2 (reg, operands[1])); 4332117395Skan operands[1] = gen_lowpart (HImode, reg); 4333117395Skan } 433490075Sobrien else if (!arm_arch4) 433590075Sobrien { 433690075Sobrien /* Note: We do not have to worry about TARGET_MMU_TRAPS 433790075Sobrien for v4 and up architectures because LDRH instructions will 433890075Sobrien be used to access the HI values, and these cannot generate 433990075Sobrien unaligned word access faults in the MMU. */ 434090075Sobrien if (GET_CODE (operands[1]) == MEM) 434190075Sobrien { 434290075Sobrien if (TARGET_MMU_TRAPS) 434390075Sobrien { 434490075Sobrien rtx base; 434590075Sobrien rtx offset = const0_rtx; 434690075Sobrien rtx reg = gen_reg_rtx (SImode); 434790075Sobrien 434890075Sobrien if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 434990075Sobrien || (GET_CODE (base) == PLUS 435090075Sobrien && (GET_CODE (offset = XEXP (base, 1)) 435190075Sobrien == CONST_INT) 435290075Sobrien && ((INTVAL(offset) & 1) != 1) 435390075Sobrien && GET_CODE (base = XEXP (base, 0)) == REG)) 435490075Sobrien && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 435590075Sobrien { 435690075Sobrien HOST_WIDE_INT new_offset = INTVAL (offset) & ~3; 435790075Sobrien rtx new; 435890075Sobrien 435990075Sobrien new = gen_rtx_MEM (SImode, 436090075Sobrien plus_constant (base, new_offset)); 436190075Sobrien MEM_COPY_ATTRIBUTES (new, operands[1]); 436290075Sobrien emit_insn (gen_movsi (reg, new)); 436390075Sobrien if (((INTVAL (offset) & 2) != 0) 436490075Sobrien ^ (BYTES_BIG_ENDIAN ? 1 : 0)) 436590075Sobrien { 436690075Sobrien rtx reg2 = gen_reg_rtx (SImode); 436790075Sobrien 436890075Sobrien emit_insn (gen_lshrsi3 (reg2, reg, 436990075Sobrien GEN_INT (16))); 437090075Sobrien reg = reg2; 437190075Sobrien } 437290075Sobrien } 437390075Sobrien else 437490075Sobrien emit_insn (gen_movhi_bytes (reg, operands[1])); 437590075Sobrien 437690075Sobrien operands[1] = gen_lowpart (HImode, reg); 437790075Sobrien } 437890075Sobrien else if (BYTES_BIG_ENDIAN) 437990075Sobrien { 438090075Sobrien rtx base; 438190075Sobrien rtx offset = const0_rtx; 438290075Sobrien 438390075Sobrien if ((GET_CODE (base = XEXP (operands[1], 0)) == REG 438490075Sobrien || (GET_CODE (base) == PLUS 438590075Sobrien && (GET_CODE (offset = XEXP (base, 1)) 438690075Sobrien == CONST_INT) 438790075Sobrien && GET_CODE (base = XEXP (base, 0)) == REG)) 438890075Sobrien && REGNO_POINTER_ALIGN (REGNO (base)) >= 32) 438990075Sobrien { 439090075Sobrien rtx reg = gen_reg_rtx (SImode); 439190075Sobrien rtx new; 439290075Sobrien 439390075Sobrien if ((INTVAL (offset) & 2) == 2) 439490075Sobrien { 439590075Sobrien HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2; 439690075Sobrien new = gen_rtx_MEM (SImode, 439790075Sobrien plus_constant (base, 439890075Sobrien new_offset)); 439990075Sobrien MEM_COPY_ATTRIBUTES (new, operands[1]); 440090075Sobrien emit_insn (gen_movsi (reg, new)); 440190075Sobrien } 440290075Sobrien else 440390075Sobrien { 440490075Sobrien new = gen_rtx_MEM (SImode, 440590075Sobrien XEXP (operands[1], 0)); 440690075Sobrien MEM_COPY_ATTRIBUTES (new, operands[1]); 440790075Sobrien emit_insn (gen_rotated_loadsi (reg, new)); 440890075Sobrien } 440990075Sobrien 441090075Sobrien operands[1] = gen_lowpart (HImode, reg); 441190075Sobrien } 441290075Sobrien else 441390075Sobrien { 441490075Sobrien emit_insn (gen_movhi_bigend (operands[0], 441590075Sobrien operands[1])); 441690075Sobrien DONE; 441790075Sobrien } 441890075Sobrien } 441990075Sobrien } 442090075Sobrien } 442190075Sobrien } 4422132718Skan /* Handle loading a large integer during reload. */ 442390075Sobrien else if (GET_CODE (operands[1]) == CONST_INT 442490075Sobrien && !const_ok_for_arm (INTVAL (operands[1])) 442590075Sobrien && !const_ok_for_arm (~INTVAL (operands[1]))) 442690075Sobrien { 442790075Sobrien /* Writing a constant to memory needs a scratch, which should 442890075Sobrien be handled with SECONDARY_RELOADs. */ 442990075Sobrien if (GET_CODE (operands[0]) != REG) 443090075Sobrien abort (); 443190075Sobrien 443290075Sobrien operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 443390075Sobrien emit_insn (gen_movsi (operands[0], operands[1])); 443490075Sobrien DONE; 443590075Sobrien } 443690075Sobrien } 443790075Sobrien else /* TARGET_THUMB */ 443890075Sobrien { 443990075Sobrien if (!no_new_pseudos) 444090075Sobrien { 444190075Sobrien if (GET_CODE (operands[0]) != REG) 444290075Sobrien operands[1] = force_reg (HImode, operands[1]); 444390075Sobrien 444490075Sobrien /* ??? We shouldn't really get invalid addresses here, but this can 444590075Sobrien happen if we are passed a SP (never OK for HImode/QImode) or 444690075Sobrien virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 444790075Sobrien HImode/QImode) relative address. */ 444890075Sobrien /* ??? This should perhaps be fixed elsewhere, for instance, in 444990075Sobrien fixup_stack_1, by checking for other kinds of invalid addresses, 445090075Sobrien e.g. a bare reference to a virtual register. This may confuse the 445190075Sobrien alpha though, which must handle this case differently. */ 445290075Sobrien if (GET_CODE (operands[0]) == MEM 445390075Sobrien && !memory_address_p (GET_MODE (operands[0]), 445490075Sobrien XEXP (operands[0], 0))) 445590075Sobrien operands[0] 445690075Sobrien = replace_equiv_address (operands[0], 445790075Sobrien copy_to_reg (XEXP (operands[0], 0))); 445890075Sobrien 445990075Sobrien if (GET_CODE (operands[1]) == MEM 446090075Sobrien && !memory_address_p (GET_MODE (operands[1]), 446190075Sobrien XEXP (operands[1], 0))) 446290075Sobrien operands[1] 446390075Sobrien = replace_equiv_address (operands[1], 446490075Sobrien copy_to_reg (XEXP (operands[1], 0))); 446590075Sobrien } 4466132718Skan /* Handle loading a large integer during reload. */ 446790075Sobrien else if (GET_CODE (operands[1]) == CONST_INT 446890075Sobrien && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I')) 446990075Sobrien { 447090075Sobrien /* Writing a constant to memory needs a scratch, which should 447190075Sobrien be handled with SECONDARY_RELOADs. */ 447290075Sobrien if (GET_CODE (operands[0]) != REG) 447390075Sobrien abort (); 447490075Sobrien 447590075Sobrien operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0); 447690075Sobrien emit_insn (gen_movsi (operands[0], operands[1])); 447790075Sobrien DONE; 447890075Sobrien } 447990075Sobrien } 448090075Sobrien " 448190075Sobrien) 448290075Sobrien 448390075Sobrien(define_insn "*thumb_movhi_insn" 4484132718Skan [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l") 4485132718Skan (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))] 448690075Sobrien "TARGET_THUMB 448790075Sobrien && ( register_operand (operands[0], HImode) 448890075Sobrien || register_operand (operands[1], HImode))" 448990075Sobrien "* 449090075Sobrien switch (which_alternative) 449190075Sobrien { 449290075Sobrien case 0: return \"add %0, %1, #0\"; 449390075Sobrien case 2: return \"strh %1, %0\"; 449490075Sobrien case 3: return \"mov %0, %1\"; 449590075Sobrien case 4: return \"mov %0, %1\"; 449690075Sobrien case 5: return \"mov %0, %1\"; 449790075Sobrien default: abort (); 449890075Sobrien case 1: 449990075Sobrien /* The stack pointer can end up being taken as an index register. 450090075Sobrien Catch this case here and deal with it. */ 450190075Sobrien if (GET_CODE (XEXP (operands[1], 0)) == PLUS 450290075Sobrien && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG 450390075Sobrien && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM) 450490075Sobrien { 450590075Sobrien rtx ops[2]; 450690075Sobrien ops[0] = operands[0]; 450790075Sobrien ops[1] = XEXP (XEXP (operands[1], 0), 0); 450890075Sobrien 450990075Sobrien output_asm_insn (\"mov %0, %1\", ops); 451090075Sobrien 451190075Sobrien XEXP (XEXP (operands[1], 0), 0) = operands[0]; 451290075Sobrien 451390075Sobrien } 451490075Sobrien return \"ldrh %0, %1\"; 451590075Sobrien }" 451690075Sobrien [(set_attr "length" "2,4,2,2,2,2") 4517132718Skan (set_attr "type" "*,load,store1,*,*,*")] 451890075Sobrien) 451990075Sobrien 452090075Sobrien 452190075Sobrien(define_insn "rotated_loadsi" 452290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 452390075Sobrien (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o") 452490075Sobrien (const_int 16)))] 452590075Sobrien "TARGET_ARM && (!TARGET_MMU_TRAPS)" 452690075Sobrien "* 452790075Sobrien { 452890075Sobrien rtx ops[2]; 452990075Sobrien 453090075Sobrien ops[0] = operands[0]; 453190075Sobrien ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2)); 453290075Sobrien output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops); 453390075Sobrien return \"\"; 453490075Sobrien }" 453590075Sobrien [(set_attr "type" "load") 453690075Sobrien (set_attr "predicable" "yes")] 453790075Sobrien) 453890075Sobrien 453990075Sobrien(define_expand "movhi_bytes" 454090075Sobrien [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" ""))) 454190075Sobrien (set (match_dup 3) 454290075Sobrien (zero_extend:SI (match_dup 6))) 454390075Sobrien (set (match_operand:SI 0 "" "") 454490075Sobrien (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))] 454590075Sobrien "TARGET_ARM" 454690075Sobrien " 454790075Sobrien { 454890075Sobrien rtx mem1, mem2; 454990075Sobrien rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); 455090075Sobrien 455190075Sobrien mem1 = gen_rtx_MEM (QImode, addr); 455290075Sobrien MEM_COPY_ATTRIBUTES (mem1, operands[1]); 455390075Sobrien mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1)); 455490075Sobrien MEM_COPY_ATTRIBUTES (mem2, operands[1]); 455590075Sobrien operands[0] = gen_lowpart (SImode, operands[0]); 455690075Sobrien operands[1] = mem1; 455790075Sobrien operands[2] = gen_reg_rtx (SImode); 455890075Sobrien operands[3] = gen_reg_rtx (SImode); 455990075Sobrien operands[6] = mem2; 456090075Sobrien 456190075Sobrien if (BYTES_BIG_ENDIAN) 456290075Sobrien { 456390075Sobrien operands[4] = operands[2]; 456490075Sobrien operands[5] = operands[3]; 456590075Sobrien } 456690075Sobrien else 456790075Sobrien { 456890075Sobrien operands[4] = operands[3]; 456990075Sobrien operands[5] = operands[2]; 457090075Sobrien } 457190075Sobrien }" 457290075Sobrien) 457390075Sobrien 457490075Sobrien(define_expand "movhi_bigend" 457590075Sobrien [(set (match_dup 2) 457690075Sobrien (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0) 457790075Sobrien (const_int 16))) 457890075Sobrien (set (match_dup 3) 457990075Sobrien (ashiftrt:SI (match_dup 2) (const_int 16))) 458090075Sobrien (set (match_operand:HI 0 "s_register_operand" "") 4581132718Skan (match_dup 4))] 458290075Sobrien "TARGET_ARM" 458390075Sobrien " 458490075Sobrien operands[2] = gen_reg_rtx (SImode); 458590075Sobrien operands[3] = gen_reg_rtx (SImode); 4586132718Skan operands[4] = gen_lowpart (HImode, operands[3]); 458790075Sobrien " 458890075Sobrien) 458990075Sobrien 4590117395Skan;; Pattern to recognize insn generated default case above 459190075Sobrien(define_insn "*movhi_insn_arch4" 459290075Sobrien [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") 459390075Sobrien (match_operand:HI 1 "general_operand" "rI,K,r,m"))] 459490075Sobrien "TARGET_ARM 459590075Sobrien && arm_arch4 459690075Sobrien && (GET_CODE (operands[1]) != CONST_INT 459790075Sobrien || const_ok_for_arm (INTVAL (operands[1])) 459890075Sobrien || const_ok_for_arm (~INTVAL (operands[1])))" 459990075Sobrien "@ 460090075Sobrien mov%?\\t%0, %1\\t%@ movhi 460190075Sobrien mvn%?\\t%0, #%B1\\t%@ movhi 460290075Sobrien str%?h\\t%1, %0\\t%@ movhi 460390075Sobrien ldr%?h\\t%0, %1\\t%@ movhi" 460490075Sobrien [(set_attr "type" "*,*,store1,load") 460590075Sobrien (set_attr "predicable" "yes") 460690075Sobrien (set_attr "pool_range" "*,*,*,256") 460790075Sobrien (set_attr "neg_pool_range" "*,*,*,244")] 460890075Sobrien) 460990075Sobrien 461090075Sobrien(define_insn "*movhi_insn_littleend" 461190075Sobrien [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 461290075Sobrien (match_operand:HI 1 "general_operand" "rI,K,m"))] 461390075Sobrien "TARGET_ARM 461490075Sobrien && !arm_arch4 461590075Sobrien && !BYTES_BIG_ENDIAN 461690075Sobrien && !TARGET_MMU_TRAPS 461790075Sobrien && (GET_CODE (operands[1]) != CONST_INT 461890075Sobrien || const_ok_for_arm (INTVAL (operands[1])) 461990075Sobrien || const_ok_for_arm (~INTVAL (operands[1])))" 462090075Sobrien "@ 462190075Sobrien mov%?\\t%0, %1\\t%@ movhi 462290075Sobrien mvn%?\\t%0, #%B1\\t%@ movhi 462390075Sobrien ldr%?\\t%0, %1\\t%@ movhi" 462490075Sobrien [(set_attr "type" "*,*,load") 462590075Sobrien (set_attr "predicable" "yes") 462690075Sobrien (set_attr "pool_range" "4096") 462790075Sobrien (set_attr "neg_pool_range" "4084")] 462890075Sobrien) 462990075Sobrien 463090075Sobrien(define_insn "*movhi_insn_bigend" 463190075Sobrien [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") 463290075Sobrien (match_operand:HI 1 "general_operand" "rI,K,m"))] 463390075Sobrien "TARGET_ARM 463490075Sobrien && !arm_arch4 463590075Sobrien && BYTES_BIG_ENDIAN 463690075Sobrien && !TARGET_MMU_TRAPS 463790075Sobrien && (GET_CODE (operands[1]) != CONST_INT 463890075Sobrien || const_ok_for_arm (INTVAL (operands[1])) 463990075Sobrien || const_ok_for_arm (~INTVAL (operands[1])))" 464090075Sobrien "@ 464190075Sobrien mov%?\\t%0, %1\\t%@ movhi 464290075Sobrien mvn%?\\t%0, #%B1\\t%@ movhi 464390075Sobrien ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16" 464490075Sobrien [(set_attr "type" "*,*,load") 464590075Sobrien (set_attr "predicable" "yes") 464690075Sobrien (set_attr "length" "4,4,8") 464790075Sobrien (set_attr "pool_range" "*,*,4092") 464890075Sobrien (set_attr "neg_pool_range" "*,*,4084")] 464990075Sobrien) 465090075Sobrien 465190075Sobrien(define_insn "*loadhi_si_bigend" 465290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 465390075Sobrien (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0) 465490075Sobrien (const_int 16)))] 465590075Sobrien "TARGET_ARM 465690075Sobrien && BYTES_BIG_ENDIAN 465790075Sobrien && !TARGET_MMU_TRAPS" 465890075Sobrien "ldr%?\\t%0, %1\\t%@ movhi_bigend" 465990075Sobrien [(set_attr "type" "load") 466090075Sobrien (set_attr "predicable" "yes") 466190075Sobrien (set_attr "pool_range" "4096") 466290075Sobrien (set_attr "neg_pool_range" "4084")] 466390075Sobrien) 466490075Sobrien 466590075Sobrien(define_insn "*movhi_bytes" 466690075Sobrien [(set (match_operand:HI 0 "s_register_operand" "=r,r") 466790075Sobrien (match_operand:HI 1 "arm_rhs_operand" "rI,K"))] 466890075Sobrien "TARGET_ARM && TARGET_MMU_TRAPS" 466990075Sobrien "@ 467090075Sobrien mov%?\\t%0, %1\\t%@ movhi 467190075Sobrien mvn%?\\t%0, #%B1\\t%@ movhi" 467290075Sobrien [(set_attr "predicable" "yes")] 467390075Sobrien) 467490075Sobrien 467590075Sobrien(define_insn "thumb_movhi_clobber" 467690075Sobrien [(set (match_operand:HI 0 "memory_operand" "=m") 467790075Sobrien (match_operand:HI 1 "register_operand" "l")) 467890075Sobrien (clobber (match_operand:SI 2 "register_operand" "=&l"))] 467990075Sobrien "TARGET_THUMB" 468090075Sobrien "* 468190075Sobrien abort ();" 468290075Sobrien) 468390075Sobrien 468490075Sobrien;; We use a DImode scratch because we may occasionally need an additional 468590075Sobrien;; temporary if the address isn't offsettable -- push_reload doesn't seem 468690075Sobrien;; to take any notice of the "o" constraints on reload_memory_operand operand. 468790075Sobrien(define_expand "reload_outhi" 468890075Sobrien [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o") 468990075Sobrien (match_operand:HI 1 "s_register_operand" "r") 469090075Sobrien (match_operand:DI 2 "s_register_operand" "=&l")])] 469190075Sobrien "TARGET_EITHER" 469290075Sobrien "if (TARGET_ARM) 469390075Sobrien arm_reload_out_hi (operands); 469490075Sobrien else 469590075Sobrien thumb_reload_out_hi (operands); 469690075Sobrien DONE; 469790075Sobrien " 469890075Sobrien) 469990075Sobrien 470090075Sobrien(define_expand "reload_inhi" 470190075Sobrien [(parallel [(match_operand:HI 0 "s_register_operand" "=r") 470290075Sobrien (match_operand:HI 1 "arm_reload_memory_operand" "o") 470390075Sobrien (match_operand:DI 2 "s_register_operand" "=&r")])] 470490075Sobrien "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)" 470590075Sobrien " 470690075Sobrien if (TARGET_ARM) 470790075Sobrien arm_reload_in_hi (operands); 470890075Sobrien else 470990075Sobrien thumb_reload_out_hi (operands); 471090075Sobrien DONE; 471190075Sobrien") 471290075Sobrien 471390075Sobrien(define_expand "movqi" 471490075Sobrien [(set (match_operand:QI 0 "general_operand" "") 471590075Sobrien (match_operand:QI 1 "general_operand" ""))] 471690075Sobrien "TARGET_EITHER" 471790075Sobrien " 471890075Sobrien if (TARGET_ARM) 471990075Sobrien { 472090075Sobrien /* Everything except mem = const or mem = mem can be done easily */ 472190075Sobrien 472290075Sobrien if (!no_new_pseudos) 472390075Sobrien { 472490075Sobrien if (GET_CODE (operands[1]) == CONST_INT) 472590075Sobrien { 472690075Sobrien rtx reg = gen_reg_rtx (SImode); 472790075Sobrien 472890075Sobrien emit_insn (gen_movsi (reg, operands[1])); 4729102780Skan operands[1] = gen_lowpart (QImode, reg); 473090075Sobrien } 4731117395Skan if (GET_CODE (operands[1]) == MEM && optimize > 0) 4732117395Skan { 4733117395Skan rtx reg = gen_reg_rtx (SImode); 4734117395Skan 4735117395Skan emit_insn (gen_zero_extendqisi2 (reg, operands[1])); 4736117395Skan operands[1] = gen_lowpart (QImode, reg); 4737117395Skan } 4738117395Skan if (GET_CODE (operands[0]) == MEM) 4739117395Skan operands[1] = force_reg (QImode, operands[1]); 4740117395Skan } 474190075Sobrien } 474290075Sobrien else /* TARGET_THUMB */ 474390075Sobrien { 474490075Sobrien if (!no_new_pseudos) 474590075Sobrien { 474690075Sobrien if (GET_CODE (operands[0]) != REG) 474790075Sobrien operands[1] = force_reg (QImode, operands[1]); 474890075Sobrien 474990075Sobrien /* ??? We shouldn't really get invalid addresses here, but this can 475090075Sobrien happen if we are passed a SP (never OK for HImode/QImode) or 475190075Sobrien virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 475290075Sobrien HImode/QImode) relative address. */ 475390075Sobrien /* ??? This should perhaps be fixed elsewhere, for instance, in 475490075Sobrien fixup_stack_1, by checking for other kinds of invalid addresses, 475590075Sobrien e.g. a bare reference to a virtual register. This may confuse the 475690075Sobrien alpha though, which must handle this case differently. */ 475790075Sobrien if (GET_CODE (operands[0]) == MEM 475890075Sobrien && !memory_address_p (GET_MODE (operands[0]), 475990075Sobrien XEXP (operands[0], 0))) 476090075Sobrien operands[0] 476190075Sobrien = replace_equiv_address (operands[0], 476290075Sobrien copy_to_reg (XEXP (operands[0], 0))); 476390075Sobrien if (GET_CODE (operands[1]) == MEM 476490075Sobrien && !memory_address_p (GET_MODE (operands[1]), 476590075Sobrien XEXP (operands[1], 0))) 476690075Sobrien operands[1] 476790075Sobrien = replace_equiv_address (operands[1], 476890075Sobrien copy_to_reg (XEXP (operands[1], 0))); 476990075Sobrien } 4770132718Skan /* Handle loading a large integer during reload. */ 477190075Sobrien else if (GET_CODE (operands[1]) == CONST_INT 477290075Sobrien && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I')) 477390075Sobrien { 477490075Sobrien /* Writing a constant to memory needs a scratch, which should 477590075Sobrien be handled with SECONDARY_RELOADs. */ 477690075Sobrien if (GET_CODE (operands[0]) != REG) 477790075Sobrien abort (); 477890075Sobrien 4779102780Skan operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); 478090075Sobrien emit_insn (gen_movsi (operands[0], operands[1])); 478190075Sobrien DONE; 478290075Sobrien } 478390075Sobrien } 478490075Sobrien " 478590075Sobrien) 478690075Sobrien 478790075Sobrien 478890075Sobrien(define_insn "*arm_movqi_insn" 478990075Sobrien [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m") 479090075Sobrien (match_operand:QI 1 "general_operand" "rI,K,m,r"))] 479190075Sobrien "TARGET_ARM 479290075Sobrien && ( register_operand (operands[0], QImode) 479390075Sobrien || register_operand (operands[1], QImode))" 479490075Sobrien "@ 479590075Sobrien mov%?\\t%0, %1 479690075Sobrien mvn%?\\t%0, #%B1 479790075Sobrien ldr%?b\\t%0, %1 479890075Sobrien str%?b\\t%1, %0" 479990075Sobrien [(set_attr "type" "*,*,load,store1") 480090075Sobrien (set_attr "predicable" "yes")] 480190075Sobrien) 480290075Sobrien 480390075Sobrien(define_insn "*thumb_movqi_insn" 480490075Sobrien [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l") 480590075Sobrien (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))] 480690075Sobrien "TARGET_THUMB 480790075Sobrien && ( register_operand (operands[0], QImode) 480890075Sobrien || register_operand (operands[1], QImode))" 480990075Sobrien "@ 481090075Sobrien add\\t%0, %1, #0 481190075Sobrien ldrb\\t%0, %1 481290075Sobrien strb\\t%1, %0 481390075Sobrien mov\\t%0, %1 481490075Sobrien mov\\t%0, %1 481590075Sobrien mov\\t%0, %1" 481690075Sobrien [(set_attr "length" "2") 481790075Sobrien (set_attr "type" "*,load,store1,*,*,*") 481890075Sobrien (set_attr "pool_range" "*,32,*,*,*,*")] 481990075Sobrien) 482090075Sobrien 482190075Sobrien(define_expand "movsf" 482290075Sobrien [(set (match_operand:SF 0 "general_operand" "") 482390075Sobrien (match_operand:SF 1 "general_operand" ""))] 482490075Sobrien "TARGET_EITHER" 482590075Sobrien " 482690075Sobrien if (TARGET_ARM) 482790075Sobrien { 482890075Sobrien if (GET_CODE (operands[0]) == MEM) 482990075Sobrien operands[1] = force_reg (SFmode, operands[1]); 483090075Sobrien } 483190075Sobrien else /* TARGET_THUMB */ 483290075Sobrien { 483390075Sobrien if (!no_new_pseudos) 483490075Sobrien { 483590075Sobrien if (GET_CODE (operands[0]) != REG) 483690075Sobrien operands[1] = force_reg (SFmode, operands[1]); 483790075Sobrien } 483890075Sobrien } 483990075Sobrien " 484090075Sobrien) 484190075Sobrien 484290075Sobrien(define_split 484390075Sobrien [(set (match_operand:SF 0 "nonimmediate_operand" "") 484490075Sobrien (match_operand:SF 1 "immediate_operand" ""))] 484590075Sobrien "TARGET_ARM 484690075Sobrien && !TARGET_HARD_FLOAT 484790075Sobrien && reload_completed 484890075Sobrien && GET_CODE (operands[1]) == CONST_DOUBLE" 484990075Sobrien [(set (match_dup 2) (match_dup 3))] 485090075Sobrien " 485190075Sobrien operands[2] = gen_lowpart (SImode, operands[0]); 485290075Sobrien operands[3] = gen_lowpart (SImode, operands[1]); 485390075Sobrien if (operands[2] == 0 || operands[3] == 0) 485490075Sobrien FAIL; 485590075Sobrien " 485690075Sobrien) 485790075Sobrien 485890075Sobrien(define_insn "*arm_movsf_soft_insn" 485990075Sobrien [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") 486090075Sobrien (match_operand:SF 1 "general_operand" "r,mE,r"))] 486190075Sobrien "TARGET_ARM 4862132718Skan && !TARGET_CIRRUS 486390075Sobrien && TARGET_SOFT_FLOAT 486490075Sobrien && (GET_CODE (operands[0]) != MEM 486590075Sobrien || register_operand (operands[1], SFmode))" 486690075Sobrien "@ 486790075Sobrien mov%?\\t%0, %1 486890075Sobrien ldr%?\\t%0, %1\\t%@ float 486990075Sobrien str%?\\t%1, %0\\t%@ float" 487090075Sobrien [(set_attr "length" "4,4,4") 487190075Sobrien (set_attr "predicable" "yes") 487290075Sobrien (set_attr "type" "*,load,store1") 487390075Sobrien (set_attr "pool_range" "*,4096,*") 487490075Sobrien (set_attr "neg_pool_range" "*,4084,*")] 487590075Sobrien) 487690075Sobrien 487790075Sobrien;;; ??? This should have alternatives for constants. 487890075Sobrien(define_insn "*thumb_movsf_insn" 487990075Sobrien [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h") 488090075Sobrien (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))] 488190075Sobrien "TARGET_THUMB 488290075Sobrien && ( register_operand (operands[0], SFmode) 488390075Sobrien || register_operand (operands[1], SFmode))" 488490075Sobrien "@ 488590075Sobrien add\\t%0, %1, #0 488690075Sobrien ldmia\\t%1, {%0} 488790075Sobrien stmia\\t%0, {%1} 488890075Sobrien ldr\\t%0, %1 488990075Sobrien str\\t%1, %0 489090075Sobrien mov\\t%0, %1 489190075Sobrien mov\\t%0, %1" 489290075Sobrien [(set_attr "length" "2") 489390075Sobrien (set_attr "type" "*,load,store1,load,store1,*,*") 489490075Sobrien (set_attr "pool_range" "*,*,*,1020,*,*,*")] 489590075Sobrien) 489690075Sobrien 489790075Sobrien(define_expand "movdf" 489890075Sobrien [(set (match_operand:DF 0 "general_operand" "") 489990075Sobrien (match_operand:DF 1 "general_operand" ""))] 490090075Sobrien "TARGET_EITHER" 490190075Sobrien " 490290075Sobrien if (TARGET_ARM) 490390075Sobrien { 490490075Sobrien if (GET_CODE (operands[0]) == MEM) 490590075Sobrien operands[1] = force_reg (DFmode, operands[1]); 490690075Sobrien } 490790075Sobrien else /* TARGET_THUMB */ 490890075Sobrien { 490990075Sobrien if (!no_new_pseudos) 491090075Sobrien { 491190075Sobrien if (GET_CODE (operands[0]) != REG) 491290075Sobrien operands[1] = force_reg (DFmode, operands[1]); 491390075Sobrien } 491490075Sobrien } 491590075Sobrien " 491690075Sobrien) 491790075Sobrien 491890075Sobrien;; Reloading a df mode value stored in integer regs to memory can require a 491990075Sobrien;; scratch reg. 492090075Sobrien(define_expand "reload_outdf" 492190075Sobrien [(match_operand:DF 0 "arm_reload_memory_operand" "=o") 492290075Sobrien (match_operand:DF 1 "s_register_operand" "r") 492390075Sobrien (match_operand:SI 2 "s_register_operand" "=&r")] 492490075Sobrien "TARGET_ARM" 492590075Sobrien " 492690075Sobrien { 492790075Sobrien enum rtx_code code = GET_CODE (XEXP (operands[0], 0)); 492890075Sobrien 492990075Sobrien if (code == REG) 493090075Sobrien operands[2] = XEXP (operands[0], 0); 493190075Sobrien else if (code == POST_INC || code == PRE_DEC) 493290075Sobrien { 493390075Sobrien operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); 493490075Sobrien operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0); 493590075Sobrien emit_insn (gen_movdi (operands[0], operands[1])); 493690075Sobrien DONE; 493790075Sobrien } 493890075Sobrien else if (code == PRE_INC) 493990075Sobrien { 494090075Sobrien rtx reg = XEXP (XEXP (operands[0], 0), 0); 494190075Sobrien 494290075Sobrien emit_insn (gen_addsi3 (reg, reg, GEN_INT (8))); 494390075Sobrien operands[2] = reg; 494490075Sobrien } 494590075Sobrien else if (code == POST_DEC) 494690075Sobrien operands[2] = XEXP (XEXP (operands[0], 0), 0); 494790075Sobrien else 494890075Sobrien emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0), 494990075Sobrien XEXP (XEXP (operands[0], 0), 1))); 495090075Sobrien 495190075Sobrien emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]), 495290075Sobrien operands[1])); 495390075Sobrien 495490075Sobrien if (code == POST_DEC) 495590075Sobrien emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8))); 495690075Sobrien 495790075Sobrien DONE; 495890075Sobrien }" 495990075Sobrien) 496090075Sobrien 496190075Sobrien(define_insn "*movdf_soft_insn" 496290075Sobrien [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m") 496390075Sobrien (match_operand:DF 1 "soft_df_operand" "r,mF,r"))] 496490075Sobrien "TARGET_ARM && TARGET_SOFT_FLOAT 4965132718Skan && !TARGET_CIRRUS 496690075Sobrien " 496790075Sobrien "* return output_move_double (operands);" 496890075Sobrien [(set_attr "length" "8,8,8") 496990075Sobrien (set_attr "type" "*,load,store2") 497096263Sobrien (set_attr "pool_range" "1020") 497196263Sobrien (set_attr "neg_pool_range" "1008")] 497290075Sobrien) 497390075Sobrien 497490075Sobrien;;; ??? This should have alternatives for constants. 497590075Sobrien;;; ??? This was originally identical to the movdi_insn pattern. 497690075Sobrien;;; ??? The 'F' constraint looks funny, but it should always be replaced by 497790075Sobrien;;; thumb_reorg with a memory reference. 497890075Sobrien(define_insn "*thumb_movdf_insn" 497990075Sobrien [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r") 498090075Sobrien (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))] 498190075Sobrien "TARGET_THUMB 498290075Sobrien && ( register_operand (operands[0], DFmode) 498390075Sobrien || register_operand (operands[1], DFmode))" 498490075Sobrien "* 498590075Sobrien switch (which_alternative) 498690075Sobrien { 498790075Sobrien default: 498890075Sobrien case 0: 498990075Sobrien if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 499090075Sobrien return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 499190075Sobrien return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 499290075Sobrien case 1: 499390075Sobrien return \"ldmia\\t%1, {%0, %H0}\"; 499490075Sobrien case 2: 499590075Sobrien return \"stmia\\t%0, {%1, %H1}\"; 499690075Sobrien case 3: 499790075Sobrien return thumb_load_double_from_address (operands); 499890075Sobrien case 4: 499990075Sobrien operands[2] = gen_rtx (MEM, SImode, 500090075Sobrien plus_constant (XEXP (operands[0], 0), 4)); 500190075Sobrien output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 500290075Sobrien return \"\"; 500390075Sobrien case 5: 500490075Sobrien if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 500590075Sobrien return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 500690075Sobrien return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 500790075Sobrien } 500890075Sobrien " 500990075Sobrien [(set_attr "length" "4,2,2,6,4,4") 501090075Sobrien (set_attr "type" "*,load,store2,load,store2,*") 501190075Sobrien (set_attr "pool_range" "*,*,*,1020,*,*")] 501290075Sobrien) 501390075Sobrien 5014132718Skan;; Vector Moves 5015132718Skan(define_expand "movv2si" 5016132718Skan [(set (match_operand:V2SI 0 "nonimmediate_operand" "") 5017132718Skan (match_operand:V2SI 1 "general_operand" ""))] 5018132718Skan "TARGET_REALLY_IWMMXT" 5019132718Skan{ 5020132718Skan}) 502190075Sobrien 5022132718Skan(define_expand "movv4hi" 5023132718Skan [(set (match_operand:V4HI 0 "nonimmediate_operand" "") 5024132718Skan (match_operand:V4HI 1 "general_operand" ""))] 5025132718Skan "TARGET_REALLY_IWMMXT" 5026132718Skan{ 5027132718Skan}) 502890075Sobrien 5029132718Skan(define_expand "movv8qi" 5030132718Skan [(set (match_operand:V8QI 0 "nonimmediate_operand" "") 5031132718Skan (match_operand:V8QI 1 "general_operand" ""))] 5032132718Skan "TARGET_REALLY_IWMMXT" 5033132718Skan{ 5034132718Skan}) 503590075Sobrien 503690075Sobrien 503790075Sobrien;; load- and store-multiple insns 503890075Sobrien;; The arm can load/store any set of registers, provided that they are in 503990075Sobrien;; ascending order; but that is beyond GCC so stick with what it knows. 504090075Sobrien 504190075Sobrien(define_expand "load_multiple" 504290075Sobrien [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 504390075Sobrien (match_operand:SI 1 "" "")) 504490075Sobrien (use (match_operand:SI 2 "" ""))])] 504590075Sobrien "TARGET_ARM" 504690075Sobrien " 504790075Sobrien /* Support only fixed point registers. */ 504890075Sobrien if (GET_CODE (operands[2]) != CONST_INT 504990075Sobrien || INTVAL (operands[2]) > 14 505090075Sobrien || INTVAL (operands[2]) < 2 505190075Sobrien || GET_CODE (operands[1]) != MEM 505290075Sobrien || GET_CODE (operands[0]) != REG 505390075Sobrien || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1) 505490075Sobrien || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 505590075Sobrien FAIL; 505690075Sobrien 505790075Sobrien operands[3] 505890075Sobrien = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]), 505990075Sobrien force_reg (SImode, XEXP (operands[1], 0)), 506090075Sobrien TRUE, FALSE, RTX_UNCHANGING_P(operands[1]), 506190075Sobrien MEM_IN_STRUCT_P(operands[1]), 506290075Sobrien MEM_SCALAR_P (operands[1])); 506390075Sobrien " 506490075Sobrien) 506590075Sobrien 506690075Sobrien;; Load multiple with write-back 506790075Sobrien 506890075Sobrien(define_insn "*ldmsi_postinc4" 506990075Sobrien [(match_parallel 0 "load_multiple_operation" 507090075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 507190075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 507290075Sobrien (const_int 16))) 507390075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 507490075Sobrien (mem:SI (match_dup 2))) 507590075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 507690075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 507790075Sobrien (set (match_operand:SI 5 "arm_hard_register_operand" "") 507890075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 8)))) 507990075Sobrien (set (match_operand:SI 6 "arm_hard_register_operand" "") 508090075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 12))))])] 508190075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 508290075Sobrien "ldm%?ia\\t%1!, {%3, %4, %5, %6}" 508390075Sobrien [(set_attr "type" "load") 508490075Sobrien (set_attr "predicable" "yes")] 508590075Sobrien) 508690075Sobrien 508790075Sobrien(define_insn "*ldmsi_postinc3" 508890075Sobrien [(match_parallel 0 "load_multiple_operation" 508990075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 509090075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 509190075Sobrien (const_int 12))) 509290075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 509390075Sobrien (mem:SI (match_dup 2))) 509490075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 509590075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 4)))) 509690075Sobrien (set (match_operand:SI 5 "arm_hard_register_operand" "") 509790075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 8))))])] 509890075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 509990075Sobrien "ldm%?ia\\t%1!, {%3, %4, %5}" 510090075Sobrien [(set_attr "type" "load") 510190075Sobrien (set_attr "predicable" "yes")] 510290075Sobrien) 510390075Sobrien 510490075Sobrien(define_insn "*ldmsi_postinc2" 510590075Sobrien [(match_parallel 0 "load_multiple_operation" 510690075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 510790075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 510890075Sobrien (const_int 8))) 510990075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 511090075Sobrien (mem:SI (match_dup 2))) 511190075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 511290075Sobrien (mem:SI (plus:SI (match_dup 2) (const_int 4))))])] 511390075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 511490075Sobrien "ldm%?ia\\t%1!, {%3, %4}" 511590075Sobrien [(set_attr "type" "load") 511690075Sobrien (set_attr "predicable" "yes")] 511790075Sobrien) 511890075Sobrien 511990075Sobrien;; Ordinary load multiple 512090075Sobrien 512190075Sobrien(define_insn "*ldmsi4" 512290075Sobrien [(match_parallel 0 "load_multiple_operation" 512390075Sobrien [(set (match_operand:SI 2 "arm_hard_register_operand" "") 512490075Sobrien (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 512590075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 512690075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 512790075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 512890075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 8)))) 512990075Sobrien (set (match_operand:SI 5 "arm_hard_register_operand" "") 513090075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] 513190075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 513290075Sobrien "ldm%?ia\\t%1, {%2, %3, %4, %5}" 513390075Sobrien [(set_attr "type" "load") 513490075Sobrien (set_attr "predicable" "yes")] 513590075Sobrien) 513690075Sobrien 513790075Sobrien(define_insn "*ldmsi3" 513890075Sobrien [(match_parallel 0 "load_multiple_operation" 513990075Sobrien [(set (match_operand:SI 2 "arm_hard_register_operand" "") 514090075Sobrien (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 514190075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 514290075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 4)))) 514390075Sobrien (set (match_operand:SI 4 "arm_hard_register_operand" "") 514490075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] 514590075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 514690075Sobrien "ldm%?ia\\t%1, {%2, %3, %4}" 514790075Sobrien [(set_attr "type" "load") 514890075Sobrien (set_attr "predicable" "yes")] 514990075Sobrien) 515090075Sobrien 515190075Sobrien(define_insn "*ldmsi2" 515290075Sobrien [(match_parallel 0 "load_multiple_operation" 515390075Sobrien [(set (match_operand:SI 2 "arm_hard_register_operand" "") 515490075Sobrien (mem:SI (match_operand:SI 1 "s_register_operand" "r"))) 515590075Sobrien (set (match_operand:SI 3 "arm_hard_register_operand" "") 515690075Sobrien (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] 515790075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 515890075Sobrien "ldm%?ia\\t%1, {%2, %3}" 515990075Sobrien [(set_attr "type" "load") 516090075Sobrien (set_attr "predicable" "yes")] 516190075Sobrien) 516290075Sobrien 516390075Sobrien(define_expand "store_multiple" 516490075Sobrien [(match_par_dup 3 [(set (match_operand:SI 0 "" "") 516590075Sobrien (match_operand:SI 1 "" "")) 516690075Sobrien (use (match_operand:SI 2 "" ""))])] 516790075Sobrien "TARGET_ARM" 516890075Sobrien " 5169132718Skan /* Support only fixed point registers. */ 517090075Sobrien if (GET_CODE (operands[2]) != CONST_INT 517190075Sobrien || INTVAL (operands[2]) > 14 517290075Sobrien || INTVAL (operands[2]) < 2 517390075Sobrien || GET_CODE (operands[1]) != REG 517490075Sobrien || GET_CODE (operands[0]) != MEM 517590075Sobrien || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1) 517690075Sobrien || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM) 517790075Sobrien FAIL; 517890075Sobrien 517990075Sobrien operands[3] 518090075Sobrien = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]), 518190075Sobrien force_reg (SImode, XEXP (operands[0], 0)), 518290075Sobrien TRUE, FALSE, RTX_UNCHANGING_P (operands[0]), 518390075Sobrien MEM_IN_STRUCT_P(operands[0]), 518490075Sobrien MEM_SCALAR_P (operands[0])); 518590075Sobrien " 518690075Sobrien) 518790075Sobrien 518890075Sobrien;; Store multiple with write-back 518990075Sobrien 519090075Sobrien(define_insn "*stmsi_postinc4" 519190075Sobrien [(match_parallel 0 "store_multiple_operation" 519290075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 519390075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 519490075Sobrien (const_int 16))) 519590075Sobrien (set (mem:SI (match_dup 2)) 519690075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 519790075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 519890075Sobrien (match_operand:SI 4 "arm_hard_register_operand" "")) 519990075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 520090075Sobrien (match_operand:SI 5 "arm_hard_register_operand" "")) 520190075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 12))) 520290075Sobrien (match_operand:SI 6 "arm_hard_register_operand" ""))])] 520390075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 5" 520490075Sobrien "stm%?ia\\t%1!, {%3, %4, %5, %6}" 520590075Sobrien [(set_attr "predicable" "yes") 520690075Sobrien (set_attr "type" "store4")] 520790075Sobrien) 520890075Sobrien 520990075Sobrien(define_insn "*stmsi_postinc3" 521090075Sobrien [(match_parallel 0 "store_multiple_operation" 521190075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 521290075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 521390075Sobrien (const_int 12))) 521490075Sobrien (set (mem:SI (match_dup 2)) 521590075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 521690075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 521790075Sobrien (match_operand:SI 4 "arm_hard_register_operand" "")) 521890075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 521990075Sobrien (match_operand:SI 5 "arm_hard_register_operand" ""))])] 522090075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 522190075Sobrien "stm%?ia\\t%1!, {%3, %4, %5}" 522290075Sobrien [(set_attr "predicable" "yes") 522390075Sobrien (set_attr "type" "store3")] 522490075Sobrien) 522590075Sobrien 522690075Sobrien(define_insn "*stmsi_postinc2" 522790075Sobrien [(match_parallel 0 "store_multiple_operation" 522890075Sobrien [(set (match_operand:SI 1 "s_register_operand" "=r") 522990075Sobrien (plus:SI (match_operand:SI 2 "s_register_operand" "1") 523090075Sobrien (const_int 8))) 523190075Sobrien (set (mem:SI (match_dup 2)) 523290075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 523390075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 523490075Sobrien (match_operand:SI 4 "arm_hard_register_operand" ""))])] 523590075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 523690075Sobrien "stm%?ia\\t%1!, {%3, %4}" 523790075Sobrien [(set_attr "predicable" "yes") 523890075Sobrien (set_attr "type" "store2")] 523990075Sobrien) 524090075Sobrien 524190075Sobrien;; Ordinary store multiple 524290075Sobrien 524390075Sobrien(define_insn "*stmsi4" 524490075Sobrien [(match_parallel 0 "store_multiple_operation" 524590075Sobrien [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 524690075Sobrien (match_operand:SI 2 "arm_hard_register_operand" "")) 524790075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 524890075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 524990075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 525090075Sobrien (match_operand:SI 4 "arm_hard_register_operand" "")) 525190075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) 525290075Sobrien (match_operand:SI 5 "arm_hard_register_operand" ""))])] 525390075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 4" 525490075Sobrien "stm%?ia\\t%1, {%2, %3, %4, %5}" 525590075Sobrien [(set_attr "predicable" "yes") 525690075Sobrien (set_attr "type" "store4")] 525790075Sobrien) 525890075Sobrien 525990075Sobrien(define_insn "*stmsi3" 526090075Sobrien [(match_parallel 0 "store_multiple_operation" 526190075Sobrien [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 526290075Sobrien (match_operand:SI 2 "arm_hard_register_operand" "")) 526390075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 526490075Sobrien (match_operand:SI 3 "arm_hard_register_operand" "")) 526590075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) 526690075Sobrien (match_operand:SI 4 "arm_hard_register_operand" ""))])] 526790075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 3" 526890075Sobrien "stm%?ia\\t%1, {%2, %3, %4}" 526990075Sobrien [(set_attr "predicable" "yes") 527090075Sobrien (set_attr "type" "store3")] 527190075Sobrien) 527290075Sobrien 527390075Sobrien(define_insn "*stmsi2" 527490075Sobrien [(match_parallel 0 "store_multiple_operation" 527590075Sobrien [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 527690075Sobrien (match_operand:SI 2 "arm_hard_register_operand" "")) 527790075Sobrien (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) 527890075Sobrien (match_operand:SI 3 "arm_hard_register_operand" ""))])] 527990075Sobrien "TARGET_ARM && XVECLEN (operands[0], 0) == 2" 528090075Sobrien "stm%?ia\\t%1, {%2, %3}" 528190075Sobrien [(set_attr "predicable" "yes") 528290075Sobrien (set_attr "type" "store2")] 528390075Sobrien) 528490075Sobrien 528590075Sobrien;; Move a block of memory if it is word aligned and MORE than 2 words long. 528690075Sobrien;; We could let this apply for blocks of less than this, but it clobbers so 528790075Sobrien;; many registers that there is then probably a better way. 528890075Sobrien 528990075Sobrien(define_expand "movstrqi" 529090075Sobrien [(match_operand:BLK 0 "general_operand" "") 529190075Sobrien (match_operand:BLK 1 "general_operand" "") 529290075Sobrien (match_operand:SI 2 "const_int_operand" "") 529390075Sobrien (match_operand:SI 3 "const_int_operand" "")] 529490075Sobrien "TARGET_EITHER" 529590075Sobrien " 529690075Sobrien if (TARGET_ARM) 529790075Sobrien { 529890075Sobrien if (arm_gen_movstrqi (operands)) 529990075Sobrien DONE; 530090075Sobrien FAIL; 530190075Sobrien } 530290075Sobrien else /* TARGET_THUMB */ 530390075Sobrien { 530490075Sobrien if ( INTVAL (operands[3]) != 4 530590075Sobrien || INTVAL (operands[2]) > 48) 530690075Sobrien FAIL; 530790075Sobrien 530890075Sobrien thumb_expand_movstrqi (operands); 530990075Sobrien DONE; 531090075Sobrien } 531190075Sobrien " 531290075Sobrien) 531390075Sobrien 531490075Sobrien;; Thumb block-move insns 531590075Sobrien 531690075Sobrien(define_insn "movmem12b" 531790075Sobrien [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 531890075Sobrien (mem:SI (match_operand:SI 3 "register_operand" "1"))) 531990075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 532090075Sobrien (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 532190075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 532290075Sobrien (mem:SI (plus:SI (match_dup 3) (const_int 8)))) 532390075Sobrien (set (match_operand:SI 0 "register_operand" "=l") 532490075Sobrien (plus:SI (match_dup 2) (const_int 12))) 532590075Sobrien (set (match_operand:SI 1 "register_operand" "=l") 532690075Sobrien (plus:SI (match_dup 3) (const_int 12))) 532790075Sobrien (clobber (match_scratch:SI 4 "=&l")) 532890075Sobrien (clobber (match_scratch:SI 5 "=&l")) 532990075Sobrien (clobber (match_scratch:SI 6 "=&l"))] 533090075Sobrien "TARGET_THUMB" 533190075Sobrien "* return thumb_output_move_mem_multiple (3, operands);" 533290075Sobrien [(set_attr "length" "4") 533390075Sobrien ; This isn't entirely accurate... It loads as well, but in terms of 533490075Sobrien ; scheduling the following insn it is better to consider it as a store 533590075Sobrien (set_attr "type" "store3")] 533690075Sobrien) 533790075Sobrien 533890075Sobrien(define_insn "movmem8b" 533990075Sobrien [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 534090075Sobrien (mem:SI (match_operand:SI 3 "register_operand" "1"))) 534190075Sobrien (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 534290075Sobrien (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 534390075Sobrien (set (match_operand:SI 0 "register_operand" "=l") 534490075Sobrien (plus:SI (match_dup 2) (const_int 8))) 534590075Sobrien (set (match_operand:SI 1 "register_operand" "=l") 534690075Sobrien (plus:SI (match_dup 3) (const_int 8))) 534790075Sobrien (clobber (match_scratch:SI 4 "=&l")) 534890075Sobrien (clobber (match_scratch:SI 5 "=&l"))] 534990075Sobrien "TARGET_THUMB" 535090075Sobrien "* return thumb_output_move_mem_multiple (2, operands);" 535190075Sobrien [(set_attr "length" "4") 535290075Sobrien ; This isn't entirely accurate... It loads as well, but in terms of 535390075Sobrien ; scheduling the following insn it is better to consider it as a store 535490075Sobrien (set_attr "type" "store2")] 535590075Sobrien) 535690075Sobrien 535790075Sobrien 535890075Sobrien 535990075Sobrien;; Compare & branch insns 5360132718Skan;; The range calculations are based as follows: 536190075Sobrien;; For forward branches, the address calculation returns the address of 536290075Sobrien;; the next instruction. This is 2 beyond the branch instruction. 536390075Sobrien;; For backward branches, the address calculation returns the address of 536490075Sobrien;; the first instruction in this pattern (cmp). This is 2 before the branch 536590075Sobrien;; instruction for the shortest sequence, and 4 before the branch instruction 536690075Sobrien;; if we have to jump around an unconditional branch. 536790075Sobrien;; To the basic branch range the PC offset must be added (this is +4). 536890075Sobrien;; So for forward branches we have 536990075Sobrien;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4). 537090075Sobrien;; And for backward branches we have 537190075Sobrien;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4). 537290075Sobrien;; 537390075Sobrien;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048). 537490075Sobrien;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256). 537590075Sobrien 5376132718Skan(define_expand "cbranchsi4" 5377132718Skan [(set (pc) (if_then_else 5378132718Skan (match_operator 0 "arm_comparison_operator" 5379132718Skan [(match_operand:SI 1 "s_register_operand" "") 5380132718Skan (match_operand:SI 2 "nonmemory_operand" "")]) 5381132718Skan (label_ref (match_operand 3 "" "")) 5382132718Skan (pc)))] 538390075Sobrien "TARGET_THUMB" 5384132718Skan " 5385132718Skan if (thumb_cmpneg_operand (operands[2], SImode)) 5386132718Skan { 5387132718Skan emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2], 5388132718Skan operands[3], operands[0])); 5389132718Skan DONE; 5390132718Skan } 5391132718Skan if (!thumb_cmp_operand (operands[2], SImode)) 5392132718Skan operands[2] = force_reg (SImode, operands[2]); 5393132718Skan ") 5394132718Skan 5395132718Skan(define_insn "*cbranchsi4_insn" 5396132718Skan [(set (pc) (if_then_else 5397132718Skan (match_operator 0 "arm_comparison_operator" 5398132718Skan [(match_operand:SI 1 "s_register_operand" "l,*h") 5399132718Skan (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")]) 5400132718Skan (label_ref (match_operand 3 "" "")) 5401132718Skan (pc)))] 5402132718Skan "TARGET_THUMB" 540390075Sobrien "* 540490075Sobrien output_asm_insn (\"cmp\\t%1, %2\", operands); 5405132718Skan 540690075Sobrien switch (get_attr_length (insn)) 540790075Sobrien { 540890075Sobrien case 4: return \"b%d0\\t%l3\"; 540990075Sobrien case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 541090075Sobrien default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 541190075Sobrien } 541290075Sobrien " 541390075Sobrien [(set (attr "far_jump") 541490075Sobrien (if_then_else 541590075Sobrien (eq_attr "length" "8") 541690075Sobrien (const_string "yes") 541790075Sobrien (const_string "no"))) 541890075Sobrien (set (attr "length") 541990075Sobrien (if_then_else 542090075Sobrien (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 542190075Sobrien (le (minus (match_dup 3) (pc)) (const_int 256))) 542290075Sobrien (const_int 4) 542390075Sobrien (if_then_else 542490075Sobrien (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 542590075Sobrien (le (minus (match_dup 3) (pc)) (const_int 2048))) 542690075Sobrien (const_int 6) 542790075Sobrien (const_int 8))))] 542890075Sobrien) 542990075Sobrien 5430132718Skan(define_insn "cbranchsi4_scratch" 5431132718Skan [(set (pc) (if_then_else 5432132718Skan (match_operator 4 "arm_comparison_operator" 5433132718Skan [(match_operand:SI 1 "s_register_operand" "l,0") 5434132718Skan (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")]) 5435132718Skan (label_ref (match_operand 3 "" "")) 5436132718Skan (pc))) 5437132718Skan (clobber (match_scratch:SI 0 "=l,l"))] 5438132718Skan "TARGET_THUMB" 5439132718Skan "* 5440132718Skan output_asm_insn (\"add\\t%0, %1, #%n2\", operands); 5441132718Skan 5442132718Skan switch (get_attr_length (insn)) 5443132718Skan { 5444132718Skan case 4: return \"b%d4\\t%l3\"; 5445132718Skan case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5446132718Skan default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5447132718Skan } 5448132718Skan " 5449132718Skan [(set (attr "far_jump") 5450132718Skan (if_then_else 5451132718Skan (eq_attr "length" "8") 5452132718Skan (const_string "yes") 5453132718Skan (const_string "no"))) 5454132718Skan (set (attr "length") 5455132718Skan (if_then_else 5456132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5457132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 5458132718Skan (const_int 4) 5459132718Skan (if_then_else 5460132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5461132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 5462132718Skan (const_int 6) 5463132718Skan (const_int 8))))] 5464132718Skan) 5465132718Skan(define_insn "*movsi_cbranchsi4" 5466132718Skan [(set (pc) 5467132718Skan (if_then_else 5468132718Skan (match_operator 3 "arm_comparison_operator" 5469132718Skan [(match_operand:SI 1 "s_register_operand" "0,l,l,l") 5470132718Skan (const_int 0)]) 5471132718Skan (label_ref (match_operand 2 "" "")) 5472132718Skan (pc))) 5473132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m") 5474132718Skan (match_dup 1))] 5475132718Skan "TARGET_THUMB" 5476132718Skan "*{ 5477132718Skan if (which_alternative == 0) 5478132718Skan output_asm_insn (\"cmp\t%0, #0\", operands); 5479132718Skan else if (which_alternative == 1) 5480132718Skan output_asm_insn (\"sub\t%0, %1, #0\", operands); 5481132718Skan else 5482132718Skan { 5483132718Skan output_asm_insn (\"cmp\t%1, #0\", operands); 5484132718Skan if (which_alternative == 2) 5485132718Skan output_asm_insn (\"mov\t%0, %1\", operands); 5486132718Skan else 5487132718Skan output_asm_insn (\"str\t%1, %0\", operands); 5488132718Skan } 5489132718Skan switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0)) 5490132718Skan { 5491132718Skan case 4: return \"b%d3\\t%l2\"; 5492132718Skan case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\"; 5493132718Skan default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\"; 5494132718Skan } 5495132718Skan }" 5496132718Skan [(set (attr "far_jump") 5497132718Skan (if_then_else 5498132718Skan (ior (and (gt (symbol_ref ("which_alternative")) 5499132718Skan (const_int 1)) 5500132718Skan (eq_attr "length" "8")) 5501132718Skan (eq_attr "length" "10")) 5502132718Skan (const_string "yes") 5503132718Skan (const_string "no"))) 5504132718Skan (set (attr "length") 5505132718Skan (if_then_else 5506132718Skan (le (symbol_ref ("which_alternative")) 5507132718Skan (const_int 1)) 5508132718Skan (if_then_else 5509132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 5510132718Skan (le (minus (match_dup 2) (pc)) (const_int 256))) 5511132718Skan (const_int 4) 5512132718Skan (if_then_else 5513132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) 5514132718Skan (le (minus (match_dup 2) (pc)) (const_int 2048))) 5515132718Skan (const_int 6) 5516132718Skan (const_int 8))) 5517132718Skan (if_then_else 5518132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -248)) 5519132718Skan (le (minus (match_dup 2) (pc)) (const_int 256))) 5520132718Skan (const_int 6) 5521132718Skan (if_then_else 5522132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -2038)) 5523132718Skan (le (minus (match_dup 2) (pc)) (const_int 2048))) 5524132718Skan (const_int 8) 5525132718Skan (const_int 10)))))] 5526132718Skan) 5527132718Skan 552890075Sobrien(define_insn "*negated_cbranchsi4" 552990075Sobrien [(set (pc) 553090075Sobrien (if_then_else 5531132718Skan (match_operator 0 "arm_comparison_operator" 5532132718Skan [(match_operand:SI 1 "s_register_operand" "l") 5533132718Skan (neg:SI (match_operand:SI 2 "s_register_operand" "l"))]) 5534132718Skan (label_ref (match_operand 3 "" "")) 553590075Sobrien (pc)))] 553690075Sobrien "TARGET_THUMB" 553790075Sobrien "* 553890075Sobrien output_asm_insn (\"cmn\\t%1, %2\", operands); 553990075Sobrien switch (get_attr_length (insn)) 554090075Sobrien { 554190075Sobrien case 4: return \"b%d0\\t%l3\"; 554290075Sobrien case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 554390075Sobrien default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 554490075Sobrien } 554590075Sobrien " 554690075Sobrien [(set (attr "far_jump") 554790075Sobrien (if_then_else 554890075Sobrien (eq_attr "length" "8") 554990075Sobrien (const_string "yes") 555090075Sobrien (const_string "no"))) 555190075Sobrien (set (attr "length") 555290075Sobrien (if_then_else 555390075Sobrien (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 555490075Sobrien (le (minus (match_dup 3) (pc)) (const_int 256))) 555590075Sobrien (const_int 4) 555690075Sobrien (if_then_else 555790075Sobrien (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 555890075Sobrien (le (minus (match_dup 3) (pc)) (const_int 2048))) 555990075Sobrien (const_int 6) 556090075Sobrien (const_int 8))))] 556190075Sobrien) 556290075Sobrien 5563132718Skan(define_insn "*tbit_cbranch" 5564132718Skan [(set (pc) 5565132718Skan (if_then_else 5566132718Skan (match_operator 0 "equality_operator" 5567132718Skan [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l") 5568132718Skan (const_int 1) 5569132718Skan (match_operand:SI 2 "const_int_operand" "i")) 5570132718Skan (const_int 0)]) 5571132718Skan (label_ref (match_operand 3 "" "")) 5572132718Skan (pc))) 5573132718Skan (clobber (match_scratch:SI 4 "=l"))] 5574132718Skan "TARGET_THUMB" 5575132718Skan "* 5576132718Skan { 5577132718Skan rtx op[3]; 5578132718Skan op[0] = operands[4]; 5579132718Skan op[1] = operands[1]; 5580132718Skan op[2] = GEN_INT (32 - 1 - INTVAL (operands[2])); 558190075Sobrien 5582132718Skan output_asm_insn (\"lsl\\t%0, %1, %2\", op); 5583132718Skan switch (get_attr_length (insn)) 5584132718Skan { 5585132718Skan case 4: return \"b%d0\\t%l3\"; 5586132718Skan case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5587132718Skan default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5588132718Skan } 5589132718Skan }" 5590132718Skan [(set (attr "far_jump") 5591132718Skan (if_then_else 5592132718Skan (eq_attr "length" "8") 5593132718Skan (const_string "yes") 5594132718Skan (const_string "no"))) 5595132718Skan (set (attr "length") 5596132718Skan (if_then_else 5597132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5598132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 5599132718Skan (const_int 4) 5600132718Skan (if_then_else 5601132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5602132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 5603132718Skan (const_int 6) 5604132718Skan (const_int 8))))] 5605132718Skan) 5606132718Skan 5607132718Skan(define_insn "*tstsi3_cbranch" 5608132718Skan [(set (pc) 5609132718Skan (if_then_else 5610132718Skan (match_operator 3 "equality_operator" 5611132718Skan [(and:SI (match_operand:SI 0 "s_register_operand" "%l") 5612132718Skan (match_operand:SI 1 "s_register_operand" "l")) 5613132718Skan (const_int 0)]) 5614132718Skan (label_ref (match_operand 2 "" "")) 5615132718Skan (pc)))] 5616132718Skan "TARGET_THUMB" 5617132718Skan "* 5618132718Skan { 5619132718Skan output_asm_insn (\"tst\\t%0, %1\", operands); 5620132718Skan switch (get_attr_length (insn)) 5621132718Skan { 5622132718Skan case 4: return \"b%d3\\t%l2\"; 5623132718Skan case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\"; 5624132718Skan default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\"; 5625132718Skan } 5626132718Skan }" 5627132718Skan [(set (attr "far_jump") 5628132718Skan (if_then_else 5629132718Skan (eq_attr "length" "8") 5630132718Skan (const_string "yes") 5631132718Skan (const_string "no"))) 5632132718Skan (set (attr "length") 5633132718Skan (if_then_else 5634132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 5635132718Skan (le (minus (match_dup 2) (pc)) (const_int 256))) 5636132718Skan (const_int 4) 5637132718Skan (if_then_else 5638132718Skan (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) 5639132718Skan (le (minus (match_dup 2) (pc)) (const_int 2048))) 5640132718Skan (const_int 6) 5641132718Skan (const_int 8))))] 5642132718Skan) 5643132718Skan 5644132718Skan(define_insn "*andsi3_cbranch" 5645132718Skan [(set (pc) 5646132718Skan (if_then_else 5647132718Skan (match_operator 5 "equality_operator" 5648132718Skan [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 5649132718Skan (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 5650132718Skan (const_int 0)]) 5651132718Skan (label_ref (match_operand 4 "" "")) 5652132718Skan (pc))) 5653132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 5654132718Skan (and:SI (match_dup 2) (match_dup 3))) 5655132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 5656132718Skan "TARGET_THUMB" 5657132718Skan "* 5658132718Skan { 5659132718Skan if (which_alternative == 0) 5660132718Skan output_asm_insn (\"and\\t%0, %3\", operands); 5661132718Skan else if (which_alternative == 1) 5662132718Skan { 5663132718Skan output_asm_insn (\"and\\t%1, %3\", operands); 5664132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 5665132718Skan } 5666132718Skan else 5667132718Skan { 5668132718Skan output_asm_insn (\"and\\t%1, %3\", operands); 5669132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 5670132718Skan } 5671132718Skan 5672132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5673132718Skan { 5674132718Skan case 4: return \"b%d5\\t%l4\"; 5675132718Skan case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5676132718Skan default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5677132718Skan } 5678132718Skan }" 5679132718Skan [(set (attr "far_jump") 5680132718Skan (if_then_else 5681132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 5682132718Skan (const_int 0)) 5683132718Skan (eq_attr "length" "8")) 5684132718Skan (eq_attr "length" "10")) 5685132718Skan (const_string "yes") 5686132718Skan (const_string "no"))) 5687132718Skan (set (attr "length") 5688132718Skan (if_then_else 5689132718Skan (eq (symbol_ref ("which_alternative")) 5690132718Skan (const_int 0)) 5691132718Skan (if_then_else 5692132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 5693132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 5694132718Skan (const_int 4) 5695132718Skan (if_then_else 5696132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 5697132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 5698132718Skan (const_int 6) 5699132718Skan (const_int 8))) 5700132718Skan (if_then_else 5701132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 5702132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 5703132718Skan (const_int 6) 5704132718Skan (if_then_else 5705132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 5706132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 5707132718Skan (const_int 8) 5708132718Skan (const_int 10)))))] 5709132718Skan) 5710132718Skan 5711132718Skan(define_insn "*orrsi3_cbranch_scratch" 5712132718Skan [(set (pc) 5713132718Skan (if_then_else 5714132718Skan (match_operator 4 "equality_operator" 5715132718Skan [(ior:SI (match_operand:SI 1 "s_register_operand" "%0") 5716132718Skan (match_operand:SI 2 "s_register_operand" "l")) 5717132718Skan (const_int 0)]) 5718132718Skan (label_ref (match_operand 3 "" "")) 5719132718Skan (pc))) 5720132718Skan (clobber (match_scratch:SI 0 "=l"))] 5721132718Skan "TARGET_THUMB" 5722132718Skan "* 5723132718Skan { 5724132718Skan output_asm_insn (\"orr\\t%0, %2\", operands); 5725132718Skan switch (get_attr_length (insn)) 5726132718Skan { 5727132718Skan case 4: return \"b%d4\\t%l3\"; 5728132718Skan case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5729132718Skan default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5730132718Skan } 5731132718Skan }" 5732132718Skan [(set (attr "far_jump") 5733132718Skan (if_then_else 5734132718Skan (eq_attr "length" "8") 5735132718Skan (const_string "yes") 5736132718Skan (const_string "no"))) 5737132718Skan (set (attr "length") 5738132718Skan (if_then_else 5739132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5740132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 5741132718Skan (const_int 4) 5742132718Skan (if_then_else 5743132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5744132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 5745132718Skan (const_int 6) 5746132718Skan (const_int 8))))] 5747132718Skan) 5748132718Skan 5749132718Skan(define_insn "*orrsi3_cbranch" 5750132718Skan [(set (pc) 5751132718Skan (if_then_else 5752132718Skan (match_operator 5 "equality_operator" 5753132718Skan [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 5754132718Skan (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 5755132718Skan (const_int 0)]) 5756132718Skan (label_ref (match_operand 4 "" "")) 5757132718Skan (pc))) 5758132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 5759132718Skan (ior:SI (match_dup 2) (match_dup 3))) 5760132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 5761132718Skan "TARGET_THUMB" 5762132718Skan "* 5763132718Skan { 5764132718Skan if (which_alternative == 0) 5765132718Skan output_asm_insn (\"orr\\t%0, %3\", operands); 5766132718Skan else if (which_alternative == 1) 5767132718Skan { 5768132718Skan output_asm_insn (\"orr\\t%1, %3\", operands); 5769132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 5770132718Skan } 5771132718Skan else 5772132718Skan { 5773132718Skan output_asm_insn (\"orr\\t%1, %3\", operands); 5774132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 5775132718Skan } 5776132718Skan 5777132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5778132718Skan { 5779132718Skan case 4: return \"b%d5\\t%l4\"; 5780132718Skan case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5781132718Skan default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5782132718Skan } 5783132718Skan }" 5784132718Skan [(set (attr "far_jump") 5785132718Skan (if_then_else 5786132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 5787132718Skan (const_int 0)) 5788132718Skan (eq_attr "length" "8")) 5789132718Skan (eq_attr "length" "10")) 5790132718Skan (const_string "yes") 5791132718Skan (const_string "no"))) 5792132718Skan (set (attr "length") 5793132718Skan (if_then_else 5794132718Skan (eq (symbol_ref ("which_alternative")) 5795132718Skan (const_int 0)) 5796132718Skan (if_then_else 5797132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 5798132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 5799132718Skan (const_int 4) 5800132718Skan (if_then_else 5801132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 5802132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 5803132718Skan (const_int 6) 5804132718Skan (const_int 8))) 5805132718Skan (if_then_else 5806132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 5807132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 5808132718Skan (const_int 6) 5809132718Skan (if_then_else 5810132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 5811132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 5812132718Skan (const_int 8) 5813132718Skan (const_int 10)))))] 5814132718Skan) 5815132718Skan 5816132718Skan(define_insn "*xorsi3_cbranch_scratch" 5817132718Skan [(set (pc) 5818132718Skan (if_then_else 5819132718Skan (match_operator 4 "equality_operator" 5820132718Skan [(xor:SI (match_operand:SI 1 "s_register_operand" "%0") 5821132718Skan (match_operand:SI 2 "s_register_operand" "l")) 5822132718Skan (const_int 0)]) 5823132718Skan (label_ref (match_operand 3 "" "")) 5824132718Skan (pc))) 5825132718Skan (clobber (match_scratch:SI 0 "=l"))] 5826132718Skan "TARGET_THUMB" 5827132718Skan "* 5828132718Skan { 5829132718Skan output_asm_insn (\"eor\\t%0, %2\", operands); 5830132718Skan switch (get_attr_length (insn)) 5831132718Skan { 5832132718Skan case 4: return \"b%d4\\t%l3\"; 5833132718Skan case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5834132718Skan default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5835132718Skan } 5836132718Skan }" 5837132718Skan [(set (attr "far_jump") 5838132718Skan (if_then_else 5839132718Skan (eq_attr "length" "8") 5840132718Skan (const_string "yes") 5841132718Skan (const_string "no"))) 5842132718Skan (set (attr "length") 5843132718Skan (if_then_else 5844132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5845132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 5846132718Skan (const_int 4) 5847132718Skan (if_then_else 5848132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5849132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 5850132718Skan (const_int 6) 5851132718Skan (const_int 8))))] 5852132718Skan) 5853132718Skan 5854132718Skan(define_insn "*xorsi3_cbranch" 5855132718Skan [(set (pc) 5856132718Skan (if_then_else 5857132718Skan (match_operator 5 "equality_operator" 5858132718Skan [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1") 5859132718Skan (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 5860132718Skan (const_int 0)]) 5861132718Skan (label_ref (match_operand 4 "" "")) 5862132718Skan (pc))) 5863132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 5864132718Skan (xor:SI (match_dup 2) (match_dup 3))) 5865132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 5866132718Skan "TARGET_THUMB" 5867132718Skan "* 5868132718Skan { 5869132718Skan if (which_alternative == 0) 5870132718Skan output_asm_insn (\"eor\\t%0, %3\", operands); 5871132718Skan else if (which_alternative == 1) 5872132718Skan { 5873132718Skan output_asm_insn (\"eor\\t%1, %3\", operands); 5874132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 5875132718Skan } 5876132718Skan else 5877132718Skan { 5878132718Skan output_asm_insn (\"eor\\t%1, %3\", operands); 5879132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 5880132718Skan } 5881132718Skan 5882132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5883132718Skan { 5884132718Skan case 4: return \"b%d5\\t%l4\"; 5885132718Skan case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5886132718Skan default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5887132718Skan } 5888132718Skan }" 5889132718Skan [(set (attr "far_jump") 5890132718Skan (if_then_else 5891132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 5892132718Skan (const_int 0)) 5893132718Skan (eq_attr "length" "8")) 5894132718Skan (eq_attr "length" "10")) 5895132718Skan (const_string "yes") 5896132718Skan (const_string "no"))) 5897132718Skan (set (attr "length") 5898132718Skan (if_then_else 5899132718Skan (eq (symbol_ref ("which_alternative")) 5900132718Skan (const_int 0)) 5901132718Skan (if_then_else 5902132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 5903132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 5904132718Skan (const_int 4) 5905132718Skan (if_then_else 5906132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 5907132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 5908132718Skan (const_int 6) 5909132718Skan (const_int 8))) 5910132718Skan (if_then_else 5911132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 5912132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 5913132718Skan (const_int 6) 5914132718Skan (if_then_else 5915132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 5916132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 5917132718Skan (const_int 8) 5918132718Skan (const_int 10)))))] 5919132718Skan) 5920132718Skan 5921132718Skan(define_insn "*bicsi3_cbranch_scratch" 5922132718Skan [(set (pc) 5923132718Skan (if_then_else 5924132718Skan (match_operator 4 "equality_operator" 5925132718Skan [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l")) 5926132718Skan (match_operand:SI 1 "s_register_operand" "0")) 5927132718Skan (const_int 0)]) 5928132718Skan (label_ref (match_operand 3 "" "")) 5929132718Skan (pc))) 5930132718Skan (clobber (match_scratch:SI 0 "=l"))] 5931132718Skan "TARGET_THUMB" 5932132718Skan "* 5933132718Skan { 5934132718Skan output_asm_insn (\"bic\\t%0, %2\", operands); 5935132718Skan switch (get_attr_length (insn)) 5936132718Skan { 5937132718Skan case 4: return \"b%d4\\t%l3\"; 5938132718Skan case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 5939132718Skan default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 5940132718Skan } 5941132718Skan }" 5942132718Skan [(set (attr "far_jump") 5943132718Skan (if_then_else 5944132718Skan (eq_attr "length" "8") 5945132718Skan (const_string "yes") 5946132718Skan (const_string "no"))) 5947132718Skan (set (attr "length") 5948132718Skan (if_then_else 5949132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 5950132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 5951132718Skan (const_int 4) 5952132718Skan (if_then_else 5953132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 5954132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 5955132718Skan (const_int 6) 5956132718Skan (const_int 8))))] 5957132718Skan) 5958132718Skan 5959132718Skan(define_insn "*bicsi3_cbranch" 5960132718Skan [(set (pc) 5961132718Skan (if_then_else 5962132718Skan (match_operator 5 "equality_operator" 5963146895Skan [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 5964146895Skan (match_operand:SI 2 "s_register_operand" "0,1,1,1")) 5965132718Skan (const_int 0)]) 5966132718Skan (label_ref (match_operand 4 "" "")) 5967132718Skan (pc))) 5968146895Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 5969132718Skan (and:SI (not:SI (match_dup 3)) (match_dup 2))) 5970146895Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 5971132718Skan "TARGET_THUMB" 5972132718Skan "* 5973132718Skan { 5974132718Skan if (which_alternative == 0) 5975132718Skan output_asm_insn (\"bic\\t%0, %3\", operands); 5976146895Skan else if (which_alternative == 1) 5977132718Skan { 5978132718Skan output_asm_insn (\"bic\\t%1, %3\", operands); 5979146895Skan output_asm_insn (\"mov\\t%0, %1\", operands); 5980146895Skan } 5981132718Skan else 5982132718Skan { 5983132718Skan output_asm_insn (\"bic\\t%1, %3\", operands); 5984132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 5985132718Skan } 5986132718Skan 5987132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 5988132718Skan { 5989132718Skan case 4: return \"b%d5\\t%l4\"; 5990132718Skan case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 5991132718Skan default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 5992132718Skan } 5993132718Skan }" 5994132718Skan [(set (attr "far_jump") 5995132718Skan (if_then_else 5996132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 5997132718Skan (const_int 0)) 5998132718Skan (eq_attr "length" "8")) 5999132718Skan (eq_attr "length" "10")) 6000132718Skan (const_string "yes") 6001132718Skan (const_string "no"))) 6002132718Skan (set (attr "length") 6003132718Skan (if_then_else 6004132718Skan (eq (symbol_ref ("which_alternative")) 6005132718Skan (const_int 0)) 6006132718Skan (if_then_else 6007132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6008132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6009132718Skan (const_int 4) 6010132718Skan (if_then_else 6011132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6012132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6013132718Skan (const_int 6) 6014132718Skan (const_int 8))) 6015132718Skan (if_then_else 6016132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6017132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6018132718Skan (const_int 6) 6019132718Skan (if_then_else 6020132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6021132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6022132718Skan (const_int 8) 6023132718Skan (const_int 10)))))] 6024132718Skan) 6025132718Skan 6026132718Skan(define_insn "*cbranchne_decr1" 6027132718Skan [(set (pc) 6028132718Skan (if_then_else (match_operator 3 "equality_operator" 6029132718Skan [(match_operand:SI 2 "s_register_operand" "l,l,1,l") 6030132718Skan (const_int 0)]) 6031132718Skan (label_ref (match_operand 4 "" "")) 6032132718Skan (pc))) 6033132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6034132718Skan (plus:SI (match_dup 2) (const_int -1))) 6035132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6036132718Skan "TARGET_THUMB" 6037132718Skan "* 6038132718Skan { 6039132718Skan rtx cond[2]; 6040132718Skan cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE 6041132718Skan ? GEU : LTU), 6042132718Skan VOIDmode, operands[2], const1_rtx); 6043132718Skan cond[1] = operands[4]; 6044132718Skan 6045132718Skan if (which_alternative == 0) 6046132718Skan output_asm_insn (\"sub\\t%0, %2, #1\", operands); 6047132718Skan else if (which_alternative == 1) 6048132718Skan { 6049132718Skan /* We must provide an alternative for a hi reg because reload 6050132718Skan cannot handle output reloads on a jump instruction, but we 6051132718Skan can't subtract into that. Fortunately a mov from lo to hi 6052132718Skan does not clobber the condition codes. */ 6053132718Skan output_asm_insn (\"sub\\t%1, %2, #1\", operands); 6054132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6055132718Skan } 6056132718Skan else 6057132718Skan { 6058132718Skan /* Similarly, but the target is memory. */ 6059132718Skan output_asm_insn (\"sub\\t%1, %2, #1\", operands); 6060132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6061132718Skan } 6062132718Skan 6063132718Skan switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 6064132718Skan { 6065132718Skan case 4: 6066132718Skan output_asm_insn (\"b%d0\\t%l1\", cond); 6067132718Skan return \"\"; 6068132718Skan case 6: 6069132718Skan output_asm_insn (\"b%D0\\t.LCB%=\", cond); 6070132718Skan return \"b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6071132718Skan default: 6072132718Skan output_asm_insn (\"b%D0\\t.LCB%=\", cond); 6073132718Skan return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6074132718Skan } 6075132718Skan } 6076132718Skan " 6077132718Skan [(set (attr "far_jump") 6078132718Skan (if_then_else 6079132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 6080132718Skan (const_int 0)) 6081132718Skan (eq_attr "length" "8")) 6082132718Skan (eq_attr "length" "10")) 6083132718Skan (const_string "yes") 6084132718Skan (const_string "no"))) 6085132718Skan (set_attr_alternative "length" 6086132718Skan [ 6087132718Skan ;; Alternative 0 6088132718Skan (if_then_else 6089132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6090132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6091132718Skan (const_int 4) 6092132718Skan (if_then_else 6093132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6094132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6095132718Skan (const_int 6) 6096132718Skan (const_int 8))) 6097132718Skan ;; Alternative 1 6098132718Skan (if_then_else 6099132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6100132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6101132718Skan (const_int 6) 6102132718Skan (if_then_else 6103132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6104132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6105132718Skan (const_int 8) 6106132718Skan (const_int 10))) 6107132718Skan ;; Alternative 2 6108132718Skan (if_then_else 6109132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6110132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6111132718Skan (const_int 6) 6112132718Skan (if_then_else 6113132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6114132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6115132718Skan (const_int 8) 6116132718Skan (const_int 10))) 6117132718Skan ;; Alternative 3 6118132718Skan (if_then_else 6119132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 6120132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6121132718Skan (const_int 6) 6122132718Skan (if_then_else 6123132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 6124132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6125132718Skan (const_int 8) 6126132718Skan (const_int 10)))])] 6127132718Skan) 6128132718Skan 6129132718Skan(define_insn "*addsi3_cbranch" 6130132718Skan [(set (pc) 6131132718Skan (if_then_else 6132132718Skan (match_operator 4 "comparison_operator" 6133132718Skan [(plus:SI 6134132718Skan (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1") 6135132718Skan (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ")) 6136132718Skan (const_int 0)]) 6137132718Skan (label_ref (match_operand 5 "" "")) 6138132718Skan (pc))) 6139132718Skan (set 6140132718Skan (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m") 6141132718Skan (plus:SI (match_dup 2) (match_dup 3))) 6142132718Skan (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))] 6143132718Skan "TARGET_THUMB 6144132718Skan && (GET_CODE (operands[4]) == EQ 6145132718Skan || GET_CODE (operands[4]) == NE 6146132718Skan || GET_CODE (operands[4]) == GE 6147132718Skan || GET_CODE (operands[4]) == LT)" 6148132718Skan "* 6149132718Skan { 6150132718Skan rtx cond[3]; 6151132718Skan 6152132718Skan 6153132718Skan cond[0] = (which_alternative < 3) ? operands[0] : operands[1]; 6154132718Skan cond[1] = operands[2]; 6155132718Skan cond[2] = operands[3]; 6156132718Skan 6157132718Skan if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0) 6158132718Skan output_asm_insn (\"sub\\t%0, %1, #%n2\", cond); 6159132718Skan else 6160132718Skan output_asm_insn (\"add\\t%0, %1, %2\", cond); 6161132718Skan 6162132718Skan if (which_alternative >= 3 6163132718Skan && which_alternative < 4) 6164132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6165132718Skan else if (which_alternative >= 4) 6166132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6167132718Skan 6168132718Skan switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0)) 6169132718Skan { 6170132718Skan case 4: 6171132718Skan return \"b%d4\\t%l5\"; 6172132718Skan case 6: 6173132718Skan return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 6174132718Skan default: 6175132718Skan return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 6176132718Skan } 6177132718Skan } 6178132718Skan " 6179132718Skan [(set (attr "far_jump") 6180132718Skan (if_then_else 6181132718Skan (ior (and (lt (symbol_ref ("which_alternative")) 6182132718Skan (const_int 3)) 6183132718Skan (eq_attr "length" "8")) 6184132718Skan (eq_attr "length" "10")) 6185132718Skan (const_string "yes") 6186132718Skan (const_string "no"))) 6187132718Skan (set (attr "length") 6188132718Skan (if_then_else 6189132718Skan (lt (symbol_ref ("which_alternative")) 6190132718Skan (const_int 3)) 6191132718Skan (if_then_else 6192132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 6193132718Skan (le (minus (match_dup 5) (pc)) (const_int 256))) 6194132718Skan (const_int 4) 6195132718Skan (if_then_else 6196132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 6197132718Skan (le (minus (match_dup 5) (pc)) (const_int 2048))) 6198132718Skan (const_int 6) 6199132718Skan (const_int 8))) 6200132718Skan (if_then_else 6201132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 6202132718Skan (le (minus (match_dup 5) (pc)) (const_int 256))) 6203132718Skan (const_int 6) 6204132718Skan (if_then_else 6205132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 6206132718Skan (le (minus (match_dup 5) (pc)) (const_int 2048))) 6207132718Skan (const_int 8) 6208132718Skan (const_int 10)))))] 6209132718Skan) 6210132718Skan 6211132718Skan(define_insn "*addsi3_cbranch_scratch" 6212132718Skan [(set (pc) 6213132718Skan (if_then_else 6214132718Skan (match_operator 3 "comparison_operator" 6215132718Skan [(plus:SI 6216132718Skan (match_operand:SI 1 "s_register_operand" "%l,l,l,0") 6217132718Skan (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L")) 6218132718Skan (const_int 0)]) 6219132718Skan (label_ref (match_operand 4 "" "")) 6220132718Skan (pc))) 6221132718Skan (clobber (match_scratch:SI 0 "=X,X,l,l"))] 6222132718Skan "TARGET_THUMB 6223132718Skan && (GET_CODE (operands[3]) == EQ 6224132718Skan || GET_CODE (operands[3]) == NE 6225132718Skan || GET_CODE (operands[3]) == GE 6226132718Skan || GET_CODE (operands[3]) == LT)" 6227132718Skan "* 6228132718Skan { 6229132718Skan switch (which_alternative) 6230132718Skan { 6231132718Skan case 0: 6232132718Skan output_asm_insn (\"cmp\t%1, #%n2\", operands); 6233132718Skan break; 6234132718Skan case 1: 6235132718Skan output_asm_insn (\"cmn\t%1, %2\", operands); 6236132718Skan break; 6237132718Skan case 3: 6238132718Skan output_asm_insn (\"add\t%0, %1, %2\", operands); 6239146895Skan break; 6240132718Skan case 4: 6241132718Skan output_asm_insn (\"add\t%0, %0, %2\", operands); 6242146895Skan break; 6243132718Skan } 6244132718Skan 6245132718Skan switch (get_attr_length (insn)) 6246132718Skan { 6247132718Skan case 4: 6248132718Skan return \"b%d3\\t%l4\"; 6249132718Skan case 6: 6250132718Skan return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 6251132718Skan default: 6252132718Skan return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 6253132718Skan } 6254132718Skan } 6255132718Skan " 6256132718Skan [(set (attr "far_jump") 6257132718Skan (if_then_else 6258132718Skan (eq_attr "length" "8") 6259132718Skan (const_string "yes") 6260132718Skan (const_string "no"))) 6261132718Skan (set (attr "length") 6262132718Skan (if_then_else 6263132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 6264132718Skan (le (minus (match_dup 4) (pc)) (const_int 256))) 6265132718Skan (const_int 4) 6266132718Skan (if_then_else 6267132718Skan (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 6268132718Skan (le (minus (match_dup 4) (pc)) (const_int 2048))) 6269132718Skan (const_int 6) 6270132718Skan (const_int 8))))] 6271132718Skan) 6272132718Skan 6273132718Skan(define_insn "*subsi3_cbranch" 6274132718Skan [(set (pc) 6275132718Skan (if_then_else 6276132718Skan (match_operator 4 "comparison_operator" 6277132718Skan [(minus:SI 6278132718Skan (match_operand:SI 2 "s_register_operand" "l,l,1,l") 6279132718Skan (match_operand:SI 3 "s_register_operand" "l,l,l,l")) 6280132718Skan (const_int 0)]) 6281132718Skan (label_ref (match_operand 5 "" "")) 6282132718Skan (pc))) 6283132718Skan (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 6284132718Skan (minus:SI (match_dup 2) (match_dup 3))) 6285132718Skan (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 6286132718Skan "TARGET_THUMB 6287132718Skan && (GET_CODE (operands[4]) == EQ 6288132718Skan || GET_CODE (operands[4]) == NE 6289132718Skan || GET_CODE (operands[4]) == GE 6290132718Skan || GET_CODE (operands[4]) == LT)" 6291132718Skan "* 6292132718Skan { 6293132718Skan if (which_alternative == 0) 6294132718Skan output_asm_insn (\"sub\\t%0, %2, %3\", operands); 6295132718Skan else if (which_alternative == 1) 6296132718Skan { 6297132718Skan /* We must provide an alternative for a hi reg because reload 6298132718Skan cannot handle output reloads on a jump instruction, but we 6299132718Skan can't subtract into that. Fortunately a mov from lo to hi 6300132718Skan does not clobber the condition codes. */ 6301132718Skan output_asm_insn (\"sub\\t%1, %2, %3\", operands); 6302132718Skan output_asm_insn (\"mov\\t%0, %1\", operands); 6303132718Skan } 6304132718Skan else 6305132718Skan { 6306132718Skan /* Similarly, but the target is memory. */ 6307132718Skan output_asm_insn (\"sub\\t%1, %2, %3\", operands); 6308132718Skan output_asm_insn (\"str\\t%1, %0\", operands); 6309132718Skan } 6310132718Skan 6311132718Skan switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0)) 6312132718Skan { 6313132718Skan case 4: 6314132718Skan return \"b%d4\\t%l5\"; 6315132718Skan case 6: 6316132718Skan return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 6317132718Skan default: 6318132718Skan return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 6319132718Skan } 6320132718Skan } 6321132718Skan " 6322132718Skan [(set (attr "far_jump") 6323132718Skan (if_then_else 6324132718Skan (ior (and (eq (symbol_ref ("which_alternative")) 6325132718Skan (const_int 0)) 6326132718Skan (eq_attr "length" "8")) 6327132718Skan (eq_attr "length" "10")) 6328132718Skan (const_string "yes") 6329132718Skan (const_string "no"))) 6330132718Skan (set (attr "length") 6331132718Skan (if_then_else 6332132718Skan (eq (symbol_ref ("which_alternative")) 6333132718Skan (const_int 0)) 6334132718Skan (if_then_else 6335132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 6336132718Skan (le (minus (match_dup 5) (pc)) (const_int 256))) 6337132718Skan (const_int 4) 6338132718Skan (if_then_else 6339132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 6340132718Skan (le (minus (match_dup 5) (pc)) (const_int 2048))) 6341132718Skan (const_int 6) 6342132718Skan (const_int 8))) 6343132718Skan (if_then_else 6344132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 6345132718Skan (le (minus (match_dup 5) (pc)) (const_int 256))) 6346132718Skan (const_int 6) 6347132718Skan (if_then_else 6348132718Skan (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 6349132718Skan (le (minus (match_dup 5) (pc)) (const_int 2048))) 6350132718Skan (const_int 8) 6351132718Skan (const_int 10)))))] 6352132718Skan) 6353132718Skan 6354132718Skan(define_insn "*subsi3_cbranch_scratch" 6355132718Skan [(set (pc) 6356132718Skan (if_then_else 6357132718Skan (match_operator 0 "arm_comparison_operator" 6358132718Skan [(minus:SI (match_operand:SI 1 "register_operand" "l") 6359132718Skan (match_operand:SI 2 "nonmemory_operand" "l")) 6360132718Skan (const_int 0)]) 6361132718Skan (label_ref (match_operand 3 "" "")) 6362132718Skan (pc)))] 6363132718Skan "TARGET_THUMB 6364132718Skan && (GET_CODE (operands[0]) == EQ 6365132718Skan || GET_CODE (operands[0]) == NE 6366132718Skan || GET_CODE (operands[0]) == GE 6367132718Skan || GET_CODE (operands[0]) == LT)" 6368132718Skan "* 6369132718Skan output_asm_insn (\"cmp\\t%1, %2\", operands); 6370132718Skan switch (get_attr_length (insn)) 6371132718Skan { 6372132718Skan case 4: return \"b%d0\\t%l3\"; 6373132718Skan case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 6374132718Skan default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 6375132718Skan } 6376132718Skan " 6377132718Skan [(set (attr "far_jump") 6378132718Skan (if_then_else 6379132718Skan (eq_attr "length" "8") 6380132718Skan (const_string "yes") 6381132718Skan (const_string "no"))) 6382132718Skan (set (attr "length") 6383132718Skan (if_then_else 6384132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 6385132718Skan (le (minus (match_dup 3) (pc)) (const_int 256))) 6386132718Skan (const_int 4) 6387132718Skan (if_then_else 6388132718Skan (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 6389132718Skan (le (minus (match_dup 3) (pc)) (const_int 2048))) 6390132718Skan (const_int 6) 6391132718Skan (const_int 8))))] 6392132718Skan) 6393132718Skan 6394132718Skan;; Comparison and test insns 6395132718Skan 639690075Sobrien(define_expand "cmpsi" 639790075Sobrien [(match_operand:SI 0 "s_register_operand" "") 639890075Sobrien (match_operand:SI 1 "arm_add_operand" "")] 639990075Sobrien "TARGET_ARM" 640090075Sobrien "{ 640190075Sobrien arm_compare_op0 = operands[0]; 640290075Sobrien arm_compare_op1 = operands[1]; 640390075Sobrien DONE; 640490075Sobrien }" 640590075Sobrien) 640690075Sobrien 640790075Sobrien(define_expand "cmpsf" 640890075Sobrien [(match_operand:SF 0 "s_register_operand" "") 640990075Sobrien (match_operand:SF 1 "fpa_rhs_operand" "")] 641090075Sobrien "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 6411132718Skan " 6412132718Skan if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode)) 641390075Sobrien operands[1] = force_reg (SFmode, operands[1]); 6414132718Skan 6415132718Skan arm_compare_op0 = operands[0]; 6416132718Skan arm_compare_op1 = operands[1]; 641790075Sobrien DONE; 641890075Sobrien " 641990075Sobrien) 642090075Sobrien 642190075Sobrien(define_expand "cmpdf" 642290075Sobrien [(match_operand:DF 0 "s_register_operand" "") 642390075Sobrien (match_operand:DF 1 "fpa_rhs_operand" "")] 642490075Sobrien "TARGET_ARM && TARGET_ANY_HARD_FLOAT" 6425132718Skan " 6426132718Skan if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode)) 642790075Sobrien operands[1] = force_reg (DFmode, operands[1]); 6428132718Skan 6429132718Skan arm_compare_op0 = operands[0]; 643090075Sobrien arm_compare_op1 = operands[1]; 643190075Sobrien DONE; 643290075Sobrien " 643390075Sobrien) 643490075Sobrien 643590075Sobrien(define_insn "*arm_cmpsi_insn" 643690075Sobrien [(set (reg:CC CC_REGNUM) 643790075Sobrien (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") 643890075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L")))] 643990075Sobrien "TARGET_ARM" 644090075Sobrien "@ 644190075Sobrien cmp%?\\t%0, %1 644290075Sobrien cmn%?\\t%0, #%n1" 644390075Sobrien [(set_attr "conds" "set")] 644490075Sobrien) 644590075Sobrien 644690075Sobrien(define_insn "*cmpsi_shiftsi" 644790075Sobrien [(set (reg:CC CC_REGNUM) 644890075Sobrien (compare:CC (match_operand:SI 0 "s_register_operand" "r") 644990075Sobrien (match_operator:SI 3 "shift_operator" 645090075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 645190075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")])))] 645290075Sobrien "TARGET_ARM" 645390075Sobrien "cmp%?\\t%0, %1%S3" 645490075Sobrien [(set_attr "conds" "set") 645590075Sobrien (set_attr "shift" "1") 645690075Sobrien ] 645790075Sobrien) 645890075Sobrien 645990075Sobrien(define_insn "*cmpsi_shiftsi_swp" 646090075Sobrien [(set (reg:CC_SWP CC_REGNUM) 646190075Sobrien (compare:CC_SWP (match_operator:SI 3 "shift_operator" 646290075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 646390075Sobrien (match_operand:SI 2 "reg_or_int_operand" "rM")]) 646490075Sobrien (match_operand:SI 0 "s_register_operand" "r")))] 646590075Sobrien "TARGET_ARM" 646690075Sobrien "cmp%?\\t%0, %1%S3" 646790075Sobrien [(set_attr "conds" "set") 646890075Sobrien (set_attr "shift" "1") 646990075Sobrien ] 647090075Sobrien) 647190075Sobrien 647290075Sobrien(define_insn "*cmpsi_neg_shiftsi" 647390075Sobrien [(set (reg:CC CC_REGNUM) 647490075Sobrien (compare:CC (match_operand:SI 0 "s_register_operand" "r") 647590075Sobrien (neg:SI (match_operator:SI 3 "shift_operator" 647690075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 647790075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]))))] 647890075Sobrien "TARGET_ARM" 647990075Sobrien "cmn%?\\t%0, %1%S3" 648090075Sobrien [(set_attr "conds" "set") 648190075Sobrien (set_attr "shift" "1") 648290075Sobrien ] 648390075Sobrien) 648490075Sobrien 648590075Sobrien;; Cirrus SF compare instruction 648690075Sobrien(define_insn "*cirrus_cmpsf" 6487132718Skan [(set (reg:CCFP CC_REGNUM) 6488132718Skan (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v") 648990075Sobrien (match_operand:SF 1 "cirrus_fp_register" "v")))] 6490132718Skan "TARGET_ARM && TARGET_CIRRUS" 6491132718Skan "cfcmps%?\\tr15, %V0, %V1" 6492132718Skan [(set_attr "type" "mav_farith") 6493132718Skan (set_attr "cirrus" "compare")] 6494132718Skan) 6495132718Skan 649690075Sobrien;; Cirrus DF compare instruction 649790075Sobrien(define_insn "*cirrus_cmpdf" 6498132718Skan [(set (reg:CCFP CC_REGNUM) 6499132718Skan (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v") 650090075Sobrien (match_operand:DF 1 "cirrus_fp_register" "v")))] 6501132718Skan "TARGET_ARM && TARGET_CIRRUS" 6502132718Skan "cfcmpd%?\\tr15, %V0, %V1" 6503132718Skan [(set_attr "type" "mav_farith") 6504132718Skan (set_attr "cirrus" "compare")] 6505132718Skan) 6506132718Skan 650790075Sobrien;; Cirrus DI compare instruction 650890075Sobrien(define_expand "cmpdi" 6509132718Skan [(match_operand:DI 0 "cirrus_fp_register" "") 6510132718Skan (match_operand:DI 1 "cirrus_fp_register" "")] 6511132718Skan "TARGET_ARM && TARGET_CIRRUS" 6512132718Skan "{ 6513132718Skan arm_compare_op0 = operands[0]; 6514132718Skan arm_compare_op1 = operands[1]; 6515132718Skan DONE; 6516132718Skan }") 6517132718Skan 6518132718Skan(define_insn "*cirrus_cmpdi" 651990075Sobrien [(set (reg:CC CC_REGNUM) 6520132718Skan (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v") 6521132718Skan (match_operand:DI 1 "cirrus_fp_register" "v")))] 6522132718Skan "TARGET_ARM && TARGET_CIRRUS" 6523132718Skan "cfcmp64%?\\tr15, %V0, %V1" 6524132718Skan [(set_attr "type" "mav_farith") 6525132718Skan (set_attr "cirrus" "compare")] 6526132718Skan) 6527132718Skan 652890075Sobrien; This insn allows redundant compares to be removed by cse, nothing should 652990075Sobrien; ever appear in the output file since (set (reg x) (reg x)) is a no-op that 653090075Sobrien; is deleted later on. The match_dup will match the mode here, so that 653190075Sobrien; mode changes of the condition codes aren't lost by this even though we don't 653290075Sobrien; specify what they are. 653390075Sobrien 653490075Sobrien(define_insn "*deleted_compare" 653590075Sobrien [(set (match_operand 0 "cc_register" "") (match_dup 0))] 653690075Sobrien "TARGET_ARM" 653790075Sobrien "\\t%@ deleted compare" 653890075Sobrien [(set_attr "conds" "set") 653990075Sobrien (set_attr "length" "0")] 654090075Sobrien) 654190075Sobrien 654290075Sobrien 654390075Sobrien;; Conditional branch insns 654490075Sobrien 654590075Sobrien(define_expand "beq" 654690075Sobrien [(set (pc) 654790075Sobrien (if_then_else (eq (match_dup 1) (const_int 0)) 654890075Sobrien (label_ref (match_operand 0 "" "")) 654990075Sobrien (pc)))] 655090075Sobrien "TARGET_ARM" 655190075Sobrien "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 655290075Sobrien) 655390075Sobrien 655490075Sobrien(define_expand "bne" 655590075Sobrien [(set (pc) 655690075Sobrien (if_then_else (ne (match_dup 1) (const_int 0)) 655790075Sobrien (label_ref (match_operand 0 "" "")) 655890075Sobrien (pc)))] 655990075Sobrien "TARGET_ARM" 656090075Sobrien "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 656190075Sobrien) 656290075Sobrien 656390075Sobrien(define_expand "bgt" 656490075Sobrien [(set (pc) 656590075Sobrien (if_then_else (gt (match_dup 1) (const_int 0)) 656690075Sobrien (label_ref (match_operand 0 "" "")) 656790075Sobrien (pc)))] 656890075Sobrien "TARGET_ARM" 656990075Sobrien "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 657090075Sobrien) 657190075Sobrien 657290075Sobrien(define_expand "ble" 657390075Sobrien [(set (pc) 657490075Sobrien (if_then_else (le (match_dup 1) (const_int 0)) 657590075Sobrien (label_ref (match_operand 0 "" "")) 657690075Sobrien (pc)))] 657790075Sobrien "TARGET_ARM" 657890075Sobrien "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 657990075Sobrien) 658090075Sobrien 658190075Sobrien(define_expand "bge" 658290075Sobrien [(set (pc) 658390075Sobrien (if_then_else (ge (match_dup 1) (const_int 0)) 658490075Sobrien (label_ref (match_operand 0 "" "")) 658590075Sobrien (pc)))] 658690075Sobrien "TARGET_ARM" 658790075Sobrien "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 658890075Sobrien) 658990075Sobrien 659090075Sobrien(define_expand "blt" 659190075Sobrien [(set (pc) 659290075Sobrien (if_then_else (lt (match_dup 1) (const_int 0)) 659390075Sobrien (label_ref (match_operand 0 "" "")) 659490075Sobrien (pc)))] 659590075Sobrien "TARGET_ARM" 659690075Sobrien "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 659790075Sobrien) 659890075Sobrien 659990075Sobrien(define_expand "bgtu" 660090075Sobrien [(set (pc) 660190075Sobrien (if_then_else (gtu (match_dup 1) (const_int 0)) 660290075Sobrien (label_ref (match_operand 0 "" "")) 660390075Sobrien (pc)))] 660490075Sobrien "TARGET_ARM" 660590075Sobrien "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 660690075Sobrien) 660790075Sobrien 660890075Sobrien(define_expand "bleu" 660990075Sobrien [(set (pc) 661090075Sobrien (if_then_else (leu (match_dup 1) (const_int 0)) 661190075Sobrien (label_ref (match_operand 0 "" "")) 661290075Sobrien (pc)))] 661390075Sobrien "TARGET_ARM" 661490075Sobrien "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 661590075Sobrien) 661690075Sobrien 661790075Sobrien(define_expand "bgeu" 661890075Sobrien [(set (pc) 661990075Sobrien (if_then_else (geu (match_dup 1) (const_int 0)) 662090075Sobrien (label_ref (match_operand 0 "" "")) 662190075Sobrien (pc)))] 662290075Sobrien "TARGET_ARM" 662390075Sobrien "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 662490075Sobrien) 662590075Sobrien 662690075Sobrien(define_expand "bltu" 662790075Sobrien [(set (pc) 662890075Sobrien (if_then_else (ltu (match_dup 1) (const_int 0)) 662990075Sobrien (label_ref (match_operand 0 "" "")) 663090075Sobrien (pc)))] 663190075Sobrien "TARGET_ARM" 663290075Sobrien "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 663390075Sobrien) 663490075Sobrien 663590075Sobrien(define_expand "bunordered" 663690075Sobrien [(set (pc) 663790075Sobrien (if_then_else (unordered (match_dup 1) (const_int 0)) 663890075Sobrien (label_ref (match_operand 0 "" "")) 663990075Sobrien (pc)))] 664090075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 664190075Sobrien "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 664290075Sobrien arm_compare_op1);" 664390075Sobrien) 664490075Sobrien 664590075Sobrien(define_expand "bordered" 664690075Sobrien [(set (pc) 664790075Sobrien (if_then_else (ordered (match_dup 1) (const_int 0)) 664890075Sobrien (label_ref (match_operand 0 "" "")) 664990075Sobrien (pc)))] 665090075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 665190075Sobrien "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 665290075Sobrien arm_compare_op1);" 665390075Sobrien) 665490075Sobrien 665590075Sobrien(define_expand "bungt" 665690075Sobrien [(set (pc) 665790075Sobrien (if_then_else (ungt (match_dup 1) (const_int 0)) 665890075Sobrien (label_ref (match_operand 0 "" "")) 665990075Sobrien (pc)))] 666090075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 666190075Sobrien "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" 666290075Sobrien) 666390075Sobrien 666490075Sobrien(define_expand "bunlt" 666590075Sobrien [(set (pc) 666690075Sobrien (if_then_else (unlt (match_dup 1) (const_int 0)) 666790075Sobrien (label_ref (match_operand 0 "" "")) 666890075Sobrien (pc)))] 666990075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 667090075Sobrien "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" 667190075Sobrien) 667290075Sobrien 667390075Sobrien(define_expand "bunge" 667490075Sobrien [(set (pc) 667590075Sobrien (if_then_else (unge (match_dup 1) (const_int 0)) 667690075Sobrien (label_ref (match_operand 0 "" "")) 667790075Sobrien (pc)))] 667890075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 667990075Sobrien "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" 668090075Sobrien) 668190075Sobrien 668290075Sobrien(define_expand "bunle" 668390075Sobrien [(set (pc) 668490075Sobrien (if_then_else (unle (match_dup 1) (const_int 0)) 668590075Sobrien (label_ref (match_operand 0 "" "")) 668690075Sobrien (pc)))] 668790075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 668890075Sobrien "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" 668990075Sobrien) 669090075Sobrien 669190075Sobrien;; The following two patterns need two branch instructions, since there is 669290075Sobrien;; no single instruction that will handle all cases. 669390075Sobrien(define_expand "buneq" 669490075Sobrien [(set (pc) 669590075Sobrien (if_then_else (uneq (match_dup 1) (const_int 0)) 669690075Sobrien (label_ref (match_operand 0 "" "")) 669790075Sobrien (pc)))] 669890075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 669990075Sobrien "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" 670090075Sobrien) 670190075Sobrien 670290075Sobrien(define_expand "bltgt" 670390075Sobrien [(set (pc) 670490075Sobrien (if_then_else (ltgt (match_dup 1) (const_int 0)) 670590075Sobrien (label_ref (match_operand 0 "" "")) 670690075Sobrien (pc)))] 670790075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 670890075Sobrien "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" 670990075Sobrien) 671090075Sobrien 671190075Sobrien;; 671290075Sobrien;; Patterns to match conditional branch insns. 671390075Sobrien;; 671490075Sobrien 671590075Sobrien; Special pattern to match UNEQ. 671690075Sobrien(define_insn "*arm_buneq" 671790075Sobrien [(set (pc) 671890075Sobrien (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 671990075Sobrien (label_ref (match_operand 0 "" "")) 672090075Sobrien (pc)))] 672190075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 672290075Sobrien "* 672390075Sobrien if (arm_ccfsm_state != 0) 672490075Sobrien abort (); 672590075Sobrien 672690075Sobrien return \"bvs\\t%l0\;beq\\t%l0\"; 672790075Sobrien " 6728117395Skan [(set_attr "conds" "jump_clob") 672990075Sobrien (set_attr "length" "8")] 673090075Sobrien) 673190075Sobrien 673290075Sobrien; Special pattern to match LTGT. 673390075Sobrien(define_insn "*arm_bltgt" 673490075Sobrien [(set (pc) 673590075Sobrien (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 673690075Sobrien (label_ref (match_operand 0 "" "")) 673790075Sobrien (pc)))] 673890075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 673990075Sobrien "* 674090075Sobrien if (arm_ccfsm_state != 0) 674190075Sobrien abort (); 674290075Sobrien 674390075Sobrien return \"bmi\\t%l0\;bgt\\t%l0\"; 674490075Sobrien " 6745117395Skan [(set_attr "conds" "jump_clob") 674690075Sobrien (set_attr "length" "8")] 674790075Sobrien) 674890075Sobrien 674990075Sobrien(define_insn "*arm_cond_branch" 675090075Sobrien [(set (pc) 675190075Sobrien (if_then_else (match_operator 1 "arm_comparison_operator" 675290075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)]) 675390075Sobrien (label_ref (match_operand 0 "" "")) 675490075Sobrien (pc)))] 675590075Sobrien "TARGET_ARM" 675690075Sobrien "* 675790075Sobrien if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 675890075Sobrien { 675990075Sobrien arm_ccfsm_state += 2; 676090075Sobrien return \"\"; 676190075Sobrien } 676290075Sobrien return \"b%d1\\t%l0\"; 676390075Sobrien " 676490075Sobrien [(set_attr "conds" "use")] 676590075Sobrien) 676690075Sobrien 676790075Sobrien; Special pattern to match reversed UNEQ. 676890075Sobrien(define_insn "*arm_buneq_reversed" 676990075Sobrien [(set (pc) 677090075Sobrien (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0)) 677190075Sobrien (pc) 677290075Sobrien (label_ref (match_operand 0 "" ""))))] 677390075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 677490075Sobrien "* 677590075Sobrien if (arm_ccfsm_state != 0) 677690075Sobrien abort (); 677790075Sobrien 677890075Sobrien return \"bmi\\t%l0\;bgt\\t%l0\"; 677990075Sobrien " 6780117395Skan [(set_attr "conds" "jump_clob") 678190075Sobrien (set_attr "length" "8")] 678290075Sobrien) 678390075Sobrien 678490075Sobrien; Special pattern to match reversed LTGT. 678590075Sobrien(define_insn "*arm_bltgt_reversed" 678690075Sobrien [(set (pc) 678790075Sobrien (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0)) 678890075Sobrien (pc) 678990075Sobrien (label_ref (match_operand 0 "" ""))))] 679090075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 679190075Sobrien "* 679290075Sobrien if (arm_ccfsm_state != 0) 679390075Sobrien abort (); 679490075Sobrien 679590075Sobrien return \"bvs\\t%l0\;beq\\t%l0\"; 679690075Sobrien " 6797117395Skan [(set_attr "conds" "jump_clob") 679890075Sobrien (set_attr "length" "8")] 679990075Sobrien) 680090075Sobrien 680190075Sobrien(define_insn "*arm_cond_branch_reversed" 680290075Sobrien [(set (pc) 680390075Sobrien (if_then_else (match_operator 1 "arm_comparison_operator" 680490075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)]) 680590075Sobrien (pc) 680690075Sobrien (label_ref (match_operand 0 "" ""))))] 680790075Sobrien "TARGET_ARM" 680890075Sobrien "* 680990075Sobrien if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 681090075Sobrien { 681190075Sobrien arm_ccfsm_state += 2; 681290075Sobrien return \"\"; 681390075Sobrien } 681490075Sobrien return \"b%D1\\t%l0\"; 681590075Sobrien " 681690075Sobrien [(set_attr "conds" "use")] 681790075Sobrien) 681890075Sobrien 681990075Sobrien 682090075Sobrien 682190075Sobrien; scc insns 682290075Sobrien 682390075Sobrien(define_expand "seq" 682490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 682590075Sobrien (eq:SI (match_dup 1) (const_int 0)))] 6826132718Skan "TARGET_ARM" 682790075Sobrien "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" 682890075Sobrien) 682990075Sobrien 683090075Sobrien(define_expand "sne" 683190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 683290075Sobrien (ne:SI (match_dup 1) (const_int 0)))] 6833132718Skan "TARGET_ARM" 683490075Sobrien "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" 683590075Sobrien) 683690075Sobrien 683790075Sobrien(define_expand "sgt" 683890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 683990075Sobrien (gt:SI (match_dup 1) (const_int 0)))] 6840132718Skan "TARGET_ARM" 684190075Sobrien "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" 684290075Sobrien) 684390075Sobrien 684490075Sobrien(define_expand "sle" 684590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 684690075Sobrien (le:SI (match_dup 1) (const_int 0)))] 6847132718Skan "TARGET_ARM" 684890075Sobrien "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" 684990075Sobrien) 685090075Sobrien 685190075Sobrien(define_expand "sge" 685290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 685390075Sobrien (ge:SI (match_dup 1) (const_int 0)))] 6854132718Skan "TARGET_ARM" 685590075Sobrien "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" 685690075Sobrien) 685790075Sobrien 685890075Sobrien(define_expand "slt" 685990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 686090075Sobrien (lt:SI (match_dup 1) (const_int 0)))] 6861132718Skan "TARGET_ARM" 686290075Sobrien "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" 686390075Sobrien) 686490075Sobrien 686590075Sobrien(define_expand "sgtu" 686690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 686790075Sobrien (gtu:SI (match_dup 1) (const_int 0)))] 6868132718Skan "TARGET_ARM" 686990075Sobrien "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" 687090075Sobrien) 687190075Sobrien 687290075Sobrien(define_expand "sleu" 687390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 687490075Sobrien (leu:SI (match_dup 1) (const_int 0)))] 6875132718Skan "TARGET_ARM" 687690075Sobrien "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" 687790075Sobrien) 687890075Sobrien 687990075Sobrien(define_expand "sgeu" 688090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 688190075Sobrien (geu:SI (match_dup 1) (const_int 0)))] 6882132718Skan "TARGET_ARM" 688390075Sobrien "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" 688490075Sobrien) 688590075Sobrien 688690075Sobrien(define_expand "sltu" 688790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 688890075Sobrien (ltu:SI (match_dup 1) (const_int 0)))] 6889132718Skan "TARGET_ARM" 689090075Sobrien "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" 689190075Sobrien) 689290075Sobrien 689390075Sobrien(define_expand "sunordered" 689490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 689590075Sobrien (unordered:SI (match_dup 1) (const_int 0)))] 6896132718Skan "TARGET_ARM && TARGET_HARD_FLOAT" 689790075Sobrien "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, 689890075Sobrien arm_compare_op1);" 689990075Sobrien) 690090075Sobrien 690190075Sobrien(define_expand "sordered" 690290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 690390075Sobrien (ordered:SI (match_dup 1) (const_int 0)))] 6904132718Skan "TARGET_ARM && TARGET_HARD_FLOAT" 690590075Sobrien "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, 690690075Sobrien arm_compare_op1);" 690790075Sobrien) 690890075Sobrien 690990075Sobrien(define_expand "sungt" 691090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 691190075Sobrien (ungt:SI (match_dup 1) (const_int 0)))] 6912132718Skan "TARGET_ARM && TARGET_HARD_FLOAT" 691390075Sobrien "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, 691490075Sobrien arm_compare_op1);" 691590075Sobrien) 691690075Sobrien 691790075Sobrien(define_expand "sunge" 691890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 691990075Sobrien (unge:SI (match_dup 1) (const_int 0)))] 6920132718Skan "TARGET_ARM && TARGET_HARD_FLOAT" 692190075Sobrien "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, 692290075Sobrien arm_compare_op1);" 692390075Sobrien) 692490075Sobrien 692590075Sobrien(define_expand "sunlt" 692690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 692790075Sobrien (unlt:SI (match_dup 1) (const_int 0)))] 6928132718Skan "TARGET_ARM && TARGET_HARD_FLOAT" 692990075Sobrien "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, 693090075Sobrien arm_compare_op1);" 693190075Sobrien) 693290075Sobrien 693390075Sobrien(define_expand "sunle" 693490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 693590075Sobrien (unle:SI (match_dup 1) (const_int 0)))] 6936132718Skan "TARGET_ARM && TARGET_HARD_FLOAT" 693790075Sobrien "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, 693890075Sobrien arm_compare_op1);" 693990075Sobrien) 694090075Sobrien 694190075Sobrien;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with 694290075Sobrien;;; simple ARM instructions. 694390075Sobrien; 694490075Sobrien; (define_expand "suneq" 694590075Sobrien; [(set (match_operand:SI 0 "s_register_operand" "") 694690075Sobrien; (uneq:SI (match_dup 1) (const_int 0)))] 6947132718Skan; "TARGET_ARM && TARGET_HARD_FLOAT" 694890075Sobrien; "abort ();" 694990075Sobrien; ) 695090075Sobrien; 695190075Sobrien; (define_expand "sltgt" 695290075Sobrien; [(set (match_operand:SI 0 "s_register_operand" "") 695390075Sobrien; (ltgt:SI (match_dup 1) (const_int 0)))] 6954132718Skan; "TARGET_ARM && TARGET_HARD_FLOAT" 695590075Sobrien; "abort ();" 695690075Sobrien; ) 695790075Sobrien 695890075Sobrien(define_insn "*mov_scc" 695990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 696090075Sobrien (match_operator:SI 1 "arm_comparison_operator" 696190075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)]))] 696290075Sobrien "TARGET_ARM" 696390075Sobrien "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 696490075Sobrien [(set_attr "conds" "use") 696590075Sobrien (set_attr "length" "8")] 696690075Sobrien) 696790075Sobrien 696890075Sobrien(define_insn "*mov_negscc" 696990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 697090075Sobrien (neg:SI (match_operator:SI 1 "arm_comparison_operator" 697190075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)])))] 697290075Sobrien "TARGET_ARM" 697390075Sobrien "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 697490075Sobrien [(set_attr "conds" "use") 697590075Sobrien (set_attr "length" "8")] 697690075Sobrien) 697790075Sobrien 697890075Sobrien(define_insn "*mov_notscc" 697990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 698090075Sobrien (not:SI (match_operator:SI 1 "arm_comparison_operator" 698190075Sobrien [(match_operand 2 "cc_register" "") (const_int 0)])))] 698290075Sobrien "TARGET_ARM" 698390075Sobrien "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" 698490075Sobrien [(set_attr "conds" "use") 698590075Sobrien (set_attr "length" "8")] 698690075Sobrien) 698790075Sobrien 698890075Sobrien 698990075Sobrien;; Conditional move insns 699090075Sobrien 699190075Sobrien(define_expand "movsicc" 699290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 699390075Sobrien (if_then_else:SI (match_operand 1 "arm_comparison_operator" "") 699490075Sobrien (match_operand:SI 2 "arm_not_operand" "") 699590075Sobrien (match_operand:SI 3 "arm_not_operand" "")))] 699690075Sobrien "TARGET_ARM" 699790075Sobrien " 699890075Sobrien { 699990075Sobrien enum rtx_code code = GET_CODE (operands[1]); 700090075Sobrien rtx ccreg; 700190075Sobrien 7002117395Skan if (code == UNEQ || code == LTGT) 700390075Sobrien FAIL; 7004117395Skan 7005117395Skan ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7006117395Skan operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 7007117395Skan }" 700890075Sobrien) 700990075Sobrien 701090075Sobrien(define_expand "movsfcc" 701190075Sobrien [(set (match_operand:SF 0 "s_register_operand" "") 701290075Sobrien (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") 701390075Sobrien (match_operand:SF 2 "s_register_operand" "") 701490075Sobrien (match_operand:SF 3 "nonmemory_operand" "")))] 701590075Sobrien "TARGET_ARM" 701690075Sobrien " 701790075Sobrien { 701890075Sobrien enum rtx_code code = GET_CODE (operands[1]); 701990075Sobrien rtx ccreg; 702090075Sobrien 702190075Sobrien if (code == UNEQ || code == LTGT) 702290075Sobrien FAIL; 7023117395Skan 7024117395Skan /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 7025117395Skan Otherwise, ensure it is a valid FP add operand. */ 702690075Sobrien if ((!TARGET_HARD_FLOAT) 7027132718Skan || (!fpa_add_operand (operands[3], SFmode))) 702890075Sobrien operands[3] = force_reg (SFmode, operands[3]); 7029132718Skan 703090075Sobrien ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 703190075Sobrien operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 703290075Sobrien }" 703390075Sobrien) 703490075Sobrien 703590075Sobrien(define_expand "movdfcc" 703690075Sobrien [(set (match_operand:DF 0 "s_register_operand" "") 703790075Sobrien (if_then_else:DF (match_operand 1 "arm_comparison_operator" "") 703890075Sobrien (match_operand:DF 2 "s_register_operand" "") 703990075Sobrien (match_operand:DF 3 "fpa_add_operand" "")))] 704090075Sobrien "TARGET_ARM && TARGET_HARD_FLOAT" 7041132718Skan " 704290075Sobrien { 704390075Sobrien enum rtx_code code = GET_CODE (operands[1]); 704490075Sobrien rtx ccreg; 704590075Sobrien 7046117395Skan if (code == UNEQ || code == LTGT) 704790075Sobrien FAIL; 7048117395Skan 7049117395Skan ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); 7050117395Skan operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); 7051117395Skan }" 705290075Sobrien) 705390075Sobrien 705490075Sobrien(define_insn "*movsicc_insn" 705590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") 705690075Sobrien (if_then_else:SI 705790075Sobrien (match_operator 3 "arm_comparison_operator" 705890075Sobrien [(match_operand 4 "cc_register" "") (const_int 0)]) 705990075Sobrien (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") 706090075Sobrien (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] 706190075Sobrien "TARGET_ARM" 706290075Sobrien "@ 706390075Sobrien mov%D3\\t%0, %2 706490075Sobrien mvn%D3\\t%0, #%B2 706590075Sobrien mov%d3\\t%0, %1 706690075Sobrien mvn%d3\\t%0, #%B1 706790075Sobrien mov%d3\\t%0, %1\;mov%D3\\t%0, %2 706890075Sobrien mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 706990075Sobrien mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 707090075Sobrien mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" 707190075Sobrien [(set_attr "length" "4,4,4,4,8,8,8,8") 707290075Sobrien (set_attr "conds" "use")] 707390075Sobrien) 707490075Sobrien 707590075Sobrien(define_insn "*movsfcc_soft_insn" 707690075Sobrien [(set (match_operand:SF 0 "s_register_operand" "=r,r") 707790075Sobrien (if_then_else:SF (match_operator 3 "arm_comparison_operator" 707890075Sobrien [(match_operand 4 "cc_register" "") (const_int 0)]) 707990075Sobrien (match_operand:SF 1 "s_register_operand" "0,r") 708090075Sobrien (match_operand:SF 2 "s_register_operand" "r,0")))] 708190075Sobrien "TARGET_ARM && TARGET_SOFT_FLOAT" 708290075Sobrien "@ 708390075Sobrien mov%D3\\t%0, %2 708490075Sobrien mov%d3\\t%0, %1" 708590075Sobrien [(set_attr "conds" "use")] 708690075Sobrien) 708790075Sobrien 708890075Sobrien 708990075Sobrien;; Jump and linkage insns 709090075Sobrien 709190075Sobrien(define_expand "jump" 709290075Sobrien [(set (pc) 709390075Sobrien (label_ref (match_operand 0 "" "")))] 709490075Sobrien "TARGET_EITHER" 709590075Sobrien "" 709690075Sobrien) 709790075Sobrien 709890075Sobrien(define_insn "*arm_jump" 709990075Sobrien [(set (pc) 710090075Sobrien (label_ref (match_operand 0 "" "")))] 710190075Sobrien "TARGET_ARM" 710290075Sobrien "* 710390075Sobrien { 710490075Sobrien if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2) 710590075Sobrien { 710690075Sobrien arm_ccfsm_state += 2; 710790075Sobrien return \"\"; 710890075Sobrien } 710990075Sobrien return \"b%?\\t%l0\"; 711090075Sobrien } 711190075Sobrien " 711290075Sobrien [(set_attr "predicable" "yes")] 711390075Sobrien) 711490075Sobrien 711590075Sobrien(define_insn "*thumb_jump" 711690075Sobrien [(set (pc) 711790075Sobrien (label_ref (match_operand 0 "" "")))] 711890075Sobrien "TARGET_THUMB" 711990075Sobrien "* 712090075Sobrien if (get_attr_length (insn) == 2) 712190075Sobrien return \"b\\t%l0\"; 712290075Sobrien return \"bl\\t%l0\\t%@ far jump\"; 712390075Sobrien " 712490075Sobrien [(set (attr "far_jump") 712590075Sobrien (if_then_else 712690075Sobrien (eq_attr "length" "4") 712790075Sobrien (const_string "yes") 712890075Sobrien (const_string "no"))) 712990075Sobrien (set (attr "length") 713090075Sobrien (if_then_else 713190075Sobrien (and (ge (minus (match_dup 0) (pc)) (const_int -2048)) 713290075Sobrien (le (minus (match_dup 0) (pc)) (const_int 2044))) 7133146895Skan (const_int 2) 7134146895Skan (const_int 4)))] 713590075Sobrien) 713690075Sobrien 713790075Sobrien(define_expand "call" 713890075Sobrien [(parallel [(call (match_operand 0 "memory_operand" "") 713990075Sobrien (match_operand 1 "general_operand" "")) 714090075Sobrien (use (match_operand 2 "" "")) 714190075Sobrien (clobber (reg:SI LR_REGNUM))])] 714290075Sobrien "TARGET_EITHER" 714390075Sobrien " 714490075Sobrien { 714590075Sobrien rtx callee; 714690075Sobrien 714790075Sobrien /* In an untyped call, we can get NULL for operand 2. */ 714890075Sobrien if (operands[2] == NULL_RTX) 714990075Sobrien operands[2] = const0_rtx; 715090075Sobrien 715190075Sobrien /* This is to decide if we should generate indirect calls by loading the 715290075Sobrien 32 bit address of the callee into a register before performing the 715390075Sobrien branch and link. operand[2] encodes the long_call/short_call 715490075Sobrien attribute of the function being called. This attribute is set whenever 715590075Sobrien __attribute__((long_call/short_call)) or #pragma long_call/no_long_call 715690075Sobrien is used, and the short_call attribute can also be set if function is 715790075Sobrien declared as static or if it has already been defined in the current 715890075Sobrien compilation unit. See arm.c and arm.h for info about this. The third 715990075Sobrien parameter to arm_is_longcall_p is used to tell it which pattern 716090075Sobrien invoked it. */ 716190075Sobrien callee = XEXP (operands[0], 0); 716290075Sobrien 716390075Sobrien if (GET_CODE (callee) != REG 716490075Sobrien && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0)) 716590075Sobrien XEXP (operands[0], 0) = force_reg (Pmode, callee); 716690075Sobrien }" 716790075Sobrien) 716890075Sobrien 716990075Sobrien(define_insn "*call_reg" 717090075Sobrien [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 717190075Sobrien (match_operand 1 "" "")) 717290075Sobrien (use (match_operand 2 "" "")) 717390075Sobrien (clobber (reg:SI LR_REGNUM))] 717490075Sobrien "TARGET_ARM" 717590075Sobrien "* 717690075Sobrien return output_call (operands); 717790075Sobrien " 717890075Sobrien ;; length is worst case, normally it is only two 717990075Sobrien [(set_attr "length" "12") 718090075Sobrien (set_attr "type" "call")] 718190075Sobrien) 718290075Sobrien 718390075Sobrien(define_insn "*call_mem" 718490075Sobrien [(call (mem:SI (match_operand:SI 0 "memory_operand" "m")) 718590075Sobrien (match_operand 1 "" "")) 718690075Sobrien (use (match_operand 2 "" "")) 718790075Sobrien (clobber (reg:SI LR_REGNUM))] 718890075Sobrien "TARGET_ARM" 718990075Sobrien "* 719090075Sobrien return output_call_mem (operands); 719190075Sobrien " 719290075Sobrien [(set_attr "length" "12") 719390075Sobrien (set_attr "type" "call")] 719490075Sobrien) 719590075Sobrien 719690075Sobrien(define_insn "*call_indirect" 719790075Sobrien [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 719890075Sobrien (match_operand 1 "" "")) 719990075Sobrien (use (match_operand 2 "" "")) 720090075Sobrien (clobber (reg:SI LR_REGNUM))] 720190075Sobrien "TARGET_THUMB" 720290075Sobrien "* 720390075Sobrien { 720490075Sobrien if (TARGET_CALLER_INTERWORKING) 720590075Sobrien return \"bl\\t%__interwork_call_via_%0\"; 720690075Sobrien else 720790075Sobrien return \"bl\\t%__call_via_%0\"; 720890075Sobrien }" 720990075Sobrien [(set_attr "type" "call")] 721090075Sobrien) 721190075Sobrien 721290075Sobrien(define_insn "*call_value_indirect" 721390075Sobrien [(set (match_operand 0 "" "") 721490075Sobrien (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 7215132718Skan (match_operand 2 "" ""))) 721690075Sobrien (use (match_operand 3 "" "")) 721790075Sobrien (clobber (reg:SI LR_REGNUM))] 721890075Sobrien "TARGET_THUMB" 721990075Sobrien "* 722090075Sobrien { 722190075Sobrien if (TARGET_CALLER_INTERWORKING) 722290075Sobrien return \"bl\\t%__interwork_call_via_%1\"; 722390075Sobrien else 722490075Sobrien return \"bl\\t%__call_via_%1\"; 722590075Sobrien }" 722690075Sobrien [(set_attr "type" "call")] 722790075Sobrien) 722890075Sobrien 722990075Sobrien(define_expand "call_value" 723090075Sobrien [(parallel [(set (match_operand 0 "" "") 723190075Sobrien (call (match_operand 1 "memory_operand" "") 723290075Sobrien (match_operand 2 "general_operand" ""))) 723390075Sobrien (use (match_operand 3 "" "")) 723490075Sobrien (clobber (reg:SI LR_REGNUM))])] 723590075Sobrien "TARGET_EITHER" 723690075Sobrien " 723790075Sobrien { 723890075Sobrien rtx callee = XEXP (operands[1], 0); 723990075Sobrien 724090075Sobrien /* In an untyped call, we can get NULL for operand 2. */ 724190075Sobrien if (operands[3] == 0) 724290075Sobrien operands[3] = const0_rtx; 724390075Sobrien 724490075Sobrien /* See the comment in define_expand \"call\". */ 724590075Sobrien if (GET_CODE (callee) != REG 724690075Sobrien && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0)) 724790075Sobrien XEXP (operands[1], 0) = force_reg (Pmode, callee); 724890075Sobrien }" 724990075Sobrien) 725090075Sobrien 725190075Sobrien(define_insn "*call_value_reg" 725290075Sobrien [(set (match_operand 0 "" "") 725390075Sobrien (call (mem:SI (match_operand:SI 1 "s_register_operand" "r")) 7254132718Skan (match_operand 2 "" ""))) 7255132718Skan (use (match_operand 3 "" "")) 725690075Sobrien (clobber (reg:SI LR_REGNUM))] 725790075Sobrien "TARGET_ARM" 725890075Sobrien "* 725990075Sobrien return output_call (&operands[1]); 726090075Sobrien " 726190075Sobrien [(set_attr "length" "12") 726290075Sobrien (set_attr "type" "call")] 726390075Sobrien) 726490075Sobrien 726590075Sobrien(define_insn "*call_value_mem" 726690075Sobrien [(set (match_operand 0 "" "") 726790075Sobrien (call (mem:SI (match_operand:SI 1 "memory_operand" "m")) 7268132718Skan (match_operand 2 "" ""))) 7269132718Skan (use (match_operand 3 "" "")) 727090075Sobrien (clobber (reg:SI LR_REGNUM))] 727190075Sobrien "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))" 727290075Sobrien "* 727390075Sobrien return output_call_mem (&operands[1]); 727490075Sobrien " 727590075Sobrien [(set_attr "length" "12") 727690075Sobrien (set_attr "type" "call")] 727790075Sobrien) 727890075Sobrien 727990075Sobrien;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses 728090075Sobrien;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. 728190075Sobrien 728290075Sobrien(define_insn "*call_symbol" 728390075Sobrien [(call (mem:SI (match_operand:SI 0 "" "")) 728490075Sobrien (match_operand 1 "" "")) 7285132718Skan (use (match_operand 2 "" "")) 728690075Sobrien (clobber (reg:SI LR_REGNUM))] 728790075Sobrien "TARGET_ARM 728890075Sobrien && (GET_CODE (operands[0]) == SYMBOL_REF) 728990075Sobrien && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 729090075Sobrien "* 729190075Sobrien { 729290075Sobrien return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\"; 729390075Sobrien }" 729490075Sobrien [(set_attr "type" "call")] 729590075Sobrien) 729690075Sobrien 729790075Sobrien(define_insn "*call_value_symbol" 729890075Sobrien [(set (match_operand 0 "s_register_operand" "") 729990075Sobrien (call (mem:SI (match_operand:SI 1 "" "")) 7300132718Skan (match_operand:SI 2 "" ""))) 7301132718Skan (use (match_operand 3 "" "")) 730290075Sobrien (clobber (reg:SI LR_REGNUM))] 730390075Sobrien "TARGET_ARM 730490075Sobrien && (GET_CODE (operands[1]) == SYMBOL_REF) 730590075Sobrien && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 730690075Sobrien "* 730790075Sobrien { 730890075Sobrien return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\"; 730990075Sobrien }" 731090075Sobrien [(set_attr "type" "call")] 731190075Sobrien) 731290075Sobrien 731390075Sobrien(define_insn "*call_insn" 731490075Sobrien [(call (mem:SI (match_operand:SI 0 "" "")) 731590075Sobrien (match_operand:SI 1 "" "")) 7316132718Skan (use (match_operand 2 "" "")) 731790075Sobrien (clobber (reg:SI LR_REGNUM))] 731890075Sobrien "TARGET_THUMB 731990075Sobrien && GET_CODE (operands[0]) == SYMBOL_REF 732090075Sobrien && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)" 732196263Sobrien "bl\\t%a0" 732296263Sobrien [(set_attr "length" "4") 732390075Sobrien (set_attr "type" "call")] 732490075Sobrien) 732590075Sobrien 732690075Sobrien(define_insn "*call_value_insn" 732790075Sobrien [(set (match_operand 0 "register_operand" "") 732890075Sobrien (call (mem:SI (match_operand 1 "" "")) 7329132718Skan (match_operand 2 "" ""))) 7330132718Skan (use (match_operand 3 "" "")) 733190075Sobrien (clobber (reg:SI LR_REGNUM))] 733290075Sobrien "TARGET_THUMB 733390075Sobrien && GET_CODE (operands[1]) == SYMBOL_REF 733490075Sobrien && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)" 733596263Sobrien "bl\\t%a1" 733696263Sobrien [(set_attr "length" "4") 733790075Sobrien (set_attr "type" "call")] 733890075Sobrien) 733990075Sobrien 734090075Sobrien;; We may also be able to do sibcalls for Thumb, but it's much harder... 734190075Sobrien(define_expand "sibcall" 734290075Sobrien [(parallel [(call (match_operand 0 "memory_operand" "") 734390075Sobrien (match_operand 1 "general_operand" "")) 734490075Sobrien (return) 734590075Sobrien (use (match_operand 2 "" ""))])] 7346117395Skan "TARGET_ARM" 7347117395Skan " 734890075Sobrien { 734990075Sobrien if (operands[2] == NULL_RTX) 735090075Sobrien operands[2] = const0_rtx; 735190075Sobrien }" 735290075Sobrien) 735390075Sobrien 735490075Sobrien(define_expand "sibcall_value" 735590075Sobrien [(parallel [(set (match_operand 0 "register_operand" "") 735690075Sobrien (call (match_operand 1 "memory_operand" "") 735790075Sobrien (match_operand 2 "general_operand" ""))) 735890075Sobrien (return) 735990075Sobrien (use (match_operand 3 "" ""))])] 7360117395Skan "TARGET_ARM" 7361117395Skan " 736290075Sobrien { 736390075Sobrien if (operands[3] == NULL_RTX) 736490075Sobrien operands[3] = const0_rtx; 736590075Sobrien }" 736690075Sobrien) 736790075Sobrien 736890075Sobrien(define_insn "*sibcall_insn" 736990075Sobrien [(call (mem:SI (match_operand:SI 0 "" "X")) 737090075Sobrien (match_operand 1 "" "")) 737190075Sobrien (return) 737290075Sobrien (use (match_operand 2 "" ""))] 7373117395Skan "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF" 7374117395Skan "* 737590075Sobrien return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; 737690075Sobrien " 737790075Sobrien [(set_attr "type" "call")] 737890075Sobrien) 737990075Sobrien 738090075Sobrien(define_insn "*sibcall_value_insn" 738190075Sobrien [(set (match_operand 0 "s_register_operand" "") 738290075Sobrien (call (mem:SI (match_operand:SI 1 "" "X")) 7383132718Skan (match_operand 2 "" ""))) 7384132718Skan (return) 738590075Sobrien (use (match_operand 3 "" ""))] 7386117395Skan "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF" 7387117395Skan "* 738890075Sobrien return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; 738990075Sobrien " 739090075Sobrien [(set_attr "type" "call")] 739190075Sobrien) 739290075Sobrien 739390075Sobrien;; Often the return insn will be the same as loading from memory, so set attr 739490075Sobrien(define_insn "return" 739590075Sobrien [(return)] 739690075Sobrien "TARGET_ARM && USE_RETURN_INSN (FALSE)" 739790075Sobrien "* 739890075Sobrien { 739990075Sobrien if (arm_ccfsm_state == 2) 740090075Sobrien { 740190075Sobrien arm_ccfsm_state += 2; 740290075Sobrien return \"\"; 740390075Sobrien } 740490075Sobrien return output_return_instruction (const_true_rtx, TRUE, FALSE); 740590075Sobrien }" 7406117395Skan [(set_attr "type" "load") 740790075Sobrien (set_attr "length" "12") 740890075Sobrien (set_attr "predicable" "yes")] 7409132718Skan) 741090075Sobrien 741190075Sobrien(define_insn "*cond_return" 741290075Sobrien [(set (pc) 741390075Sobrien (if_then_else (match_operator 0 "arm_comparison_operator" 741490075Sobrien [(match_operand 1 "cc_register" "") (const_int 0)]) 741590075Sobrien (return) 741690075Sobrien (pc)))] 741790075Sobrien "TARGET_ARM && USE_RETURN_INSN (TRUE)" 741890075Sobrien "* 741990075Sobrien { 742090075Sobrien if (arm_ccfsm_state == 2) 742190075Sobrien { 742290075Sobrien arm_ccfsm_state += 2; 742390075Sobrien return \"\"; 742490075Sobrien } 742590075Sobrien return output_return_instruction (operands[0], TRUE, FALSE); 742690075Sobrien }" 742790075Sobrien [(set_attr "conds" "use") 742890075Sobrien (set_attr "length" "12") 742990075Sobrien (set_attr "type" "load")] 7430132718Skan) 743190075Sobrien 743290075Sobrien(define_insn "*cond_return_inverted" 743390075Sobrien [(set (pc) 743490075Sobrien (if_then_else (match_operator 0 "arm_comparison_operator" 743590075Sobrien [(match_operand 1 "cc_register" "") (const_int 0)]) 743690075Sobrien (pc) 743790075Sobrien (return)))] 743890075Sobrien "TARGET_ARM && USE_RETURN_INSN (TRUE)" 743990075Sobrien "* 744090075Sobrien { 744190075Sobrien if (arm_ccfsm_state == 2) 744290075Sobrien { 744390075Sobrien arm_ccfsm_state += 2; 744490075Sobrien return \"\"; 744590075Sobrien } 744690075Sobrien return output_return_instruction (operands[0], TRUE, TRUE); 744790075Sobrien }" 744890075Sobrien [(set_attr "conds" "use") 744990075Sobrien (set_attr "type" "load")] 745090075Sobrien) 745190075Sobrien 745290075Sobrien;; Generate a sequence of instructions to determine if the processor is 745390075Sobrien;; in 26-bit or 32-bit mode, and return the appropriate return address 7454117395Skan;; mask. 7455117395Skan 7456117395Skan(define_expand "return_addr_mask" 7457117395Skan [(set (match_dup 1) 7458117395Skan (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 7459117395Skan (const_int 0))) 7460117395Skan (set (match_operand:SI 0 "s_register_operand" "") 7461117395Skan (if_then_else:SI (eq (match_dup 1) (const_int 0)) 7462117395Skan (const_int -1) 7463117395Skan (const_int 67108860)))] ; 0x03fffffc 7464117395Skan "TARGET_ARM" 7465117395Skan " 7466117395Skan operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM); 7467117395Skan ") 7468132718Skan 7469117395Skan(define_insn "*check_arch2" 7470117395Skan [(set (match_operand:CC_NOOV 0 "cc_register" "") 7471117395Skan (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) 7472117395Skan (const_int 0)))] 7473117395Skan "TARGET_ARM" 7474117395Skan "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc" 7475117395Skan [(set_attr "length" "8") 7476117395Skan (set_attr "conds" "set")] 7477117395Skan) 7478117395Skan 7479117395Skan;; Call subroutine returning any type. 7480117395Skan 748190075Sobrien(define_expand "untyped_call" 748290075Sobrien [(parallel [(call (match_operand 0 "" "") 748390075Sobrien (const_int 0)) 748490075Sobrien (match_operand 1 "" "") 748590075Sobrien (match_operand 2 "" "")])] 748690075Sobrien "TARGET_ARM" 748790075Sobrien " 748890075Sobrien { 748990075Sobrien int i; 749090075Sobrien 749190075Sobrien emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); 749290075Sobrien 749390075Sobrien for (i = 0; i < XVECLEN (operands[2], 0); i++) 749490075Sobrien { 749590075Sobrien rtx set = XVECEXP (operands[2], 0, i); 749690075Sobrien 749790075Sobrien emit_move_insn (SET_DEST (set), SET_SRC (set)); 749890075Sobrien } 749990075Sobrien 750090075Sobrien /* The optimizer does not know that the call sets the function value 750190075Sobrien registers we stored in the result block. We avoid problems by 750290075Sobrien claiming that all hard registers are used and clobbered at this 750390075Sobrien point. */ 750490075Sobrien emit_insn (gen_blockage ()); 750590075Sobrien 750690075Sobrien DONE; 750790075Sobrien }" 750890075Sobrien) 750990075Sobrien 751090075Sobrien;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 751190075Sobrien;; all of memory. This blocks insns from being moved across this point. 751290075Sobrien 751390075Sobrien(define_insn "blockage" 751490075Sobrien [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)] 751590075Sobrien "TARGET_EITHER" 751690075Sobrien "" 751790075Sobrien [(set_attr "length" "0") 751890075Sobrien (set_attr "type" "block")] 751990075Sobrien) 752090075Sobrien 752190075Sobrien(define_expand "casesi" 752290075Sobrien [(match_operand:SI 0 "s_register_operand" "") ; index to jump on 752390075Sobrien (match_operand:SI 1 "const_int_operand" "") ; lower bound 752490075Sobrien (match_operand:SI 2 "const_int_operand" "") ; total range 752590075Sobrien (match_operand:SI 3 "" "") ; table label 752690075Sobrien (match_operand:SI 4 "" "")] ; Out of range label 752790075Sobrien "TARGET_ARM" 752890075Sobrien " 752990075Sobrien { 753090075Sobrien rtx reg; 753190075Sobrien if (operands[1] != const0_rtx) 753290075Sobrien { 753390075Sobrien reg = gen_reg_rtx (SImode); 753490075Sobrien 753590075Sobrien emit_insn (gen_addsi3 (reg, operands[0], 753690075Sobrien GEN_INT (-INTVAL (operands[1])))); 753790075Sobrien operands[0] = reg; 753890075Sobrien } 753990075Sobrien 754090075Sobrien if (!const_ok_for_arm (INTVAL (operands[2]))) 754190075Sobrien operands[2] = force_reg (SImode, operands[2]); 754290075Sobrien 754390075Sobrien emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3], 754490075Sobrien operands[4])); 754590075Sobrien DONE; 754690075Sobrien }" 754790075Sobrien) 754890075Sobrien 754990075Sobrien;; The USE in this pattern is needed to tell flow analysis that this is 755090075Sobrien;; a CASESI insn. It has no other purpose. 755190075Sobrien(define_insn "casesi_internal" 755290075Sobrien [(parallel [(set (pc) 755390075Sobrien (if_then_else 755490075Sobrien (leu (match_operand:SI 0 "s_register_operand" "r") 755590075Sobrien (match_operand:SI 1 "arm_rhs_operand" "rI")) 755690075Sobrien (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 755790075Sobrien (label_ref (match_operand 2 "" "")))) 755890075Sobrien (label_ref (match_operand 3 "" "")))) 755990075Sobrien (clobber (reg:CC CC_REGNUM)) 756090075Sobrien (use (label_ref (match_dup 2)))])] 756190075Sobrien "TARGET_ARM" 756290075Sobrien "* 756390075Sobrien if (flag_pic) 756490075Sobrien return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\"; 756590075Sobrien return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\"; 756690075Sobrien " 756790075Sobrien [(set_attr "conds" "clob") 756890075Sobrien (set_attr "length" "12")] 756990075Sobrien) 757090075Sobrien 757190075Sobrien(define_expand "indirect_jump" 757290075Sobrien [(set (pc) 757390075Sobrien (match_operand:SI 0 "s_register_operand" ""))] 757490075Sobrien "TARGET_EITHER" 757590075Sobrien "" 757690075Sobrien) 757790075Sobrien 757890075Sobrien(define_insn "*arm_indirect_jump" 757990075Sobrien [(set (pc) 758090075Sobrien (match_operand:SI 0 "s_register_operand" "r"))] 758190075Sobrien "TARGET_ARM" 758290075Sobrien "mov%?\\t%|pc, %0\\t%@ indirect register jump" 758390075Sobrien [(set_attr "predicable" "yes")] 758490075Sobrien) 758590075Sobrien 758690075Sobrien;; Although not supported by the define_expand above, 758790075Sobrien;; cse/combine may generate this form. 758890075Sobrien(define_insn "*load_indirect_jump" 758990075Sobrien [(set (pc) 759090075Sobrien (match_operand:SI 0 "memory_operand" "m"))] 759190075Sobrien "TARGET_ARM" 759290075Sobrien "ldr%?\\t%|pc, %0\\t%@ indirect memory jump" 759390075Sobrien [(set_attr "type" "load") 759490075Sobrien (set_attr "pool_range" "4096") 759590075Sobrien (set_attr "neg_pool_range" "4084") 759690075Sobrien (set_attr "predicable" "yes")] 759790075Sobrien) 759890075Sobrien 759990075Sobrien(define_insn "*thumb_indirect_jump" 760090075Sobrien [(set (pc) 760190075Sobrien (match_operand:SI 0 "register_operand" "l*r"))] 760290075Sobrien "TARGET_THUMB" 760390075Sobrien "mov\\tpc, %0" 760490075Sobrien [(set_attr "conds" "clob") 760590075Sobrien (set_attr "length" "2")] 760690075Sobrien) 760790075Sobrien 760890075Sobrien 760990075Sobrien;; Misc insns 761090075Sobrien 761190075Sobrien(define_insn "nop" 761290075Sobrien [(const_int 0)] 761390075Sobrien "TARGET_EITHER" 761490075Sobrien "* 761590075Sobrien if (TARGET_ARM) 761690075Sobrien return \"mov%?\\t%|r0, %|r0\\t%@ nop\"; 761790075Sobrien return \"mov\\tr8, r8\"; 761890075Sobrien " 761990075Sobrien [(set (attr "length") 762090075Sobrien (if_then_else (eq_attr "is_thumb" "yes") 762190075Sobrien (const_int 2) 762290075Sobrien (const_int 4)))] 762390075Sobrien) 762490075Sobrien 762590075Sobrien 762690075Sobrien;; Patterns to allow combination of arithmetic, cond code and shifts 762790075Sobrien 762890075Sobrien(define_insn "*arith_shiftsi" 762990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 763090075Sobrien (match_operator:SI 1 "shiftable_operator" 763190075Sobrien [(match_operator:SI 3 "shift_operator" 763290075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 763390075Sobrien (match_operand:SI 5 "reg_or_int_operand" "rI")]) 763490075Sobrien (match_operand:SI 2 "s_register_operand" "r")]))] 763590075Sobrien "TARGET_ARM" 763690075Sobrien "%i1%?\\t%0, %2, %4%S3" 763790075Sobrien [(set_attr "predicable" "yes") 763890075Sobrien (set_attr "shift" "4") 763990075Sobrien ] 764090075Sobrien) 764190075Sobrien 764290075Sobrien(define_split 764390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 7644132718Skan (match_operator:SI 1 "shiftable_operator" 7645132718Skan [(match_operator:SI 2 "shiftable_operator" 7646132718Skan [(match_operator:SI 3 "shift_operator" 7647132718Skan [(match_operand:SI 4 "s_register_operand" "") 7648132718Skan (match_operand:SI 5 "reg_or_int_operand" "")]) 7649132718Skan (match_operand:SI 6 "s_register_operand" "")]) 7650132718Skan (match_operand:SI 7 "arm_rhs_operand" "")])) 7651132718Skan (clobber (match_operand:SI 8 "s_register_operand" ""))] 7652132718Skan "TARGET_ARM" 7653132718Skan [(set (match_dup 8) 7654132718Skan (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 7655132718Skan (match_dup 6)])) 7656132718Skan (set (match_dup 0) 7657132718Skan (match_op_dup 1 [(match_dup 8) (match_dup 7)]))] 7658132718Skan "") 7659132718Skan 7660132718Skan(define_insn "*arith_shiftsi_compare0" 7661132718Skan [(set (reg:CC_NOOV CC_REGNUM) 766290075Sobrien (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 766390075Sobrien [(match_operator:SI 3 "shift_operator" 766490075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 766590075Sobrien (match_operand:SI 5 "reg_or_int_operand" "rI")]) 766690075Sobrien (match_operand:SI 2 "s_register_operand" "r")]) 766790075Sobrien (const_int 0))) 766890075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 766990075Sobrien (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 767090075Sobrien (match_dup 2)]))] 767190075Sobrien "TARGET_ARM" 767290075Sobrien "%i1%?s\\t%0, %2, %4%S3" 767390075Sobrien [(set_attr "conds" "set") 767490075Sobrien (set_attr "shift" "4") 767590075Sobrien ] 767690075Sobrien) 767790075Sobrien 767890075Sobrien(define_insn "*arith_shiftsi_compare0_scratch" 767990075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 768090075Sobrien (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 768190075Sobrien [(match_operator:SI 3 "shift_operator" 768290075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 768390075Sobrien (match_operand:SI 5 "reg_or_int_operand" "rI")]) 768490075Sobrien (match_operand:SI 2 "s_register_operand" "r")]) 768590075Sobrien (const_int 0))) 768690075Sobrien (clobber (match_scratch:SI 0 "=r"))] 768790075Sobrien "TARGET_ARM" 768890075Sobrien "%i1%?s\\t%0, %2, %4%S3" 768990075Sobrien [(set_attr "conds" "set") 769090075Sobrien (set_attr "shift" "4") 769190075Sobrien ] 769290075Sobrien) 769390075Sobrien 769490075Sobrien(define_insn "*sub_shiftsi" 769590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 769690075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "r") 769790075Sobrien (match_operator:SI 2 "shift_operator" 769890075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 769990075Sobrien (match_operand:SI 4 "reg_or_int_operand" "rM")])))] 770090075Sobrien "TARGET_ARM" 770190075Sobrien "sub%?\\t%0, %1, %3%S2" 770290075Sobrien [(set_attr "predicable" "yes") 770390075Sobrien (set_attr "shift" "3") 770490075Sobrien ] 770590075Sobrien) 770690075Sobrien 770790075Sobrien(define_insn "*sub_shiftsi_compare0" 770890075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 770990075Sobrien (compare:CC_NOOV 771090075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "r") 771190075Sobrien (match_operator:SI 2 "shift_operator" 771290075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 771390075Sobrien (match_operand:SI 4 "reg_or_int_operand" "rM")])) 771490075Sobrien (const_int 0))) 771590075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 771690075Sobrien (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 771790075Sobrien (match_dup 4)])))] 771890075Sobrien "TARGET_ARM" 771990075Sobrien "sub%?s\\t%0, %1, %3%S2" 772090075Sobrien [(set_attr "conds" "set") 772190075Sobrien (set_attr "shift" "3") 772290075Sobrien ] 772390075Sobrien) 772490075Sobrien 772590075Sobrien(define_insn "*sub_shiftsi_compare0_scratch" 772690075Sobrien [(set (reg:CC_NOOV CC_REGNUM) 772790075Sobrien (compare:CC_NOOV 772890075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "r") 772990075Sobrien (match_operator:SI 2 "shift_operator" 773090075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 773190075Sobrien (match_operand:SI 4 "reg_or_int_operand" "rM")])) 773290075Sobrien (const_int 0))) 773390075Sobrien (clobber (match_scratch:SI 0 "=r"))] 773490075Sobrien "TARGET_ARM" 773590075Sobrien "sub%?s\\t%0, %1, %3%S2" 773690075Sobrien [(set_attr "conds" "set") 773790075Sobrien (set_attr "shift" "3") 773890075Sobrien ] 773990075Sobrien) 774090075Sobrien 774190075Sobrien 774290075Sobrien 774390075Sobrien(define_insn "*and_scc" 774490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 774590075Sobrien (and:SI (match_operator:SI 1 "arm_comparison_operator" 774690075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 774790075Sobrien (match_operand:SI 2 "s_register_operand" "r")))] 774890075Sobrien "TARGET_ARM" 774990075Sobrien "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" 775090075Sobrien [(set_attr "conds" "use") 775190075Sobrien (set_attr "length" "8")] 775290075Sobrien) 775390075Sobrien 775490075Sobrien(define_insn "*ior_scc" 775590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 775690075Sobrien (ior:SI (match_operator:SI 2 "arm_comparison_operator" 775790075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 775890075Sobrien (match_operand:SI 1 "s_register_operand" "0,?r")))] 775990075Sobrien "TARGET_ARM" 776090075Sobrien "@ 776190075Sobrien orr%d2\\t%0, %1, #1 776290075Sobrien mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" 776390075Sobrien [(set_attr "conds" "use") 776490075Sobrien (set_attr "length" "4,8")] 776590075Sobrien) 776690075Sobrien 776790075Sobrien(define_insn "*compare_scc" 776890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 776990075Sobrien (match_operator:SI 1 "arm_comparison_operator" 777090075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 777190075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,L")])) 777290075Sobrien (clobber (reg:CC CC_REGNUM))] 777390075Sobrien "TARGET_ARM" 777490075Sobrien "* 777590075Sobrien if (operands[3] == const0_rtx) 777690075Sobrien { 7777132718Skan if (GET_CODE (operands[1]) == LT) 7778132718Skan return \"mov\\t%0, %2, lsr #31\"; 7779132718Skan 7780132718Skan if (GET_CODE (operands[1]) == GE) 778190075Sobrien return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; 7782132718Skan 7783132718Skan if (GET_CODE (operands[1]) == EQ) 778490075Sobrien return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\"; 7785132718Skan } 7786132718Skan 7787132718Skan if (GET_CODE (operands[1]) == NE) 7788132718Skan { 778990075Sobrien if (which_alternative == 1) 779090075Sobrien return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; 779190075Sobrien return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; 779290075Sobrien } 779390075Sobrien if (which_alternative == 1) 779490075Sobrien output_asm_insn (\"cmn\\t%2, #%n3\", operands); 779590075Sobrien else 779690075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 779790075Sobrien return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; 779890075Sobrien " 779990075Sobrien [(set_attr "conds" "clob") 780090075Sobrien (set_attr "length" "12")] 780190075Sobrien) 780290075Sobrien 780390075Sobrien(define_insn "*cond_move" 780490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 780590075Sobrien (if_then_else:SI (match_operator 3 "equality_operator" 780690075Sobrien [(match_operator 4 "arm_comparison_operator" 780790075Sobrien [(match_operand 5 "cc_register" "") (const_int 0)]) 780890075Sobrien (const_int 0)]) 780990075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 781090075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 781190075Sobrien "TARGET_ARM" 781290075Sobrien "* 781390075Sobrien if (GET_CODE (operands[3]) == NE) 781490075Sobrien { 781590075Sobrien if (which_alternative != 1) 781690075Sobrien output_asm_insn (\"mov%D4\\t%0, %2\", operands); 781790075Sobrien if (which_alternative != 0) 781890075Sobrien output_asm_insn (\"mov%d4\\t%0, %1\", operands); 781990075Sobrien return \"\"; 782090075Sobrien } 782190075Sobrien if (which_alternative != 0) 782290075Sobrien output_asm_insn (\"mov%D4\\t%0, %1\", operands); 782390075Sobrien if (which_alternative != 1) 782490075Sobrien output_asm_insn (\"mov%d4\\t%0, %2\", operands); 782590075Sobrien return \"\"; 782690075Sobrien " 782790075Sobrien [(set_attr "conds" "use") 782890075Sobrien (set_attr "length" "4,4,8")] 782990075Sobrien) 783090075Sobrien 783190075Sobrien(define_insn "*cond_arith" 783290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 783390075Sobrien (match_operator:SI 5 "shiftable_operator" 783490075Sobrien [(match_operator:SI 4 "arm_comparison_operator" 783590075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 783690075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 783790075Sobrien (match_operand:SI 1 "s_register_operand" "0,?r")])) 783890075Sobrien (clobber (reg:CC CC_REGNUM))] 783990075Sobrien "TARGET_ARM" 784090075Sobrien "* 784190075Sobrien if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 784290075Sobrien return \"%i5\\t%0, %1, %2, lsr #31\"; 784390075Sobrien 784490075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 784590075Sobrien if (GET_CODE (operands[5]) == AND) 784690075Sobrien output_asm_insn (\"mov%D4\\t%0, #0\", operands); 784790075Sobrien else if (GET_CODE (operands[5]) == MINUS) 784890075Sobrien output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 784990075Sobrien else if (which_alternative != 0) 785090075Sobrien output_asm_insn (\"mov%D4\\t%0, %1\", operands); 785190075Sobrien return \"%i5%d4\\t%0, %1, #1\"; 785290075Sobrien " 785390075Sobrien [(set_attr "conds" "clob") 785490075Sobrien (set_attr "length" "12")] 785590075Sobrien) 785690075Sobrien 785790075Sobrien(define_insn "*cond_sub" 785890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 785990075Sobrien (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 786090075Sobrien (match_operator:SI 4 "arm_comparison_operator" 786190075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 786290075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 786390075Sobrien (clobber (reg:CC CC_REGNUM))] 786490075Sobrien "TARGET_ARM" 786590075Sobrien "* 786690075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 786790075Sobrien if (which_alternative != 0) 786890075Sobrien output_asm_insn (\"mov%D4\\t%0, %1\", operands); 786990075Sobrien return \"sub%d4\\t%0, %1, #1\"; 787090075Sobrien " 787190075Sobrien [(set_attr "conds" "clob") 787290075Sobrien (set_attr "length" "8,12")] 787390075Sobrien) 787490075Sobrien 787590075Sobrien(define_insn "*cmp_ite0" 787690075Sobrien [(set (match_operand 6 "dominant_cc_register" "") 787790075Sobrien (compare 787890075Sobrien (if_then_else:SI 787990075Sobrien (match_operator 4 "arm_comparison_operator" 788090075Sobrien [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 788190075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 788290075Sobrien (match_operator:SI 5 "arm_comparison_operator" 788390075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 788490075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 788590075Sobrien (const_int 0)) 788690075Sobrien (const_int 0)))] 788790075Sobrien "TARGET_ARM" 788890075Sobrien "* 788990075Sobrien { 789090075Sobrien static const char * const opcodes[4][2] = 789190075Sobrien { 789290075Sobrien {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 789390075Sobrien \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 789490075Sobrien {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 789590075Sobrien \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 789690075Sobrien {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 789790075Sobrien \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 789890075Sobrien {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 789990075Sobrien \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 790090075Sobrien }; 790190075Sobrien int swap = 790290075Sobrien comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 790390075Sobrien 790490075Sobrien return opcodes[which_alternative][swap]; 790590075Sobrien }" 790690075Sobrien [(set_attr "conds" "set") 790790075Sobrien (set_attr "length" "8")] 790890075Sobrien) 790990075Sobrien 791090075Sobrien(define_insn "*cmp_ite1" 791190075Sobrien [(set (match_operand 6 "dominant_cc_register" "") 791290075Sobrien (compare 791390075Sobrien (if_then_else:SI 791490075Sobrien (match_operator 4 "arm_comparison_operator" 791590075Sobrien [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 791690075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 791790075Sobrien (match_operator:SI 5 "arm_comparison_operator" 791890075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 791990075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]) 792090075Sobrien (const_int 1)) 792190075Sobrien (const_int 0)))] 792290075Sobrien "TARGET_ARM" 792390075Sobrien "* 792490075Sobrien { 792590075Sobrien static const char * const opcodes[4][2] = 792690075Sobrien { 792790075Sobrien {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", 792890075Sobrien \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 792990075Sobrien {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", 793090075Sobrien \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 793190075Sobrien {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", 793290075Sobrien \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 793390075Sobrien {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\", 793490075Sobrien \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 793590075Sobrien }; 793690075Sobrien int swap = 793790075Sobrien comparison_dominates_p (GET_CODE (operands[5]), 793890075Sobrien reverse_condition (GET_CODE (operands[4]))); 793990075Sobrien 794090075Sobrien return opcodes[which_alternative][swap]; 794190075Sobrien }" 794290075Sobrien [(set_attr "conds" "set") 794390075Sobrien (set_attr "length" "8")] 794490075Sobrien) 794590075Sobrien 794690075Sobrien(define_insn "*cmp_and" 794790075Sobrien [(set (match_operand 6 "dominant_cc_register" "") 794890075Sobrien (compare 794990075Sobrien (and:SI 795090075Sobrien (match_operator 4 "arm_comparison_operator" 795190075Sobrien [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 795290075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 795390075Sobrien (match_operator:SI 5 "arm_comparison_operator" 795490075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 795590075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 795690075Sobrien (const_int 0)))] 795790075Sobrien "TARGET_ARM" 795890075Sobrien "* 795990075Sobrien { 796090075Sobrien static const char *const opcodes[4][2] = 796190075Sobrien { 796290075Sobrien {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\", 796390075Sobrien \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"}, 796490075Sobrien {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", 796590075Sobrien \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"}, 796690075Sobrien {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", 796790075Sobrien \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"}, 796890075Sobrien {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\", 796990075Sobrien \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"} 797090075Sobrien }; 797190075Sobrien int swap = 797290075Sobrien comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 797390075Sobrien 797490075Sobrien return opcodes[which_alternative][swap]; 797590075Sobrien }" 797690075Sobrien [(set_attr "conds" "set") 797790075Sobrien (set_attr "predicable" "no") 797890075Sobrien (set_attr "length" "8")] 797990075Sobrien) 798090075Sobrien 798190075Sobrien(define_insn "*cmp_ior" 798290075Sobrien [(set (match_operand 6 "dominant_cc_register" "") 798390075Sobrien (compare 798490075Sobrien (ior:SI 798590075Sobrien (match_operator 4 "arm_comparison_operator" 798690075Sobrien [(match_operand:SI 0 "s_register_operand" "r,r,r,r") 798790075Sobrien (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")]) 798890075Sobrien (match_operator:SI 5 "arm_comparison_operator" 798990075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r,r") 799090075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])) 799190075Sobrien (const_int 0)))] 799290075Sobrien "TARGET_ARM" 799390075Sobrien "* 799490075Sobrien{ 799590075Sobrien static const char *const opcodes[4][2] = 799690075Sobrien { 799790075Sobrien {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\", 799890075Sobrien \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"}, 799990075Sobrien {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\", 800090075Sobrien \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"}, 800190075Sobrien {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\", 800290075Sobrien \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"}, 800390075Sobrien {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\", 800490075Sobrien \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"} 800590075Sobrien }; 800690075Sobrien int swap = 800790075Sobrien comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])); 800890075Sobrien 800990075Sobrien return opcodes[which_alternative][swap]; 801090075Sobrien} 801190075Sobrien" 801290075Sobrien [(set_attr "conds" "set") 801390075Sobrien (set_attr "length" "8")] 801490075Sobrien) 801590075Sobrien 801690075Sobrien(define_insn_and_split "*ior_scc_scc" 801790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 8018132718Skan (ior:SI (match_operator:SI 3 "arm_comparison_operator" 8019132718Skan [(match_operand:SI 1 "s_register_operand" "r") 8020132718Skan (match_operand:SI 2 "arm_add_operand" "rIL")]) 8021132718Skan (match_operator:SI 6 "arm_comparison_operator" 8022132718Skan [(match_operand:SI 4 "s_register_operand" "r") 8023132718Skan (match_operand:SI 5 "arm_add_operand" "rIL")]))) 8024132718Skan (clobber (reg:CC CC_REGNUM))] 8025132718Skan "TARGET_ARM 8026132718Skan && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y) 8027132718Skan != CCmode)" 8028132718Skan "#" 8029132718Skan "TARGET_ARM && reload_completed" 8030132718Skan [(set (match_dup 7) 8031132718Skan (compare 8032132718Skan (ior:SI 8033132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8034132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8035132718Skan (const_int 0))) 8036132718Skan (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))] 8037132718Skan "operands[7] 8038132718Skan = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6], 8039132718Skan DOM_CC_X_OR_Y), 8040132718Skan CC_REGNUM);" 8041132718Skan [(set_attr "conds" "clob") 8042132718Skan (set_attr "length" "16")]) 8043132718Skan 8044132718Skan; If the above pattern is followed by a CMP insn, then the compare is 8045132718Skan; redundant, since we can rework the conditional instruction that follows. 8046132718Skan(define_insn_and_split "*ior_scc_scc_cmp" 8047132718Skan [(set (match_operand 0 "dominant_cc_register" "") 8048132718Skan (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator" 8049132718Skan [(match_operand:SI 1 "s_register_operand" "r") 8050132718Skan (match_operand:SI 2 "arm_add_operand" "rIL")]) 8051132718Skan (match_operator:SI 6 "arm_comparison_operator" 8052132718Skan [(match_operand:SI 4 "s_register_operand" "r") 8053132718Skan (match_operand:SI 5 "arm_add_operand" "rIL")])) 8054132718Skan (const_int 0))) 8055132718Skan (set (match_operand:SI 7 "s_register_operand" "=r") 8056132718Skan (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8057132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])))] 8058132718Skan "TARGET_ARM" 8059132718Skan "#" 8060132718Skan "TARGET_ARM && reload_completed" 8061132718Skan [(set (match_dup 0) 8062132718Skan (compare 8063132718Skan (ior:SI 8064132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8065132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8066132718Skan (const_int 0))) 8067132718Skan (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))] 8068132718Skan "" 8069132718Skan [(set_attr "conds" "set") 8070132718Skan (set_attr "length" "16")]) 8071132718Skan 8072132718Skan(define_insn_and_split "*and_scc_scc" 8073132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 8074132718Skan (and:SI (match_operator:SI 3 "arm_comparison_operator" 8075132718Skan [(match_operand:SI 1 "s_register_operand" "r") 8076132718Skan (match_operand:SI 2 "arm_add_operand" "rIL")]) 8077132718Skan (match_operator:SI 6 "arm_comparison_operator" 8078132718Skan [(match_operand:SI 4 "s_register_operand" "r") 8079132718Skan (match_operand:SI 5 "arm_add_operand" "rIL")]))) 8080132718Skan (clobber (reg:CC CC_REGNUM))] 8081132718Skan "TARGET_ARM 8082132718Skan && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8083132718Skan != CCmode)" 8084132718Skan "#" 8085132718Skan "TARGET_ARM && reload_completed 8086132718Skan && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8087132718Skan != CCmode)" 8088132718Skan [(set (match_dup 7) 8089132718Skan (compare 8090132718Skan (and:SI 8091132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8092132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8093132718Skan (const_int 0))) 8094132718Skan (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))] 8095132718Skan "operands[7] 8096132718Skan = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6], 8097132718Skan DOM_CC_X_AND_Y), 8098132718Skan CC_REGNUM);" 8099132718Skan [(set_attr "conds" "clob") 8100132718Skan (set_attr "length" "16")]) 8101132718Skan 8102132718Skan; If the above pattern is followed by a CMP insn, then the compare is 8103132718Skan; redundant, since we can rework the conditional instruction that follows. 8104132718Skan(define_insn_and_split "*and_scc_scc_cmp" 8105132718Skan [(set (match_operand 0 "dominant_cc_register" "") 8106132718Skan (compare (and:SI (match_operator:SI 3 "arm_comparison_operator" 8107132718Skan [(match_operand:SI 1 "s_register_operand" "r") 8108132718Skan (match_operand:SI 2 "arm_add_operand" "rIL")]) 8109132718Skan (match_operator:SI 6 "arm_comparison_operator" 8110132718Skan [(match_operand:SI 4 "s_register_operand" "r") 8111132718Skan (match_operand:SI 5 "arm_add_operand" "rIL")])) 8112132718Skan (const_int 0))) 8113132718Skan (set (match_operand:SI 7 "s_register_operand" "=r") 8114132718Skan (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8115132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])))] 8116132718Skan "TARGET_ARM" 8117132718Skan "#" 8118132718Skan "TARGET_ARM && reload_completed" 8119132718Skan [(set (match_dup 0) 8120132718Skan (compare 8121132718Skan (and:SI 8122132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)]) 8123132718Skan (match_op_dup 6 [(match_dup 4) (match_dup 5)])) 8124132718Skan (const_int 0))) 8125132718Skan (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))] 8126132718Skan "" 8127132718Skan [(set_attr "conds" "set") 8128132718Skan (set_attr "length" "16")]) 8129132718Skan 8130132718Skan;; If there is no dominance in the comparison, then we can still save an 8131132718Skan;; instruction in the AND case, since we can know that the second compare 8132132718Skan;; need only zero the value if false (if true, then the value is already 8133132718Skan;; correct). 8134132718Skan(define_insn_and_split "*and_scc_scc_nodom" 8135132718Skan [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r") 8136132718Skan (and:SI (match_operator:SI 3 "arm_comparison_operator" 8137132718Skan [(match_operand:SI 1 "s_register_operand" "r,r,0") 8138132718Skan (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")]) 8139132718Skan (match_operator:SI 6 "arm_comparison_operator" 8140132718Skan [(match_operand:SI 4 "s_register_operand" "r,r,r") 8141132718Skan (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")]))) 8142132718Skan (clobber (reg:CC CC_REGNUM))] 8143132718Skan "TARGET_ARM 8144132718Skan && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y) 8145132718Skan == CCmode)" 8146132718Skan "#" 8147132718Skan "TARGET_ARM && reload_completed" 8148132718Skan [(parallel [(set (match_dup 0) 8149132718Skan (match_op_dup 3 [(match_dup 1) (match_dup 2)])) 8150132718Skan (clobber (reg:CC CC_REGNUM))]) 8151132718Skan (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)])) 8152132718Skan (set (match_dup 0) 8153132718Skan (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)]) 8154132718Skan (match_dup 0) 8155132718Skan (const_int 0)))] 8156132718Skan "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]), 8157132718Skan operands[4], operands[5]), 8158132718Skan CC_REGNUM); 8159132718Skan operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4], 8160132718Skan operands[5]);" 8161132718Skan [(set_attr "conds" "clob") 8162132718Skan (set_attr "length" "20")]) 8163132718Skan 8164132718Skan(define_split 8165132718Skan [(set (reg:CC_NOOV CC_REGNUM) 8166132718Skan (compare:CC_NOOV (ior:SI 8167132718Skan (and:SI (match_operand:SI 0 "s_register_operand" "") 8168132718Skan (const_int 1)) 8169132718Skan (match_operator:SI 1 "comparison_operator" 8170132718Skan [(match_operand:SI 2 "s_register_operand" "") 8171132718Skan (match_operand:SI 3 "arm_add_operand" "")])) 8172132718Skan (const_int 0))) 8173132718Skan (clobber (match_operand:SI 4 "s_register_operand" ""))] 8174132718Skan "TARGET_ARM" 8175132718Skan [(set (match_dup 4) 8176132718Skan (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)]) 8177132718Skan (match_dup 0))) 8178132718Skan (set (reg:CC_NOOV CC_REGNUM) 8179132718Skan (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1)) 8180132718Skan (const_int 0)))] 8181132718Skan "") 8182132718Skan 8183132718Skan(define_split 8184132718Skan [(set (reg:CC_NOOV CC_REGNUM) 8185132718Skan (compare:CC_NOOV (ior:SI 8186132718Skan (match_operator:SI 1 "comparison_operator" 8187132718Skan [(match_operand:SI 2 "s_register_operand" "") 8188132718Skan (match_operand:SI 3 "arm_add_operand" "")]) 8189132718Skan (and:SI (match_operand:SI 0 "s_register_operand" "") 8190132718Skan (const_int 1))) 8191132718Skan (const_int 0))) 8192132718Skan (clobber (match_operand:SI 4 "s_register_operand" ""))] 8193132718Skan "TARGET_ARM" 8194132718Skan [(set (match_dup 4) 8195132718Skan (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)]) 8196132718Skan (match_dup 0))) 8197132718Skan (set (reg:CC_NOOV CC_REGNUM) 8198132718Skan (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1)) 8199132718Skan (const_int 0)))] 8200132718Skan "") 8201132718Skan 8202132718Skan(define_insn "*negscc" 8203132718Skan [(set (match_operand:SI 0 "s_register_operand" "=r") 820490075Sobrien (neg:SI (match_operator 3 "arm_comparison_operator" 820590075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 820690075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 820790075Sobrien (clobber (reg:CC CC_REGNUM))] 820890075Sobrien "TARGET_ARM" 820990075Sobrien "* 821090075Sobrien if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx) 821190075Sobrien return \"mov\\t%0, %1, asr #31\"; 821290075Sobrien 821390075Sobrien if (GET_CODE (operands[3]) == NE) 821490075Sobrien return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\"; 821590075Sobrien 821690075Sobrien if (GET_CODE (operands[3]) == GT) 821790075Sobrien return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\"; 821890075Sobrien 821990075Sobrien output_asm_insn (\"cmp\\t%1, %2\", operands); 822090075Sobrien output_asm_insn (\"mov%D3\\t%0, #0\", operands); 822190075Sobrien return \"mvn%d3\\t%0, #0\"; 822290075Sobrien " 822390075Sobrien [(set_attr "conds" "clob") 822490075Sobrien (set_attr "length" "12")] 822590075Sobrien) 822690075Sobrien 822790075Sobrien(define_insn "movcond" 822890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 822990075Sobrien (if_then_else:SI 823090075Sobrien (match_operator 5 "arm_comparison_operator" 823190075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r,r") 823290075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 823390075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 823490075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 823590075Sobrien (clobber (reg:CC CC_REGNUM))] 823690075Sobrien "TARGET_ARM" 823790075Sobrien "* 823890075Sobrien if (GET_CODE (operands[5]) == LT 823990075Sobrien && (operands[4] == const0_rtx)) 824090075Sobrien { 824190075Sobrien if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 824290075Sobrien { 824390075Sobrien if (operands[2] == const0_rtx) 824490075Sobrien return \"and\\t%0, %1, %3, asr #31\"; 824590075Sobrien return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\"; 824690075Sobrien } 824790075Sobrien else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 824890075Sobrien { 824990075Sobrien if (operands[1] == const0_rtx) 825090075Sobrien return \"bic\\t%0, %2, %3, asr #31\"; 825190075Sobrien return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\"; 825290075Sobrien } 825390075Sobrien /* The only case that falls through to here is when both ops 1 & 2 825490075Sobrien are constants. */ 825590075Sobrien } 8256132718Skan 825790075Sobrien if (GET_CODE (operands[5]) == GE 825890075Sobrien && (operands[4] == const0_rtx)) 825990075Sobrien { 826090075Sobrien if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 826190075Sobrien { 826290075Sobrien if (operands[2] == const0_rtx) 826390075Sobrien return \"bic\\t%0, %1, %3, asr #31\"; 826490075Sobrien return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\"; 826590075Sobrien } 826690075Sobrien else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 826790075Sobrien { 826890075Sobrien if (operands[1] == const0_rtx) 826990075Sobrien return \"and\\t%0, %2, %3, asr #31\"; 827090075Sobrien return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\"; 827190075Sobrien } 827290075Sobrien /* The only case that falls through to here is when both ops 1 & 2 827390075Sobrien are constants. */ 827490075Sobrien } 8275132718Skan if (GET_CODE (operands[4]) == CONST_INT 827690075Sobrien && !const_ok_for_arm (INTVAL (operands[4]))) 827790075Sobrien output_asm_insn (\"cmn\\t%3, #%n4\", operands); 827890075Sobrien else 827990075Sobrien output_asm_insn (\"cmp\\t%3, %4\", operands); 828090075Sobrien if (which_alternative != 0) 828190075Sobrien output_asm_insn (\"mov%d5\\t%0, %1\", operands); 828290075Sobrien if (which_alternative != 1) 828390075Sobrien output_asm_insn (\"mov%D5\\t%0, %2\", operands); 828490075Sobrien return \"\"; 828590075Sobrien " 828690075Sobrien [(set_attr "conds" "clob") 828790075Sobrien (set_attr "length" "8,8,12")] 828890075Sobrien) 828990075Sobrien 829090075Sobrien(define_insn "*ifcompare_plus_move" 829190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 829290075Sobrien (if_then_else:SI (match_operator 6 "arm_comparison_operator" 829390075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 829490075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 829590075Sobrien (plus:SI 829690075Sobrien (match_operand:SI 2 "s_register_operand" "r,r") 829790075Sobrien (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) 829890075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 829990075Sobrien (clobber (reg:CC CC_REGNUM))] 830090075Sobrien "TARGET_ARM" 830190075Sobrien "#" 830290075Sobrien [(set_attr "conds" "clob") 830390075Sobrien (set_attr "length" "8,12")] 830490075Sobrien) 830590075Sobrien 830690075Sobrien(define_insn "*if_plus_move" 830790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 830890075Sobrien (if_then_else:SI 830990075Sobrien (match_operator 4 "arm_comparison_operator" 831090075Sobrien [(match_operand 5 "cc_register" "") (const_int 0)]) 831190075Sobrien (plus:SI 831290075Sobrien (match_operand:SI 2 "s_register_operand" "r,r,r,r") 831390075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")) 831490075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))] 831590075Sobrien "TARGET_ARM" 831690075Sobrien "@ 831790075Sobrien add%d4\\t%0, %2, %3 831890075Sobrien sub%d4\\t%0, %2, #%n3 831990075Sobrien add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1 832090075Sobrien sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1" 832190075Sobrien [(set_attr "conds" "use") 832290075Sobrien (set_attr "length" "4,4,8,8") 832390075Sobrien (set_attr "type" "*,*,*,*")] 832490075Sobrien) 832590075Sobrien 832690075Sobrien(define_insn "*ifcompare_move_plus" 832790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 832890075Sobrien (if_then_else:SI (match_operator 6 "arm_comparison_operator" 832990075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 833090075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 833190075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 833290075Sobrien (plus:SI 833390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r") 833490075Sobrien (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) 833590075Sobrien (clobber (reg:CC CC_REGNUM))] 833690075Sobrien "TARGET_ARM" 833790075Sobrien "#" 833890075Sobrien [(set_attr "conds" "clob") 833990075Sobrien (set_attr "length" "8,12")] 834090075Sobrien) 834190075Sobrien 834290075Sobrien(define_insn "*if_move_plus" 834390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") 834490075Sobrien (if_then_else:SI 834590075Sobrien (match_operator 4 "arm_comparison_operator" 834690075Sobrien [(match_operand 5 "cc_register" "") (const_int 0)]) 834790075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI") 834890075Sobrien (plus:SI 834990075Sobrien (match_operand:SI 2 "s_register_operand" "r,r,r,r") 835090075Sobrien (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))] 835190075Sobrien "TARGET_ARM" 835290075Sobrien "@ 835390075Sobrien add%D4\\t%0, %2, %3 835490075Sobrien sub%D4\\t%0, %2, #%n3 835590075Sobrien add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1 835690075Sobrien sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1" 835790075Sobrien [(set_attr "conds" "use") 835890075Sobrien (set_attr "length" "4,4,8,8") 835990075Sobrien (set_attr "type" "*,*,*,*")] 836090075Sobrien) 836190075Sobrien 836290075Sobrien(define_insn "*ifcompare_arith_arith" 836390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 836490075Sobrien (if_then_else:SI (match_operator 9 "arm_comparison_operator" 836590075Sobrien [(match_operand:SI 5 "s_register_operand" "r") 836690075Sobrien (match_operand:SI 6 "arm_add_operand" "rIL")]) 836790075Sobrien (match_operator:SI 8 "shiftable_operator" 836890075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 836990075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")]) 837090075Sobrien (match_operator:SI 7 "shiftable_operator" 837190075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 837290075Sobrien (match_operand:SI 4 "arm_rhs_operand" "rI")]))) 837390075Sobrien (clobber (reg:CC CC_REGNUM))] 837490075Sobrien "TARGET_ARM" 837590075Sobrien "#" 837690075Sobrien [(set_attr "conds" "clob") 837790075Sobrien (set_attr "length" "12")] 837890075Sobrien) 837990075Sobrien 838090075Sobrien(define_insn "*if_arith_arith" 838190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 838290075Sobrien (if_then_else:SI (match_operator 5 "arm_comparison_operator" 838390075Sobrien [(match_operand 8 "cc_register" "") (const_int 0)]) 838490075Sobrien (match_operator:SI 6 "shiftable_operator" 838590075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 838690075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rI")]) 838790075Sobrien (match_operator:SI 7 "shiftable_operator" 838890075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 838990075Sobrien (match_operand:SI 4 "arm_rhs_operand" "rI")])))] 839090075Sobrien "TARGET_ARM" 839190075Sobrien "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4" 839290075Sobrien [(set_attr "conds" "use") 839390075Sobrien (set_attr "length" "8")] 839490075Sobrien) 839590075Sobrien 839690075Sobrien(define_insn "*ifcompare_arith_move" 839790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 839890075Sobrien (if_then_else:SI (match_operator 6 "arm_comparison_operator" 839990075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 840090075Sobrien (match_operand:SI 3 "arm_add_operand" "rIL,rIL")]) 840190075Sobrien (match_operator:SI 7 "shiftable_operator" 840290075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 840390075Sobrien (match_operand:SI 5 "arm_rhs_operand" "rI,rI")]) 840490075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) 840590075Sobrien (clobber (reg:CC CC_REGNUM))] 840690075Sobrien "TARGET_ARM" 840790075Sobrien "* 840890075Sobrien /* If we have an operation where (op x 0) is the identity operation and 840990075Sobrien the conditional operator is LT or GE and we are comparing against zero and 841090075Sobrien everything is in registers then we can do this in two instructions. */ 841190075Sobrien if (operands[3] == const0_rtx 8412132718Skan && GET_CODE (operands[7]) != AND 841390075Sobrien && GET_CODE (operands[5]) == REG 841490075Sobrien && GET_CODE (operands[1]) == REG 841590075Sobrien && REGNO (operands[1]) == REGNO (operands[4]) 841690075Sobrien && REGNO (operands[4]) != REGNO (operands[0])) 841790075Sobrien { 841890075Sobrien if (GET_CODE (operands[6]) == LT) 841990075Sobrien return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 842090075Sobrien else if (GET_CODE (operands[6]) == GE) 842190075Sobrien return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\"; 842290075Sobrien } 842390075Sobrien if (GET_CODE (operands[3]) == CONST_INT 842490075Sobrien && !const_ok_for_arm (INTVAL (operands[3]))) 842590075Sobrien output_asm_insn (\"cmn\\t%2, #%n3\", operands); 842690075Sobrien else 842790075Sobrien output_asm_insn (\"cmp\\t%2, %3\", operands); 842890075Sobrien output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands); 842990075Sobrien if (which_alternative != 0) 843090075Sobrien return \"mov%D6\\t%0, %1\"; 843190075Sobrien return \"\"; 843290075Sobrien " 843390075Sobrien [(set_attr "conds" "clob") 843490075Sobrien (set_attr "length" "8,12")] 843590075Sobrien) 843690075Sobrien 843790075Sobrien(define_insn "*if_arith_move" 843890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 843990075Sobrien (if_then_else:SI (match_operator 4 "arm_comparison_operator" 844090075Sobrien [(match_operand 6 "cc_register" "") (const_int 0)]) 844190075Sobrien (match_operator:SI 5 "shiftable_operator" 844290075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 844390075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 844490075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))] 844590075Sobrien "TARGET_ARM" 844690075Sobrien "@ 844790075Sobrien %I5%d4\\t%0, %2, %3 844890075Sobrien %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1" 844990075Sobrien [(set_attr "conds" "use") 845090075Sobrien (set_attr "length" "4,8") 845190075Sobrien (set_attr "type" "*,*")] 845290075Sobrien) 845390075Sobrien 845490075Sobrien(define_insn "*ifcompare_move_arith" 845590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 845690075Sobrien (if_then_else:SI (match_operator 6 "arm_comparison_operator" 845790075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 845890075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 845990075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 846090075Sobrien (match_operator:SI 7 "shiftable_operator" 846190075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 846290075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 846390075Sobrien (clobber (reg:CC CC_REGNUM))] 846490075Sobrien "TARGET_ARM" 846590075Sobrien "* 846690075Sobrien /* If we have an operation where (op x 0) is the identity operation and 846790075Sobrien the conditional operator is LT or GE and we are comparing against zero and 846890075Sobrien everything is in registers then we can do this in two instructions */ 846990075Sobrien if (operands[5] == const0_rtx 847090075Sobrien && GET_CODE (operands[7]) != AND 847190075Sobrien && GET_CODE (operands[3]) == REG 847290075Sobrien && GET_CODE (operands[1]) == REG 847390075Sobrien && REGNO (operands[1]) == REGNO (operands[2]) 847490075Sobrien && REGNO (operands[2]) != REGNO (operands[0])) 847590075Sobrien { 847690075Sobrien if (GET_CODE (operands[6]) == GE) 847790075Sobrien return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 847890075Sobrien else if (GET_CODE (operands[6]) == LT) 847990075Sobrien return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\"; 848090075Sobrien } 848190075Sobrien 848290075Sobrien if (GET_CODE (operands[5]) == CONST_INT 848390075Sobrien && !const_ok_for_arm (INTVAL (operands[5]))) 848490075Sobrien output_asm_insn (\"cmn\\t%4, #%n5\", operands); 848590075Sobrien else 848690075Sobrien output_asm_insn (\"cmp\\t%4, %5\", operands); 848790075Sobrien 848890075Sobrien if (which_alternative != 0) 848990075Sobrien output_asm_insn (\"mov%d6\\t%0, %1\", operands); 849090075Sobrien return \"%I7%D6\\t%0, %2, %3\"; 849190075Sobrien " 849290075Sobrien [(set_attr "conds" "clob") 849390075Sobrien (set_attr "length" "8,12")] 849490075Sobrien) 849590075Sobrien 849690075Sobrien(define_insn "*if_move_arith" 849790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 849890075Sobrien (if_then_else:SI 849990075Sobrien (match_operator 4 "arm_comparison_operator" 850090075Sobrien [(match_operand 6 "cc_register" "") (const_int 0)]) 850190075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 850290075Sobrien (match_operator:SI 5 "shiftable_operator" 850390075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 850490075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))] 850590075Sobrien "TARGET_ARM" 850690075Sobrien "@ 850790075Sobrien %I5%D4\\t%0, %2, %3 850890075Sobrien %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1" 850990075Sobrien [(set_attr "conds" "use") 851090075Sobrien (set_attr "length" "4,8") 851190075Sobrien (set_attr "type" "*,*")] 851290075Sobrien) 851390075Sobrien 851490075Sobrien(define_insn "*ifcompare_move_not" 851590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 851690075Sobrien (if_then_else:SI 851790075Sobrien (match_operator 5 "arm_comparison_operator" 851890075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r") 851990075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 852090075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK") 852190075Sobrien (not:SI 852290075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")))) 852390075Sobrien (clobber (reg:CC CC_REGNUM))] 852490075Sobrien "TARGET_ARM" 852590075Sobrien "#" 852690075Sobrien [(set_attr "conds" "clob") 852790075Sobrien (set_attr "length" "8,12")] 852890075Sobrien) 852990075Sobrien 853090075Sobrien(define_insn "*if_move_not" 853190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 853290075Sobrien (if_then_else:SI 853390075Sobrien (match_operator 4 "arm_comparison_operator" 853490075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 853590075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 853690075Sobrien (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 853790075Sobrien "TARGET_ARM" 853890075Sobrien "@ 853990075Sobrien mvn%D4\\t%0, %2 854090075Sobrien mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 854190075Sobrien mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" 854290075Sobrien [(set_attr "conds" "use") 854390075Sobrien (set_attr "length" "4,8,8")] 854490075Sobrien) 854590075Sobrien 854690075Sobrien(define_insn "*ifcompare_not_move" 854790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 854890075Sobrien (if_then_else:SI 854990075Sobrien (match_operator 5 "arm_comparison_operator" 855090075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r") 855190075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 855290075Sobrien (not:SI 855390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r")) 855490075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 855590075Sobrien (clobber (reg:CC CC_REGNUM))] 855690075Sobrien "TARGET_ARM" 855790075Sobrien "#" 855890075Sobrien [(set_attr "conds" "clob") 855990075Sobrien (set_attr "length" "8,12")] 856090075Sobrien) 856190075Sobrien 856290075Sobrien(define_insn "*if_not_move" 856390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 856490075Sobrien (if_then_else:SI 856590075Sobrien (match_operator 4 "arm_comparison_operator" 856690075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 856790075Sobrien (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 856890075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 856990075Sobrien "TARGET_ARM" 857090075Sobrien "@ 857190075Sobrien mvn%d4\\t%0, %2 857290075Sobrien mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 857390075Sobrien mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" 857490075Sobrien [(set_attr "conds" "use") 857590075Sobrien (set_attr "length" "4,8,8")] 857690075Sobrien) 857790075Sobrien 857890075Sobrien(define_insn "*ifcompare_shift_move" 857990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 858090075Sobrien (if_then_else:SI 858190075Sobrien (match_operator 6 "arm_comparison_operator" 858290075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 858390075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 858490075Sobrien (match_operator:SI 7 "shift_operator" 858590075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 858690075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) 858790075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 858890075Sobrien (clobber (reg:CC CC_REGNUM))] 858990075Sobrien "TARGET_ARM" 859090075Sobrien "#" 859190075Sobrien [(set_attr "conds" "clob") 859290075Sobrien (set_attr "length" "8,12")] 859390075Sobrien) 859490075Sobrien 859590075Sobrien(define_insn "*if_shift_move" 859690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 859790075Sobrien (if_then_else:SI 859890075Sobrien (match_operator 5 "arm_comparison_operator" 859990075Sobrien [(match_operand 6 "cc_register" "") (const_int 0)]) 860090075Sobrien (match_operator:SI 4 "shift_operator" 860190075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r") 860290075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")]) 860390075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 860490075Sobrien "TARGET_ARM" 860590075Sobrien "@ 860690075Sobrien mov%d5\\t%0, %2%S4 860790075Sobrien mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4 860890075Sobrien mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" 860990075Sobrien [(set_attr "conds" "use") 861090075Sobrien (set_attr "shift" "2") 861190075Sobrien (set_attr "length" "4,8,8")] 861290075Sobrien) 861390075Sobrien 861490075Sobrien(define_insn "*ifcompare_move_shift" 861590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 861690075Sobrien (if_then_else:SI 861790075Sobrien (match_operator 6 "arm_comparison_operator" 861890075Sobrien [(match_operand:SI 4 "s_register_operand" "r,r") 861990075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL,rIL")]) 862090075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK") 862190075Sobrien (match_operator:SI 7 "shift_operator" 862290075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r") 862390075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) 862490075Sobrien (clobber (reg:CC CC_REGNUM))] 862590075Sobrien "TARGET_ARM" 862690075Sobrien "#" 862790075Sobrien [(set_attr "conds" "clob") 862890075Sobrien (set_attr "length" "8,12")] 862990075Sobrien) 863090075Sobrien 863190075Sobrien(define_insn "*if_move_shift" 863290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 863390075Sobrien (if_then_else:SI 863490075Sobrien (match_operator 5 "arm_comparison_operator" 863590075Sobrien [(match_operand 6 "cc_register" "") (const_int 0)]) 863690075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 863790075Sobrien (match_operator:SI 4 "shift_operator" 863890075Sobrien [(match_operand:SI 2 "s_register_operand" "r,r,r") 863990075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))] 864090075Sobrien "TARGET_ARM" 864190075Sobrien "@ 864290075Sobrien mov%D5\\t%0, %2%S4 864390075Sobrien mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4 864490075Sobrien mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" 864590075Sobrien [(set_attr "conds" "use") 864690075Sobrien (set_attr "shift" "2") 864790075Sobrien (set_attr "length" "4,8,8")] 864890075Sobrien) 864990075Sobrien 865090075Sobrien(define_insn "*ifcompare_shift_shift" 865190075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 865290075Sobrien (if_then_else:SI 865390075Sobrien (match_operator 7 "arm_comparison_operator" 865490075Sobrien [(match_operand:SI 5 "s_register_operand" "r") 865590075Sobrien (match_operand:SI 6 "arm_add_operand" "rIL")]) 865690075Sobrien (match_operator:SI 8 "shift_operator" 865790075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 865890075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]) 865990075Sobrien (match_operator:SI 9 "shift_operator" 866090075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 866190075Sobrien (match_operand:SI 4 "arm_rhs_operand" "rM")]))) 866290075Sobrien (clobber (reg:CC CC_REGNUM))] 866390075Sobrien "TARGET_ARM" 866490075Sobrien "#" 866590075Sobrien [(set_attr "conds" "clob") 866690075Sobrien (set_attr "length" "12")] 866790075Sobrien) 866890075Sobrien 866990075Sobrien(define_insn "*if_shift_shift" 867090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 867190075Sobrien (if_then_else:SI 867290075Sobrien (match_operator 5 "arm_comparison_operator" 867390075Sobrien [(match_operand 8 "cc_register" "") (const_int 0)]) 867490075Sobrien (match_operator:SI 6 "shift_operator" 867590075Sobrien [(match_operand:SI 1 "s_register_operand" "r") 867690075Sobrien (match_operand:SI 2 "arm_rhs_operand" "rM")]) 867790075Sobrien (match_operator:SI 7 "shift_operator" 867890075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 867990075Sobrien (match_operand:SI 4 "arm_rhs_operand" "rM")])))] 868090075Sobrien "TARGET_ARM" 868190075Sobrien "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" 868290075Sobrien [(set_attr "conds" "use") 868390075Sobrien (set_attr "shift" "1") 868490075Sobrien (set_attr "length" "8")] 868590075Sobrien) 868690075Sobrien 868790075Sobrien(define_insn "*ifcompare_not_arith" 868890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 868990075Sobrien (if_then_else:SI 869090075Sobrien (match_operator 6 "arm_comparison_operator" 869190075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 869290075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL")]) 869390075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r")) 869490075Sobrien (match_operator:SI 7 "shiftable_operator" 869590075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 869690075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI")]))) 869790075Sobrien (clobber (reg:CC CC_REGNUM))] 869890075Sobrien "TARGET_ARM" 869990075Sobrien "#" 870090075Sobrien [(set_attr "conds" "clob") 870190075Sobrien (set_attr "length" "12")] 870290075Sobrien) 870390075Sobrien 870490075Sobrien(define_insn "*if_not_arith" 870590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 870690075Sobrien (if_then_else:SI 870790075Sobrien (match_operator 5 "arm_comparison_operator" 870890075Sobrien [(match_operand 4 "cc_register" "") (const_int 0)]) 870990075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r")) 871090075Sobrien (match_operator:SI 6 "shiftable_operator" 871190075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 871290075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI")])))] 871390075Sobrien "TARGET_ARM" 871490075Sobrien "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" 871590075Sobrien [(set_attr "conds" "use") 871690075Sobrien (set_attr "length" "8")] 871790075Sobrien) 871890075Sobrien 871990075Sobrien(define_insn "*ifcompare_arith_not" 872090075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 872190075Sobrien (if_then_else:SI 872290075Sobrien (match_operator 6 "arm_comparison_operator" 872390075Sobrien [(match_operand:SI 4 "s_register_operand" "r") 872490075Sobrien (match_operand:SI 5 "arm_add_operand" "rIL")]) 872590075Sobrien (match_operator:SI 7 "shiftable_operator" 872690075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 872790075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI")]) 872890075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r")))) 872990075Sobrien (clobber (reg:CC CC_REGNUM))] 873090075Sobrien "TARGET_ARM" 873190075Sobrien "#" 873290075Sobrien [(set_attr "conds" "clob") 873390075Sobrien (set_attr "length" "12")] 873490075Sobrien) 873590075Sobrien 873690075Sobrien(define_insn "*if_arith_not" 873790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 873890075Sobrien (if_then_else:SI 873990075Sobrien (match_operator 5 "arm_comparison_operator" 874090075Sobrien [(match_operand 4 "cc_register" "") (const_int 0)]) 874190075Sobrien (match_operator:SI 6 "shiftable_operator" 874290075Sobrien [(match_operand:SI 2 "s_register_operand" "r") 874390075Sobrien (match_operand:SI 3 "arm_rhs_operand" "rI")]) 874490075Sobrien (not:SI (match_operand:SI 1 "s_register_operand" "r"))))] 874590075Sobrien "TARGET_ARM" 874690075Sobrien "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" 874790075Sobrien [(set_attr "conds" "use") 874890075Sobrien (set_attr "length" "8")] 874990075Sobrien) 875090075Sobrien 875190075Sobrien(define_insn "*ifcompare_neg_move" 875290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 875390075Sobrien (if_then_else:SI 875490075Sobrien (match_operator 5 "arm_comparison_operator" 875590075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r") 875690075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 875790075Sobrien (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) 875890075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) 875990075Sobrien (clobber (reg:CC CC_REGNUM))] 876090075Sobrien "TARGET_ARM" 876190075Sobrien "#" 876290075Sobrien [(set_attr "conds" "clob") 876390075Sobrien (set_attr "length" "8,12")] 876490075Sobrien) 876590075Sobrien 876690075Sobrien(define_insn "*if_neg_move" 876790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 876890075Sobrien (if_then_else:SI 876990075Sobrien (match_operator 4 "arm_comparison_operator" 877090075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 877190075Sobrien (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r")) 877290075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))] 877390075Sobrien "TARGET_ARM" 877490075Sobrien "@ 877590075Sobrien rsb%d4\\t%0, %2, #0 877690075Sobrien mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0 877790075Sobrien mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0" 877890075Sobrien [(set_attr "conds" "use") 877990075Sobrien (set_attr "length" "4,8,8")] 878090075Sobrien) 878190075Sobrien 878290075Sobrien(define_insn "*ifcompare_move_neg" 878390075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 878490075Sobrien (if_then_else:SI 878590075Sobrien (match_operator 5 "arm_comparison_operator" 878690075Sobrien [(match_operand:SI 3 "s_register_operand" "r,r") 878790075Sobrien (match_operand:SI 4 "arm_add_operand" "rIL,rIL")]) 878890075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rIK") 878990075Sobrien (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) 879090075Sobrien (clobber (reg:CC CC_REGNUM))] 879190075Sobrien "TARGET_ARM" 879290075Sobrien "#" 879390075Sobrien [(set_attr "conds" "clob") 879490075Sobrien (set_attr "length" "8,12")] 879590075Sobrien) 879690075Sobrien 879790075Sobrien(define_insn "*if_move_neg" 879890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 879990075Sobrien (if_then_else:SI 880090075Sobrien (match_operator 4 "arm_comparison_operator" 880190075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 880290075Sobrien (match_operand:SI 1 "arm_not_operand" "0,?rI,K") 880390075Sobrien (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))] 880490075Sobrien "TARGET_ARM" 880590075Sobrien "@ 880690075Sobrien rsb%D4\\t%0, %2, #0 880790075Sobrien mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0 880890075Sobrien mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0" 880990075Sobrien [(set_attr "conds" "use") 881090075Sobrien (set_attr "length" "4,8,8")] 881190075Sobrien) 881290075Sobrien 881390075Sobrien(define_insn "*arith_adjacentmem" 881490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 881590075Sobrien (match_operator:SI 1 "shiftable_operator" 881690075Sobrien [(match_operand:SI 2 "memory_operand" "m") 881790075Sobrien (match_operand:SI 3 "memory_operand" "m")])) 881890075Sobrien (clobber (match_scratch:SI 4 "=r"))] 881990075Sobrien "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])" 882090075Sobrien "* 882190075Sobrien { 882290075Sobrien rtx ldm[3]; 882390075Sobrien rtx arith[4]; 882490075Sobrien int val1 = 0, val2 = 0; 882590075Sobrien 882690075Sobrien if (REGNO (operands[0]) > REGNO (operands[4])) 882790075Sobrien { 882890075Sobrien ldm[1] = operands[4]; 882990075Sobrien ldm[2] = operands[0]; 883090075Sobrien } 883190075Sobrien else 883290075Sobrien { 883390075Sobrien ldm[1] = operands[0]; 883490075Sobrien ldm[2] = operands[4]; 883590075Sobrien } 883690075Sobrien if (GET_CODE (XEXP (operands[2], 0)) != REG) 883790075Sobrien val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1)); 883890075Sobrien if (GET_CODE (XEXP (operands[3], 0)) != REG) 883990075Sobrien val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); 884090075Sobrien arith[0] = operands[0]; 884190075Sobrien arith[3] = operands[1]; 884290075Sobrien if (val1 < val2) 884390075Sobrien { 884490075Sobrien arith[1] = ldm[1]; 884590075Sobrien arith[2] = ldm[2]; 884690075Sobrien } 884790075Sobrien else 884890075Sobrien { 884990075Sobrien arith[1] = ldm[2]; 885090075Sobrien arith[2] = ldm[1]; 885190075Sobrien } 885290075Sobrien if (val1 && val2) 885390075Sobrien { 885490075Sobrien rtx ops[3]; 885590075Sobrien ldm[0] = ops[0] = operands[4]; 885690075Sobrien ops[1] = XEXP (XEXP (operands[2], 0), 0); 885790075Sobrien ops[2] = XEXP (XEXP (operands[2], 0), 1); 885890075Sobrien output_add_immediate (ops); 885990075Sobrien if (val1 < val2) 886090075Sobrien output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 886190075Sobrien else 886290075Sobrien output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 886390075Sobrien } 886490075Sobrien else if (val1) 886590075Sobrien { 886690075Sobrien ldm[0] = XEXP (operands[3], 0); 886790075Sobrien if (val1 < val2) 886890075Sobrien output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 886990075Sobrien else 887090075Sobrien output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 887190075Sobrien } 887290075Sobrien else 887390075Sobrien { 887490075Sobrien ldm[0] = XEXP (operands[2], 0); 887590075Sobrien if (val1 < val2) 887690075Sobrien output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm); 887790075Sobrien else 887890075Sobrien output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); 887990075Sobrien } 888090075Sobrien output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith); 888190075Sobrien return \"\"; 888290075Sobrien }" 888390075Sobrien [(set_attr "length" "12") 888490075Sobrien (set_attr "predicable" "yes") 888590075Sobrien (set_attr "type" "load")] 888690075Sobrien) 888790075Sobrien 888890075Sobrien;; the arm can support extended pre-inc instructions 888990075Sobrien 889090075Sobrien;; In all these cases, we use operands 0 and 1 for the register being 889190075Sobrien;; incremented because those are the operands that local-alloc will 889290075Sobrien;; tie and these are the pair most likely to be tieable (and the ones 889390075Sobrien;; that will benefit the most). 889490075Sobrien 889590075Sobrien;; We reject the frame pointer if it occurs anywhere in these patterns since 889690075Sobrien;; elimination will cause too many headaches. 889790075Sobrien 889890075Sobrien(define_insn "*strqi_preinc" 889990075Sobrien [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 890090075Sobrien (match_operand:SI 2 "index_operand" "rJ"))) 890190075Sobrien (match_operand:QI 3 "s_register_operand" "r")) 890290075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 890390075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 890490075Sobrien "TARGET_ARM 890590075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 890690075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 890790075Sobrien && (GET_CODE (operands[2]) != REG 890890075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 890990075Sobrien "str%?b\\t%3, [%0, %2]!" 891090075Sobrien [(set_attr "type" "store1") 891190075Sobrien (set_attr "predicable" "yes")] 891290075Sobrien) 891390075Sobrien 891490075Sobrien(define_insn "*strqi_predec" 891590075Sobrien [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 891690075Sobrien (match_operand:SI 2 "s_register_operand" "r"))) 891790075Sobrien (match_operand:QI 3 "s_register_operand" "r")) 891890075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 891990075Sobrien (minus:SI (match_dup 1) (match_dup 2)))] 892090075Sobrien "TARGET_ARM 892190075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 892290075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 892390075Sobrien && (GET_CODE (operands[2]) != REG 892490075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 892590075Sobrien "str%?b\\t%3, [%0, -%2]!" 892690075Sobrien [(set_attr "type" "store1") 892790075Sobrien (set_attr "predicable" "yes")] 892890075Sobrien) 892990075Sobrien 893090075Sobrien(define_insn "*loadqi_preinc" 893190075Sobrien [(set (match_operand:QI 3 "s_register_operand" "=r") 893290075Sobrien (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 893390075Sobrien (match_operand:SI 2 "index_operand" "rJ")))) 893490075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 893590075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 893690075Sobrien "TARGET_ARM 893790075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 893890075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 893990075Sobrien && (GET_CODE (operands[2]) != REG 894090075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 894190075Sobrien "ldr%?b\\t%3, [%0, %2]!" 894290075Sobrien [(set_attr "type" "load") 894390075Sobrien (set_attr "predicable" "yes")] 894490075Sobrien) 894590075Sobrien 894690075Sobrien(define_insn "*loadqi_predec" 894790075Sobrien [(set (match_operand:QI 3 "s_register_operand" "=r") 894890075Sobrien (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 894990075Sobrien (match_operand:SI 2 "s_register_operand" "r")))) 895090075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 895190075Sobrien (minus:SI (match_dup 1) (match_dup 2)))] 895290075Sobrien "TARGET_ARM 895390075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 895490075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 895590075Sobrien && (GET_CODE (operands[2]) != REG 895690075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 895790075Sobrien "ldr%?b\\t%3, [%0, -%2]!" 895890075Sobrien [(set_attr "type" "load") 895990075Sobrien (set_attr "predicable" "yes")] 896090075Sobrien) 896190075Sobrien 896290075Sobrien(define_insn "*loadqisi_preinc" 896390075Sobrien [(set (match_operand:SI 3 "s_register_operand" "=r") 896490075Sobrien (zero_extend:SI 896590075Sobrien (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 896690075Sobrien (match_operand:SI 2 "index_operand" "rJ"))))) 896790075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 896890075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 896990075Sobrien "TARGET_ARM 897090075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 897190075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 897290075Sobrien && (GET_CODE (operands[2]) != REG 897390075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 897490075Sobrien "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi" 897590075Sobrien [(set_attr "type" "load") 897690075Sobrien (set_attr "predicable" "yes")] 897790075Sobrien) 897890075Sobrien 897990075Sobrien(define_insn "*loadqisi_predec" 898090075Sobrien [(set (match_operand:SI 3 "s_register_operand" "=r") 898190075Sobrien (zero_extend:SI 898290075Sobrien (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 898390075Sobrien (match_operand:SI 2 "s_register_operand" "r"))))) 898490075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 898590075Sobrien (minus:SI (match_dup 1) (match_dup 2)))] 898690075Sobrien "TARGET_ARM 898790075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 898890075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 898990075Sobrien && (GET_CODE (operands[2]) != REG 899090075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 899190075Sobrien "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi" 899290075Sobrien [(set_attr "type" "load") 899390075Sobrien (set_attr "predicable" "yes")] 899490075Sobrien) 899590075Sobrien 899690075Sobrien(define_insn "*strsi_preinc" 899790075Sobrien [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 899890075Sobrien (match_operand:SI 2 "index_operand" "rJ"))) 899990075Sobrien (match_operand:SI 3 "s_register_operand" "r")) 900090075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 900190075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 900290075Sobrien "TARGET_ARM 900390075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 900490075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 900590075Sobrien && (GET_CODE (operands[2]) != REG 900690075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 900790075Sobrien "str%?\\t%3, [%0, %2]!" 900890075Sobrien [(set_attr "type" "store1") 900990075Sobrien (set_attr "predicable" "yes")] 901090075Sobrien) 901190075Sobrien 901290075Sobrien(define_insn "*strsi_predec" 901390075Sobrien [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 901490075Sobrien (match_operand:SI 2 "s_register_operand" "r"))) 901590075Sobrien (match_operand:SI 3 "s_register_operand" "r")) 901690075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 901790075Sobrien (minus:SI (match_dup 1) (match_dup 2)))] 901890075Sobrien "TARGET_ARM 901990075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 902090075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 902190075Sobrien && (GET_CODE (operands[2]) != REG 902290075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 902390075Sobrien "str%?\\t%3, [%0, -%2]!" 902490075Sobrien [(set_attr "type" "store1") 902590075Sobrien (set_attr "predicable" "yes")] 902690075Sobrien) 902790075Sobrien 902890075Sobrien(define_insn "*loadsi_preinc" 902990075Sobrien [(set (match_operand:SI 3 "s_register_operand" "=r") 903090075Sobrien (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 903190075Sobrien (match_operand:SI 2 "index_operand" "rJ")))) 903290075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 903390075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 903490075Sobrien "TARGET_ARM 903590075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 903690075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 903790075Sobrien && (GET_CODE (operands[2]) != REG 903890075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 903990075Sobrien "ldr%?\\t%3, [%0, %2]!" 904090075Sobrien [(set_attr "type" "load") 904190075Sobrien (set_attr "predicable" "yes")] 904290075Sobrien) 904390075Sobrien 904490075Sobrien(define_insn "*loadsi_predec" 904590075Sobrien [(set (match_operand:SI 3 "s_register_operand" "=r") 904690075Sobrien (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 904790075Sobrien (match_operand:SI 2 "s_register_operand" "r")))) 904890075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 904990075Sobrien (minus:SI (match_dup 1) (match_dup 2)))] 905090075Sobrien "TARGET_ARM 905190075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 905290075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 905390075Sobrien && (GET_CODE (operands[2]) != REG 905490075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 905590075Sobrien "ldr%?\\t%3, [%0, -%2]!" 905690075Sobrien [(set_attr "type" "load") 905790075Sobrien (set_attr "predicable" "yes")] 905890075Sobrien) 905990075Sobrien 906090075Sobrien(define_insn "*loadhi_preinc" 906190075Sobrien [(set (match_operand:HI 3 "s_register_operand" "=r") 906290075Sobrien (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 906390075Sobrien (match_operand:SI 2 "index_operand" "rJ")))) 906490075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 906590075Sobrien (plus:SI (match_dup 1) (match_dup 2)))] 906690075Sobrien "TARGET_ARM 906790075Sobrien && !BYTES_BIG_ENDIAN 906890075Sobrien && !TARGET_MMU_TRAPS 906990075Sobrien && !arm_arch4 907090075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 907196263Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 907290075Sobrien && (GET_CODE (operands[2]) != REG 907390075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 907490075Sobrien "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi" 907590075Sobrien [(set_attr "type" "load") 907690075Sobrien (set_attr "predicable" "yes")] 907790075Sobrien) 907890075Sobrien 907990075Sobrien(define_insn "*loadhi_predec" 908090075Sobrien [(set (match_operand:HI 3 "s_register_operand" "=r") 908190075Sobrien (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 908290075Sobrien (match_operand:SI 2 "s_register_operand" "r")))) 908390075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 908490075Sobrien (minus:SI (match_dup 1) (match_dup 2)))] 908590075Sobrien "TARGET_ARM 908690075Sobrien && !BYTES_BIG_ENDIAN 908790075Sobrien && !TARGET_MMU_TRAPS 908890075Sobrien && !arm_arch4 908990075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 909096263Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 909190075Sobrien && (GET_CODE (operands[2]) != REG 909290075Sobrien || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" 909390075Sobrien "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi" 909490075Sobrien [(set_attr "type" "load") 909590075Sobrien (set_attr "predicable" "yes")] 909690075Sobrien) 909790075Sobrien 909890075Sobrien(define_insn "*strqi_shiftpreinc" 909990075Sobrien [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 910090075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 910190075Sobrien (match_operand:SI 4 "const_shift_operand" "n")]) 910290075Sobrien (match_operand:SI 1 "s_register_operand" "0"))) 910390075Sobrien (match_operand:QI 5 "s_register_operand" "r")) 910490075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 910590075Sobrien (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 910690075Sobrien (match_dup 1)))] 910790075Sobrien "TARGET_ARM 910890075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 910990075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 911090075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 911190075Sobrien "str%?b\\t%5, [%0, %3%S2]!" 911290075Sobrien [(set_attr "type" "store1") 911390075Sobrien (set_attr "predicable" "yes")] 911490075Sobrien) 911590075Sobrien 911690075Sobrien(define_insn "*strqi_shiftpredec" 911790075Sobrien [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 911890075Sobrien (match_operator:SI 2 "shift_operator" 911990075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 912090075Sobrien (match_operand:SI 4 "const_shift_operand" "n")]))) 912190075Sobrien (match_operand:QI 5 "s_register_operand" "r")) 912290075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 912390075Sobrien (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 912490075Sobrien (match_dup 4)])))] 912590075Sobrien "TARGET_ARM 912690075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 912790075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 912890075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 912990075Sobrien "str%?b\\t%5, [%0, -%3%S2]!" 913090075Sobrien [(set_attr "type" "store1") 913190075Sobrien (set_attr "predicable" "yes")] 913290075Sobrien) 913390075Sobrien 913490075Sobrien(define_insn "*loadqi_shiftpreinc" 913590075Sobrien [(set (match_operand:QI 5 "s_register_operand" "=r") 913690075Sobrien (mem:QI (plus:SI (match_operator:SI 2 "shift_operator" 913790075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 913890075Sobrien (match_operand:SI 4 "const_shift_operand" "n")]) 913990075Sobrien (match_operand:SI 1 "s_register_operand" "0")))) 914090075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 914190075Sobrien (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 914290075Sobrien (match_dup 1)))] 914390075Sobrien "TARGET_ARM 914490075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 914590075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 914690075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 914790075Sobrien "ldr%?b\\t%5, [%0, %3%S2]!" 914890075Sobrien [(set_attr "type" "load") 914990075Sobrien (set_attr "predicable" "yes")] 915090075Sobrien) 915190075Sobrien 915290075Sobrien(define_insn "*loadqi_shiftpredec" 915390075Sobrien [(set (match_operand:QI 5 "s_register_operand" "=r") 915490075Sobrien (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 915590075Sobrien (match_operator:SI 2 "shift_operator" 915690075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 915790075Sobrien (match_operand:SI 4 "const_shift_operand" "n")])))) 915890075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 915990075Sobrien (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 916090075Sobrien (match_dup 4)])))] 916190075Sobrien "TARGET_ARM 916290075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 916390075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 916490075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 916590075Sobrien "ldr%?b\\t%5, [%0, -%3%S2]!" 916690075Sobrien [(set_attr "type" "load") 916790075Sobrien (set_attr "predicable" "yes")] 916890075Sobrien) 916990075Sobrien 917090075Sobrien(define_insn "*strsi_shiftpreinc" 917190075Sobrien [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 917290075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 917390075Sobrien (match_operand:SI 4 "const_shift_operand" "n")]) 917490075Sobrien (match_operand:SI 1 "s_register_operand" "0"))) 917590075Sobrien (match_operand:SI 5 "s_register_operand" "r")) 917690075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 917790075Sobrien (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 917890075Sobrien (match_dup 1)))] 917990075Sobrien "TARGET_ARM 918090075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 918190075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 918290075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 918390075Sobrien "str%?\\t%5, [%0, %3%S2]!" 918490075Sobrien [(set_attr "type" "store1") 918590075Sobrien (set_attr "predicable" "yes")] 918690075Sobrien) 918790075Sobrien 918890075Sobrien(define_insn "*strsi_shiftpredec" 918990075Sobrien [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 919090075Sobrien (match_operator:SI 2 "shift_operator" 919190075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 919290075Sobrien (match_operand:SI 4 "const_shift_operand" "n")]))) 919390075Sobrien (match_operand:SI 5 "s_register_operand" "r")) 919490075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 919590075Sobrien (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 919690075Sobrien (match_dup 4)])))] 919790075Sobrien "TARGET_ARM 919890075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 919990075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 920090075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 920190075Sobrien "str%?\\t%5, [%0, -%3%S2]!" 920290075Sobrien [(set_attr "type" "store1") 920390075Sobrien (set_attr "predicable" "yes")] 920490075Sobrien) 920590075Sobrien 920690075Sobrien(define_insn "*loadsi_shiftpreinc" 920790075Sobrien [(set (match_operand:SI 5 "s_register_operand" "=r") 920890075Sobrien (mem:SI (plus:SI (match_operator:SI 2 "shift_operator" 920990075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 921090075Sobrien (match_operand:SI 4 "const_shift_operand" "n")]) 921190075Sobrien (match_operand:SI 1 "s_register_operand" "0")))) 921290075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 921390075Sobrien (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 921490075Sobrien (match_dup 1)))] 921590075Sobrien "TARGET_ARM 921690075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 921790075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 921890075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 921990075Sobrien "ldr%?\\t%5, [%0, %3%S2]!" 922090075Sobrien [(set_attr "type" "load") 922190075Sobrien (set_attr "predicable" "yes")] 922290075Sobrien) 922390075Sobrien 922490075Sobrien(define_insn "*loadsi_shiftpredec" 922590075Sobrien [(set (match_operand:SI 5 "s_register_operand" "=r") 922690075Sobrien (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 922790075Sobrien (match_operator:SI 2 "shift_operator" 922890075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 922990075Sobrien (match_operand:SI 4 "const_shift_operand" "n")])))) 923090075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 923190075Sobrien (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 923290075Sobrien (match_dup 4)])))] 923390075Sobrien "TARGET_ARM 923490075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 923590075Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 923690075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 923790075Sobrien "ldr%?\\t%5, [%0, -%3%S2]!" 923890075Sobrien [(set_attr "type" "load") 923990075Sobrien (set_attr "predicable" "yes")]) 924090075Sobrien 924190075Sobrien(define_insn "*loadhi_shiftpreinc" 924290075Sobrien [(set (match_operand:HI 5 "s_register_operand" "=r") 924390075Sobrien (mem:HI (plus:SI (match_operator:SI 2 "shift_operator" 924490075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 924590075Sobrien (match_operand:SI 4 "const_shift_operand" "n")]) 924690075Sobrien (match_operand:SI 1 "s_register_operand" "0")))) 924790075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 924890075Sobrien (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 924990075Sobrien (match_dup 1)))] 925090075Sobrien "TARGET_ARM 925190075Sobrien && !BYTES_BIG_ENDIAN 925290075Sobrien && !TARGET_MMU_TRAPS 925390075Sobrien && !arm_arch4 925490075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 925596263Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 925690075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 925790075Sobrien "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi" 925890075Sobrien [(set_attr "type" "load") 925990075Sobrien (set_attr "predicable" "yes")] 926090075Sobrien) 926190075Sobrien 926290075Sobrien(define_insn "*loadhi_shiftpredec" 926390075Sobrien [(set (match_operand:HI 5 "s_register_operand" "=r") 926490075Sobrien (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0") 926590075Sobrien (match_operator:SI 2 "shift_operator" 926690075Sobrien [(match_operand:SI 3 "s_register_operand" "r") 926790075Sobrien (match_operand:SI 4 "const_shift_operand" "n")])))) 926890075Sobrien (set (match_operand:SI 0 "s_register_operand" "=r") 926990075Sobrien (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 927090075Sobrien (match_dup 4)])))] 927190075Sobrien "TARGET_ARM 927290075Sobrien && !BYTES_BIG_ENDIAN 927390075Sobrien && !TARGET_MMU_TRAPS 927490075Sobrien && !arm_arch4 927590075Sobrien && REGNO (operands[0]) != FRAME_POINTER_REGNUM 927696263Sobrien && REGNO (operands[1]) != FRAME_POINTER_REGNUM 927790075Sobrien && REGNO (operands[3]) != FRAME_POINTER_REGNUM" 927890075Sobrien "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi" 927990075Sobrien [(set_attr "type" "load") 928090075Sobrien (set_attr "predicable" "yes")] 928190075Sobrien) 928290075Sobrien 928390075Sobrien; It can also support extended post-inc expressions, but combine doesn't 928490075Sobrien; try these.... 928590075Sobrien; It doesn't seem worth adding peepholes for anything but the most common 928690075Sobrien; cases since, unlike combine, the increment must immediately follow the load 928790075Sobrien; for this pattern to match. 928890075Sobrien; We must watch to see that the source/destination register isn't also the 928990075Sobrien; same as the base address register, and that if the index is a register, 929090075Sobrien; that it is not the same as the base address register. In such cases the 929190075Sobrien; instruction that we would generate would have UNPREDICTABLE behavior so 929290075Sobrien; we cannot use it. 9293117395Skan 929490075Sobrien(define_peephole 929590075Sobrien [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r")) 929690075Sobrien (match_operand:QI 2 "s_register_operand" "r")) 929790075Sobrien (set (match_dup 0) 929890075Sobrien (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 929990075Sobrien "TARGET_ARM 930090075Sobrien && (REGNO (operands[2]) != REGNO (operands[0])) 930190075Sobrien && (GET_CODE (operands[1]) != REG 930290075Sobrien || (REGNO (operands[1]) != REGNO (operands[0])))" 930390075Sobrien "str%?b\\t%2, [%0], %1" 930490075Sobrien) 930590075Sobrien 930690075Sobrien(define_peephole 930790075Sobrien [(set (match_operand:QI 0 "s_register_operand" "=r") 930890075Sobrien (mem:QI (match_operand:SI 1 "s_register_operand" "+r"))) 930990075Sobrien (set (match_dup 1) 931090075Sobrien (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 931190075Sobrien "TARGET_ARM 931290075Sobrien && REGNO (operands[0]) != REGNO(operands[1]) 931390075Sobrien && (GET_CODE (operands[2]) != REG 931490075Sobrien || REGNO(operands[0]) != REGNO (operands[2]))" 931590075Sobrien "ldr%?b\\t%0, [%1], %2" 931690075Sobrien) 931790075Sobrien 931890075Sobrien(define_peephole 931990075Sobrien [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r")) 932090075Sobrien (match_operand:SI 2 "s_register_operand" "r")) 932190075Sobrien (set (match_dup 0) 932290075Sobrien (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] 932390075Sobrien "TARGET_ARM 932490075Sobrien && (REGNO (operands[2]) != REGNO (operands[0])) 932590075Sobrien && (GET_CODE (operands[1]) != REG 932690075Sobrien || (REGNO (operands[1]) != REGNO (operands[0])))" 932790075Sobrien "str%?\\t%2, [%0], %1" 932890075Sobrien) 932990075Sobrien 933090075Sobrien(define_peephole 933190075Sobrien [(set (match_operand:HI 0 "s_register_operand" "=r") 933290075Sobrien (mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) 933390075Sobrien (set (match_dup 1) 933490075Sobrien (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 933590075Sobrien "TARGET_ARM 933690075Sobrien && !BYTES_BIG_ENDIAN 933790075Sobrien && !TARGET_MMU_TRAPS 933890075Sobrien && !arm_arch4 933990075Sobrien && REGNO (operands[0]) != REGNO(operands[1]) 934096263Sobrien && (GET_CODE (operands[2]) != REG 934190075Sobrien || REGNO(operands[0]) != REGNO (operands[2]))" 934290075Sobrien "ldr%?\\t%0, [%1], %2\\t%@ loadhi" 934390075Sobrien) 934490075Sobrien 934590075Sobrien(define_peephole 934690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 934790075Sobrien (mem:SI (match_operand:SI 1 "s_register_operand" "+r"))) 934890075Sobrien (set (match_dup 1) 934990075Sobrien (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] 935090075Sobrien "TARGET_ARM 935190075Sobrien && REGNO (operands[0]) != REGNO(operands[1]) 935290075Sobrien && (GET_CODE (operands[2]) != REG 935390075Sobrien || REGNO(operands[0]) != REGNO (operands[2]))" 935490075Sobrien "ldr%?\\t%0, [%1], %2" 935590075Sobrien) 935690075Sobrien 935790075Sobrien(define_peephole 935890075Sobrien [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r") 935990075Sobrien (match_operand:SI 1 "index_operand" "rJ"))) 936090075Sobrien (match_operand:QI 2 "s_register_operand" "r")) 936190075Sobrien (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] 936290075Sobrien "TARGET_ARM 936390075Sobrien && (REGNO (operands[2]) != REGNO (operands[0])) 936490075Sobrien && (GET_CODE (operands[1]) != REG 936590075Sobrien || (REGNO (operands[1]) != REGNO (operands[0])))" 936690075Sobrien "str%?b\\t%2, [%0, %1]!" 936790075Sobrien) 936890075Sobrien 936990075Sobrien(define_peephole 937090075Sobrien [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator" 937190075Sobrien [(match_operand:SI 0 "s_register_operand" "r") 937290075Sobrien (match_operand:SI 1 "const_int_operand" "n")]) 937390075Sobrien (match_operand:SI 2 "s_register_operand" "+r"))) 937490075Sobrien (match_operand:QI 3 "s_register_operand" "r")) 937590075Sobrien (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)]) 937690075Sobrien (match_dup 2)))] 937790075Sobrien "TARGET_ARM 937890075Sobrien && (REGNO (operands[3]) != REGNO (operands[2])) 937990075Sobrien && (REGNO (operands[0]) != REGNO (operands[2]))" 938090075Sobrien "str%?b\\t%3, [%2, %0%S4]!" 938190075Sobrien) 938290075Sobrien 938390075Sobrien; This pattern is never tried by combine, so do it as a peephole 938490075Sobrien 938590075Sobrien(define_peephole2 938690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 938790075Sobrien (match_operand:SI 1 "s_register_operand" "")) 938890075Sobrien (set (reg:CC CC_REGNUM) 938990075Sobrien (compare:CC (match_dup 1) (const_int 0)))] 939090075Sobrien "TARGET_ARM 939190075Sobrien && (!TARGET_CIRRUS 939290075Sobrien || (!cirrus_fp_register (operands[0], SImode) 9393132718Skan && !cirrus_fp_register (operands[1], SImode))) 9394132718Skan " 9395132718Skan [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) 939690075Sobrien (set (match_dup 0) (match_dup 1))])] 939790075Sobrien "" 939890075Sobrien) 939990075Sobrien 940090075Sobrien; Peepholes to spot possible load- and store-multiples, if the ordering is 940190075Sobrien; reversed, check that the memory references aren't volatile. 940290075Sobrien 940390075Sobrien(define_peephole 940490075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 940590075Sobrien (match_operand:SI 4 "memory_operand" "m")) 940690075Sobrien (set (match_operand:SI 1 "s_register_operand" "=r") 940790075Sobrien (match_operand:SI 5 "memory_operand" "m")) 940890075Sobrien (set (match_operand:SI 2 "s_register_operand" "=r") 940990075Sobrien (match_operand:SI 6 "memory_operand" "m")) 941090075Sobrien (set (match_operand:SI 3 "s_register_operand" "=r") 941190075Sobrien (match_operand:SI 7 "memory_operand" "m"))] 941290075Sobrien "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)" 941390075Sobrien "* 941490075Sobrien return emit_ldm_seq (operands, 4); 941590075Sobrien " 941690075Sobrien) 941790075Sobrien 941890075Sobrien(define_peephole 941990075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 942090075Sobrien (match_operand:SI 3 "memory_operand" "m")) 942190075Sobrien (set (match_operand:SI 1 "s_register_operand" "=r") 942290075Sobrien (match_operand:SI 4 "memory_operand" "m")) 942390075Sobrien (set (match_operand:SI 2 "s_register_operand" "=r") 942490075Sobrien (match_operand:SI 5 "memory_operand" "m"))] 942590075Sobrien "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)" 942690075Sobrien "* 942790075Sobrien return emit_ldm_seq (operands, 3); 942890075Sobrien " 942990075Sobrien) 943090075Sobrien 943190075Sobrien(define_peephole 943290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 943390075Sobrien (match_operand:SI 2 "memory_operand" "m")) 943490075Sobrien (set (match_operand:SI 1 "s_register_operand" "=r") 943590075Sobrien (match_operand:SI 3 "memory_operand" "m"))] 943690075Sobrien "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)" 943790075Sobrien "* 943890075Sobrien return emit_ldm_seq (operands, 2); 943990075Sobrien " 944090075Sobrien) 944190075Sobrien 944290075Sobrien(define_peephole 944390075Sobrien [(set (match_operand:SI 4 "memory_operand" "=m") 944490075Sobrien (match_operand:SI 0 "s_register_operand" "r")) 944590075Sobrien (set (match_operand:SI 5 "memory_operand" "=m") 944690075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 944790075Sobrien (set (match_operand:SI 6 "memory_operand" "=m") 944890075Sobrien (match_operand:SI 2 "s_register_operand" "r")) 944990075Sobrien (set (match_operand:SI 7 "memory_operand" "=m") 945090075Sobrien (match_operand:SI 3 "s_register_operand" "r"))] 945190075Sobrien "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)" 945290075Sobrien "* 945390075Sobrien return emit_stm_seq (operands, 4); 945490075Sobrien " 945590075Sobrien) 945690075Sobrien 945790075Sobrien(define_peephole 945890075Sobrien [(set (match_operand:SI 3 "memory_operand" "=m") 945990075Sobrien (match_operand:SI 0 "s_register_operand" "r")) 946090075Sobrien (set (match_operand:SI 4 "memory_operand" "=m") 946190075Sobrien (match_operand:SI 1 "s_register_operand" "r")) 946290075Sobrien (set (match_operand:SI 5 "memory_operand" "=m") 946390075Sobrien (match_operand:SI 2 "s_register_operand" "r"))] 946490075Sobrien "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)" 946590075Sobrien "* 946690075Sobrien return emit_stm_seq (operands, 3); 946790075Sobrien " 946890075Sobrien) 946990075Sobrien 947090075Sobrien(define_peephole 947190075Sobrien [(set (match_operand:SI 2 "memory_operand" "=m") 947290075Sobrien (match_operand:SI 0 "s_register_operand" "r")) 947390075Sobrien (set (match_operand:SI 3 "memory_operand" "=m") 947490075Sobrien (match_operand:SI 1 "s_register_operand" "r"))] 947590075Sobrien "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)" 947690075Sobrien "* 947790075Sobrien return emit_stm_seq (operands, 2); 947890075Sobrien " 947990075Sobrien) 948090075Sobrien 948190075Sobrien(define_split 948290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 948390075Sobrien (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "") 948490075Sobrien (const_int 0)) 948590075Sobrien (neg:SI (match_operator:SI 2 "arm_comparison_operator" 948690075Sobrien [(match_operand:SI 3 "s_register_operand" "") 948790075Sobrien (match_operand:SI 4 "arm_rhs_operand" "")])))) 948890075Sobrien (clobber (match_operand:SI 5 "s_register_operand" ""))] 948990075Sobrien "TARGET_ARM" 949090075Sobrien [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31)))) 949190075Sobrien (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) 949290075Sobrien (match_dup 5)))] 949390075Sobrien "" 949490075Sobrien) 949590075Sobrien 949690075Sobrien;; This split can be used because CC_Z mode implies that the following 949790075Sobrien;; branch will be an equality, or an unsigned inequality, so the sign 949890075Sobrien;; extension is not needed. 949990075Sobrien 950090075Sobrien(define_split 950190075Sobrien [(set (reg:CC_Z CC_REGNUM) 950290075Sobrien (compare:CC_Z 950390075Sobrien (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0) 950490075Sobrien (const_int 24)) 950590075Sobrien (match_operand 1 "const_int_operand" ""))) 950690075Sobrien (clobber (match_scratch:SI 2 ""))] 950790075Sobrien "TARGET_ARM 950890075Sobrien && (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) 950990075Sobrien == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)" 951090075Sobrien [(set (match_dup 2) (zero_extend:SI (match_dup 0))) 951190075Sobrien (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))] 951290075Sobrien " 951390075Sobrien operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24); 951490075Sobrien " 951590075Sobrien) 951690075Sobrien 951790075Sobrien(define_expand "prologue" 951890075Sobrien [(clobber (const_int 0))] 951990075Sobrien "TARGET_EITHER" 952090075Sobrien "if (TARGET_ARM) 952190075Sobrien arm_expand_prologue (); 952290075Sobrien else 952390075Sobrien thumb_expand_prologue (); 952490075Sobrien DONE; 952590075Sobrien " 952690075Sobrien) 952790075Sobrien 952890075Sobrien(define_expand "epilogue" 952990075Sobrien [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 953090075Sobrien "TARGET_EITHER" 953190075Sobrien " 953290075Sobrien if (TARGET_THUMB) 953390075Sobrien thumb_expand_epilogue (); 953490075Sobrien else if (USE_RETURN_INSN (FALSE)) 953590075Sobrien { 953690075Sobrien emit_jump_insn (gen_return ()); 953790075Sobrien DONE; 953890075Sobrien } 953990075Sobrien emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode, 954090075Sobrien gen_rtvec (1, 954190075Sobrien gen_rtx_RETURN (VOIDmode)), 954290075Sobrien VUNSPEC_EPILOGUE)); 954390075Sobrien DONE; 954490075Sobrien " 954590075Sobrien) 954690075Sobrien 954790075Sobrien;; Note - although unspec_volatile's USE all hard registers, 954890075Sobrien;; USEs are ignored after relaod has completed. Thus we need 9549117395Skan;; to add an unspec of the link register to ensure that flow 9550117395Skan;; does not think that it is unused by the sibcall branch that 9551117395Skan;; will replace the standard function epilogue. 9552117395Skan(define_insn "sibcall_epilogue" 9553117395Skan [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE) 955490075Sobrien (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])] 9555117395Skan "TARGET_ARM" 9556117395Skan "* 955790075Sobrien if (use_return_insn (FALSE, next_nonnote_insn (insn))) 955890075Sobrien return output_return_instruction (const_true_rtx, FALSE, FALSE); 9559132718Skan return arm_output_epilogue (next_nonnote_insn (insn)); 9560117395Skan " 9561132718Skan;; Length is absolute worst case 956290075Sobrien [(set_attr "length" "44") 956390075Sobrien (set_attr "type" "block") 956490075Sobrien ;; We don't clobber the conditions, but the potential length of this 9565117395Skan ;; operation is sufficient to make conditionalizing the sequence 9566117395Skan ;; unlikely to be profitable. 9567117395Skan (set_attr "conds" "clob")] 9568117395Skan) 9569117395Skan 957090075Sobrien(define_insn "*epilogue_insns" 957190075Sobrien [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 957290075Sobrien "TARGET_EITHER" 957390075Sobrien "* 957490075Sobrien if (TARGET_ARM) 957590075Sobrien return arm_output_epilogue (NULL); 957690075Sobrien else /* TARGET_THUMB */ 9577132718Skan return thumb_unexpanded_epilogue (); 957890075Sobrien " 957990075Sobrien ; Length is absolute worst case 958090075Sobrien [(set_attr "length" "44") 958190075Sobrien (set_attr "type" "block") 958290075Sobrien ;; We don't clobber the conditions, but the potential length of this 9583117395Skan ;; operation is sufficient to make conditionalizing the sequence 9584117395Skan ;; unlikely to be profitable. 9585117395Skan (set_attr "conds" "clob")] 9586117395Skan) 9587117395Skan 958890075Sobrien(define_expand "eh_epilogue" 958990075Sobrien [(use (match_operand:SI 0 "register_operand" "")) 959090075Sobrien (use (match_operand:SI 1 "register_operand" "")) 9591132718Skan (use (match_operand:SI 2 "register_operand" ""))] 9592132718Skan "TARGET_EITHER" 9593132718Skan " 959490075Sobrien { 959590075Sobrien cfun->machine->eh_epilogue_sp_ofs = operands[1]; 959690075Sobrien if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2) 959790075Sobrien { 959890075Sobrien rtx ra = gen_rtx_REG (Pmode, 2); 959990075Sobrien 960090075Sobrien emit_move_insn (ra, operands[2]); 960190075Sobrien operands[2] = ra; 960290075Sobrien } 960390075Sobrien /* This is a hack -- we may have crystalized the function type too 960490075Sobrien early. */ 960590075Sobrien cfun->machine->func_type = 0; 960690075Sobrien }" 960790075Sobrien) 960890075Sobrien 960990075Sobrien;; This split is only used during output to reduce the number of patterns 961090075Sobrien;; that need assembler instructions adding to them. We allowed the setting 961190075Sobrien;; of the conditions to be implicit during rtl generation so that 961290075Sobrien;; the conditional compare patterns would work. However this conflicts to 961390075Sobrien;; some extent with the conditional data operations, so we have to split them 961490075Sobrien;; up again here. 961590075Sobrien 961690075Sobrien(define_split 961790075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 961890075Sobrien (if_then_else:SI (match_operator 1 "arm_comparison_operator" 961990075Sobrien [(match_operand 2 "" "") (match_operand 3 "" "")]) 962090075Sobrien (match_dup 0) 962190075Sobrien (match_operand 4 "" ""))) 962290075Sobrien (clobber (reg:CC CC_REGNUM))] 962390075Sobrien "TARGET_ARM && reload_completed" 962490075Sobrien [(set (match_dup 5) (match_dup 6)) 962590075Sobrien (cond_exec (match_dup 7) 962690075Sobrien (set (match_dup 0) (match_dup 4)))] 962790075Sobrien " 962890075Sobrien { 962990075Sobrien enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 963090075Sobrien operands[2], operands[3]); 963190075Sobrien enum rtx_code rc = GET_CODE (operands[1]); 963290075Sobrien 963390075Sobrien operands[5] = gen_rtx_REG (mode, CC_REGNUM); 963490075Sobrien operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 963590075Sobrien if (mode == CCFPmode || mode == CCFPEmode) 963690075Sobrien rc = reverse_condition_maybe_unordered (rc); 963790075Sobrien else 963890075Sobrien rc = reverse_condition (rc); 963990075Sobrien 964090075Sobrien operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx); 964190075Sobrien }" 964290075Sobrien) 964390075Sobrien 964490075Sobrien(define_split 964590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 964690075Sobrien (if_then_else:SI (match_operator 1 "arm_comparison_operator" 964790075Sobrien [(match_operand 2 "" "") (match_operand 3 "" "")]) 964890075Sobrien (match_operand 4 "" "") 964990075Sobrien (match_dup 0))) 965090075Sobrien (clobber (reg:CC CC_REGNUM))] 965190075Sobrien "TARGET_ARM && reload_completed" 965290075Sobrien [(set (match_dup 5) (match_dup 6)) 965390075Sobrien (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)]) 965490075Sobrien (set (match_dup 0) (match_dup 4)))] 965590075Sobrien " 965690075Sobrien { 965790075Sobrien enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 965890075Sobrien operands[2], operands[3]); 965990075Sobrien 966090075Sobrien operands[5] = gen_rtx_REG (mode, CC_REGNUM); 966190075Sobrien operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 966290075Sobrien }" 966390075Sobrien) 966490075Sobrien 966590075Sobrien(define_split 966690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 966790075Sobrien (if_then_else:SI (match_operator 1 "arm_comparison_operator" 966890075Sobrien [(match_operand 2 "" "") (match_operand 3 "" "")]) 966990075Sobrien (match_operand 4 "" "") 967090075Sobrien (match_operand 5 "" ""))) 967190075Sobrien (clobber (reg:CC CC_REGNUM))] 967290075Sobrien "TARGET_ARM && reload_completed" 967390075Sobrien [(set (match_dup 6) (match_dup 7)) 967490075Sobrien (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 967590075Sobrien (set (match_dup 0) (match_dup 4))) 967690075Sobrien (cond_exec (match_dup 8) 967790075Sobrien (set (match_dup 0) (match_dup 5)))] 967890075Sobrien " 967990075Sobrien { 968090075Sobrien enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 968190075Sobrien operands[2], operands[3]); 968290075Sobrien enum rtx_code rc = GET_CODE (operands[1]); 968390075Sobrien 968490075Sobrien operands[6] = gen_rtx_REG (mode, CC_REGNUM); 968590075Sobrien operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]); 968690075Sobrien if (mode == CCFPmode || mode == CCFPEmode) 968790075Sobrien rc = reverse_condition_maybe_unordered (rc); 968890075Sobrien else 968990075Sobrien rc = reverse_condition (rc); 969090075Sobrien 969190075Sobrien operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 969290075Sobrien }" 969390075Sobrien) 969490075Sobrien 969590075Sobrien(define_split 969690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 969790075Sobrien (if_then_else:SI (match_operator 1 "arm_comparison_operator" 969890075Sobrien [(match_operand:SI 2 "s_register_operand" "") 969990075Sobrien (match_operand:SI 3 "arm_add_operand" "")]) 970090075Sobrien (match_operand:SI 4 "arm_rhs_operand" "") 970190075Sobrien (not:SI 970290075Sobrien (match_operand:SI 5 "s_register_operand" "")))) 970390075Sobrien (clobber (reg:CC CC_REGNUM))] 970490075Sobrien "TARGET_ARM && reload_completed" 970590075Sobrien [(set (match_dup 6) (match_dup 7)) 970690075Sobrien (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) 970790075Sobrien (set (match_dup 0) (match_dup 4))) 970890075Sobrien (cond_exec (match_dup 8) 970990075Sobrien (set (match_dup 0) (not:SI (match_dup 5))))] 971090075Sobrien " 971190075Sobrien { 971290075Sobrien enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), 971390075Sobrien operands[2], operands[3]); 971490075Sobrien enum rtx_code rc = GET_CODE (operands[1]); 971590075Sobrien 971690075Sobrien operands[6] = gen_rtx_REG (mode, CC_REGNUM); 971790075Sobrien operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]); 971890075Sobrien if (mode == CCFPmode || mode == CCFPEmode) 971990075Sobrien rc = reverse_condition_maybe_unordered (rc); 972090075Sobrien else 972190075Sobrien rc = reverse_condition (rc); 972290075Sobrien 972390075Sobrien operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); 972490075Sobrien }" 972590075Sobrien) 972690075Sobrien 972790075Sobrien(define_insn "*cond_move_not" 972890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r,r") 972990075Sobrien (if_then_else:SI (match_operator 4 "arm_comparison_operator" 973090075Sobrien [(match_operand 3 "cc_register" "") (const_int 0)]) 973190075Sobrien (match_operand:SI 1 "arm_rhs_operand" "0,?rI") 973290075Sobrien (not:SI 973390075Sobrien (match_operand:SI 2 "s_register_operand" "r,r"))))] 973490075Sobrien "TARGET_ARM" 973590075Sobrien "@ 973690075Sobrien mvn%D4\\t%0, %2 973790075Sobrien mov%d4\\t%0, %1\;mvn%D4\\t%0, %2" 973890075Sobrien [(set_attr "conds" "use") 973990075Sobrien (set_attr "length" "4,8")] 974090075Sobrien) 974190075Sobrien 974290075Sobrien;; The next two patterns occur when an AND operation is followed by a 974390075Sobrien;; scc insn sequence 974490075Sobrien 974590075Sobrien(define_insn "*sign_extract_onebit" 974690075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 974790075Sobrien (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 974890075Sobrien (const_int 1) 974990075Sobrien (match_operand:SI 2 "const_int_operand" "n"))) 975090075Sobrien (clobber (reg:CC CC_REGNUM))] 9751104752Skan "TARGET_ARM" 9752104752Skan "* 975390075Sobrien operands[2] = GEN_INT (1 << INTVAL (operands[2])); 975490075Sobrien output_asm_insn (\"ands\\t%0, %1, %2\", operands); 975590075Sobrien return \"mvnne\\t%0, #0\"; 975690075Sobrien " 975790075Sobrien [(set_attr "conds" "clob") 975890075Sobrien (set_attr "length" "8")] 975990075Sobrien) 976090075Sobrien 976190075Sobrien(define_insn "*not_signextract_onebit" 976290075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 976390075Sobrien (not:SI 976490075Sobrien (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") 976590075Sobrien (const_int 1) 976690075Sobrien (match_operand:SI 2 "const_int_operand" "n")))) 976790075Sobrien (clobber (reg:CC CC_REGNUM))] 9768104752Skan "TARGET_ARM" 9769104752Skan "* 977090075Sobrien operands[2] = GEN_INT (1 << INTVAL (operands[2])); 977190075Sobrien output_asm_insn (\"tst\\t%1, %2\", operands); 977290075Sobrien output_asm_insn (\"mvneq\\t%0, #0\", operands); 977390075Sobrien return \"movne\\t%0, #0\"; 977490075Sobrien " 977590075Sobrien [(set_attr "conds" "clob") 977690075Sobrien (set_attr "length" "12")] 977790075Sobrien) 977890075Sobrien 977990075Sobrien;; Push multiple registers to the stack. Registers are in parallel (use ...) 978090075Sobrien;; expressions. For simplicity, the first register is also in the unspec 978190075Sobrien;; part. 978290075Sobrien(define_insn "*push_multi" 978390075Sobrien [(match_parallel 2 "multi_register_push" 978490075Sobrien [(set (match_operand:BLK 0 "memory_operand" "=m") 978590075Sobrien (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 978690075Sobrien UNSPEC_PUSH_MULT))])] 978790075Sobrien "TARGET_ARM" 978890075Sobrien "* 978990075Sobrien { 979090075Sobrien int num_saves = XVECLEN (operands[2], 0); 979190075Sobrien 979290075Sobrien /* For the StrongARM at least it is faster to 979390075Sobrien use STR to store only a single register. */ 979490075Sobrien if (num_saves == 1) 979590075Sobrien output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands); 979690075Sobrien else 979790075Sobrien { 979890075Sobrien int i; 979990075Sobrien char pattern[100]; 980090075Sobrien 980190075Sobrien strcpy (pattern, \"stmfd\\t%m0!, {%1\"); 980290075Sobrien 980390075Sobrien for (i = 1; i < num_saves; i++) 980490075Sobrien { 980590075Sobrien strcat (pattern, \", %|\"); 980690075Sobrien strcat (pattern, 980790075Sobrien reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]); 980890075Sobrien } 980990075Sobrien 981090075Sobrien strcat (pattern, \"}\"); 981190075Sobrien output_asm_insn (pattern, operands); 981290075Sobrien } 981390075Sobrien 981490075Sobrien return \"\"; 981590075Sobrien }" 981690075Sobrien [(set_attr "type" "store4")] 981790075Sobrien) 981890075Sobrien 981990075Sobrien(define_insn "stack_tie" 982090075Sobrien [(set (mem:BLK (scratch)) 9821117395Skan (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r") 9822117395Skan (match_operand:SI 1 "s_register_operand" "r")] 9823117395Skan UNSPEC_PRLG_STK))] 9824117395Skan "" 9825117395Skan "" 9826117395Skan [(set_attr "length" "0")] 9827117395Skan) 9828117395Skan 9829117395Skan;; Similarly for the floating point registers 9830117395Skan(define_insn "*push_fp_multi" 983190075Sobrien [(match_parallel 2 "multi_register_push" 983290075Sobrien [(set (match_operand:BLK 0 "memory_operand" "=m") 983390075Sobrien (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 983490075Sobrien UNSPEC_PUSH_MULT))])] 983590075Sobrien "TARGET_ARM" 983690075Sobrien "* 983790075Sobrien { 983890075Sobrien char pattern[100]; 983990075Sobrien 984090075Sobrien sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0)); 984190075Sobrien output_asm_insn (pattern, operands); 984290075Sobrien return \"\"; 984390075Sobrien }" 984490075Sobrien [(set_attr "type" "f_store")] 984590075Sobrien) 984690075Sobrien 984790075Sobrien;; Special patterns for dealing with the constant pool 984890075Sobrien 984990075Sobrien(define_insn "align_4" 985090075Sobrien [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)] 985190075Sobrien "TARGET_EITHER" 985290075Sobrien "* 985390075Sobrien assemble_align (32); 985490075Sobrien return \"\"; 985590075Sobrien " 985690075Sobrien) 985790075Sobrien 985890075Sobrien(define_insn "align_8" 985990075Sobrien [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)] 9860132718Skan "TARGET_REALLY_IWMMXT" 9861132718Skan "* 9862132718Skan assemble_align (64); 9863132718Skan return \"\"; 9864132718Skan " 9865132718Skan) 9866132718Skan 9867132718Skan(define_insn "consttable_end" 9868132718Skan [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)] 986990075Sobrien "TARGET_EITHER" 987090075Sobrien "* 987190075Sobrien making_const_table = FALSE; 987290075Sobrien return \"\"; 987390075Sobrien " 987490075Sobrien) 987590075Sobrien 987690075Sobrien(define_insn "consttable_1" 987790075Sobrien [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)] 987890075Sobrien "TARGET_THUMB" 987990075Sobrien "* 988090075Sobrien making_const_table = TRUE; 988190075Sobrien assemble_integer (operands[0], 1, BITS_PER_WORD, 1); 988290075Sobrien assemble_zeros (3); 988390075Sobrien return \"\"; 988490075Sobrien " 988590075Sobrien [(set_attr "length" "4")] 988690075Sobrien) 988790075Sobrien 988890075Sobrien(define_insn "consttable_2" 988990075Sobrien [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)] 989090075Sobrien "TARGET_THUMB" 989190075Sobrien "* 989290075Sobrien making_const_table = TRUE; 989390075Sobrien assemble_integer (operands[0], 2, BITS_PER_WORD, 1); 989490075Sobrien assemble_zeros (2); 989590075Sobrien return \"\"; 989690075Sobrien " 989790075Sobrien [(set_attr "length" "4")] 989890075Sobrien) 989990075Sobrien 990090075Sobrien(define_insn "consttable_4" 990190075Sobrien [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)] 990290075Sobrien "TARGET_EITHER" 990390075Sobrien "* 990490075Sobrien { 990590075Sobrien making_const_table = TRUE; 990690075Sobrien switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 990790075Sobrien { 990890075Sobrien case MODE_FLOAT: 990990075Sobrien { 991090075Sobrien REAL_VALUE_TYPE r; 991190075Sobrien REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 9912117395Skan assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 9913117395Skan break; 9914117395Skan } 991590075Sobrien default: 991690075Sobrien assemble_integer (operands[0], 4, BITS_PER_WORD, 1); 991790075Sobrien break; 991890075Sobrien } 991990075Sobrien return \"\"; 992090075Sobrien }" 992190075Sobrien [(set_attr "length" "4")] 992290075Sobrien) 992390075Sobrien 992490075Sobrien(define_insn "consttable_8" 992590075Sobrien [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)] 992690075Sobrien "TARGET_EITHER" 992790075Sobrien "* 992890075Sobrien { 992990075Sobrien making_const_table = TRUE; 993090075Sobrien switch (GET_MODE_CLASS (GET_MODE (operands[0]))) 993190075Sobrien { 993290075Sobrien case MODE_FLOAT: 993390075Sobrien { 993490075Sobrien REAL_VALUE_TYPE r; 993590075Sobrien REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); 9936117395Skan assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); 9937117395Skan break; 9938117395Skan } 993990075Sobrien default: 994090075Sobrien assemble_integer (operands[0], 8, BITS_PER_WORD, 1); 994190075Sobrien break; 994290075Sobrien } 994390075Sobrien return \"\"; 994490075Sobrien }" 994590075Sobrien [(set_attr "length" "8")] 994690075Sobrien) 994790075Sobrien 994890075Sobrien;; Miscellaneous Thumb patterns 994990075Sobrien 995090075Sobrien(define_expand "tablejump" 995190075Sobrien [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "")) 995296263Sobrien (use (label_ref (match_operand 1 "" "")))])] 9953132718Skan "TARGET_THUMB" 995496263Sobrien " 995596263Sobrien if (flag_pic) 995696263Sobrien { 995796263Sobrien /* Hopefully, CSE will eliminate this copy. */ 995896263Sobrien rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); 995996263Sobrien rtx reg2 = gen_reg_rtx (SImode); 996096263Sobrien 996196263Sobrien emit_insn (gen_addsi3 (reg2, operands[0], reg1)); 996296263Sobrien operands[0] = reg2; 996396263Sobrien } 996496263Sobrien " 996596263Sobrien) 996696263Sobrien 996796263Sobrien(define_insn "*thumb_tablejump" 996896263Sobrien [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 996996263Sobrien (use (label_ref (match_operand 1 "" "")))] 997090075Sobrien "TARGET_THUMB" 997190075Sobrien "mov\\t%|pc, %0" 997290075Sobrien [(set_attr "length" "2")] 997396263Sobrien) 997490075Sobrien 997590075Sobrien;; V5 Instructions, 997690075Sobrien 997790075Sobrien(define_insn "clzsi2" 997890075Sobrien [(set (match_operand:SI 0 "s_register_operand" "=r") 9979132718Skan (clz:SI (match_operand:SI 1 "s_register_operand" "r")))] 9980132718Skan "TARGET_ARM && arm_arch5" 9981132718Skan "clz%?\\t%0, %1" 998290075Sobrien [(set_attr "predicable" "yes")]) 9983132718Skan 9984132718Skan(define_expand "ffssi2" 998590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 998690075Sobrien (ffs:SI (match_operand:SI 1 "s_register_operand" "")))] 998790075Sobrien "TARGET_ARM && arm_arch5" 998890075Sobrien " 998990075Sobrien { 999090075Sobrien rtx t1, t2, t3; 999190075Sobrien 999290075Sobrien t1 = gen_reg_rtx (SImode); 999390075Sobrien t2 = gen_reg_rtx (SImode); 999490075Sobrien t3 = gen_reg_rtx (SImode); 999590075Sobrien 999690075Sobrien emit_insn (gen_negsi2 (t1, operands[1])); 999790075Sobrien emit_insn (gen_andsi3 (t2, operands[1], t1)); 999890075Sobrien emit_insn (gen_clzsi2 (t3, t2)); 999990075Sobrien emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3)); 10000132718Skan DONE; 1000190075Sobrien }" 1000290075Sobrien) 1000390075Sobrien 1000490075Sobrien(define_expand "ctzsi2" 1000590075Sobrien [(set (match_operand:SI 0 "s_register_operand" "") 10006132718Skan (ctz:SI (match_operand:SI 1 "s_register_operand" "")))] 10007132718Skan "TARGET_ARM && arm_arch5" 10008132718Skan " 10009132718Skan { 10010132718Skan rtx t1, t2, t3; 10011132718Skan 10012132718Skan t1 = gen_reg_rtx (SImode); 10013132718Skan t2 = gen_reg_rtx (SImode); 10014132718Skan t3 = gen_reg_rtx (SImode); 10015132718Skan 10016132718Skan emit_insn (gen_negsi2 (t1, operands[1])); 10017132718Skan emit_insn (gen_andsi3 (t2, operands[1], t1)); 10018132718Skan emit_insn (gen_clzsi2 (t3, t2)); 10019132718Skan emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3)); 10020132718Skan DONE; 10021132718Skan }" 10022132718Skan) 10023132718Skan 10024132718Skan;; V5E instructions. 10025132718Skan 1002690075Sobrien(define_insn "prefetch" 1002790075Sobrien [(prefetch (match_operand:SI 0 "address_operand" "p") 1002890075Sobrien (match_operand:SI 1 "" "") 1002990075Sobrien (match_operand:SI 2 "" ""))] 1003090075Sobrien "TARGET_ARM && arm_arch5e" 1003190075Sobrien "pld\\t%a0") 1003290075Sobrien 1003390075Sobrien;; General predication pattern 1003490075Sobrien 1003590075Sobrien(define_cond_exec 1003690075Sobrien [(match_operator 0 "arm_comparison_operator" 1003790075Sobrien [(match_operand 1 "cc_register" "") 1003890075Sobrien (const_int 0)])] 1003990075Sobrien "TARGET_ARM" 1004090075Sobrien "" 1004190075Sobrien) 1004290075Sobrien 1004390075Sobrien(define_insn "prologue_use" 1004490075Sobrien [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)] 1004590075Sobrien "" 1004690075Sobrien "%@ %0 needed for prologue" 1004790075Sobrien) 1004890075Sobrien 1004990075Sobrien;; Load the FPA co-processor patterns 10050132718Skan(include "fpa.md") 10051132718Skan;; Load the Maverick co-processor patterns 10052132718Skan(include "cirrus.md") 10053132718Skan;; Load the Intel Wireless Multimedia Extension patterns 10054132718Skan(include "iwmmxt.md") 10055132718Skan