;;- Machine description for ARM for GNU compiler
;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
;; Free Software Foundation, Inc.
;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
;; and Martin Simmons (@harleqn.co.uk).
(UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
; a given symbolic address.
(UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
+ (UNSPEC_RBIT 26) ; rbit operation.
+ (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
+ ; another symbolic address.
+ (UNSPEC_MEMORY_BARRIER 28) ; Represent a memory barrier.
]
)
(VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions
(VUNSPEC_EH_RETURN 20); Use to override the return address for exception
; handling.
+ (VUNSPEC_SYNC_COMPARE_AND_SWAP 21) ; Represent an atomic compare swap.
+ (VUNSPEC_SYNC_LOCK 22) ; Represent a sync_lock_test_and_set.
+ (VUNSPEC_SYNC_OP 23) ; Represent a sync_<op>
+ (VUNSPEC_SYNC_NEW_OP 24) ; Represent a sync_new_<op>
+ (VUNSPEC_SYNC_OLD_OP 25) ; Represent a sync_old_<op>
]
)
\f
; patterns that share the same RTL in both ARM and Thumb code.
(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
-; 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_tune_strongarm")))
+; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
+(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
-; IS_XSCALE is set to 'yes' when compiling for XScale.
-(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
+; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
+(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
;; Operand number of an input operand that is shifted. Zero if the
;; given instruction does not shift one of its input operands.
; 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" "none,fpa,fpe2,fpe3,maverick,vfp,vfpv3d16,vfpv3,neon,neon_fp16"
+(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
(const (symbol_ref "arm_fpu_attr")))
+(define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
+(define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
+ (const_string "none"))
+
; LENGTH of an instruction (in bytes)
-(define_attr "length" "" (const_int 4))
+(define_attr "length" ""
+ (cond [(not (eq_attr "sync_memory" "none"))
+ (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
+ ] (const_int 4)))
+
+; The architecture which supports the instruction (or alternative).
+; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
+; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
+; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
+; arm_arch6. This attribute is used to compute attribute "enabled",
+; use type "any" to enable an alternative in all cases.
+(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6"
+ (const_string "any"))
+
+(define_attr "arch_enabled" "no,yes"
+ (cond [(eq_attr "arch" "any")
+ (const_string "yes")
+
+ (and (eq_attr "arch" "a")
+ (ne (symbol_ref "TARGET_ARM") (const_int 0)))
+ (const_string "yes")
+
+ (and (eq_attr "arch" "t")
+ (ne (symbol_ref "TARGET_THUMB") (const_int 0)))
+ (const_string "yes")
+
+ (and (eq_attr "arch" "t1")
+ (ne (symbol_ref "TARGET_THUMB1") (const_int 0)))
+ (const_string "yes")
+
+ (and (eq_attr "arch" "t2")
+ (ne (symbol_ref "TARGET_THUMB2") (const_int 0)))
+ (const_string "yes")
+
+ (and (eq_attr "arch" "32")
+ (ne (symbol_ref "TARGET_32BIT") (const_int 0)))
+ (const_string "yes")
+
+ (and (eq_attr "arch" "v6")
+ (ne (symbol_ref "(TARGET_32BIT && arm_arch6)") (const_int 0)))
+ (const_string "yes")
+
+ (and (eq_attr "arch" "nov6")
+ (ne (symbol_ref "(TARGET_32BIT && !arm_arch6)") (const_int 0)))
+ (const_string "yes")]
+ (const_string "no")))
+
+; Allows an insn to disable certain alternatives for reasons other than
+; arch support.
+(define_attr "insn_enabled" "no,yes"
+ (const_string "yes"))
+
+; Enable all alternatives that are both arch_enabled and insn_enabled.
+ (define_attr "enabled" "no,yes"
+ (if_then_else (eq_attr "insn_enabled" "yes")
+ (if_then_else (eq_attr "arch_enabled" "yes")
+ (const_string "yes")
+ (const_string "no"))
+ (const_string "no")))
; POOL_RANGE is how far away from a constant pool entry that this insn
; can be placed. If the distance is zero, then this insn will never
; reference the pool.
; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
; before its address.
-(define_attr "pool_range" "" (const_int 0))
-(define_attr "neg_pool_range" "" (const_int 0))
+(define_attr "arm_pool_range" "" (const_int 0))
+(define_attr "thumb2_pool_range" "" (const_int 0))
+(define_attr "arm_neg_pool_range" "" (const_int 0))
+(define_attr "thumb2_neg_pool_range" "" (const_int 0))
+
+(define_attr "pool_range" ""
+ (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
+ (attr "arm_pool_range")))
+(define_attr "neg_pool_range" ""
+ (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
+ (attr "arm_neg_pool_range")))
; An assembler sequence may clobber the condition codes without us knowing.
; If such an insn references the pool, then we have no way of knowing how,
(const_string "alu")))
; Load scheduling, set from the arm_ld_sched variable
-; initialized by arm_override_options()
+; initialized by arm_option_override()
(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
;; Classification of NEON instructions for scheduling purposes.
; CLOB means that the condition codes are altered in an undefined manner, if
; they are altered at all
;
-; UNCONDITIONAL means the instions can not be conditionally executed.
+; UNCONDITIONAL means the instruction can not be conditionally executed and
+; that the instruction does not use or alter the condition codes.
;
-; NOCOND means that the condition codes are neither altered nor affect the
-; output of this insn
+; NOCOND means that the instruction does not use or alter the condition
+; codes but can be converted into a conditionally exectuted instruction.
(define_attr "conds" "use,set,clob,unconditional,nocond"
- (if_then_else (eq_attr "type" "call")
+ (if_then_else
+ (ior (eq_attr "is_thumb1" "yes")
+ (eq_attr "type" "call"))
(const_string "clob")
(if_then_else (eq_attr "neon_type" "none")
(const_string "nocond")
;;---------------------------------------------------------------------------
;; Mode iterators
-; 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])
+(include "iterators.md")
;;---------------------------------------------------------------------------
;; Predicates
(define_attr "generic_sched" "yes,no"
(const (if_then_else
- (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
+ (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,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" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9")
(eq_attr "tune_cortexr4" "no"))
(const_string "yes")
(const_string "no"))))
(include "arm1020e.md")
(include "arm1026ejs.md")
(include "arm1136jfs.md")
+(include "cortex-a5.md")
(include "cortex-a8.md")
(include "cortex-a9.md")
(include "cortex-r4.md")
(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_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
+ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
"#"
- "TARGET_32BIT && reload_completed"
+ "TARGET_32BIT && reload_completed
+ && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
[(parallel [(set (reg:CC_C CC_REGNUM)
(compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
(match_dup 1)))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (plus:SI (match_dup 4) (match_dup 5))))]
+ (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
+ (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
"
{
operands[3] = gen_highpart (SImode, operands[0]);
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(plus:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "r,0")))
+ (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
(compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
(match_dup 1)))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (plus:SI (ashiftrt:SI (match_dup 2)
+ (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
(const_int 31))
- (match_dup 4))))]
+ (match_dup 4))
+ (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
"
{
operands[3] = gen_highpart (SImode, operands[0]);
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(plus:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "r,0")))
+ (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
(compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
(match_dup 1)))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
- (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (plus:SI (match_dup 4) (const_int 0))))]
+ (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
+ (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
"
{
operands[3] = gen_highpart (SImode, operands[0]);
;; (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, !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")))]
+ [(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
(set_attr "predicable" "yes")]
)
-;; Register group 'k' is a single register group containing only the stack
-;; register. Trying to reload it will always fail catastrophically,
-;; so never allow those alternatives to match if reloading is needed.
-
(define_insn_and_split "*thumb1_addsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
+ [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
+ (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
"TARGET_THUMB1"
"*
static const char * const asms[] =
\"add\\t%0, %1, %2\",
\"add\\t%0, %1, %2\",
\"#\",
+ \"#\",
\"#\"
};
if ((which_alternative == 2 || which_alternative == 6)
return asms[which_alternative];
"
"&& reload_completed && CONST_INT_P (operands[2])
- && operands[1] != stack_pointer_rtx
- && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)"
+ && ((operands[1] != stack_pointer_rtx
+ && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
+ || (operands[1] == stack_pointer_rtx
+ && INTVAL (operands[2]) > 1020))"
[(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
{
HOST_WIDE_INT offset = INTVAL (operands[2]);
- if (offset > 255)
- offset = 255;
- else if (offset < -255)
- offset = -255;
-
+ if (operands[1] == stack_pointer_rtx)
+ offset -= 1020;
+ else
+ {
+ if (offset > 255)
+ offset = 255;
+ else if (offset < -255)
+ offset = -255;
+ }
operands[3] = GEN_INT (offset);
operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
}
- [(set_attr "length" "2,2,2,2,2,2,2,4,4")]
+ [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
)
;; Reloading and elimination of the frame pointer can
""
)
-;; ??? Make Thumb-2 variants which prefer low regs
(define_insn "*addsi3_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT"
+ "TARGET_ARM"
"@
add%.\\t%0, %1, %2
sub%.\\t%0, %1, #%n2"
(plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
(match_operand:SI 1 "arm_add_operand" "rI,L"))
(const_int 0)))]
- "TARGET_32BIT"
+ "TARGET_ARM"
"@
cmn%?\\t%0, %1
cmp%?\\t%0, #%n1"
[(set (reg:CC CC_REGNUM)
(compare:CC
(match_operand:SI 1 "s_register_operand" "r,r")
- (match_operand:SI 2 "arm_addimm_operand" "I,L")))
+ (match_operand:SI 2 "arm_addimm_operand" "L,I")))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (match_dup 1)
- (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
+ (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
"TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
"@
- sub%.\\t%0, %1, %2
- add%.\\t%0, %1, #%n2"
+ add%.\\t%0, %1, %3
+ sub%.\\t%0, %1, #%n3"
[(set_attr "conds" "set")]
)
[(set_attr "conds" "set")]
)
-(define_insn "*addsi3_carryin"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (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_32BIT"
- "adc%?\\t%0, %1, %2"
- [(set_attr "conds" "use")]
-)
-
-(define_insn "*addsi3_carryin_shift"
- [(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" "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 "type") (if_then_else (match_operand 4 "const_int_operand" "")
- (const_string "alu_shift")
- (const_string "alu_shift_reg")))]
-)
-
-(define_insn "*addsi3_carryin_alt1"
+(define_insn "*addsi3_carryin_<optab>"
[(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
+ (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))))]
+ (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
"TARGET_32BIT"
"adc%?\\t%0, %1, %2"
[(set_attr "conds" "use")]
)
-(define_insn "*addsi3_carryin_alt2"
+(define_insn "*addsi3_carryin_alt2_<optab>"
[(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
- (match_operand:SI 1 "s_register_operand" "r"))
+ (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
+ (match_operand:SI 1 "s_register_operand" "%r"))
(match_operand:SI 2 "arm_rhs_operand" "rI")))]
"TARGET_32BIT"
"adc%?\\t%0, %1, %2"
[(set_attr "conds" "use")]
)
-(define_insn "*addsi3_carryin_alt3"
+(define_insn "*addsi3_carryin_shift_<optab>"
[(set (match_operand:SI 0 "s_register_operand" "=r")
- (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")))]
+ (plus:SI (plus:SI
+ (match_operator:SI 2 "shift_operator"
+ [(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"))
+ (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
"TARGET_32BIT"
- "adc%?\\t%0, %1, %2"
- [(set_attr "conds" "use")]
+ "adc%?\\t%0, %1, %3%S2"
+ [(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_expand "incscc"
[(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"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
if (TARGET_MAVERICK
&& !cirrus_fp_register (operands[2], DFmode))
(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_32BIT"
+ "TARGET_32BIT && !TARGET_NEON"
"subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
[(set_attr "conds" "clob")
(set_attr "length" "8")]
(define_insn "*subdi_di_zesidi"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
(zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))))
(clobber (reg:CC CC_REGNUM))]
(define_insn "*subdi_di_sesidi"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
+ (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
(sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))))
(clobber (reg:CC CC_REGNUM))]
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(minus:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))
+ (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(minus:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))
+ (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
"
)
-(define_insn "*thumb1_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")))]
+ (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
"TARGET_THUMB1"
"sub\\t%0, %1, %2"
- [(set_attr "length" "2")]
-)
+ [(set_attr "length" "2")
+ (set_attr "conds" "set")])
; ??? Check Thumb-2 split length
(define_insn_and_split "*arm_subsi3_insn"
- [(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")))]
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
+ (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
+ (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
"TARGET_32BIT"
"@
rsb%?\\t%0, %2, %1
sub%?\\t%0, %1, %2
+ sub%?\\t%0, %1, %2
+ #
#"
- "TARGET_32BIT
- && GET_CODE (operands[1]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[1]))"
+ "&& ((GET_CODE (operands[1]) == CONST_INT
+ && !const_ok_for_arm (INTVAL (operands[1])))
+ || (GET_CODE (operands[2]) == CONST_INT
+ && !const_ok_for_arm (INTVAL (operands[2]))))"
[(clobber (const_int 0))]
"
arm_split_constant (MINUS, SImode, curr_insn,
INTVAL (operands[1]), operands[0], operands[2], 0);
DONE;
"
- [(set_attr "length" "4,4,16")
+ [(set_attr "length" "4,4,4,16,16")
(set_attr "predicable" "yes")]
)
[(set_attr "conds" "set")]
)
+(define_insn "*subsi3_compare"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
+ (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
+ (set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (minus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_32BIT"
+ "@
+ sub%.\\t%0, %1, %2
+ rsb%.\\t%0, %2, %1"
+ [(set_attr "conds" "set")]
+)
+
(define_expand "decscc"
[(set (match_operand:SI 0 "s_register_operand" "=r,r")
(minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
[(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"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
if (TARGET_MAVERICK)
{
(define_insn "*arm_mulsi3"
[(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")))]
+ (match_operand:SI 1 "s_register_operand" "%0,r")))]
"TARGET_32BIT && !arm_arch6"
"mul%?\\t%0, %2, %1"
[(set_attr "insn" "mul")
(match_operand:SI 2 "register_operand" "l,0,0")))]
"TARGET_THUMB1 && arm_arch6"
"@
- mul\\t%0, %2
- mul\\t%0, %1
+ mul\\t%0, %2
+ mul\\t%0, %1
mul\\t%0, %1"
[(set_attr "length" "2")
(set_attr "insn" "mul")]
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV (mult:SI
(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 1 "s_register_operand" "%?r,0"))
+ (match_operand:SI 1 "s_register_operand" "%0,r"))
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(mult:SI (match_dup 2) (match_dup 1)))]
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV (mult:SI
(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 1 "s_register_operand" "%?r,0"))
+ (match_operand:SI 1 "s_register_operand" "%0,r"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r"))]
"TARGET_ARM && !arm_arch6"
[(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
(plus:SI
(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")))]
+ (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
+ (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
"TARGET_32BIT && !arm_arch6"
"mla%?\\t%0, %2, %1, %3"
[(set_attr "insn" "mla")
(compare:CC_NOOV
(plus:SI (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"))
+ (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
+ (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
(plus:SI (mult:SI (match_dup 2) (match_dup 1))
(compare:CC_NOOV
(plus:SI (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 1 "s_register_operand" "%0,r,0,r"))
(match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
(set_attr "predicable" "yes")]
)
-;; Unnamed template to match long long multiply-accumulate (smlal)
+(define_expand "maddsidi4"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (plus:DI
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
+ (match_operand:DI 3 "s_register_operand" "")))]
+ "TARGET_32BIT && arm_arch3m"
+ "")
(define_insn "*mulsidi3adddi"
[(set (match_operand:DI 0 "s_register_operand" "=&r")
(set_attr "predicable" "yes")]
)
-;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
+(define_expand "umaddsidi4"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (plus:DI
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
+ (match_operand:DI 3 "s_register_operand" "")))]
+ "TARGET_32BIT && arm_arch3m"
+ "")
(define_insn "*umulsidi3adddi"
[(set (match_operand:DI 0 "s_register_operand" "=&r")
(truncate:SI
(lshiftrt:DI
(mult:DI
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=&r,&r"))]
(truncate:SI
(lshiftrt:DI
(mult:DI
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
(zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=&r,&r"))]
(set_attr "predicable" "yes")]
)
-(define_insn "*mulhisi3addsi"
+(define_insn "maddhisi4"
[(set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 1 "s_register_operand" "r")
+ (plus:SI (match_operand:SI 3 "s_register_operand" "r")
(mult:SI (sign_extend:SI
- (match_operand:HI 2 "s_register_operand" "%r"))
+ (match_operand:HI 1 "s_register_operand" "%r"))
(sign_extend:SI
- (match_operand:HI 3 "s_register_operand" "r")))))]
+ (match_operand:HI 2 "s_register_operand" "r")))))]
"TARGET_DSP_MULTIPLY"
- "smlabb%?\\t%0, %2, %3, %1"
+ "smlabb%?\\t%0, %1, %2, %3"
[(set_attr "insn" "smlaxy")
(set_attr "predicable" "yes")]
)
-(define_insn "*mulhidi3adddi"
+(define_insn "*maddhidi4"
[(set (match_operand:DI 0 "s_register_operand" "=r")
(plus:DI
- (match_operand:DI 1 "s_register_operand" "0")
+ (match_operand:DI 3 "s_register_operand" "0")
(mult:DI (sign_extend:DI
- (match_operand:HI 2 "s_register_operand" "%r"))
+ (match_operand:HI 1 "s_register_operand" "%r"))
(sign_extend:DI
- (match_operand:HI 3 "s_register_operand" "r")))))]
+ (match_operand:HI 2 "s_register_operand" "r")))))]
"TARGET_DSP_MULTIPLY"
- "smlalbb%?\\t%Q0, %R0, %2, %3"
+ "smlalbb%?\\t%Q0, %R0, %1, %2"
[(set_attr "insn" "smlalxy")
(set_attr "predicable" "yes")])
[(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"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
if (TARGET_MAVERICK
&& !cirrus_fp_register (operands[2], DFmode))
[(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)"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
"")
\f
;; Modulo insns
[(match_operand:DI 1 "s_register_operand" "")
(match_operand:DI 2 "s_register_operand" "")]))]
"TARGET_32BIT && reload_completed
+ && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
&& ! 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)]))]
}"
)
-(define_insn "anddi3"
+(define_expand "anddi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (and:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:DI 2 "neon_inv_logic_op2" "")))]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*anddi3_insn"
[(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_32BIT && ! TARGET_IWMMXT"
+ "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
"#"
[(set_attr "length" "8")]
)
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
"TARGET_32BIT && reload_completed"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
[(set_attr "length" "8")]
{
if (GET_CODE (operands[2]) == CONST_INT)
{
- arm_split_constant (AND, SImode, NULL_RTX,
- INTVAL (operands[2]), operands[0],
- operands[1], optimize && can_create_pseudo_p ());
+ if (INTVAL (operands[2]) == 255 && arm_arch6)
+ {
+ operands[1] = convert_to_mode (QImode, operands[1], 1);
+ emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
+ operands[1]));
+ }
+ else
+ arm_split_constant (AND, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0],
+ operands[1],
+ optimize && can_create_pseudo_p ());
DONE;
}
else /* TARGET_THUMB1 */
{
if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
+ {
+ rtx tmp = force_reg (SImode, operands[2]);
+ if (rtx_equal_p (operands[0], operands[1]))
+ operands[2] = tmp;
+ else
+ {
+ operands[2] = operands[1];
+ operands[1] = tmp;
+ }
+ }
else
{
int i;
operands[2] = force_reg (SImode,
GEN_INT (~INTVAL (operands[2])));
- emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
+ emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
DONE;
}
(and:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "register_operand" "l")))]
"TARGET_THUMB1"
- "and\\t%0, %0, %2"
- [(set_attr "length" "2")]
-)
+ "and\\t%0, %2"
+ [(set_attr "length" "2")
+ (set_attr "conds" "set")])
(define_insn "*andsi3_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
; 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")))]
+ (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
+ (match_operand:DI 2 "s_register_operand" "r,0")))]
"TARGET_32BIT"
"#"
- "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
+ "TARGET_32BIT && reload_completed
+ && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
+ && ! 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)))]
"
[(set_attr "predicable" "yes")]
)
-(define_insn "bicsi3"
+(define_insn "thumb1_bicsi3"
[(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_THUMB1"
- "bic\\t%0, %0, %1"
- [(set_attr "length" "2")]
-)
+ "bic\\t%0, %1"
+ [(set_attr "length" "2")
+ (set_attr "conds" "set")])
(define_insn "andsi_not_shiftsi_si"
[(set (match_operand:SI 0 "s_register_operand" "=r")
[(set_attr "conds" "set")]
)
-(define_insn "iordi3"
+(define_expand "iordi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (ior:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:DI 2 "neon_logic_op2" "")))]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*iordi3_insn"
[(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_32BIT && ! TARGET_IWMMXT"
+ "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
"#"
[(set_attr "length" "8")
(set_attr "predicable" "yes")]
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(ior:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
[(set_attr "length" "8")
DONE;
}
else /* TARGET_THUMB1 */
- operands [2] = force_reg (SImode, operands [2]);
+ {
+ rtx tmp = force_reg (SImode, operands[2]);
+ if (rtx_equal_p (operands[0], operands[1]))
+ operands[2] = tmp;
+ else
+ {
+ operands[2] = operands[1];
+ operands[1] = tmp;
+ }
+ }
}
"
)
-(define_insn_and_split "*arm_iorsi3"
- [(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"
+(define_insn_and_split "*iorsi3_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
+ (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
+ (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
+ "TARGET_32BIT"
"@
orr%?\\t%0, %1, %2
+ orn%?\\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]))
+ || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
[(clobber (const_int 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")]
-)
+}
+ [(set_attr "length" "4,4,16")
+ (set_attr "arch" "32,t2,32")
+ (set_attr "predicable" "yes")])
-(define_insn "*thumb1_iorsi3"
+(define_insn "*thumb1_iorsi3_insn"
[(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_THUMB1"
- "orr\\t%0, %0, %2"
- [(set_attr "length" "2")]
-)
+ "orr\\t%0, %2"
+ [(set_attr "length" "2")
+ (set_attr "conds" "set")])
(define_peephole2
[(match_scratch:SI 3 "r")
[(set_attr "conds" "set")]
)
-(define_insn "xordi3"
+(define_expand "xordi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (xor:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:DI 2 "s_register_operand" "")))]
+ "TARGET_32BIT"
+ ""
+)
+
+(define_insn "*xordi3_insn"
[(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_32BIT && !TARGET_IWMMXT"
+ "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
"#"
[(set_attr "length" "8")
(set_attr "predicable" "yes")]
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(xor:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
[(set_attr "length" "8")
(define_expand "xorsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(xor:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
+ (match_operand:SI 2 "reg_or_int_operand" "")))]
"TARGET_EITHER"
- "if (TARGET_THUMB1)
- if (GET_CODE (operands[2]) == CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- "
+ "if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (TARGET_32BIT)
+ {
+ arm_split_constant (XOR, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0], operands[1],
+ optimize && can_create_pseudo_p ());
+ DONE;
+ }
+ else /* TARGET_THUMB1 */
+ {
+ rtx tmp = force_reg (SImode, operands[2]);
+ if (rtx_equal_p (operands[0], operands[1]))
+ operands[2] = tmp;
+ else
+ {
+ operands[2] = operands[1];
+ operands[1] = tmp;
+ }
+ }
+ }"
)
(define_insn "*arm_xorsi3"
[(set_attr "predicable" "yes")]
)
-(define_insn "*thumb1_xorsi3"
+(define_insn "*thumb1_xorsi3_insn"
[(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_THUMB1"
- "eor\\t%0, %0, %2"
- [(set_attr "length" "2")]
-)
+ "eor\\t%0, %2"
+ [(set_attr "length" "2")
+ (set_attr "conds" "set")])
(define_insn "*xorsi3_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
(define_insn "*andsi_iorsi3_notsi"
[(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
- (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
+ (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
"TARGET_32BIT"
)
(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")
+ [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
+ (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
(const_int 1)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
(match_operand:SI 2 "nonmemory_operand" "N,l")))]
"TARGET_THUMB1"
"lsl\\t%0, %1, %2"
- [(set_attr "length" "2")]
-)
+ [(set_attr "length" "2")
+ (set_attr "conds" "set")])
(define_expand "ashrdi3"
[(set (match_operand:DI 0 "s_register_operand" "")
)
(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")
+ [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
+ (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
(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 "insn" "mov")
(set_attr "length" "8")]
)
(match_operand:SI 2 "nonmemory_operand" "N,l")))]
"TARGET_THUMB1"
"asr\\t%0, %1, %2"
- [(set_attr "length" "2")]
-)
+ [(set_attr "length" "2")
+ (set_attr "conds" "set")])
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "s_register_operand" "")
)
(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")
+ [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
+ (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
(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 "insn" "mov")
(set_attr "length" "8")]
)
(match_operand:SI 2 "nonmemory_operand" "N,l")))]
"TARGET_THUMB1"
"lsr\\t%0, %1, %2"
- [(set_attr "length" "2")]
-)
+ [(set_attr "length" "2")
+ (set_attr "conds" "set")])
(define_expand "rotlsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(set_attr "shift" "1")]
)
-(define_insn "*arm_notsi_shiftsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+(define_insn "*not_shiftsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
(not:SI (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
- "TARGET_ARM"
+ [(match_operand:SI 1 "s_register_operand" "r,r")
+ (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
+ "TARGET_32BIT"
"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")))]
-)
+ (set_attr "insn" "mvn")
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
-(define_insn "*arm_notsi_shiftsi_compare0"
+(define_insn "*not_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")
- (match_operand:SI 2 "arm_rhs_operand" "rM")]))
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
+ (compare:CC_NOOV
+ (not:SI (match_operator:SI 3 "shift_operator"
+ [(match_operand:SI 1 "s_register_operand" "r,r")
+ (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
+ (const_int 0)))
+ (set (match_operand:SI 0 "s_register_operand" "=r,r")
(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"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")))]
-)
+ (set_attr "insn" "mvn")
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
-(define_insn "*arm_not_shiftsi_compare0_scratch"
+(define_insn "*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")
- (match_operand:SI 2 "arm_rhs_operand" "rM")]))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
+ (compare:CC_NOOV
+ (not:SI (match_operator:SI 3 "shift_operator"
+ [(match_operand:SI 1 "s_register_operand" "r,r")
+ (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r,r"))]
+ "TARGET_32BIT"
"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")))]
-)
+ (set_attr "insn" "mvn")
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
;; We don't really have extzv, but defining this using shifts helps
;; to reduce register pressure later on.
(define_expand "negdi2"
[(parallel
- [(set (match_operand:DI 0 "s_register_operand" "")
- (neg:DI (match_operand:DI 1 "s_register_operand" "")))
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (neg:DI (match_operand:DI 1 "s_register_operand" "")))
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
- "
- if (TARGET_THUMB1)
- {
- if (GET_CODE (operands[1]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
- "
+ ""
)
;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
-;; The second alternative is to allow the common case of a *full* overlap.
+;; The first alternative allows the common case of a *full* overlap.
(define_insn "*arm_negdi2"
[(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
+ (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
)
(define_insn "*thumb1_negdi2"
- [(set (match_operand:DI 0 "register_operand" "=&l")
- (neg:DI (match_operand:DI 1 "register_operand" "l")))
+ [(set (match_operand:DI 0 "register_operand" "=&l")
+ (neg:DI (match_operand:DI 1 "register_operand" "l")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_THUMB1"
"mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
(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)"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
"")
;; abssi2 doesn't really clobber the condition codes if a different register
(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"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"")
(define_expand "sqrtsf2"
(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)"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
"")
(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")))]
+ (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
"TARGET_32BIT && reload_completed"
(not:SI (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_32BIT"
"mvn%?\\t%0, %1"
- [(set_attr "predicable" "yes")]
+ [(set_attr "predicable" "yes")
+ (set_attr "insn" "mvn")]
)
(define_insn "*thumb1_one_cmplsi2"
(not:SI (match_operand:SI 1 "register_operand" "l")))]
"TARGET_THUMB1"
"mvn\\t%0, %1"
- [(set_attr "length" "2")]
+ [(set_attr "length" "2")
+ (set_attr "insn" "mvn")]
)
(define_insn "*notsi_compare0"
(not:SI (match_dup 1)))]
"TARGET_32BIT"
"mvn%.\\t%0, %1"
- [(set_attr "conds" "set")]
+ [(set_attr "conds" "set")
+ (set_attr "insn" "mvn")]
)
(define_insn "*notsi_compare0_scratch"
(clobber (match_scratch:SI 0 "=r"))]
"TARGET_32BIT"
"mvn%.\\t%0, %1"
- [(set_attr "conds" "set")]
+ [(set_attr "conds" "set")
+ (set_attr "insn" "mvn")]
)
\f
;; Fixed <--> Floating conversion insns
(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"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
if (TARGET_MAVERICK)
{
(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"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
if (TARGET_MAVERICK)
{
[(set (match_operand:SF 0 "s_register_operand" "")
(float_truncate:SF
(match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
""
)
\f
;; Zero and sign extension instructions.
-(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 "zero_extend<mode>di2"
+ [(set (match_operand:DI 0 "s_register_operand" "=r")
+ (zero_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))]
+ "TARGET_32BIT <qhs_zextenddi_cond>"
+ "#"
+ [(set_attr "length" "8")
+ (set_attr "ce_count" "2")
+ (set_attr "predicable" "yes")]
)
-(define_insn "*arm_zero_extendsidi2"
+(define_insn "extend<mode>di2"
[(set (match_operand:DI 0 "s_register_operand" "=r")
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
- "*
- if (REGNO (operands[1])
- != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
- output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
- return \"mov%?\\t%R0, #0\";
- "
+ (sign_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))]
+ "TARGET_32BIT <qhs_sextenddi_cond>"
+ "#"
[(set_attr "length" "8")
+ (set_attr "ce_count" "2")
+ (set_attr "shift" "1")
(set_attr "predicable" "yes")]
)
-(define_expand "zero_extendqidi2"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
+;; Splits for all extensions to DImode
+(define_split
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (zero_extend:DI (match_operand 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"
- [(set_attr "length" "8")
- (set_attr "predicable" "yes")
- (set_attr "type" "*,load_byte")
- (set_attr "pool_range" "*,4092")
- (set_attr "neg_pool_range" "*,4084")]
-)
+ [(set (match_dup 0) (match_dup 1))]
+{
+ rtx lo_part = gen_lowpart (SImode, operands[0]);
+ enum machine_mode src_mode = GET_MODE (operands[1]);
+
+ if (REG_P (operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1]))
+ emit_clobber (operands[0]);
+ if (!REG_P (lo_part) || src_mode != SImode
+ || !rtx_equal_p (lo_part, operands[1]))
+ {
+ if (src_mode == SImode)
+ emit_move_insn (lo_part, operands[1]);
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, lo_part,
+ gen_rtx_ZERO_EXTEND (SImode, operands[1])));
+ operands[1] = lo_part;
+ }
+ operands[0] = gen_highpart (SImode, operands[0]);
+ operands[1] = const0_rtx;
+})
-(define_expand "extendsidi2"
+(define_split
[(set (match_operand:DI 0 "s_register_operand" "")
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
+ (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
"TARGET_32BIT"
- ""
-)
+ [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
+{
+ rtx lo_part = gen_lowpart (SImode, operands[0]);
+ enum machine_mode src_mode = GET_MODE (operands[1]);
-(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"
- "*
- if (REGNO (operands[1])
- != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
- output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
- return \"mov%?\\t%R0, %Q0, asr #31\";
- "
- [(set_attr "length" "8")
- (set_attr "shift" "1")
- (set_attr "predicable" "yes")]
-)
+ if (REG_P (operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1]))
+ emit_clobber (operands[0]);
+
+ if (!REG_P (lo_part) || src_mode != SImode
+ || !rtx_equal_p (lo_part, operands[1]))
+ {
+ if (src_mode == SImode)
+ emit_move_insn (lo_part, operands[1]);
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, lo_part,
+ gen_rtx_SIGN_EXTEND (SImode, operands[1])));
+ operands[1] = lo_part;
+ }
+ operands[0] = gen_highpart (SImode, operands[0]);
+})
(define_expand "zero_extendhisi2"
- [(set (match_dup 2)
- (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
- (const_int 16)))
- (set (match_operand:SI 0 "s_register_operand" "")
- (lshiftrt:SI (match_dup 2) (const_int 16)))]
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
"TARGET_EITHER"
- "
- {
- if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ZERO_EXTEND (SImode, operands[1])));
- DONE;
- }
-
- if (TARGET_ARM && 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]);
-
- 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 "*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);
-
- 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)
+{
+ if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
{
- 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\";
+ emit_insn (gen_movhi_bytes (operands[0], operands[1]));
+ DONE;
}
-
- return \"ldrh\\t%0, %1\";
- "
- [(set_attr "length" "4")
- (set_attr "type" "load_byte")
- (set_attr "pool_range" "60")]
-)
+ if (!arm_arch6 && !MEM_P (operands[1]))
+ {
+ rtx t = gen_lowpart (SImode, operands[1]);
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
+ emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
+ DONE;
+ }
+})
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
+ "!TARGET_THUMB2 && !arm_arch6"
+ [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
+ (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
+{
+ operands[2] = gen_lowpart (SImode, operands[1]);
+})
-(define_insn "*thumb1_zero_extendhisi2_v6"
+(define_insn "*thumb1_zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=l,l")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
- "TARGET_THUMB1 && arm_arch6"
- "*
+ "TARGET_THUMB1"
+{
rtx mem;
+ if (which_alternative == 0 && arm_arch6)
+ return "uxth\t%0, %1";
if (which_alternative == 0)
- return \"uxth\\t%0, %1\";
+ return "#";
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)
ops[0] = operands[0];
ops[1] = a;
- output_asm_insn (\"mov %0, %1\", ops);
+ output_asm_insn ("mov\t%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")]
+ return "ldrh\t%0, %1";
+}
+ [(set_attr_alternative "length"
+ [(if_then_else (eq_attr "is_arch6" "yes")
+ (const_int 2) (const_int 4))
+ (const_int 4)])
+ (set_attr "type" "alu_shift,load_byte")]
)
(define_insn "*arm_zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,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")]
+ "@
+ #
+ ldr%(h%)\\t%0, %1"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")]
)
(define_insn "*arm_zero_extendhisi2_v6"
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")]
+ (set_attr "predicable" "yes")]
)
(define_insn "*arm_zero_extendhisi2addsi"
[(set (match_operand:SI 0 "s_register_operand" "")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
"TARGET_EITHER"
- "
- if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
+{
+ if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
{
- if (TARGET_ARM)
- {
- emit_insn (gen_andsi3 (operands[0],
- gen_lowpart (SImode, operands[1]),
- GEN_INT (255)));
- }
- else /* TARGET_THUMB */
- {
- rtx temp = gen_reg_rtx (SImode);
- rtx ops[3];
-
- operands[1] = copy_to_mode_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
-
- ops[0] = temp;
- 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] = temp;
- ops[2] = GEN_INT (24);
+ emit_insn (gen_andsi3 (operands[0],
+ gen_lowpart (SImode, operands[1]),
+ GEN_INT (255)));
+ DONE;
+ }
+ if (!arm_arch6 && !MEM_P (operands[1]))
+ {
+ rtx t = gen_lowpart (SImode, operands[1]);
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
+ emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
+ DONE;
+ }
+})
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
- }
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
+ "!arm_arch6"
+ [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
+ (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
+{
+ operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
+ if (TARGET_ARM)
+ {
+ emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
DONE;
}
- "
-)
+})
(define_insn "*thumb1_zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
"TARGET_THUMB1 && !arm_arch6"
- "ldrb\\t%0, %1"
- [(set_attr "length" "2")
- (set_attr "type" "load_byte")
- (set_attr "pool_range" "32")]
+ "@
+ #
+ ldrb\\t%0, %1"
+ [(set_attr "length" "4,2")
+ (set_attr "type" "alu_shift,load_byte")
+ (set_attr "pool_range" "*,32")]
)
(define_insn "*thumb1_zero_extendqisi2_v6"
"@
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")]
+ [(set_attr "length" "2")
+ (set_attr "type" "alu_shift,load_byte")]
)
(define_insn "*arm_zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ [(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"
- "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")]
+ "@
+ #
+ ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
+ [(set_attr "length" "8,4")
+ (set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")]
)
(define_insn "*arm_zero_extendqisi2_v6"
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")]
+ (set_attr "predicable" "yes")]
)
(define_insn "*arm_zero_extendqisi2addsi"
""
)
-(define_code_iterator ior_xor [ior xor])
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(match_operator 5 "subreg_lowpart_operator"
[(match_operand:SI 4 "s_register_operand" "")]))))]
"TARGET_32BIT
- && (INTVAL (operands[3])
+ && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
== (GET_MODE_MASK (GET_MODE (operands[5]))
& (GET_MODE_MASK (GET_MODE (operands[5]))
<< (INTVAL (operands[2])))))"
)
(define_expand "extendhisi2"
- [(set (match_dup 2)
- (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
- (const_int 16)))
- (set (match_operand:SI 0 "s_register_operand" "")
- (ashiftrt:SI (match_dup 2)
- (const_int 16)))]
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
"TARGET_EITHER"
- "
- {
- if (GET_CODE (operands[1]) == MEM)
- {
- 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 && 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]);
-
- if (arm_arch6)
- {
- 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 "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];
- rtx 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;
- }
+{
+ if (TARGET_THUMB1)
+ {
+ emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
+ DONE;
+ }
+ if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
+ {
+ emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
+ DONE;
+ }
- gcc_assert (GET_CODE (ops[1]) == REG);
+ if (!arm_arch6 && !MEM_P (operands[1]))
+ {
+ rtx t = gen_lowpart (SImode, operands[1]);
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
+ emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
+ DONE;
+ }
+})
- ops[0] = operands[0];
- ops[3] = operands[2];
- output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
- return \"\";
- }"
- [(set_attr "length" "4")
- (set_attr "type" "load_byte")
- (set_attr "pool_range" "1020")]
-)
+(define_split
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
+ (clobber (match_scratch:SI 2 ""))])]
+ "!arm_arch6"
+ [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
+ (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
+{
+ operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
+})
;; We used to have an early-clobber on the scratch register here.
;; However, there's a bug somewhere in reload which means that this
;; 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"
+(define_insn "thumb1_extendhisi2"
[(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"
+ "TARGET_THUMB1"
"*
{
rtx ops[4];
rtx mem;
+ if (which_alternative == 0 && !arm_arch6)
+ return \"#\";
if (which_alternative == 0)
return \"sxth\\t%0, %1\";
output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
return \"\";
}"
- [(set_attr "length" "2,4")
+ [(set_attr_alternative "length"
+ [(if_then_else (eq_attr "is_arch6" "yes")
+ (const_int 2) (const_int 4))
+ (const_int 4)])
(set_attr "type" "alu_shift,load_byte")
(set_attr "pool_range" "*,1020")]
)
}"
)
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
+ "!arm_arch6"
+ [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
+ (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
+{
+ operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
+})
+
(define_insn "*arm_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
"TARGET_ARM && arm_arch4 && !arm_arch6"
- "ldr%(sh%)\\t%0, %1"
- [(set_attr "type" "load_byte")
+ "@
+ #
+ ldr%(sh%)\\t%0, %1"
+ [(set_attr "length" "8,4")
+ (set_attr "type" "alu_shift,load_byte")
(set_attr "predicable" "yes")
- (set_attr "pool_range" "256")
- (set_attr "neg_pool_range" "244")]
+ (set_attr "pool_range" "*,256")
+ (set_attr "neg_pool_range" "*,244")]
)
;; ??? Check Thumb-2 pool range
)
(define_expand "extendqisi2"
- [(set (match_dup 2)
- (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)
- (const_int 24)))]
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
"TARGET_EITHER"
- "
- {
- if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
- {
- 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_arch4 && MEM_P (operands[1]))
+ 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;
- }
+ if (!arm_arch6 && !MEM_P (operands[1]))
+ {
+ rtx t = gen_lowpart (SImode, operands[1]);
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
+ emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
+ DONE;
+ }
+})
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
- }"
-)
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
+ "!arm_arch6"
+ [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
+ (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
+{
+ operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
+})
(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")))]
+ [(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_arch4 && !arm_arch6"
- "ldr%(sb%)\\t%0, %1"
- [(set_attr "type" "load_byte")
+ "@
+ #
+ ldr%(sb%)\\t%0, %1"
+ [(set_attr "length" "8,4")
+ (set_attr "type" "alu_shift,load_byte")
(set_attr "predicable" "yes")
- (set_attr "pool_range" "256")
- (set_attr "neg_pool_range" "244")]
+ (set_attr "pool_range" "*,256")
+ (set_attr "neg_pool_range" "*,244")]
)
(define_insn "*arm_extendqisi_v6"
(set_attr "predicable" "yes")]
)
-(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];
- rtx 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\";
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
+ "TARGET_THUMB1 && reload_completed"
+ [(set (match_dup 0) (match_dup 2))
+ (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
+{
+ rtx addr = XEXP (operands[1], 0);
- 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 (addr) == CONST)
+ addr = XEXP (addr, 0);
- 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 (\"lsl\\t%0, %0, #24\", ops);
- output_asm_insn (\"asr\\t%0, %0, #24\", 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 (\"lsl\\t%0, %0, #24\", ops);
- output_asm_insn (\"asr\\t%0, %0, #24\", 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 (\"lsl\\t%0, %0, #24\", ops);
- output_asm_insn (\"asr\\t%0, %0, #24\", 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,6")
- (set_attr "type" "load_byte,load_byte")
- (set_attr "pool_range" "32,32")]
-)
+ if (GET_CODE (addr) == PLUS
+ && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
+ /* No split necessary. */
+ FAIL;
+
+ if (GET_CODE (addr) == PLUS
+ && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
+ FAIL;
+
+ if (reg_overlap_mentioned_p (operands[0], addr))
+ {
+ rtx t = gen_lowpart (QImode, operands[0]);
+ emit_move_insn (t, operands[1]);
+ emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
+ DONE;
+ }
+
+ if (REG_P (addr))
+ {
+ addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
+ operands[2] = const0_rtx;
+ }
+ else if (GET_CODE (addr) != PLUS)
+ FAIL;
+ else if (REG_P (XEXP (addr, 0)))
+ {
+ operands[2] = XEXP (addr, 1);
+ addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
+ }
+ else
+ {
+ operands[2] = XEXP (addr, 0);
+ addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
+ }
+
+ operands[3] = change_address (operands[1], QImode, addr);
+})
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
+ (set (match_operand:SI 2 "register_operand" "") (const_int 0))
+ (set (match_operand:SI 3 "register_operand" "")
+ (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
+ "TARGET_THUMB1
+ && GET_CODE (XEXP (operands[4], 0)) == PLUS
+ && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
+ && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
+ && (peep2_reg_dead_p (3, operands[0])
+ || rtx_equal_p (operands[0], operands[3]))
+ && (peep2_reg_dead_p (3, operands[2])
+ || rtx_equal_p (operands[2], operands[3]))"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
+{
+ rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
+ operands[4] = change_address (operands[4], QImode, addr);
+})
-(define_insn "*thumb1_extendqisi2_v6"
+(define_insn "thumb1_extendqisi2"
[(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;
-
- if (which_alternative == 0)
- return \"sxtb\\t%0, %1\";
+ "TARGET_THUMB1"
+{
+ rtx addr;
- 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 (which_alternative == 0 && arm_arch6)
+ return "sxtb\\t%0, %1";
+ if (which_alternative == 0)
+ return "#";
- 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\";
+ addr = XEXP (operands[1], 0);
+ if (GET_CODE (addr) == PLUS
+ && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
+ 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")]
+ return "#";
+}
+ [(set_attr_alternative "length"
+ [(if_then_else (eq_attr "is_arch6" "yes")
+ (const_int 2) (const_int 4))
+ (const_int 2)
+ (if_then_else (eq_attr "is_arch6" "yes")
+ (const_int 4) (const_int 6))])
+ (set_attr "type" "alu_shift,load_byte,load_byte")]
)
(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"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
""
)
(define_insn "*arm_movdi"
[(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_32BIT
&& !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
&& !TARGET_IWMMXT
&& ( register_operand (operands[0], DImode)
"
[(set_attr "length" "8,12,16,8,8")
(set_attr "type" "*,*,*,load2,store2")
- (set_attr "pool_range" "*,*,*,1020,*")
- (set_attr "neg_pool_range" "*,*,*,1008,*")]
+ (set_attr "arm_pool_range" "*,*,*,1020,*")
+ (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
+ (set_attr "thumb2_pool_range" "*,*,*,4096,*")
+ (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
)
(define_split
}"
[(set_attr "length" "4,4,6,2,2,6,4,4")
(set_attr "type" "*,*,*,load2,store2,load2,store2,*")
+ (set_attr "insn" "*,mov,*,*,*,*,*,mov")
(set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
)
ldr%?\\t%0, %1
str%?\\t%1, %0"
[(set_attr "type" "*,*,*,*,load1,store1")
+ (set_attr "insn" "mov,mov,mvn,mov,*,*")
(set_attr "predicable" "yes")
(set_attr "pool_range" "*,*,*,*,4096,*")
(set_attr "neg_pool_range" "*,*,*,*,4084,*")]
mov\\t%0, %1"
[(set_attr "length" "2,2,4,4,2,2,2,2,2")
(set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
- (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
-)
+ (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
+ (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
"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]));"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (neg:SI (match_dup 2)))]
+ "
+ {
+ operands[1] = GEN_INT (- INTVAL (operands[1]));
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
+ }"
)
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
"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)))]
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
"
{
unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
if ((val & (mask << i)) == val)
break;
- /* Shouldn't happen, but we don't want to split if the shift is zero. */
+ /* Don't split if the shift is zero. */
if (i == 0)
FAIL;
operands[1] = GEN_INT (val >> i);
- operands[2] = GEN_INT (i);
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
+ operands[3] = GEN_INT (i);
}"
)
;; we use an unspec. The offset will be loaded from a constant pool entry,
;; since that is the only type of relocation we can use.
+;; Wrap calculation of the whole PIC address in a single pattern for the
+;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
+;; a PIC address involves two loads from memory, so we want to CSE it
+;; as often as possible.
+;; This pattern will be split into one of the pic_load_addr_* patterns
+;; and a move after GCSE optimizations.
+;;
+;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
+(define_expand "calculate_pic_address"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
+ (unspec:SI [(match_operand:SI 2 "" "")]
+ UNSPEC_PIC_SYM))))]
+ "flag_pic"
+)
+
+;; Split calculate_pic_address into pic_load_addr_* and a move.
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
+ (unspec:SI [(match_operand:SI 2 "" "")]
+ UNSPEC_PIC_SYM))))]
+ "flag_pic"
+ [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
+ (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
+ "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
+)
+
;; The rather odd constraints on the following are to force reload to leave
;; the insn alone, and to force the minipool generation pass to then move
;; the GOT symbol to memory.
-(define_insn "pic_load_addr_arm"
+(define_insn "pic_load_addr_32bit"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
- "TARGET_ARM && flag_pic"
+ "TARGET_32BIT && flag_pic"
"ldr%?\\t%0, %1"
[(set_attr "type" "load1")
- (set (attr "pool_range") (const_int 4096))
- (set (attr "neg_pool_range") (const_int 4084))]
+ (set_attr "pool_range" "4096")
+ (set (attr "neg_pool_range")
+ (if_then_else (eq_attr "is_thumb" "no")
+ (const_int 4084)
+ (const_int 0)))]
)
(define_insn "pic_load_addr_thumb1"
(const_int 4)
(match_operand 2 "" "")]
UNSPEC_PIC_BASE))]
- "TARGET_THUMB1"
+ "TARGET_THUMB"
"*
(*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
INTVAL (operands[2]));
)
(define_insn "tls_load_dot_plus_eight"
- [(set (match_operand:SI 0 "register_operand" "+r")
+ [(set (match_operand:SI 0 "register_operand" "=r")
(mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
(const_int 8)
(match_operand 2 "" "")]
return \"ldrh %0, %1\";
}"
[(set_attr "length" "2,4,2,2,2,2")
- (set_attr "type" "*,load1,store1,*,*,*")]
-)
+ (set_attr "type" "*,load1,store1,*,*,*")
+ (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
(define_expand "movhi_bytes"
;; Pattern to recognize insn generated default case above
(define_insn "*movhi_insn_arch4"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
(match_operand:HI 1 "general_operand" "rI,K,r,m"))]
"TARGET_ARM
&& arm_arch4
ldr%(h%)\\t%0, %1\\t%@ movhi"
[(set_attr "type" "*,*,store1,load1")
(set_attr "predicable" "yes")
+ (set_attr "insn" "mov,mvn,*,*")
(set_attr "pool_range" "*,*,*,256")
(set_attr "neg_pool_range" "*,*,*,244")]
)
"@
mov%?\\t%0, %1\\t%@ movhi
mvn%?\\t%0, #%B1\\t%@ movhi"
- [(set_attr "predicable" "yes")]
+ [(set_attr "predicable" "yes")
+ (set_attr "insn" "mov,mvn")]
)
(define_expand "thumb_movhi_clobber"
{
rtx reg = gen_reg_rtx (SImode);
+ /* For thumb we want an unsigned immediate, then we are more likely
+ to be able to use a movs insn. */
+ if (TARGET_THUMB)
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
+
emit_insn (gen_movsi (reg, operands[1]));
operands[1] = gen_lowpart (QImode, reg);
}
ldr%(b%)\\t%0, %1
str%(b%)\\t%1, %0"
[(set_attr "type" "*,*,load1,store1")
+ (set_attr "insn" "mov,mvn,*,*")
(set_attr "predicable" "yes")]
)
mov\\t%0, %1"
[(set_attr "length" "2")
(set_attr "type" "*,load1,store1,*,*,*")
- (set_attr "pool_range" "*,32,*,*,*,*")]
-)
+ (set_attr "insn" "*,*,*,mov,mov,mov")
+ (set_attr "pool_range" "*,32,*,*,*,*")
+ (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
;; HFmode moves
(define_expand "movhf"
(define_insn "*arm32_movhf"
[(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
(match_operand:HF 1 "general_operand" " m,r,r,F"))]
- "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_NEON_FP16)
+ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
&& ( s_register_operand (operands[0], HFmode)
|| s_register_operand (operands[1], HFmode))"
"*
"
[(set_attr "conds" "unconditional")
(set_attr "type" "load1,store1,*,*")
+ (set_attr "insn" "*,*,mov,mov")
(set_attr "length" "4,4,4,8")
- (set_attr "predicable" "yes")
- ]
+ (set_attr "predicable" "yes")]
)
(define_insn "*thumb1_movhf"
"
[(set_attr "length" "2")
(set_attr "type" "*,load1,store1,*,*")
- (set_attr "pool_range" "*,1020,*,*,*")]
-)
+ (set_attr "insn" "mov,*,*,mov,mov")
+ (set_attr "pool_range" "*,1020,*,*,*")
+ (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(define_split
[(set (match_operand:SF 0 "arm_general_register_operand" "")
(match_operand:SF 1 "immediate_operand" ""))]
- "TARGET_32BIT
+ "TARGET_EITHER
&& reload_completed
&& GET_CODE (operands[1]) == CONST_DOUBLE"
[(set (match_dup 2) (match_dup 3))]
(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"))]
- "TARGET_ARM
+ "TARGET_32BIT
&& TARGET_SOFT_FLOAT
&& (GET_CODE (operands[0]) != MEM
|| register_operand (operands[1], SFmode))"
mov%?\\t%0, %1
ldr%?\\t%0, %1\\t%@ float
str%?\\t%1, %0\\t%@ float"
- [(set_attr "length" "4,4,4")
- (set_attr "predicable" "yes")
+ [(set_attr "predicable" "yes")
(set_attr "type" "*,load1,store1")
+ (set_attr "insn" "mov,*,*")
(set_attr "pool_range" "*,4096,*")
- (set_attr "neg_pool_range" "*,4084,*")]
+ (set_attr "arm_neg_pool_range" "*,4084,*")
+ (set_attr "thumb2_neg_pool_range" "*,0,*")]
)
;;; ??? This should have alternatives for constants.
mov\\t%0, %1"
[(set_attr "length" "2")
(set_attr "type" "*,load1,store1,load1,store1,*,*")
- (set_attr "pool_range" "*,*,*,1020,*,*,*")]
+ (set_attr "pool_range" "*,*,*,1020,*,*,*")
+ (set_attr "insn" "*,*,*,*,*,mov,mov")
+ (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
)
(define_expand "movdf"
(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
+ "TARGET_32BIT && TARGET_SOFT_FLOAT
&& ( register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode))"
"*
"
[(set_attr "length" "8,12,16,8,8")
(set_attr "type" "*,*,*,load2,store2")
- (set_attr "pool_range" "1020")
- (set_attr "neg_pool_range" "1008")]
+ (set_attr "pool_range" "*,*,*,1020,*")
+ (set_attr "arm_neg_pool_range" "*,*,*,1008,*")
+ (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
)
;;; ??? This should have alternatives for constants.
"
[(set_attr "length" "4,2,2,6,4,4")
(set_attr "type" "*,load2,store2,load2,store2,*")
+ (set_attr "insn" "*,*,*,*,*,mov")
(set_attr "pool_range" "*,*,*,1020,*,*")]
)
;; load- and store-multiple insns
;; The arm can load/store any set of registers, provided that they are in
-;; ascending order; but that is beyond GCC so stick with what it knows.
+;; ascending order, but these expanders assume a contiguous set.
(define_expand "load_multiple"
[(match_par_dup 3 [(set (match_operand:SI 0 "" "")
FAIL;
operands[3]
- = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
+ = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
+ INTVAL (operands[2]),
force_reg (SImode, XEXP (operands[1], 0)),
- TRUE, FALSE, operands[1], &offset);
+ FALSE, operands[1], &offset);
})
-;; Load multiple with write-back
-
-(define_insn "*ldmsi_postinc4"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (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_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")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 12)))
- (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))))])]
- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "ldm%(ia%)\\t%1!, {%3, %4, %5}"
- [(set_attr "type" "load3")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*ldmsi_postinc2"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 8)))
- (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))))])]
- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "ldm%(ia%)\\t%1!, {%3, %4}"
- [(set_attr "type" "load2")
- (set_attr "predicable" "yes")]
-)
-
-;; Ordinary load multiple
-
-(define_insn "*ldmsi4"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
- (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))))
- (set (match_operand:SI 4 "arm_hard_register_operand" "")
- (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_32BIT && XVECLEN (operands[0], 0) == 4"
- "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
- [(set_attr "type" "load4")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*ldmsi3"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
- (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))))
- (set (match_operand:SI 4 "arm_hard_register_operand" "")
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "ldm%(ia%)\\t%1, {%2, %3, %4}"
- [(set_attr "type" "load3")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*ldmsi2"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
- (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_32BIT && XVECLEN (operands[0], 0) == 2"
- "ldm%(ia%)\\t%1, {%2, %3}"
- [(set_attr "type" "load2")
- (set_attr "predicable" "yes")]
-)
-
(define_expand "store_multiple"
[(match_par_dup 3 [(set (match_operand:SI 0 "" "")
(match_operand:SI 1 "" ""))
FAIL;
operands[3]
- = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
+ = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
+ INTVAL (operands[2]),
force_reg (SImode, XEXP (operands[0], 0)),
- TRUE, FALSE, operands[0], &offset);
+ FALSE, operands[0], &offset);
})
-;; Store multiple with write-back
-
-(define_insn "*stmsi_postinc4"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (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_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")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 12)))
- (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" ""))])]
- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "stm%(ia%)\\t%1!, {%3, %4, %5}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store3")]
-)
-
-(define_insn "*stmsi_postinc2"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "=r")
- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
- (const_int 8)))
- (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" ""))])]
- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "stm%(ia%)\\t%1!, {%3, %4}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store2")]
-)
-
-;; Ordinary store multiple
-
-(define_insn "*stmsi4"
- [(match_parallel 0 "store_multiple_operation"
- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
- (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" ""))
- (set (mem:SI (plus:SI (match_dup 1) (const_int 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_32BIT && XVECLEN (operands[0], 0) == 4"
- "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store4")]
-)
-
-(define_insn "*stmsi3"
- [(match_parallel 0 "store_multiple_operation"
- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
- (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" ""))
- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "stm%(ia%)\\t%1, {%2, %3, %4}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store3")]
-)
-
-(define_insn "*stmsi2"
- [(match_parallel 0 "store_multiple_operation"
- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
- (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_32BIT && XVECLEN (operands[0], 0) == 2"
- "stm%(ia%)\\t%1, {%2, %3}"
- [(set_attr "predicable" "yes")
- (set_attr "type" "store2")]
-)
;; Move a block of memory if it is word aligned and MORE than 2 words long.
;; We could let this apply for blocks of less than this, but it clobbers so
operands[2] = force_reg (SImode, operands[2]);
")
+;; A pattern to recognize a special situation and optimize for it.
+;; On the thumb, zero-extension from memory is preferrable to sign-extension
+;; due to the available addressing modes. Hence, convert a signed comparison
+;; with zero into an unsigned comparison with 127 if possible.
+(define_expand "cbranchqi4"
+ [(set (pc) (if_then_else
+ (match_operator 0 "lt_ge_comparison_operator"
+ [(match_operand:QI 1 "memory_operand" "")
+ (match_operand:QI 2 "const0_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_THUMB1"
+{
+ rtx xops[4];
+ xops[1] = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
+ xops[2] = GEN_INT (127);
+ xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
+ VOIDmode, xops[1], xops[2]);
+ xops[3] = operands[3];
+ emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
+ DONE;
+})
+
(define_expand "cbranchsf4"
[(set (pc) (if_then_else
(match_operator 0 "arm_comparison_operator"
(match_operand:DF 2 "arm_float_compare_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))]
- "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
operands[3])); DONE;"
)
-;; this uses the Cirrus DI compare instruction
(define_expand "cbranchdi4"
[(set (pc) (if_then_else
(match_operator 0 "arm_comparison_operator"
- [(match_operand:DI 1 "cirrus_fp_register" "")
- (match_operand:DI 2 "cirrus_fp_register" "")])
+ [(match_operand:DI 1 "cmpdi_operand" "")
+ (match_operand:DI 2 "cmpdi_operand" "")])
(label_ref (match_operand 3 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
- operands[3])); DONE;"
+ "TARGET_32BIT"
+ "{
+ rtx swap = NULL_RTX;
+ enum rtx_code code = GET_CODE (operands[0]);
+
+ /* We should not have two constants. */
+ gcc_assert (GET_MODE (operands[1]) == DImode
+ || GET_MODE (operands[2]) == DImode);
+
+ /* Flip unimplemented DImode comparisons to a form that
+ arm_gen_compare_reg can handle. */
+ switch (code)
+ {
+ case GT:
+ swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
+ case LE:
+ swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
+ case GTU:
+ swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
+ case LEU:
+ swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
+ default:
+ break;
+ }
+ if (swap)
+ emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
+ operands[3]));
+ else
+ emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }"
)
-(define_insn "*cbranchsi4_insn"
+(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 1 "s_register_operand" "l,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);
+{
+ rtx t = cfun->machine->thumb1_cc_insn;
+ if (t != NULL_RTX)
+ {
+ if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
+ || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
+ t = NULL_RTX;
+ if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
+ {
+ if (!noov_comparison_operator (operands[0], VOIDmode))
+ t = NULL_RTX;
+ }
+ else if (cfun->machine->thumb1_cc_mode != CCmode)
+ t = NULL_RTX;
+ }
+ if (t == NULL_RTX)
+ {
+ output_asm_insn ("cmp\t%1, %2", operands);
+ cfun->machine->thumb1_cc_insn = insn;
+ cfun->machine->thumb1_cc_op0 = operands[1];
+ cfun->machine->thumb1_cc_op1 = operands[2];
+ cfun->machine->thumb1_cc_mode = CCmode;
+ }
+ else
+ /* Ensure we emit the right type of condition code on the jump. */
+ XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
+ CC_REGNUM);
switch (get_attr_length (insn))
{
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_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))]
+
+;; Two peepholes to generate subtract of 0 instead of a move if the
+;; condition codes will be useful.
+(define_peephole2
+ [(set (match_operand:SI 0 "low_register_operand" "")
+ (match_operand:SI 1 "low_register_operand" ""))
+ (set (pc)
+ (if_then_else (match_operator 2 "arm_comparison_operator"
+ [(match_dup 1) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
"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)))))]
-)
+ [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
+ (set (pc)
+ (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
+ (label_ref (match_dup 3))
+ (pc)))]
+ "")
+
+;; Sigh! This variant shouldn't be needed, but combine often fails to
+;; merge cases like this because the op1 is a hard register in
+;; CLASS_LIKELY_SPILLED_P.
+(define_peephole2
+ [(set (match_operand:SI 0 "low_register_operand" "")
+ (match_operand:SI 1 "low_register_operand" ""))
+ (set (pc)
+ (if_then_else (match_operator 2 "arm_comparison_operator"
+ [(match_dup 0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_THUMB1"
+ [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
+ (set (pc)
+ (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
+ (label_ref (match_dup 3))
+ (pc)))]
+ "")
(define_insn "*negated_cbranchsi4"
[(set (pc)
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%=:\";
+ 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_int 6)
(const_int 8))))]
)
-
-(define_insn "*xorsi3_cbranch"
+
+(define_insn "*tbit_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"))
+ (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 4 "" ""))
+ (label_ref (match_operand 3 "" ""))
(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"))]
+ (clobber (match_scratch:SI 4 "=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);
- }
+ rtx op[3];
+ op[0] = operands[4];
+ op[1] = operands[1];
+ op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
- switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
+ output_asm_insn (\"lsl\\t%0, %1, %2\", op);
+ switch (get_attr_length (insn))
{
- 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%=:\";
+ 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
- (ior (and (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
+ (eq_attr "length" "8")
(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)))))]
+ (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 "*bicsi3_cbranch_scratch"
+
+(define_insn "*tlobits_cbranch"
[(set (pc)
(if_then_else
- (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"))
+ (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 0 "=l"))]
+ (clobber (match_scratch:SI 4 "=l"))]
"TARGET_THUMB1"
"*
{
- output_asm_insn (\"bic\\t%0, %2\", operands);
+ 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%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%=:\";
+ 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")
(const_int 6)
(const_int 8))))]
)
-
-(define_insn "*bicsi3_cbranch"
+
+(define_insn "*tstsi3_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"))
+ (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 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"))]
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
"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);
- }
-
- switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
+ output_asm_insn (\"tst\\t%0, %1\", operands);
+ switch (get_attr_length (insn))
{
- 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%=:\";
+ 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 (eq (symbol_ref ("which_alternative"))
- (const_int 0))
- (eq_attr "length" "8"))
- (eq_attr "length" "10"))
+ (eq_attr "length" "8")
(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)))))]
+ (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 "*cbranchne_decr1"
[(set (pc)
(if_then_else (match_operator 3 "equality_operator"
(if_then_else
(match_operator 4 "arm_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"))
+ (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
+ (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,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"))]
+ (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
"TARGET_THUMB1
&& (GET_CODE (operands[4]) == EQ
|| GET_CODE (operands[4]) == NE
{
rtx cond[3];
-
- cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
+ cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
cond[1] = operands[2];
cond[2] = operands[3];
else
output_asm_insn (\"add\\t%0, %1, %2\", cond);
- if (which_alternative >= 3
+ if (which_alternative >= 2
&& 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))
+ switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
{
case 4:
return \"b%d4\\t%l5\";
[(set (attr "far_jump")
(if_then_else
(ior (and (lt (symbol_ref ("which_alternative"))
- (const_int 3))
+ (const_int 2))
(eq_attr "length" "8"))
(eq_attr "length" "10"))
(const_string "yes")
(set (attr "length")
(if_then_else
(lt (symbol_ref ("which_alternative"))
- (const_int 3))
+ (const_int 2))
(if_then_else
(and (ge (minus (match_dup 5) (pc)) (const_int -250))
(le (minus (match_dup 5) (pc)) (const_int 256)))
(const_int 8))))]
)
-(define_insn "*subsi3_cbranch"
- [(set (pc)
- (if_then_else
- (match_operator 4 "arm_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_THUMB1
- && (GET_CODE (operands[0]) == EQ
- || GET_CODE (operands[0]) == NE
- || GET_CODE (operands[0]) == GE
- || GET_CODE (operands[0]) == LT)"
- "*
- 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))))]
-)
;; Comparison and test insns
[(set_attr "conds" "set")]
)
-(define_insn "*arm_cmpsi_shiftsi"
+(define_insn "*cmpsi_shiftsi"
[(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:SI 0 "s_register_operand" "r")
+ (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
- "TARGET_ARM"
+ [(match_operand:SI 1 "s_register_operand" "r,r")
+ (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
+ "TARGET_32BIT"
"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")))]
-)
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
-(define_insn "*arm_cmpsi_shiftsi_swp"
+(define_insn "*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")
- (match_operand:SI 2 "reg_or_int_operand" "rM")])
- (match_operand:SI 0 "s_register_operand" "r")))]
- "TARGET_ARM"
+ [(match_operand:SI 1 "s_register_operand" "r,r")
+ (match_operand:SI 2 "shift_amount_operand" "M,rM")])
+ (match_operand:SI 0 "s_register_operand" "r,r")))]
+ "TARGET_32BIT"
"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")))]
-)
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
(define_insn "*arm_cmpsi_negshiftsi_si"
[(set (reg:CC_Z CC_REGNUM)
(const_string "alu_shift_reg")))]
)
+;; DImode comparisons. The generic code generates branches that
+;; if-conversion can not reduce to a conditional compare, so we do
+;; that directly.
+
+(define_insn "*arm_cmpdi_insn"
+ [(set (reg:CC_NCV CC_REGNUM)
+ (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
+ (match_operand:DI 1 "arm_di_operand" "rDi")))
+ (clobber (match_scratch:SI 2 "=r"))]
+ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
+ "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
+ [(set_attr "conds" "set")
+ (set_attr "length" "8")]
+)
+
+(define_insn "*arm_cmpdi_unsigned"
+ [(set (reg:CC_CZ CC_REGNUM)
+ (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
+ (match_operand:DI 1 "arm_di_operand" "rDi")))]
+ "TARGET_ARM"
+ "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
+ [(set_attr "conds" "set")
+ (set_attr "length" "8")]
+)
+
+(define_insn "*arm_cmpdi_zero"
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
+ (const_int 0)))
+ (clobber (match_scratch:SI 1 "=r"))]
+ "TARGET_32BIT"
+ "orr%.\\t%1, %Q0, %R0"
+ [(set_attr "conds" "set")]
+)
+
+(define_insn "*thumb_cmpdi_zero"
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
+ (const_int 0)))
+ (clobber (match_scratch:SI 1 "=l"))]
+ "TARGET_THUMB1"
+ "orr\\t%1, %Q0, %R0"
+ [(set_attr "conds" "set")
+ (set_attr "length" "2")]
+)
+
;; Cirrus SF compare instruction
(define_insn "*cirrus_cmpsf"
[(set (reg:CCFP CC_REGNUM)
"TARGET_ARM"
"mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
[(set_attr "conds" "use")
+ (set_attr "insn" "mov")
(set_attr "length" "8")]
)
"TARGET_ARM"
"mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
[(set_attr "conds" "use")
+ (set_attr "insn" "mov")
(set_attr "length" "8")]
)
"TARGET_ARM"
"mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
[(set_attr "conds" "use")
+ (set_attr "insn" "mov")
(set_attr "length" "8")]
)
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));
+ emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
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));
+ emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
break;
/* No good sequences for GT, LT. */
(match_operator:SI 1 "arm_comparison_operator"
[(match_operand:DF 2 "s_register_operand" "")
(match_operand:DF 3 "arm_float_compare_operand" "")]))]
- "TARGET_32BIT && TARGET_HARD_FLOAT"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"emit_insn (gen_cstore_cc (operands[0], operands[1],
operands[2], operands[3])); DONE;"
)
-;; this uses the Cirrus DI compare instruction
(define_expand "cstoredi4"
[(set (match_operand:SI 0 "s_register_operand" "")
(match_operator:SI 1 "arm_comparison_operator"
- [(match_operand:DI 2 "cirrus_fp_register" "")
- (match_operand:DI 3 "cirrus_fp_register" "")]))]
- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
- "emit_insn (gen_cstore_cc (operands[0], operands[1],
- operands[2], operands[3])); DONE;"
+ [(match_operand:DI 2 "cmpdi_operand" "")
+ (match_operand:DI 3 "cmpdi_operand" "")]))]
+ "TARGET_32BIT"
+ "{
+ rtx swap = NULL_RTX;
+ enum rtx_code code = GET_CODE (operands[1]);
+
+ /* We should not have two constants. */
+ gcc_assert (GET_MODE (operands[2]) == DImode
+ || GET_MODE (operands[3]) == DImode);
+
+ /* Flip unimplemented DImode comparisons to a form that
+ arm_gen_compare_reg can handle. */
+ switch (code)
+ {
+ case GT:
+ swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
+ case LE:
+ swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
+ case GTU:
+ swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
+ case LEU:
+ swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
+ default:
+ break;
+ }
+ if (swap)
+ emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
+ operands[2]));
+ else
+ emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }"
)
-
(define_expand "cstoresi_eq0_thumb1"
[(parallel
[(set (match_operand:SI 0 "s_register_operand" "")
[(set_attr "length" "4")]
)
+;; Used as part of the expansion of thumb ltu and gtu sequences
(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")
[(set_attr "length" "4")]
)
+(define_insn_and_split "cstoresi_ltu_thumb1"
+ [(set (match_operand:SI 0 "s_register_operand" "=l,l")
+ (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
+ (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
+ "TARGET_THUMB1"
+ "#"
+ "TARGET_THUMB1"
+ [(set (match_dup 3)
+ (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
+ (set (match_dup 0) (neg:SI (match_dup 3)))]
+ "operands[3] = gen_reg_rtx (SImode);"
+ [(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")
(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
(match_operand:DF 2 "s_register_operand" "")
(match_operand:DF 3 "arm_float_add_operand" "")))]
- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
"
{
enum rtx_code code = GET_CODE (operands[1]);
mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
[(set_attr "length" "4,4,4,4,8,8,8,8")
- (set_attr "conds" "use")]
+ (set_attr "conds" "use")
+ (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
)
(define_insn "*movsfcc_soft_insn"
"@
mov%D3\\t%0, %2
mov%d3\\t%0, %1"
- [(set_attr "conds" "use")]
+ [(set_attr "conds" "use")
+ (set_attr "insn" "mov")]
)
\f
(set_attr "type" "call")]
)
+
+;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
+;; considered a function call by the branch predictor of some cores (PR40887).
+;; Falls back to blx rN (*call_reg_armv5).
+
(define_insn "*call_mem"
[(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM"
+ "TARGET_ARM && !arm_arch5"
"*
return output_call_mem (operands);
"
(set_attr "type" "call")]
)
+;; Note: see *call_mem
+
(define_insn "*call_value_mem"
[(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))]
- "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
+ "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
"*
return output_call_mem (&operands[1]);
"
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM
+ "TARGET_32BIT
&& (GET_CODE (operands[0]) == SYMBOL_REF)
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
"*
(match_operand:SI 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM
+ "TARGET_32BIT
&& (GET_CODE (operands[1]) == SYMBOL_REF)
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
"*
(match_operand:SI 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB
+ "TARGET_THUMB1
&& GET_CODE (operands[0]) == SYMBOL_REF
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
"bl\\t%a0"
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB
+ "TARGET_THUMB1
&& GET_CODE (operands[1]) == SYMBOL_REF
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
"bl\\t%a1"
(match_operand 1 "general_operand" ""))
(return)
(use (match_operand 2 "" ""))])]
- "TARGET_ARM"
+ "TARGET_32BIT"
"
{
if (operands[2] == NULL_RTX)
(match_operand 2 "general_operand" "")))
(return)
(use (match_operand 3 "" ""))])]
- "TARGET_ARM"
+ "TARGET_32BIT"
"
{
if (operands[3] == NULL_RTX)
(match_operand 1 "" ""))
(return)
(use (match_operand 2 "" ""))]
- "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
+ "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
"*
return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
"
(match_operand 2 "" "")))
(return)
(use (match_operand 3 "" ""))]
- "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
+ "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
"*
return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
"
[(set_attr "type" "call")]
)
+(define_expand "return"
+ [(return)]
+ "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
+ "")
+
;; Often the return insn will be the same as loading from memory, so set attr
-(define_insn "return"
+(define_insn "*arm_return"
[(return)]
"TARGET_ARM && USE_RETURN_INSN (FALSE)"
"*
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));
+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
size = TARGET_ARM ? 16 : 0;
}
else
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));
+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
size = TARGET_ARM ? 16 : 0;
}
else
;; Patterns to allow combination of arithmetic, cond code and shifts
(define_insn "*arith_shiftsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
(match_operator:SI 1 "shiftable_operator"
[(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "reg_or_int_operand" "rI")])
- (match_operand:SI 2 "s_register_operand" "r")]))]
- "TARGET_ARM"
+ [(match_operand:SI 4 "s_register_operand" "r,r")
+ (match_operand:SI 5 "shift_amount_operand" "M,r")])
+ (match_operand:SI 2 "s_register_operand" "rk,rk")]))]
+ "TARGET_32BIT"
"%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")))]
-)
+ (set_attr "arch" "32,a")
+ ;; We have to make sure to disable the second alternative if
+ ;; the shift_operator is MULT, since otherwise the insn will
+ ;; also match a multiply_accumulate pattern and validate_change
+ ;; will allow a replacement of the constant with a register
+ ;; despite the checks done in shift_operator.
+ (set_attr_alternative "insn_enabled"
+ [(const_string "yes")
+ (if_then_else
+ (match_operand:SI 3 "mult_operator" "")
+ (const_string "no") (const_string "yes"))])
+ (set_attr "type" "alu_shift,alu_shift_reg")])
(define_split
[(set (match_operand:SI 0 "s_register_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"
+ "TARGET_32BIT"
[(set (match_dup 8)
(match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
(match_dup 6)]))
(define_insn "*arith_shiftsi_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
- [(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "reg_or_int_operand" "rI")])
- (match_operand:SI 2 "s_register_operand" "r")])
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r")
+ (compare:CC_NOOV
+ (match_operator:SI 1 "shiftable_operator"
+ [(match_operator:SI 3 "shift_operator"
+ [(match_operand:SI 4 "s_register_operand" "r,r")
+ (match_operand:SI 5 "shift_amount_operand" "M,r")])
+ (match_operand:SI 2 "s_register_operand" "r,r")])
+ (const_int 0)))
+ (set (match_operand:SI 0 "s_register_operand" "=r,r")
(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
(match_dup 2)]))]
- "TARGET_ARM"
+ "TARGET_32BIT"
"%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")))]
-)
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
(define_insn "*arith_shiftsi_compare0_scratch"
[(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
- [(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 4 "s_register_operand" "r")
- (match_operand:SI 5 "reg_or_int_operand" "rI")])
- (match_operand:SI 2 "s_register_operand" "r")])
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
+ (compare:CC_NOOV
+ (match_operator:SI 1 "shiftable_operator"
+ [(match_operator:SI 3 "shift_operator"
+ [(match_operand:SI 4 "s_register_operand" "r,r")
+ (match_operand:SI 5 "shift_amount_operand" "M,r")])
+ (match_operand:SI 2 "s_register_operand" "r,r")])
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r,r"))]
+ "TARGET_32BIT"
"%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")))]
-)
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
(define_insn "*sub_shiftsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_operand:SI 1 "s_register_operand" "r")
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
(match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
- "TARGET_ARM"
+ [(match_operand:SI 3 "s_register_operand" "r,r")
+ (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
+ "TARGET_32BIT"
"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")))]
-)
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
(define_insn "*sub_shiftsi_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV
- (minus:SI (match_operand:SI 1 "s_register_operand" "r")
+ (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
(match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "reg_or_int_operand" "rM")]))
+ [(match_operand:SI 3 "s_register_operand" "r,r")
+ (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
(const_int 0)))
- (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"
+ (set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (minus:SI (match_dup 1)
+ (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
+ "TARGET_32BIT"
"sub%.\\t%0, %1, %3%S2"
[(set_attr "conds" "set")
(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")))]
-)
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
(define_insn "*sub_shiftsi_compare0_scratch"
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV
- (minus:SI (match_operand:SI 1 "s_register_operand" "r")
+ (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
(match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "reg_or_int_operand" "rM")]))
+ [(match_operand:SI 3 "s_register_operand" "r,r")
+ (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
(const_int 0)))
- (clobber (match_scratch:SI 0 "=r"))]
- "TARGET_ARM"
+ (clobber (match_scratch:SI 0 "=r,r"))]
+ "TARGET_32BIT"
"sub%.\\t%0, %1, %3%S2"
[(set_attr "conds" "set")
(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")))]
-)
-
+ (set_attr "arch" "32,a")
+ (set_attr "type" "alu_shift,alu_shift_reg")])
\f
(define_insn "*and_scc"
"TARGET_ARM"
"mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
[(set_attr "conds" "use")
+ (set_attr "insn" "mov")
(set_attr "length" "8")]
)
(set_attr "length" "4,8")]
)
-(define_insn "*compare_scc"
+; A series of splitters for the compare_scc pattern below. Note that
+; order is important.
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (lt:SI (match_operand:SI 1 "s_register_operand" "")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT && reload_completed"
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (ge:SI (match_operand:SI 1 "s_register_operand" "")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT && reload_completed"
+ [(set (match_dup 0) (not:SI (match_dup 1)))
+ (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (eq:SI (match_operand:SI 1 "s_register_operand" "")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT && reload_completed"
+ [(parallel
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (const_int 1) (match_dup 1)))
+ (set (match_dup 0)
+ (minus:SI (const_int 1) (match_dup 1)))])
+ (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
+ (set (match_dup 0) (const_int 0)))])
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (ne:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT && reload_completed"
+ [(parallel
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
+ (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
+ (set (match_dup 0) (const_int 1)))]
+{
+ operands[3] = GEN_INT (-INTVAL (operands[2]));
+})
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (ne:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "arm_add_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT && reload_completed"
+ [(parallel
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
+ (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (set (match_dup 0) (const_int 1)))])
+
+(define_insn_and_split "*compare_scc"
[(set (match_operand:SI 0 "s_register_operand" "=r,r")
(match_operator:SI 1 "arm_comparison_operator"
[(match_operand:SI 2 "s_register_operand" "r,r")
(match_operand:SI 3 "arm_add_operand" "rI,L")]))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM"
- "*
- if (operands[3] == const0_rtx)
- {
- if (GET_CODE (operands[1]) == LT)
- return \"mov\\t%0, %2, lsr #31\";
+ "TARGET_32BIT"
+ "#"
+ "&& reload_completed"
+ [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
+ (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
+ (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
+{
+ rtx tmp1;
+ enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
+ operands[2], operands[3]);
+ enum rtx_code rc = GET_CODE (operands[1]);
- if (GET_CODE (operands[1]) == GE)
- return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
+ tmp1 = gen_rtx_REG (mode, CC_REGNUM);
- if (GET_CODE (operands[1]) == EQ)
- return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
- }
+ operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
+ if (mode == CCFPmode || mode == CCFPEmode)
+ rc = reverse_condition_maybe_unordered (rc);
+ else
+ rc = reverse_condition (rc);
+ operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
+})
- if (GET_CODE (operands[1]) == NE)
- {
- if (which_alternative == 1)
- return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
- return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
- }
- if (which_alternative == 1)
- output_asm_insn (\"cmn\\t%2, #%n3\", operands);
- else
- output_asm_insn (\"cmp\\t%2, %3\", operands);
- return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
- "
- [(set_attr "conds" "clob")
- (set_attr "length" "12")]
-)
+;; Attempt to improve the sequence generated by the compare_scc splitters
+;; not to use conditional execution.
+(define_peephole2
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "arm_rhs_operand" "")))
+ (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
+ (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
+ (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
+ (set (match_dup 0) (const_int 1)))
+ (match_scratch:SI 3 "r")]
+ "TARGET_32BIT"
+ [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))
+ (parallel
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (const_int 0) (match_dup 3)))
+ (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
+ (set (match_dup 0)
+ (plus:SI (plus:SI (match_dup 0) (match_dup 3))
+ (geu:SI (reg:CC CC_REGNUM) (const_int 0))))])
(define_insn "*cond_move"
[(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
return \"\";
"
[(set_attr "conds" "use")
+ (set_attr "insn" "mov")
(set_attr "length" "4,4,8")]
)
mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
[(set_attr "conds" "use")
+ (set_attr "insn" "mvn")
(set_attr "length" "4,8,8")]
)
mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
[(set_attr "conds" "use")
+ (set_attr "insn" "mvn")
(set_attr "length" "4,8,8")]
)
[(set_attr "conds" "use")
(set_attr "shift" "2")
(set_attr "length" "4,8,8")
+ (set_attr "insn" "mov")
(set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
(const_string "alu_shift")
(const_string "alu_shift_reg")))]
[(set_attr "conds" "use")
(set_attr "shift" "2")
(set_attr "length" "4,8,8")
+ (set_attr "insn" "mov")
(set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
(const_string "alu_shift")
(const_string "alu_shift_reg")))]
[(set_attr "conds" "use")
(set_attr "shift" "1")
(set_attr "length" "8")
+ (set_attr "insn" "mov")
(set (attr "type") (if_then_else
(and (match_operand 2 "const_int_operand" "")
(match_operand 4 "const_int_operand" ""))
"TARGET_ARM"
"mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
[(set_attr "conds" "use")
+ (set_attr "insn" "mvn")
(set_attr "length" "8")]
)
"TARGET_ARM"
"mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
[(set_attr "conds" "use")
+ (set_attr "insn" "mvn")
(set_attr "length" "8")]
)
""
)
-; Peepholes to spot possible load- and store-multiples, if the ordering is
-; reversed, check that the memory references aren't volatile.
-
-(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=rk")
- (match_operand:SI 4 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=rk")
- (match_operand:SI 5 "memory_operand" "m"))
- (set (match_operand:SI 2 "s_register_operand" "=rk")
- (match_operand:SI 6 "memory_operand" "m"))
- (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)"
- "*
- return emit_ldm_seq (operands, 4);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=rk")
- (match_operand:SI 3 "memory_operand" "m"))
- (set (match_operand:SI 1 "s_register_operand" "=rk")
- (match_operand:SI 4 "memory_operand" "m"))
- (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)"
- "*
- return emit_ldm_seq (operands, 3);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=rk")
- (match_operand:SI 2 "memory_operand" "m"))
- (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)"
- "*
- return emit_ldm_seq (operands, 2);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 4 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "rk"))
- (set (match_operand:SI 5 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "rk"))
- (set (match_operand:SI 6 "memory_operand" "=m")
- (match_operand:SI 2 "s_register_operand" "rk"))
- (set (match_operand:SI 7 "memory_operand" "=m")
- (match_operand:SI 3 "s_register_operand" "rk"))]
- "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
- "*
- return emit_stm_seq (operands, 4);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 3 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "rk"))
- (set (match_operand:SI 4 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "rk"))
- (set (match_operand:SI 5 "memory_operand" "=m")
- (match_operand:SI 2 "s_register_operand" "rk"))]
- "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
- "*
- return emit_stm_seq (operands, 3);
- "
-)
-
-(define_peephole
- [(set (match_operand:SI 2 "memory_operand" "=m")
- (match_operand:SI 0 "s_register_operand" "rk"))
- (set (match_operand:SI 3 "memory_operand" "=m")
- (match_operand:SI 1 "s_register_operand" "rk"))]
- "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
- "*
- return emit_stm_seq (operands, 2);
- "
-)
-
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
mvn%D4\\t%0, %2
mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
[(set_attr "conds" "use")
+ (set_attr "insn" "mvn")
(set_attr "length" "4,8")]
)
(define_insn "*push_multi"
[(match_parallel 2 "multi_register_push"
[(set (match_operand:BLK 0 "memory_operand" "=m")
- (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
+ (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
UNSPEC_PUSH_MULT))])]
"TARGET_32BIT"
"*
(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:BLK [(match_operand:XF 1 "f_register_operand" "")]
UNSPEC_PUSH_MULT))])]
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
"*
}
break;
default:
+ /* XXX: Sometimes gcc does something really dumb and ends up with
+ a HIGH in a constant pool entry, usually because it's trying to
+ load into a VFP register. We know this will always be used in
+ combination with a LO_SUM which ignores the high bits, so just
+ strip off the HIGH. */
+ if (GET_CODE (x) == HIGH)
+ x = XEXP (x, 0);
assemble_integer (x, 4, BITS_PER_WORD, 1);
mark_symbol_refs_as_used (x);
break;
[(set_attr "predicable" "yes")
(set_attr "insn" "clz")])
+(define_insn "rbitsi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
+ "TARGET_32BIT && arm_arch_thumb2"
+ "rbit%?\\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "insn" "clz")])
+
+(define_expand "ctzsi2"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
+ "TARGET_32BIT && arm_arch_thumb2"
+ "
+ {
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_rbitsi2 (tmp, operands[1]));
+ emit_insn (gen_clzsi2 (operands[0], tmp));
+ }
+ DONE;
+ "
+)
+
;; V5E instructions.
(define_insn "prefetch"
[(set_attr "conds" "clob")]
)
+(define_insn "*arm_movtas_ze"
+ [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
+ (const_int 16)
+ (const_int 16))
+ (match_operand:SI 1 "const_int_operand" ""))]
+ "TARGET_32BIT"
+ "movt%?\t%0, %c1"
+ [(set_attr "predicable" "yes")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*arm_rev"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
+ "TARGET_32BIT && arm_arch6"
+ "rev%?\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*thumb1_rev"
+ [(set (match_operand:SI 0 "s_register_operand" "=l")
+ (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
+ "TARGET_THUMB1 && arm_arch6"
+ "rev\t%0, %1"
+ [(set_attr "length" "2")]
+)
+
+(define_expand "arm_legacy_rev"
+ [(set (match_operand:SI 2 "s_register_operand" "")
+ (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
+ (const_int 16))
+ (match_dup 1)))
+ (set (match_dup 2)
+ (lshiftrt:SI (match_dup 2)
+ (const_int 8)))
+ (set (match_operand:SI 3 "s_register_operand" "")
+ (rotatert:SI (match_dup 1)
+ (const_int 8)))
+ (set (match_dup 2)
+ (and:SI (match_dup 2)
+ (const_int -65281)))
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (xor:SI (match_dup 3)
+ (match_dup 2)))]
+ "TARGET_32BIT"
+ ""
+)
+
+;; Reuse temporaries to keep register pressure down.
+(define_expand "thumb_legacy_rev"
+ [(set (match_operand:SI 2 "s_register_operand" "")
+ (ashift:SI (match_operand:SI 1 "s_register_operand" "")
+ (const_int 24)))
+ (set (match_operand:SI 3 "s_register_operand" "")
+ (lshiftrt:SI (match_dup 1)
+ (const_int 24)))
+ (set (match_dup 3)
+ (ior:SI (match_dup 3)
+ (match_dup 2)))
+ (set (match_operand:SI 4 "s_register_operand" "")
+ (const_int 16))
+ (set (match_operand:SI 5 "s_register_operand" "")
+ (rotatert:SI (match_dup 1)
+ (match_dup 4)))
+ (set (match_dup 2)
+ (ashift:SI (match_dup 5)
+ (const_int 24)))
+ (set (match_dup 5)
+ (lshiftrt:SI (match_dup 5)
+ (const_int 24)))
+ (set (match_dup 5)
+ (ior:SI (match_dup 5)
+ (match_dup 2)))
+ (set (match_dup 5)
+ (rotatert:SI (match_dup 5)
+ (match_dup 4)))
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (ior:SI (match_dup 5)
+ (match_dup 3)))]
+ "TARGET_THUMB"
+ ""
+)
+
+(define_expand "bswapsi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
+"TARGET_EITHER && (arm_arch6 || !optimize_size)"
+"
+ if (!arm_arch6)
+ {
+ rtx op2 = gen_reg_rtx (SImode);
+ rtx op3 = gen_reg_rtx (SImode);
+
+ if (TARGET_THUMB)
+ {
+ rtx op4 = gen_reg_rtx (SImode);
+ rtx op5 = gen_reg_rtx (SImode);
+
+ emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
+ op2, op3, op4, op5));
+ }
+ else
+ {
+ emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
+ op2, op3));
+ }
+
+ DONE;
+ }
+ "
+)
+
+;; Load the load/store multiple patterns
+(include "ldmstm.md")
;; Load the FPA co-processor patterns
(include "fpa.md")
;; Load the Maverick co-processor patterns
(include "thumb2.md")
;; Neon patterns
(include "neon.md")
-
+;; Synchronization Primitives
+(include "sync.md")