X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Fconfig%2Farm%2Farm.md;fp=gcc%2Fconfig%2Farm%2Farm.md;h=f2b7a7d1b8205d47ecf9ed3a96bf2a06230dd30b;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=5180c75933a2efd3cd2c9cac84b2dff646f38b06;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 5180c759..f2b7a7d1 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -1,49 +1,57 @@
;;- Machine description for ARM for GNU compiler
;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002 Free Software Foundation, Inc.
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+;; Free Software Foundation, Inc.
;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
;; and Martin Simmons (@harleqn.co.uk).
;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
-;; This file is part of GNU CC.
+;; This file is part of GCC.
-;; GNU CC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
-;; GNU CC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GCC; see the file COPYING3. If not see
+;; .
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
-;; There are patterns in this file to support XFmode arithmetic.
-;; Unfortunately RISC iX doesn't work well with these so they are disabled.
-;; (See arm.h)
;;---------------------------------------------------------------------------
;; Constants
;; Register numbers
(define_constants
- [(IP_REGNUM 12) ; Scratch register
+ [(R0_REGNUM 0) ; First CORE register
+ (IP_REGNUM 12) ; Scratch register
(SP_REGNUM 13) ; Stack pointer
(LR_REGNUM 14) ; Return address register
(PC_REGNUM 15) ; Program counter
(CC_REGNUM 24) ; Condition code pseudo register
- (LAST_ARM_REGNUM 15)
+ (LAST_ARM_REGNUM 15) ;
+ (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
+ (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
+ ]
+)
+;; 3rd operand to select_dominance_cc_mode
+(define_constants
+ [(DOM_CC_X_AND_Y 0)
+ (DOM_CC_NX_OR_Y 1)
+ (DOM_CC_X_OR_Y 2)
]
)
;; UNSPEC Usage:
;; Note: sin and cos are no-longer used.
+;; Unspec constants for Neon are defined in neon.md.
(define_constants
[(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
@@ -59,16 +67,38 @@
(UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
; usage, that is, we will add the pic_register
; value to it before trying to dereference it.
- (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
+ (UNSPEC_PIC_BASE 4) ; Add PC and all but the last operand together,
+ ; The last operand is the number of a PIC_LABEL
+ ; that points at the containing instruction.
+ (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
; being scheduled before the stack adjustment insn.
- (UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
- ; operand 0 is the result,
- ; operand 1 is the parameter.
(UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
; this unspec is used to prevent the deletion of
; instructions setting registers for EH handling
; and stack frame generation. Operand 0 is the
; register to "use".
+ (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
+ (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
+ (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
+ (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
+ (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
+ (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
+ (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
+ (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
+ (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
+ (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
+ (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
+ (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
+ (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
+ (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
+ (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
+ ; instruction stream.
+ (UNSPEC_STACK_ALIGN 22) ; Doubleword aligned stack pointer. Used to
+ ; generate correct unwind information.
+ (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
+ ; correctly for PIC usage.
+ (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
+ ; a given symbolic address.
]
)
@@ -93,6 +123,16 @@
; a 32-bit object.
(VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
; a 64-bit object.
+ (VUNSPEC_POOL_16 8) ; `pool-entry(16)'. An entry in the constant pool for
+ ; a 128-bit object.
+ (VUNSPEC_TMRC 9) ; Used by the iWMMXt TMRC instruction.
+ (VUNSPEC_TMCR 10) ; Used by the iWMMXt TMCR instruction.
+ (VUNSPEC_ALIGN8 11) ; 8-byte alignment version of VUNSPEC_ALIGN
+ (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions
+ (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
+ (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
+ (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
+ ; handling.
]
)
@@ -104,24 +144,22 @@
; patterns that share the same RTL in both ARM and Thumb code.
(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
-; PROG_MODE attribute is used to determine whether condition codes are
-; clobbered by a call insn: they are if in prog32 mode. This is controlled
-; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
-(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
-
; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
; scheduling decisions for the load unit and the multiplier.
-(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
+(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
+
+; IS_XSCALE is set to 'yes' when compiling for XScale.
+(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
;; Operand number of an input operand that is shifted. Zero if the
;; given instruction does not shift one of its input operands.
-(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
(define_attr "shift" "" (const_int 0))
; Floating Point Unit. If we only have floating point emulation, then there
; is no point in scheduling the floating point insns. (Well, for best
; performance we should try and group them together).
-(define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
+(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp,vfpv3d16,vfpv3,neon"
+ (const (symbol_ref "arm_fpu_attr")))
; LENGTH of an instruction (in bytes)
(define_attr "length" "" (const_int 4))
@@ -142,17 +180,31 @@
(set_attr "length" "4")
(set_attr "pool_range" "250")])
+;; The instruction used to implement a particular pattern. This
+;; information is used by pipeline descriptions to provide accurate
+;; scheduling information.
+
+(define_attr "insn"
+ "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
+ (const_string "other"))
+
; TYPE attribute is used to detect floating point instructions which, if
; running on a co-processor can run in parallel with other, basic instructions
; If write-buffer scheduling is enabled then it can also be used in the
; scheduling of writes.
; Classification of each insn
-; normal any data instruction that doesn't hit memory or fp regs
+; Note: vfp.md has different meanings for some of these, and some further
+; types as well. See that file for details.
+; alu any alu instruction that doesn't hit memory or fp
+; regs or have a shifted source operand
+; alu_shift any data instruction that doesn't hit memory or fp
+; regs, but has a source operand shifted by a constant
+; alu_shift_reg any data instruction that doesn't hit memory or fp
+; regs, but has a source operand shifted by a register value
; mult a multiply instruction
; block blockage insn, this blocks all functional units
; float a floating point arithmetic operation (subject to expansion)
-; fdivx XFmode floating point division
; fdivd DFmode floating point division
; fdivs SFmode floating point division
; fmul Floating point multiply
@@ -163,25 +215,110 @@
; even on a machine with an fpa.
; f_load a floating point load from memory
; f_store a floating point store to memory
+; f_load[sd] single/double load from memory
+; f_store[sd] single/double store to memory
+; f_flag a transfer of co-processor flags to the CPSR
; f_mem_r a transfer of a floating point register to a real reg via mem
; r_mem_f the reverse of f_mem_r
; f_2_r fast transfer float to arm (no memory needed)
; r_2_f fast transfer arm to float
+; f_cvt convert floating<->integral
+; branch a branch
; call a subroutine call
-; load any load from memory
-; store1 store 1 word to memory from arm registers
+; load_byte load byte(s) from memory to arm registers
+; load1 load 1 word from memory to arm registers
+; load2 load 2 words from memory to arm registers
+; load3 load 3 words from memory to arm registers
+; load4 load 4 words from memory to arm registers
+; store store 1 word to memory from arm registers
; store2 store 2 words
; store3 store 3 words
-; store4 store 4 words
+; store4 store 4 (or more) words
+; Additions for Cirrus Maverick co-processor:
+; mav_farith Floating point arithmetic (4 cycle)
+; mav_dmult Double multiplies (7 cycle)
;
+
(define_attr "type"
- "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"
- (const_string "normal"))
+ "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
+ (if_then_else
+ (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
+ (const_string "mult")
+ (const_string "alu")))
; Load scheduling, set from the arm_ld_sched variable
-; initialised by arm_override_options()
+; initialized by arm_override_options()
(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
+;; Classification of NEON instructions for scheduling purposes.
+;; Do not set this attribute and the "type" attribute together in
+;; any one instruction pattern.
+(define_attr "neon_type"
+ "neon_int_1,\
+ neon_int_2,\
+ neon_int_3,\
+ neon_int_4,\
+ neon_int_5,\
+ neon_vqneg_vqabs,\
+ neon_vmov,\
+ neon_vaba,\
+ neon_vsma,\
+ neon_vaba_qqq,\
+ neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
+ neon_mul_qqq_8_16_32_ddd_32,\
+ neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
+ neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
+ neon_mla_qqq_8_16,\
+ neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
+ neon_mla_qqq_32_qqd_32_scalar,\
+ neon_mul_ddd_16_scalar_32_16_long_scalar,\
+ neon_mul_qqd_32_scalar,\
+ neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
+ neon_shift_1,\
+ neon_shift_2,\
+ neon_shift_3,\
+ neon_vshl_ddd,\
+ neon_vqshl_vrshl_vqrshl_qqq,\
+ neon_vsra_vrsra,\
+ neon_fp_vadd_ddd_vabs_dd,\
+ neon_fp_vadd_qqq_vabs_qq,\
+ neon_fp_vsum,\
+ neon_fp_vmul_ddd,\
+ neon_fp_vmul_qqd,\
+ neon_fp_vmla_ddd,\
+ neon_fp_vmla_qqq,\
+ neon_fp_vmla_ddd_scalar,\
+ neon_fp_vmla_qqq_scalar,\
+ neon_fp_vrecps_vrsqrts_ddd,\
+ neon_fp_vrecps_vrsqrts_qqq,\
+ neon_bp_simple,\
+ neon_bp_2cycle,\
+ neon_bp_3cycle,\
+ neon_ldr,\
+ neon_str,\
+ neon_vld1_1_2_regs,\
+ neon_vld1_3_4_regs,\
+ neon_vld2_2_regs_vld1_vld2_all_lanes,\
+ neon_vld2_4_regs,\
+ neon_vld3_vld4,\
+ neon_vst1_1_2_regs_vst2_2_regs,\
+ neon_vst1_3_4_regs,\
+ neon_vst2_4_regs_vst3_vst4,\
+ neon_vst3_vst4,\
+ neon_vld1_vld2_lane,\
+ neon_vld3_vld4_lane,\
+ neon_vst1_vst2_lane,\
+ neon_vst3_vst4_lane,\
+ neon_vld3_vld4_all_lanes,\
+ neon_mcr,\
+ neon_mcr_2_mcrr,\
+ neon_mrc,\
+ neon_mrrc,\
+ neon_ldm_2,\
+ neon_stm_2,\
+ none"
+ (const_string "none"))
+
; condition codes: this one is used by final_prescan_insn to speed up
; conditionalizing instructions. It saves having to scan the rtl to see if
; it uses or alters the condition codes.
@@ -199,14 +336,17 @@
; JUMP_CLOB is used when the condition cannot be represented by a single
; instruction (UNEQ and LTGT). These cannot be predicated.
;
+; UNCONDITIONAL means the instions can not be conditionally executed.
+;
; NOCOND means that the condition codes are neither altered nor affect the
; output of this insn
-(define_attr "conds" "use,set,clob,jump_clob,nocond"
+(define_attr "conds" "use,set,clob,jump_clob,unconditional,nocond"
(if_then_else (eq_attr "type" "call")
- (if_then_else (eq_attr "prog_mode" "prog32")
- (const_string "clob") (const_string "nocond"))
- (const_string "nocond")))
+ (const_string "clob")
+ (if_then_else (eq_attr "neon_type" "none")
+ (const_string "nocond")
+ (const_string "unconditional"))))
; Predicable means that the insn can be conditionally executed based on
; an automatically added predicate (additional patterns are generated by
@@ -216,15 +356,15 @@
; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
; have one. Later ones, such as StrongARM, have write-back caches, so don't
-; suffer blockages enough to warrent modelling this (and it can adversely
+; suffer blockages enough to warrant modelling this (and it can adversely
; affect the schedule).
-(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
+(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
; WRITE_CONFLICT implies that a read following an unrelated write is likely
; to stall the processor. Used with model_wbuf above.
(define_attr "write_conflict" "no,yes"
(if_then_else (eq_attr "type"
- "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
+ "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
(const_string "yes")
(const_string "no")))
@@ -232,7 +372,7 @@
; than one on the main cpu execution unit.
(define_attr "core_cycles" "single,multi"
(if_then_else (eq_attr "type"
- "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
+ "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
(const_string "single")
(const_string "multi")))
@@ -240,157 +380,65 @@
;; distant label. Only applicable to Thumb code.
(define_attr "far_jump" "yes,no" (const_string "no"))
-;; (define_function_unit {name} {num-units} {n-users} {test}
-;; {ready-delay} {issue-delay} [{conflict-list}])
-
-;;--------------------------------------------------------------------
-;; Floating point unit (FPA)
-;;--------------------------------------------------------------------
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "fdivx")) 71 69)
-
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "fdivd")) 59 57)
-
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "fdivs")) 31 29)
-
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "fmul")) 9 7)
-
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "ffmul")) 6 4)
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "farith")) 4 2)
+;; The number of machine instructions this pattern expands to.
+;; Used for Thumb-2 conditional execution.
+(define_attr "ce_count" "" (const_int 1))
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "ffarith")) 2 2)
+;;---------------------------------------------------------------------------
+;; Mode iterators
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "r_2_f")) 5 3)
+; A list of modes that are exactly 64 bits in size. We use this to expand
+; some splits that are the same for all modes when operating on ARM
+; registers.
+(define_mode_iterator ANY64 [DI DF V8QI V4HI V2SI V2SF])
-(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "f_2_r")) 1 2)
+;;---------------------------------------------------------------------------
+;; Predicates
-; The fpa10 doesn't really have a memory read unit, but it can start to
-; speculatively execute the instruction in the pipeline, provided the data
-; is already loaded, so pretend reads have a delay of 2 (and that the
-; pipeline is infinite).
+(include "predicates.md")
+(include "constraints.md")
-(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
- (eq_attr "type" "f_load")) 3 1)
+;;---------------------------------------------------------------------------
+;; Pipeline descriptions
+
+;; Processor type. This is created automatically from arm-cores.def.
+(include "arm-tune.md")
+
+(define_attr "tune_cortexr4" "yes,no"
+ (const (if_then_else
+ (eq_attr "tune" "cortexr4,cortexr4f")
+ (const_string "yes")
+ (const_string "no"))))
+
+;; True if the generic scheduling description should be used.
+
+(define_attr "generic_sched" "yes,no"
+ (const (if_then_else
+ (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
+ (eq_attr "tune_cortexr4" "yes"))
+ (const_string "no")
+ (const_string "yes"))))
+
+(define_attr "generic_vfp" "yes,no"
+ (const (if_then_else
+ (and (eq_attr "fpu" "vfp")
+ (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9")
+ (eq_attr "tune_cortexr4" "no"))
+ (const_string "yes")
+ (const_string "no"))))
+
+(include "arm-generic.md")
+(include "arm926ejs.md")
+(include "arm1020e.md")
+(include "arm1026ejs.md")
+(include "arm1136jfs.md")
+(include "cortex-a8.md")
+(include "cortex-a9.md")
+(include "cortex-r4.md")
+(include "cortex-r4f.md")
+(include "vfp11.md")
-;;--------------------------------------------------------------------
-;; Write buffer
-;;--------------------------------------------------------------------
-; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
-;
-; The write buffer on some of the arm6 processors is hard to model exactly.
-; There is room in the buffer for up to two addresses and up to eight words
-; of memory, but the two needn't be split evenly. When writing the two
-; addresses are fully pipelined. However, a read from memory that is not
-; currently in the cache will block until the writes have completed.
-; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
-; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
-; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
-; cycle to add as well.
-
-(define_function_unit "write_buf" 1 2
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store1,r_mem_f")) 5 3)
-(define_function_unit "write_buf" 1 2
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store2")) 7 4)
-(define_function_unit "write_buf" 1 2
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store3")) 9 5)
-(define_function_unit "write_buf" 1 2
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store4")) 11 6)
-
-;;--------------------------------------------------------------------
-;; Write blockage unit
-;;--------------------------------------------------------------------
-; The write_blockage unit models (partially), the fact that reads will stall
-; until the write buffer empties.
-; The f_mem_r and r_mem_f could also block, but they are to the stack,
-; so we don't model them here
-(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store1")) 5 5
- [(eq_attr "write_conflict" "yes")])
-(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store2")) 7 7
- [(eq_attr "write_conflict" "yes")])
-(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store3")) 9 9
- [(eq_attr "write_conflict" "yes")])
-(define_function_unit "write_blockage" 1 0
- (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
- [(eq_attr "write_conflict" "yes")])
-(define_function_unit "write_blockage" 1 0
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "write_conflict" "yes")) 1 1)
-
-;;--------------------------------------------------------------------
-;; Core unit
-;;--------------------------------------------------------------------
-; Everything must spend at least one cycle in the core unit
-(define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
-
-;; We do not need to conditionalize the define_function_unit immediately
-;; above. This one will be ignored for anything other than xscale
-;; compiles and for xscale compiles it provides a larger delay
-;; and the scheduler will DTRT.
-;; FIXME: this test needs to be revamped to not depend on this feature
-;; of the scheduler.
-
-(define_function_unit "core" 1 0
- (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
- (eq_attr "is_xscale" "yes"))
- 3 1)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
-
-(define_function_unit "core" 1 0
- (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
- (eq_attr "type" "mult")) 4 4)
-
-(define_function_unit "core" 1 0
- (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
- (eq_attr "type" "mult")) 3 2)
-
-(define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
-
-(define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
-
-(define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
-
-(define_function_unit "core" 1 0
- (and (eq_attr "core_cycles" "multi")
- (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
;;---------------------------------------------------------------------------
;; Insn patterns
@@ -400,6 +448,8 @@
;; Note: For DImode insns, there is normally no reason why operands should
;; not be in the same register, what we don't want is for something being
;; written to partially overlap something that is an input.
+;; Cirrus 64bit additions should not be split because we have a native
+;; 64bit addition instructions.
(define_expand "adddi3"
[(parallel
@@ -409,23 +459,33 @@
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
"
- if (TARGET_THUMB)
+ if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
+ {
+ if (!cirrus_fp_register (operands[0], DImode))
+ operands[0] = force_reg (DImode, operands[0]);
+ if (!cirrus_fp_register (operands[1], DImode))
+ operands[1] = force_reg (DImode, operands[1]);
+ emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+
+ if (TARGET_THUMB1)
{
if (GET_CODE (operands[1]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
+ operands[1] = force_reg (DImode, operands[1]);
if (GET_CODE (operands[2]) != REG)
- operands[2] = force_reg (SImode, operands[2]);
+ operands[2] = force_reg (DImode, operands[2]);
}
"
)
-(define_insn "*thumb_adddi3"
+(define_insn "*thumb1_adddi3"
[(set (match_operand:DI 0 "register_operand" "=l")
(plus:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "l")))
(clobber (reg:CC CC_REGNUM))
]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
[(set_attr "length" "4")]
)
@@ -435,9 +495,9 @@
(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
(match_operand:DI 2 "s_register_operand" "r, 0")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
+ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
- "TARGET_ARM && reload_completed"
+ "TARGET_32BIT && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM)
(compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
(match_dup 1)))
@@ -463,9 +523,9 @@
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "r,0")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
+ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
- "TARGET_ARM && reload_completed"
+ "TARGET_32BIT && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM)
(compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
(match_dup 1)))
@@ -492,9 +552,9 @@
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "r,0")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
+ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
- "TARGET_ARM && reload_completed"
+ "TARGET_32BIT && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM)
(compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
(match_dup 1)))
@@ -519,24 +579,24 @@
(match_operand:SI 2 "reg_or_int_operand" "")))]
"TARGET_EITHER"
"
- if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
+ if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
{
- arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
- operands[1],
- (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
+ arm_split_constant (PLUS, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0], operands[1],
+ optimize && can_create_pseudo_p ());
DONE;
}
"
)
-; If there is a scratch available, this will be faster than synthesising the
+; If there is a scratch available, this will be faster than synthesizing the
; addition.
(define_peephole2
[(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "s_register_operand" "")
- (plus:SI (match_operand:SI 1 "s_register_operand" "")
+ (set (match_operand:SI 0 "arm_general_register_operand" "")
+ (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))]
- "TARGET_ARM &&
+ "TARGET_32BIT &&
!(const_ok_for_arm (INTVAL (operands[2]))
|| const_ok_for_arm (-INTVAL (operands[2])))
&& const_ok_for_arm (~INTVAL (operands[2]))"
@@ -545,26 +605,33 @@
""
)
+;; The r/r/k alternative is required when reloading the address
+;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
+;; put the duplicated register first, and not try the commutative version.
(define_insn_and_split "*arm_addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
- (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
- "TARGET_ARM"
+ [(set (match_operand:SI 0 "s_register_operand" "=r, !k, r,r, !k,r")
+ (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
+ (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
+ "TARGET_32BIT"
"@
add%?\\t%0, %1, %2
+ add%?\\t%0, %1, %2
+ add%?\\t%0, %2, %1
+ sub%?\\t%0, %1, #%n2
sub%?\\t%0, %1, #%n2
#"
- "TARGET_ARM &&
+ "TARGET_32BIT &&
GET_CODE (operands[2]) == CONST_INT
&& !(const_ok_for_arm (INTVAL (operands[2]))
|| const_ok_for_arm (-INTVAL (operands[2])))"
[(clobber (const_int 0))]
"
- arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
+ arm_split_constant (PLUS, SImode, curr_insn,
+ INTVAL (operands[2]), operands[0],
operands[1], 0);
DONE;
"
- [(set_attr "length" "4,4,16")
+ [(set_attr "length" "4,4,4,4,4,16")
(set_attr "predicable" "yes")]
)
@@ -572,11 +639,11 @@
;; register. Trying to reload it will always fail catastrophically,
;; so never allow those alternatives to match if reloading is needed.
-(define_insn "*thumb_addsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
+(define_insn "*thumb1_addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
- "TARGET_THUMB"
+ (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O")))]
+ "TARGET_THUMB1"
"*
static const char * const asms[] =
{
@@ -600,18 +667,18 @@
;; Reloading and elimination of the frame pointer can
;; sometimes cause this optimization to be missed.
(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
+ [(set (match_operand:SI 0 "arm_general_register_operand" "")
+ (match_operand:SI 1 "const_int_operand" ""))
(set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
- "TARGET_THUMB
- && REGNO (operands[2]) == STACK_POINTER_REGNUM
+ (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
+ "TARGET_THUMB1
&& (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
&& (INTVAL (operands[1]) & 3) == 0"
- [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
+ [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
""
)
+;; ??? Make Thumb-2 variants which prefer low regs
(define_insn "*addsi3_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV
@@ -620,10 +687,10 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
- add%?s\\t%0, %1, %2
- sub%?s\\t%0, %1, #%n2"
+ add%.\\t%0, %1, %2
+ sub%.\\t%0, %1, #%n2"
[(set_attr "conds" "set")]
)
@@ -633,40 +700,75 @@
(plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
(match_operand:SI 1 "arm_add_operand" "rI,L"))
(const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
cmn%?\\t%0, %1
cmp%?\\t%0, #%n1"
[(set_attr "conds" "set")]
)
-;; These patterns are the same ones as the two regular addsi3_compare0
-;; patterns, except we write them slightly different - the combiner
-;; tends to generate them this way.
-(define_insn "*addsi3_compare0_for_combiner"
+(define_insn "*compare_negsi_si"
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z
+ (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand:SI 1 "s_register_operand" "r")))]
+ "TARGET_32BIT"
+ "cmn%?\\t%1, %0"
+ [(set_attr "conds" "set")]
+)
+
+;; This is the canonicalization of addsi3_compare0_for_combiner when the
+;; addend is a constant.
+(define_insn "*cmpsi2_addneg"
[(set (reg:CC CC_REGNUM)
(compare:CC
(match_operand:SI 1 "s_register_operand" "r,r")
- (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
+ (match_operand:SI 2 "arm_addimm_operand" "I,L")))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
+ (plus:SI (match_dup 1)
+ (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
+ "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
"@
- add%?s\\t%0, %1, %2
- sub%?s\\t%0, %1, #%n2"
+ sub%.\\t%0, %1, %2
+ add%.\\t%0, %1, #%n2"
[(set_attr "conds" "set")]
)
-(define_insn "*addsi3_compare0_scratch_for_combiner"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (match_operand:SI 0 "s_register_operand" "r,r")
- (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
- "TARGET_ARM"
- "@
- cmn%?\\t%0, %1
- cmp%?\\t%0, #%n1"
- [(set_attr "conds" "set")]
+;; Convert the sequence
+;; sub rd, rn, #1
+;; cmn rd, #1 (equivalent to cmp rd, #-1)
+;; bne dest
+;; into
+;; subs rd, rn, #1
+;; bcs dest ((unsigned)rn >= 1)
+;; similarly for the beq variant using bcc.
+;; This is a common looping idiom (while (n--))
+(define_peephole2
+ [(set (match_operand:SI 0 "arm_general_register_operand" "")
+ (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
+ (const_int -1)))
+ (set (match_operand 2 "cc_register" "")
+ (compare (match_dup 0) (const_int -1)))
+ (set (pc)
+ (if_then_else (match_operator 3 "equality_operator"
+ [(match_dup 2) (const_int 0)])
+ (match_operand 4 "" "")
+ (match_operand 5 "" "")))]
+ "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
+ [(parallel[
+ (set (match_dup 2)
+ (compare:CC
+ (match_dup 1) (const_int 1)))
+ (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
+ (match_dup 4)
+ (match_dup 5)))]
+ "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
+ operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
+ ? GEU : LTU),
+ VOIDmode,
+ operands[2], const0_rtx);"
)
;; The next four insns work because they compare the result with one of
@@ -681,10 +783,10 @@
(match_dup 1)))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
- add%?s\\t%0, %1, %2
- sub%?s\\t%0, %1, #%n2"
+ add%.\\t%0, %1, %2
+ sub%.\\t%0, %1, #%n2"
[(set_attr "conds" "set")]
)
@@ -696,10 +798,10 @@
(match_dup 2)))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
- add%?s\\t%0, %1, %2
- sub%?s\\t%0, %1, #%n2"
+ add%.\\t%0, %1, %2
+ sub%.\\t%0, %1, #%n2"
[(set_attr "conds" "set")]
)
@@ -709,7 +811,7 @@
(plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
(match_operand:SI 1 "arm_add_operand" "rI,L"))
(match_dup 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
cmn%?\\t%0, %1
cmp%?\\t%0, #%n1"
@@ -722,7 +824,7 @@
(plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
(match_operand:SI 1 "arm_add_operand" "rI,L"))
(match_dup 1)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
cmn%?\\t%0, %1
cmp%?\\t%0, #%n1"
@@ -734,22 +836,25 @@
(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
(plus:SI (match_operand:SI 1 "s_register_operand" "r")
(match_operand:SI 2 "arm_rhs_operand" "rI"))))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"adc%?\\t%0, %1, %2"
[(set_attr "conds" "use")]
)
(define_insn "*addsi3_carryin_shift"
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
(plus:SI
(match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "")
- (match_operand:SI 4 "reg_or_int_operand" "")])
- (match_operand:SI 1 "s_register_operand" ""))))]
- "TARGET_ARM"
+ [(match_operand:SI 3 "s_register_operand" "r")
+ (match_operand:SI 4 "reg_or_int_operand" "rM")])
+ (match_operand:SI 1 "s_register_operand" "r"))))]
+ "TARGET_32BIT"
"adc%?\\t%0, %1, %3%S2"
- [(set_attr "conds" "use")]
+ [(set_attr "conds" "use")
+ (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*addsi3_carryin_alt1"
@@ -757,7 +862,7 @@
(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
(match_operand:SI 2 "arm_rhs_operand" "rI"))
(ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"adc%?\\t%0, %1, %2"
[(set_attr "conds" "use")]
)
@@ -767,7 +872,7 @@
(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
(match_operand:SI 1 "s_register_operand" "r"))
(match_operand:SI 2 "arm_rhs_operand" "rI")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"adc%?\\t%0, %1, %2"
[(set_attr "conds" "use")]
)
@@ -777,12 +882,21 @@
(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
(match_operand:SI 2 "arm_rhs_operand" "rI"))
(match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"adc%?\\t%0, %1, %2"
[(set_attr "conds" "use")]
)
-(define_insn "incscc"
+(define_expand "incscc"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (plus:SI (match_operator:SI 2 "arm_comparison_operator"
+ [(match_operand:CC 3 "cc_register" "") (const_int 0)])
+ (match_operand:SI 1 "s_register_operand" "0,?r")))]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*arm_incscc"
[(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (match_operator:SI 2 "arm_comparison_operator"
[(match_operand:CC 3 "cc_register" "") (const_int 0)])
@@ -795,77 +909,41 @@
(set_attr "length" "4,8")]
)
-(define_insn "addsf3"
- [(set (match_operand:SF 0 "s_register_operand" "=f,f")
- (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
- (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- adf%?s\\t%0, %1, %2
- suf%?s\\t%0, %1, #%N2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "adddf3"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
- (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- adf%?d\\t%0, %1, %2
- suf%?d\\t%0, %1, #%N2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*adddf_esfdf_df"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (plus:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f,f"))
- (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- adf%?d\\t%0, %1, %2
- suf%?d\\t%0, %1, #%N2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*adddf_df_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (plus:DF (match_operand:DF 1 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "adf%?d\\t%0, %1, %2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
+; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
+ (match_operand:SI 2 "s_register_operand" ""))
+ (const_int -1)))
+ (clobber (match_operand:SI 3 "s_register_operand" ""))]
+ "TARGET_32BIT"
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
+ "
+ operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
+")
-(define_insn "*adddf_esfdf_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (plus:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "adf%?d\\t%0, %1, %2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
+(define_expand "addsf3"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (plus:SF (match_operand:SF 1 "s_register_operand" "")
+ (match_operand:SF 2 "arm_float_add_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK
+ && !cirrus_fp_register (operands[2], SFmode))
+ operands[2] = force_reg (SFmode, operands[2]);
+")
-(define_insn "addxf3"
- [(set (match_operand:XF 0 "s_register_operand" "=f,f")
- (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
- (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "@
- adf%?e\\t%0, %1, %2
- suf%?e\\t%0, %1, #%N2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
+(define_expand "adddf3"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (plus:DF (match_operand:DF 1 "s_register_operand" "")
+ (match_operand:DF 2 "arm_float_add_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK
+ && !cirrus_fp_register (operands[2], DFmode))
+ operands[2] = force_reg (DFmode, operands[2]);
+")
(define_expand "subdi3"
[(parallel
@@ -875,7 +953,16 @@
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
"
- if (TARGET_THUMB)
+ if (TARGET_HARD_FLOAT && TARGET_MAVERICK
+ && TARGET_32BIT
+ && cirrus_fp_register (operands[0], DImode)
+ && cirrus_fp_register (operands[1], DImode))
+ {
+ emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+
+ if (TARGET_THUMB1)
{
if (GET_CODE (operands[1]) != REG)
operands[1] = force_reg (SImode, operands[1]);
@@ -890,7 +977,7 @@
(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
(match_operand:DI 2 "s_register_operand" "r,0,0")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
[(set_attr "conds" "clob")
(set_attr "length" "8")]
@@ -901,7 +988,7 @@
(minus:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "register_operand" "l")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
[(set_attr "length" "4")]
)
@@ -912,7 +999,7 @@
(zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
[(set_attr "conds" "clob")
(set_attr "length" "8")]
@@ -924,7 +1011,7 @@
(sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
[(set_attr "conds" "clob")
(set_attr "length" "8")]
@@ -961,8 +1048,8 @@
(zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r"))))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
+ "TARGET_32BIT"
+ "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
[(set_attr "conds" "clob")
(set_attr "length" "8")]
)
@@ -975,56 +1062,57 @@
"
if (GET_CODE (operands[1]) == CONST_INT)
{
- if (TARGET_ARM)
+ if (TARGET_32BIT)
{
- arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
- operands[2],
- (no_new_pseudos ? 0
- : preserve_subexpressions_p ()));
+ arm_split_constant (MINUS, SImode, NULL_RTX,
+ INTVAL (operands[1]), operands[0],
+ operands[2], optimize && can_create_pseudo_p ());
DONE;
}
- else /* TARGET_THUMB */
+ else /* TARGET_THUMB1 */
operands[1] = force_reg (SImode, operands[1]);
}
"
)
-(define_insn "*thumb_subsi3_insn"
+(define_insn "*thumb1_subsi3_insn"
[(set (match_operand:SI 0 "register_operand" "=l")
(minus:SI (match_operand:SI 1 "register_operand" "l")
(match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"sub\\t%0, %1, %2"
[(set_attr "length" "2")]
)
+; ??? Check Thumb-2 split length
(define_insn_and_split "*arm_subsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
- (match_operand:SI 2 "s_register_operand" "r,r")))]
- "TARGET_ARM"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r")
+ (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n")
+ (match_operand:SI 2 "s_register_operand" "r, r, r")))]
+ "TARGET_32BIT"
"@
rsb%?\\t%0, %2, %1
+ sub%?\\t%0, %1, %2
#"
- "TARGET_ARM
+ "TARGET_32BIT
&& GET_CODE (operands[1]) == CONST_INT
&& !const_ok_for_arm (INTVAL (operands[1]))"
[(clobber (const_int 0))]
"
- arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
- operands[2], 0);
+ arm_split_constant (MINUS, SImode, curr_insn,
+ INTVAL (operands[1]), operands[0], operands[2], 0);
DONE;
"
- [(set_attr "length" "4,16")
+ [(set_attr "length" "4,4,16")
(set_attr "predicable" "yes")]
)
(define_peephole2
[(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "s_register_operand" "")
+ (set (match_operand:SI 0 "arm_general_register_operand" "")
(minus:SI (match_operand:SI 1 "const_int_operand" "")
- (match_operand:SI 2 "s_register_operand" "")))]
- "TARGET_ARM
+ (match_operand:SI 2 "arm_general_register_operand" "")))]
+ "TARGET_32BIT
&& !const_ok_for_arm (INTVAL (operands[1]))
&& const_ok_for_arm (~INTVAL (operands[1]))"
[(set (match_dup 3) (match_dup 1))
@@ -1040,14 +1128,23 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
- sub%?s\\t%0, %1, %2
- rsb%?s\\t%0, %2, %1"
+ sub%.\\t%0, %1, %2
+ rsb%.\\t%0, %2, %1"
[(set_attr "conds" "set")]
)
-(define_insn "decscc"
+(define_expand "decscc"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
+ (match_operator:SI 2 "arm_comparison_operator"
+ [(match_operand 3 "cc_register" "") (const_int 0)])))]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*arm_decscc"
[(set (match_operand:SI 0 "s_register_operand" "=r,r")
(minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
(match_operator:SI 2 "arm_comparison_operator"
@@ -1060,76 +1157,36 @@
(set_attr "length" "*,8")]
)
-(define_insn "subsf3"
- [(set (match_operand:SF 0 "s_register_operand" "=f,f")
- (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
- (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- suf%?s\\t%0, %1, %2
- rsf%?s\\t%0, %2, %1"
- [(set_attr "type" "farith")]
-)
-
-(define_insn "subdf3"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
- (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- suf%?d\\t%0, %1, %2
- rsf%?d\\t%0, %2, %1"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*subdf_esfdf_df"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (minus:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "suf%?d\\t%0, %1, %2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*subdf_df_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f,f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- suf%?d\\t%0, %1, %2
- rsf%?d\\t%0, %2, %1"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
+(define_expand "subsf3"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
+ (match_operand:SF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK)
+ {
+ if (!cirrus_fp_register (operands[1], SFmode))
+ operands[1] = force_reg (SFmode, operands[1]);
+ if (!cirrus_fp_register (operands[2], SFmode))
+ operands[2] = force_reg (SFmode, operands[2]);
+ }
+")
-(define_insn "*subdf_esfdf_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (minus:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "suf%?d\\t%0, %1, %2"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
+(define_expand "subdf3"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
+ (match_operand:DF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK)
+ {
+ if (!cirrus_fp_register (operands[1], DFmode))
+ operands[1] = force_reg (DFmode, operands[1]);
+ if (!cirrus_fp_register (operands[2], DFmode))
+ operands[2] = force_reg (DFmode, operands[2]);
+ }
+")
-(define_insn "subxf3"
- [(set (match_operand:XF 0 "s_register_operand" "=f,f")
- (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
- (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "@
- suf%?e\\t%0, %1, %2
- rsf%?e\\t%0, %2, %1"
- [(set_attr "type" "farith")
- (set_attr "predicable" "yes")]
-)
;; Multiplication insns
@@ -1146,9 +1203,19 @@
[(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
(match_operand:SI 1 "s_register_operand" "%?r,0")))]
- "TARGET_ARM"
+ "TARGET_32BIT && !arm_arch6"
"mul%?\\t%0, %2, %1"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "mul")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*arm_mulsi3_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_32BIT && arm_arch6"
+ "mul%?\\t%0, %1, %2"
+ [(set_attr "insn" "mul")
(set_attr "predicable" "yes")]
)
@@ -1161,15 +1228,28 @@
[(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
(mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
(match_operand:SI 2 "register_operand" "l,l,l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1 && !arm_arch6"
"*
if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
+ return \"mov\\t%0, %1\;mul\\t%0, %2\";
else
- return \"mul\\t%0, %0, %2\";
+ return \"mul\\t%0, %2\";
"
[(set_attr "length" "4,4,2")
- (set_attr "type" "mult")]
+ (set_attr "insn" "mul")]
+)
+
+(define_insn "*thumb_mulsi3_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l,l")
+ (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
+ (match_operand:SI 2 "register_operand" "l,0,0")))]
+ "TARGET_THUMB1 && arm_arch6"
+ "@
+ mul\\t%0, %2
+ mul\\t%0, %1
+ mul\\t%0, %1"
+ [(set_attr "length" "2")
+ (set_attr "insn" "mul")]
)
(define_insn "*mulsi3_compare0"
@@ -1180,10 +1260,24 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(mult:SI (match_dup 2) (match_dup 1)))]
- "TARGET_ARM && !arm_is_xscale"
- "mul%?s\\t%0, %2, %1"
+ "TARGET_ARM && !arm_arch6"
+ "mul%.\\t%0, %2, %1"
+ [(set_attr "conds" "set")
+ (set_attr "insn" "muls")]
+)
+
+(define_insn "*mulsi3_compare0_v6"
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (mult:SI
+ (match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 1 "s_register_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "s_register_operand" "=r")
+ (mult:SI (match_dup 2) (match_dup 1)))]
+ "TARGET_ARM && arm_arch6 && optimize_size"
+ "mul%.\\t%0, %2, %1"
[(set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set_attr "insn" "muls")]
)
(define_insn "*mulsi_compare0_scratch"
@@ -1193,10 +1287,23 @@
(match_operand:SI 1 "s_register_operand" "%?r,0"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r"))]
- "TARGET_ARM && !arm_is_xscale"
- "mul%?s\\t%0, %2, %1"
+ "TARGET_ARM && !arm_arch6"
+ "mul%.\\t%0, %2, %1"
+ [(set_attr "conds" "set")
+ (set_attr "insn" "muls")]
+)
+
+(define_insn "*mulsi_compare0_scratch_v6"
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (mult:SI
+ (match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 1 "s_register_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "TARGET_ARM && arm_arch6 && optimize_size"
+ "mul%.\\t%0, %2, %1"
[(set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set_attr "insn" "muls")]
)
;; Unnamed templates to match MLA instruction.
@@ -1207,9 +1314,21 @@
(mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
(match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
(match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
- "TARGET_ARM"
+ "TARGET_32BIT && !arm_arch6"
+ "mla%?\\t%0, %2, %1, %3"
+ [(set_attr "insn" "mla")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*mulsi3addsi_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI
+ (mult:SI (match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand:SI 3 "s_register_operand" "r")))]
+ "TARGET_32BIT && arm_arch6"
"mla%?\\t%0, %2, %1, %3"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "mla")
(set_attr "predicable" "yes")]
)
@@ -1224,10 +1343,27 @@
(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
(plus:SI (mult:SI (match_dup 2) (match_dup 1))
(match_dup 3)))]
- "TARGET_ARM && !arm_is_xscale"
- "mla%?s\\t%0, %2, %1, %3"
+ "TARGET_ARM && arm_arch6"
+ "mla%.\\t%0, %2, %1, %3"
+ [(set_attr "conds" "set")
+ (set_attr "insn" "mlas")]
+)
+
+(define_insn "*mulsi3addsi_compare0_v6"
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV
+ (plus:SI (mult:SI
+ (match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand:SI 3 "s_register_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (mult:SI (match_dup 2) (match_dup 1))
+ (match_dup 3)))]
+ "TARGET_ARM && arm_arch6 && optimize_size"
+ "mla%.\\t%0, %2, %1, %3"
[(set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set_attr "insn" "mlas")]
)
(define_insn "*mulsi3addsi_compare0_scratch"
@@ -1239,13 +1375,40 @@
(match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
- "TARGET_ARM && !arm_is_xscale"
- "mla%?s\\t%0, %2, %1, %3"
+ "TARGET_ARM && !arm_arch6"
+ "mla%.\\t%0, %2, %1, %3"
+ [(set_attr "conds" "set")
+ (set_attr "insn" "mlas")]
+)
+
+(define_insn "*mulsi3addsi_compare0_scratch_v6"
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV
+ (plus:SI (mult:SI
+ (match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand:SI 3 "s_register_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "TARGET_ARM && arm_arch6 && optimize_size"
+ "mla%.\\t%0, %2, %1, %3"
[(set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set_attr "insn" "mlas")]
+)
+
+(define_insn "*mulsi3subsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (minus:SI
+ (match_operand:SI 3 "s_register_operand" "r")
+ (mult:SI (match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 1 "s_register_operand" "r"))))]
+ "TARGET_32BIT && arm_arch_thumb2"
+ "mls%?\\t%0, %2, %1, %3"
+ [(set_attr "insn" "mla")
+ (set_attr "predicable" "yes")]
)
-;; Unnamed template to match long long multiply-accumlate (smlal)
+;; Unnamed template to match long long multiply-accumulate (smlal)
(define_insn "*mulsidi3adddi"
[(set (match_operand:DI 0 "s_register_operand" "=&r")
@@ -1254,35 +1417,94 @@
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
(sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
(match_operand:DI 1 "s_register_operand" "0")))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_32BIT && arm_arch3m && !arm_arch6"
+ "smlal%?\\t%Q0, %R0, %3, %2"
+ [(set_attr "insn" "smlal")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*mulsidi3adddi_v6"
+ [(set (match_operand:DI 0 "s_register_operand" "=r")
+ (plus:DI
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
+ (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
+ (match_operand:DI 1 "s_register_operand" "0")))]
+ "TARGET_32BIT && arm_arch6"
"smlal%?\\t%Q0, %R0, %3, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smlal")
(set_attr "predicable" "yes")]
)
-(define_insn "mulsidi3"
+;; 32x32->64 widening multiply.
+;; As with mulsi3, the only difference between the v3-5 and v6+
+;; versions of these patterns is the requirement that the output not
+;; overlap the inputs, but that still means we have to have a named
+;; expander and two different starred insns.
+
+(define_expand "mulsidi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
+ "TARGET_32BIT && arm_arch3m"
+ ""
+)
+
+(define_insn "*mulsidi3_nov6"
[(set (match_operand:DI 0 "s_register_operand" "=&r")
(mult:DI
(sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_32BIT && arm_arch3m && !arm_arch6"
"smull%?\\t%Q0, %R0, %1, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smull")
(set_attr "predicable" "yes")]
)
-(define_insn "umulsidi3"
+(define_insn "*mulsidi3_v6"
+ [(set (match_operand:DI 0 "s_register_operand" "=r")
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
+ "TARGET_32BIT && arm_arch6"
+ "smull%?\\t%Q0, %R0, %1, %2"
+ [(set_attr "insn" "smull")
+ (set_attr "predicable" "yes")]
+)
+
+(define_expand "umulsidi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
+ "TARGET_32BIT && arm_arch3m"
+ ""
+)
+
+(define_insn "*umulsidi3_nov6"
[(set (match_operand:DI 0 "s_register_operand" "=&r")
(mult:DI
(zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
(zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_32BIT && arm_arch3m && !arm_arch6"
+ "umull%?\\t%Q0, %R0, %1, %2"
+ [(set_attr "insn" "umull")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*umulsidi3_v6"
+ [(set (match_operand:DI 0 "s_register_operand" "=r")
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
+ "TARGET_32BIT && arm_arch6"
"umull%?\\t%Q0, %R0, %1, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "umull")
(set_attr "predicable" "yes")]
)
-;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
+;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
(define_insn "*umulsidi3adddi"
[(set (match_operand:DI 0 "s_register_operand" "=&r")
@@ -1291,13 +1513,40 @@
(zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
(zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
(match_operand:DI 1 "s_register_operand" "0")))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_32BIT && arm_arch3m && !arm_arch6"
+ "umlal%?\\t%Q0, %R0, %3, %2"
+ [(set_attr "insn" "umlal")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*umulsidi3adddi_v6"
+ [(set (match_operand:DI 0 "s_register_operand" "=r")
+ (plus:DI
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
+ (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
+ (match_operand:DI 1 "s_register_operand" "0")))]
+ "TARGET_32BIT && arm_arch6"
"umlal%?\\t%Q0, %R0, %3, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "umlal")
(set_attr "predicable" "yes")]
)
-(define_insn "smulsi3_highpart"
+(define_expand "smulsi3_highpart"
+ [(parallel
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 ""))])]
+ "TARGET_32BIT && arm_arch3m"
+ ""
+)
+
+(define_insn "*smulsi3_highpart_nov6"
[(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(truncate:SI
(lshiftrt:DI
@@ -1306,14 +1555,43 @@
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=&r,&r"))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_32BIT && arm_arch3m && !arm_arch6"
"smull%?\\t%3, %0, %2, %1"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smull")
(set_attr "predicable" "yes")]
)
-(define_insn "umulsi3_highpart"
- [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
+(define_insn "*smulsi3_highpart_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 "=r"))]
+ "TARGET_32BIT && arm_arch6"
+ "smull%?\\t%3, %0, %2, %1"
+ [(set_attr "insn" "smull")
+ (set_attr "predicable" "yes")]
+)
+
+(define_expand "umulsi3_highpart"
+ [(parallel
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 ""))])]
+ "TARGET_32BIT && arm_arch3m"
+ ""
+)
+
+(define_insn "*umulsi3_highpart_nov6"
+ [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(truncate:SI
(lshiftrt:DI
(mult:DI
@@ -1321,9 +1599,24 @@
(zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=&r,&r"))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_32BIT && arm_arch3m && !arm_arch6"
+ "umull%?\\t%3, %0, %2, %1"
+ [(set_attr "insn" "umull")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*umulsi3_highpart_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 "=r"))]
+ "TARGET_32BIT && arm_arch6"
"umull%?\\t%3, %0, %2, %1"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "umull")
(set_attr "predicable" "yes")]
)
@@ -1333,9 +1626,50 @@
(match_operand:HI 1 "s_register_operand" "%r"))
(sign_extend:SI
(match_operand:HI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_is_xscale"
+ "TARGET_DSP_MULTIPLY"
"smulbb%?\\t%0, %1, %2"
- [(set_attr "type" "mult")]
+ [(set_attr "insn" "smulxy")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*mulhisi3tb"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (mult:SI (ashiftrt:SI
+ (match_operand:SI 1 "s_register_operand" "r")
+ (const_int 16))
+ (sign_extend:SI
+ (match_operand:HI 2 "s_register_operand" "r"))))]
+ "TARGET_DSP_MULTIPLY"
+ "smultb%?\\t%0, %1, %2"
+ [(set_attr "insn" "smulxy")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*mulhisi3bt"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "s_register_operand" "r"))
+ (ashiftrt:SI
+ (match_operand:SI 2 "s_register_operand" "r")
+ (const_int 16))))]
+ "TARGET_DSP_MULTIPLY"
+ "smulbt%?\\t%0, %1, %2"
+ [(set_attr "insn" "smulxy")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*mulhisi3tt"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (mult:SI (ashiftrt:SI
+ (match_operand:SI 1 "s_register_operand" "r")
+ (const_int 16))
+ (ashiftrt:SI
+ (match_operand:SI 2 "s_register_operand" "r")
+ (const_int 16))))]
+ "TARGET_DSP_MULTIPLY"
+ "smultt%?\\t%0, %1, %2"
+ [(set_attr "insn" "smulxy")
+ (set_attr "predicable" "yes")]
)
(define_insn "*mulhisi3addsi"
@@ -1345,9 +1679,10 @@
(match_operand:HI 2 "s_register_operand" "%r"))
(sign_extend:SI
(match_operand:HI 3 "s_register_operand" "r")))))]
- "TARGET_ARM && arm_is_xscale"
+ "TARGET_DSP_MULTIPLY"
"smlabb%?\\t%0, %2, %3, %1"
- [(set_attr "type" "mult")]
+ [(set_attr "insn" "smlaxy")
+ (set_attr "predicable" "yes")]
)
(define_insn "*mulhidi3adddi"
@@ -1358,210 +1693,64 @@
(match_operand:HI 2 "s_register_operand" "%r"))
(sign_extend:DI
(match_operand:HI 3 "s_register_operand" "r")))))]
- "TARGET_ARM && arm_is_xscale"
+ "TARGET_DSP_MULTIPLY"
"smlalbb%?\\t%Q0, %R0, %2, %3"
-[(set_attr "type" "mult")])
-
-(define_insn "mulsf3"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (mult:SF (match_operand:SF 1 "s_register_operand" "f")
- (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "fml%?s\\t%0, %1, %2"
- [(set_attr "type" "ffmul")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "muldf3"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mult:DF (match_operand:DF 1 "s_register_operand" "f")
- (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "muf%?d\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*muldf_esfdf_df"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mult:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "muf%?d\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*muldf_df_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mult:DF (match_operand:DF 1 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "muf%?d\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
+ [(set_attr "insn" "smlalxy")
+ (set_attr "predicable" "yes")])
-(define_insn "*muldf_esfdf_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mult:DF
- (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "muf%?d\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
+(define_expand "mulsf3"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (mult:SF (match_operand:SF 1 "s_register_operand" "")
+ (match_operand:SF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK
+ && !cirrus_fp_register (operands[2], SFmode))
+ operands[2] = force_reg (SFmode, operands[2]);
+")
-(define_insn "mulxf3"
- [(set (match_operand:XF 0 "s_register_operand" "=f")
- (mult:XF (match_operand:XF 1 "s_register_operand" "f")
- (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "muf%?e\\t%0, %1, %2"
- [(set_attr "type" "fmul")
- (set_attr "predicable" "yes")]
-)
+(define_expand "muldf3"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (mult:DF (match_operand:DF 1 "s_register_operand" "")
+ (match_operand:DF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK
+ && !cirrus_fp_register (operands[2], DFmode))
+ operands[2] = force_reg (DFmode, operands[2]);
+")
;; Division insns
-(define_insn "divsf3"
- [(set (match_operand:SF 0 "s_register_operand" "=f,f")
- (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
- (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- fdv%?s\\t%0, %1, %2
- frd%?s\\t%0, %2, %1"
- [(set_attr "type" "fdivs")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "divdf3"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
- (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- dvf%?d\\t%0, %1, %2
- rdf%?d\\t%0, %2, %1"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*divdf_esfdf_df"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (div:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "dvf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*divdf_df_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "rdf%?d\\t%0, %2, %1"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*divdf_esfdf_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (div:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "dvf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
+(define_expand "divsf3"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
+ (match_operand:SF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+ "")
-(define_insn "divxf3"
- [(set (match_operand:XF 0 "s_register_operand" "=f,f")
- (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
- (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "@
- dvf%?e\\t%0, %1, %2
- rdf%?e\\t%0, %2, %1"
- [(set_attr "type" "fdivx")
- (set_attr "predicable" "yes")]
-)
+(define_expand "divdf3"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
+ (match_operand:DF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+ "")
;; Modulo insns
-(define_insn "modsf3"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (mod:SF (match_operand:SF 1 "s_register_operand" "f")
- (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "rmf%?s\\t%0, %1, %2"
- [(set_attr "type" "fdivs")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "moddf3"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mod:DF (match_operand:DF 1 "s_register_operand" "f")
- (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "rmf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*moddf_esfdf_df"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mod:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "rmf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*moddf_df_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mod:DF (match_operand:DF 1 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "rmf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*moddf_esfdf_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (mod:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))
- (float_extend:DF
- (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "rmf%?d\\t%0, %1, %2"
- [(set_attr "type" "fdivd")
- (set_attr "predicable" "yes")]
-)
+(define_expand "modsf3"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (mod:SF (match_operand:SF 1 "s_register_operand" "")
+ (match_operand:SF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
+ "")
-(define_insn "modxf3"
- [(set (match_operand:XF 0 "s_register_operand" "=f")
- (mod:XF (match_operand:XF 1 "s_register_operand" "f")
- (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
- "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "rmf%?e\\t%0, %1, %2"
- [(set_attr "type" "fdivx")
- (set_attr "predicable" "yes")]
-)
+(define_expand "moddf3"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (mod:DF (match_operand:DF 1 "s_register_operand" "")
+ (match_operand:DF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
+ "")
;; Boolean and,ior,xor insns
@@ -1574,7 +1763,8 @@
(match_operator:DI 6 "logical_binary_operator"
[(match_operand:DI 1 "s_register_operand" "")
(match_operand:DI 2 "s_register_operand" "")]))]
- "TARGET_ARM && reload_completed"
+ "TARGET_32BIT && reload_completed
+ && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
[(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
(set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
"
@@ -1593,7 +1783,7 @@
(match_operator:DI 6 "logical_binary_operator"
[(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
(match_operand:DI 1 "s_register_operand" "")]))]
- "TARGET_ARM && reload_completed"
+ "TARGET_32BIT && reload_completed"
[(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
(set (match_dup 3) (match_op_dup:SI 6
[(ashiftrt:SI (match_dup 2) (const_int 31))
@@ -1616,7 +1806,7 @@
(ior:DI
(zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
(match_operand:DI 1 "s_register_operand" "")))]
- "TARGET_ARM && operands[0] != operands[1] && reload_completed"
+ "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
[(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
(set (match_dup 3) (match_dup 4))]
"
@@ -1635,7 +1825,7 @@
(xor:DI
(zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
(match_operand:DI 1 "s_register_operand" "")))]
- "TARGET_ARM && operands[0] != operands[1] && reload_completed"
+ "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
[(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
(set (match_dup 3) (match_dup 4))]
"
@@ -1651,7 +1841,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
(match_operand:DI 2 "s_register_operand" "r,r")))]
- "TARGET_ARM"
+ "TARGET_32BIT && ! TARGET_IWMMXT"
"#"
[(set_attr "length" "8")]
)
@@ -1661,9 +1851,9 @@
(and:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"#"
- "TARGET_ARM && reload_completed"
+ "TARGET_32BIT && reload_completed"
; The zero extend of operand 2 clears the high word of the output
; operand.
[(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
@@ -1682,7 +1872,7 @@
(and:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"#"
[(set_attr "length" "8")]
)
@@ -1693,18 +1883,18 @@
(match_operand:SI 2 "reg_or_int_operand" "")))]
"TARGET_EITHER"
"
- if (TARGET_ARM)
+ if (TARGET_32BIT)
{
if (GET_CODE (operands[2]) == CONST_INT)
{
- arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
- operands[1],
- (no_new_pseudos
- ? 0 : preserve_subexpressions_p ()));
+ arm_split_constant (AND, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0],
+ operands[1], optimize && can_create_pseudo_p ());
+
DONE;
}
}
- else /* TARGET_THUMB */
+ else /* TARGET_THUMB1 */
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = force_reg (SImode, operands[2]);
@@ -1749,34 +1939,35 @@
"
)
+; ??? Check split length for Thumb-2
(define_insn_and_split "*arm_andsi3_insn"
[(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
(and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
(match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
and%?\\t%0, %1, %2
bic%?\\t%0, %1, #%B2
#"
- "TARGET_ARM
+ "TARGET_32BIT
&& GET_CODE (operands[2]) == CONST_INT
&& !(const_ok_for_arm (INTVAL (operands[2]))
|| const_ok_for_arm (~INTVAL (operands[2])))"
[(clobber (const_int 0))]
"
- arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
- operands[1], 0);
+ arm_split_constant (AND, SImode, curr_insn,
+ INTVAL (operands[2]), operands[0], operands[1], 0);
DONE;
"
[(set_attr "length" "4,4,16")
(set_attr "predicable" "yes")]
)
-(define_insn "*thumb_andsi3_insn"
+(define_insn "*thumb1_andsi3_insn"
[(set (match_operand:SI 0 "register_operand" "=l")
(and:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"and\\t%0, %0, %2"
[(set_attr "length" "2")]
)
@@ -1789,10 +1980,10 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(and:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
- and%?s\\t%0, %1, %2
- bic%?s\\t%0, %1, #%B2"
+ and%.\\t%0, %1, %2
+ bic%.\\t%0, %1, #%B2"
[(set_attr "conds" "set")]
)
@@ -1803,10 +1994,10 @@
(match_operand:SI 1 "arm_not_operand" "rI,K"))
(const_int 0)))
(clobber (match_scratch:SI 2 "=X,r"))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
tst%?\\t%0, %1
- bic%?s\\t%2, %0, #%B1"
+ bic%.\\t%2, %0, #%B1"
[(set_attr "conds" "set")]
)
@@ -1817,7 +2008,7 @@
(match_operand 1 "const_int_operand" "n")
(match_operand 2 "const_int_operand" "n"))
(const_int 0)))]
- "TARGET_ARM
+ "TARGET_32BIT
&& (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
&& INTVAL (operands[1]) > 0
&& INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
@@ -1831,7 +2022,7 @@
[(set_attr "conds" "set")]
)
-(define_insn "*ne_zeroextractsi"
+(define_insn_and_split "*ne_zeroextractsi"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(ne:SI (zero_extract:SI
(match_operand:SI 1 "s_register_operand" "r")
@@ -1839,27 +2030,209 @@
(match_operand:SI 3 "const_int_operand" "n"))
(const_int 0)))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM
+ "TARGET_32BIT
&& (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
&& INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
&& INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
- "*
+ "#"
+ "TARGET_32BIT
+ && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
+ && INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
+ && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
+ [(parallel [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (match_dup 0) (const_int 1)))]
+ "
+ operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
+ << INTVAL (operands[3]));
+ "
+ [(set_attr "conds" "clob")
+ (set (attr "length")
+ (if_then_else (eq_attr "is_thumb" "yes")
+ (const_int 12)
+ (const_int 8)))]
+)
+
+(define_insn_and_split "*ne_zeroextractsi_shifted"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (ne:SI (zero_extract:SI
+ (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (const_int 0))
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM"
+ "#"
+ "TARGET_ARM"
+ [(parallel [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (match_dup 0) (const_int 1)))]
+ "
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+ "
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
+(define_insn_and_split "*ite_ne_zeroextractsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (if_then_else:SI (ne (zero_extract:SI
+ (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n"))
+ (const_int 0))
+ (match_operand:SI 4 "arm_not_operand" "rIK")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM
+ && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
+ && INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
+ && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
+ "#"
+ "TARGET_ARM
+ && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
+ && INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
+ && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
+ [(parallel [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (match_dup 0) (match_dup 4)))]
+ "
operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
- << INTVAL (operands[3]));
- output_asm_insn (\"ands\\t%0, %1, %2\", operands);
- return \"movne\\t%0, #1\";
+ << INTVAL (operands[3]));
+ "
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
+(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (if_then_else:SI (ne (zero_extract:SI
+ (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (const_int 0))
+ (const_int 0))
+ (match_operand:SI 3 "arm_not_operand" "rIK")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
+ "#"
+ "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
+ [(parallel [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (match_dup 0) (match_dup 3)))]
+ "
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
"
[(set_attr "conds" "clob")
(set_attr "length" "8")]
)
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")))
+ (clobber (match_operand:SI 4 "s_register_operand" ""))]
+ "TARGET_THUMB1"
+ [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
+ "{
+ HOST_WIDE_INT temp = INTVAL (operands[2]);
+
+ operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
+ operands[3] = GEN_INT (32 - temp);
+ }"
+)
+
+;; ??? Use Thumb-2 has bitfield insert/extract instructions.
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "shiftable_operator"
+ [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")
+ (match_operand:SI 4 "const_int_operand" ""))
+ (match_operand:SI 5 "s_register_operand" "")]))
+ (clobber (match_operand:SI 6 "s_register_operand" ""))]
+ "TARGET_ARM"
+ [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
+ (set (match_dup 0)
+ (match_op_dup 1
+ [(lshiftrt:SI (match_dup 6) (match_dup 4))
+ (match_dup 5)]))]
+ "{
+ HOST_WIDE_INT temp = INTVAL (operands[3]);
+
+ operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
+ operands[4] = GEN_INT (32 - temp);
+ }"
+)
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")))]
+ "TARGET_THUMB1"
+ [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
+ "{
+ HOST_WIDE_INT temp = INTVAL (operands[2]);
+
+ operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
+ operands[3] = GEN_INT (32 - temp);
+ }"
+)
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "shiftable_operator"
+ [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")
+ (match_operand:SI 4 "const_int_operand" ""))
+ (match_operand:SI 5 "s_register_operand" "")]))
+ (clobber (match_operand:SI 6 "s_register_operand" ""))]
+ "TARGET_ARM"
+ [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
+ (set (match_dup 0)
+ (match_op_dup 1
+ [(ashiftrt:SI (match_dup 6) (match_dup 4))
+ (match_dup 5)]))]
+ "{
+ HOST_WIDE_INT temp = INTVAL (operands[3]);
+
+ operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
+ operands[4] = GEN_INT (32 - temp);
+ }"
+)
+
;;; ??? This pattern is bogus. If operand3 has bits outside the range
;;; represented by the bitfield, then this will produce incorrect results.
;;; Somewhere, the value needs to be truncated. On targets like the m68k,
-;;; which have a real bitfield insert instruction, the truncation happens
-;;; in the bitfield insert instruction itself. Since arm does not have a
-;;; bitfield insert instruction, we would have to emit code here to truncate
+;;; which have a real bit-field insert instruction, the truncation happens
+;;; in the bit-field insert instruction itself. Since arm does not have a
+;;; bit-field insert instruction, we would have to emit code here to truncate
;;; the value before we insert. This loses some of the advantage of having
;;; this insv pattern, so this pattern needs to be reevalutated.
@@ -1867,8 +2240,8 @@
[(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
(match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" ""))
- (match_operand:SI 3 "nonmemory_operand" ""))]
- "TARGET_ARM"
+ (match_operand:SI 3 "reg_or_int_operand" ""))]
+ "TARGET_ARM || arm_arch_thumb2"
"
{
int start_bit = INTVAL (operands[2]);
@@ -1876,6 +2249,37 @@
HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
rtx target, subtarget;
+ if (arm_arch_thumb2)
+ {
+ bool use_bfi = TRUE;
+
+ if (GET_CODE (operands[3]) == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
+
+ if (val == 0)
+ {
+ emit_insn (gen_insv_zero (operands[0], operands[1],
+ operands[2]));
+ DONE;
+ }
+
+ /* See if the set can be done with a single orr instruction. */
+ if (val == mask && const_ok_for_arm (val << start_bit))
+ use_bfi = FALSE;
+ }
+
+ if (use_bfi)
+ {
+ if (GET_CODE (operands[3]) != REG)
+ operands[3] = force_reg (SImode, operands[3]);
+
+ emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
+ }
+
target = operands[0];
/* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
subreg as the final target. */
@@ -1902,9 +2306,10 @@
HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
- emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
+ emit_insn (gen_andsi3 (op1, operands[0],
+ gen_int_mode (~mask2, SImode)));
emit_insn (gen_iorsi3 (subtarget, op1,
- GEN_INT (op3_value << start_bit)));
+ gen_int_mode (op3_value << start_bit, SImode)));
}
else if (start_bit == 0
&& !(const_ok_for_arm (mask)
@@ -1913,7 +2318,7 @@
/* A Trick, since we are setting the bottom bits in the word,
we can shift operand[3] up, operand[0] down, OR them together
and rotate the result back again. This takes 3 insns, and
- the third might be mergable into another op. */
+ the third might be mergeable into another op. */
/* The shift up copes with the possibility that operand[3] is
wider than the bitfield. */
rtx op0 = gen_reg_rtx (SImode);
@@ -1940,7 +2345,7 @@
}
else
{
- rtx op0 = GEN_INT (mask);
+ rtx op0 = gen_int_mode (mask, SImode);
rtx op1 = gen_reg_rtx (SImode);
rtx op2 = gen_reg_rtx (SImode);
@@ -1959,7 +2364,7 @@
&& (const_ok_for_arm (mask << start_bit)
|| const_ok_for_arm (~(mask << start_bit))))
{
- op0 = GEN_INT (~(mask << start_bit));
+ op0 = gen_int_mode (~(mask << start_bit), SImode);
emit_insn (gen_andsi3 (op2, operands[0], op0));
}
else
@@ -1998,14 +2403,36 @@
}"
)
+(define_insn "insv_zero"
+ [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
+ (match_operand:SI 1 "const_int_operand" "M")
+ (match_operand:SI 2 "const_int_operand" "M"))
+ (const_int 0))]
+ "arm_arch_thumb2"
+ "bfc%?\t%0, %2, %1"
+ [(set_attr "length" "4")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "insv_t2"
+ [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
+ (match_operand:SI 1 "const_int_operand" "M")
+ (match_operand:SI 2 "const_int_operand" "M"))
+ (match_operand:SI 3 "s_register_operand" "r"))]
+ "arm_arch_thumb2"
+ "bfi%?\t%0, %3, %2, %1"
+ [(set_attr "length" "4")
+ (set_attr "predicable" "yes")]
+)
+
; constants for op 2 will never be given to these patterns.
(define_insn_and_split "*anddi_notdi_di"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
(match_operand:DI 2 "s_register_operand" "0,r")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"#"
- "TARGET_ARM && reload_completed"
+ "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
[(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
"
@@ -2026,16 +2453,16 @@
(and:DI (not:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r")))
(match_operand:DI 1 "s_register_operand" "0,?r")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
bic%?\\t%Q0, %Q1, %2
#"
; (not (zero_extend ...)) allows us to just copy the high word from
; operand1 to operand0.
- "TARGET_ARM
+ "TARGET_32BIT
&& reload_completed
&& operands[0] != operands[1]"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+ [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
(set (match_dup 3) (match_dup 4))]
"
{
@@ -2052,11 +2479,11 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (not:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r")))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
+ "TARGET_32BIT"
"#"
- "TARGET_ARM && reload_completed"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+ "TARGET_32BIT && reload_completed"
+ [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
(set (match_dup 3) (and:SI (not:SI
(ashiftrt:SI (match_dup 2) (const_int 31)))
(match_dup 4)))]
@@ -2075,7 +2502,7 @@
[(set (match_operand:SI 0 "s_register_operand" "=r")
(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
(match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"bic%?\\t%0, %1, %2"
[(set_attr "predicable" "yes")]
)
@@ -2084,22 +2511,24 @@
[(set (match_operand:SI 0 "register_operand" "=l")
(and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
(match_operand:SI 2 "register_operand" "0")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"bic\\t%0, %0, %1"
[(set_attr "length" "2")]
)
(define_insn "andsi_not_shiftsi_si"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (and:SI (not:SI (match_operator:SI 4 "shift_operator"
- [(match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "arm_rhs_operand" "rM")]))
- (match_operand:SI 1 "s_register_operand" "r")))]
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (and:SI (not:SI (match_operator:SI 4 "shift_operator"
+ [(match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 3 "arm_rhs_operand" "rM")]))
+ (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_ARM"
"bic%?\\t%0, %1, %2%S4"
[(set_attr "predicable" "yes")
(set_attr "shift" "2")
- ]
+ (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*andsi_notsi_si_compare0"
@@ -2110,8 +2539,8 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r")
(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
- "TARGET_ARM"
- "bic%?s\\t%0, %1, %2"
+ "TARGET_32BIT"
+ "bic%.\\t%0, %1, %2"
[(set_attr "conds" "set")]
)
@@ -2122,8 +2551,8 @@
(match_operand:SI 1 "s_register_operand" "r"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "bic%?s\\t%0, %1, %2"
+ "TARGET_32BIT"
+ "bic%.\\t%0, %1, %2"
[(set_attr "conds" "set")]
)
@@ -2131,7 +2560,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
(match_operand:DI 2 "s_register_operand" "r,r")))]
- "TARGET_ARM"
+ "TARGET_32BIT && ! TARGET_IWMMXT"
"#"
[(set_attr "length" "8")
(set_attr "predicable" "yes")]
@@ -2142,7 +2571,7 @@
(ior:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "0,?r")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
orr%?\\t%Q0, %Q1, %2
#"
@@ -2155,7 +2584,7 @@
(ior:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"#"
[(set_attr "length" "8")
(set_attr "predicable" "yes")]
@@ -2169,15 +2598,14 @@
"
if (GET_CODE (operands[2]) == CONST_INT)
{
- if (TARGET_ARM)
+ if (TARGET_32BIT)
{
- arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
- operands[1],
- (no_new_pseudos
- ? 0 : preserve_subexpressions_p ()));
+ arm_split_constant (IOR, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0], operands[1],
+ optimize && can_create_pseudo_p ());
DONE;
}
- else /* TARGET_THUMB */
+ else /* TARGET_THUMB1 */
operands [2] = force_reg (SImode, operands [2]);
}
"
@@ -2187,38 +2615,38 @@
[(set (match_operand:SI 0 "s_register_operand" "=r,r")
(ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
(match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
orr%?\\t%0, %1, %2
#"
- "TARGET_ARM
+ "TARGET_32BIT
&& GET_CODE (operands[2]) == CONST_INT
&& !const_ok_for_arm (INTVAL (operands[2]))"
[(clobber (const_int 0))]
"
- arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
- operands[1], 0);
+ arm_split_constant (IOR, SImode, curr_insn,
+ INTVAL (operands[2]), operands[0], operands[1], 0);
DONE;
"
[(set_attr "length" "4,16")
(set_attr "predicable" "yes")]
)
-(define_insn "*thumb_iorsi3"
+(define_insn "*thumb1_iorsi3"
[(set (match_operand:SI 0 "register_operand" "=l")
(ior:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"orr\\t%0, %0, %2"
[(set_attr "length" "2")]
)
(define_peephole2
[(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "s_register_operand" "")
- (ior:SI (match_operand:SI 1 "s_register_operand" "")
+ (set (match_operand:SI 0 "arm_general_register_operand" "")
+ (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))]
- "TARGET_ARM
+ "TARGET_32BIT
&& !const_ok_for_arm (INTVAL (operands[2]))
&& const_ok_for_arm (~INTVAL (operands[2]))"
[(set (match_dup 3) (match_dup 2))
@@ -2233,8 +2661,8 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r")
(ior:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "orr%?s\\t%0, %1, %2"
+ "TARGET_32BIT"
+ "orr%.\\t%0, %1, %2"
[(set_attr "conds" "set")]
)
@@ -2244,8 +2672,8 @@
(match_operand:SI 2 "arm_rhs_operand" "rI"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "orr%?s\\t%0, %1, %2"
+ "TARGET_32BIT"
+ "orr%.\\t%0, %1, %2"
[(set_attr "conds" "set")]
)
@@ -2253,7 +2681,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
(match_operand:DI 2 "s_register_operand" "r,r")))]
- "TARGET_ARM"
+ "TARGET_32BIT && !TARGET_IWMMXT"
"#"
[(set_attr "length" "8")
(set_attr "predicable" "yes")]
@@ -2264,7 +2692,7 @@
(xor:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "0,?r")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
eor%?\\t%Q0, %Q1, %2
#"
@@ -2277,7 +2705,7 @@
(xor:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"#"
[(set_attr "length" "8")
(set_attr "predicable" "yes")]
@@ -2288,7 +2716,7 @@
(xor:SI (match_operand:SI 1 "s_register_operand" "")
(match_operand:SI 2 "arm_rhs_operand" "")))]
"TARGET_EITHER"
- "if (TARGET_THUMB)
+ "if (TARGET_THUMB1)
if (GET_CODE (operands[2]) == CONST_INT)
operands[2] = force_reg (SImode, operands[2]);
"
@@ -2298,16 +2726,16 @@
[(set (match_operand:SI 0 "s_register_operand" "=r")
(xor:SI (match_operand:SI 1 "s_register_operand" "r")
(match_operand:SI 2 "arm_rhs_operand" "rI")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"eor%?\\t%0, %1, %2"
[(set_attr "predicable" "yes")]
)
-(define_insn "*thumb_xorsi3"
+(define_insn "*thumb1_xorsi3"
[(set (match_operand:SI 0 "register_operand" "=l")
(xor:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"eor\\t%0, %0, %2"
[(set_attr "length" "2")]
)
@@ -2319,8 +2747,8 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r")
(xor:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM"
- "eor%?s\\t%0, %1, %2"
+ "TARGET_32BIT"
+ "eor%.\\t%0, %1, %2"
[(set_attr "conds" "set")]
)
@@ -2329,7 +2757,7 @@
(compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
(match_operand:SI 1 "arm_rhs_operand" "rI"))
(const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"teq%?\\t%0, %1"
[(set_attr "conds" "set")]
)
@@ -2339,12 +2767,12 @@
; insns.
(define_split
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
- (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
- (match_operand:SI 3 "arm_rhs_operand" "rI")))
- (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
- "TARGET_ARM"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
+ (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
+ (match_operand:SI 3 "arm_rhs_operand" "")))
+ (clobber (match_operand:SI 4 "s_register_operand" ""))]
+ "TARGET_32BIT"
[(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
(not:SI (match_dup 3))))
(set (match_dup 0) (not:SI (match_dup 4)))]
@@ -2356,45 +2784,222 @@
(and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
[(set_attr "length" "8")
+ (set_attr "ce_count" "2")
(set_attr "predicable" "yes")]
)
+; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
+; insns are available?
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "logical_binary_operator"
+ [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")
+ (match_operand:SI 4 "const_int_operand" ""))
+ (match_operator:SI 9 "logical_binary_operator"
+ [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
+ (match_operand:SI 6 "const_int_operand" ""))
+ (match_operand:SI 7 "s_register_operand" "")])]))
+ (clobber (match_operand:SI 8 "s_register_operand" ""))]
+ "TARGET_32BIT
+ && GET_CODE (operands[1]) == GET_CODE (operands[9])
+ && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
+ [(set (match_dup 8)
+ (match_op_dup 1
+ [(ashift:SI (match_dup 2) (match_dup 4))
+ (match_dup 5)]))
+ (set (match_dup 0)
+ (match_op_dup 1
+ [(lshiftrt:SI (match_dup 8) (match_dup 6))
+ (match_dup 7)]))]
+ "
+ operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
+")
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "logical_binary_operator"
+ [(match_operator:SI 9 "logical_binary_operator"
+ [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
+ (match_operand:SI 6 "const_int_operand" ""))
+ (match_operand:SI 7 "s_register_operand" "")])
+ (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")
+ (match_operand:SI 4 "const_int_operand" ""))]))
+ (clobber (match_operand:SI 8 "s_register_operand" ""))]
+ "TARGET_32BIT
+ && GET_CODE (operands[1]) == GET_CODE (operands[9])
+ && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
+ [(set (match_dup 8)
+ (match_op_dup 1
+ [(ashift:SI (match_dup 2) (match_dup 4))
+ (match_dup 5)]))
+ (set (match_dup 0)
+ (match_op_dup 1
+ [(lshiftrt:SI (match_dup 8) (match_dup 6))
+ (match_dup 7)]))]
+ "
+ operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
+")
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "logical_binary_operator"
+ [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")
+ (match_operand:SI 4 "const_int_operand" ""))
+ (match_operator:SI 9 "logical_binary_operator"
+ [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
+ (match_operand:SI 6 "const_int_operand" ""))
+ (match_operand:SI 7 "s_register_operand" "")])]))
+ (clobber (match_operand:SI 8 "s_register_operand" ""))]
+ "TARGET_32BIT
+ && GET_CODE (operands[1]) == GET_CODE (operands[9])
+ && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
+ [(set (match_dup 8)
+ (match_op_dup 1
+ [(ashift:SI (match_dup 2) (match_dup 4))
+ (match_dup 5)]))
+ (set (match_dup 0)
+ (match_op_dup 1
+ [(ashiftrt:SI (match_dup 8) (match_dup 6))
+ (match_dup 7)]))]
+ "
+ operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
+")
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "logical_binary_operator"
+ [(match_operator:SI 9 "logical_binary_operator"
+ [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
+ (match_operand:SI 6 "const_int_operand" ""))
+ (match_operand:SI 7 "s_register_operand" "")])
+ (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")
+ (match_operand:SI 4 "const_int_operand" ""))]))
+ (clobber (match_operand:SI 8 "s_register_operand" ""))]
+ "TARGET_32BIT
+ && GET_CODE (operands[1]) == GET_CODE (operands[9])
+ && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
+ [(set (match_dup 8)
+ (match_op_dup 1
+ [(ashift:SI (match_dup 2) (match_dup 4))
+ (match_dup 5)]))
+ (set (match_dup 0)
+ (match_op_dup 1
+ [(ashiftrt:SI (match_dup 8) (match_dup 6))
+ (match_dup 7)]))]
+ "
+ operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
+")
;; Minimum and maximum insns
-(define_insn "smaxsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
+(define_expand "smaxsi3"
+ [(parallel [
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (smax:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "arm_rhs_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_32BIT"
+ "
+ if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
+ {
+ /* No need for a clobber of the condition code register here. */
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SMAX (SImode, operands[1],
+ operands[2])));
+ DONE;
+ }
+")
+
+(define_insn "*smax_0"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (smax:SI (match_operand:SI 1 "s_register_operand" "r")
+ (const_int 0)))]
+ "TARGET_32BIT"
+ "bic%?\\t%0, %1, %1, asr #31"
+ [(set_attr "predicable" "yes")]
+)
+
+(define_insn "*smax_m1"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (smax:SI (match_operand:SI 1 "s_register_operand" "r")
+ (const_int -1)))]
+ "TARGET_32BIT"
+ "orr%?\\t%0, %1, %1, asr #31"
+ [(set_attr "predicable" "yes")]
+)
+
+(define_insn "*arm_smax_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
+ (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"@
cmp\\t%1, %2\;movlt\\t%0, %2
- cmp\\t%1, %2\;movge\\t%0, %1
cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
[(set_attr "conds" "clob")
- (set_attr "length" "8,8,12")]
+ (set_attr "length" "8,12")]
)
-(define_insn "sminsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
+(define_expand "sminsi3"
+ [(parallel [
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (smin:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "arm_rhs_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_32BIT"
+ "
+ if (operands[2] == const0_rtx)
+ {
+ /* No need for a clobber of the condition code register here. */
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SMIN (SImode, operands[1],
+ operands[2])));
+ DONE;
+ }
+")
+
+(define_insn "*smin_0"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (smin:SI (match_operand:SI 1 "s_register_operand" "r")
+ (const_int 0)))]
+ "TARGET_32BIT"
+ "and%?\\t%0, %1, %1, asr #31"
+ [(set_attr "predicable" "yes")]
+)
+
+(define_insn "*arm_smin_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
+ (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"@
cmp\\t%1, %2\;movge\\t%0, %2
- cmp\\t%1, %2\;movlt\\t%0, %1
cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
[(set_attr "conds" "clob")
- (set_attr "length" "8,8,12")]
+ (set_attr "length" "8,12")]
+)
+
+(define_expand "umaxsi3"
+ [(parallel [
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (umax:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "arm_rhs_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_32BIT"
+ ""
)
-(define_insn "umaxsi3"
+(define_insn "*arm_umaxsi3"
[(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
@@ -2408,7 +3013,17 @@
(set_attr "length" "8,8,12")]
)
-(define_insn "uminsi3"
+(define_expand "uminsi3"
+ [(parallel [
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (umin:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "arm_rhs_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*arm_uminsi3"
[(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
@@ -2428,17 +3043,22 @@
[(match_operand:SI 1 "s_register_operand" "r")
(match_operand:SI 2 "s_register_operand" "r")]))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"*
- operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
- operands[2]);
+ operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
+ operands[1], operands[2]);
output_asm_insn (\"cmp\\t%1, %2\", operands);
+ if (TARGET_THUMB2)
+ output_asm_insn (\"ite\t%d3\", operands);
output_asm_insn (\"str%d3\\t%1, %0\", operands);
output_asm_insn (\"str%D3\\t%2, %0\", operands);
return \"\";
"
[(set_attr "conds" "clob")
- (set_attr "length" "12")
+ (set (attr "length")
+ (if_then_else (eq_attr "is_thumb" "yes")
+ (const_int 14)
+ (const_int 12)))
(set_attr "type" "store1")]
)
@@ -2452,30 +3072,78 @@
(match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
(match_operand:SI 1 "s_register_operand" "0,?r")]))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM
- && (GET_CODE (operands[1]) != REG
- || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
- && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
+ "TARGET_32BIT && !arm_eliminable_register (operands[1])"
"*
{
enum rtx_code code = GET_CODE (operands[4]);
+ bool need_else;
- operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
- operands[3]);
- output_asm_insn (\"cmp\\t%2, %3\", operands);
- output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
if (which_alternative != 0 || operands[3] != const0_rtx
|| (code != PLUS && code != MINUS && code != IOR && code != XOR))
+ need_else = true;
+ else
+ need_else = false;
+
+ operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
+ operands[2], operands[3]);
+ output_asm_insn (\"cmp\\t%2, %3\", operands);
+ if (TARGET_THUMB2)
+ {
+ if (need_else)
+ output_asm_insn (\"ite\\t%d5\", operands);
+ else
+ output_asm_insn (\"it\\t%d5\", operands);
+ }
+ output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
+ if (need_else)
output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
return \"\";
}"
[(set_attr "conds" "clob")
- (set_attr "length" "12")]
+ (set (attr "length")
+ (if_then_else (eq_attr "is_thumb" "yes")
+ (const_int 14)
+ (const_int 12)))]
)
;; Shift and rotation insns
+(define_expand "ashldi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (ashift:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:SI 2 "reg_or_int_operand" "")))]
+ "TARGET_32BIT"
+ "
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
+ DONE;
+ }
+ /* Ideally we shouldn't fail here if we could know that operands[1]
+ ends up already living in an iwmmxt register. Otherwise it's
+ cheaper to have the alternate code being generated than moving
+ values to iwmmxt regs and back. */
+ FAIL;
+ }
+ else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
+ FAIL;
+ "
+)
+
+(define_insn "arm_ashldi3_1bit"
+ [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
+ (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (const_int 1)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT"
+ "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
(define_expand "ashlsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(ashift:SI (match_operand:SI 1 "s_register_operand" "")
@@ -2491,15 +3159,50 @@
"
)
-(define_insn "*thumb_ashlsi3"
+(define_insn "*thumb1_ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=l,l")
(ashift:SI (match_operand:SI 1 "register_operand" "l,0")
(match_operand:SI 2 "nonmemory_operand" "N,l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"lsl\\t%0, %1, %2"
[(set_attr "length" "2")]
)
+(define_expand "ashrdi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:SI 2 "reg_or_int_operand" "")))]
+ "TARGET_32BIT"
+ "
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
+ DONE;
+ }
+ /* Ideally we shouldn't fail here if we could know that operands[1]
+ ends up already living in an iwmmxt register. Otherwise it's
+ cheaper to have the alternate code being generated than moving
+ values to iwmmxt regs and back. */
+ FAIL;
+ }
+ else if (!TARGET_REALLY_IWMMXT)
+ FAIL;
+ "
+)
+
+(define_insn "arm_ashrdi3_1bit"
+ [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
+ (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (const_int 1)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT"
+ "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
@@ -2512,15 +3215,50 @@
"
)
-(define_insn "*thumb_ashrsi3"
+(define_insn "*thumb1_ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=l,l")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
(match_operand:SI 2 "nonmemory_operand" "N,l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"asr\\t%0, %1, %2"
[(set_attr "length" "2")]
)
+(define_expand "lshrdi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:SI 2 "reg_or_int_operand" "")))]
+ "TARGET_32BIT"
+ "
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
+ DONE;
+ }
+ /* Ideally we shouldn't fail here if we could know that operands[1]
+ ends up already living in an iwmmxt register. Otherwise it's
+ cheaper to have the alternate code being generated than moving
+ values to iwmmxt regs and back. */
+ FAIL;
+ }
+ else if (!TARGET_REALLY_IWMMXT)
+ FAIL;
+ "
+)
+
+(define_insn "arm_lshrdi3_1bit"
+ [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
+ (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (const_int 1)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT"
+ "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
@@ -2536,11 +3274,11 @@
"
)
-(define_insn "*thumb_lshrsi3"
+(define_insn "*thumb1_lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=l,l")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
(match_operand:SI 2 "nonmemory_operand" "N,l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"lsr\\t%0, %1, %2"
[(set_attr "length" "2")]
)
@@ -2549,7 +3287,7 @@
[(set (match_operand:SI 0 "s_register_operand" "")
(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
(match_operand:SI 2 "reg_or_int_operand" "")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"
if (GET_CODE (operands[2]) == CONST_INT)
operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
@@ -2568,13 +3306,13 @@
(match_operand:SI 2 "arm_rhs_operand" "")))]
"TARGET_EITHER"
"
- if (TARGET_ARM)
+ if (TARGET_32BIT)
{
if (GET_CODE (operands[2]) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
}
- else /* TARGET_THUMB */
+ else /* TARGET_THUMB1 */
{
if (GET_CODE (operands [2]) == CONST_INT)
operands [2] = force_reg (SImode, operands[2]);
@@ -2582,11 +3320,11 @@
"
)
-(define_insn "*thumb_rotrsi3"
+(define_insn "*thumb1_rotrsi3"
[(set (match_operand:SI 0 "register_operand" "=l")
(rotatert:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "register_operand" "l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"ror\\t%0, %0, %2"
[(set_attr "length" "2")]
)
@@ -2596,11 +3334,13 @@
(match_operator:SI 3 "shift_operator"
[(match_operand:SI 1 "s_register_operand" "r")
(match_operand:SI 2 "reg_or_int_operand" "rM")]))]
- "TARGET_ARM"
- "mov%?\\t%0, %1%S3"
+ "TARGET_32BIT"
+ "* return arm_output_shift(operands, 0);"
[(set_attr "predicable" "yes")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*shiftsi3_compare0"
@@ -2611,11 +3351,13 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r")
(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
- "TARGET_ARM"
- "mov%?s\\t%0, %1%S3"
+ "TARGET_32BIT"
+ "* return arm_output_shift(operands, 1);"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*shiftsi3_compare0_scratch"
@@ -2625,14 +3367,13 @@
(match_operand:SI 2 "arm_rhs_operand" "rM")])
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "mov%?s\\t%0, %1%S3"
+ "TARGET_32BIT"
+ "* return arm_output_shift(operands, 1);"
[(set_attr "conds" "set")
- (set_attr "shift" "1")
- ]
+ (set_attr "shift" "1")]
)
-(define_insn "*notsi_shiftsi"
+(define_insn "*arm_notsi_shiftsi"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(not:SI (match_operator:SI 3 "shift_operator"
[(match_operand:SI 1 "s_register_operand" "r")
@@ -2641,10 +3382,12 @@
"mvn%?\\t%0, %1%S3"
[(set_attr "predicable" "yes")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
-(define_insn "*notsi_shiftsi_compare0"
+(define_insn "*arm_notsi_shiftsi_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
[(match_operand:SI 1 "s_register_operand" "r")
@@ -2653,13 +3396,15 @@
(set (match_operand:SI 0 "s_register_operand" "=r")
(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
"TARGET_ARM"
- "mvn%?s\\t%0, %1%S3"
+ "mvn%.\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
-(define_insn "*not_shiftsi_compare0_scratch"
+(define_insn "*arm_not_shiftsi_compare0_scratch"
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
[(match_operand:SI 1 "s_register_operand" "r")
@@ -2667,10 +3412,12 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"TARGET_ARM"
- "mvn%?s\\t%0, %1%S3"
+ "mvn%.\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
;; We don't really have extzv, but defining this using shifts helps
@@ -2683,12 +3430,19 @@
(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_dup 4)
(match_operand:SI 3 "const_int_operand" "")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1 || arm_arch_thumb2"
"
{
HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
+ if (arm_arch_thumb2)
+ {
+ emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
+
operands[3] = GEN_INT (rshift);
if (lshift == 0)
@@ -2702,6 +3456,28 @@
}"
)
+(define_insn "extv"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "M")
+ (match_operand:SI 3 "const_int_operand" "M")))]
+ "arm_arch_thumb2"
+ "sbfx%?\t%0, %1, %3, %2"
+ [(set_attr "length" "4")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "extzv_t2"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "M")
+ (match_operand:SI 3 "const_int_operand" "M")))]
+ "arm_arch_thumb2"
+ "ubfx%?\t%0, %1, %3, %2"
+ [(set_attr "length" "4")
+ (set_attr "predicable" "yes")]
+)
+
;; Unary arithmetic insns
@@ -2712,7 +3488,7 @@
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
"
- if (TARGET_THUMB)
+ if (TARGET_THUMB1)
{
if (GET_CODE (operands[1]) != REG)
operands[1] = force_reg (SImode, operands[1]);
@@ -2732,11 +3508,11 @@
(set_attr "length" "8")]
)
-(define_insn "*thumb_negdi2"
+(define_insn "*thumb1_negdi2"
[(set (match_operand:DI 0 "register_operand" "=&l")
(neg:DI (match_operand:DI 1 "register_operand" "l")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
[(set_attr "length" "6")]
)
@@ -2751,63 +3527,52 @@
(define_insn "*arm_negsi2"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"rsb%?\\t%0, %1, #0"
[(set_attr "predicable" "yes")]
)
-(define_insn "*thumb_negsi2"
+(define_insn "*thumb1_negsi2"
[(set (match_operand:SI 0 "register_operand" "=l")
(neg:SI (match_operand:SI 1 "register_operand" "l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"neg\\t%0, %1"
[(set_attr "length" "2")]
)
-(define_insn "negsf2"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "mnf%?s\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "negdf2"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "mnf%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*negdf_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (neg:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "mnf%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
+(define_expand "negsf2"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+ ""
)
-(define_insn "negxf2"
- [(set (match_operand:XF 0 "s_register_operand" "=f")
- (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "mnf%?e\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
+(define_expand "negdf2"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+ "")
;; abssi2 doesn't really clobber the condition codes if a different register
;; is being set. To keep things simple, assume during rtl manipulations that
;; it does, but tell the final scan operator the truth. Similarly for
;; (neg (abs...))
-(define_insn "abssi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
+(define_expand "abssi2"
+ [(parallel
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (abs:SI (match_operand:SI 1 "s_register_operand" "")))
+ (clobber (match_dup 2))])]
+ "TARGET_EITHER"
+ "
+ if (TARGET_THUMB1)
+ operands[2] = gen_rtx_SCRATCH (SImode);
+ else
+ operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
+")
+
+(define_insn "*arm_abssi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
@@ -2820,7 +3585,21 @@
(set_attr "length" "8")]
)
-(define_insn "*neg_abssi2"
+(define_insn_and_split "*thumb1_abssi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=l")
+ (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
+ (clobber (match_scratch:SI 2 "=&l"))]
+ "TARGET_THUMB1"
+ "#"
+ "TARGET_THUMB1 && reload_completed"
+ [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
+ ""
+ [(set_attr "length" "6")]
+)
+
+(define_insn "*arm_neg_abssi2"
[(set (match_operand:SI 0 "s_register_operand" "=r,&r")
(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
(clobber (reg:CC CC_REGNUM))]
@@ -2834,154 +3613,50 @@
(set_attr "length" "8")]
)
-(define_insn "abssf2"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "abs%?s\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "absdf2"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "abs%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*absdf_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (abs:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "abs%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "absxf2"
- [(set (match_operand:XF 0 "s_register_operand" "=f")
- (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "abs%?e\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "sqrtsf2"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "sqt%?s\\t%0, %1"
- [(set_attr "type" "float_em")
- (set_attr "predicable" "yes")]
+(define_insn_and_split "*thumb1_neg_abssi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=l")
+ (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
+ (clobber (match_scratch:SI 2 "=&l"))]
+ "TARGET_THUMB1"
+ "#"
+ "TARGET_THUMB1 && reload_completed"
+ [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
+ (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
+ (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
+ ""
+ [(set_attr "length" "6")]
)
-(define_insn "sqrtdf2"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "sqt%?d\\t%0, %1"
- [(set_attr "type" "float_em")
- (set_attr "predicable" "yes")]
-)
+(define_expand "abssf2"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "")
-(define_insn "*sqrtdf_esfdf"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (sqrt:DF (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "sqt%?d\\t%0, %1"
- [(set_attr "type" "float_em")
- (set_attr "predicable" "yes")]
-)
+(define_expand "absdf2"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "")
-(define_insn "sqrtxf2"
- [(set (match_operand:XF 0 "s_register_operand" "=f")
- (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "sqt%?e\\t%0, %1"
- [(set_attr "type" "float_em")
- (set_attr "predicable" "yes")]
-)
+(define_expand "sqrtsf2"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+ "")
-;; SIN COS TAN and family are always emulated, so it's probably better
-;; to always call a library function.
-;(define_insn "sinsf2"
-; [(set (match_operand:SF 0 "s_register_operand" "=f")
-; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
-; UNSPEC_SIN))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "sin%?s\\t%0, %1"
-;[(set_attr "type" "float_em")])
-;
-;(define_insn "sindf2"
-; [(set (match_operand:DF 0 "s_register_operand" "=f")
-; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
-; UNSPEC_SIN))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "sin%?d\\t%0, %1"
-;[(set_attr "type" "float_em")])
-;
-;(define_insn "*sindf_esfdf"
-; [(set (match_operand:DF 0 "s_register_operand" "=f")
-; (unspec:DF [(float_extend:DF
-; (match_operand:SF 1 "s_register_operand" "f"))]
-; UNSPEC_SIN))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "sin%?d\\t%0, %1"
-;[(set_attr "type" "float_em")])
-;
-;(define_insn "sinxf2"
-; [(set (match_operand:XF 0 "s_register_operand" "=f")
-; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
-; UNSPEC_SIN))]
-; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
-; "sin%?e\\t%0, %1"
-;[(set_attr "type" "float_em")])
-;
-;(define_insn "cossf2"
-; [(set (match_operand:SF 0 "s_register_operand" "=f")
-; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
-; UNSPEC_COS))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "cos%?s\\t%0, %1"
-;[(set_attr "type" "float_em")])
-;
-;(define_insn "cosdf2"
-; [(set (match_operand:DF 0 "s_register_operand" "=f")
-; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
-; UNSPEC_COS))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "cos%?d\\t%0, %1"
-;[(set_attr "type" "float_em")])
-;
-;(define_insn "*cosdf_esfdf"
-; [(set (match_operand:DF 0 "s_register_operand" "=f")
-; (unspec:DF [(float_extend:DF
-; (match_operand:SF 1 "s_register_operand" "f"))]
-; UNSPEC_COS))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "cos%?d\\t%0, %1"
-;[(set_attr "type" "float_em")])
-;
-;(define_insn "cosxf2"
-; [(set (match_operand:XF 0 "s_register_operand" "=f")
-; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
-; UNSEPC_COS))]
-; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
-; "cos%?e\\t%0, %1"
-;[(set_attr "type" "float_em")])
+(define_expand "sqrtdf2"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+ "")
(define_insn_and_split "one_cmpldi2"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"#"
- "TARGET_ARM && reload_completed"
+ "TARGET_32BIT && reload_completed"
[(set (match_dup 0) (not:SI (match_dup 1)))
(set (match_dup 2) (not:SI (match_dup 3)))]
"
@@ -3005,15 +3680,15 @@
(define_insn "*arm_one_cmplsi2"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(not:SI (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"mvn%?\\t%0, %1"
[(set_attr "predicable" "yes")]
)
-(define_insn "*thumb_one_cmplsi2"
+(define_insn "*thumb1_one_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "=l")
(not:SI (match_operand:SI 1 "register_operand" "l")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"mvn\\t%0, %1"
[(set_attr "length" "2")]
)
@@ -3024,8 +3699,8 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r")
(not:SI (match_dup 1)))]
- "TARGET_ARM"
- "mvn%?s\\t%0, %1"
+ "TARGET_32BIT"
+ "mvn%.\\t%0, %1"
[(set_attr "conds" "set")]
)
@@ -3034,102 +3709,87 @@
(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
- "mvn%?s\\t%0, %1"
+ "TARGET_32BIT"
+ "mvn%.\\t%0, %1"
[(set_attr "conds" "set")]
)
;; Fixed <--> Floating conversion insns
-(define_insn "floatsisf2"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "flt%?s\\t%0, %1"
- [(set_attr "type" "r_2_f")
- (set_attr "predicable" "yes")]
-)
+(define_expand "floatsisf2"
+ [(set (match_operand:SF 0 "s_register_operand" "")
+ (float:SF (match_operand:SI 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK)
+ {
+ emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
+ DONE;
+ }
+")
-(define_insn "floatsidf2"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "flt%?d\\t%0, %1"
- [(set_attr "type" "r_2_f")
- (set_attr "predicable" "yes")]
-)
+(define_expand "floatsidf2"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (float:DF (match_operand:SI 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK)
+ {
+ emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
+ DONE;
+ }
+")
-(define_insn "floatsixf2"
- [(set (match_operand:XF 0 "s_register_operand" "=f")
- (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "flt%?e\\t%0, %1"
- [(set_attr "type" "r_2_f")
- (set_attr "predicable" "yes")]
-)
+(define_expand "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK)
+ {
+ if (!cirrus_fp_register (operands[0], SImode))
+ operands[0] = force_reg (SImode, operands[0]);
+ if (!cirrus_fp_register (operands[1], SFmode))
+ operands[1] = force_reg (SFmode, operands[0]);
+ emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
+ DONE;
+ }
+")
-(define_insn "fix_truncsfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "fix%?z\\t%0, %1"
- [(set_attr "type" "f_2_r")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "fix_truncdfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "fix%?z\\t%0, %1"
- [(set_attr "type" "f_2_r")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "fix_truncxfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "fix%?z\\t%0, %1"
- [(set_attr "type" "f_2_r")
- (set_attr "predicable" "yes")]
-)
+(define_expand "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "
+ if (TARGET_MAVERICK)
+ {
+ if (!cirrus_fp_register (operands[1], DFmode))
+ operands[1] = force_reg (DFmode, operands[0]);
+ emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
+ DONE;
+ }
+")
;; Truncation insns
-(define_insn "truncdfsf2"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
- (float_truncate:SF
- (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "mvf%?s\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "truncxfsf2"
- [(set (match_operand:SF 0 "s_register_operand" "=f")
+(define_expand "truncdfsf2"
+ [(set (match_operand:SF 0 "s_register_operand" "")
(float_truncate:SF
- (match_operand:XF 1 "s_register_operand" "f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "mvf%?s\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "truncxfdf2"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (float_truncate:DF
- (match_operand:XF 1 "s_register_operand" "f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "mvf%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
+ (match_operand:DF 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ ""
)
;; Zero and sign extension instructions.
-(define_insn "zero_extendsidi2"
+(define_expand "zero_extendsidi2"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*arm_zero_extendsidi2"
[(set (match_operand:DI 0 "s_register_operand" "=r")
(zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_ARM"
@@ -3143,21 +3803,35 @@
(set_attr "predicable" "yes")]
)
-(define_insn "zero_extendqidi2"
+(define_expand "zero_extendqidi2"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*arm_zero_extendqidi2"
[(set (match_operand:DI 0 "s_register_operand" "=r,r")
(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
"TARGET_ARM"
"@
and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
- ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
+ ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
[(set_attr "length" "8")
(set_attr "predicable" "yes")
- (set_attr "type" "*,load")
+ (set_attr "type" "*,load_byte")
(set_attr "pool_range" "*,4092")
(set_attr "neg_pool_range" "*,4084")]
)
-(define_insn "extendsidi2"
+(define_expand "extendsidi2"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*arm_extendsidi2"
[(set (match_operand:DI 0 "s_register_operand" "=r")
(sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_ARM"
@@ -3181,72 +3855,38 @@
"TARGET_EITHER"
"
{
- if (TARGET_ARM)
+ if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
{
- if (arm_arch4 && GET_CODE (operands[1]) == MEM)
- {
- /* Note: We do not have to worry about TARGET_MMU_TRAPS
- here because the insn below will generate an LDRH instruction
- rather than an LDR instruction, so we cannot get an unaligned
- word access. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ZERO_EXTEND (SImode,
- operands[1])));
- DONE;
- }
- if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_movhi_bytes (operands[0], operands[1]));
- DONE;
- }
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_ZERO_EXTEND (SImode, operands[1])));
+ DONE;
}
- else /* TARGET_THUMB */
- {
- if (GET_CODE (operands[1]) == MEM)
- {
- rtx tmp;
- tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- emit_insn (tmp);
- }
- else
- {
- rtx ops[3];
-
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- ops[2] = GEN_INT (16);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
+ if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
+ {
+ emit_insn (gen_movhi_bytes (operands[0], operands[1]));
+ DONE;
+ }
- ops[0] = operands[0];
- ops[1] = operands[2];
- ops[2] = GEN_INT (16);
+ if (!s_register_operand (operands[1], HImode))
+ operands[1] = copy_to_mode_reg (HImode, operands[1]);
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_LSHIFTRT (SImode, ops[1],
- ops[2])));
- }
- DONE;
+ if (arm_arch6)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_ZERO_EXTEND (SImode, operands[1])));
+ DONE;
}
+
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode);
}"
)
-(define_insn "*thumb_zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_THUMB"
+(define_insn "*thumb1_zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_THUMB1 && !arm_arch6"
"*
rtx mem = XEXP (operands[1], 0);
@@ -3281,49 +3921,89 @@
return \"ldrh\\t%0, %1\";
"
[(set_attr "length" "4")
- (set_attr "type" "load")
+ (set_attr "type" "load_byte")
(set_attr "pool_range" "60")]
)
+(define_insn "*thumb1_zero_extendhisi2_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
+ "TARGET_THUMB1 && arm_arch6"
+ "*
+ rtx mem;
+
+ if (which_alternative == 0)
+ return \"uxth\\t%0, %1\";
+
+ mem = XEXP (operands[1], 0);
+
+ if (GET_CODE (mem) == CONST)
+ mem = XEXP (mem, 0);
+
+ if (GET_CODE (mem) == LABEL_REF)
+ return \"ldr\\t%0, %1\";
+
+ if (GET_CODE (mem) == PLUS)
+ {
+ rtx a = XEXP (mem, 0);
+ rtx b = XEXP (mem, 1);
+
+ /* This can happen due to bugs in reload. */
+ if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
+ {
+ rtx ops[2];
+ ops[0] = operands[0];
+ ops[1] = a;
+
+ output_asm_insn (\"mov %0, %1\", ops);
+
+ XEXP (mem, 0) = operands[0];
+ }
+
+ else if ( GET_CODE (a) == LABEL_REF
+ && GET_CODE (b) == CONST_INT)
+ return \"ldr\\t%0, %1\";
+ }
+
+ return \"ldrh\\t%0, %1\";
+ "
+ [(set_attr "length" "2,4")
+ (set_attr "type" "alu_shift,load_byte")
+ (set_attr "pool_range" "*,60")]
+)
+
(define_insn "*arm_zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_ARM && arm_arch4"
- "ldr%?h\\t%0, %1"
- [(set_attr "type" "load")
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_ARM && arm_arch4 && !arm_arch6"
+ "ldr%(h%)\\t%0, %1"
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (!arm_arch4)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
- "
- if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
- FAIL;
- "
+(define_insn "*arm_zero_extendhisi2_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_ARM && arm_arch6"
+ "@
+ uxth%?\\t%0, %1
+ ldr%(h%)\\t%0, %1"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")
+ (set_attr "pool_range" "*,256")
+ (set_attr "neg_pool_range" "*,244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 3 "shiftable_operator"
- [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
- (match_operand:SI 4 "s_register_operand" "")]))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (!arm_arch4)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0)
- (match_op_dup 3
- [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
- "
- if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
- FAIL;
- "
+(define_insn "*arm_zero_extendhisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_INT_SIMD"
+ "uxtah%?\\t%0, %2, %1"
+ [(set_attr "type" "alu_shift")
+ (set_attr "predicable" "yes")]
)
(define_expand "zero_extendqisi2"
@@ -3331,7 +4011,7 @@
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
"TARGET_EITHER"
"
- if (GET_CODE (operands[1]) != MEM)
+ if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
{
if (TARGET_ARM)
{
@@ -3366,32 +4046,78 @@
"
)
-(define_insn "*thumb_zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_THUMB"
+(define_insn "*thumb1_zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ "TARGET_THUMB1 && !arm_arch6"
"ldrb\\t%0, %1"
[(set_attr "length" "2")
- (set_attr "type" "load")
+ (set_attr "type" "load_byte")
(set_attr "pool_range" "32")]
)
+(define_insn "*thumb1_zero_extendqisi2_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
+ "TARGET_THUMB1 && arm_arch6"
+ "@
+ uxtb\\t%0, %1
+ ldrb\\t%0, %1"
+ [(set_attr "length" "2,2")
+ (set_attr "type" "alu_shift,load_byte")
+ (set_attr "pool_range" "*,32")]
+)
+
(define_insn "*arm_zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_ARM"
- "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
- [(set_attr "type" "load")
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ "TARGET_ARM && !arm_arch6"
+ "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
(set_attr "pool_range" "4096")
(set_attr "neg_pool_range" "4084")]
)
+(define_insn "*arm_zero_extendqisi2_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_ARM && arm_arch6"
+ "@
+ uxtb%(%)\\t%0, %1
+ ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")
+ (set_attr "pool_range" "*,4096")
+ (set_attr "neg_pool_range" "*,4084")]
+)
+
+(define_insn "*arm_zero_extendqisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_INT_SIMD"
+ "uxtab%?\\t%0, %2, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "insn" "xtab")
+ (set_attr "type" "alu_shift")]
+)
+
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
(clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
+ "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
+ ""
+)
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
+ (clobber (match_operand:SI 2 "s_register_operand" ""))]
+ "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
""
@@ -3401,7 +4127,7 @@
[(set (reg:CC_Z CC_REGNUM)
(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
(const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"tst\\t%0, #255"
[(set_attr "conds" "set")]
)
@@ -3416,55 +4142,51 @@
"TARGET_EITHER"
"
{
- if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
+ if (GET_CODE (operands[1]) == MEM)
{
- /* Note: We do not have to worry about TARGET_MMU_TRAPS
- here because the insn below will generate an LDRH instruction
- rather than an LDR instruction, so we cannot get an unaligned
- word access. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SIGN_EXTEND (SImode, operands[1])));
- DONE;
+ if (TARGET_THUMB1)
+ {
+ emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
+ DONE;
+ }
+ else if (arm_arch4)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SIGN_EXTEND (SImode, operands[1])));
+ DONE;
+ }
}
- if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
+ if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
{
emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
DONE;
}
+
if (!s_register_operand (operands[1], HImode))
operands[1] = copy_to_mode_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
- if (TARGET_THUMB)
+ if (arm_arch6)
{
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- ops[2] = GEN_INT (16);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
-
- ops[0] = operands[0];
- ops[1] = operands[2];
- ops[2] = GEN_INT (16);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
-
+ if (TARGET_THUMB1)
+ emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SIGN_EXTEND (SImode, operands[1])));
+
DONE;
}
+
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode);
}"
)
-(define_insn "*thumb_extendhisi2_insn"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- "TARGET_THUMB"
+(define_insn "thumb1_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
+ (clobber (match_scratch:SI 2 "=&l"))]
+ "TARGET_THUMB1 && !arm_arch6"
"*
{
rtx ops[4];
@@ -3501,12 +4223,8 @@
ops[1] = mem;
ops[2] = const0_rtx;
}
-
- if (GET_CODE (ops[1]) != REG)
- {
- debug_rtx (ops[1]);
- abort ();
- }
+
+ gcc_assert (GET_CODE (ops[1]) == REG);
ops[0] = operands[0];
ops[3] = operands[2];
@@ -3514,10 +4232,80 @@
return \"\";
}"
[(set_attr "length" "4")
- (set_attr "type" "load")
+ (set_attr "type" "load_byte")
(set_attr "pool_range" "1020")]
)
+;; We used to have an early-clobber on the scratch register here.
+;; However, there's a bug somewhere in reload which means that this
+;; can be partially ignored during spill allocation if the memory
+;; address also needs reloading; this causes us to die later on when
+;; we try to verify the operands. Fortunately, we don't really need
+;; the early-clobber: we can always use operand 0 if operand 2
+;; overlaps the address.
+(define_insn "*thumb1_extendhisi2_insn_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
+ (clobber (match_scratch:SI 2 "=X,l"))]
+ "TARGET_THUMB1 && arm_arch6"
+ "*
+ {
+ rtx ops[4];
+ rtx mem;
+
+ if (which_alternative == 0)
+ return \"sxth\\t%0, %1\";
+
+ mem = XEXP (operands[1], 0);
+
+ /* This code used to try to use 'V', and fix the address only if it was
+ offsettable, but this fails for e.g. REG+48 because 48 is outside the
+ range of QImode offsets, and offsettable_address_p does a QImode
+ address check. */
+
+ if (GET_CODE (mem) == CONST)
+ mem = XEXP (mem, 0);
+
+ if (GET_CODE (mem) == LABEL_REF)
+ return \"ldr\\t%0, %1\";
+
+ if (GET_CODE (mem) == PLUS)
+ {
+ rtx a = XEXP (mem, 0);
+ rtx b = XEXP (mem, 1);
+
+ if (GET_CODE (a) == LABEL_REF
+ && GET_CODE (b) == CONST_INT)
+ return \"ldr\\t%0, %1\";
+
+ if (GET_CODE (b) == REG)
+ return \"ldrsh\\t%0, %1\";
+
+ ops[1] = a;
+ ops[2] = b;
+ }
+ else
+ {
+ ops[1] = mem;
+ ops[2] = const0_rtx;
+ }
+
+ gcc_assert (GET_CODE (ops[1]) == REG);
+
+ ops[0] = operands[0];
+ if (reg_mentioned_p (operands[2], ops[1]))
+ ops[3] = ops[0];
+ else
+ ops[3] = operands[2];
+ output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
+ return \"\";
+ }"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "alu_shift,load_byte")
+ (set_attr "pool_range" "*,1020")]
+)
+
+;; This pattern will only be used when ldsh is not available
(define_expand "extendhisi2_mem"
[(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
(set (match_dup 3)
@@ -3531,10 +4319,8 @@
rtx mem1, mem2;
rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- mem1 = gen_rtx_MEM (QImode, addr);
- MEM_COPY_ATTRIBUTES (mem1, operands[1]);
- mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
- MEM_COPY_ATTRIBUTES (mem2, operands[1]);
+ mem1 = change_address (operands[1], QImode, addr);
+ mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = mem1;
operands[2] = gen_reg_rtx (SImode);
@@ -3555,49 +4341,42 @@
}"
)
-(define_insn "*arm_extendhisi_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_ARM && arm_arch4"
- "ldr%?sh\\t%0, %1"
- [(set_attr "type" "load")
+(define_insn "*arm_extendhisi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_ARM && arm_arch4 && !arm_arch6"
+ "ldr%(sh%)\\t%0, %1"
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (!arm_arch4)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
- "
- if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
- FAIL;
- "
+;; ??? Check Thumb-2 pool range
+(define_insn "*arm_extendhisi2_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_32BIT && arm_arch6"
+ "@
+ sxth%?\\t%0, %1
+ ldr%(sh%)\\t%0, %1"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")
+ (set_attr "pool_range" "*,256")
+ (set_attr "neg_pool_range" "*,244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 3 "shiftable_operator"
- [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
- (match_operand:SI 4 "s_register_operand" "")]))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (!arm_arch4)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0)
- (match_op_dup 3
- [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
- "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
- FAIL;
- "
+(define_insn "*arm_extendhisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_INT_SIMD"
+ "sxtah%?\\t%0, %2, %1"
)
(define_expand "extendqihi2"
[(set (match_dup 2)
- (ashift:SI (match_operand:QI 1 "general_operand" "")
+ (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
(const_int 24)))
(set (match_operand:HI 0 "s_register_operand" "")
(ashiftrt:SI (match_dup 2)
@@ -3620,62 +4399,20 @@
}"
)
-; Rather than restricting all byte accesses to memory addresses that ldrsb
-; can handle, we fix up the ones that ldrsb can't grok with a split.
-(define_insn "*extendqihi_insn"
- [(set (match_operand:HI 0 "s_register_operand" "=r")
- (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
+(define_insn "*arm_extendqihi_insn"
+ [(set (match_operand:HI 0 "s_register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
"TARGET_ARM && arm_arch4"
- "*
- /* If the address is invalid, this will split the instruction into two. */
- if (bad_signed_byte_operand (operands[1], VOIDmode))
- return \"#\";
- return \"ldr%?sb\\t%0, %1\";
- "
- [(set_attr "type" "load")
+ "ldr%(sb%)\\t%0, %1"
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
- (set_attr "length" "8")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
)
-(define_split
- [(set (match_operand:HI 0 "s_register_operand" "")
- (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
- "TARGET_ARM && arm_arch4 && reload_completed"
- [(set (match_dup 3) (match_dup 1))
- (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
- "
- {
- HOST_WIDE_INT offset;
-
- operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
- operands[2] = gen_rtx_MEM (QImode, operands[3]);
- MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
- operands[1] = XEXP (operands[1], 0);
- if (GET_CODE (operands[1]) == PLUS
- && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
- && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
- || const_ok_for_arm (-offset)))
- {
- HOST_WIDE_INT low = (offset > 0
- ? (offset & 0xff) : -((-offset) & 0xff));
- XEXP (operands[2], 0) = plus_constant (operands[3], low);
- operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
- }
- /* Ensure the sum is in correct canonical form */
- else if (GET_CODE (operands[1]) == PLUS
- && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
- && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
- operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
- XEXP (operands[1], 1),
- XEXP (operands[1], 0));
- }"
-)
-
(define_expand "extendqisi2"
[(set (match_dup 2)
- (ashift:SI (match_operand:QI 1 "general_operand" "")
+ (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
(const_int 24)))
(set (match_operand:SI 0 "s_register_operand" "")
(ashiftrt:SI (match_dup 2)
@@ -3683,97 +4420,68 @@
"TARGET_EITHER"
"
{
- if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
+ if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
{
- emit_insn (gen_rtx_SET (VOIDmode,
- operands[0],
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_SIGN_EXTEND (SImode, operands[1])));
DONE;
}
+
if (!s_register_operand (operands[1], QImode))
operands[1] = copy_to_mode_reg (QImode, operands[1]);
+
+ if (arm_arch6)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SIGN_EXTEND (SImode, operands[1])));
+ DONE;
+ }
+
operands[1] = gen_lowpart (SImode, operands[1]);
operands[2] = gen_reg_rtx (SImode);
-
- if (TARGET_THUMB)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- ops[2] = GEN_INT (24);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
+ }"
+)
- ops[0] = operands[0];
- ops[1] = operands[2];
- ops[2] = GEN_INT (24);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
-
- DONE;
- }
- }"
-)
-
-; Rather than restricting all byte accesses to memory addresses that ldrsb
-; can handle, we fix up the ones that ldrsb can't grok with a split.
-(define_insn "*arm_extendqisi_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_ARM && arm_arch4"
- "*
- /* If the address is invalid, this will split the instruction into two. */
- if (bad_signed_byte_operand (operands[1], VOIDmode))
- return \"#\";
- return \"ldr%?sb\\t%0, %1\";
- "
- [(set_attr "type" "load")
+(define_insn "*arm_extendqisi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
+ "TARGET_ARM && arm_arch4 && !arm_arch6"
+ "ldr%(sb%)\\t%0, %1"
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
- (set_attr "length" "8")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
- "TARGET_ARM && arm_arch4 && reload_completed"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
- "
- {
- HOST_WIDE_INT offset;
-
- operands[2] = gen_rtx_MEM (QImode, operands[0]);
- MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
- operands[1] = XEXP (operands[1], 0);
- if (GET_CODE (operands[1]) == PLUS
- && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
- && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
- || const_ok_for_arm (-offset)))
- {
- HOST_WIDE_INT low = (offset > 0
- ? (offset & 0xff) : -((-offset) & 0xff));
- XEXP (operands[2], 0) = plus_constant (operands[0], low);
- operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
- }
- /* Ensure the sum is in correct canonical form */
- else if (GET_CODE (operands[1]) == PLUS
- && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
- && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
- operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
- XEXP (operands[1], 1),
- XEXP (operands[1], 0));
- }"
+(define_insn "*arm_extendqisi_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (sign_extend:SI
+ (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
+ "TARGET_ARM && arm_arch6"
+ "@
+ sxtb%?\\t%0, %1
+ ldr%(sb%)\\t%0, %1"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")
+ (set_attr "pool_range" "*,256")
+ (set_attr "neg_pool_range" "*,244")]
+)
+
+(define_insn "*arm_extendqisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_INT_SIMD"
+ "sxtab%?\\t%0, %2, %1"
+ [(set_attr "type" "alu_shift")
+ (set_attr "insn" "xtab")
+ (set_attr "predicable" "yes")]
)
-(define_insn "*thumb_extendqisi2_insn"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- "TARGET_THUMB"
+(define_insn "*thumb1_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
+ "TARGET_THUMB1 && !arm_arch6"
"*
{
rtx ops[3];
@@ -3815,10 +4523,9 @@
else
output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
}
- else if (GET_CODE (b) != REG)
- abort ();
else
{
+ gcc_assert (GET_CODE (b) == REG);
if (REGNO (b) == REGNO (ops[0]))
{
output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
@@ -3845,37 +4552,96 @@
return \"\";
}"
[(set_attr "length" "2,6")
- (set_attr "type" "load,load")
+ (set_attr "type" "load_byte,load_byte")
(set_attr "pool_range" "32,32")]
)
-(define_insn "extendsfdf2"
- [(set (match_operand:DF 0 "s_register_operand" "=f")
- (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "mvf%?d\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
+(define_insn "*thumb1_extendqisi2_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l,l")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
+ "TARGET_THUMB1 && arm_arch6"
+ "*
+ {
+ rtx ops[3];
+ rtx mem;
-(define_insn "extendsfxf2"
- [(set (match_operand:XF 0 "s_register_operand" "=f")
- (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "mvf%?e\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
-)
+ if (which_alternative == 0)
+ return \"sxtb\\t%0, %1\";
-(define_insn "extenddfxf2"
- [(set (match_operand:XF 0 "s_register_operand" "=f")
- (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "mvf%?e\\t%0, %1"
- [(set_attr "type" "ffarith")
- (set_attr "predicable" "yes")]
+ mem = XEXP (operands[1], 0);
+
+ if (GET_CODE (mem) == CONST)
+ mem = XEXP (mem, 0);
+
+ if (GET_CODE (mem) == LABEL_REF)
+ return \"ldr\\t%0, %1\";
+
+ if (GET_CODE (mem) == PLUS
+ && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
+ return \"ldr\\t%0, %1\";
+
+ if (which_alternative == 0)
+ return \"ldrsb\\t%0, %1\";
+
+ ops[0] = operands[0];
+
+ if (GET_CODE (mem) == PLUS)
+ {
+ rtx a = XEXP (mem, 0);
+ rtx b = XEXP (mem, 1);
+
+ ops[1] = a;
+ ops[2] = b;
+
+ if (GET_CODE (a) == REG)
+ {
+ if (GET_CODE (b) == REG)
+ output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
+ else if (REGNO (a) == REGNO (ops[0]))
+ {
+ output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
+ output_asm_insn (\"sxtb\\t%0, %0\", ops);
+ }
+ else
+ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
+ }
+ else
+ {
+ gcc_assert (GET_CODE (b) == REG);
+ if (REGNO (b) == REGNO (ops[0]))
+ {
+ output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
+ output_asm_insn (\"sxtb\\t%0, %0\", ops);
+ }
+ else
+ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
+ }
+ }
+ else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
+ {
+ output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
+ output_asm_insn (\"sxtb\\t%0, %0\", ops);
+ }
+ else
+ {
+ ops[1] = mem;
+ ops[2] = const0_rtx;
+
+ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
+ }
+ return \"\";
+ }"
+ [(set_attr "length" "2,2,4")
+ (set_attr "type" "alu_shift,load_byte,load_byte")
+ (set_attr "pool_range" "*,32,32")]
)
+(define_expand "extendsfdf2"
+ [(set (match_operand:DF 0 "s_register_operand" "")
+ (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
+ ""
+)
;; Move insns (including loads and stores)
@@ -3913,7 +4679,7 @@
;; DONE;
;;}")
-;; Recognise garbage generated above.
+;; Recognize garbage generated above.
;;(define_insn ""
;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
@@ -3943,38 +4709,139 @@
(match_operand:DI 1 "general_operand" ""))]
"TARGET_EITHER"
"
- if (TARGET_THUMB)
+ if (can_create_pseudo_p ())
{
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
+ if (GET_CODE (operands[0]) != REG)
+ operands[1] = force_reg (DImode, operands[1]);
}
"
)
(define_insn "*arm_movdi"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
- (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
- "TARGET_ARM"
+ [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
+ (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
+ "TARGET_ARM
+ && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
+ && !TARGET_IWMMXT
+ && ( register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode))"
"*
- return (output_move_double (operands));
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ case 2:
+ return \"#\";
+ default:
+ return output_move_double (operands);
+ }
+ "
+ [(set_attr "length" "8,12,16,8,8")
+ (set_attr "type" "*,*,*,load2,store2")
+ (set_attr "pool_range" "*,*,*,1020,*")
+ (set_attr "neg_pool_range" "*,*,*,1008,*")]
+)
+
+(define_split
+ [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
+ (match_operand:ANY64 1 "const_double_operand" ""))]
+ "TARGET_32BIT
+ && reload_completed
+ && (arm_const_double_inline_cost (operands[1])
+ <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
+ [(const_int 0)]
+ "
+ arm_split_constant (SET, SImode, curr_insn,
+ INTVAL (gen_lowpart (SImode, operands[1])),
+ gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
+ arm_split_constant (SET, SImode, curr_insn,
+ INTVAL (gen_highpart_mode (SImode,
+ GET_MODE (operands[0]),
+ operands[1])),
+ gen_highpart (SImode, operands[0]), NULL_RTX, 0);
+ DONE;
+ "
+)
+
+; If optimizing for size, or if we have load delay slots, then
+; we want to split the constant into two separate operations.
+; In both cases this may split a trivial part into a single data op
+; leaving a single complex constant to load. We can also get longer
+; offsets in a LDR which means we get better chances of sharing the pool
+; entries. Finally, we can normally do a better job of scheduling
+; LDR instructions than we can with LDM.
+; This pattern will only match if the one above did not.
+(define_split
+ [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
+ (match_operand:ANY64 1 "const_double_operand" ""))]
+ "TARGET_ARM && reload_completed
+ && arm_const_double_by_parts (operands[1])"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))]
+ "
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
+ operands[1]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ "
+)
+
+(define_split
+ [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
+ (match_operand:ANY64 1 "arm_general_register_operand" ""))]
+ "TARGET_EITHER && reload_completed"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))]
+ "
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[3] = gen_highpart (SImode, operands[1]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+
+ /* Handle a partial overlap. */
+ if (rtx_equal_p (operands[0], operands[3]))
+ {
+ rtx tmp0 = operands[0];
+ rtx tmp1 = operands[1];
+
+ operands[0] = operands[2];
+ operands[1] = operands[3];
+ operands[2] = tmp0;
+ operands[3] = tmp1;
+ }
+ "
+)
+
+;; We can't actually do base+index doubleword loads if the index and
+;; destination overlap. Split here so that we at least have chance to
+;; schedule.
+(define_split
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "s_register_operand" ""))))]
+ "TARGET_LDRD
+ && reg_overlap_mentioned_p (operands[0], operands[1])
+ && reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 4)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (mem:DI (match_dup 4)))]
+ "
+ operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
"
- [(set_attr "length" "8")
- (set_attr "type" "*,load,store2")
- (set_attr "pool_range" "*,1020,*")
- (set_attr "neg_pool_range" "*,1008,*")]
)
;;; ??? This should have alternatives for constants.
;;; ??? This was originally identical to the movdf_insn pattern.
;;; ??? The 'i' constraint looks funny, but it should always be replaced by
;;; thumb_reorg with a memory reference.
-(define_insn "*thumb_movdi_insn"
+(define_insn "*thumb1_movdi_insn"
[(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
(match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
- "TARGET_THUMB
+ "TARGET_THUMB1
+ && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
&& ( register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
"*
@@ -3998,7 +4865,7 @@
case 5:
return thumb_load_double_from_address (operands);
case 6:
- operands[2] = gen_rtx (MEM, SImode,
+ operands[2] = gen_rtx_MEM (SImode,
plus_constant (XEXP (operands[0], 0), 4));
output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
return \"\";
@@ -4009,7 +4876,7 @@
}
}"
[(set_attr "length" "4,4,6,2,2,6,4,4")
- (set_attr "type" "*,*,*,load,store2,load,store2,*")
+ (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
(set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
)
@@ -4018,75 +4885,152 @@
(match_operand:SI 1 "general_operand" ""))]
"TARGET_EITHER"
"
- if (TARGET_ARM)
+ {
+ rtx base, offset, tmp;
+
+ if (TARGET_32BIT)
{
- /* Everything except mem = const or mem = mem can be done easily */
+ /* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SImode, operands[1]);
- if (GET_CODE (operands[1]) == CONST_INT
+ if (arm_general_register_operand (operands[0], SImode)
+ && GET_CODE (operands[1]) == CONST_INT
&& !(const_ok_for_arm (INTVAL (operands[1]))
|| const_ok_for_arm (~INTVAL (operands[1]))))
{
- arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
- NULL_RTX,
- (no_new_pseudos ? 0
- : preserve_subexpressions_p ()));
+ arm_split_constant (SET, SImode, NULL_RTX,
+ INTVAL (operands[1]), operands[0], NULL_RTX,
+ optimize && can_create_pseudo_p ());
DONE;
}
+
+ if (TARGET_USE_MOVT && !target_word_relocations
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && !flag_pic && !arm_tls_referenced_p (operands[1]))
+ {
+ arm_emit_movpair (operands[0], operands[1]);
+ DONE;
+ }
}
- else /* TARGET_THUMB.... */
+ else /* TARGET_THUMB1... */
{
- if (!no_new_pseudos)
+ if (can_create_pseudo_p ())
{
if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (SImode, operands[1]);
}
}
-
- if (flag_pic
- && (CONSTANT_P (operands[1])
- || symbol_mentioned_p (operands[1])
- || label_mentioned_p (operands[1])))
- operands[1] = legitimize_pic_address (operands[1], SImode,
- (no_new_pseudos ? operands[0] : 0));
+
+ if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
+ {
+ split_const (operands[1], &base, &offset);
+ if (GET_CODE (base) == SYMBOL_REF
+ && !offset_within_block_p (base, INTVAL (offset)))
+ {
+ tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
+ emit_move_insn (tmp, base);
+ emit_insn (gen_addsi3 (operands[0], tmp, offset));
+ DONE;
+ }
+ }
+
+ /* Recognize the case where operand[1] is a reference to thread-local
+ data and load its address to a register. */
+ if (arm_tls_referenced_p (operands[1]))
+ {
+ rtx tmp = operands[1];
+ rtx addend = NULL;
+
+ if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
+ {
+ addend = XEXP (XEXP (tmp, 0), 1);
+ tmp = XEXP (XEXP (tmp, 0), 0);
+ }
+
+ gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
+ gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
+
+ tmp = legitimize_tls_address (tmp,
+ !can_create_pseudo_p () ? operands[0] : 0);
+ if (addend)
+ {
+ tmp = gen_rtx_PLUS (SImode, tmp, addend);
+ tmp = force_operand (tmp, operands[0]);
+ }
+ operands[1] = tmp;
+ }
+ else if (flag_pic
+ && (CONSTANT_P (operands[1])
+ || symbol_mentioned_p (operands[1])
+ || label_mentioned_p (operands[1])))
+ operands[1] = legitimize_pic_address (operands[1], SImode,
+ (!can_create_pseudo_p ()
+ ? operands[0]
+ : 0));
+ }
"
)
+;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
+;; LO_SUM adds in the high bits. Fortunately these are opaque operations
+;; so this does not matter.
+(define_insn "*arm_movt"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:SI 2 "general_operand" "i")))]
+ "TARGET_32BIT"
+ "movt%?\t%0, #:upper16:%c2"
+ [(set_attr "predicable" "yes")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*arm_movw"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+ (high:SI (match_operand:SI 1 "general_operand" "i")))]
+ "TARGET_32BIT"
+ "movw%?\t%0, #:lower16:%c1"
+ [(set_attr "predicable" "yes")
+ (set_attr "length" "4")]
+)
+
(define_insn "*arm_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
- "TARGET_ARM
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
+ (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk"))]
+ "TARGET_ARM && ! TARGET_IWMMXT
+ && !(TARGET_HARD_FLOAT && TARGET_VFP)
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"@
+ mov%?\\t%0, %1
mov%?\\t%0, %1
mvn%?\\t%0, #%B1
+ movw%?\\t%0, %1
ldr%?\\t%0, %1
str%?\\t%1, %0"
- [(set_attr "type" "*,*,load,store1")
+ [(set_attr "type" "*,*,*,*,load1,store1")
(set_attr "predicable" "yes")
- (set_attr "pool_range" "*,*,4096,*")
- (set_attr "neg_pool_range" "*,*,4084,*")]
+ (set_attr "pool_range" "*,*,*,*,4096,*")
+ (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
)
(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "arm_general_register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_ARM
+ "TARGET_32BIT
&& (!(const_ok_for_arm (INTVAL (operands[1]))
|| const_ok_for_arm (~INTVAL (operands[1]))))"
[(clobber (const_int 0))]
"
- arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
- NULL_RTX, 0);
+ arm_split_constant (SET, SImode, NULL_RTX,
+ INTVAL (operands[1]), operands[0], NULL_RTX, 0);
DONE;
"
)
-(define_insn "*thumb_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
- (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
- "TARGET_THUMB
+(define_insn "*thumb1_movsi_insn"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
+ (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
+ "TARGET_THUMB1
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"@
@@ -4100,14 +5044,14 @@
str\\t%1, %0
mov\\t%0, %1"
[(set_attr "length" "2,2,4,4,2,2,2,2,2")
- (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
+ (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
(set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
)
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
+ "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 0) (neg:SI (match_dup 0)))]
"operands[1] = GEN_INT (- INTVAL (operands[1]));"
@@ -4116,7 +5060,7 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
+ "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
"
@@ -4129,6 +5073,7 @@
if ((val & (mask << i)) == val)
break;
+ /* Shouldn't happen, but we don't want to split if the shift is zero. */
if (i == 0)
FAIL;
@@ -4151,85 +5096,104 @@
(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
"TARGET_ARM && flag_pic"
"ldr%?\\t%0, %1"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
(set (attr "pool_range") (const_int 4096))
(set (attr "neg_pool_range") (const_int 4084))]
)
-(define_insn "pic_load_addr_thumb"
+(define_insn "pic_load_addr_thumb1"
[(set (match_operand:SI 0 "s_register_operand" "=l")
(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
- "TARGET_THUMB && flag_pic"
+ "TARGET_THUMB1 && flag_pic"
"ldr\\t%0, %1"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
(set (attr "pool_range") (const_int 1024))]
)
-;; This variant is used for AOF assembly, since it needs to mention the
-;; pic register in the rtl.
-(define_expand "pic_load_addr_based"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
- "TARGET_ARM && flag_pic"
- "operands[2] = pic_offset_table_rtx;"
-)
-
-(define_insn "*pic_load_addr_based_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (unspec:SI [(match_operand 1 "" "")
- (match_operand 2 "s_register_operand" "r")]
- UNSPEC_PIC_SYM))]
- "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
- "*
-#ifdef AOF_ASSEMBLER
- operands[1] = aof_pic_entry (operands[1]);
-#endif
- output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
- return \"\";
- "
- [(set_attr "type" "load")
- (set (attr "pool_range")
- (if_then_else (eq_attr "is_thumb" "yes")
- (const_int 1024)
- (const_int 4096)))
- (set (attr "neg_pool_range")
- (if_then_else (eq_attr "is_thumb" "yes")
- (const_int 0)
- (const_int 4084)))]
-)
-
(define_insn "pic_add_dot_plus_four"
- [(set (match_operand:SI 0 "register_operand" "+r")
- (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
- (use (label_ref (match_operand 1 "" "")))]
- "TARGET_THUMB && flag_pic"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "0")
+ (const_int 4)
+ (match_operand 2 "" "")]
+ UNSPEC_PIC_BASE))]
+ "TARGET_THUMB1"
"*
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (operands[1]));
+ (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
+ INTVAL (operands[2]));
return \"add\\t%0, %|pc\";
"
[(set_attr "length" "2")]
)
(define_insn "pic_add_dot_plus_eight"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
+ (match_operand 2 "" "")]
+ UNSPEC_PIC_BASE))]
+ "TARGET_ARM"
+ "*
+ (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
+ INTVAL (operands[2]));
+ return \"add%?\\t%0, %|pc, %1\";
+ "
+ [(set_attr "predicable" "yes")]
+)
+
+(define_insn "tls_load_dot_plus_eight"
[(set (match_operand:SI 0 "register_operand" "+r")
- (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
- (use (label_ref (match_operand 1 "" "")))]
- "TARGET_ARM && flag_pic"
+ (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
+ (match_operand 2 "" "")]
+ UNSPEC_PIC_BASE)))]
+ "TARGET_ARM"
"*
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (operands[1]));
- return \"add%?\\t%0, %|pc, %0\";
+ (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
+ INTVAL (operands[2]));
+ return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
"
[(set_attr "predicable" "yes")]
)
+;; PIC references to local variables can generate pic_add_dot_plus_eight
+;; followed by a load. These sequences can be crunched down to
+;; tls_load_dot_plus_eight by a peephole.
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(match_operand:SI 3 "register_operand" "")
+ (const_int 8)
+ (match_operand 1 "" "")]
+ UNSPEC_PIC_BASE))
+ (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
+ "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
+ [(set (match_dup 2)
+ (mem:SI (unspec:SI [(match_dup 3)
+ (const_int 8)
+ (match_dup 1)]
+ UNSPEC_PIC_BASE)))]
+ ""
+)
+
+(define_insn "pic_offset_arm"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "" "X")]
+ UNSPEC_PIC_OFFSET))))]
+ "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
+ "ldr%?\\t%0, [%1,%2]"
+ [(set_attr "type" "load1")]
+)
+
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"flag_pic"
"
{
- arm_finalize_pic (0);
+ /* r3 is clobbered by set/longjmp, so we can use it as a scratch
+ register. */
+ if (arm_pic_register != INVALID_REGNUM)
+ arm_load_pic_register (1UL << 3);
DONE;
}")
@@ -4243,10 +5207,10 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(match_dup 1))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
cmp%?\\t%0, #0
- sub%?s\\t%0, %1, #0"
+ sub%.\\t%0, %1, #0"
[(set_attr "conds" "set")]
)
@@ -4265,7 +5229,7 @@
(set (match_dup 2)
(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
;; store the high byte
- (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
+ (set (match_dup 4) (match_dup 5))]
"TARGET_ARM"
"
{
@@ -4281,7 +5245,8 @@
operands[1] = adjust_address (operands[1], QImode, 0);
operands[3] = gen_lowpart (QImode, operands[0]);
operands[0] = gen_lowpart (SImode, operands[0]);
- operands[2] = gen_reg_rtx (SImode);
+ operands[2] = gen_reg_rtx (SImode);
+ operands[5] = gen_lowpart (QImode, operands[2]);
}"
)
@@ -4289,7 +5254,7 @@
[(set (match_dup 4) (match_dup 3))
(set (match_dup 2)
(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
- (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
+ (set (match_operand 1 "" "") (match_dup 5))]
"TARGET_ARM"
"
{
@@ -4306,13 +5271,14 @@
operands[3] = gen_lowpart (QImode, operands[0]);
operands[0] = gen_lowpart (SImode, operands[0]);
operands[2] = gen_reg_rtx (SImode);
+ operands[5] = gen_lowpart (QImode, operands[2]);
}"
)
;; Subroutine to store a half word integer constant into memory.
(define_expand "storeinthi"
[(set (match_operand 0 "" "")
- (subreg:QI (match_operand 1 "" "") 0))
+ (match_operand 1 "" ""))
(set (match_dup 3) (match_dup 2))]
"TARGET_ARM"
"
@@ -4353,13 +5319,14 @@
operands[3] = adjust_address (op0, QImode, 1);
operands[0] = adjust_address (operands[0], QImode, 0);
operands[2] = gen_lowpart (QImode, operands[2]);
+ operands[1] = gen_lowpart (QImode, operands[1]);
}"
)
(define_expand "storehi_single_op"
[(set (match_operand:HI 0 "memory_operand" "")
(match_operand:HI 1 "general_operand" ""))]
- "TARGET_ARM && arm_arch4"
+ "TARGET_32BIT && arm_arch4"
"
if (!s_register_operand (operands[1], HImode))
operands[1] = copy_to_mode_reg (HImode, operands[1]);
@@ -4373,7 +5340,7 @@
"
if (TARGET_ARM)
{
- if (!no_new_pseudos)
+ if (can_create_pseudo_p ())
{
if (GET_CODE (operands[0]) == MEM)
{
@@ -4417,115 +5384,95 @@
emit_insn (gen_movsi (reg, GEN_INT (val)));
operands[1] = gen_lowpart (HImode, reg);
}
+ else if (arm_arch4 && optimize && can_create_pseudo_p ()
+ && GET_CODE (operands[1]) == MEM)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
else if (!arm_arch4)
{
- /* Note: We do not have to worry about TARGET_MMU_TRAPS
- for v4 and up architectures because LDRH instructions will
- be used to access the HI values, and these cannot generate
- unaligned word access faults in the MMU. */
if (GET_CODE (operands[1]) == MEM)
{
- if (TARGET_MMU_TRAPS)
- {
- rtx base;
- rtx offset = const0_rtx;
- rtx reg = gen_reg_rtx (SImode);
-
- if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
- || (GET_CODE (base) == PLUS
- && (GET_CODE (offset = XEXP (base, 1))
- == CONST_INT)
- && ((INTVAL(offset) & 1) != 1)
- && GET_CODE (base = XEXP (base, 0)) == REG))
- && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
- {
- HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
- rtx new;
-
- new = gen_rtx_MEM (SImode,
- plus_constant (base, new_offset));
- MEM_COPY_ATTRIBUTES (new, operands[1]);
- emit_insn (gen_movsi (reg, new));
- if (((INTVAL (offset) & 2) != 0)
- ^ (BYTES_BIG_ENDIAN ? 1 : 0))
- {
- rtx reg2 = gen_reg_rtx (SImode);
-
- emit_insn (gen_lshrsi3 (reg2, reg,
- GEN_INT (16)));
- reg = reg2;
- }
- }
- else
- emit_insn (gen_movhi_bytes (reg, operands[1]));
-
- operands[1] = gen_lowpart (HImode, reg);
- }
- else if (BYTES_BIG_ENDIAN)
+ rtx base;
+ rtx offset = const0_rtx;
+ rtx reg = gen_reg_rtx (SImode);
+
+ if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
+ || (GET_CODE (base) == PLUS
+ && (GET_CODE (offset = XEXP (base, 1))
+ == CONST_INT)
+ && ((INTVAL(offset) & 1) != 1)
+ && GET_CODE (base = XEXP (base, 0)) == REG))
+ && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
{
- rtx base;
- rtx offset = const0_rtx;
-
- if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
- || (GET_CODE (base) == PLUS
- && (GET_CODE (offset = XEXP (base, 1))
- == CONST_INT)
- && GET_CODE (base = XEXP (base, 0)) == REG))
- && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
- {
- rtx reg = gen_reg_rtx (SImode);
- rtx new;
-
- if ((INTVAL (offset) & 2) == 2)
- {
- HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
- new = gen_rtx_MEM (SImode,
- plus_constant (base,
- new_offset));
- MEM_COPY_ATTRIBUTES (new, operands[1]);
- emit_insn (gen_movsi (reg, new));
- }
- else
- {
- new = gen_rtx_MEM (SImode,
- XEXP (operands[1], 0));
- MEM_COPY_ATTRIBUTES (new, operands[1]);
- emit_insn (gen_rotated_loadsi (reg, new));
- }
-
- operands[1] = gen_lowpart (HImode, reg);
- }
- else
- {
- emit_insn (gen_movhi_bigend (operands[0],
- operands[1]));
- DONE;
- }
+ rtx new_rtx;
+
+ new_rtx = widen_memory_access (operands[1], SImode,
+ ((INTVAL (offset) & ~3)
+ - INTVAL (offset)));
+ emit_insn (gen_movsi (reg, new_rtx));
+ if (((INTVAL (offset) & 2) != 0)
+ ^ (BYTES_BIG_ENDIAN ? 1 : 0))
+ {
+ rtx reg2 = gen_reg_rtx (SImode);
+
+ emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
+ reg = reg2;
+ }
}
+ else
+ emit_insn (gen_movhi_bytes (reg, operands[1]));
+
+ operands[1] = gen_lowpart (HImode, reg);
}
}
}
- /* Handle loading a large integer during reload */
+ /* Handle loading a large integer during reload. */
else if (GET_CODE (operands[1]) == CONST_INT
&& !const_ok_for_arm (INTVAL (operands[1]))
&& !const_ok_for_arm (~INTVAL (operands[1])))
{
/* Writing a constant to memory needs a scratch, which should
be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
+ gcc_assert (GET_CODE (operands[0]) == REG);
operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
emit_insn (gen_movsi (operands[0], operands[1]));
DONE;
}
}
- else /* TARGET_THUMB */
+ else if (TARGET_THUMB2)
{
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
+ /* Thumb-2 can do everything except mem=mem and mem=const easily. */
+ if (can_create_pseudo_p ())
+ {
+ if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (HImode, operands[1]);
+ /* Zero extend a constant, and keep it in an SImode reg. */
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+ HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
+
+ emit_insn (gen_movsi (reg, GEN_INT (val)));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
+ }
+ }
+ else /* TARGET_THUMB1 */
+ {
+ if (can_create_pseudo_p ())
+ {
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
/* ??? We shouldn't really get invalid addresses here, but this can
happen if we are passed a SP (never OK for HImode/QImode) or
@@ -4548,17 +5495,28 @@
operands[1]
= replace_equiv_address (operands[1],
copy_to_reg (XEXP (operands[1], 0)));
+
+ if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
+
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (HImode, operands[1]);
}
- /* Handle loading a large integer during reload */
else if (GET_CODE (operands[1]) == CONST_INT
- && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
+ && !satisfies_constraint_I (operands[1]))
{
+ /* Handle loading a large integer during reload. */
+
/* Writing a constant to memory needs a scratch, which should
be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
+ gcc_assert (GET_CODE (operands[0]) == REG);
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
+ operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
emit_insn (gen_movsi (operands[0], operands[1]));
DONE;
}
@@ -4566,10 +5524,10 @@
"
)
-(define_insn "*thumb_movhi_insn"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
- (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
- "TARGET_THUMB
+(define_insn "*thumb1_movhi_insn"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
+ (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
+ "TARGET_THUMB1
&& ( register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))"
"*
@@ -4580,7 +5538,7 @@
case 3: return \"mov %0, %1\";
case 4: return \"mov %0, %1\";
case 5: return \"mov %0, %1\";
- default: abort ();
+ default: gcc_unreachable ();
case 1:
/* The stack pointer can end up being taken as an index register.
Catch this case here and deal with it. */
@@ -4600,29 +5558,10 @@
return \"ldrh %0, %1\";
}"
[(set_attr "length" "2,4,2,2,2,2")
- (set_attr "type" "*,load,store1,*,*,*")
- (set_attr "pool_range" "*,64,*,*,*,*")]
+ (set_attr "type" "*,load1,store1,*,*,*")]
)
-(define_insn "rotated_loadsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
- (const_int 16)))]
- "TARGET_ARM && (!TARGET_MMU_TRAPS)"
- "*
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
- output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
- return \"\";
- }"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
(define_expand "movhi_bytes"
[(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
(set (match_dup 3)
@@ -4635,10 +5574,8 @@
rtx mem1, mem2;
rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- mem1 = gen_rtx_MEM (QImode, addr);
- MEM_COPY_ATTRIBUTES (mem1, operands[1]);
- mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
- MEM_COPY_ATTRIBUTES (mem2, operands[1]);
+ mem1 = change_address (operands[1], QImode, addr);
+ mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = mem1;
operands[2] = gen_reg_rtx (SImode);
@@ -4665,15 +5602,16 @@
(set (match_dup 3)
(ashiftrt:SI (match_dup 2) (const_int 16)))
(set (match_operand:HI 0 "s_register_operand" "")
- (subreg:HI (match_dup 3) 0))]
+ (match_dup 4))]
"TARGET_ARM"
"
operands[2] = gen_reg_rtx (SImode);
operands[3] = gen_reg_rtx (SImode);
+ operands[4] = gen_lowpart (HImode, operands[3]);
"
)
-;; Pattern to recognise insn generated default case above
+;; Pattern to recognize insn generated default case above
(define_insn "*movhi_insn_arch4"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
(match_operand:HI 1 "general_operand" "rI,K,r,m"))]
@@ -4685,86 +5623,39 @@
"@
mov%?\\t%0, %1\\t%@ movhi
mvn%?\\t%0, #%B1\\t%@ movhi
- str%?h\\t%1, %0\\t%@ movhi
- ldr%?h\\t%0, %1\\t%@ movhi"
- [(set_attr "type" "*,*,store1,load")
+ str%(h%)\\t%1, %0\\t%@ movhi
+ ldr%(h%)\\t%0, %1\\t%@ movhi"
+ [(set_attr "type" "*,*,store1,load1")
(set_attr "predicable" "yes")
(set_attr "pool_range" "*,*,*,256")
(set_attr "neg_pool_range" "*,*,*,244")]
)
-(define_insn "*movhi_insn_littleend"
- [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
- (match_operand:HI 1 "general_operand" "rI,K,m"))]
- "TARGET_ARM
- && !arm_arch4
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && (GET_CODE (operands[1]) != CONST_INT
- || const_ok_for_arm (INTVAL (operands[1]))
- || const_ok_for_arm (~INTVAL (operands[1])))"
- "@
- mov%?\\t%0, %1\\t%@ movhi
- mvn%?\\t%0, #%B1\\t%@ movhi
- ldr%?\\t%0, %1\\t%@ movhi"
- [(set_attr "type" "*,*,load")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "4096")
- (set_attr "neg_pool_range" "4084")]
-)
-
-(define_insn "*movhi_insn_bigend"
- [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
- (match_operand:HI 1 "general_operand" "rI,K,m"))]
- "TARGET_ARM
- && !arm_arch4
- && BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && (GET_CODE (operands[1]) != CONST_INT
- || const_ok_for_arm (INTVAL (operands[1]))
- || const_ok_for_arm (~INTVAL (operands[1])))"
- "@
- mov%?\\t%0, %1\\t%@ movhi
- mvn%?\\t%0, #%B1\\t%@ movhi
- ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
- [(set_attr "type" "*,*,load")
- (set_attr "predicable" "yes")
- (set_attr "length" "4,4,8")
- (set_attr "pool_range" "*,*,4092")
- (set_attr "neg_pool_range" "*,*,4084")]
-)
-
-(define_insn "*loadhi_si_bigend"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
- (const_int 16)))]
- "TARGET_ARM
- && BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS"
- "ldr%?\\t%0, %1\\t%@ movhi_bigend"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "4096")
- (set_attr "neg_pool_range" "4084")]
-)
-
(define_insn "*movhi_bytes"
[(set (match_operand:HI 0 "s_register_operand" "=r,r")
(match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
- "TARGET_ARM && TARGET_MMU_TRAPS"
+ "TARGET_ARM"
"@
mov%?\\t%0, %1\\t%@ movhi
mvn%?\\t%0, #%B1\\t%@ movhi"
[(set_attr "predicable" "yes")]
)
-(define_insn "thumb_movhi_clobber"
- [(set (match_operand:HI 0 "memory_operand" "=m")
- (match_operand:HI 1 "register_operand" "l"))
- (clobber (match_operand:SI 2 "register_operand" "=&l"))]
- "TARGET_THUMB"
- "*
- abort ();"
+(define_expand "thumb_movhi_clobber"
+ [(set (match_operand:HI 0 "memory_operand" "")
+ (match_operand:HI 1 "register_operand" ""))
+ (clobber (match_operand:DI 2 "register_operand" ""))]
+ "TARGET_THUMB1"
+ "
+ if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
+ && REGNO (operands[1]) <= LAST_LO_REGNUM)
+ {
+ emit_insn (gen_movhi (operands[0], operands[1]));
+ DONE;
+ }
+ /* XXX Fixme, need to handle other cases here as well. */
+ gcc_unreachable ();
+ "
)
;; We use a DImode scratch because we may occasionally need an additional
@@ -4787,7 +5678,7 @@
[(parallel [(match_operand:HI 0 "s_register_operand" "=r")
(match_operand:HI 1 "arm_reload_memory_operand" "o")
(match_operand:DI 2 "s_register_operand" "=&r")])]
- "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
+ "TARGET_EITHER"
"
if (TARGET_ARM)
arm_reload_in_hi (operands);
@@ -4801,30 +5692,20 @@
(match_operand:QI 1 "general_operand" ""))]
"TARGET_EITHER"
"
- if (TARGET_ARM)
- {
- /* Everything except mem = const or mem = mem can be done easily */
-
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- rtx reg = gen_reg_rtx (SImode);
+ /* Everything except mem = const or mem = mem can be done easily */
- emit_insn (gen_movsi (reg, operands[1]));
- operands[1] = gen_lowpart (QImode, reg);
- }
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
- }
- }
- else /* TARGET_THUMB */
+ if (can_create_pseudo_p ())
{
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (QImode, operands[1]);
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+ if (TARGET_THUMB)
+ {
/* ??? We shouldn't really get invalid addresses here, but this can
happen if we are passed a SP (never OK for HImode/QImode) or
virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
@@ -4845,20 +5726,32 @@
operands[1]
= replace_equiv_address (operands[1],
copy_to_reg (XEXP (operands[1], 0)));
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
+ }
- operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
+ if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (QImode, operands[1]);
+ }
+ else if (TARGET_THUMB
+ && GET_CODE (operands[1]) == CONST_INT
+ && !satisfies_constraint_I (operands[1]))
+ {
+ /* Handle loading a large integer during reload. */
+
+ /* Writing a constant to memory needs a scratch, which should
+ be handled with SECONDARY_RELOADs. */
+ gcc_assert (GET_CODE (operands[0]) == REG);
+
+ operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
+ emit_insn (gen_movsi (operands[0], operands[1]));
+ DONE;
}
"
)
@@ -4867,22 +5760,22 @@
(define_insn "*arm_movqi_insn"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
- "TARGET_ARM
+ "TARGET_32BIT
&& ( register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))"
"@
mov%?\\t%0, %1
mvn%?\\t%0, #%B1
- ldr%?b\\t%0, %1
- str%?b\\t%1, %0"
- [(set_attr "type" "*,*,load,store1")
+ ldr%(b%)\\t%0, %1
+ str%(b%)\\t%1, %0"
+ [(set_attr "type" "*,*,load1,store1")
(set_attr "predicable" "yes")]
)
-(define_insn "*thumb_movqi_insn"
+(define_insn "*thumb1_movqi_insn"
[(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
(match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
- "TARGET_THUMB
+ "TARGET_THUMB1
&& ( register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))"
"@
@@ -4893,7 +5786,7 @@
mov\\t%0, %1
mov\\t%0, %1"
[(set_attr "length" "2")
- (set_attr "type" "*,load,store1,*,*,*")
+ (set_attr "type" "*,load1,store1,*,*,*")
(set_attr "pool_range" "*,32,*,*,*,*")]
)
@@ -4902,14 +5795,14 @@
(match_operand:SF 1 "general_operand" ""))]
"TARGET_EITHER"
"
- if (TARGET_ARM)
+ if (TARGET_32BIT)
{
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
}
- else /* TARGET_THUMB */
+ else /* TARGET_THUMB1 */
{
- if (!no_new_pseudos)
+ if (can_create_pseudo_p ())
{
if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (SFmode, operands[1]);
@@ -4918,11 +5811,12 @@
"
)
+;; Transform a floating-point move of a constant into a core register into
+;; an SImode operation.
(define_split
- [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ [(set (match_operand:SF 0 "arm_general_register_operand" "")
(match_operand:SF 1 "immediate_operand" ""))]
- "TARGET_ARM
- && !TARGET_HARD_FLOAT
+ "TARGET_32BIT
&& reload_completed
&& GET_CODE (operands[1]) == CONST_DOUBLE"
[(set (match_dup 2) (match_dup 3))]
@@ -4934,35 +5828,6 @@
"
)
-(define_insn "*arm_movsf_hard_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
- (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
- "TARGET_ARM
- && TARGET_HARD_FLOAT
- && (GET_CODE (operands[0]) != MEM
- || register_operand (operands[1], SFmode))"
- "@
- mvf%?s\\t%0, %1
- mnf%?s\\t%0, #%N1
- ldf%?s\\t%0, %1
- stf%?s\\t%1, %0
- str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
- stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
- mov%?\\t%0, %1
- ldr%?\\t%0, %1\\t%@ float
- str%?\\t%1, %0\\t%@ float"
- [(set_attr "length" "4,4,4,4,8,8,4,4,4")
- (set_attr "predicable" "yes")
- (set_attr "type"
- "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
- (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
- (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
-)
-
-;; Exactly the same as above, except that all `f' cases are deleted.
-;; This is necessary to prevent reload from ever trying to use a `f' reg
-;; when -msoft-float.
-
(define_insn "*arm_movsf_soft_insn"
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
(match_operand:SF 1 "general_operand" "r,mE,r"))]
@@ -4976,16 +5841,16 @@
str%?\\t%1, %0\\t%@ float"
[(set_attr "length" "4,4,4")
(set_attr "predicable" "yes")
- (set_attr "type" "*,load,store1")
+ (set_attr "type" "*,load1,store1")
(set_attr "pool_range" "*,4096,*")
(set_attr "neg_pool_range" "*,4084,*")]
)
;;; ??? This should have alternatives for constants.
-(define_insn "*thumb_movsf_insn"
+(define_insn "*thumb1_movsf_insn"
[(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
(match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
- "TARGET_THUMB
+ "TARGET_THUMB1
&& ( register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))"
"@
@@ -4997,7 +5862,7 @@
mov\\t%0, %1
mov\\t%0, %1"
[(set_attr "length" "2")
- (set_attr "type" "*,load,store1,load,store1,*,*")
+ (set_attr "type" "*,load1,store1,load1,store1,*,*")
(set_attr "pool_range" "*,*,*,1020,*,*,*")]
)
@@ -5006,14 +5871,14 @@
(match_operand:DF 1 "general_operand" ""))]
"TARGET_EITHER"
"
- if (TARGET_ARM)
+ if (TARGET_32BIT)
{
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (DFmode, operands[1]);
}
else /* TARGET_THUMB */
{
- if (!no_new_pseudos)
+ if (can_create_pseudo_p ())
{
if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (DFmode, operands[1]);
@@ -5028,7 +5893,7 @@
[(match_operand:DF 0 "arm_reload_memory_operand" "=o")
(match_operand:DF 1 "s_register_operand" "r")
(match_operand:SI 2 "s_register_operand" "=&r")]
- "TARGET_ARM"
+ "TARGET_32BIT"
"
{
enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
@@ -5055,7 +5920,8 @@
emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
XEXP (XEXP (operands[0], 0), 1)));
- emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
+ emit_insn (gen_rtx_SET (VOIDmode,
+ replace_equiv_address (operands[0], operands[2]),
operands[1]));
if (code == POST_DEC)
@@ -5065,52 +5931,25 @@
}"
)
-(define_insn "*movdf_hard_insn"
- [(set (match_operand:DF 0 "nonimmediate_operand"
- "=r,Q,r,m,r, f, f,f, m,!f,!r")
- (match_operand:DF 1 "general_operand"
- "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
- "TARGET_ARM
- && TARGET_HARD_FLOAT
- && (GET_CODE (operands[0]) != MEM
+(define_insn "*movdf_soft_insn"
+ [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
+ (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
+ "TARGET_ARM && TARGET_SOFT_FLOAT
+ && ( register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode))"
"*
- {
switch (which_alternative)
{
+ case 0:
+ case 1:
+ case 2:
+ return \"#\";
default:
- case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
- case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
- case 2: case 3: case 4: return output_move_double (operands);
- case 5: return \"mvf%?d\\t%0, %1\";
- case 6: return \"mnf%?d\\t%0, #%N1\";
- case 7: return \"ldf%?d\\t%0, %1\";
- case 8: return \"stf%?d\\t%1, %0\";
- case 9: return output_mov_double_fpu_from_arm (operands);
- case 10: return output_mov_double_arm_from_fpu (operands);
+ return output_move_double (operands);
}
- }
- "
- [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
- (set_attr "predicable" "yes")
- (set_attr "type"
- "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
- (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
- (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
-)
-
-;; Software floating point version. This is essentially the same as movdi.
-;; Do not use `f' as a constraint to prevent reload from ever trying to use
-;; an `f' reg.
-
-(define_insn "*movdf_soft_insn"
- [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
- (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
- "TARGET_ARM && TARGET_SOFT_FLOAT
"
- "* return output_move_double (operands);"
- [(set_attr "length" "8,8,8")
- (set_attr "type" "*,load,store2")
+ [(set_attr "length" "8,12,16,8,8")
+ (set_attr "type" "*,*,*,load2,store2")
(set_attr "pool_range" "1020")
(set_attr "neg_pool_range" "1008")]
)
@@ -5122,7 +5961,7 @@
(define_insn "*thumb_movdf_insn"
[(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
(match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
- "TARGET_THUMB
+ "TARGET_THUMB1
&& ( register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode))"
"*
@@ -5140,8 +5979,8 @@
case 3:
return thumb_load_double_from_address (operands);
case 4:
- operands[2] = gen_rtx (MEM, SImode,
- plus_constant (XEXP (operands[0], 0), 4));
+ operands[2] = gen_rtx_MEM (SImode,
+ plus_constant (XEXP (operands[0], 0), 4));
output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
return \"\";
case 5:
@@ -5151,43 +5990,20 @@
}
"
[(set_attr "length" "4,2,2,6,4,4")
- (set_attr "type" "*,load,store2,load,store2,*")
+ (set_attr "type" "*,load2,store2,load2,store2,*")
(set_attr "pool_range" "*,*,*,1020,*,*")]
)
-
(define_expand "movxf"
[(set (match_operand:XF 0 "general_operand" "")
(match_operand:XF 1 "general_operand" ""))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "")
-
-;; Even when the XFmode patterns aren't enabled, we enable this after
-;; reloading so that we can push floating point registers in the prologue.
-
-(define_insn "*movxf_hard_insn"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
- (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
- "*
- switch (which_alternative)
- {
- default:
- case 0: return \"mvf%?e\\t%0, %1\";
- case 1: return \"mnf%?e\\t%0, #%N1\";
- case 2: return \"ldf%?e\\t%0, %1\";
- case 3: return \"stf%?e\\t%1, %0\";
- case 4: return output_mov_long_double_fpu_from_arm (operands);
- case 5: return output_mov_long_double_arm_from_fpu (operands);
- case 6: return output_mov_long_double_arm_from_arm (operands);
- }
+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
+ "
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (XFmode, operands[1]);
"
- [(set_attr "length" "4,4,4,4,8,8,12")
- (set_attr "predicable" "yes")
- (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
- (set_attr "pool_range" "*,*,1024,*,*,*,*")
- (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
)
+
;; load- and store-multiple insns
@@ -5198,8 +6014,10 @@
[(match_par_dup 3 [(set (match_operand:SI 0 "" "")
(match_operand:SI 1 "" ""))
(use (match_operand:SI 2 "" ""))])]
- "TARGET_ARM"
- "
+ "TARGET_32BIT"
+{
+ HOST_WIDE_INT offset = 0;
+
/* Support only fixed point registers. */
if (GET_CODE (operands[2]) != CONST_INT
|| INTVAL (operands[2]) > 14
@@ -5213,11 +6031,8 @@
operands[3]
= arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
force_reg (SImode, XEXP (operands[1], 0)),
- TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
- MEM_IN_STRUCT_P(operands[1]),
- MEM_SCALAR_P (operands[1]));
- "
-)
+ TRUE, FALSE, operands[1], &offset);
+})
;; Load multiple with write-back
@@ -5234,12 +6049,30 @@
(mem:SI (plus:SI (match_dup 2) (const_int 8))))
(set (match_operand:SI 6 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
- "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
- [(set_attr "type" "load")
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
+ "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
+ [(set_attr "type" "load4")
(set_attr "predicable" "yes")]
)
+(define_insn "*ldmsi_postinc4_thumb1"
+ [(match_parallel 0 "load_multiple_operation"
+ [(set (match_operand:SI 1 "s_register_operand" "=l")
+ (plus:SI (match_operand:SI 2 "s_register_operand" "1")
+ (const_int 16)))
+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
+ (mem:SI (match_dup 2)))
+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
+ "ldmia\\t%1!, {%3, %4, %5, %6}"
+ [(set_attr "type" "load4")]
+)
+
(define_insn "*ldmsi_postinc3"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "s_register_operand" "=r")
@@ -5251,9 +6084,9 @@
(mem:SI (plus:SI (match_dup 2) (const_int 4))))
(set (match_operand:SI 5 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "ldm%?ia\\t%1!, {%3, %4, %5}"
- [(set_attr "type" "load")
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
+ "ldm%(ia%)\\t%1!, {%3, %4, %5}"
+ [(set_attr "type" "load3")
(set_attr "predicable" "yes")]
)
@@ -5266,9 +6099,9 @@
(mem:SI (match_dup 2)))
(set (match_operand:SI 4 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "ldm%?ia\\t%1!, {%3, %4}"
- [(set_attr "type" "load")
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
+ "ldm%(ia%)\\t%1!, {%3, %4}"
+ [(set_attr "type" "load2")
(set_attr "predicable" "yes")]
)
@@ -5284,9 +6117,9 @@
(mem:SI (plus:SI (match_dup 1) (const_int 8))))
(set (match_operand:SI 5 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "ldm%?ia\\t%1, {%2, %3, %4, %5}"
- [(set_attr "type" "load")
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
+ "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
+ [(set_attr "type" "load4")
(set_attr "predicable" "yes")]
)
@@ -5298,9 +6131,9 @@
(mem:SI (plus:SI (match_dup 1) (const_int 4))))
(set (match_operand:SI 4 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "ldm%?ia\\t%1, {%2, %3, %4}"
- [(set_attr "type" "load")
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
+ "ldm%(ia%)\\t%1, {%2, %3, %4}"
+ [(set_attr "type" "load3")
(set_attr "predicable" "yes")]
)
@@ -5310,9 +6143,9 @@
(mem:SI (match_operand:SI 1 "s_register_operand" "r")))
(set (match_operand:SI 3 "arm_hard_register_operand" "")
(mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
- "ldm%?ia\\t%1, {%2, %3}"
- [(set_attr "type" "load")
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
+ "ldm%(ia%)\\t%1, {%2, %3}"
+ [(set_attr "type" "load2")
(set_attr "predicable" "yes")]
)
@@ -5320,9 +6153,11 @@
[(match_par_dup 3 [(set (match_operand:SI 0 "" "")
(match_operand:SI 1 "" ""))
(use (match_operand:SI 2 "" ""))])]
- "TARGET_ARM"
- "
- /* Support only fixed point registers */
+ "TARGET_32BIT"
+{
+ HOST_WIDE_INT offset = 0;
+
+ /* Support only fixed point registers. */
if (GET_CODE (operands[2]) != CONST_INT
|| INTVAL (operands[2]) > 14
|| INTVAL (operands[2]) < 2
@@ -5335,11 +6170,8 @@
operands[3]
= arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
force_reg (SImode, XEXP (operands[0], 0)),
- TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
- MEM_IN_STRUCT_P(operands[0]),
- MEM_SCALAR_P (operands[0]));
- "
-)
+ TRUE, FALSE, operands[0], &offset);
+})
;; Store multiple with write-back
@@ -5356,12 +6188,30 @@
(match_operand:SI 5 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
(match_operand:SI 6 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
- "stm%?ia\\t%1!, {%3, %4, %5, %6}"
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
+ "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
[(set_attr "predicable" "yes")
(set_attr "type" "store4")]
)
+(define_insn "*stmsi_postinc4_thumb1"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (match_operand:SI 1 "s_register_operand" "=l")
+ (plus:SI (match_operand:SI 2 "s_register_operand" "1")
+ (const_int 16)))
+ (set (mem:SI (match_dup 2))
+ (match_operand:SI 3 "arm_hard_register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
+ (match_operand:SI 4 "arm_hard_register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
+ (match_operand:SI 5 "arm_hard_register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
+ "stmia\\t%1!, {%3, %4, %5, %6}"
+ [(set_attr "type" "store4")]
+)
+
(define_insn "*stmsi_postinc3"
[(match_parallel 0 "store_multiple_operation"
[(set (match_operand:SI 1 "s_register_operand" "=r")
@@ -5373,8 +6223,8 @@
(match_operand:SI 4 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
(match_operand:SI 5 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "stm%?ia\\t%1!, {%3, %4, %5}"
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
+ "stm%(ia%)\\t%1!, {%3, %4, %5}"
[(set_attr "predicable" "yes")
(set_attr "type" "store3")]
)
@@ -5388,8 +6238,8 @@
(match_operand:SI 3 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
(match_operand:SI 4 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "stm%?ia\\t%1!, {%3, %4}"
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
+ "stm%(ia%)\\t%1!, {%3, %4}"
[(set_attr "predicable" "yes")
(set_attr "type" "store2")]
)
@@ -5406,8 +6256,8 @@
(match_operand:SI 4 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
(match_operand:SI 5 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "stm%?ia\\t%1, {%2, %3, %4, %5}"
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
+ "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
[(set_attr "predicable" "yes")
(set_attr "type" "store4")]
)
@@ -5420,8 +6270,8 @@
(match_operand:SI 3 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
(match_operand:SI 4 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "stm%?ia\\t%1, {%2, %3, %4}"
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
+ "stm%(ia%)\\t%1, {%2, %3, %4}"
[(set_attr "predicable" "yes")
(set_attr "type" "store3")]
)
@@ -5432,8 +6282,8 @@
(match_operand:SI 2 "arm_hard_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
(match_operand:SI 3 "arm_hard_register_operand" ""))])]
- "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
- "stm%?ia\\t%1, {%2, %3}"
+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
+ "stm%(ia%)\\t%1, {%2, %3}"
[(set_attr "predicable" "yes")
(set_attr "type" "store2")]
)
@@ -5442,26 +6292,26 @@
;; We could let this apply for blocks of less than this, but it clobbers so
;; many registers that there is then probably a better way.
-(define_expand "movstrqi"
+(define_expand "movmemqi"
[(match_operand:BLK 0 "general_operand" "")
(match_operand:BLK 1 "general_operand" "")
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" "")]
"TARGET_EITHER"
"
- if (TARGET_ARM)
+ if (TARGET_32BIT)
{
- if (arm_gen_movstrqi (operands))
+ if (arm_gen_movmemqi (operands))
DONE;
FAIL;
}
- else /* TARGET_THUMB */
+ else /* TARGET_THUMB1 */
{
if ( INTVAL (operands[3]) != 4
|| INTVAL (operands[2]) > 48)
FAIL;
- thumb_expand_movstrqi (operands);
+ thumb_expand_movmemqi (operands);
DONE;
}
"
@@ -5483,7 +6333,7 @@
(clobber (match_scratch:SI 4 "=&l"))
(clobber (match_scratch:SI 5 "=&l"))
(clobber (match_scratch:SI 6 "=&l"))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"* return thumb_output_move_mem_multiple (3, operands);"
[(set_attr "length" "4")
; This isn't entirely accurate... It loads as well, but in terms of
@@ -5502,7 +6352,7 @@
(plus:SI (match_dup 3) (const_int 8)))
(clobber (match_scratch:SI 4 "=&l"))
(clobber (match_scratch:SI 5 "=&l"))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"* return thumb_output_move_mem_multiple (2, operands);"
[(set_attr "length" "4")
; This isn't entirely accurate... It loads as well, but in terms of
@@ -5513,7 +6363,7 @@
;; Compare & branch insns
-;; The range calcualations are based as follows:
+;; The range calculations are based as follows:
;; For forward branches, the address calculation returns the address of
;; the next instruction. This is 2 beyond the branch instruction.
;; For backward branches, the address calculation returns the address of
@@ -5529,24 +6379,616 @@
;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
;; For a 'b' pos_range = 254, neg_range = -256 giving (-250 ->256).
-(define_insn "cbranchsi4"
+(define_expand "cbranchsi4"
+ [(set (pc) (if_then_else
+ (match_operator 0 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_THUMB1"
+ "
+ if (thumb1_cmpneg_operand (operands[2], SImode))
+ {
+ emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
+ operands[3], operands[0]));
+ DONE;
+ }
+ if (!thumb1_cmp_operand (operands[2], SImode))
+ operands[2] = force_reg (SImode, operands[2]);
+ ")
+
+(define_insn "*cbranchsi4_insn"
+ [(set (pc) (if_then_else
+ (match_operator 0 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "l,*h")
+ (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_THUMB1"
+ "*
+ output_asm_insn (\"cmp\\t%1, %2\", operands);
+
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d0\\t%l3\";
+ case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ "
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
+(define_insn "cbranchsi4_scratch"
+ [(set (pc) (if_then_else
+ (match_operator 4 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "l,0")
+ (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 0 "=l,l"))]
+ "TARGET_THUMB1"
+ "*
+ output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
+
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d4\\t%l3\";
+ case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ "
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+(define_insn "*movsi_cbranchsi4"
+ [(set (pc)
+ (if_then_else
+ (match_operator 3 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
+ (match_dup 1))]
+ "TARGET_THUMB1"
+ "*{
+ if (which_alternative == 0)
+ output_asm_insn (\"cmp\t%0, #0\", operands);
+ else if (which_alternative == 1)
+ output_asm_insn (\"sub\t%0, %1, #0\", operands);
+ else
+ {
+ output_asm_insn (\"cmp\t%1, #0\", operands);
+ if (which_alternative == 2)
+ output_asm_insn (\"mov\t%0, %1\", operands);
+ else
+ output_asm_insn (\"str\t%1, %0\", operands);
+ }
+ switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
+ {
+ case 4: return \"b%d3\\t%l2\";
+ case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (ior (and (gt (symbol_ref ("which_alternative"))
+ (const_int 1))
+ (eq_attr "length" "8"))
+ (eq_attr "length" "10"))
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (le (symbol_ref ("which_alternative"))
+ (const_int 1))
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -250))
+ (le (minus (match_dup 2) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
+ (le (minus (match_dup 2) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8)))
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -248))
+ (le (minus (match_dup 2) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
+ (le (minus (match_dup 2) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))))]
+)
+
+(define_insn "*negated_cbranchsi4"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(match_operand:SI 1 "s_register_operand" "l")
+ (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_THUMB1"
+ "*
+ output_asm_insn (\"cmn\\t%1, %2\", operands);
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d0\\t%l3\";
+ case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ "
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
+(define_insn "*tbit_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
+ (const_int 1)
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 4 "=l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ rtx op[3];
+ op[0] = operands[4];
+ op[1] = operands[1];
+ op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
+
+ output_asm_insn (\"lsl\\t%0, %1, %2\", op);
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d0\\t%l3\";
+ case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
+(define_insn "*tlobits_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
+ (match_operand:SI 2 "const_int_operand" "i")
+ (const_int 0))
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 4 "=l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ rtx op[3];
+ op[0] = operands[4];
+ op[1] = operands[1];
+ op[2] = GEN_INT (32 - INTVAL (operands[2]));
+
+ output_asm_insn (\"lsl\\t%0, %1, %2\", op);
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d0\\t%l3\";
+ case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
+(define_insn "*tstsi3_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 3 "equality_operator"
+ [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
+ (match_operand:SI 1 "s_register_operand" "l"))
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "TARGET_THUMB1"
+ "*
+ {
+ output_asm_insn (\"tst\\t%0, %1\", operands);
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d3\\t%l2\";
+ case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -250))
+ (le (minus (match_dup 2) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
+ (le (minus (match_dup 2) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
+(define_insn "*andsi3_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 5 "equality_operator"
+ [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
+ (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
+ (const_int 0)])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
+ (and:SI (match_dup 2) (match_dup 3)))
+ (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ if (which_alternative == 0)
+ output_asm_insn (\"and\\t%0, %3\", operands);
+ else if (which_alternative == 1)
+ {
+ output_asm_insn (\"and\\t%1, %3\", operands);
+ output_asm_insn (\"mov\\t%0, %1\", operands);
+ }
+ else
+ {
+ output_asm_insn (\"and\\t%1, %3\", operands);
+ output_asm_insn (\"str\\t%1, %0\", operands);
+ }
+
+ switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
+ {
+ case 4: return \"b%d5\\t%l4\";
+ case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (ior (and (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (eq_attr "length" "8"))
+ (eq_attr "length" "10"))
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -250))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8)))
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -248))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))))]
+)
+
+(define_insn "*orrsi3_cbranch_scratch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 4 "equality_operator"
+ [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
+ (match_operand:SI 2 "s_register_operand" "l"))
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 0 "=l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ output_asm_insn (\"orr\\t%0, %2\", operands);
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d4\\t%l3\";
+ case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
+(define_insn "*orrsi3_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 5 "equality_operator"
+ [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
+ (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
+ (const_int 0)])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
+ (ior:SI (match_dup 2) (match_dup 3)))
+ (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ if (which_alternative == 0)
+ output_asm_insn (\"orr\\t%0, %3\", operands);
+ else if (which_alternative == 1)
+ {
+ output_asm_insn (\"orr\\t%1, %3\", operands);
+ output_asm_insn (\"mov\\t%0, %1\", operands);
+ }
+ else
+ {
+ output_asm_insn (\"orr\\t%1, %3\", operands);
+ output_asm_insn (\"str\\t%1, %0\", operands);
+ }
+
+ switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
+ {
+ case 4: return \"b%d5\\t%l4\";
+ case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (ior (and (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (eq_attr "length" "8"))
+ (eq_attr "length" "10"))
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -250))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8)))
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -248))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))))]
+)
+
+(define_insn "*xorsi3_cbranch_scratch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 4 "equality_operator"
+ [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
+ (match_operand:SI 2 "s_register_operand" "l"))
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 0 "=l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ output_asm_insn (\"eor\\t%0, %2\", operands);
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d4\\t%l3\";
+ case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
+(define_insn "*xorsi3_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 5 "equality_operator"
+ [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
+ (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
+ (const_int 0)])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
+ (xor:SI (match_dup 2) (match_dup 3)))
+ (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ if (which_alternative == 0)
+ output_asm_insn (\"eor\\t%0, %3\", operands);
+ else if (which_alternative == 1)
+ {
+ output_asm_insn (\"eor\\t%1, %3\", operands);
+ output_asm_insn (\"mov\\t%0, %1\", operands);
+ }
+ else
+ {
+ output_asm_insn (\"eor\\t%1, %3\", operands);
+ output_asm_insn (\"str\\t%1, %0\", operands);
+ }
+
+ switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
+ {
+ case 4: return \"b%d5\\t%l4\";
+ case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (ior (and (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (eq_attr "length" "8"))
+ (eq_attr "length" "10"))
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -250))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8)))
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -248))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))))]
+)
+
+(define_insn "*bicsi3_cbranch_scratch"
[(set (pc)
(if_then_else
- (match_operator 0 "arm_comparison_operator"
- [(match_operand:SI 1 "register_operand" "l,r")
- (match_operand:SI 2 "nonmemory_operand" "rI,r")])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "TARGET_THUMB"
+ (match_operator 4 "equality_operator"
+ [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
+ (match_operand:SI 1 "s_register_operand" "0"))
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 0 "=l"))]
+ "TARGET_THUMB1"
"*
- output_asm_insn (\"cmp\\t%1, %2\", operands);
+ {
+ output_asm_insn (\"bic\\t%0, %2\", operands);
switch (get_attr_length (insn))
{
- case 4: return \"b%d0\\t%l3\";
- case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ case 4: return \"b%d4\\t%l3\";
+ case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
}
- "
+ }"
[(set (attr "far_jump")
(if_then_else
(eq_attr "length" "8")
@@ -5563,18 +7005,426 @@
(const_int 6)
(const_int 8))))]
)
+
+(define_insn "*bicsi3_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 5 "equality_operator"
+ [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
+ (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
+ (const_int 0)])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
+ (and:SI (not:SI (match_dup 3)) (match_dup 2)))
+ (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ if (which_alternative == 0)
+ output_asm_insn (\"bic\\t%0, %3\", operands);
+ else if (which_alternative <= 2)
+ {
+ output_asm_insn (\"bic\\t%1, %3\", operands);
+ /* It's ok if OP0 is a lo-reg, even though the mov will set the
+ conditions again, since we're only testing for equality. */
+ output_asm_insn (\"mov\\t%0, %1\", operands);
+ }
+ else
+ {
+ output_asm_insn (\"bic\\t%1, %3\", operands);
+ output_asm_insn (\"str\\t%1, %0\", operands);
+ }
-(define_insn "*negated_cbranchsi4"
+ switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
+ {
+ case 4: return \"b%d5\\t%l4\";
+ case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (ior (and (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (eq_attr "length" "8"))
+ (eq_attr "length" "10"))
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -250))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8)))
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -248))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))))]
+)
+
+(define_insn "*cbranchne_decr1"
+ [(set (pc)
+ (if_then_else (match_operator 3 "equality_operator"
+ [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
+ (const_int 0)])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
+ (plus:SI (match_dup 2) (const_int -1)))
+ (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
+ "TARGET_THUMB1"
+ "*
+ {
+ rtx cond[2];
+ cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
+ ? GEU : LTU),
+ VOIDmode, operands[2], const1_rtx);
+ cond[1] = operands[4];
+
+ if (which_alternative == 0)
+ output_asm_insn (\"sub\\t%0, %2, #1\", operands);
+ else if (which_alternative == 1)
+ {
+ /* We must provide an alternative for a hi reg because reload
+ cannot handle output reloads on a jump instruction, but we
+ can't subtract into that. Fortunately a mov from lo to hi
+ does not clobber the condition codes. */
+ output_asm_insn (\"sub\\t%1, %2, #1\", operands);
+ output_asm_insn (\"mov\\t%0, %1\", operands);
+ }
+ else
+ {
+ /* Similarly, but the target is memory. */
+ output_asm_insn (\"sub\\t%1, %2, #1\", operands);
+ output_asm_insn (\"str\\t%1, %0\", operands);
+ }
+
+ switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
+ {
+ case 4:
+ output_asm_insn (\"b%d0\\t%l1\", cond);
+ return \"\";
+ case 6:
+ output_asm_insn (\"b%D0\\t.LCB%=\", cond);
+ return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
+ default:
+ output_asm_insn (\"b%D0\\t.LCB%=\", cond);
+ return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
+ }
+ }
+ "
+ [(set (attr "far_jump")
+ (if_then_else
+ (ior (and (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (eq_attr "length" "8"))
+ (eq_attr "length" "10"))
+ (const_string "yes")
+ (const_string "no")))
+ (set_attr_alternative "length"
+ [
+ ;; Alternative 0
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -250))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8)))
+ ;; Alternative 1
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -248))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))
+ ;; Alternative 2
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -248))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))
+ ;; Alternative 3
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -248))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))])]
+)
+
+(define_insn "*addsi3_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 4 "comparison_operator"
+ [(plus:SI
+ (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
+ (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
+ (const_int 0)])
+ (label_ref (match_operand 5 "" ""))
+ (pc)))
+ (set
+ (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
+ (plus:SI (match_dup 2) (match_dup 3)))
+ (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
+ "TARGET_THUMB1
+ && (GET_CODE (operands[4]) == EQ
+ || GET_CODE (operands[4]) == NE
+ || GET_CODE (operands[4]) == GE
+ || GET_CODE (operands[4]) == LT)"
+ "*
+ {
+ rtx cond[3];
+
+
+ cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
+ cond[1] = operands[2];
+ cond[2] = operands[3];
+
+ if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
+ output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
+ else
+ output_asm_insn (\"add\\t%0, %1, %2\", cond);
+
+ if (which_alternative >= 3
+ && which_alternative < 4)
+ output_asm_insn (\"mov\\t%0, %1\", operands);
+ else if (which_alternative >= 4)
+ output_asm_insn (\"str\\t%1, %0\", operands);
+
+ switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
+ {
+ case 4:
+ return \"b%d4\\t%l5\";
+ case 6:
+ return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
+ default:
+ return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
+ }
+ }
+ "
+ [(set (attr "far_jump")
+ (if_then_else
+ (ior (and (lt (symbol_ref ("which_alternative"))
+ (const_int 3))
+ (eq_attr "length" "8"))
+ (eq_attr "length" "10"))
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (lt (symbol_ref ("which_alternative"))
+ (const_int 3))
+ (if_then_else
+ (and (ge (minus (match_dup 5) (pc)) (const_int -250))
+ (le (minus (match_dup 5) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
+ (le (minus (match_dup 5) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8)))
+ (if_then_else
+ (and (ge (minus (match_dup 5) (pc)) (const_int -248))
+ (le (minus (match_dup 5) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
+ (le (minus (match_dup 5) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))))]
+)
+
+(define_insn "*addsi3_cbranch_scratch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 3 "comparison_operator"
+ [(plus:SI
+ (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
+ (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
+ (const_int 0)])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 0 "=X,X,l,l"))]
+ "TARGET_THUMB1
+ && (GET_CODE (operands[3]) == EQ
+ || GET_CODE (operands[3]) == NE
+ || GET_CODE (operands[3]) == GE
+ || GET_CODE (operands[3]) == LT)"
+ "*
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ output_asm_insn (\"cmp\t%1, #%n2\", operands);
+ break;
+ case 1:
+ output_asm_insn (\"cmn\t%1, %2\", operands);
+ break;
+ case 2:
+ if (INTVAL (operands[2]) < 0)
+ output_asm_insn (\"sub\t%0, %1, %2\", operands);
+ else
+ output_asm_insn (\"add\t%0, %1, %2\", operands);
+ break;
+ case 3:
+ if (INTVAL (operands[2]) < 0)
+ output_asm_insn (\"sub\t%0, %0, %2\", operands);
+ else
+ output_asm_insn (\"add\t%0, %0, %2\", operands);
+ break;
+ }
+
+ switch (get_attr_length (insn))
+ {
+ case 4:
+ return \"b%d3\\t%l4\";
+ case 6:
+ return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
+ default:
+ return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
+ }
+ }
+ "
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -250))
+ (le (minus (match_dup 4) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
+ (le (minus (match_dup 4) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
+(define_insn "*subsi3_cbranch"
[(set (pc)
(if_then_else
- (match_operator 0 "arm_comparison_operator"
- [(match_operand:SI 1 "register_operand" "l")
- (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
- (label_ref (match_operand 3 "" ""))
+ (match_operator 4 "comparison_operator"
+ [(minus:SI
+ (match_operand:SI 2 "s_register_operand" "l,l,1,l")
+ (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
+ (const_int 0)])
+ (label_ref (match_operand 5 "" ""))
+ (pc)))
+ (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
+ (minus:SI (match_dup 2) (match_dup 3)))
+ (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
+ "TARGET_THUMB1
+ && (GET_CODE (operands[4]) == EQ
+ || GET_CODE (operands[4]) == NE
+ || GET_CODE (operands[4]) == GE
+ || GET_CODE (operands[4]) == LT)"
+ "*
+ {
+ if (which_alternative == 0)
+ output_asm_insn (\"sub\\t%0, %2, %3\", operands);
+ else if (which_alternative == 1)
+ {
+ /* We must provide an alternative for a hi reg because reload
+ cannot handle output reloads on a jump instruction, but we
+ can't subtract into that. Fortunately a mov from lo to hi
+ does not clobber the condition codes. */
+ output_asm_insn (\"sub\\t%1, %2, %3\", operands);
+ output_asm_insn (\"mov\\t%0, %1\", operands);
+ }
+ else
+ {
+ /* Similarly, but the target is memory. */
+ output_asm_insn (\"sub\\t%1, %2, %3\", operands);
+ output_asm_insn (\"str\\t%1, %0\", operands);
+ }
+
+ switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
+ {
+ case 4:
+ return \"b%d4\\t%l5\";
+ case 6:
+ return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
+ default:
+ return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
+ }
+ }
+ "
+ [(set (attr "far_jump")
+ (if_then_else
+ (ior (and (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (eq_attr "length" "8"))
+ (eq_attr "length" "10"))
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (eq (symbol_ref ("which_alternative"))
+ (const_int 0))
+ (if_then_else
+ (and (ge (minus (match_dup 5) (pc)) (const_int -250))
+ (le (minus (match_dup 5) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
+ (le (minus (match_dup 5) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8)))
+ (if_then_else
+ (and (ge (minus (match_dup 5) (pc)) (const_int -248))
+ (le (minus (match_dup 5) (pc)) (const_int 256)))
+ (const_int 6)
+ (if_then_else
+ (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
+ (le (minus (match_dup 5) (pc)) (const_int 2048)))
+ (const_int 8)
+ (const_int 10)))))]
+)
+
+(define_insn "*subsi3_cbranch_scratch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "arm_comparison_operator"
+ [(minus:SI (match_operand:SI 1 "register_operand" "l")
+ (match_operand:SI 2 "nonmemory_operand" "l"))
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
- "TARGET_THUMB"
+ "TARGET_THUMB1
+ && (GET_CODE (operands[0]) == EQ
+ || GET_CODE (operands[0]) == NE
+ || GET_CODE (operands[0]) == GE
+ || GET_CODE (operands[0]) == LT)"
"*
- output_asm_insn (\"cmn\\t%1, %2\", operands);
+ output_asm_insn (\"cmp\\t%1, %2\", operands);
switch (get_attr_length (insn))
{
case 4: return \"b%d0\\t%l3\";
@@ -5599,13 +7449,12 @@
(const_int 8))))]
)
-
;; Comparison and test insns
(define_expand "cmpsi"
[(match_operand:SI 0 "s_register_operand" "")
(match_operand:SI 1 "arm_add_operand" "")]
- "TARGET_ARM"
+ "TARGET_32BIT"
"{
arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1];
@@ -5615,8 +7464,8 @@
(define_expand "cmpsf"
[(match_operand:SF 0 "s_register_operand" "")
- (match_operand:SF 1 "fpu_rhs_operand" "")]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:SF 1 "arm_float_compare_operand" "")]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
"
arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1];
@@ -5626,19 +7475,8 @@
(define_expand "cmpdf"
[(match_operand:DF 0 "s_register_operand" "")
- (match_operand:DF 1 "fpu_rhs_operand" "")]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "
- arm_compare_op0 = operands[0];
- arm_compare_op1 = operands[1];
- DONE;
- "
-)
-
-(define_expand "cmpxf"
- [(match_operand:XF 0 "s_register_operand" "")
- (match_operand:XF 1 "fpu_rhs_operand" "")]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
+ (match_operand:DF 1 "arm_float_compare_operand" "")]
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
"
arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1];
@@ -5650,14 +7488,14 @@
[(set (reg:CC CC_REGNUM)
(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
(match_operand:SI 1 "arm_add_operand" "rI,L")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"@
cmp%?\\t%0, %1
cmn%?\\t%0, #%n1"
[(set_attr "conds" "set")]
)
-(define_insn "*cmpsi_shiftsi"
+(define_insn "*arm_cmpsi_shiftsi"
[(set (reg:CC CC_REGNUM)
(compare:CC (match_operand:SI 0 "s_register_operand" "r")
(match_operator:SI 3 "shift_operator"
@@ -5667,10 +7505,12 @@
"cmp%?\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
-(define_insn "*cmpsi_shiftsi_swp"
+(define_insn "*arm_cmpsi_shiftsi_swp"
[(set (reg:CC_SWP CC_REGNUM)
(compare:CC_SWP (match_operator:SI 3 "shift_operator"
[(match_operand:SI 1 "s_register_operand" "r")
@@ -5680,140 +7520,67 @@
"cmp%?\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
-(define_insn "*cmpsi_neg_shiftsi"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:SI 0 "s_register_operand" "r")
- (neg:SI (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
+(define_insn "*arm_cmpsi_negshiftsi_si"
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z
+ (neg:SI (match_operator:SI 1 "shift_operator"
+ [(match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 3 "reg_or_int_operand" "rM")]))
+ (match_operand:SI 0 "s_register_operand" "r")))]
"TARGET_ARM"
- "cmn%?\\t%0, %1%S3"
- [(set_attr "conds" "set")
- (set_attr "shift" "1")
- ]
-)
-
-(define_insn "*cmpsf_insn"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
- (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- cmf%?\\t%0, %1
- cnf%?\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpdf_insn"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
- (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- cmf%?\\t%0, %1
- cnf%?\\t%0, #%N1"
+ "cmn%?\\t%0, %2%S1"
[(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
+ (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
-(define_insn "*cmpesfdf_df"
+;; Cirrus SF compare instruction
+(define_insn "*cirrus_cmpsf"
[(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (float_extend:DF
- (match_operand:SF 0 "s_register_operand" "f,f"))
- (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- cmf%?\\t%0, %1
- cnf%?\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpdf_esfdf"
- [(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "cmf%?\\t%0, %1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
+ (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
+ (match_operand:SF 1 "cirrus_fp_register" "v")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+ "cfcmps%?\\tr15, %V0, %V1"
+ [(set_attr "type" "mav_farith")
+ (set_attr "cirrus" "compare")]
)
-(define_insn "*cmpxf_insn"
+;; Cirrus DF compare instruction
+(define_insn "*cirrus_cmpdf"
[(set (reg:CCFP CC_REGNUM)
- (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
- (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "@
- cmf%?\\t%0, %1
- cnf%?\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpsf_trap"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
- (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- cmf%?e\\t%0, %1
- cnf%?e\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmpdf_trap"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
- (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- cmf%?e\\t%0, %1
- cnf%?e\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmp_esfdf_df_trap"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (float_extend:DF
- (match_operand:SF 0 "s_register_operand" "f,f"))
- (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- cmf%?e\\t%0, %1
- cnf%?e\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
-
-(define_insn "*cmp_df_esfdf_trap"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
- (float_extend:DF
- (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "cmf%?e\\t%0, %1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
-)
+ (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
+ (match_operand:DF 1 "cirrus_fp_register" "v")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+ "cfcmpd%?\\tr15, %V0, %V1"
+ [(set_attr "type" "mav_farith")
+ (set_attr "cirrus" "compare")]
+)
+
+;; Cirrus DI compare instruction
+(define_expand "cmpdi"
+ [(match_operand:DI 0 "cirrus_fp_register" "")
+ (match_operand:DI 1 "cirrus_fp_register" "")]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+ "{
+ arm_compare_op0 = operands[0];
+ arm_compare_op1 = operands[1];
+ DONE;
+ }")
-(define_insn "*cmpxf_trap"
- [(set (reg:CCFPE CC_REGNUM)
- (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
- (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
- "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
- "@
- cmf%?e\\t%0, %1
- cnf%?e\\t%0, #%N1"
- [(set_attr "conds" "set")
- (set_attr "type" "f_2_r")]
+(define_insn "*cirrus_cmpdi"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
+ (match_operand:DI 1 "cirrus_fp_register" "v")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+ "cfcmp64%?\\tr15, %V0, %V1"
+ [(set_attr "type" "mav_farith")
+ (set_attr "cirrus" "compare")]
)
; This insn allows redundant compares to be removed by cse, nothing should
@@ -5824,7 +7591,7 @@
(define_insn "*deleted_compare"
[(set (match_operand 0 "cc_register" "") (match_dup 0))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"\\t%@ deleted compare"
[(set_attr "conds" "set")
(set_attr "length" "0")]
@@ -5838,7 +7605,7 @@
(if_then_else (eq (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
)
@@ -5847,7 +7614,7 @@
(if_then_else (ne (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
)
@@ -5856,7 +7623,7 @@
(if_then_else (gt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
)
@@ -5865,7 +7632,7 @@
(if_then_else (le (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
)
@@ -5874,7 +7641,7 @@
(if_then_else (ge (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
)
@@ -5883,7 +7650,7 @@
(if_then_else (lt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
)
@@ -5892,7 +7659,7 @@
(if_then_else (gtu (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
)
@@ -5901,7 +7668,7 @@
(if_then_else (leu (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
)
@@ -5910,7 +7677,7 @@
(if_then_else (geu (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
)
@@ -5919,7 +7686,7 @@
(if_then_else (ltu (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
)
@@ -5928,7 +7695,7 @@
(if_then_else (unordered (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
arm_compare_op1);"
)
@@ -5938,7 +7705,7 @@
(if_then_else (ordered (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
arm_compare_op1);"
)
@@ -5948,7 +7715,7 @@
(if_then_else (ungt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
)
@@ -5957,7 +7724,7 @@
(if_then_else (unlt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
)
@@ -5966,7 +7733,7 @@
(if_then_else (unge (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
)
@@ -5975,7 +7742,7 @@
(if_then_else (unle (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
)
@@ -5986,7 +7753,7 @@
(if_then_else (uneq (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
)
@@ -5995,7 +7762,7 @@
(if_then_else (ltgt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
)
@@ -6009,12 +7776,11 @@
(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"*
- if (arm_ccfsm_state != 0)
- abort ();
+ gcc_assert (!arm_ccfsm_state);
- return \"bvs\\t%l0;beq\\t%l0\";
+ return \"bvs\\t%l0\;beq\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6026,12 +7792,11 @@
(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"*
- if (arm_ccfsm_state != 0)
- abort ();
+ gcc_assert (!arm_ccfsm_state);
- return \"bmi\\t%l0;bgt\\t%l0\";
+ return \"bmi\\t%l0\;bgt\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6043,7 +7808,7 @@
[(match_operand 2 "cc_register" "") (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"*
if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
{
@@ -6052,7 +7817,8 @@
}
return \"b%d1\\t%l0\";
"
- [(set_attr "conds" "use")]
+ [(set_attr "conds" "use")
+ (set_attr "type" "branch")]
)
; Special pattern to match reversed UNEQ.
@@ -6061,12 +7827,11 @@
(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"*
- if (arm_ccfsm_state != 0)
- abort ();
+ gcc_assert (!arm_ccfsm_state);
- return \"bmi\\t%l0;bgt\\t%l0\";
+ return \"bmi\\t%l0\;bgt\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6078,12 +7843,11 @@
(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"*
- if (arm_ccfsm_state != 0)
- abort ();
+ gcc_assert (!arm_ccfsm_state);
- return \"bvs\\t%l0;beq\\t%l0\";
+ return \"bvs\\t%l0\;beq\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6095,7 +7859,7 @@
[(match_operand 2 "cc_register" "") (const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"*
if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
{
@@ -6104,7 +7868,8 @@
}
return \"b%D1\\t%l0\";
"
- [(set_attr "conds" "use")]
+ [(set_attr "conds" "use")
+ (set_attr "type" "branch")]
)
@@ -6112,119 +7877,119 @@
; scc insns
(define_expand "seq"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(eq:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sne"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(ne:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sgt"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(gt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sle"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(le:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sge"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(ge:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
)
(define_expand "slt"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(lt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sgtu"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(gtu:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sleu"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(leu:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sgeu"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(geu:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sltu"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(ltu:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
)
(define_expand "sunordered"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(unordered:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
arm_compare_op1);"
)
(define_expand "sordered"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(ordered:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
arm_compare_op1);"
)
(define_expand "sungt"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(ungt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
arm_compare_op1);"
)
(define_expand "sunge"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(unge:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
arm_compare_op1);"
)
(define_expand "sunlt"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(unlt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
arm_compare_op1);"
)
(define_expand "sunle"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "")
(unle:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
arm_compare_op1);"
)
@@ -6233,17 +7998,17 @@
;;; simple ARM instructions.
;
; (define_expand "suneq"
-; [(set (match_operand:SI 0 "s_register_operand" "=r")
+; [(set (match_operand:SI 0 "s_register_operand" "")
; (uneq:SI (match_dup 1) (const_int 0)))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "abort ();"
+; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+; "gcc_unreachable ();"
; )
;
; (define_expand "sltgt"
-; [(set (match_operand:SI 0 "s_register_operand" "=r")
+; [(set (match_operand:SI 0 "s_register_operand" "")
; (ltgt:SI (match_dup 1) (const_int 0)))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "abort ();"
+; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+; "gcc_unreachable ();"
; )
(define_insn "*mov_scc"
@@ -6276,6 +8041,198 @@
(set_attr "length" "8")]
)
+(define_expand "cstoresi4"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "arm_comparison_operator"
+ [(match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "reg_or_int_operand" "")]))]
+ "TARGET_THUMB1"
+ "{
+ rtx op3, scratch, scratch2;
+
+ if (operands[3] == const0_rtx)
+ {
+ switch (GET_CODE (operands[1]))
+ {
+ case EQ:
+ emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
+ break;
+
+ case NE:
+ emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
+ break;
+
+ case LE:
+ scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
+ NULL_RTX, 0, OPTAB_WIDEN);
+ scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
+ NULL_RTX, 0, OPTAB_WIDEN);
+ expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
+ operands[0], 1, OPTAB_WIDEN);
+ break;
+
+ case GE:
+ scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
+ NULL_RTX, 1);
+ expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
+ NULL_RTX, 1, OPTAB_WIDEN);
+ break;
+
+ case GT:
+ scratch = expand_binop (SImode, ashr_optab, operands[2],
+ GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
+ scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
+ NULL_RTX, 0, OPTAB_WIDEN);
+ expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
+ 0, OPTAB_WIDEN);
+ break;
+
+ /* LT is handled by generic code. No need for unsigned with 0. */
+ default:
+ FAIL;
+ }
+ DONE;
+ }
+
+ switch (GET_CODE (operands[1]))
+ {
+ case EQ:
+ scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
+ NULL_RTX, 0, OPTAB_WIDEN);
+ emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
+ break;
+
+ case NE:
+ scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
+ NULL_RTX, 0, OPTAB_WIDEN);
+ emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
+ break;
+
+ case LE:
+ op3 = force_reg (SImode, operands[3]);
+
+ scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
+ NULL_RTX, 1, OPTAB_WIDEN);
+ scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
+ NULL_RTX, 0, OPTAB_WIDEN);
+ emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
+ op3, operands[2]));
+ break;
+
+ case GE:
+ op3 = operands[3];
+ if (!thumb1_cmp_operand (op3, SImode))
+ op3 = force_reg (SImode, op3);
+ scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
+ NULL_RTX, 0, OPTAB_WIDEN);
+ scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
+ NULL_RTX, 1, OPTAB_WIDEN);
+ emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
+ operands[2], op3));
+ break;
+
+ case LEU:
+ op3 = force_reg (SImode, operands[3]);
+ scratch = force_reg (SImode, const0_rtx);
+ emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
+ op3, operands[2]));
+ break;
+
+ case GEU:
+ op3 = operands[3];
+ if (!thumb1_cmp_operand (op3, SImode))
+ op3 = force_reg (SImode, op3);
+ scratch = force_reg (SImode, const0_rtx);
+ emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
+ operands[2], op3));
+ break;
+
+ case LTU:
+ op3 = operands[3];
+ if (!thumb1_cmp_operand (op3, SImode))
+ op3 = force_reg (SImode, op3);
+ scratch = gen_reg_rtx (SImode);
+ emit_insn (gen_cstoresi_nltu_thumb1 (scratch, operands[2], op3));
+ emit_insn (gen_negsi2 (operands[0], scratch));
+ break;
+
+ case GTU:
+ op3 = force_reg (SImode, operands[3]);
+ scratch = gen_reg_rtx (SImode);
+ emit_insn (gen_cstoresi_nltu_thumb1 (scratch, op3, operands[2]));
+ emit_insn (gen_negsi2 (operands[0], scratch));
+ break;
+
+ /* No good sequences for GT, LT. */
+ default:
+ FAIL;
+ }
+ DONE;
+}")
+
+(define_expand "cstoresi_eq0_thumb1"
+ [(parallel
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (eq:SI (match_operand:SI 1 "s_register_operand" "")
+ (const_int 0)))
+ (clobber (match_dup:SI 2))])]
+ "TARGET_THUMB1"
+ "operands[2] = gen_reg_rtx (SImode);"
+)
+
+(define_expand "cstoresi_ne0_thumb1"
+ [(parallel
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (ne:SI (match_operand:SI 1 "s_register_operand" "")
+ (const_int 0)))
+ (clobber (match_dup:SI 2))])]
+ "TARGET_THUMB1"
+ "operands[2] = gen_reg_rtx (SImode);"
+)
+
+(define_insn "*cstoresi_eq0_thumb1_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
+ (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
+ (const_int 0)))
+ (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
+ "TARGET_THUMB1"
+ "@
+ neg\\t%0, %1\;adc\\t%0, %0, %1
+ neg\\t%2, %1\;adc\\t%0, %1, %2"
+ [(set_attr "length" "4")]
+)
+
+(define_insn "*cstoresi_ne0_thumb1_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "=l")
+ (ne:SI (match_operand:SI 1 "s_register_operand" "0")
+ (const_int 0)))
+ (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
+ "TARGET_THUMB1"
+ "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
+ [(set_attr "length" "4")]
+)
+
+(define_insn "cstoresi_nltu_thumb1"
+ [(set (match_operand:SI 0 "s_register_operand" "=l,l")
+ (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
+ (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
+ "TARGET_THUMB1"
+ "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
+ [(set_attr "length" "4")]
+)
+
+;; Used as part of the expansion of thumb les sequence.
+(define_insn "thumb1_addsi3_addgeu"
+ [(set (match_operand:SI 0 "s_register_operand" "=l")
+ (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
+ (match_operand:SI 2 "s_register_operand" "l"))
+ (geu:SI (match_operand:SI 3 "s_register_operand" "l")
+ (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
+ "TARGET_THUMB1"
+ "cmp\\t%3, %4\;adc\\t%0, %1, %2"
+ [(set_attr "length" "4")]
+)
+
;; Conditional move insns
@@ -6284,13 +8241,17 @@
(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
(match_operand:SI 2 "arm_not_operand" "")
(match_operand:SI 3 "arm_not_operand" "")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ rtx ccreg;
+
+ if (code == UNEQ || code == LTGT)
+ FAIL;
- operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
+ ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -6299,20 +8260,23 @@
(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
(match_operand:SF 2 "s_register_operand" "")
(match_operand:SF 3 "nonmemory_operand" "")))]
- "TARGET_ARM"
+ "TARGET_32BIT && TARGET_HARD_FLOAT"
"
{
enum rtx_code code = GET_CODE (operands[1]);
rtx ccreg;
+ if (code == UNEQ || code == LTGT)
+ FAIL;
+
/* When compiling for SOFT_FLOAT, ensure both arms are in registers.
Otherwise, ensure it is a valid FP add operand */
- if ((!TARGET_HARD_FLOAT)
- || (!fpu_add_operand (operands[3], SFmode)))
+ if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
+ || (!arm_float_add_operand (operands[3], SFmode)))
operands[3] = force_reg (SFmode, operands[3]);
ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
- operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -6320,14 +8284,18 @@
[(set (match_operand:DF 0 "s_register_operand" "")
(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
(match_operand:DF 2 "s_register_operand" "")
- (match_operand:DF 3 "fpu_add_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 3 "arm_float_add_operand" "")))]
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ rtx ccreg;
+
+ if (code == UNEQ || code == LTGT)
+ FAIL;
- operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
+ ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -6352,61 +8320,17 @@
(set_attr "conds" "use")]
)
-(define_insn "*movsfcc_hard_insn"
- [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
- (if_then_else:SF
- (match_operator 3 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
- (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
- "@
- mvf%D3s\\t%0, %2
- mnf%D3s\\t%0, #%N2
- mvf%d3s\\t%0, %1
- mnf%d3s\\t%0, #%N1
- mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
- mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
- mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
- mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
- [(set_attr "length" "4,4,4,4,8,8,8,8")
- (set_attr "type" "ffarith")
- (set_attr "conds" "use")]
-)
-
(define_insn "*movsfcc_soft_insn"
[(set (match_operand:SF 0 "s_register_operand" "=r,r")
(if_then_else:SF (match_operator 3 "arm_comparison_operator"
[(match_operand 4 "cc_register" "") (const_int 0)])
(match_operand:SF 1 "s_register_operand" "0,r")
(match_operand:SF 2 "s_register_operand" "r,0")))]
- "TARGET_ARM && TARGET_SOFT_FLOAT"
- "@
- mov%D3\\t%0, %2
- mov%d3\\t%0, %1"
- [(set_attr "conds" "use")]
-)
-
-(define_insn "*movdfcc_insn"
- [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
- (if_then_else:DF
- (match_operator 3 "arm_comparison_operator"
- [(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
- (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_SOFT_FLOAT"
"@
- mvf%D3d\\t%0, %2
- mnf%D3d\\t%0, #%N2
- mvf%d3d\\t%0, %1
- mnf%d3d\\t%0, #%N1
- mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
- mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
- mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
- mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
- [(set_attr "length" "4,4,4,4,8,8,8,8")
- (set_attr "type" "ffarith")
- (set_attr "conds" "use")]
+ mov%D3\\t%0, %2
+ mov%d3\\t%0, %1"
+ [(set_attr "conds" "use")]
)
@@ -6422,7 +8346,7 @@
(define_insn "*arm_jump"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"*
{
if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
@@ -6439,7 +8363,7 @@
(define_insn "*thumb_jump"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"*
if (get_attr_length (insn) == 2)
return \"b\\t%l0\";
@@ -6452,8 +8376,8 @@
(const_string "no")))
(set (attr "length")
(if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
+ (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
+ (le (minus (match_dup 0) (pc)) (const_int 2048)))
(const_int 2)
(const_int 4)))]
)
@@ -6466,36 +8390,49 @@
"TARGET_EITHER"
"
{
- rtx callee;
+ rtx callee, pat;
/* In an untyped call, we can get NULL for operand 2. */
if (operands[2] == NULL_RTX)
operands[2] = const0_rtx;
- /* This is to decide if we should generate indirect calls by loading the
- 32 bit address of the callee into a register before performing the
- branch and link. operand[2] encodes the long_call/short_call
- attribute of the function being called. This attribute is set whenever
- __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
- is used, and the short_call attribute can also be set if function is
- declared as static or if it has already been defined in the current
- compilation unit. See arm.c and arm.h for info about this. The third
- parameter to arm_is_longcall_p is used to tell it which pattern
- invoked it. */
- callee = XEXP (operands[0], 0);
-
- if (GET_CODE (callee) != REG
- && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
+ /* Decide if we should generate indirect calls by loading the
+ 32-bit address of the callee into a register before performing the
+ branch and link. */
+ callee = XEXP (operands[0], 0);
+ if (GET_CODE (callee) == SYMBOL_REF
+ ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
+ : !REG_P (callee))
XEXP (operands[0], 0) = force_reg (Pmode, callee);
+
+ pat = gen_call_internal (operands[0], operands[1], operands[2]);
+ arm_emit_call_insn (pat, XEXP (operands[0], 0));
+ DONE;
}"
)
-(define_insn "*call_reg"
+(define_expand "call_internal"
+ [(parallel [(call (match_operand 0 "memory_operand" "")
+ (match_operand 1 "general_operand" ""))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:SI LR_REGNUM))])])
+
+(define_insn "*call_reg_armv5"
[(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM"
+ "TARGET_ARM && arm_arch5"
+ "blx%?\\t%0"
+ [(set_attr "type" "call")]
+)
+
+(define_insn "*call_reg_arm"
+ [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:SI LR_REGNUM))]
+ "TARGET_ARM && !arm_arch5"
"*
return output_call (operands);
"
@@ -6505,7 +8442,7 @@
)
(define_insn "*call_mem"
- [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
+ [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
@@ -6517,35 +8454,33 @@
(set_attr "type" "call")]
)
-(define_insn "*call_indirect"
+(define_insn "*call_reg_thumb1_v5"
[(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB"
- "*
- {
- if (TARGET_CALLER_INTERWORKING)
- return \"bl\\t%__interwork_call_via_%0\";
- else
- return \"bl\\t%__call_via_%0\";
- }"
- [(set_attr "type" "call")]
+ "TARGET_THUMB1 && arm_arch5"
+ "blx\\t%0"
+ [(set_attr "length" "2")
+ (set_attr "type" "call")]
)
-(define_insn "*call_value_indirect"
- [(set (match_operand 0 "" "=l")
- (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
+(define_insn "*call_reg_thumb1"
+ [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB"
+ "TARGET_THUMB1 && !arm_arch5"
"*
{
- if (TARGET_CALLER_INTERWORKING)
- return \"bl\\t%__interwork_call_via_%1\";
+ if (!TARGET_CALLER_INTERWORKING)
+ return thumb_call_via_reg (operands[0]);
+ else if (operands[1] == const0_rtx)
+ return \"bl\\t%__interwork_call_via_%0\";
+ else if (frame_pointer_needed)
+ return \"bl\\t%__interwork_r7_call_via_%0\";
else
- return \"bl\\t%__call_via_%1\";
+ return \"bl\\t%__interwork_r11_call_via_%0\";
}"
[(set_attr "type" "call")]
)
@@ -6559,26 +8494,53 @@
"TARGET_EITHER"
"
{
- rtx callee = XEXP (operands[1], 0);
+ rtx pat, callee;
/* In an untyped call, we can get NULL for operand 2. */
if (operands[3] == 0)
operands[3] = const0_rtx;
- /* See the comment in define_expand \"call\". */
- if (GET_CODE (callee) != REG
- && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
+ /* Decide if we should generate indirect calls by loading the
+ 32-bit address of the callee into a register before performing the
+ branch and link. */
+ callee = XEXP (operands[1], 0);
+ if (GET_CODE (callee) == SYMBOL_REF
+ ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
+ : !REG_P (callee))
XEXP (operands[1], 0) = force_reg (Pmode, callee);
+
+ pat = gen_call_value_internal (operands[0], operands[1],
+ operands[2], operands[3]);
+ arm_emit_call_insn (pat, XEXP (operands[1], 0));
+ DONE;
}"
)
-(define_insn "*call_value_reg"
- [(set (match_operand 0 "" "=r,f")
- (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
+(define_expand "call_value_internal"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "memory_operand" "")
+ (match_operand 2 "general_operand" "")))
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI LR_REGNUM))])])
+
+(define_insn "*call_value_reg_armv5"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM"
+ "TARGET_ARM && arm_arch5"
+ "blx%?\\t%1"
+ [(set_attr "type" "call")]
+)
+
+(define_insn "*call_value_reg_arm"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI LR_REGNUM))]
+ "TARGET_ARM && !arm_arch5"
"*
return output_call (&operands[1]);
"
@@ -6587,8 +8549,8 @@
)
(define_insn "*call_value_mem"
- [(set (match_operand 0 "" "=r,f")
- (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
@@ -6600,17 +8562,50 @@
(set_attr "type" "call")]
)
+(define_insn "*call_value_reg_thumb1_v5"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI LR_REGNUM))]
+ "TARGET_THUMB1 && arm_arch5"
+ "blx\\t%1"
+ [(set_attr "length" "2")
+ (set_attr "type" "call")]
+)
+
+(define_insn "*call_value_reg_thumb1"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI LR_REGNUM))]
+ "TARGET_THUMB1 && !arm_arch5"
+ "*
+ {
+ if (!TARGET_CALLER_INTERWORKING)
+ return thumb_call_via_reg (operands[1]);
+ else if (operands[2] == const0_rtx)
+ return \"bl\\t%__interwork_call_via_%1\";
+ else if (frame_pointer_needed)
+ return \"bl\\t%__interwork_r7_call_via_%1\";
+ else
+ return \"bl\\t%__interwork_r11_call_via_%1\";
+ }"
+ [(set_attr "type" "call")]
+)
+
;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
(define_insn "*call_symbol"
- [(call (mem:SI (match_operand:SI 0 "" "X"))
+ [(call (mem:SI (match_operand:SI 0 "" ""))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_ARM
&& (GET_CODE (operands[0]) == SYMBOL_REF)
- && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
+ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
"*
{
return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
@@ -6619,14 +8614,14 @@
)
(define_insn "*call_value_symbol"
- [(set (match_operand 0 "s_register_operand" "=r,f")
- (call (mem:SI (match_operand:SI 1 "" "X,X"))
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "" ""))
(match_operand:SI 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_ARM
&& (GET_CODE (operands[1]) == SYMBOL_REF)
- && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
+ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
"*
{
return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
@@ -6635,27 +8630,27 @@
)
(define_insn "*call_insn"
- [(call (mem:SI (match_operand:SI 0 "" "X"))
+ [(call (mem:SI (match_operand:SI 0 "" ""))
(match_operand:SI 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB
&& GET_CODE (operands[0]) == SYMBOL_REF
- && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
+ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
"bl\\t%a0"
[(set_attr "length" "4")
(set_attr "type" "call")]
)
(define_insn "*call_value_insn"
- [(set (match_operand 0 "register_operand" "=l")
- (call (mem:SI (match_operand 1 "" "X"))
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand 1 "" ""))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB
&& GET_CODE (operands[1]) == SYMBOL_REF
- && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
+ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
"bl\\t%a1"
[(set_attr "length" "4")
(set_attr "type" "call")]
@@ -6665,8 +8660,8 @@
(define_expand "sibcall"
[(parallel [(call (match_operand 0 "memory_operand" "")
(match_operand 1 "general_operand" ""))
- (use (match_operand 2 "" ""))
- (use (reg:SI LR_REGNUM))])]
+ (return)
+ (use (match_operand 2 "" ""))])]
"TARGET_ARM"
"
{
@@ -6676,11 +8671,11 @@
)
(define_expand "sibcall_value"
- [(parallel [(set (match_operand 0 "register_operand" "")
+ [(parallel [(set (match_operand 0 "" "")
(call (match_operand 1 "memory_operand" "")
(match_operand 2 "general_operand" "")))
- (use (match_operand 3 "" ""))
- (use (reg:SI LR_REGNUM))])]
+ (return)
+ (use (match_operand 3 "" ""))])]
"TARGET_ARM"
"
{
@@ -6692,8 +8687,8 @@
(define_insn "*sibcall_insn"
[(call (mem:SI (match_operand:SI 0 "" "X"))
(match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (use (reg:SI LR_REGNUM))]
+ (return)
+ (use (match_operand 2 "" ""))]
"TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
"*
return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
@@ -6702,11 +8697,11 @@
)
(define_insn "*sibcall_value_insn"
- [(set (match_operand 0 "s_register_operand" "=r,f")
- (call (mem:SI (match_operand:SI 1 "" "X,X"))
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "" "X"))
(match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (use (reg:SI LR_REGNUM))]
+ (return)
+ (use (match_operand 3 "" ""))]
"TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
"*
return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
@@ -6725,9 +8720,10 @@
arm_ccfsm_state += 2;
return \"\";
}
- return output_return_instruction (NULL, TRUE, FALSE);
+ return output_return_instruction (const_true_rtx, TRUE, FALSE);
}"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
+ (set_attr "length" "12")
(set_attr "predicable" "yes")]
)
@@ -6748,7 +8744,8 @@
return output_return_instruction (operands[0], TRUE, FALSE);
}"
[(set_attr "conds" "use")
- (set_attr "type" "load")]
+ (set_attr "length" "12")
+ (set_attr "type" "load1")]
)
(define_insn "*cond_return_inverted"
@@ -6768,7 +8765,35 @@
return output_return_instruction (operands[0], TRUE, TRUE);
}"
[(set_attr "conds" "use")
- (set_attr "type" "load")]
+ (set_attr "length" "12")
+ (set_attr "type" "load1")]
+)
+
+;; Generate a sequence of instructions to determine if the processor is
+;; in 26-bit or 32-bit mode, and return the appropriate return address
+;; mask.
+
+(define_expand "return_addr_mask"
+ [(set (match_dup 1)
+ (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
+ (const_int 0)))
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (if_then_else:SI (eq (match_dup 1) (const_int 0))
+ (const_int -1)
+ (const_int 67108860)))] ; 0x03fffffc
+ "TARGET_ARM"
+ "
+ operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
+ ")
+
+(define_insn "*check_arch2"
+ [(set (match_operand:CC_NOOV 0 "cc_register" "")
+ (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
+ (const_int 0)))]
+ "TARGET_ARM"
+ "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
+ [(set_attr "length" "8")
+ (set_attr "conds" "set")]
)
;; Call subroutine returning any type.
@@ -6778,18 +8803,59 @@
(const_int 0))
(match_operand 1 "" "")
(match_operand 2 "" "")])]
- "TARGET_ARM"
+ "TARGET_EITHER"
"
{
int i;
+ rtx par = gen_rtx_PARALLEL (VOIDmode,
+ rtvec_alloc (XVECLEN (operands[2], 0)));
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx mem;
+ int size = 0;
- emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+ emit_move_insn (addr, XEXP (operands[1], 0));
+ mem = change_address (operands[1], BLKmode, addr);
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
- rtx set = XVECEXP (operands[2], 0, i);
+ rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
+
+ /* Default code only uses r0 as a return value, but we could
+ be using anything up to 4 registers. */
+ if (REGNO (src) == R0_REGNUM)
+ src = gen_rtx_REG (TImode, R0_REGNUM);
+
+ XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
+ GEN_INT (size));
+ size += GET_MODE_SIZE (GET_MODE (src));
+ }
+
+ emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
+ const0_rtx));
+
+ size = 0;
+
+ for (i = 0; i < XVECLEN (par, 0); i++)
+ {
+ HOST_WIDE_INT offset = 0;
+ rtx reg = XEXP (XVECEXP (par, 0, i), 0);
- emit_move_insn (SET_DEST (set), SET_SRC (set));
+ if (size != 0)
+ emit_move_insn (addr, plus_constant (addr, size));
+
+ mem = change_address (mem, GET_MODE (reg), NULL);
+ if (REGNO (reg) == R0_REGNUM)
+ {
+ /* On thumb we have to use a write-back instruction. */
+ emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
+ size = TARGET_ARM ? 16 : 0;
+ }
+ else
+ {
+ emit_move_insn (mem, reg);
+ size = GET_MODE_SIZE (GET_MODE (reg));
+ }
}
/* The optimizer does not know that the call sets the function value
@@ -6802,6 +8868,54 @@
}"
)
+(define_expand "untyped_return"
+ [(match_operand:BLK 0 "memory_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_EITHER"
+ "
+ {
+ int i;
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx mem;
+ int size = 0;
+
+ emit_move_insn (addr, XEXP (operands[0], 0));
+ mem = change_address (operands[0], BLKmode, addr);
+
+ for (i = 0; i < XVECLEN (operands[1], 0); i++)
+ {
+ HOST_WIDE_INT offset = 0;
+ rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
+
+ if (size != 0)
+ emit_move_insn (addr, plus_constant (addr, size));
+
+ mem = change_address (mem, GET_MODE (reg), NULL);
+ if (REGNO (reg) == R0_REGNUM)
+ {
+ /* On thumb we have to use a write-back instruction. */
+ emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
+ size = TARGET_ARM ? 16 : 0;
+ }
+ else
+ {
+ emit_move_insn (reg, mem);
+ size = GET_MODE_SIZE (GET_MODE (reg));
+ }
+ }
+
+ /* Emit USE insns before the return. */
+ for (i = 0; i < XVECLEN (operands[1], 0); i++)
+ emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
+
+ /* Construct the return. */
+ expand_naked_return ();
+
+ DONE;
+ }"
+)
+
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.
@@ -6819,7 +8933,7 @@
(match_operand:SI 2 "const_int_operand" "") ; total range
(match_operand:SI 3 "" "") ; table label
(match_operand:SI 4 "" "")] ; Out of range label
- "TARGET_ARM"
+ "TARGET_32BIT"
"
{
rtx reg;
@@ -6835,15 +8949,28 @@
if (!const_ok_for_arm (INTVAL (operands[2])))
operands[2] = force_reg (SImode, operands[2]);
- emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
- operands[4]));
+ if (TARGET_ARM)
+ {
+ emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
+ operands[3], operands[4]));
+ }
+ else if (flag_pic)
+ {
+ emit_jump_insn (gen_thumb2_casesi_internal_pic (operands[0],
+ operands[2], operands[3], operands[4]));
+ }
+ else
+ {
+ emit_jump_insn (gen_thumb2_casesi_internal (operands[0], operands[2],
+ operands[3], operands[4]));
+ }
DONE;
}"
)
;; The USE in this pattern is needed to tell flow analysis that this is
;; a CASESI insn. It has no other purpose.
-(define_insn "casesi_internal"
+(define_insn "arm_casesi_internal"
[(parallel [(set (pc)
(if_then_else
(leu (match_operand:SI 0 "s_register_operand" "r")
@@ -6867,9 +8994,20 @@
[(set (pc)
(match_operand:SI 0 "s_register_operand" ""))]
"TARGET_EITHER"
- ""
+ "
+ /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
+ address and use bx. */
+ if (TARGET_THUMB2)
+ {
+ rtx tmp;
+ tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
+ operands[0] = tmp;
+ }
+ "
)
+;; NB Never uses BX.
(define_insn "*arm_indirect_jump"
[(set (pc)
(match_operand:SI 0 "s_register_operand" "r"))]
@@ -6878,23 +9016,22 @@
[(set_attr "predicable" "yes")]
)
-;; Although not supported by the define_expand above,
-;; cse/combine may generate this form.
(define_insn "*load_indirect_jump"
[(set (pc)
(match_operand:SI 0 "memory_operand" "m"))]
"TARGET_ARM"
"ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
(set_attr "pool_range" "4096")
(set_attr "neg_pool_range" "4084")
(set_attr "predicable" "yes")]
)
-(define_insn "*thumb_indirect_jump"
+;; NB Never uses BX.
+(define_insn "*thumb1_indirect_jump"
[(set (pc)
(match_operand:SI 0 "register_operand" "l*r"))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"mov\\tpc, %0"
[(set_attr "conds" "clob")
(set_attr "length" "2")]
@@ -6907,6 +9044,8 @@
[(const_int 0)]
"TARGET_EITHER"
"*
+ if (TARGET_UNIFIED_ASM)
+ return \"nop\";
if (TARGET_ARM)
return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
return \"mov\\tr8, r8\";
@@ -6931,9 +9070,29 @@
"%i1%?\\t%0, %2, %4%S3"
[(set_attr "predicable" "yes")
(set_attr "shift" "4")
- ]
+ (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "shiftable_operator"
+ [(match_operator:SI 2 "shiftable_operator"
+ [(match_operator:SI 3 "shift_operator"
+ [(match_operand:SI 4 "s_register_operand" "")
+ (match_operand:SI 5 "reg_or_int_operand" "")])
+ (match_operand:SI 6 "s_register_operand" "")])
+ (match_operand:SI 7 "arm_rhs_operand" "")]))
+ (clobber (match_operand:SI 8 "s_register_operand" ""))]
+ "TARGET_ARM"
+ [(set (match_dup 8)
+ (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
+ (match_dup 6)]))
+ (set (match_dup 0)
+ (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
+ "")
+
(define_insn "*arith_shiftsi_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
@@ -6946,10 +9105,12 @@
(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
(match_dup 2)]))]
"TARGET_ARM"
- "%i1%?s\\t%0, %2, %4%S3"
+ "%i1%.\\t%0, %2, %4%S3"
[(set_attr "conds" "set")
(set_attr "shift" "4")
- ]
+ (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*arith_shiftsi_compare0_scratch"
@@ -6962,10 +9123,12 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"TARGET_ARM"
- "%i1%?s\\t%0, %2, %4%S3"
+ "%i1%.\\t%0, %2, %4%S3"
[(set_attr "conds" "set")
(set_attr "shift" "4")
- ]
+ (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*sub_shiftsi"
@@ -6978,7 +9141,9 @@
"sub%?\\t%0, %1, %3%S2"
[(set_attr "predicable" "yes")
(set_attr "shift" "3")
- ]
+ (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*sub_shiftsi_compare0"
@@ -6993,10 +9158,12 @@
(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
(match_dup 4)])))]
"TARGET_ARM"
- "sub%?s\\t%0, %1, %3%S2"
+ "sub%.\\t%0, %1, %3%S2"
[(set_attr "conds" "set")
- (set_attr "shift" "3")
- ]
+ (set_attr "shift" "3")
+ (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*sub_shiftsi_compare0_scratch"
@@ -7009,143 +9176,12 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"TARGET_ARM"
- "sub%?s\\t%0, %1, %3%S2"
- [(set_attr "conds" "set")
- (set_attr "shift" "3")
- ]
-)
-
-;; These variants of the above insns can occur if the first operand is the
-;; frame pointer and we eliminate that. This is a kludge, but there doesn't
-;; seem to be a way around it. Most of the predicates have to be null
-;; because the format can be generated part way through reload, so
-;; if we don't match it as soon as it becomes available, reload doesn't know
-;; how to reload pseudos that haven't got hard registers; the constraints will
-;; sort everything out.
-
-(define_insn "*reload_mulsi3"
- [(set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 2 "" "r"))
- (match_operand:SI 1 "const_int_operand" "n")))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
- operands[2] = operands[1];
- operands[1] = operands[0];
- return output_add_immediate (operands);
- "
- [
- ; we have no idea how long the add_immediate is, it could be up to 4.
- (set_attr "length" "20")]
-)
-
-(define_insn "*reload_mulsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI
- (plus:SI
- (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
- (match_dup 1))
- (match_dup 2)))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- return \"add%?s\\t%0, %0, %3%S5\";
- "
- [(set_attr "conds" "set")
- (set_attr "shift" "3")
- (set_attr "length" "20")]
-)
-
-(define_insn "*reload_mulsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI
- (plus:SI
- (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=&r"))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- return \"add%?s\\t%0, %0, %3%S5\";
- "
+ "sub%.\\t%0, %1, %3%S2"
[(set_attr "conds" "set")
(set_attr "shift" "3")
- (set_attr "length" "20")]
-)
-
-;; These are similar, but are needed when the mla pattern contains the
-;; eliminated register as operand 3.
-
-(define_insn "*reload_muladdsi"
- [(set (match_operand:SI 0 "" "=&r,&r")
- (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
- (match_operand:SI 2 "" "r,r"))
- (match_operand:SI 3 "" "r,r"))
- (match_operand:SI 4 "const_int_operand" "n,n")))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
- operands[2] = operands[4];
- operands[1] = operands[0];
- return output_add_immediate (operands);
- "
- [(set_attr "length" "20")
- (set_attr "type" "mult")]
-)
-
-(define_insn "*reload_muladdsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
- (match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "r"))
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
- (match_dup 2)))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
- return \"\";
- "
- [(set_attr "length" "20")
- (set_attr "conds" "set")
- (set_attr "type" "mult")]
-)
-
-(define_insn "*reload_muladdsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
- (match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "r"))
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=&r"))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_add_immediate (operands);
- return \"mla%?s\\t%0, %3, %4, %0\";
- "
- [(set_attr "length" "20")
- (set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
@@ -7182,11 +9218,17 @@
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"*
- if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
- return \"mov\\t%0, %2, lsr #31\";
+ if (operands[3] == const0_rtx)
+ {
+ if (GET_CODE (operands[1]) == LT)
+ return \"mov\\t%0, %2, lsr #31\";
+
+ if (GET_CODE (operands[1]) == GE)
+ return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
- if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
- return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
+ if (GET_CODE (operands[1]) == EQ)
+ return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
+ }
if (GET_CODE (operands[1]) == NE)
{
@@ -7276,6 +9318,7 @@
(set_attr "length" "8,12")]
)
+;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
(define_insn "*cmp_ite0"
[(set (match_operand 6 "dominant_cc_register" "")
(compare
@@ -7410,12 +9453,199 @@
int swap =
comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
- return opcodes[which_alternative][swap];
-}
-"
- [(set_attr "conds" "set")
- (set_attr "length" "8")]
-)
+ return opcodes[which_alternative][swap];
+}
+"
+ [(set_attr "conds" "set")
+ (set_attr "length" "8")]
+)
+
+(define_insn_and_split "*ior_scc_scc"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (ior:SI (match_operator:SI 3 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "arm_add_operand" "rIL")])
+ (match_operator:SI 6 "arm_comparison_operator"
+ [(match_operand:SI 4 "s_register_operand" "r")
+ (match_operand:SI 5 "arm_add_operand" "rIL")])))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM
+ && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
+ != CCmode)"
+ "#"
+ "TARGET_ARM && reload_completed"
+ [(set (match_dup 7)
+ (compare
+ (ior:SI
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)])
+ (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
+ (const_int 0)))
+ (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
+ "operands[7]
+ = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
+ DOM_CC_X_OR_Y),
+ CC_REGNUM);"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "16")])
+
+; If the above pattern is followed by a CMP insn, then the compare is
+; redundant, since we can rework the conditional instruction that follows.
+(define_insn_and_split "*ior_scc_scc_cmp"
+ [(set (match_operand 0 "dominant_cc_register" "")
+ (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "arm_add_operand" "rIL")])
+ (match_operator:SI 6 "arm_comparison_operator"
+ [(match_operand:SI 4 "s_register_operand" "r")
+ (match_operand:SI 5 "arm_add_operand" "rIL")]))
+ (const_int 0)))
+ (set (match_operand:SI 7 "s_register_operand" "=r")
+ (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
+ (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
+ "TARGET_ARM"
+ "#"
+ "TARGET_ARM && reload_completed"
+ [(set (match_dup 0)
+ (compare
+ (ior:SI
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)])
+ (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
+ (const_int 0)))
+ (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
+ ""
+ [(set_attr "conds" "set")
+ (set_attr "length" "16")])
+
+(define_insn_and_split "*and_scc_scc"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (and:SI (match_operator:SI 3 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "arm_add_operand" "rIL")])
+ (match_operator:SI 6 "arm_comparison_operator"
+ [(match_operand:SI 4 "s_register_operand" "r")
+ (match_operand:SI 5 "arm_add_operand" "rIL")])))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM
+ && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
+ != CCmode)"
+ "#"
+ "TARGET_ARM && reload_completed
+ && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
+ != CCmode)"
+ [(set (match_dup 7)
+ (compare
+ (and:SI
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)])
+ (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
+ (const_int 0)))
+ (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
+ "operands[7]
+ = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
+ DOM_CC_X_AND_Y),
+ CC_REGNUM);"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "16")])
+
+; If the above pattern is followed by a CMP insn, then the compare is
+; redundant, since we can rework the conditional instruction that follows.
+(define_insn_and_split "*and_scc_scc_cmp"
+ [(set (match_operand 0 "dominant_cc_register" "")
+ (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "arm_add_operand" "rIL")])
+ (match_operator:SI 6 "arm_comparison_operator"
+ [(match_operand:SI 4 "s_register_operand" "r")
+ (match_operand:SI 5 "arm_add_operand" "rIL")]))
+ (const_int 0)))
+ (set (match_operand:SI 7 "s_register_operand" "=r")
+ (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
+ (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
+ "TARGET_ARM"
+ "#"
+ "TARGET_ARM && reload_completed"
+ [(set (match_dup 0)
+ (compare
+ (and:SI
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)])
+ (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
+ (const_int 0)))
+ (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
+ ""
+ [(set_attr "conds" "set")
+ (set_attr "length" "16")])
+
+;; If there is no dominance in the comparison, then we can still save an
+;; instruction in the AND case, since we can know that the second compare
+;; need only zero the value if false (if true, then the value is already
+;; correct).
+(define_insn_and_split "*and_scc_scc_nodom"
+ [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
+ (and:SI (match_operator:SI 3 "arm_comparison_operator"
+ [(match_operand:SI 1 "s_register_operand" "r,r,0")
+ (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
+ (match_operator:SI 6 "arm_comparison_operator"
+ [(match_operand:SI 4 "s_register_operand" "r,r,r")
+ (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM
+ && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
+ == CCmode)"
+ "#"
+ "TARGET_ARM && reload_completed"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (reg:CC CC_REGNUM))])
+ (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
+ (set (match_dup 0)
+ (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
+ (match_dup 0)
+ (const_int 0)))]
+ "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
+ operands[4], operands[5]),
+ CC_REGNUM);
+ operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
+ operands[5]);"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "20")])
+
+(define_split
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (ior:SI
+ (and:SI (match_operand:SI 0 "s_register_operand" "")
+ (const_int 1))
+ (match_operator:SI 1 "comparison_operator"
+ [(match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "arm_add_operand" "")]))
+ (const_int 0)))
+ (clobber (match_operand:SI 4 "s_register_operand" ""))]
+ "TARGET_ARM"
+ [(set (match_dup 4)
+ (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
+ (match_dup 0)))
+ (set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
+ (const_int 0)))]
+ "")
+
+(define_split
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (ior:SI
+ (match_operator:SI 1 "comparison_operator"
+ [(match_operand:SI 2 "s_register_operand" "")
+ (match_operand:SI 3 "arm_add_operand" "")])
+ (and:SI (match_operand:SI 0 "s_register_operand" "")
+ (const_int 1)))
+ (const_int 0)))
+ (clobber (match_operand:SI 4 "s_register_operand" ""))]
+ "TARGET_ARM"
+ [(set (match_dup 4)
+ (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
+ (match_dup 0)))
+ (set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
+ (const_int 0)))]
+ "")
+;; ??? The conditional patterns above need checking for Thumb-2 usefulness
(define_insn "*negscc"
[(set (match_operand:SI 0 "s_register_operand" "=r")
@@ -7425,15 +9655,12 @@
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"*
- if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
+ if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
return \"mov\\t%0, %1, asr #31\";
if (GET_CODE (operands[3]) == NE)
return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
- if (GET_CODE (operands[3]) == GT)
- return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
-
output_asm_insn (\"cmp\\t%1, %2\", operands);
output_asm_insn (\"mov%D3\\t%0, #0\", operands);
return \"mvn%d3\\t%0, #0\";
@@ -7469,7 +9696,7 @@
return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
}
/* The only case that falls through to here is when both ops 1 & 2
- are constants */
+ are constants. */
}
if (GET_CODE (operands[5]) == GE
@@ -7488,7 +9715,7 @@
return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
}
/* The only case that falls through to here is when both ops 1 & 2
- are constants */
+ are constants. */
}
if (GET_CODE (operands[4]) == CONST_INT
&& !const_ok_for_arm (INTVAL (operands[4])))
@@ -7505,6 +9732,8 @@
(set_attr "length" "8,8,12")]
)
+;; ??? The patterns below need checking for Thumb-2 usefulness.
+
(define_insn "*ifcompare_plus_move"
[(set (match_operand:SI 0 "s_register_operand" "=r,r")
(if_then_else:SI (match_operator 6 "arm_comparison_operator"
@@ -7625,7 +9854,7 @@
"*
/* If we have an operation where (op x 0) is the identity operation and
the conditional operator is LT or GE and we are comparing against zero and
- everything is in registers then we can do this in two instructions */
+ everything is in registers then we can do this in two instructions. */
if (operands[3] == const0_rtx
&& GET_CODE (operands[7]) != AND
&& GET_CODE (operands[5]) == REG
@@ -7826,7 +10055,10 @@
mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
[(set_attr "conds" "use")
(set_attr "shift" "2")
- (set_attr "length" "4,8,8")]
+ (set_attr "length" "4,8,8")
+ (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*ifcompare_move_shift"
@@ -7862,7 +10094,10 @@
mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
[(set_attr "conds" "use")
(set_attr "shift" "2")
- (set_attr "length" "4,8,8")]
+ (set_attr "length" "4,8,8")
+ (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*ifcompare_shift_shift"
@@ -7899,7 +10134,12 @@
"mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
[(set_attr "conds" "use")
(set_attr "shift" "1")
- (set_attr "length" "8")]
+ (set_attr "length" "8")
+ (set (attr "type") (if_then_else
+ (and (match_operand 2 "const_int_operand" "")
+ (match_operand 4 "const_int_operand" ""))
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*ifcompare_not_arith"
@@ -7961,652 +10201,185 @@
(match_operand:SI 3 "arm_rhs_operand" "rI")])
(not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
"TARGET_ARM"
- "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
- [(set_attr "conds" "use")
- (set_attr "length" "8")]
-)
-
-(define_insn "*ifcompare_neg_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand:SI 3 "s_register_operand" "r,r")
- (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
- (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_neg_move"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
- (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
- "TARGET_ARM"
- "@
- rsb%d4\\t%0, %2, #0
- mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
- mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8,8")]
-)
-
-(define_insn "*ifcompare_move_neg"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r")
- (if_then_else:SI
- (match_operator 5 "arm_comparison_operator"
- [(match_operand:SI 3 "s_register_operand" "r,r")
- (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
- (match_operand:SI 1 "arm_not_operand" "0,?rIK")
- (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "#"
- [(set_attr "conds" "clob")
- (set_attr "length" "8,12")]
-)
-
-(define_insn "*if_move_neg"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (if_then_else:SI
- (match_operator 4 "arm_comparison_operator"
- [(match_operand 3 "cc_register" "") (const_int 0)])
- (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
- (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
- "TARGET_ARM"
- "@
- rsb%D4\\t%0, %2, #0
- mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
- mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
- [(set_attr "conds" "use")
- (set_attr "length" "4,8,8")]
-)
-
-(define_insn "*arith_adjacentmem"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (match_operator:SI 1 "shiftable_operator"
- [(match_operand:SI 2 "memory_operand" "m")
- (match_operand:SI 3 "memory_operand" "m")]))
- (clobber (match_scratch:SI 4 "=r"))]
- "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
- "*
- {
- rtx ldm[3];
- rtx arith[4];
- int val1 = 0, val2 = 0;
-
- if (REGNO (operands[0]) > REGNO (operands[4]))
- {
- ldm[1] = operands[4];
- ldm[2] = operands[0];
- }
- else
- {
- ldm[1] = operands[0];
- ldm[2] = operands[4];
- }
- if (GET_CODE (XEXP (operands[2], 0)) != REG)
- val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
- if (GET_CODE (XEXP (operands[3], 0)) != REG)
- val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
- arith[0] = operands[0];
- arith[3] = operands[1];
- if (val1 < val2)
- {
- arith[1] = ldm[1];
- arith[2] = ldm[2];
- }
- else
- {
- arith[1] = ldm[2];
- arith[2] = ldm[1];
- }
- if (val1 && val2)
- {
- rtx ops[3];
- ldm[0] = ops[0] = operands[4];
- ops[1] = XEXP (XEXP (operands[2], 0), 0);
- ops[2] = XEXP (XEXP (operands[2], 0), 1);
- output_add_immediate (ops);
- if (val1 < val2)
- output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
- else
- output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
- }
- else if (val1)
- {
- ldm[0] = XEXP (operands[3], 0);
- if (val1 < val2)
- output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
- else
- output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
- }
- else
- {
- ldm[0] = XEXP (operands[2], 0);
- if (val1 < val2)
- output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
- else
- output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
- }
- output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
- return \"\";
- }"
- [(set_attr "length" "12")
- (set_attr "predicable" "yes")
- (set_attr "type" "load")]
-)
-
-;; the arm can support extended pre-inc instructions
-
-;; In all these cases, we use operands 0 and 1 for the register being
-;; incremented because those are the operands that local-alloc will
-;; tie and these are the pair most likely to be tieable (and the ones
-;; that will benefit the most).
-
-;; We reject the frame pointer if it occurs anywhere in these patterns since
-;; elimination will cause too many headaches.
-
-(define_insn "*strqi_preinc"
- [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ")))
- (match_operand:QI 3 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "str%?b\\t%3, [%0, %2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strqi_predec"
- [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r")))
- (match_operand:QI 3 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "str%?b\\t%3, [%0, -%2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqi_preinc"
- [(set (match_operand:QI 3 "s_register_operand" "=r")
- (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?b\\t%3, [%0, %2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqi_predec"
- [(set (match_operand:QI 3 "s_register_operand" "=r")
- (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?b\\t%3, [%0, -%2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqisi_preinc"
- [(set (match_operand:SI 3 "s_register_operand" "=r")
- (zero_extend:SI
- (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ")))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqisi_predec"
- [(set (match_operand:SI 3 "s_register_operand" "=r")
- (zero_extend:SI
- (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r")))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strsi_preinc"
- [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ")))
- (match_operand:SI 3 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "str%?\\t%3, [%0, %2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strsi_predec"
- [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r")))
- (match_operand:SI 3 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "str%?\\t%3, [%0, -%2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadsi_preinc"
- [(set (match_operand:SI 3 "s_register_operand" "=r")
- (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?\\t%3, [%0, %2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadsi_predec"
- [(set (match_operand:SI 3 "s_register_operand" "=r")
- (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?\\t%3, [%0, -%2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadhi_preinc"
- [(set (match_operand:HI 3 "s_register_operand" "=r")
- (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadhi_predec"
- [(set (match_operand:HI 3 "s_register_operand" "=r")
- (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strqi_shiftpreinc"
- [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0")))
- (match_operand:QI 5 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "str%?b\\t%5, [%0, %3%S2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strqi_shiftpredec"
- [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])))
- (match_operand:QI 5 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "str%?b\\t%5, [%0, -%3%S2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqi_shiftpreinc"
- [(set (match_operand:QI 5 "s_register_operand" "=r")
- (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?b\\t%5, [%0, %3%S2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqi_shiftpredec"
- [(set (match_operand:QI 5 "s_register_operand" "=r")
- (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")]))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?b\\t%5, [%0, -%3%S2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strsi_shiftpreinc"
- [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0")))
- (match_operand:SI 5 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "str%?\\t%5, [%0, %3%S2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strsi_shiftpredec"
- [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])))
- (match_operand:SI 5 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "str%?\\t%5, [%0, -%3%S2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
+ "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
+ [(set_attr "conds" "use")
+ (set_attr "length" "8")]
)
-(define_insn "*loadsi_shiftpreinc"
- [(set (match_operand:SI 5 "s_register_operand" "=r")
- (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?\\t%5, [%0, %3%S2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
+(define_insn "*ifcompare_neg_move"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (if_then_else:SI
+ (match_operator 5 "arm_comparison_operator"
+ [(match_operand:SI 3 "s_register_operand" "r,r")
+ (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
+ (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
+ (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM"
+ "#"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8,12")]
)
-(define_insn "*loadsi_shiftpredec"
- [(set (match_operand:SI 5 "s_register_operand" "=r")
- (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")]))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?\\t%5, [%0, -%3%S2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")])
+(define_insn "*if_neg_move"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
+ (if_then_else:SI
+ (match_operator 4 "arm_comparison_operator"
+ [(match_operand 3 "cc_register" "") (const_int 0)])
+ (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
+ (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
+ "TARGET_ARM"
+ "@
+ rsb%d4\\t%0, %2, #0
+ mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
+ mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
+ [(set_attr "conds" "use")
+ (set_attr "length" "4,8,8")]
+)
-(define_insn "*loadhi_shiftpreinc"
- [(set (match_operand:HI 5 "s_register_operand" "=r")
- (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
+(define_insn "*ifcompare_move_neg"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (if_then_else:SI
+ (match_operator 5 "arm_comparison_operator"
+ [(match_operand:SI 3 "s_register_operand" "r,r")
+ (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
+ (match_operand:SI 1 "arm_not_operand" "0,?rIK")
+ (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM"
+ "#"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8,12")]
)
-(define_insn "*loadhi_shiftpredec"
- [(set (match_operand:HI 5 "s_register_operand" "=r")
- (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")]))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
+(define_insn "*if_move_neg"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
+ (if_then_else:SI
+ (match_operator 4 "arm_comparison_operator"
+ [(match_operand 3 "cc_register" "") (const_int 0)])
+ (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
+ (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
+ "TARGET_ARM"
+ "@
+ rsb%D4\\t%0, %2, #0
+ mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
+ mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
+ [(set_attr "conds" "use")
+ (set_attr "length" "4,8,8")]
)
-; It can also support extended post-inc expressions, but combine doesn't
-; try these....
-; It doesn't seem worth adding peepholes for anything but the most common
-; cases since, unlike combine, the increment must immediately follow the load
-; for this pattern to match.
-; We must watch to see that the source/destination register isn't also the
-; same as the base address register, and that if the index is a register,
-; that it is not the same as the base address register. In such cases the
-; instruction that we would generate would have UNPREDICTABLE behaviour so
-; we cannot use it.
+(define_insn "*arith_adjacentmem"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (match_operator:SI 1 "shiftable_operator"
+ [(match_operand:SI 2 "memory_operand" "m")
+ (match_operand:SI 3 "memory_operand" "m")]))
+ (clobber (match_scratch:SI 4 "=r"))]
+ "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
+ "*
+ {
+ rtx ldm[3];
+ rtx arith[4];
+ rtx base_reg;
+ HOST_WIDE_INT val1 = 0, val2 = 0;
-(define_peephole
- [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
- (match_operand:QI 2 "s_register_operand" "r"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
- "TARGET_ARM
- && (REGNO (operands[2]) != REGNO (operands[0]))
- && (GET_CODE (operands[1]) != REG
- || (REGNO (operands[1]) != REGNO (operands[0])))"
- "str%?b\\t%2, [%0], %1"
-)
+ if (REGNO (operands[0]) > REGNO (operands[4]))
+ {
+ ldm[1] = operands[4];
+ ldm[2] = operands[0];
+ }
+ else
+ {
+ ldm[1] = operands[0];
+ ldm[2] = operands[4];
+ }
-(define_peephole
- [(set (match_operand:QI 0 "s_register_operand" "=r")
- (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
- (set (match_dup 1)
- (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
- "TARGET_ARM
- && REGNO (operands[0]) != REGNO(operands[1])
- && (GET_CODE (operands[2]) != REG
- || REGNO(operands[0]) != REGNO (operands[2]))"
- "ldr%?b\\t%0, [%1], %2"
-)
+ base_reg = XEXP (operands[2], 0);
-(define_peephole
- [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
- (match_operand:SI 2 "s_register_operand" "r"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
- "TARGET_ARM
- && (REGNO (operands[2]) != REGNO (operands[0]))
- && (GET_CODE (operands[1]) != REG
- || (REGNO (operands[1]) != REGNO (operands[0])))"
- "str%?\\t%2, [%0], %1"
-)
+ if (!REG_P (base_reg))
+ {
+ val1 = INTVAL (XEXP (base_reg, 1));
+ base_reg = XEXP (base_reg, 0);
+ }
-(define_peephole
- [(set (match_operand:HI 0 "s_register_operand" "=r")
- (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
- (set (match_dup 1)
- (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != REGNO(operands[1])
- && (GET_CODE (operands[2]) != REG
- || REGNO(operands[0]) != REGNO (operands[2]))"
- "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
-)
+ if (!REG_P (XEXP (operands[3], 0)))
+ val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
-(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
- (set (match_dup 1)
- (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
- "TARGET_ARM
- && REGNO (operands[0]) != REGNO(operands[1])
- && (GET_CODE (operands[2]) != REG
- || REGNO(operands[0]) != REGNO (operands[2]))"
- "ldr%?\\t%0, [%1], %2"
-)
+ arith[0] = operands[0];
+ arith[3] = operands[1];
-(define_peephole
- [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
- (match_operand:SI 1 "index_operand" "rJ")))
- (match_operand:QI 2 "s_register_operand" "r"))
- (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
- "TARGET_ARM
- && (REGNO (operands[2]) != REGNO (operands[0]))
- && (GET_CODE (operands[1]) != REG
- || (REGNO (operands[1]) != REGNO (operands[0])))"
- "str%?b\\t%2, [%0, %1]!"
-)
+ if (val1 < val2)
+ {
+ arith[1] = ldm[1];
+ arith[2] = ldm[2];
+ }
+ else
+ {
+ arith[1] = ldm[2];
+ arith[2] = ldm[1];
+ }
-(define_peephole
- [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
- [(match_operand:SI 0 "s_register_operand" "r")
- (match_operand:SI 1 "const_int_operand" "n")])
- (match_operand:SI 2 "s_register_operand" "+r")))
- (match_operand:QI 3 "s_register_operand" "r"))
- (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
- (match_dup 2)))]
- "TARGET_ARM
- && (REGNO (operands[3]) != REGNO (operands[2]))
- && (REGNO (operands[0]) != REGNO (operands[2]))"
- "str%?b\\t%3, [%2, %0%S4]!"
+ ldm[0] = base_reg;
+ if (val1 !=0 && val2 != 0)
+ {
+ rtx ops[3];
+
+ if (val1 == 4 || val2 == 4)
+ /* Other val must be 8, since we know they are adjacent and neither
+ is zero. */
+ output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
+ else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
+ {
+ ldm[0] = ops[0] = operands[4];
+ ops[1] = base_reg;
+ ops[2] = GEN_INT (val1);
+ output_add_immediate (ops);
+ if (val1 < val2)
+ output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
+ else
+ output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
+ }
+ else
+ {
+ /* Offset is out of range for a single add, so use two ldr. */
+ ops[0] = ldm[1];
+ ops[1] = base_reg;
+ ops[2] = GEN_INT (val1);
+ output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
+ ops[0] = ldm[2];
+ ops[2] = GEN_INT (val2);
+ output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
+ }
+ }
+ else if (val1 != 0)
+ {
+ if (val1 < val2)
+ output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
+ else
+ output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
+ }
+ else
+ {
+ if (val1 < val2)
+ output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
+ else
+ output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
+ }
+ output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
+ return \"\";
+ }"
+ [(set_attr "length" "12")
+ (set_attr "predicable" "yes")
+ (set_attr "type" "load1")]
)
; This pattern is never tried by combine, so do it as a peephole
(define_peephole2
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "s_register_operand" ""))
+ [(set (match_operand:SI 0 "arm_general_register_operand" "")
+ (match_operand:SI 1 "arm_general_register_operand" ""))
(set (reg:CC CC_REGNUM)
(compare:CC (match_dup 1) (const_int 0)))]
- "TARGET_ARM
- "
+ "TARGET_ARM"
[(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
(set (match_dup 0) (match_dup 1))])]
""
@@ -8616,13 +10389,13 @@
; reversed, check that the memory references aren't volatile.
(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "=rk")
(match_operand:SI 4 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
+ (set (match_operand:SI 1 "s_register_operand" "=rk")
(match_operand:SI 5 "memory_operand" "m"))
- (set (match_operand:SI 2 "s_register_operand" "=r")
+ (set (match_operand:SI 2 "s_register_operand" "=rk")
(match_operand:SI 6 "memory_operand" "m"))
- (set (match_operand:SI 3 "s_register_operand" "=r")
+ (set (match_operand:SI 3 "s_register_operand" "=rk")
(match_operand:SI 7 "memory_operand" "m"))]
"TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
"*
@@ -8631,11 +10404,11 @@
)
(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "=rk")
(match_operand:SI 3 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
+ (set (match_operand:SI 1 "s_register_operand" "=rk")
(match_operand:SI 4 "memory_operand" "m"))
- (set (match_operand:SI 2 "s_register_operand" "=r")
+ (set (match_operand:SI 2 "s_register_operand" "=rk")
(match_operand:SI 5 "memory_operand" "m"))]
"TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
"*
@@ -8644,9 +10417,9 @@
)
(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "=rk")
(match_operand:SI 2 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=r")
+ (set (match_operand:SI 1 "s_register_operand" "=rk")
(match_operand:SI 3 "memory_operand" "m"))]
"TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
"*
@@ -8656,13 +10429,13 @@
(define_peephole
[(set (match_operand:SI 4 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand:SI 0 "s_register_operand" "rk"))
(set (match_operand:SI 5 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand:SI 1 "s_register_operand" "rk"))
(set (match_operand:SI 6 "memory_operand" "=m")
- (match_operand:SI 2 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "rk"))
(set (match_operand:SI 7 "memory_operand" "=m")
- (match_operand:SI 3 "s_register_operand" "r"))]
+ (match_operand:SI 3 "s_register_operand" "rk"))]
"TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
"*
return emit_stm_seq (operands, 4);
@@ -8671,11 +10444,11 @@
(define_peephole
[(set (match_operand:SI 3 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand:SI 0 "s_register_operand" "rk"))
(set (match_operand:SI 4 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand:SI 1 "s_register_operand" "rk"))
(set (match_operand:SI 5 "memory_operand" "=m")
- (match_operand:SI 2 "s_register_operand" "r"))]
+ (match_operand:SI 2 "s_register_operand" "rk"))]
"TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
"*
return emit_stm_seq (operands, 3);
@@ -8684,9 +10457,9 @@
(define_peephole
[(set (match_operand:SI 2 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand:SI 0 "s_register_operand" "rk"))
(set (match_operand:SI 3 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "r"))]
+ (match_operand:SI 1 "s_register_operand" "rk"))]
"TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
"*
return emit_stm_seq (operands, 2);
@@ -8728,24 +10501,27 @@
operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
"
)
+;; ??? Check the patterns above for Thumb-2 usefulness
(define_expand "prologue"
[(clobber (const_int 0))]
"TARGET_EITHER"
- "if (TARGET_ARM)
+ "if (TARGET_32BIT)
arm_expand_prologue ();
else
- thumb_expand_prologue ();
+ thumb1_expand_prologue ();
DONE;
"
)
(define_expand "epilogue"
- [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
+ [(clobber (const_int 0))]
"TARGET_EITHER"
"
- if (TARGET_THUMB)
- thumb_expand_epilogue ();
+ if (crtl->calls_eh_return)
+ emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
+ if (TARGET_THUMB1)
+ thumb1_expand_epilogue ();
else if (USE_RETURN_INSN (FALSE))
{
emit_jump_insn (gen_return ());
@@ -8759,38 +10535,51 @@
"
)
+;; Note - although unspec_volatile's USE all hard registers,
+;; USEs are ignored after relaod has completed. Thus we need
+;; to add an unspec of the link register to ensure that flow
+;; does not think that it is unused by the sibcall branch that
+;; will replace the standard function epilogue.
(define_insn "sibcall_epilogue"
- [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
- "TARGET_ARM"
+ [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
+ (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
+ "TARGET_32BIT"
"*
- output_asm_insn (\"%@ Sibcall epilogue\", operands);
- if (USE_RETURN_INSN (FALSE))
- return output_return_instruction (NULL, FALSE, FALSE);
- return arm_output_epilogue (FALSE);
+ if (use_return_insn (FALSE, next_nonnote_insn (insn)))
+ return output_return_instruction (const_true_rtx, FALSE, FALSE);
+ return arm_output_epilogue (next_nonnote_insn (insn));
"
;; Length is absolute worst case
[(set_attr "length" "44")
- (set_attr "type" "block")]
+ (set_attr "type" "block")
+ ;; We don't clobber the conditions, but the potential length of this
+ ;; operation is sufficient to make conditionalizing the sequence
+ ;; unlikely to be profitable.
+ (set_attr "conds" "clob")]
)
(define_insn "*epilogue_insns"
[(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
"TARGET_EITHER"
"*
- if (TARGET_ARM)
- return arm_output_epilogue (TRUE);
- else /* TARGET_THUMB */
+ if (TARGET_32BIT)
+ return arm_output_epilogue (NULL);
+ else /* TARGET_THUMB1 */
return thumb_unexpanded_epilogue ();
"
; Length is absolute worst case
[(set_attr "length" "44")
- (set_attr "type" "block")]
+ (set_attr "type" "block")
+ ;; We don't clobber the conditions, but the potential length of this
+ ;; operation is sufficient to make conditionalizing the sequence
+ ;; unlikely to be profitable.
+ (set_attr "conds" "clob")]
)
(define_expand "eh_epilogue"
- [(use (match_operand:SI 0 "register_operand" "r"))
- (use (match_operand:SI 1 "register_operand" "r"))
- (use (match_operand:SI 2 "register_operand" "r"))]
+ [(use (match_operand:SI 0 "register_operand" ""))
+ (use (match_operand:SI 1 "register_operand" ""))
+ (use (match_operand:SI 2 "register_operand" ""))]
"TARGET_EITHER"
"
{
@@ -8815,6 +10604,9 @@
;; some extent with the conditional data operations, so we have to split them
;; up again here.
+;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
+;; conditional execution sufficient?
+
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(if_then_else:SI (match_operator 1 "arm_comparison_operator"
@@ -8916,7 +10708,7 @@
enum rtx_code rc = GET_CODE (operands[1]);
operands[6] = gen_rtx_REG (mode, CC_REGNUM);
- operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
+ operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
if (mode == CCFPmode || mode == CCFPEmode)
rc = reverse_condition_maybe_unordered (rc);
else
@@ -8977,6 +10769,7 @@
[(set_attr "conds" "clob")
(set_attr "length" "12")]
)
+;; ??? The above patterns need auditing for Thumb-2
;; Push multiple registers to the stack. Registers are in parallel (use ...)
;; expressions. For simplicity, the first register is also in the unspec
@@ -8986,21 +10779,26 @@
[(set (match_operand:BLK 0 "memory_operand" "=m")
(unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
UNSPEC_PUSH_MULT))])]
- "TARGET_ARM"
+ "TARGET_32BIT"
"*
{
int num_saves = XVECLEN (operands[2], 0);
/* For the StrongARM at least it is faster to
- use STR to store only a single register. */
- if (num_saves == 1)
+ use STR to store only a single register.
+ In Thumb mode always use push, and the assembler will pick
+ something appropriate. */
+ if (num_saves == 1 && TARGET_ARM)
output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
else
{
int i;
char pattern[100];
- strcpy (pattern, \"stmfd\\t%m0!, {%1\");
+ if (TARGET_ARM)
+ strcpy (pattern, \"stmfd\\t%m0!, {%1\");
+ else
+ strcpy (pattern, \"push\\t{%1\");
for (i = 1; i < num_saves; i++)
{
@@ -9018,13 +10816,23 @@
[(set_attr "type" "store4")]
)
+(define_insn "stack_tie"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
+ (match_operand:SI 1 "s_register_operand" "rk")]
+ UNSPEC_PRLG_STK))]
+ ""
+ ""
+ [(set_attr "length" "0")]
+)
+
;; Similarly for the floating point registers
(define_insn "*push_fp_multi"
[(match_parallel 2 "multi_register_push"
[(set (match_operand:BLK 0 "memory_operand" "=m")
(unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
UNSPEC_PUSH_MULT))])]
- "TARGET_ARM"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
"*
{
char pattern[100];
@@ -9047,6 +10855,15 @@
"
)
+(define_insn "align_8"
+ [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
+ "TARGET_EITHER"
+ "*
+ assemble_align (64);
+ return \"\";
+ "
+)
+
(define_insn "consttable_end"
[(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
"TARGET_EITHER"
@@ -9058,7 +10875,7 @@
(define_insn "consttable_1"
[(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"*
making_const_table = TRUE;
assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
@@ -9070,7 +10887,7 @@
(define_insn "consttable_2"
[(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"*
making_const_table = TRUE;
assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
@@ -9090,13 +10907,14 @@
{
case MODE_FLOAT:
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+ assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
break;
}
default:
assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
+ mark_symbol_refs_as_used (operands[0]);
break;
}
return \"\";
@@ -9114,9 +10932,9 @@
{
case MODE_FLOAT:
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+ assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
break;
}
default:
@@ -9128,12 +10946,36 @@
[(set_attr "length" "8")]
)
+(define_insn "consttable_16"
+ [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
+ "TARGET_EITHER"
+ "*
+ {
+ making_const_table = TRUE;
+ switch (GET_MODE_CLASS (GET_MODE (operands[0])))
+ {
+ case MODE_FLOAT:
+ {
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+ assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
+ break;
+ }
+ default:
+ assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
+ break;
+ }
+ return \"\";
+ }"
+ [(set_attr "length" "16")]
+)
+
;; Miscellaneous Thumb patterns
(define_expand "tablejump"
- [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
+ [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
(use (label_ref (match_operand 1 "" "")))])]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"
if (flag_pic)
{
@@ -9147,42 +10989,24 @@
"
)
-(define_insn "*thumb_tablejump"
+;; NB never uses BX.
+(define_insn "*thumb1_tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
(use (label_ref (match_operand 1 "" "")))]
- "TARGET_THUMB"
+ "TARGET_THUMB1"
"mov\\t%|pc, %0"
[(set_attr "length" "2")]
)
;; V5 Instructions,
-(define_insn "clz"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
- UNSPEC_CLZ))]
- "TARGET_ARM && arm_arch5"
- "clz\\t%0, %1")
-
-(define_expand "ffssi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_ARM && arm_arch5"
- "
- {
- rtx t1, t2, t3;
-
- t1 = gen_reg_rtx (SImode);
- t2 = gen_reg_rtx (SImode);
- t3 = gen_reg_rtx (SImode);
-
- emit_insn (gen_negsi2 (t1, operands[1]));
- emit_insn (gen_andsi3 (t2, operands[1], t1));
- emit_insn (gen_clz (t3, t2));
- emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
- DONE;
- }"
-)
+(define_insn "clzsi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
+ "TARGET_32BIT && arm_arch5"
+ "clz%?\\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "insn" "clz")])
;; V5E instructions.
@@ -9190,7 +11014,7 @@
[(prefetch (match_operand:SI 0 "address_operand" "p")
(match_operand:SI 1 "" "")
(match_operand:SI 2 "" ""))]
- "TARGET_ARM && arm_arch5e"
+ "TARGET_32BIT && arm_arch5e"
"pld\\t%a0")
;; General predication pattern
@@ -9199,7 +11023,7 @@
[(match_operator 0 "arm_comparison_operator"
[(match_operand 1 "cc_register" "")
(const_int 0)])]
- "TARGET_ARM"
+ "TARGET_32BIT"
""
)
@@ -9208,3 +11032,88 @@
""
"%@ %0 needed for prologue"
)
+
+
+;; Patterns for exception handling
+
+(define_expand "eh_return"
+ [(use (match_operand 0 "general_operand" ""))]
+ "TARGET_EITHER"
+ "
+ {
+ if (TARGET_32BIT)
+ emit_insn (gen_arm_eh_return (operands[0]));
+ else
+ emit_insn (gen_thumb_eh_return (operands[0]));
+ DONE;
+ }"
+)
+
+;; We can't expand this before we know where the link register is stored.
+(define_insn_and_split "arm_eh_return"
+ [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
+ VUNSPEC_EH_RETURN)
+ (clobber (match_scratch:SI 1 "=&r"))]
+ "TARGET_ARM"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "
+ {
+ arm_set_return_address (operands[0], operands[1]);
+ DONE;
+ }"
+)
+
+(define_insn_and_split "thumb_eh_return"
+ [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
+ VUNSPEC_EH_RETURN)
+ (clobber (match_scratch:SI 1 "=&l"))]
+ "TARGET_THUMB1"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "
+ {
+ thumb_set_return_address (operands[0], operands[1]);
+ DONE;
+ }"
+)
+
+
+;; TLS support
+
+(define_insn "load_tp_hard"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(const_int 0)] UNSPEC_TLS))]
+ "TARGET_HARD_TP"
+ "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
+ [(set_attr "predicable" "yes")]
+)
+
+;; Doesn't clobber R1-R3. Must use r0 for the first operand.
+(define_insn "load_tp_soft"
+ [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
+ (clobber (reg:SI LR_REGNUM))
+ (clobber (reg:SI IP_REGNUM))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_SOFT_TP"
+ "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
+ [(set_attr "conds" "clob")]
+)
+
+;; Load the FPA co-processor patterns
+(include "fpa.md")
+;; Load the Maverick co-processor patterns
+(include "cirrus.md")
+;; Vector bits common to IWMMXT and Neon
+(include "vec-common.md")
+;; Load the Intel Wireless Multimedia Extension patterns
+(include "iwmmxt.md")
+;; Load the VFP co-processor patterns
+(include "vfp.md")
+;; Thumb-2 patterns
+(include "thumb2.md")
+;; Neon patterns
+(include "neon.md")
+