]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* config/ia64/unwind-ia64.c (uw_advance_context): New. Call
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
afe27f3b 3;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
b11cae9e 4;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
f082f1c4 5;; and Martin Simmons (@harleqn.co.uk).
129a2fe4 6;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
b11cae9e 7
acf6ed70 8;; This file is part of GCC.
b11cae9e 9
acf6ed70 10;; GCC is free software; you can redistribute it and/or modify it
11;; under the terms of the GNU General Public License as published
12;; by the Free Software Foundation; either version 2, or (at your
13;; option) any later version.
b11cae9e 14
acf6ed70 15;; GCC is distributed in the hope that it will be useful, but WITHOUT
16;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18;; License for more details.
b11cae9e 19
20;; You should have received a copy of the GNU General Public License
acf6ed70 21;; along with GCC; see the file COPYING. If not, write to
dbddc6c4 22;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23;; Boston, MA 02110-1301, USA.
b11cae9e 24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
9c08d1fa 27\f
e1159bbe 28;;---------------------------------------------------------------------------
29;; Constants
30
31;; Register numbers
32(define_constants
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
e1159bbe 35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
e1159bbe 51
9c08d1fa 52;; UNSPEC Usage:
8a18b90c 53;; Note: sin and cos are no-longer used.
e1159bbe 54
55(define_constants
56 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
60 ; operand 0 is the result,
61 ; operand 1 the parameter.
62 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63 ; operand 0 is the first register,
64 ; subsequent registers are in parallel (use ...)
65 ; expressions.
66 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
67 ; usage, that is, we will add the pic_register
68 ; value to it before trying to dereference it.
2c96dc5a 69 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
70 ; GLOBAL_OFFSET_TABLE. The operation is fully
71 ; described by the RTL but must be wrapped to
72 ; prevent combine from trying to rip it apart.
73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
e1159bbe 74 ; being scheduled before the stack adjustment insn.
063a05c7 75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
68121397 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
8d232dc7 81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
f655717d 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
6cdcb15c 94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
e1159bbe 96 ]
97)
98
215b30b3 99;; UNSPEC_VOLATILE Usage:
e1159bbe 100
101(define_constants
102 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
103 ; insn in the code.
104 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
105 ; instruction epilogue sequence that isn't expanded
106 ; into normal RTL. Used for both normal and sibcall
107 ; epilogues.
108 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
109 ; for inlined constants.
110 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
111 ; table.
112 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
113 ; an 8-bit object.
114 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
115 ; a 16-bit object.
116 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
117 ; a 32-bit object.
118 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
119 ; a 64-bit object.
755eb2b4 120 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
121 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
122 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
123 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
124 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
125 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 126 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 127 ; handling.
e1159bbe 128 ]
129)
b11cae9e 130\f
e1159bbe 131;;---------------------------------------------------------------------------
9c08d1fa 132;; Attributes
133
215b30b3 134; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
135; generating ARM code. This is used to control the length of some insn
136; patterns that share the same RTL in both ARM and Thumb code.
1c494086 137(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 138
215b30b3 139; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
140; scheduling decisions for the load unit and the multiplier.
74a71f7d 141(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 142
5ecb8da7 143; IS_XSCALE is set to 'yes' when compiling for XScale.
144(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
145
331beb1a 146;; Operand number of an input operand that is shifted. Zero if the
147;; given instruction does not shift one of its input operands.
331beb1a 148(define_attr "shift" "" (const_int 0))
149
3d91c5d6 150; Floating Point Unit. If we only have floating point emulation, then there
151; is no point in scheduling the floating point insns. (Well, for best
152; performance we should try and group them together).
a2cd141b 153(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 154 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 155
094e994f 156; LENGTH of an instruction (in bytes)
157(define_attr "length" "" (const_int 4))
9c08d1fa 158
56d27660 159; POOL_RANGE is how far away from a constant pool entry that this insn
160; can be placed. If the distance is zero, then this insn will never
161; reference the pool.
cffb2a26 162; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
163; before its address.
56d27660 164(define_attr "pool_range" "" (const_int 0))
cffb2a26 165(define_attr "neg_pool_range" "" (const_int 0))
56d27660 166
215b30b3 167; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 168; If such an insn references the pool, then we have no way of knowing how,
169; so use the most conservative value for pool_range.
9c08d1fa 170(define_asm_attributes
4d7a8451 171 [(set_attr "conds" "clob")
172 (set_attr "length" "4")
173 (set_attr "pool_range" "250")])
9c08d1fa 174
a2cd141b 175;; The instruction used to implement a particular pattern. This
176;; information is used by pipeline descriptions to provide accurate
177;; scheduling information.
178
179(define_attr "insn"
180 "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
181 (const_string "other"))
182
9c08d1fa 183; TYPE attribute is used to detect floating point instructions which, if
184; running on a co-processor can run in parallel with other, basic instructions
185; If write-buffer scheduling is enabled then it can also be used in the
186; scheduling of writes.
187
188; Classification of each insn
a2cd141b 189; alu any alu instruction that doesn't hit memory or fp
190; regs or have a shifted source operand
191; alu_shift any data instruction that doesn't hit memory or fp
192; regs, but has a source operand shifted by a constant
193; alu_shift_reg any data instruction that doesn't hit memory or fp
194; regs, but has a source operand shifted by a register value
f7fbdd4a 195; mult a multiply instruction
9c08d1fa 196; block blockage insn, this blocks all functional units
197; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 198; fdivd DFmode floating point division
199; fdivs SFmode floating point division
200; fmul Floating point multiply
201; ffmul Fast floating point multiply
202; farith Floating point arithmetic (4 cycle)
203; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 204; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 205; even on a machine with an fpa.
9c08d1fa 206; f_load a floating point load from memory
207; f_store a floating point store to memory
9aff9709 208; f_load[sd] single/double load from memory
209; f_store[sd] single/double store to memory
c0e1af52 210; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 211; f_mem_r a transfer of a floating point register to a real reg via mem
212; r_mem_f the reverse of f_mem_r
213; f_2_r fast transfer float to arm (no memory needed)
214; r_2_f fast transfer arm to float
c0e1af52 215; f_cvt convert floating<->integral
a2cd141b 216; branch a branch
9c08d1fa 217; call a subroutine call
a2cd141b 218; load_byte load byte(s) from memory to arm registers
219; load1 load 1 word from memory to arm registers
220; load2 load 2 words from memory to arm registers
221; load3 load 3 words from memory to arm registers
222; load4 load 4 words from memory to arm registers
223; store store 1 word to memory from arm registers
9c08d1fa 224; store2 store 2 words
225; store3 store 3 words
a2cd141b 226; store4 store 4 (or more) words
2c6c7d8b 227; Additions for Cirrus Maverick co-processor:
228; mav_farith Floating point arithmetic (4 cycle)
229; mav_dmult Double multiplies (7 cycle)
9c08d1fa 230;
231(define_attr "type"
c0e1af52 232 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
a2cd141b 233 (if_then_else
234 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
235 (const_string "mult")
236 (const_string "alu")))
9c08d1fa 237
9888ad6d 238; Load scheduling, set from the arm_ld_sched variable
457275b6 239; initialized by arm_override_options()
9888ad6d 240(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 241
f7fbdd4a 242; condition codes: this one is used by final_prescan_insn to speed up
243; conditionalizing instructions. It saves having to scan the rtl to see if
244; it uses or alters the condition codes.
215b30b3 245;
f7fbdd4a 246; USE means that the condition codes are used by the insn in the process of
215b30b3 247; outputting code, this means (at present) that we can't use the insn in
248; inlined branches
249;
f7fbdd4a 250; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 251; well defined manner.
252;
f7fbdd4a 253; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 254; they are altered at all
255;
8fa3ba89 256; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 257; instruction (UNEQ and LTGT). These cannot be predicated.
258;
f7fbdd4a 259; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 260; output of this insn
f7fbdd4a 261
262(define_attr "conds" "use,set,clob,jump_clob,nocond"
263 (if_then_else (eq_attr "type" "call")
c1a66faf 264 (const_string "clob")
f7fbdd4a 265 (const_string "nocond")))
266
215b30b3 267; Predicable means that the insn can be conditionally executed based on
268; an automatically added predicate (additional patterns are generated by
269; gen...). We default to 'no' because no Thumb patterns match this rule
270; and not all ARM patterns do.
0d66636f 271(define_attr "predicable" "no,yes" (const_string "no"))
272
129a2fe4 273; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
274; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 275; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 276; affect the schedule).
74a71f7d 277(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 278
215b30b3 279; WRITE_CONFLICT implies that a read following an unrelated write is likely
280; to stall the processor. Used with model_wbuf above.
9c08d1fa 281(define_attr "write_conflict" "no,yes"
282 (if_then_else (eq_attr "type"
a2cd141b 283 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 284 (const_string "yes")
285 (const_string "no")))
286
215b30b3 287; Classify the insns into those that take one cycle and those that take more
288; than one on the main cpu execution unit.
f7fbdd4a 289(define_attr "core_cycles" "single,multi"
290 (if_then_else (eq_attr "type"
a2cd141b 291 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 292 (const_string "single")
293 (const_string "multi")))
294
cffb2a26 295;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 296;; distant label. Only applicable to Thumb code.
cffb2a26 297(define_attr "far_jump" "yes,no" (const_string "no"))
298
d51f92df 299
300;;---------------------------------------------------------------------------
301;; Mode macros
302
303; A list of modes that are exactly 64 bits in size. We use this to expand
304; some splits that are the same for all modes when operating on ARM
305; registers.
306(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
307
308;;---------------------------------------------------------------------------
309;; Predicates
310
9c9db025 311(include "predicates.md")
312
a2cd141b 313;;---------------------------------------------------------------------------
314;; Pipeline descriptions
215b30b3 315
06469f9e 316;; Processor type. This is created automatically from arm-cores.def.
317(include "arm-tune.md")
331beb1a 318
a2cd141b 319;; True if the generic scheduling description should be used.
320
321(define_attr "generic_sched" "yes,no"
4d5cb40d 322 (const (if_then_else
c0e1af52 323 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
4d5cb40d 324 (const_string "no")
325 (const_string "yes"))))
326
c0e1af52 327(define_attr "generic_vfp" "yes,no"
328 (const (if_then_else
329 (and (eq_attr "fpu" "vfp")
330 (eq_attr "tune" "!arm1020e,arm1022e"))
331 (const_string "yes")
332 (const_string "no"))))
333
a2cd141b 334(include "arm-generic.md")
335(include "arm926ejs.md")
c0e1af52 336(include "arm1020e.md")
a2cd141b 337(include "arm1026ejs.md")
338(include "arm1136jfs.md")
3586df96 339
9c08d1fa 340\f
215b30b3 341;;---------------------------------------------------------------------------
e1159bbe 342;; Insn patterns
343;;
a0f94409 344;; Addition insns.
215b30b3 345
9c08d1fa 346;; Note: For DImode insns, there is normally no reason why operands should
347;; not be in the same register, what we don't want is for something being
348;; written to partially overlap something that is an input.
7d57ec45 349;; Cirrus 64bit additions should not be split because we have a native
350;; 64bit addition instructions.
9c08d1fa 351
cffb2a26 352(define_expand "adddi3"
353 [(parallel
215b30b3 354 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 355 (plus:DI (match_operand:DI 1 "s_register_operand" "")
356 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 357 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 358 "TARGET_EITHER"
359 "
a2cd141b 360 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 361 {
362 if (!cirrus_fp_register (operands[0], DImode))
363 operands[0] = force_reg (DImode, operands[0]);
364 if (!cirrus_fp_register (operands[1], DImode))
365 operands[1] = force_reg (DImode, operands[1]);
366 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
367 DONE;
368 }
369
cffb2a26 370 if (TARGET_THUMB)
371 {
372 if (GET_CODE (operands[1]) != REG)
373 operands[1] = force_reg (SImode, operands[1]);
374 if (GET_CODE (operands[2]) != REG)
375 operands[2] = force_reg (SImode, operands[2]);
376 }
377 "
378)
379
380(define_insn "*thumb_adddi3"
381 [(set (match_operand:DI 0 "register_operand" "=l")
382 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 383 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 384 (clobber (reg:CC CC_REGNUM))
cffb2a26 385 ]
386 "TARGET_THUMB"
387 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388 [(set_attr "length" "4")]
389)
390
a0f94409 391(define_insn_and_split "*arm_adddi3"
cffb2a26 392 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 393 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 395 (clobber (reg:CC CC_REGNUM))]
a2cd141b 396 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 397 "#"
a0f94409 398 "TARGET_ARM && reload_completed"
399 [(parallel [(set (reg:CC_C CC_REGNUM)
400 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
401 (match_dup 1)))
402 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404 (plus:SI (match_dup 4) (match_dup 5))))]
405 "
406 {
407 operands[3] = gen_highpart (SImode, operands[0]);
408 operands[0] = gen_lowpart (SImode, operands[0]);
409 operands[4] = gen_highpart (SImode, operands[1]);
410 operands[1] = gen_lowpart (SImode, operands[1]);
411 operands[5] = gen_highpart (SImode, operands[2]);
412 operands[2] = gen_lowpart (SImode, operands[2]);
413 }"
cffb2a26 414 [(set_attr "conds" "clob")
415 (set_attr "length" "8")]
416)
9c08d1fa 417
a0f94409 418(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 419 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420 (plus:DI (sign_extend:DI
97499065 421 (match_operand:SI 2 "s_register_operand" "r,r"))
422 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 423 (clobber (reg:CC CC_REGNUM))]
a2cd141b 424 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 425 "#"
a0f94409 426 "TARGET_ARM && reload_completed"
427 [(parallel [(set (reg:CC_C CC_REGNUM)
428 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
429 (match_dup 1)))
430 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432 (plus:SI (ashiftrt:SI (match_dup 2)
433 (const_int 31))
434 (match_dup 4))))]
435 "
436 {
437 operands[3] = gen_highpart (SImode, operands[0]);
438 operands[0] = gen_lowpart (SImode, operands[0]);
439 operands[4] = gen_highpart (SImode, operands[1]);
440 operands[1] = gen_lowpart (SImode, operands[1]);
441 operands[2] = gen_lowpart (SImode, operands[2]);
442 }"
215b30b3 443 [(set_attr "conds" "clob")
444 (set_attr "length" "8")]
445)
9c08d1fa 446
a0f94409 447(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 448 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449 (plus:DI (zero_extend:DI
97499065 450 (match_operand:SI 2 "s_register_operand" "r,r"))
451 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 452 (clobber (reg:CC CC_REGNUM))]
a2cd141b 453 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 454 "#"
a0f94409 455 "TARGET_ARM && reload_completed"
456 [(parallel [(set (reg:CC_C CC_REGNUM)
457 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
458 (match_dup 1)))
459 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461 (plus:SI (match_dup 4) (const_int 0))))]
462 "
463 {
464 operands[3] = gen_highpart (SImode, operands[0]);
465 operands[0] = gen_lowpart (SImode, operands[0]);
466 operands[4] = gen_highpart (SImode, operands[1]);
467 operands[1] = gen_lowpart (SImode, operands[1]);
468 operands[2] = gen_lowpart (SImode, operands[2]);
469 }"
cffb2a26 470 [(set_attr "conds" "clob")
471 (set_attr "length" "8")]
472)
b11cae9e 473
87b22bf7 474(define_expand "addsi3"
cffb2a26 475 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 476 (plus:SI (match_operand:SI 1 "s_register_operand" "")
477 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 478 "TARGET_EITHER"
87b22bf7 479 "
cffb2a26 480 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 481 {
96f57e36 482 arm_split_constant (PLUS, SImode, NULL_RTX,
483 INTVAL (operands[2]), operands[0], operands[1],
615caa51 484 optimize && !no_new_pseudos);
87b22bf7 485 DONE;
486 }
cffb2a26 487 "
488)
87b22bf7 489
5bd751ff 490; If there is a scratch available, this will be faster than synthesizing the
a0f94409 491; addition.
492(define_peephole2
493 [(match_scratch:SI 3 "r")
372575c7 494 (set (match_operand:SI 0 "arm_general_register_operand" "")
495 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 496 (match_operand:SI 2 "const_int_operand" "")))]
497 "TARGET_ARM &&
a0f94409 498 !(const_ok_for_arm (INTVAL (operands[2]))
499 || const_ok_for_arm (-INTVAL (operands[2])))
500 && const_ok_for_arm (~INTVAL (operands[2]))"
501 [(set (match_dup 3) (match_dup 2))
502 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503 ""
504)
87b22bf7 505
a0f94409 506(define_insn_and_split "*arm_addsi3"
cffb2a26 507 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0f94409 508 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
87b22bf7 509 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
cffb2a26 510 "TARGET_ARM"
5565501b 511 "@
512 add%?\\t%0, %1, %2
87b22bf7 513 sub%?\\t%0, %1, #%n2
514 #"
a0f94409 515 "TARGET_ARM &&
516 GET_CODE (operands[2]) == CONST_INT
517 && !(const_ok_for_arm (INTVAL (operands[2]))
518 || const_ok_for_arm (-INTVAL (operands[2])))"
519 [(clobber (const_int 0))]
520 "
96f57e36 521 arm_split_constant (PLUS, SImode, curr_insn,
522 INTVAL (operands[2]), operands[0],
a0f94409 523 operands[1], 0);
524 DONE;
525 "
0d66636f 526 [(set_attr "length" "4,4,16")
527 (set_attr "predicable" "yes")]
cffb2a26 528)
529
530;; Register group 'k' is a single register group containing only the stack
531;; register. Trying to reload it will always fail catastrophically,
532;; so never allow those alternatives to match if reloading is needed.
533
534(define_insn "*thumb_addsi3"
535 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
536 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
538 "TARGET_THUMB"
539 "*
0d66636f 540 static const char * const asms[] =
cffb2a26 541 {
542 \"add\\t%0, %0, %2\",
543 \"sub\\t%0, %0, #%n2\",
544 \"add\\t%0, %1, %2\",
545 \"add\\t%0, %0, %2\",
546 \"add\\t%0, %0, %2\",
547 \"add\\t%0, %1, %2\",
548 \"add\\t%0, %1, %2\"
549 };
550 if ((which_alternative == 2 || which_alternative == 6)
551 && GET_CODE (operands[2]) == CONST_INT
552 && INTVAL (operands[2]) < 0)
553 return \"sub\\t%0, %1, #%n2\";
554 return asms[which_alternative];
555 "
556 [(set_attr "length" "2")]
557)
558
559;; Reloading and elimination of the frame pointer can
560;; sometimes cause this optimization to be missed.
a0f94409 561(define_peephole2
372575c7 562 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 563 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 564 (set (match_dup 0)
372575c7 565 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
cffb2a26 566 "TARGET_THUMB
cffb2a26 567 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568 && (INTVAL (operands[1]) & 3) == 0"
372575c7 569 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 570 ""
cffb2a26 571)
b11cae9e 572
f7fbdd4a 573(define_insn "*addsi3_compare0"
bd5b4116 574 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 575 (compare:CC_NOOV
215b30b3 576 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 578 (const_int 0)))
579 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 580 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 581 "TARGET_ARM"
5565501b 582 "@
583 add%?s\\t%0, %1, %2
584 sub%?s\\t%0, %1, #%n2"
cffb2a26 585 [(set_attr "conds" "set")]
586)
9c08d1fa 587
aea4c774 588(define_insn "*addsi3_compare0_scratch"
bd5b4116 589 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 590 (compare:CC_NOOV
215b30b3 591 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 593 (const_int 0)))]
cffb2a26 594 "TARGET_ARM"
595 "@
596 cmn%?\\t%0, %1
597 cmp%?\\t%0, #%n1"
0d66636f 598 [(set_attr "conds" "set")]
599)
cffb2a26 600
aed179ae 601(define_insn "*compare_negsi_si"
602 [(set (reg:CC_Z CC_REGNUM)
603 (compare:CC_Z
604 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 606 "TARGET_ARM"
aed179ae 607 "cmn%?\\t%1, %0"
0d66636f 608 [(set_attr "conds" "set")]
609)
aea4c774 610
203c488f 611;; This is the canonicalization of addsi3_compare0_for_combiner when the
612;; addend is a constant.
613(define_insn "*cmpsi2_addneg"
614 [(set (reg:CC CC_REGNUM)
615 (compare:CC
616 (match_operand:SI 1 "s_register_operand" "r,r")
617 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618 (set (match_operand:SI 0 "s_register_operand" "=r,r")
619 (plus:SI (match_dup 1)
620 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
622 "@
623 sub%?s\\t%0, %1, %2
624 add%?s\\t%0, %1, #%n2"
625 [(set_attr "conds" "set")]
626)
627
628;; Convert the sequence
629;; sub rd, rn, #1
630;; cmn rd, #1 (equivalent to cmp rd, #-1)
631;; bne dest
632;; into
633;; subs rd, rn, #1
634;; bcs dest ((unsigned)rn >= 1)
635;; similarly for the beq variant using bcc.
636;; This is a common looping idiom (while (n--))
637(define_peephole2
372575c7 638 [(set (match_operand:SI 0 "arm_general_register_operand" "")
639 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 640 (const_int -1)))
641 (set (match_operand 2 "cc_register" "")
642 (compare (match_dup 0) (const_int -1)))
643 (set (pc)
644 (if_then_else (match_operator 3 "equality_operator"
645 [(match_dup 2) (const_int 0)])
646 (match_operand 4 "" "")
647 (match_operand 5 "" "")))]
648 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
649 [(parallel[
650 (set (match_dup 2)
651 (compare:CC
652 (match_dup 1) (const_int 1)))
653 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
654 (set (pc)
655 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
656 (match_dup 4)
657 (match_dup 5)))]
658 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
660 ? GEU : LTU),
661 VOIDmode,
662 operands[2], const0_rtx);"
663)
664
ebcc79bc 665;; The next four insns work because they compare the result with one of
666;; the operands, and we know that the use of the condition code is
667;; either GEU or LTU, so we can use the carry flag from the addition
668;; instead of doing the compare a second time.
669(define_insn "*addsi3_compare_op1"
bd5b4116 670 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 671 (compare:CC_C
672 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673 (match_operand:SI 2 "arm_add_operand" "rI,L"))
674 (match_dup 1)))
675 (set (match_operand:SI 0 "s_register_operand" "=r,r")
676 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 677 "TARGET_ARM"
ebcc79bc 678 "@
679 add%?s\\t%0, %1, %2
680 sub%?s\\t%0, %1, #%n2"
0d66636f 681 [(set_attr "conds" "set")]
682)
ebcc79bc 683
684(define_insn "*addsi3_compare_op2"
bd5b4116 685 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 686 (compare:CC_C
687 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688 (match_operand:SI 2 "arm_add_operand" "rI,L"))
689 (match_dup 2)))
5565501b 690 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 691 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 692 "TARGET_ARM"
5565501b 693 "@
694 add%?s\\t%0, %1, %2
695 sub%?s\\t%0, %1, #%n2"
0d66636f 696 [(set_attr "conds" "set")]
697)
9c08d1fa 698
ebcc79bc 699(define_insn "*compare_addsi2_op0"
bd5b4116 700 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 701 (compare:CC_C
702 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703 (match_operand:SI 1 "arm_add_operand" "rI,L"))
704 (match_dup 0)))]
cffb2a26 705 "TARGET_ARM"
ebcc79bc 706 "@
707 cmn%?\\t%0, %1
708 cmp%?\\t%0, #%n1"
0d66636f 709 [(set_attr "conds" "set")]
710)
ebcc79bc 711
712(define_insn "*compare_addsi2_op1"
bd5b4116 713 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 714 (compare:CC_C
715 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716 (match_operand:SI 1 "arm_add_operand" "rI,L"))
717 (match_dup 1)))]
cffb2a26 718 "TARGET_ARM"
ebcc79bc 719 "@
720 cmn%?\\t%0, %1
721 cmp%?\\t%0, #%n1"
0d66636f 722 [(set_attr "conds" "set")]
723)
ebcc79bc 724
725(define_insn "*addsi3_carryin"
726 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 727 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 728 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
cffb2a26 730 "TARGET_ARM"
ebcc79bc 731 "adc%?\\t%0, %1, %2"
cffb2a26 732 [(set_attr "conds" "use")]
733)
ebcc79bc 734
33782ec7 735(define_insn "*addsi3_carryin_shift"
7b63a8dd 736 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 737 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 738 (plus:SI
739 (match_operator:SI 2 "shift_operator"
7b63a8dd 740 [(match_operand:SI 3 "s_register_operand" "r")
741 (match_operand:SI 4 "reg_or_int_operand" "rM")])
742 (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 743 "TARGET_ARM"
33782ec7 744 "adc%?\\t%0, %1, %3%S2"
a2cd141b 745 [(set_attr "conds" "use")
746 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747 (const_string "alu_shift")
748 (const_string "alu_shift_reg")))]
33782ec7 749)
750
ebcc79bc 751(define_insn "*addsi3_carryin_alt1"
752 [(set (match_operand:SI 0 "s_register_operand" "=r")
753 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 755 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
cffb2a26 756 "TARGET_ARM"
ebcc79bc 757 "adc%?\\t%0, %1, %2"
cffb2a26 758 [(set_attr "conds" "use")]
759)
ebcc79bc 760
761(define_insn "*addsi3_carryin_alt2"
762 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 763 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 764 (match_operand:SI 1 "s_register_operand" "r"))
765 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 766 "TARGET_ARM"
ebcc79bc 767 "adc%?\\t%0, %1, %2"
0d66636f 768 [(set_attr "conds" "use")]
769)
ebcc79bc 770
771(define_insn "*addsi3_carryin_alt3"
772 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 773 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 774 (match_operand:SI 2 "arm_rhs_operand" "rI"))
775 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 776 "TARGET_ARM"
ebcc79bc 777 "adc%?\\t%0, %1, %2"
cffb2a26 778 [(set_attr "conds" "use")]
779)
ebcc79bc 780
9c08d1fa 781(define_insn "incscc"
782 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 783 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 784 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 785 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 786 "TARGET_ARM"
5565501b 787 "@
788 add%d2\\t%0, %1, #1
789 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 790 [(set_attr "conds" "use")
215b30b3 791 (set_attr "length" "4,8")]
792)
9c08d1fa 793
d795fb69 794; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
795(define_split
796 [(set (match_operand:SI 0 "s_register_operand" "")
797 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798 (match_operand:SI 2 "s_register_operand" ""))
799 (const_int -1)))
800 (clobber (match_operand:SI 3 "s_register_operand" ""))]
801 "TARGET_ARM"
802 [(set (match_dup 3) (match_dup 1))
803 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
804 "
805 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
806")
807
604f3a0a 808(define_expand "addsf3"
809 [(set (match_operand:SF 0 "s_register_operand" "")
810 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 811 (match_operand:SF 2 "arm_float_add_operand" "")))]
812 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 813 "
a2cd141b 814 if (TARGET_MAVERICK
604f3a0a 815 && !cirrus_fp_register (operands[2], SFmode))
816 operands[2] = force_reg (SFmode, operands[2]);
817")
818
604f3a0a 819(define_expand "adddf3"
820 [(set (match_operand:DF 0 "s_register_operand" "")
821 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 822 (match_operand:DF 2 "arm_float_add_operand" "")))]
823 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 824 "
a2cd141b 825 if (TARGET_MAVERICK
604f3a0a 826 && !cirrus_fp_register (operands[2], DFmode))
827 operands[2] = force_reg (DFmode, operands[2]);
828")
829
cffb2a26 830(define_expand "subdi3"
831 [(parallel
832 [(set (match_operand:DI 0 "s_register_operand" "")
833 (minus:DI (match_operand:DI 1 "s_register_operand" "")
834 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 835 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 836 "TARGET_EITHER"
837 "
a2cd141b 838 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
7d57ec45 839 && TARGET_ARM
840 && cirrus_fp_register (operands[0], DImode)
841 && cirrus_fp_register (operands[1], DImode))
842 {
843 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
844 DONE;
845 }
846
cffb2a26 847 if (TARGET_THUMB)
848 {
849 if (GET_CODE (operands[1]) != REG)
850 operands[1] = force_reg (SImode, operands[1]);
851 if (GET_CODE (operands[2]) != REG)
852 operands[2] = force_reg (SImode, operands[2]);
853 }
854 "
855)
856
857(define_insn "*arm_subdi3"
858 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 859 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 861 (clobber (reg:CC CC_REGNUM))]
cffb2a26 862 "TARGET_ARM"
97499065 863 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 864 [(set_attr "conds" "clob")
865 (set_attr "length" "8")]
866)
867
868(define_insn "*thumb_subdi3"
869 [(set (match_operand:DI 0 "register_operand" "=l")
870 (minus:DI (match_operand:DI 1 "register_operand" "0")
871 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 872 (clobber (reg:CC CC_REGNUM))]
cffb2a26 873 "TARGET_THUMB"
874 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875 [(set_attr "length" "4")]
876)
9c08d1fa 877
f7fbdd4a 878(define_insn "*subdi_di_zesidi"
cffb2a26 879 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
880 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 881 (zero_extend:DI
cffb2a26 882 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 883 (clobber (reg:CC CC_REGNUM))]
cffb2a26 884 "TARGET_ARM"
97499065 885 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
888)
9c08d1fa 889
f7fbdd4a 890(define_insn "*subdi_di_sesidi"
cffb2a26 891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
892 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 893 (sign_extend:DI
cffb2a26 894 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 895 (clobber (reg:CC CC_REGNUM))]
cffb2a26 896 "TARGET_ARM"
97499065 897 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 898 [(set_attr "conds" "clob")
899 (set_attr "length" "8")]
900)
9c08d1fa 901
f7fbdd4a 902(define_insn "*subdi_zesidi_di"
cffb2a26 903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 904 (minus:DI (zero_extend:DI
cffb2a26 905 (match_operand:SI 2 "s_register_operand" "r,r"))
906 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 907 (clobber (reg:CC CC_REGNUM))]
cffb2a26 908 "TARGET_ARM"
97499065 909 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
912)
9c08d1fa 913
f7fbdd4a 914(define_insn "*subdi_sesidi_di"
cffb2a26 915 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 916 (minus:DI (sign_extend:DI
cffb2a26 917 (match_operand:SI 2 "s_register_operand" "r,r"))
918 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 919 (clobber (reg:CC CC_REGNUM))]
cffb2a26 920 "TARGET_ARM"
97499065 921 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 922 [(set_attr "conds" "clob")
923 (set_attr "length" "8")]
924)
9c08d1fa 925
f7fbdd4a 926(define_insn "*subdi_zesidi_zesidi"
cffb2a26 927 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 928 (minus:DI (zero_extend:DI
cffb2a26 929 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 930 (zero_extend:DI
cffb2a26 931 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 932 (clobber (reg:CC CC_REGNUM))]
cffb2a26 933 "TARGET_ARM"
97499065 934 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
cffb2a26 935 [(set_attr "conds" "clob")
936 (set_attr "length" "8")]
937)
b11cae9e 938
87b22bf7 939(define_expand "subsi3"
cffb2a26 940 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 941 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 943 "TARGET_EITHER"
87b22bf7 944 "
945 if (GET_CODE (operands[1]) == CONST_INT)
946 {
cffb2a26 947 if (TARGET_ARM)
948 {
96f57e36 949 arm_split_constant (MINUS, SImode, NULL_RTX,
950 INTVAL (operands[1]), operands[0],
615caa51 951 operands[2], optimize && !no_new_pseudos);
cffb2a26 952 DONE;
953 }
954 else /* TARGET_THUMB */
955 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 956 }
cffb2a26 957 "
958)
87b22bf7 959
cffb2a26 960(define_insn "*thumb_subsi3_insn"
961 [(set (match_operand:SI 0 "register_operand" "=l")
962 (minus:SI (match_operand:SI 1 "register_operand" "l")
963 (match_operand:SI 2 "register_operand" "l")))]
964 "TARGET_THUMB"
965 "sub\\t%0, %1, %2"
966 [(set_attr "length" "2")]
967)
968
a0f94409 969(define_insn_and_split "*arm_subsi3_insn"
cffb2a26 970 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 971 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972 (match_operand:SI 2 "s_register_operand" "r,r")))]
cffb2a26 973 "TARGET_ARM"
e2348bcb 974 "@
87b22bf7 975 rsb%?\\t%0, %2, %1
976 #"
a0f94409 977 "TARGET_ARM
978 && GET_CODE (operands[1]) == CONST_INT
979 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 980 [(clobber (const_int 0))]
981 "
96f57e36 982 arm_split_constant (MINUS, SImode, curr_insn,
983 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 984 DONE;
cffb2a26 985 "
a0f94409 986 [(set_attr "length" "4,16")
987 (set_attr "predicable" "yes")]
988)
989
990(define_peephole2
991 [(match_scratch:SI 3 "r")
372575c7 992 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 993 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 994 (match_operand:SI 2 "arm_general_register_operand" "")))]
a0f94409 995 "TARGET_ARM
996 && !const_ok_for_arm (INTVAL (operands[1]))
997 && const_ok_for_arm (~INTVAL (operands[1]))"
998 [(set (match_dup 3) (match_dup 1))
999 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1000 ""
cffb2a26 1001)
b11cae9e 1002
f7fbdd4a 1003(define_insn "*subsi3_compare0"
bd5b4116 1004 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1005 (compare:CC_NOOV
1006 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1008 (const_int 0)))
9c08d1fa 1009 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1011 "TARGET_ARM"
e2348bcb 1012 "@
40dbec34 1013 sub%?s\\t%0, %1, %2
1014 rsb%?s\\t%0, %2, %1"
cffb2a26 1015 [(set_attr "conds" "set")]
1016)
9c08d1fa 1017
1018(define_insn "decscc"
cffb2a26 1019 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1020 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1021 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1022 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1023 "TARGET_ARM"
e2348bcb 1024 "@
215b30b3 1025 sub%d2\\t%0, %1, #1
1026 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1027 [(set_attr "conds" "use")
1028 (set_attr "length" "*,8")]
1029)
9c08d1fa 1030
604f3a0a 1031(define_expand "subsf3"
1032 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1033 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1036 "
a2cd141b 1037 if (TARGET_MAVERICK)
604f3a0a 1038 {
1039 if (!cirrus_fp_register (operands[1], SFmode))
1040 operands[1] = force_reg (SFmode, operands[1]);
1041 if (!cirrus_fp_register (operands[2], SFmode))
1042 operands[2] = force_reg (SFmode, operands[2]);
1043 }
1044")
1045
604f3a0a 1046(define_expand "subdf3"
1047 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1048 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1051 "
a2cd141b 1052 if (TARGET_MAVERICK)
604f3a0a 1053 {
1054 if (!cirrus_fp_register (operands[1], DFmode))
1055 operands[1] = force_reg (DFmode, operands[1]);
1056 if (!cirrus_fp_register (operands[2], DFmode))
1057 operands[2] = force_reg (DFmode, operands[2]);
1058 }
1059")
1060
b11cae9e 1061\f
1062;; Multiplication insns
1063
cffb2a26 1064(define_expand "mulsi3"
1065 [(set (match_operand:SI 0 "s_register_operand" "")
1066 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067 (match_operand:SI 1 "s_register_operand" "")))]
1068 "TARGET_EITHER"
1069 ""
1070)
1071
9c08d1fa 1072;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1073(define_insn "*arm_mulsi3"
1074 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1075 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
cffb2a26 1077 "TARGET_ARM"
f7fbdd4a 1078 "mul%?\\t%0, %2, %1"
a2cd141b 1079 [(set_attr "insn" "mul")
0d66636f 1080 (set_attr "predicable" "yes")]
cffb2a26 1081)
1082
215b30b3 1083; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1084; 1 and 2; are the same, because reload will make operand 0 match
1085; operand 1 without realizing that this conflicts with operand 2. We fix
1086; this by adding another alternative to match this case, and then `reload'
1087; it ourselves. This alternative must come first.
cffb2a26 1088(define_insn "*thumb_mulsi3"
1089 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1090 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091 (match_operand:SI 2 "register_operand" "l,l,l")))]
1092 "TARGET_THUMB"
1093 "*
1094 if (which_alternative < 2)
20c4e896 1095 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1096 else
20c4e896 1097 return \"mul\\t%0, %2\";
cffb2a26 1098 "
1099 [(set_attr "length" "4,4,2")
a2cd141b 1100 (set_attr "insn" "mul")]
cffb2a26 1101)
b11cae9e 1102
f7fbdd4a 1103(define_insn "*mulsi3_compare0"
bd5b4116 1104 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1105 (compare:CC_NOOV (mult:SI
1106 (match_operand:SI 2 "s_register_operand" "r,r")
1107 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1108 (const_int 0)))
1109 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110 (mult:SI (match_dup 2) (match_dup 1)))]
e8a4aa75 1111 "TARGET_ARM"
40dbec34 1112 "mul%?s\\t%0, %2, %1"
cffb2a26 1113 [(set_attr "conds" "set")
a2cd141b 1114 (set_attr "insn" "muls")]
cffb2a26 1115)
9c08d1fa 1116
f7fbdd4a 1117(define_insn "*mulsi_compare0_scratch"
bd5b4116 1118 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1119 (compare:CC_NOOV (mult:SI
1120 (match_operand:SI 2 "s_register_operand" "r,r")
1121 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1122 (const_int 0)))
1123 (clobber (match_scratch:SI 0 "=&r,&r"))]
e8a4aa75 1124 "TARGET_ARM"
40dbec34 1125 "mul%?s\\t%0, %2, %1"
cffb2a26 1126 [(set_attr "conds" "set")
a2cd141b 1127 (set_attr "insn" "muls")]
cffb2a26 1128)
9c08d1fa 1129
b11cae9e 1130;; Unnamed templates to match MLA instruction.
1131
f7fbdd4a 1132(define_insn "*mulsi3addsi"
9c08d1fa 1133 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1134 (plus:SI
9c08d1fa 1135 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
cffb2a26 1138 "TARGET_ARM"
f7fbdd4a 1139 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1140 [(set_attr "insn" "mla")
0d66636f 1141 (set_attr "predicable" "yes")]
1142)
b11cae9e 1143
f7fbdd4a 1144(define_insn "*mulsi3addsi_compare0"
bd5b4116 1145 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1146 (compare:CC_NOOV
1147 (plus:SI (mult:SI
1148 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1151 (const_int 0)))
9c08d1fa 1152 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1154 (match_dup 3)))]
e8a4aa75 1155 "TARGET_ARM"
40dbec34 1156 "mla%?s\\t%0, %2, %1, %3"
0d66636f 1157 [(set_attr "conds" "set")
a2cd141b 1158 (set_attr "insn" "mlas")]
0d66636f 1159)
9c08d1fa 1160
f7fbdd4a 1161(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1162 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1163 (compare:CC_NOOV
1164 (plus:SI (mult:SI
1165 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1168 (const_int 0)))
9c08d1fa 1169 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
e8a4aa75 1170 "TARGET_ARM"
40dbec34 1171 "mla%?s\\t%0, %2, %1, %3"
cffb2a26 1172 [(set_attr "conds" "set")
a2cd141b 1173 (set_attr "insn" "mlas")]
cffb2a26 1174)
f7fbdd4a 1175
efee20da 1176;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1177
1178(define_insn "*mulsidi3adddi"
fe8dbf85 1179 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1180 (plus:DI
215b30b3 1181 (mult:DI
fe8dbf85 1182 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1185 "TARGET_ARM && arm_arch3m"
fe8dbf85 1186 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1187 [(set_attr "insn" "smlal")
0d66636f 1188 (set_attr "predicable" "yes")]
1189)
82b85d08 1190
f7fbdd4a 1191(define_insn "mulsidi3"
1192 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1193 (mult:DI
1194 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1196 "TARGET_ARM && arm_arch3m"
97499065 1197 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1198 [(set_attr "insn" "smull")
0d66636f 1199 (set_attr "predicable" "yes")]
1200)
f7fbdd4a 1201
1202(define_insn "umulsidi3"
1203 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1204 (mult:DI
1205 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1207 "TARGET_ARM && arm_arch3m"
97499065 1208 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1209 [(set_attr "insn" "umull")
0d66636f 1210 (set_attr "predicable" "yes")]
1211)
b11cae9e 1212
efee20da 1213;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1214
1215(define_insn "*umulsidi3adddi"
8ead09f9 1216 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1217 (plus:DI
215b30b3 1218 (mult:DI
fe8dbf85 1219 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1222 "TARGET_ARM && arm_arch3m"
fe8dbf85 1223 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1224 [(set_attr "insn" "umlal")
0d66636f 1225 (set_attr "predicable" "yes")]
1226)
82b85d08 1227
f082f1c4 1228(define_insn "smulsi3_highpart"
1229 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230 (truncate:SI
1231 (lshiftrt:DI
215b30b3 1232 (mult:DI
1233 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1235 (const_int 32))))
1236 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1237 "TARGET_ARM && arm_arch3m"
f082f1c4 1238 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1239 [(set_attr "insn" "smull")
0d66636f 1240 (set_attr "predicable" "yes")]
cffb2a26 1241)
f082f1c4 1242
1243(define_insn "umulsi3_highpart"
1244 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1245 (truncate:SI
1246 (lshiftrt:DI
215b30b3 1247 (mult:DI
1248 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1250 (const_int 32))))
1251 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1252 "TARGET_ARM && arm_arch3m"
f082f1c4 1253 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1254 [(set_attr "insn" "umull")
0d66636f 1255 (set_attr "predicable" "yes")]
cffb2a26 1256)
f082f1c4 1257
331beb1a 1258(define_insn "mulhisi3"
1259 [(set (match_operand:SI 0 "s_register_operand" "=r")
1260 (mult:SI (sign_extend:SI
1261 (match_operand:HI 1 "s_register_operand" "%r"))
1262 (sign_extend:SI
1263 (match_operand:HI 2 "s_register_operand" "r"))))]
fec538d9 1264 "TARGET_ARM && arm_arch5e"
61a2d04c 1265 "smulbb%?\\t%0, %1, %2"
a2cd141b 1266 [(set_attr "insn" "smulxy")
fec538d9 1267 (set_attr "predicable" "yes")]
1268)
1269
1270(define_insn "*mulhisi3tb"
1271 [(set (match_operand:SI 0 "s_register_operand" "=r")
1272 (mult:SI (ashiftrt:SI
1273 (match_operand:SI 1 "s_register_operand" "r")
1274 (const_int 16))
1275 (sign_extend:SI
1276 (match_operand:HI 2 "s_register_operand" "r"))))]
1277 "TARGET_ARM && arm_arch5e"
1278 "smultb%?\\t%0, %1, %2"
a2cd141b 1279 [(set_attr "insn" "smulxy")
fec538d9 1280 (set_attr "predicable" "yes")]
1281)
1282
1283(define_insn "*mulhisi3bt"
1284 [(set (match_operand:SI 0 "s_register_operand" "=r")
1285 (mult:SI (sign_extend:SI
1286 (match_operand:HI 1 "s_register_operand" "r"))
1287 (ashiftrt:SI
1288 (match_operand:SI 2 "s_register_operand" "r")
1289 (const_int 16))))]
1290 "TARGET_ARM && arm_arch5e"
1291 "smulbt%?\\t%0, %1, %2"
a2cd141b 1292 [(set_attr "insn" "smulxy")
fec538d9 1293 (set_attr "predicable" "yes")]
1294)
1295
1296(define_insn "*mulhisi3tt"
1297 [(set (match_operand:SI 0 "s_register_operand" "=r")
1298 (mult:SI (ashiftrt:SI
1299 (match_operand:SI 1 "s_register_operand" "r")
1300 (const_int 16))
1301 (ashiftrt:SI
1302 (match_operand:SI 2 "s_register_operand" "r")
1303 (const_int 16))))]
1304 "TARGET_ARM && arm_arch5e"
1305 "smultt%?\\t%0, %1, %2"
a2cd141b 1306 [(set_attr "insn" "smulxy")
fec538d9 1307 (set_attr "predicable" "yes")]
331beb1a 1308)
1309
1310(define_insn "*mulhisi3addsi"
1311 [(set (match_operand:SI 0 "s_register_operand" "=r")
1312 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313 (mult:SI (sign_extend:SI
1314 (match_operand:HI 2 "s_register_operand" "%r"))
1315 (sign_extend:SI
1316 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1317 "TARGET_ARM && arm_arch5e"
61a2d04c 1318 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1319 [(set_attr "insn" "smlaxy")
fec538d9 1320 (set_attr "predicable" "yes")]
331beb1a 1321)
1322
1323(define_insn "*mulhidi3adddi"
1324 [(set (match_operand:DI 0 "s_register_operand" "=r")
1325 (plus:DI
1326 (match_operand:DI 1 "s_register_operand" "0")
1327 (mult:DI (sign_extend:DI
1328 (match_operand:HI 2 "s_register_operand" "%r"))
1329 (sign_extend:DI
1330 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1331 "TARGET_ARM && arm_arch5e"
331beb1a 1332 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1333 [(set_attr "insn" "smlalxy")
fec538d9 1334 (set_attr "predicable" "yes")])
331beb1a 1335
604f3a0a 1336(define_expand "mulsf3"
1337 [(set (match_operand:SF 0 "s_register_operand" "")
1338 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1339 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1341 "
a2cd141b 1342 if (TARGET_MAVERICK
604f3a0a 1343 && !cirrus_fp_register (operands[2], SFmode))
1344 operands[2] = force_reg (SFmode, operands[2]);
1345")
1346
604f3a0a 1347(define_expand "muldf3"
1348 [(set (match_operand:DF 0 "s_register_operand" "")
1349 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1350 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1352 "
a2cd141b 1353 if (TARGET_MAVERICK
604f3a0a 1354 && !cirrus_fp_register (operands[2], DFmode))
1355 operands[2] = force_reg (DFmode, operands[2]);
1356")
b11cae9e 1357\f
1358;; Division insns
1359
7db9af5d 1360(define_expand "divsf3"
1361 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1362 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1365 "")
9c08d1fa 1366
7db9af5d 1367(define_expand "divdf3"
1368 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1369 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1372 "")
b11cae9e 1373\f
1374;; Modulo insns
1375
7db9af5d 1376(define_expand "modsf3"
1377 [(set (match_operand:SF 0 "s_register_operand" "")
1378 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1379 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1381 "")
9c08d1fa 1382
7db9af5d 1383(define_expand "moddf3"
1384 [(set (match_operand:DF 0 "s_register_operand" "")
1385 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1386 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1388 "")
b11cae9e 1389\f
1390;; Boolean and,ior,xor insns
1391
f6ebffac 1392;; Split up double word logical operations
1393
1394;; Split up simple DImode logical operations. Simply perform the logical
1395;; operation on the upper and lower halves of the registers.
1396(define_split
1397 [(set (match_operand:DI 0 "s_register_operand" "")
1398 (match_operator:DI 6 "logical_binary_operator"
1399 [(match_operand:DI 1 "s_register_operand" "")
1400 (match_operand:DI 2 "s_register_operand" "")]))]
755eb2b4 1401 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1402 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1404 "
215b30b3 1405 {
1406 operands[3] = gen_highpart (SImode, operands[0]);
1407 operands[0] = gen_lowpart (SImode, operands[0]);
1408 operands[4] = gen_highpart (SImode, operands[1]);
1409 operands[1] = gen_lowpart (SImode, operands[1]);
1410 operands[5] = gen_highpart (SImode, operands[2]);
1411 operands[2] = gen_lowpart (SImode, operands[2]);
1412 }"
1413)
f6ebffac 1414
f6ebffac 1415(define_split
1416 [(set (match_operand:DI 0 "s_register_operand" "")
1417 (match_operator:DI 6 "logical_binary_operator"
1418 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419 (match_operand:DI 1 "s_register_operand" "")]))]
cffb2a26 1420 "TARGET_ARM && reload_completed"
f6ebffac 1421 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422 (set (match_dup 3) (match_op_dup:SI 6
1423 [(ashiftrt:SI (match_dup 2) (const_int 31))
1424 (match_dup 4)]))]
1425 "
215b30b3 1426 {
1427 operands[3] = gen_highpart (SImode, operands[0]);
1428 operands[0] = gen_lowpart (SImode, operands[0]);
1429 operands[4] = gen_highpart (SImode, operands[1]);
1430 operands[1] = gen_lowpart (SImode, operands[1]);
1431 operands[5] = gen_highpart (SImode, operands[2]);
1432 operands[2] = gen_lowpart (SImode, operands[2]);
1433 }"
1434)
f6ebffac 1435
f6ebffac 1436;; The zero extend of operand 2 means we can just copy the high part of
1437;; operand1 into operand0.
1438(define_split
1439 [(set (match_operand:DI 0 "s_register_operand" "")
1440 (ior:DI
1441 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1443 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1444 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445 (set (match_dup 3) (match_dup 4))]
1446 "
215b30b3 1447 {
1448 operands[4] = gen_highpart (SImode, operands[1]);
1449 operands[3] = gen_highpart (SImode, operands[0]);
1450 operands[0] = gen_lowpart (SImode, operands[0]);
1451 operands[1] = gen_lowpart (SImode, operands[1]);
1452 }"
1453)
f6ebffac 1454
1455;; The zero extend of operand 2 means we can just copy the high part of
1456;; operand1 into operand0.
1457(define_split
1458 [(set (match_operand:DI 0 "s_register_operand" "")
1459 (xor:DI
1460 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1462 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1463 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464 (set (match_dup 3) (match_dup 4))]
1465 "
215b30b3 1466 {
1467 operands[4] = gen_highpart (SImode, operands[1]);
1468 operands[3] = gen_highpart (SImode, operands[0]);
1469 operands[0] = gen_lowpart (SImode, operands[0]);
1470 operands[1] = gen_lowpart (SImode, operands[1]);
1471 }"
1472)
f6ebffac 1473
b11cae9e 1474(define_insn "anddi3"
cffb2a26 1475 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1476 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1477 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 1478 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 1479 "#"
215b30b3 1480 [(set_attr "length" "8")]
1481)
b11cae9e 1482
a0f94409 1483(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1484 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485 (and:DI (zero_extend:DI
1486 (match_operand:SI 2 "s_register_operand" "r,r"))
1487 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 1488 "TARGET_ARM"
f6ebffac 1489 "#"
a0f94409 1490 "TARGET_ARM && reload_completed"
1491 ; The zero extend of operand 2 clears the high word of the output
1492 ; operand.
1493 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494 (set (match_dup 3) (const_int 0))]
1495 "
1496 {
1497 operands[3] = gen_highpart (SImode, operands[0]);
1498 operands[0] = gen_lowpart (SImode, operands[0]);
1499 operands[1] = gen_lowpart (SImode, operands[1]);
1500 }"
215b30b3 1501 [(set_attr "length" "8")]
1502)
b11cae9e 1503
f7fbdd4a 1504(define_insn "*anddi_sesdi_di"
cffb2a26 1505 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1506 (and:DI (sign_extend:DI
1507 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1508 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1509 "TARGET_ARM"
f6ebffac 1510 "#"
cffb2a26 1511 [(set_attr "length" "8")]
1512)
b11cae9e 1513
87b22bf7 1514(define_expand "andsi3"
cffb2a26 1515 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1516 (and:SI (match_operand:SI 1 "s_register_operand" "")
1517 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1518 "TARGET_EITHER"
87b22bf7 1519 "
cffb2a26 1520 if (TARGET_ARM)
87b22bf7 1521 {
cffb2a26 1522 if (GET_CODE (operands[2]) == CONST_INT)
1523 {
96f57e36 1524 arm_split_constant (AND, SImode, NULL_RTX,
1525 INTVAL (operands[2]), operands[0],
615caa51 1526 operands[1], optimize && !no_new_pseudos);
1527
cffb2a26 1528 DONE;
1529 }
87b22bf7 1530 }
cffb2a26 1531 else /* TARGET_THUMB */
1532 {
1533 if (GET_CODE (operands[2]) != CONST_INT)
1534 operands[2] = force_reg (SImode, operands[2]);
1535 else
1536 {
1537 int i;
1538
215b30b3 1539 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1540 {
215b30b3 1541 operands[2] = force_reg (SImode,
1542 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1543
1544 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1545
1546 DONE;
1547 }
87b22bf7 1548
cffb2a26 1549 for (i = 9; i <= 31; i++)
1550 {
1551 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1552 {
1553 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1554 const0_rtx));
1555 DONE;
1556 }
215b30b3 1557 else if ((((HOST_WIDE_INT) 1) << i) - 1
1558 == ~INTVAL (operands[2]))
cffb2a26 1559 {
1560 rtx shift = GEN_INT (i);
1561 rtx reg = gen_reg_rtx (SImode);
1562
1563 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1565
1566 DONE;
1567 }
1568 }
1569
1570 operands[2] = force_reg (SImode, operands[2]);
1571 }
215b30b3 1572 }
1573 "
cffb2a26 1574)
1575
a0f94409 1576(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1577 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1578 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
cffb2a26 1580 "TARGET_ARM"
5565501b 1581 "@
1582 and%?\\t%0, %1, %2
87b22bf7 1583 bic%?\\t%0, %1, #%B2
1584 #"
a0f94409 1585 "TARGET_ARM
1586 && GET_CODE (operands[2]) == CONST_INT
1587 && !(const_ok_for_arm (INTVAL (operands[2]))
1588 || const_ok_for_arm (~INTVAL (operands[2])))"
1589 [(clobber (const_int 0))]
1590 "
96f57e36 1591 arm_split_constant (AND, SImode, curr_insn,
1592 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1593 DONE;
1594 "
0d66636f 1595 [(set_attr "length" "4,4,16")
1596 (set_attr "predicable" "yes")]
cffb2a26 1597)
1598
1599(define_insn "*thumb_andsi3_insn"
1600 [(set (match_operand:SI 0 "register_operand" "=l")
1601 (and:SI (match_operand:SI 1 "register_operand" "%0")
1602 (match_operand:SI 2 "register_operand" "l")))]
1603 "TARGET_THUMB"
1604 "and\\t%0, %0, %2"
1605 [(set_attr "length" "2")]
1606)
87b22bf7 1607
f7fbdd4a 1608(define_insn "*andsi3_compare0"
bd5b4116 1609 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1610 (compare:CC_NOOV
1611 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1613 (const_int 0)))
cffb2a26 1614 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1615 (and:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1616 "TARGET_ARM"
5565501b 1617 "@
1618 and%?s\\t%0, %1, %2
1619 bic%?s\\t%0, %1, #%B2"
cffb2a26 1620 [(set_attr "conds" "set")]
1621)
9c08d1fa 1622
f7fbdd4a 1623(define_insn "*andsi3_compare0_scratch"
bd5b4116 1624 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1625 (compare:CC_NOOV
1626 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1628 (const_int 0)))
dd193d7c 1629 (clobber (match_scratch:SI 2 "=X,r"))]
cffb2a26 1630 "TARGET_ARM"
5565501b 1631 "@
1632 tst%?\\t%0, %1
dd193d7c 1633 bic%?s\\t%2, %0, #%B1"
0d66636f 1634 [(set_attr "conds" "set")]
1635)
9c08d1fa 1636
f7fbdd4a 1637(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 1638 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1639 (compare:CC_NOOV (zero_extract:SI
1640 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 1641 (match_operand 1 "const_int_operand" "n")
1642 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 1643 (const_int 0)))]
cffb2a26 1644 "TARGET_ARM
1645 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646 && INTVAL (operands[1]) > 0
1647 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 1649 "*
5c49a439 1650 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651 << INTVAL (operands[2]));
40dbec34 1652 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 1653 return \"\";
0d66636f 1654 "
1655 [(set_attr "conds" "set")]
1656)
9c08d1fa 1657
f4462328 1658(define_insn_and_split "*ne_zeroextractsi"
c4034607 1659 [(set (match_operand:SI 0 "s_register_operand" "=r")
1660 (ne:SI (zero_extract:SI
1661 (match_operand:SI 1 "s_register_operand" "r")
1662 (match_operand:SI 2 "const_int_operand" "n")
1663 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 1664 (const_int 0)))
1665 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1666 "TARGET_ARM
1667 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668 && INTVAL (operands[2]) > 0
1669 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 1671 "#"
1672 "TARGET_ARM
1673 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674 && INTVAL (operands[2]) > 0
1675 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1679 (const_int 0)))
1680 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1681 (set (match_dup 0)
1682 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683 (match_dup 0) (const_int 1)))]
1684 "
1685 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686 << INTVAL (operands[3]));
1687 "
1688 [(set_attr "conds" "clob")
1689 (set_attr "length" "8")]
1690)
1691
1692(define_insn_and_split "*ne_zeroextractsi_shifted"
1693 [(set (match_operand:SI 0 "s_register_operand" "=r")
1694 (ne:SI (zero_extract:SI
1695 (match_operand:SI 1 "s_register_operand" "r")
1696 (match_operand:SI 2 "const_int_operand" "n")
1697 (const_int 0))
1698 (const_int 0)))
1699 (clobber (reg:CC CC_REGNUM))]
1700 "TARGET_ARM"
1701 "#"
1702 "TARGET_ARM"
1703 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1705 (const_int 0)))
1706 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1707 (set (match_dup 0)
1708 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709 (match_dup 0) (const_int 1)))]
1710 "
1711 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1712 "
1713 [(set_attr "conds" "clob")
1714 (set_attr "length" "8")]
1715)
1716
1717(define_insn_and_split "*ite_ne_zeroextractsi"
1718 [(set (match_operand:SI 0 "s_register_operand" "=r")
1719 (if_then_else:SI (ne (zero_extract:SI
1720 (match_operand:SI 1 "s_register_operand" "r")
1721 (match_operand:SI 2 "const_int_operand" "n")
1722 (match_operand:SI 3 "const_int_operand" "n"))
1723 (const_int 0))
1724 (match_operand:SI 4 "arm_not_operand" "rIK")
1725 (const_int 0)))
1726 (clobber (reg:CC CC_REGNUM))]
1727 "TARGET_ARM
1728 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729 && INTVAL (operands[2]) > 0
1730 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1731 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1733 "#"
1734 "TARGET_ARM
1735 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736 && INTVAL (operands[2]) > 0
1737 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1738 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1740 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1742 (const_int 0)))
1743 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1744 (set (match_dup 0)
1745 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746 (match_dup 0) (match_dup 4)))]
1747 "
c4034607 1748 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 1749 << INTVAL (operands[3]));
1750 "
1751 [(set_attr "conds" "clob")
1752 (set_attr "length" "8")]
1753)
1754
1755(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756 [(set (match_operand:SI 0 "s_register_operand" "=r")
1757 (if_then_else:SI (ne (zero_extract:SI
1758 (match_operand:SI 1 "s_register_operand" "r")
1759 (match_operand:SI 2 "const_int_operand" "n")
1760 (const_int 0))
1761 (const_int 0))
1762 (match_operand:SI 3 "arm_not_operand" "rIK")
1763 (const_int 0)))
1764 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 1765 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1766 "#"
f8d7bf2f 1767 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1768 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1770 (const_int 0)))
1771 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1772 (set (match_dup 0)
1773 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774 (match_dup 0) (match_dup 3)))]
1775 "
1776 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 1777 "
1778 [(set_attr "conds" "clob")
215b30b3 1779 (set_attr "length" "8")]
1780)
9c08d1fa 1781
58d6528b 1782(define_split
1783 [(set (match_operand:SI 0 "s_register_operand" "")
1784 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785 (match_operand:SI 2 "const_int_operand" "")
1786 (match_operand:SI 3 "const_int_operand" "")))
1787 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1788 "TARGET_THUMB"
1789 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1791 "{
1792 HOST_WIDE_INT temp = INTVAL (operands[2]);
1793
1794 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795 operands[3] = GEN_INT (32 - temp);
1796 }"
1797)
1798
d7863cfe 1799(define_split
1800 [(set (match_operand:SI 0 "s_register_operand" "")
1801 (match_operator:SI 1 "shiftable_operator"
1802 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803 (match_operand:SI 3 "const_int_operand" "")
1804 (match_operand:SI 4 "const_int_operand" ""))
1805 (match_operand:SI 5 "s_register_operand" "")]))
1806 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1807 "TARGET_ARM"
1808 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1809 (set (match_dup 0)
1810 (match_op_dup 1
1811 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1812 (match_dup 5)]))]
1813 "{
1814 HOST_WIDE_INT temp = INTVAL (operands[3]);
1815
1816 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817 operands[4] = GEN_INT (32 - temp);
1818 }"
1819)
1820
58d6528b 1821(define_split
1822 [(set (match_operand:SI 0 "s_register_operand" "")
1823 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824 (match_operand:SI 2 "const_int_operand" "")
1825 (match_operand:SI 3 "const_int_operand" "")))]
1826 "TARGET_THUMB"
1827 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1829 "{
1830 HOST_WIDE_INT temp = INTVAL (operands[2]);
1831
1832 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833 operands[3] = GEN_INT (32 - temp);
1834 }"
1835)
1836
d7863cfe 1837(define_split
1838 [(set (match_operand:SI 0 "s_register_operand" "")
1839 (match_operator:SI 1 "shiftable_operator"
1840 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841 (match_operand:SI 3 "const_int_operand" "")
1842 (match_operand:SI 4 "const_int_operand" ""))
1843 (match_operand:SI 5 "s_register_operand" "")]))
1844 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1845 "TARGET_ARM"
1846 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1847 (set (match_dup 0)
1848 (match_op_dup 1
1849 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1850 (match_dup 5)]))]
1851 "{
1852 HOST_WIDE_INT temp = INTVAL (operands[3]);
1853
1854 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855 operands[4] = GEN_INT (32 - temp);
1856 }"
1857)
1858
a42059fd 1859;;; ??? This pattern is bogus. If operand3 has bits outside the range
1860;;; represented by the bitfield, then this will produce incorrect results.
1861;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 1862;;; which have a real bit-field insert instruction, the truncation happens
1863;;; in the bit-field insert instruction itself. Since arm does not have a
1864;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 1865;;; the value before we insert. This loses some of the advantage of having
1866;;; this insv pattern, so this pattern needs to be reevalutated.
1867
8a18b90c 1868(define_expand "insv"
1869 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870 (match_operand:SI 1 "general_operand" "")
1871 (match_operand:SI 2 "general_operand" ""))
19335226 1872 (match_operand:SI 3 "reg_or_int_operand" ""))]
cffb2a26 1873 "TARGET_ARM"
8a18b90c 1874 "
215b30b3 1875 {
1876 int start_bit = INTVAL (operands[2]);
1877 int width = INTVAL (operands[1]);
1878 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879 rtx target, subtarget;
1880
1881 target = operands[0];
1882 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1883 subreg as the final target. */
1884 if (GET_CODE (target) == SUBREG)
1885 {
1886 subtarget = gen_reg_rtx (SImode);
1887 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888 < GET_MODE_SIZE (SImode))
1889 target = SUBREG_REG (target);
1890 }
1891 else
1892 subtarget = target;
8a18b90c 1893
215b30b3 1894 if (GET_CODE (operands[3]) == CONST_INT)
1895 {
1896 /* Since we are inserting a known constant, we may be able to
1897 reduce the number of bits that we have to clear so that
1898 the mask becomes simple. */
1899 /* ??? This code does not check to see if the new mask is actually
1900 simpler. It may not be. */
1901 rtx op1 = gen_reg_rtx (SImode);
1902 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1903 start of this pattern. */
1904 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1906
c5b3a71b 1907 emit_insn (gen_andsi3 (op1, operands[0],
1908 gen_int_mode (~mask2, SImode)));
215b30b3 1909 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 1910 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 1911 }
1912 else if (start_bit == 0
1913 && !(const_ok_for_arm (mask)
1914 || const_ok_for_arm (~mask)))
1915 {
1916 /* A Trick, since we are setting the bottom bits in the word,
1917 we can shift operand[3] up, operand[0] down, OR them together
1918 and rotate the result back again. This takes 3 insns, and
5910bb95 1919 the third might be mergeable into another op. */
215b30b3 1920 /* The shift up copes with the possibility that operand[3] is
1921 wider than the bitfield. */
1922 rtx op0 = gen_reg_rtx (SImode);
1923 rtx op1 = gen_reg_rtx (SImode);
1924
1925 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1927 emit_insn (gen_iorsi3 (op1, op1, op0));
1928 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1929 }
1930 else if ((width + start_bit == 32)
1931 && !(const_ok_for_arm (mask)
1932 || const_ok_for_arm (~mask)))
1933 {
1934 /* Similar trick, but slightly less efficient. */
8a18b90c 1935
215b30b3 1936 rtx op0 = gen_reg_rtx (SImode);
1937 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 1938
215b30b3 1939 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1943 }
1944 else
1945 {
c5b3a71b 1946 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 1947 rtx op1 = gen_reg_rtx (SImode);
1948 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 1949
215b30b3 1950 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1951 {
1952 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1953
215b30b3 1954 emit_insn (gen_movsi (tmp, op0));
1955 op0 = tmp;
1956 }
8a18b90c 1957
215b30b3 1958 /* Mask out any bits in operand[3] that are not needed. */
1959 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 1960
215b30b3 1961 if (GET_CODE (op0) == CONST_INT
1962 && (const_ok_for_arm (mask << start_bit)
1963 || const_ok_for_arm (~(mask << start_bit))))
1964 {
c5b3a71b 1965 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 1966 emit_insn (gen_andsi3 (op2, operands[0], op0));
1967 }
1968 else
1969 {
1970 if (GET_CODE (op0) == CONST_INT)
1971 {
1972 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1973
215b30b3 1974 emit_insn (gen_movsi (tmp, op0));
1975 op0 = tmp;
1976 }
1977
1978 if (start_bit != 0)
1979 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 1980
215b30b3 1981 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1982 }
8a18b90c 1983
215b30b3 1984 if (start_bit != 0)
1985 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 1986
215b30b3 1987 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988 }
f082f1c4 1989
215b30b3 1990 if (subtarget != target)
1991 {
1992 /* If TARGET is still a SUBREG, then it must be wider than a word,
1993 so we must be careful only to set the subword we were asked to. */
1994 if (GET_CODE (target) == SUBREG)
1995 emit_move_insn (target, subtarget);
1996 else
1997 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1998 }
8a18b90c 1999
215b30b3 2000 DONE;
2001 }"
2002)
8a18b90c 2003
215b30b3 2004; constants for op 2 will never be given to these patterns.
a0f94409 2005(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2006 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2007 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008 (match_operand:DI 2 "s_register_operand" "0,r")))]
cffb2a26 2009 "TARGET_ARM"
f6ebffac 2010 "#"
755eb2b4 2011 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2012 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014 "
2015 {
2016 operands[3] = gen_highpart (SImode, operands[0]);
2017 operands[0] = gen_lowpart (SImode, operands[0]);
2018 operands[4] = gen_highpart (SImode, operands[1]);
2019 operands[1] = gen_lowpart (SImode, operands[1]);
2020 operands[5] = gen_highpart (SImode, operands[2]);
2021 operands[2] = gen_lowpart (SImode, operands[2]);
2022 }"
0d66636f 2023 [(set_attr "length" "8")
2024 (set_attr "predicable" "yes")]
2025)
9c08d1fa 2026
a0f94409 2027(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2028 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029 (and:DI (not:DI (zero_extend:DI
2030 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2031 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2032 "TARGET_ARM"
e2348bcb 2033 "@
97499065 2034 bic%?\\t%Q0, %Q1, %2
f6ebffac 2035 #"
a0f94409 2036 ; (not (zero_extend ...)) allows us to just copy the high word from
2037 ; operand1 to operand0.
2038 "TARGET_ARM
2039 && reload_completed
2040 && operands[0] != operands[1]"
5a097f7d 2041 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2042 (set (match_dup 3) (match_dup 4))]
2043 "
2044 {
2045 operands[3] = gen_highpart (SImode, operands[0]);
2046 operands[0] = gen_lowpart (SImode, operands[0]);
2047 operands[4] = gen_highpart (SImode, operands[1]);
2048 operands[1] = gen_lowpart (SImode, operands[1]);
2049 }"
0d66636f 2050 [(set_attr "length" "4,8")
2051 (set_attr "predicable" "yes")]
2052)
9c08d1fa 2053
a0f94409 2054(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2055 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056 (and:DI (not:DI (sign_extend:DI
2057 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2058 (match_operand:DI 1 "s_register_operand" "0,r")))]
cffb2a26 2059 "TARGET_ARM"
f6ebffac 2060 "#"
a0f94409 2061 "TARGET_ARM && reload_completed"
5a097f7d 2062 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2063 (set (match_dup 3) (and:SI (not:SI
2064 (ashiftrt:SI (match_dup 2) (const_int 31)))
2065 (match_dup 4)))]
2066 "
2067 {
2068 operands[3] = gen_highpart (SImode, operands[0]);
2069 operands[0] = gen_lowpart (SImode, operands[0]);
2070 operands[4] = gen_highpart (SImode, operands[1]);
2071 operands[1] = gen_lowpart (SImode, operands[1]);
2072 }"
0d66636f 2073 [(set_attr "length" "8")
2074 (set_attr "predicable" "yes")]
2075)
9c08d1fa 2076
8a18b90c 2077(define_insn "andsi_notsi_si"
9c08d1fa 2078 [(set (match_operand:SI 0 "s_register_operand" "=r")
2079 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2081 "TARGET_ARM"
0d66636f 2082 "bic%?\\t%0, %1, %2"
2083 [(set_attr "predicable" "yes")]
2084)
b11cae9e 2085
cffb2a26 2086(define_insn "bicsi3"
2087 [(set (match_operand:SI 0 "register_operand" "=l")
2088 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089 (match_operand:SI 2 "register_operand" "0")))]
2090 "TARGET_THUMB"
2091 "bic\\t%0, %0, %1"
2092 [(set_attr "length" "2")]
2093)
2094
8a18b90c 2095(define_insn "andsi_not_shiftsi_si"
a2cd141b 2096 [(set (match_operand:SI 0 "s_register_operand" "=r")
2097 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098 [(match_operand:SI 2 "s_register_operand" "r")
2099 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2101 "TARGET_ARM"
6c4c2133 2102 "bic%?\\t%0, %1, %2%S4"
344495ea 2103 [(set_attr "predicable" "yes")
331beb1a 2104 (set_attr "shift" "2")
a2cd141b 2105 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106 (const_string "alu_shift")
2107 (const_string "alu_shift_reg")))]
6c4c2133 2108)
8a18b90c 2109
f7fbdd4a 2110(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2111 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2112 (compare:CC_NOOV
2113 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114 (match_operand:SI 1 "s_register_operand" "r"))
2115 (const_int 0)))
9c08d1fa 2116 (set (match_operand:SI 0 "s_register_operand" "=r")
2117 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
cffb2a26 2118 "TARGET_ARM"
40dbec34 2119 "bic%?s\\t%0, %1, %2"
0d66636f 2120 [(set_attr "conds" "set")]
2121)
9c08d1fa 2122
f7fbdd4a 2123(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2124 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2125 (compare:CC_NOOV
2126 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127 (match_operand:SI 1 "s_register_operand" "r"))
2128 (const_int 0)))
9c08d1fa 2129 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2130 "TARGET_ARM"
40dbec34 2131 "bic%?s\\t%0, %1, %2"
0d66636f 2132 [(set_attr "conds" "set")]
2133)
9c08d1fa 2134
2135(define_insn "iordi3"
cffb2a26 2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2138 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2139 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 2140 "#"
0d66636f 2141 [(set_attr "length" "8")
2142 (set_attr "predicable" "yes")]
cffb2a26 2143)
9c08d1fa 2144
f7fbdd4a 2145(define_insn "*iordi_zesidi_di"
9c08d1fa 2146 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147 (ior:DI (zero_extend:DI
2148 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2149 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2150 "TARGET_ARM"
e2348bcb 2151 "@
97499065 2152 orr%?\\t%Q0, %Q1, %2
f6ebffac 2153 #"
0d66636f 2154 [(set_attr "length" "4,8")
2155 (set_attr "predicable" "yes")]
cffb2a26 2156)
9c08d1fa 2157
f7fbdd4a 2158(define_insn "*iordi_sesidi_di"
9c08d1fa 2159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160 (ior:DI (sign_extend:DI
2161 (match_operand:SI 2 "s_register_operand" "r,r"))
2162 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2163 "TARGET_ARM"
f6ebffac 2164 "#"
0d66636f 2165 [(set_attr "length" "8")
2166 (set_attr "predicable" "yes")]
cffb2a26 2167)
9c08d1fa 2168
87b22bf7 2169(define_expand "iorsi3"
cffb2a26 2170 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2171 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2173 "TARGET_EITHER"
87b22bf7 2174 "
2175 if (GET_CODE (operands[2]) == CONST_INT)
2176 {
cffb2a26 2177 if (TARGET_ARM)
2178 {
96f57e36 2179 arm_split_constant (IOR, SImode, NULL_RTX,
2180 INTVAL (operands[2]), operands[0], operands[1],
615caa51 2181 optimize && !no_new_pseudos);
cffb2a26 2182 DONE;
2183 }
2184 else /* TARGET_THUMB */
2185 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2186 }
cffb2a26 2187 "
2188)
87b22bf7 2189
a0f94409 2190(define_insn_and_split "*arm_iorsi3"
cffb2a26 2191 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2192 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
cffb2a26 2194 "TARGET_ARM"
87b22bf7 2195 "@
2196 orr%?\\t%0, %1, %2
2197 #"
a0f94409 2198 "TARGET_ARM
2199 && GET_CODE (operands[2]) == CONST_INT
2200 && !const_ok_for_arm (INTVAL (operands[2]))"
2201 [(clobber (const_int 0))]
2202 "
96f57e36 2203 arm_split_constant (IOR, SImode, curr_insn,
2204 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2205 DONE;
2206 "
0d66636f 2207 [(set_attr "length" "4,16")
2208 (set_attr "predicable" "yes")]
cffb2a26 2209)
2210
2211(define_insn "*thumb_iorsi3"
2212 [(set (match_operand:SI 0 "register_operand" "=l")
2213 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214 (match_operand:SI 2 "register_operand" "l")))]
2215 "TARGET_THUMB"
2216 "orr\\t%0, %0, %2"
2217 [(set_attr "length" "2")]
2218)
9c08d1fa 2219
a0f94409 2220(define_peephole2
2221 [(match_scratch:SI 3 "r")
372575c7 2222 (set (match_operand:SI 0 "arm_general_register_operand" "")
2223 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2224 (match_operand:SI 2 "const_int_operand" "")))]
a0f94409 2225 "TARGET_ARM
2226 && !const_ok_for_arm (INTVAL (operands[2]))
2227 && const_ok_for_arm (~INTVAL (operands[2]))"
2228 [(set (match_dup 3) (match_dup 2))
2229 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2230 ""
215b30b3 2231)
a0f94409 2232
f7fbdd4a 2233(define_insn "*iorsi3_compare0"
bd5b4116 2234 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2235 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237 (const_int 0)))
2238 (set (match_operand:SI 0 "s_register_operand" "=r")
2239 (ior:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2240 "TARGET_ARM"
40dbec34 2241 "orr%?s\\t%0, %1, %2"
cffb2a26 2242 [(set_attr "conds" "set")]
2243)
9c08d1fa 2244
f7fbdd4a 2245(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2246 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2247 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2249 (const_int 0)))
2250 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2251 "TARGET_ARM"
40dbec34 2252 "orr%?s\\t%0, %1, %2"
0d66636f 2253 [(set_attr "conds" "set")]
2254)
9c08d1fa 2255
2256(define_insn "xordi3"
cffb2a26 2257 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2258 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2259 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2260 "TARGET_ARM && !TARGET_IWMMXT"
f6ebffac 2261 "#"
0d66636f 2262 [(set_attr "length" "8")
2263 (set_attr "predicable" "yes")]
cffb2a26 2264)
9c08d1fa 2265
f7fbdd4a 2266(define_insn "*xordi_zesidi_di"
9c08d1fa 2267 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268 (xor:DI (zero_extend:DI
2269 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2270 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2271 "TARGET_ARM"
e2348bcb 2272 "@
97499065 2273 eor%?\\t%Q0, %Q1, %2
f6ebffac 2274 #"
0d66636f 2275 [(set_attr "length" "4,8")
2276 (set_attr "predicable" "yes")]
cffb2a26 2277)
9c08d1fa 2278
f7fbdd4a 2279(define_insn "*xordi_sesidi_di"
9c08d1fa 2280 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281 (xor:DI (sign_extend:DI
2282 (match_operand:SI 2 "s_register_operand" "r,r"))
2283 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2284 "TARGET_ARM"
f6ebffac 2285 "#"
0d66636f 2286 [(set_attr "length" "8")
2287 (set_attr "predicable" "yes")]
cffb2a26 2288)
9c08d1fa 2289
cffb2a26 2290(define_expand "xorsi3"
2291 [(set (match_operand:SI 0 "s_register_operand" "")
2292 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293 (match_operand:SI 2 "arm_rhs_operand" "")))]
2294 "TARGET_EITHER"
2295 "if (TARGET_THUMB)
2296 if (GET_CODE (operands[2]) == CONST_INT)
2297 operands[2] = force_reg (SImode, operands[2]);
2298 "
2299)
2300
2301(define_insn "*arm_xorsi3"
2302 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2303 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 2305 "TARGET_ARM"
2306 "eor%?\\t%0, %1, %2"
0d66636f 2307 [(set_attr "predicable" "yes")]
cffb2a26 2308)
2309
2310(define_insn "*thumb_xorsi3"
2311 [(set (match_operand:SI 0 "register_operand" "=l")
2312 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313 (match_operand:SI 2 "register_operand" "l")))]
2314 "TARGET_THUMB"
2315 "eor\\t%0, %0, %2"
2316 [(set_attr "length" "2")]
2317)
9c08d1fa 2318
f7fbdd4a 2319(define_insn "*xorsi3_compare0"
bd5b4116 2320 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2321 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2323 (const_int 0)))
2324 (set (match_operand:SI 0 "s_register_operand" "=r")
2325 (xor:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2326 "TARGET_ARM"
40dbec34 2327 "eor%?s\\t%0, %1, %2"
0d66636f 2328 [(set_attr "conds" "set")]
2329)
9c08d1fa 2330
f7fbdd4a 2331(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2332 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2333 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2335 (const_int 0)))]
cffb2a26 2336 "TARGET_ARM"
40dbec34 2337 "teq%?\\t%0, %1"
cffb2a26 2338 [(set_attr "conds" "set")]
2339)
9c08d1fa 2340
215b30b3 2341; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2342; (NOT D) we can sometimes merge the final NOT into one of the following
2343; insns.
9c08d1fa 2344
2345(define_split
a058e94a 2346 [(set (match_operand:SI 0 "s_register_operand" "")
2347 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349 (match_operand:SI 3 "arm_rhs_operand" "")))
2350 (clobber (match_operand:SI 4 "s_register_operand" ""))]
cffb2a26 2351 "TARGET_ARM"
9c08d1fa 2352 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353 (not:SI (match_dup 3))))
2354 (set (match_dup 0) (not:SI (match_dup 4)))]
2355 ""
2356)
2357
f7fbdd4a 2358(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2359 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
cffb2a26 2363 "TARGET_ARM"
40dbec34 2364 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2365 [(set_attr "length" "8")
2366 (set_attr "predicable" "yes")]
cffb2a26 2367)
9c08d1fa 2368
d7863cfe 2369(define_split
2370 [(set (match_operand:SI 0 "s_register_operand" "")
2371 (match_operator:SI 1 "logical_binary_operator"
2372 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373 (match_operand:SI 3 "const_int_operand" "")
2374 (match_operand:SI 4 "const_int_operand" ""))
2375 (match_operator:SI 9 "logical_binary_operator"
2376 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377 (match_operand:SI 6 "const_int_operand" ""))
2378 (match_operand:SI 7 "s_register_operand" "")])]))
2379 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2380 "TARGET_ARM
2381 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2383 [(set (match_dup 8)
2384 (match_op_dup 1
2385 [(ashift:SI (match_dup 2) (match_dup 4))
2386 (match_dup 5)]))
2387 (set (match_dup 0)
2388 (match_op_dup 1
2389 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2390 (match_dup 7)]))]
2391 "
2392 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2393")
2394
2395(define_split
2396 [(set (match_operand:SI 0 "s_register_operand" "")
2397 (match_operator:SI 1 "logical_binary_operator"
2398 [(match_operator:SI 9 "logical_binary_operator"
2399 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400 (match_operand:SI 6 "const_int_operand" ""))
2401 (match_operand:SI 7 "s_register_operand" "")])
2402 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403 (match_operand:SI 3 "const_int_operand" "")
2404 (match_operand:SI 4 "const_int_operand" ""))]))
2405 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2406 "TARGET_ARM
2407 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2409 [(set (match_dup 8)
2410 (match_op_dup 1
2411 [(ashift:SI (match_dup 2) (match_dup 4))
2412 (match_dup 5)]))
2413 (set (match_dup 0)
2414 (match_op_dup 1
2415 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2416 (match_dup 7)]))]
2417 "
2418 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2419")
2420
2421(define_split
2422 [(set (match_operand:SI 0 "s_register_operand" "")
2423 (match_operator:SI 1 "logical_binary_operator"
2424 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425 (match_operand:SI 3 "const_int_operand" "")
2426 (match_operand:SI 4 "const_int_operand" ""))
2427 (match_operator:SI 9 "logical_binary_operator"
2428 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429 (match_operand:SI 6 "const_int_operand" ""))
2430 (match_operand:SI 7 "s_register_operand" "")])]))
2431 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2432 "TARGET_ARM
2433 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2435 [(set (match_dup 8)
2436 (match_op_dup 1
2437 [(ashift:SI (match_dup 2) (match_dup 4))
2438 (match_dup 5)]))
2439 (set (match_dup 0)
2440 (match_op_dup 1
2441 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2442 (match_dup 7)]))]
2443 "
2444 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2445")
2446
2447(define_split
2448 [(set (match_operand:SI 0 "s_register_operand" "")
2449 (match_operator:SI 1 "logical_binary_operator"
2450 [(match_operator:SI 9 "logical_binary_operator"
2451 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452 (match_operand:SI 6 "const_int_operand" ""))
2453 (match_operand:SI 7 "s_register_operand" "")])
2454 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455 (match_operand:SI 3 "const_int_operand" "")
2456 (match_operand:SI 4 "const_int_operand" ""))]))
2457 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2458 "TARGET_ARM
2459 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2461 [(set (match_dup 8)
2462 (match_op_dup 1
2463 [(ashift:SI (match_dup 2) (match_dup 4))
2464 (match_dup 5)]))
2465 (set (match_dup 0)
2466 (match_op_dup 1
2467 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2468 (match_dup 7)]))]
2469 "
2470 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2471")
9c08d1fa 2472\f
2473
2474;; Minimum and maximum insns
2475
2476(define_insn "smaxsi3"
cffb2a26 2477 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2478 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2479 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2480 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2481 "TARGET_ARM"
e2348bcb 2482 "@
2483 cmp\\t%1, %2\;movlt\\t%0, %2
2484 cmp\\t%1, %2\;movge\\t%0, %1
2485 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2486 [(set_attr "conds" "clob")
2487 (set_attr "length" "8,8,12")]
2488)
9c08d1fa 2489
2490(define_insn "sminsi3"
2491 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2492 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2493 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2494 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2495 "TARGET_ARM"
e2348bcb 2496 "@
2497 cmp\\t%1, %2\;movge\\t%0, %2
2498 cmp\\t%1, %2\;movlt\\t%0, %1
2499 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 2500 [(set_attr "conds" "clob")
2501 (set_attr "length" "8,8,12")]
2502)
9c08d1fa 2503
2504(define_insn "umaxsi3"
2505 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2506 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2507 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2508 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2509 "TARGET_ARM"
e2348bcb 2510 "@
2511 cmp\\t%1, %2\;movcc\\t%0, %2
2512 cmp\\t%1, %2\;movcs\\t%0, %1
2513 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 2514 [(set_attr "conds" "clob")
2515 (set_attr "length" "8,8,12")]
2516)
9c08d1fa 2517
2518(define_insn "uminsi3"
2519 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2520 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2521 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2522 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2523 "TARGET_ARM"
e2348bcb 2524 "@
2525 cmp\\t%1, %2\;movcs\\t%0, %2
2526 cmp\\t%1, %2\;movcc\\t%0, %1
2527 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 2528 [(set_attr "conds" "clob")
2529 (set_attr "length" "8,8,12")]
2530)
9c08d1fa 2531
8a18b90c 2532(define_insn "*store_minmaxsi"
9c08d1fa 2533 [(set (match_operand:SI 0 "memory_operand" "=m")
2534 (match_operator:SI 3 "minmax_operator"
2535 [(match_operand:SI 1 "s_register_operand" "r")
2536 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 2537 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2538 "TARGET_ARM"
9c08d1fa 2539 "*
dc55b8a9 2540 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2541 operands[1], operands[2]);
e2348bcb 2542 output_asm_insn (\"cmp\\t%1, %2\", operands);
2543 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2544 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2545 return \"\";
0d66636f 2546 "
2547 [(set_attr "conds" "clob")
2548 (set_attr "length" "12")
2549 (set_attr "type" "store1")]
2550)
9c08d1fa 2551
8a18b90c 2552; Reject the frame pointer in operand[1], since reloading this after
2553; it has been eliminated can cause carnage.
f7fbdd4a 2554(define_insn "*minmax_arithsi"
9c08d1fa 2555 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2556 (match_operator:SI 4 "shiftable_operator"
2557 [(match_operator:SI 5 "minmax_operator"
2558 [(match_operand:SI 2 "s_register_operand" "r,r")
2559 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2560 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 2561 (clobber (reg:CC CC_REGNUM))]
da45ccee 2562 "TARGET_ARM && !arm_eliminable_register (operands[1])"
9c08d1fa 2563 "*
0d66636f 2564 {
2565 enum rtx_code code = GET_CODE (operands[4]);
2566
dc55b8a9 2567 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2568 operands[2], operands[3]);
0d66636f 2569 output_asm_insn (\"cmp\\t%2, %3\", operands);
2570 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2571 if (which_alternative != 0 || operands[3] != const0_rtx
2572 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2573 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2574 return \"\";
215b30b3 2575 }"
0d66636f 2576 [(set_attr "conds" "clob")
2577 (set_attr "length" "12")]
2578)
9c08d1fa 2579
b11cae9e 2580\f
2581;; Shift and rotation insns
2582
a2cd141b 2583(define_expand "ashldi3"
2584 [(set (match_operand:DI 0 "s_register_operand" "")
2585 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2586 (match_operand:SI 2 "reg_or_int_operand" "")))]
2587 "TARGET_ARM"
2588 "
2589 if (GET_CODE (operands[2]) == CONST_INT)
2590 {
2591 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2592 {
2593 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2594 DONE;
2595 }
2596 /* Ideally we shouldn't fail here if we could know that operands[1]
2597 ends up already living in an iwmmxt register. Otherwise it's
2598 cheaper to have the alternate code being generated than moving
1d60d981 2599 values to iwmmxt regs and back. */
a2cd141b 2600 FAIL;
2601 }
2602 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2603 FAIL;
2604 "
2605)
2606
2607(define_insn "arm_ashldi3_1bit"
2608 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2609 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2610 (const_int 1)))
2611 (clobber (reg:CC CC_REGNUM))]
2612 "TARGET_ARM"
2613 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2614 [(set_attr "conds" "clob")
2615 (set_attr "length" "8")]
2616)
2617
87b22bf7 2618(define_expand "ashlsi3"
cffb2a26 2619 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2620 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2621 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2622 "TARGET_EITHER"
87b22bf7 2623 "
2624 if (GET_CODE (operands[2]) == CONST_INT
2625 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2626 {
2627 emit_insn (gen_movsi (operands[0], const0_rtx));
2628 DONE;
2629 }
cffb2a26 2630 "
2631)
2632
2633(define_insn "*thumb_ashlsi3"
2634 [(set (match_operand:SI 0 "register_operand" "=l,l")
2635 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2636 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2637 "TARGET_THUMB"
2638 "lsl\\t%0, %1, %2"
2639 [(set_attr "length" "2")]
2640)
b11cae9e 2641
a2cd141b 2642(define_expand "ashrdi3"
2643 [(set (match_operand:DI 0 "s_register_operand" "")
2644 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2645 (match_operand:SI 2 "reg_or_int_operand" "")))]
2646 "TARGET_ARM"
2647 "
2648 if (GET_CODE (operands[2]) == CONST_INT)
2649 {
2650 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2651 {
2652 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2653 DONE;
2654 }
2655 /* Ideally we shouldn't fail here if we could know that operands[1]
2656 ends up already living in an iwmmxt register. Otherwise it's
2657 cheaper to have the alternate code being generated than moving
1d60d981 2658 values to iwmmxt regs and back. */
a2cd141b 2659 FAIL;
2660 }
2661 else if (!TARGET_REALLY_IWMMXT)
2662 FAIL;
2663 "
2664)
2665
2666(define_insn "arm_ashrdi3_1bit"
2667 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2668 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2669 (const_int 1)))
2670 (clobber (reg:CC CC_REGNUM))]
2671 "TARGET_ARM"
2672 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2673 [(set_attr "conds" "clob")
2674 (set_attr "length" "8")]
2675)
2676
87b22bf7 2677(define_expand "ashrsi3"
cffb2a26 2678 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2679 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2680 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2681 "TARGET_EITHER"
87b22bf7 2682 "
2683 if (GET_CODE (operands[2]) == CONST_INT
2684 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2685 operands[2] = GEN_INT (31);
cffb2a26 2686 "
2687)
2688
2689(define_insn "*thumb_ashrsi3"
2690 [(set (match_operand:SI 0 "register_operand" "=l,l")
2691 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2692 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2693 "TARGET_THUMB"
2694 "asr\\t%0, %1, %2"
2695 [(set_attr "length" "2")]
2696)
b11cae9e 2697
a2cd141b 2698(define_expand "lshrdi3"
2699 [(set (match_operand:DI 0 "s_register_operand" "")
2700 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2701 (match_operand:SI 2 "reg_or_int_operand" "")))]
2702 "TARGET_ARM"
2703 "
2704 if (GET_CODE (operands[2]) == CONST_INT)
2705 {
2706 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2707 {
2708 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2709 DONE;
2710 }
2711 /* Ideally we shouldn't fail here if we could know that operands[1]
2712 ends up already living in an iwmmxt register. Otherwise it's
2713 cheaper to have the alternate code being generated than moving
1d60d981 2714 values to iwmmxt regs and back. */
a2cd141b 2715 FAIL;
2716 }
2717 else if (!TARGET_REALLY_IWMMXT)
2718 FAIL;
2719 "
2720)
2721
2722(define_insn "arm_lshrdi3_1bit"
2723 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2724 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2725 (const_int 1)))
2726 (clobber (reg:CC CC_REGNUM))]
2727 "TARGET_ARM"
2728 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2729 [(set_attr "conds" "clob")
2730 (set_attr "length" "8")]
2731)
2732
87b22bf7 2733(define_expand "lshrsi3"
cffb2a26 2734 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2735 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2736 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2737 "TARGET_EITHER"
87b22bf7 2738 "
2739 if (GET_CODE (operands[2]) == CONST_INT
2740 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2741 {
2742 emit_insn (gen_movsi (operands[0], const0_rtx));
2743 DONE;
2744 }
cffb2a26 2745 "
2746)
2747
2748(define_insn "*thumb_lshrsi3"
2749 [(set (match_operand:SI 0 "register_operand" "=l,l")
2750 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2751 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2752 "TARGET_THUMB"
2753 "lsr\\t%0, %1, %2"
2754 [(set_attr "length" "2")]
2755)
b11cae9e 2756
87b22bf7 2757(define_expand "rotlsi3"
cffb2a26 2758 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2759 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2760 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2761 "TARGET_ARM"
87b22bf7 2762 "
2763 if (GET_CODE (operands[2]) == CONST_INT)
2764 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2765 else
b11cae9e 2766 {
87b22bf7 2767 rtx reg = gen_reg_rtx (SImode);
2768 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2769 operands[2] = reg;
b11cae9e 2770 }
cffb2a26 2771 "
2772)
9c08d1fa 2773
87b22bf7 2774(define_expand "rotrsi3"
cffb2a26 2775 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2776 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2777 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2778 "TARGET_EITHER"
87b22bf7 2779 "
cffb2a26 2780 if (TARGET_ARM)
2781 {
2782 if (GET_CODE (operands[2]) == CONST_INT
2783 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2784 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2785 }
2786 else /* TARGET_THUMB */
2787 {
2788 if (GET_CODE (operands [2]) == CONST_INT)
2789 operands [2] = force_reg (SImode, operands[2]);
2790 }
2791 "
2792)
87b22bf7 2793
cffb2a26 2794(define_insn "*thumb_rotrsi3"
2795 [(set (match_operand:SI 0 "register_operand" "=l")
2796 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2797 (match_operand:SI 2 "register_operand" "l")))]
2798 "TARGET_THUMB"
2799 "ror\\t%0, %0, %2"
2800 [(set_attr "length" "2")]
2801)
2802
2803(define_insn "*arm_shiftsi3"
2804 [(set (match_operand:SI 0 "s_register_operand" "=r")
2805 (match_operator:SI 3 "shift_operator"
2806 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 2807 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
cffb2a26 2808 "TARGET_ARM"
6c4c2133 2809 "mov%?\\t%0, %1%S3"
344495ea 2810 [(set_attr "predicable" "yes")
331beb1a 2811 (set_attr "shift" "1")
a2cd141b 2812 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2813 (const_string "alu_shift")
2814 (const_string "alu_shift_reg")))]
6c4c2133 2815)
87b22bf7 2816
f7fbdd4a 2817(define_insn "*shiftsi3_compare0"
bd5b4116 2818 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2819 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2820 [(match_operand:SI 1 "s_register_operand" "r")
2821 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2822 (const_int 0)))
2823 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2824 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
cffb2a26 2825 "TARGET_ARM"
87b22bf7 2826 "mov%?s\\t%0, %1%S3"
344495ea 2827 [(set_attr "conds" "set")
331beb1a 2828 (set_attr "shift" "1")
a2cd141b 2829 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2830 (const_string "alu_shift")
2831 (const_string "alu_shift_reg")))]
0d66636f 2832)
9c08d1fa 2833
f7fbdd4a 2834(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 2835 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2836 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2837 [(match_operand:SI 1 "s_register_operand" "r")
2838 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2839 (const_int 0)))
2840 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2841 "TARGET_ARM"
87b22bf7 2842 "mov%?s\\t%0, %1%S3"
344495ea 2843 [(set_attr "conds" "set")
a2cd141b 2844 (set_attr "shift" "1")]
0d66636f 2845)
9c08d1fa 2846
f7fbdd4a 2847(define_insn "*notsi_shiftsi"
9c08d1fa 2848 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2849 (not:SI (match_operator:SI 3 "shift_operator"
2850 [(match_operand:SI 1 "s_register_operand" "r")
2851 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 2852 "TARGET_ARM"
6c4c2133 2853 "mvn%?\\t%0, %1%S3"
344495ea 2854 [(set_attr "predicable" "yes")
331beb1a 2855 (set_attr "shift" "1")
a2cd141b 2856 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2857 (const_string "alu_shift")
2858 (const_string "alu_shift_reg")))]
0d66636f 2859)
9c08d1fa 2860
f7fbdd4a 2861(define_insn "*notsi_shiftsi_compare0"
bd5b4116 2862 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2863 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2864 [(match_operand:SI 1 "s_register_operand" "r")
2865 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2866 (const_int 0)))
2867 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2868 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 2869 "TARGET_ARM"
87b22bf7 2870 "mvn%?s\\t%0, %1%S3"
344495ea 2871 [(set_attr "conds" "set")
331beb1a 2872 (set_attr "shift" "1")
a2cd141b 2873 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874 (const_string "alu_shift")
2875 (const_string "alu_shift_reg")))]
0d66636f 2876)
9c08d1fa 2877
f7fbdd4a 2878(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 2879 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2880 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2881 [(match_operand:SI 1 "s_register_operand" "r")
2882 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2883 (const_int 0)))
2884 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2885 "TARGET_ARM"
87b22bf7 2886 "mvn%?s\\t%0, %1%S3"
344495ea 2887 [(set_attr "conds" "set")
331beb1a 2888 (set_attr "shift" "1")
a2cd141b 2889 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2890 (const_string "alu_shift")
2891 (const_string "alu_shift_reg")))]
0d66636f 2892)
9c08d1fa 2893
cffb2a26 2894;; We don't really have extzv, but defining this using shifts helps
2895;; to reduce register pressure later on.
2896
2897(define_expand "extzv"
2898 [(set (match_dup 4)
2899 (ashift:SI (match_operand:SI 1 "register_operand" "")
2900 (match_operand:SI 2 "const_int_operand" "")))
2901 (set (match_operand:SI 0 "register_operand" "")
2902 (lshiftrt:SI (match_dup 4)
215b30b3 2903 (match_operand:SI 3 "const_int_operand" "")))]
cffb2a26 2904 "TARGET_THUMB"
2905 "
2906 {
2907 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2908 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2909
2910 operands[3] = GEN_INT (rshift);
2911
2912 if (lshift == 0)
2913 {
2914 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2915 DONE;
2916 }
2917
2918 operands[2] = GEN_INT (lshift);
2919 operands[4] = gen_reg_rtx (SImode);
215b30b3 2920 }"
cffb2a26 2921)
2922
b11cae9e 2923\f
2924;; Unary arithmetic insns
2925
cffb2a26 2926(define_expand "negdi2"
2927 [(parallel
2928 [(set (match_operand:DI 0 "s_register_operand" "")
2929 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 2930 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 2931 "TARGET_EITHER"
2932 "
2933 if (TARGET_THUMB)
2934 {
2935 if (GET_CODE (operands[1]) != REG)
2936 operands[1] = force_reg (SImode, operands[1]);
2937 }
215b30b3 2938 "
cffb2a26 2939)
2940
2941;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2942;; The second alternative is to allow the common case of a *full* overlap.
2943(define_insn "*arm_negdi2"
2944 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2945 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 2946 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2947 "TARGET_ARM"
97499065 2948 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 2949 [(set_attr "conds" "clob")
2950 (set_attr "length" "8")]
2951)
b11cae9e 2952
cffb2a26 2953(define_insn "*thumb_negdi2"
2954 [(set (match_operand:DI 0 "register_operand" "=&l")
2955 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 2956 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2957 "TARGET_THUMB"
2958 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2959 [(set_attr "length" "6")]
2960)
2961
2962(define_expand "negsi2"
2963 [(set (match_operand:SI 0 "s_register_operand" "")
2964 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2965 "TARGET_EITHER"
b11cae9e 2966 ""
cffb2a26 2967)
2968
2969(define_insn "*arm_negsi2"
2970 [(set (match_operand:SI 0 "s_register_operand" "=r")
2971 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2972 "TARGET_ARM"
2973 "rsb%?\\t%0, %1, #0"
0d66636f 2974 [(set_attr "predicable" "yes")]
cffb2a26 2975)
2976
2977(define_insn "*thumb_negsi2"
2978 [(set (match_operand:SI 0 "register_operand" "=l")
2979 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2980 "TARGET_THUMB"
2981 "neg\\t%0, %1"
2982 [(set_attr "length" "2")]
2983)
b11cae9e 2984
604f3a0a 2985(define_expand "negsf2"
2986 [(set (match_operand:SF 0 "s_register_operand" "")
2987 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
890ab29e 2988 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 2989 ""
2990)
2991
2992(define_expand "negdf2"
2993 [(set (match_operand:DF 0 "s_register_operand" "")
2994 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
890ab29e 2995 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 2996 "")
2997
9c08d1fa 2998;; abssi2 doesn't really clobber the condition codes if a different register
2999;; is being set. To keep things simple, assume during rtl manipulations that
3000;; it does, but tell the final scan operator the truth. Similarly for
3001;; (neg (abs...))
3002
604f3a0a 3003(define_expand "abssi2"
3004 [(parallel
3005 [(set (match_operand:SI 0 "s_register_operand" "")
3006 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3007 (clobber (reg:CC CC_REGNUM))])]
3008 "TARGET_ARM"
3009 "")
3010
7d57ec45 3011(define_insn "*arm_abssi2"
722f9800 3012 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3013 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3014 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3015 "TARGET_ARM"
e2348bcb 3016 "@
3017 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3018 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3019 [(set_attr "conds" "clob,*")
331beb1a 3020 (set_attr "shift" "1")
0d66636f 3021 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3022 (set_attr "length" "8")]
3023)
9c08d1fa 3024
f7fbdd4a 3025(define_insn "*neg_abssi2"
9c08d1fa 3026 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3027 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3028 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3029 "TARGET_ARM"
e2348bcb 3030 "@
3031 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3032 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3033 [(set_attr "conds" "clob,*")
331beb1a 3034 (set_attr "shift" "1")
0d66636f 3035 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3036 (set_attr "length" "8")]
3037)
b11cae9e 3038
604f3a0a 3039(define_expand "abssf2"
3040 [(set (match_operand:SF 0 "s_register_operand" "")
3041 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3042 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3043 "")
3044
604f3a0a 3045(define_expand "absdf2"
3046 [(set (match_operand:DF 0 "s_register_operand" "")
3047 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3048 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3049 "")
3050
7db9af5d 3051(define_expand "sqrtsf2"
3052 [(set (match_operand:SF 0 "s_register_operand" "")
3053 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3054 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3055 "")
9c08d1fa 3056
7db9af5d 3057(define_expand "sqrtdf2"
3058 [(set (match_operand:DF 0 "s_register_operand" "")
3059 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3060 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3061 "")
9c08d1fa 3062
a0f94409 3063(define_insn_and_split "one_cmpldi2"
9c08d1fa 3064 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3065 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 3066 "TARGET_ARM"
f6ebffac 3067 "#"
a0f94409 3068 "TARGET_ARM && reload_completed"
3069 [(set (match_dup 0) (not:SI (match_dup 1)))
3070 (set (match_dup 2) (not:SI (match_dup 3)))]
3071 "
3072 {
3073 operands[2] = gen_highpart (SImode, operands[0]);
3074 operands[0] = gen_lowpart (SImode, operands[0]);
3075 operands[3] = gen_highpart (SImode, operands[1]);
3076 operands[1] = gen_lowpart (SImode, operands[1]);
3077 }"
0d66636f 3078 [(set_attr "length" "8")
3079 (set_attr "predicable" "yes")]
cffb2a26 3080)
b11cae9e 3081
cffb2a26 3082(define_expand "one_cmplsi2"
3083 [(set (match_operand:SI 0 "s_register_operand" "")
3084 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3085 "TARGET_EITHER"
b11cae9e 3086 ""
cffb2a26 3087)
3088
3089(define_insn "*arm_one_cmplsi2"
3090 [(set (match_operand:SI 0 "s_register_operand" "=r")
3091 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3092 "TARGET_ARM"
3093 "mvn%?\\t%0, %1"
0d66636f 3094 [(set_attr "predicable" "yes")]
cffb2a26 3095)
3096
3097(define_insn "*thumb_one_cmplsi2"
3098 [(set (match_operand:SI 0 "register_operand" "=l")
3099 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3100 "TARGET_THUMB"
3101 "mvn\\t%0, %1"
3102 [(set_attr "length" "2")]
3103)
9c08d1fa 3104
f7fbdd4a 3105(define_insn "*notsi_compare0"
bd5b4116 3106 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3107 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3108 (const_int 0)))
3109 (set (match_operand:SI 0 "s_register_operand" "=r")
3110 (not:SI (match_dup 1)))]
cffb2a26 3111 "TARGET_ARM"
40dbec34 3112 "mvn%?s\\t%0, %1"
cffb2a26 3113 [(set_attr "conds" "set")]
3114)
9c08d1fa 3115
f7fbdd4a 3116(define_insn "*notsi_compare0_scratch"
bd5b4116 3117 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3118 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3119 (const_int 0)))
3120 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3121 "TARGET_ARM"
40dbec34 3122 "mvn%?s\\t%0, %1"
cffb2a26 3123 [(set_attr "conds" "set")]
3124)
b11cae9e 3125\f
3126;; Fixed <--> Floating conversion insns
3127
604f3a0a 3128(define_expand "floatsisf2"
3129 [(set (match_operand:SF 0 "s_register_operand" "")
3130 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3131 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3132 "
a2cd141b 3133 if (TARGET_MAVERICK)
604f3a0a 3134 {
3135 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3136 DONE;
3137 }
3138")
3139
604f3a0a 3140(define_expand "floatsidf2"
3141 [(set (match_operand:DF 0 "s_register_operand" "")
3142 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3143 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3144 "
a2cd141b 3145 if (TARGET_MAVERICK)
604f3a0a 3146 {
3147 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3148 DONE;
3149 }
3150")
3151
604f3a0a 3152(define_expand "fix_truncsfsi2"
3153 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3154 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
a2cd141b 3155 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3156 "
a2cd141b 3157 if (TARGET_MAVERICK)
604f3a0a 3158 {
3159 if (!cirrus_fp_register (operands[0], SImode))
3160 operands[0] = force_reg (SImode, operands[0]);
3161 if (!cirrus_fp_register (operands[1], SFmode))
3162 operands[1] = force_reg (SFmode, operands[0]);
3163 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3164 DONE;
3165 }
3166")
3167
604f3a0a 3168(define_expand "fix_truncdfsi2"
3169 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3170 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a2cd141b 3171 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3172 "
a2cd141b 3173 if (TARGET_MAVERICK)
604f3a0a 3174 {
3175 if (!cirrus_fp_register (operands[1], DFmode))
3176 operands[1] = force_reg (DFmode, operands[0]);
3177 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3178 DONE;
3179 }
3180")
3181
f544c6d2 3182;; Truncation insns
b11cae9e 3183
604f3a0a 3184(define_expand "truncdfsf2"
3185 [(set (match_operand:SF 0 "s_register_operand" "")
3186 (float_truncate:SF
3187 (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3188 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3189 ""
3190)
b11cae9e 3191\f
9c08d1fa 3192;; Zero and sign extension instructions.
b11cae9e 3193
9c08d1fa 3194(define_insn "zero_extendsidi2"
3195 [(set (match_operand:DI 0 "s_register_operand" "=r")
3196 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3197 "TARGET_ARM"
9c08d1fa 3198 "*
0d66636f 3199 if (REGNO (operands[1])
3200 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3201 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3202 return \"mov%?\\t%R0, #0\";
3203 "
3204 [(set_attr "length" "8")
3205 (set_attr "predicable" "yes")]
3206)
9c08d1fa 3207
3208(define_insn "zero_extendqidi2"
cffb2a26 3209 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3210 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3211 "TARGET_ARM"
e2348bcb 3212 "@
97499065 3213 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3214 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3215 [(set_attr "length" "8")
0d66636f 3216 (set_attr "predicable" "yes")
a2cd141b 3217 (set_attr "type" "*,load_byte")
cffb2a26 3218 (set_attr "pool_range" "*,4092")
3219 (set_attr "neg_pool_range" "*,4084")]
3220)
9c08d1fa 3221
3222(define_insn "extendsidi2"
3223 [(set (match_operand:DI 0 "s_register_operand" "=r")
3224 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3225 "TARGET_ARM"
9c08d1fa 3226 "*
0d66636f 3227 if (REGNO (operands[1])
3228 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3229 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3230 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3231 "
3232 [(set_attr "length" "8")
331beb1a 3233 (set_attr "shift" "1")
0d66636f 3234 (set_attr "predicable" "yes")]
3235)
9c08d1fa 3236
3237(define_expand "zero_extendhisi2"
cffb2a26 3238 [(set (match_dup 2)
0d66636f 3239 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3240 (const_int 16)))
9c08d1fa 3241 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3242 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3243 "TARGET_EITHER"
9c08d1fa 3244 "
cffb2a26 3245 {
a2cd141b 3246 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3247 {
a2cd141b 3248 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250 DONE;
cffb2a26 3251 }
cffb2a26 3252
c1a66faf 3253 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3254 {
3255 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3256 DONE;
3257 }
cffb2a26 3258
a2cd141b 3259 if (!s_register_operand (operands[1], HImode))
3260 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3261
a2cd141b 3262 if (arm_arch6)
3263 {
3264 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3265 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3266 DONE;
cffb2a26 3267 }
a2cd141b 3268
3269 operands[1] = gen_lowpart (SImode, operands[1]);
3270 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3271 }"
3272)
3273
3274(define_insn "*thumb_zero_extendhisi2"
a2cd141b 3275 [(set (match_operand:SI 0 "register_operand" "=l")
3276 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3277 "TARGET_THUMB && !arm_arch6"
cffb2a26 3278 "*
3279 rtx mem = XEXP (operands[1], 0);
3280
3281 if (GET_CODE (mem) == CONST)
3282 mem = XEXP (mem, 0);
3283
3284 if (GET_CODE (mem) == LABEL_REF)
3285 return \"ldr\\t%0, %1\";
3286
3287 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3288 {
cffb2a26 3289 rtx a = XEXP (mem, 0);
3290 rtx b = XEXP (mem, 1);
3291
3292 /* This can happen due to bugs in reload. */
3293 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3294 {
3295 rtx ops[2];
3296 ops[0] = operands[0];
3297 ops[1] = a;
3298
3299 output_asm_insn (\"mov %0, %1\", ops);
3300
3301 XEXP (mem, 0) = operands[0];
3302 }
3303
3304 else if ( GET_CODE (a) == LABEL_REF
3305 && GET_CODE (b) == CONST_INT)
3306 return \"ldr\\t%0, %1\";
25f7a26e 3307 }
cffb2a26 3308
3309 return \"ldrh\\t%0, %1\";
3310 "
3311 [(set_attr "length" "4")
a2cd141b 3312 (set_attr "type" "load_byte")
cffb2a26 3313 (set_attr "pool_range" "60")]
3314)
9c08d1fa 3315
a2cd141b 3316(define_insn "*thumb_zero_extendhisi2_v6"
3317 [(set (match_operand:SI 0 "register_operand" "=l,l")
3318 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3319 "TARGET_THUMB && arm_arch6"
3320 "*
3321 rtx mem;
3322
3323 if (which_alternative == 0)
3324 return \"uxth\\t%0, %1\";
3325
3326 mem = XEXP (operands[1], 0);
3327
3328 if (GET_CODE (mem) == CONST)
3329 mem = XEXP (mem, 0);
3330
3331 if (GET_CODE (mem) == LABEL_REF)
3332 return \"ldr\\t%0, %1\";
3333
3334 if (GET_CODE (mem) == PLUS)
3335 {
3336 rtx a = XEXP (mem, 0);
3337 rtx b = XEXP (mem, 1);
3338
3339 /* This can happen due to bugs in reload. */
3340 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3341 {
3342 rtx ops[2];
3343 ops[0] = operands[0];
3344 ops[1] = a;
3345
3346 output_asm_insn (\"mov %0, %1\", ops);
3347
3348 XEXP (mem, 0) = operands[0];
3349 }
3350
3351 else if ( GET_CODE (a) == LABEL_REF
3352 && GET_CODE (b) == CONST_INT)
3353 return \"ldr\\t%0, %1\";
3354 }
3355
3356 return \"ldrh\\t%0, %1\";
3357 "
3358 [(set_attr "length" "2,4")
3359 (set_attr "type" "alu_shift,load_byte")
3360 (set_attr "pool_range" "*,60")]
3361)
3362
cffb2a26 3363(define_insn "*arm_zero_extendhisi2"
a2cd141b 3364 [(set (match_operand:SI 0 "s_register_operand" "=r")
3365 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3366 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3367 "ldr%?h\\t%0, %1"
a2cd141b 3368 [(set_attr "type" "load_byte")
0d66636f 3369 (set_attr "predicable" "yes")
cffb2a26 3370 (set_attr "pool_range" "256")
3371 (set_attr "neg_pool_range" "244")]
3372)
f7fbdd4a 3373
a2cd141b 3374(define_insn "*arm_zero_extendhisi2_v6"
3375 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3376 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3377 "TARGET_ARM && arm_arch6"
3378 "@
3379 uxth%?\\t%0, %1
3380 ldr%?h\\t%0, %1"
3381 [(set_attr "type" "alu_shift,load_byte")
3382 (set_attr "predicable" "yes")
3383 (set_attr "pool_range" "*,256")
3384 (set_attr "neg_pool_range" "*,244")]
3385)
3386
3387(define_insn "*arm_zero_extendhisi2addsi"
3388 [(set (match_operand:SI 0 "s_register_operand" "=r")
3389 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3390 (match_operand:SI 2 "s_register_operand" "r")))]
3391 "TARGET_ARM && arm_arch6"
3392 "uxtah%?\\t%0, %2, %1"
3393 [(set_attr "type" "alu_shift")
3394 (set_attr "predicable" "yes")]
3395)
3396
87b22bf7 3397(define_expand "zero_extendqisi2"
cffb2a26 3398 [(set (match_operand:SI 0 "s_register_operand" "")
3399 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3400 "TARGET_EITHER"
87b22bf7 3401 "
a2cd141b 3402 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 3403 {
cffb2a26 3404 if (TARGET_ARM)
3405 {
215b30b3 3406 emit_insn (gen_andsi3 (operands[0],
3407 gen_lowpart (SImode, operands[1]),
cffb2a26 3408 GEN_INT (255)));
3409 }
3410 else /* TARGET_THUMB */
3411 {
3412 rtx temp = gen_reg_rtx (SImode);
3413 rtx ops[3];
3414
3415 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3416 operands[1] = gen_lowpart (SImode, operands[1]);
3417
3418 ops[0] = temp;
3419 ops[1] = operands[1];
3420 ops[2] = GEN_INT (24);
3421
215b30b3 3422 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3423 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3424
3425 ops[0] = operands[0];
3426 ops[1] = temp;
3427 ops[2] = GEN_INT (24);
3428
215b30b3 3429 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3430 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3431 }
87b22bf7 3432 DONE;
3433 }
215b30b3 3434 "
3435)
9c08d1fa 3436
cffb2a26 3437(define_insn "*thumb_zero_extendqisi2"
a2cd141b 3438 [(set (match_operand:SI 0 "register_operand" "=l")
3439 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3440 "TARGET_THUMB && !arm_arch6"
cffb2a26 3441 "ldrb\\t%0, %1"
3442 [(set_attr "length" "2")
a2cd141b 3443 (set_attr "type" "load_byte")
cffb2a26 3444 (set_attr "pool_range" "32")]
3445)
3446
a2cd141b 3447(define_insn "*thumb_zero_extendqisi2_v6"
3448 [(set (match_operand:SI 0 "register_operand" "=l,l")
3449 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3450 "TARGET_THUMB && arm_arch6"
3451 "@
3452 uxtb\\t%0, %1
3453 ldrb\\t%0, %1"
3454 [(set_attr "length" "2,2")
3455 (set_attr "type" "alu_shift,load_byte")
3456 (set_attr "pool_range" "*,32")]
3457)
3458
cffb2a26 3459(define_insn "*arm_zero_extendqisi2"
a2cd141b 3460 [(set (match_operand:SI 0 "s_register_operand" "=r")
3461 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3462 "TARGET_ARM && !arm_arch6"
87b22bf7 3463 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3464 [(set_attr "type" "load_byte")
0d66636f 3465 (set_attr "predicable" "yes")
cffb2a26 3466 (set_attr "pool_range" "4096")
3467 (set_attr "neg_pool_range" "4084")]
3468)
87b22bf7 3469
a2cd141b 3470(define_insn "*arm_zero_extendqisi2_v6"
3471 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3472 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3473 "TARGET_ARM && arm_arch6"
3474 "@
3475 uxtb%?\\t%0, %1
3476 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3477 [(set_attr "type" "alu_shift,load_byte")
3478 (set_attr "predicable" "yes")
3479 (set_attr "pool_range" "*,4096")
3480 (set_attr "neg_pool_range" "*,4084")]
3481)
3482
3483(define_insn "*arm_zero_extendqisi2addsi"
3484 [(set (match_operand:SI 0 "s_register_operand" "=r")
3485 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3486 (match_operand:SI 2 "s_register_operand" "r")))]
3487 "TARGET_ARM && arm_arch6"
3488 "uxtab%?\\t%0, %2, %1"
3489 [(set_attr "predicable" "yes")
3490 (set_attr "type" "alu_shift")]
3491)
3492
87b22bf7 3493(define_split
3494 [(set (match_operand:SI 0 "s_register_operand" "")
3495 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3496 (clobber (match_operand:SI 2 "s_register_operand" ""))]
9e8503e6 3497 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 3498 [(set (match_dup 2) (match_dup 1))
3499 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 3500 ""
3501)
9c08d1fa 3502
f7fbdd4a 3503(define_insn "*compareqi_eq0"
bd5b4116 3504 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 3505 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 3506 (const_int 0)))]
cffb2a26 3507 "TARGET_ARM"
87b22bf7 3508 "tst\\t%0, #255"
cffb2a26 3509 [(set_attr "conds" "set")]
3510)
b11cae9e 3511
b11cae9e 3512(define_expand "extendhisi2"
c8f69309 3513 [(set (match_dup 2)
25f7a26e 3514 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 3515 (const_int 16)))
9c08d1fa 3516 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3517 (ashiftrt:SI (match_dup 2)
3518 (const_int 16)))]
cffb2a26 3519 "TARGET_EITHER"
b11cae9e 3520 "
cffb2a26 3521 {
a2cd141b 3522 if (GET_CODE (operands[1]) == MEM)
cffb2a26 3523 {
a2cd141b 3524 if (TARGET_THUMB)
3525 {
3526 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3527 DONE;
3528 }
3529 else if (arm_arch4)
3530 {
a2cd141b 3531 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3532 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3533 DONE;
3534 }
cffb2a26 3535 }
7bd8ccc9 3536
c1a66faf 3537 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 3538 {
3539 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3540 DONE;
3541 }
a2cd141b 3542
215b30b3 3543 if (!s_register_operand (operands[1], HImode))
cffb2a26 3544 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3545
a2cd141b 3546 if (arm_arch6)
cffb2a26 3547 {
a2cd141b 3548 if (TARGET_THUMB)
3549 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3550 else
3551 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3552 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3553
cffb2a26 3554 DONE;
3555 }
a2cd141b 3556
3557 operands[1] = gen_lowpart (SImode, operands[1]);
3558 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3559 }"
3560)
3561
a2cd141b 3562(define_insn "thumb_extendhisi2"
3563 [(set (match_operand:SI 0 "register_operand" "=l")
3564 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3565 (clobber (match_scratch:SI 2 "=&l"))]
3566 "TARGET_THUMB && !arm_arch6"
cffb2a26 3567 "*
3568 {
3569 rtx ops[4];
3570 rtx mem = XEXP (operands[1], 0);
3571
3572 /* This code used to try to use 'V', and fix the address only if it was
3573 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3574 range of QImode offsets, and offsettable_address_p does a QImode
3575 address check. */
3576
3577 if (GET_CODE (mem) == CONST)
3578 mem = XEXP (mem, 0);
3579
3580 if (GET_CODE (mem) == LABEL_REF)
3581 return \"ldr\\t%0, %1\";
3582
3583 if (GET_CODE (mem) == PLUS)
3584 {
3585 rtx a = XEXP (mem, 0);
3586 rtx b = XEXP (mem, 1);
3587
3588 if (GET_CODE (a) == LABEL_REF
3589 && GET_CODE (b) == CONST_INT)
3590 return \"ldr\\t%0, %1\";
3591
3592 if (GET_CODE (b) == REG)
3593 return \"ldrsh\\t%0, %1\";
3594
3595 ops[1] = a;
3596 ops[2] = b;
3597 }
3598 else
3599 {
3600 ops[1] = mem;
3601 ops[2] = const0_rtx;
3602 }
ed29c566 3603
3604 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 3605
3606 ops[0] = operands[0];
3607 ops[3] = operands[2];
3608 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3609 return \"\";
3610 }"
3611 [(set_attr "length" "4")
a2cd141b 3612 (set_attr "type" "load_byte")
cffb2a26 3613 (set_attr "pool_range" "1020")]
3614)
25f7a26e 3615
a2cd141b 3616;; We used to have an early-clobber on the scratch register here.
3617;; However, there's a bug somewhere in reload which means that this
3618;; can be partially ignored during spill allocation if the memory
ed29c566 3619;; address also needs reloading; this causes us to die later on when
a2cd141b 3620;; we try to verify the operands. Fortunately, we don't really need
3621;; the early-clobber: we can always use operand 0 if operand 2
3622;; overlaps the address.
3623(define_insn "*thumb_extendhisi2_insn_v6"
3624 [(set (match_operand:SI 0 "register_operand" "=l,l")
3625 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3626 (clobber (match_scratch:SI 2 "=X,l"))]
3627 "TARGET_THUMB && arm_arch6"
3628 "*
3629 {
3630 rtx ops[4];
3631 rtx mem;
3632
3633 if (which_alternative == 0)
3634 return \"sxth\\t%0, %1\";
3635
3636 mem = XEXP (operands[1], 0);
3637
3638 /* This code used to try to use 'V', and fix the address only if it was
3639 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3640 range of QImode offsets, and offsettable_address_p does a QImode
3641 address check. */
3642
3643 if (GET_CODE (mem) == CONST)
3644 mem = XEXP (mem, 0);
3645
3646 if (GET_CODE (mem) == LABEL_REF)
3647 return \"ldr\\t%0, %1\";
3648
3649 if (GET_CODE (mem) == PLUS)
3650 {
3651 rtx a = XEXP (mem, 0);
3652 rtx b = XEXP (mem, 1);
3653
3654 if (GET_CODE (a) == LABEL_REF
3655 && GET_CODE (b) == CONST_INT)
3656 return \"ldr\\t%0, %1\";
3657
3658 if (GET_CODE (b) == REG)
3659 return \"ldrsh\\t%0, %1\";
3660
3661 ops[1] = a;
3662 ops[2] = b;
3663 }
3664 else
3665 {
3666 ops[1] = mem;
3667 ops[2] = const0_rtx;
3668 }
3669
ed29c566 3670 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 3671
3672 ops[0] = operands[0];
3673 if (reg_mentioned_p (operands[2], ops[1]))
3674 ops[3] = ops[0];
3675 else
3676 ops[3] = operands[2];
3677 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3678 return \"\";
3679 }"
3680 [(set_attr "length" "2,4")
3681 (set_attr "type" "alu_shift,load_byte")
3682 (set_attr "pool_range" "*,1020")]
3683)
3684
25f7a26e 3685(define_expand "extendhisi2_mem"
eab14235 3686 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 3687 (set (match_dup 3)
eab14235 3688 (zero_extend:SI (match_dup 7)))
25f7a26e 3689 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3690 (set (match_operand:SI 0 "" "")
3691 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 3692 "TARGET_ARM"
25f7a26e 3693 "
215b30b3 3694 {
3695 rtx mem1, mem2;
3696 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3697
788fcce0 3698 mem1 = change_address (operands[1], QImode, addr);
3699 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 3700 operands[0] = gen_lowpart (SImode, operands[0]);
3701 operands[1] = mem1;
3702 operands[2] = gen_reg_rtx (SImode);
3703 operands[3] = gen_reg_rtx (SImode);
3704 operands[6] = gen_reg_rtx (SImode);
3705 operands[7] = mem2;
25f7a26e 3706
215b30b3 3707 if (BYTES_BIG_ENDIAN)
3708 {
3709 operands[4] = operands[2];
3710 operands[5] = operands[3];
3711 }
3712 else
3713 {
3714 operands[4] = operands[3];
3715 operands[5] = operands[2];
3716 }
3717 }"
3718)
b11cae9e 3719
a2cd141b 3720(define_insn "*arm_extendhisi2"
3721 [(set (match_operand:SI 0 "s_register_operand" "=r")
3722 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3723 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3724 "ldr%?sh\\t%0, %1"
a2cd141b 3725 [(set_attr "type" "load_byte")
0d66636f 3726 (set_attr "predicable" "yes")
cffb2a26 3727 (set_attr "pool_range" "256")
3728 (set_attr "neg_pool_range" "244")]
3729)
f7fbdd4a 3730
a2cd141b 3731(define_insn "*arm_extendhisi2_v6"
3732 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3733 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3734 "TARGET_ARM && arm_arch6"
3735 "@
3736 sxth%?\\t%0, %1
3737 ldr%?sh\\t%0, %1"
3738 [(set_attr "type" "alu_shift,load_byte")
3739 (set_attr "predicable" "yes")
3740 (set_attr "pool_range" "*,256")
3741 (set_attr "neg_pool_range" "*,244")]
3742)
3743
3744(define_insn "*arm_extendhisi2addsi"
3745 [(set (match_operand:SI 0 "s_register_operand" "=r")
3746 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3747 (match_operand:SI 2 "s_register_operand" "r")))]
3748 "TARGET_ARM && arm_arch6"
3749 "sxtah%?\\t%0, %2, %1"
3750)
3751
c8f69309 3752(define_expand "extendqihi2"
3753 [(set (match_dup 2)
f7fbdd4a 3754 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 3755 (const_int 24)))
9c08d1fa 3756 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 3757 (ashiftrt:SI (match_dup 2)
3758 (const_int 24)))]
cffb2a26 3759 "TARGET_ARM"
c8f69309 3760 "
215b30b3 3761 {
3762 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3763 {
3764 emit_insn (gen_rtx_SET (VOIDmode,
3765 operands[0],
3766 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3767 DONE;
3768 }
3769 if (!s_register_operand (operands[1], QImode))
3770 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3771 operands[0] = gen_lowpart (SImode, operands[0]);
3772 operands[1] = gen_lowpart (SImode, operands[1]);
3773 operands[2] = gen_reg_rtx (SImode);
3774 }"
3775)
f7fbdd4a 3776
3777(define_insn "*extendqihi_insn"
b4e8a300 3778 [(set (match_operand:HI 0 "s_register_operand" "=r")
3779 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
cffb2a26 3780 "TARGET_ARM && arm_arch4"
b4e8a300 3781 "ldr%?sb\\t%0, %1"
a2cd141b 3782 [(set_attr "type" "load_byte")
0d66636f 3783 (set_attr "predicable" "yes")
cffb2a26 3784 (set_attr "pool_range" "256")
3785 (set_attr "neg_pool_range" "244")]
3786)
3fc2009e 3787
b11cae9e 3788(define_expand "extendqisi2"
c8f69309 3789 [(set (match_dup 2)
3fc2009e 3790 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 3791 (const_int 24)))
9c08d1fa 3792 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3793 (ashiftrt:SI (match_dup 2)
3794 (const_int 24)))]
cffb2a26 3795 "TARGET_EITHER"
b11cae9e 3796 "
cffb2a26 3797 {
a2cd141b 3798 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3799 {
a2cd141b 3800 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 3801 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3802 DONE;
3803 }
a2cd141b 3804
215b30b3 3805 if (!s_register_operand (operands[1], QImode))
cffb2a26 3806 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 3807
a2cd141b 3808 if (arm_arch6)
3809 {
3810 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3811 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3812 DONE;
cffb2a26 3813 }
a2cd141b 3814
3815 operands[1] = gen_lowpart (SImode, operands[1]);
3816 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3817 }"
3818)
f7fbdd4a 3819
a2cd141b 3820(define_insn "*arm_extendqisi"
3821 [(set (match_operand:SI 0 "s_register_operand" "=r")
b4e8a300 3822 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
a2cd141b 3823 "TARGET_ARM && arm_arch4 && !arm_arch6"
b4e8a300 3824 "ldr%?sb\\t%0, %1"
a2cd141b 3825 [(set_attr "type" "load_byte")
0d66636f 3826 (set_attr "predicable" "yes")
cffb2a26 3827 (set_attr "pool_range" "256")
3828 (set_attr "neg_pool_range" "244")]
3829)
3fc2009e 3830
a2cd141b 3831(define_insn "*arm_extendqisi_v6"
3832 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
b4e8a300 3833 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
a2cd141b 3834 "TARGET_ARM && arm_arch6"
b4e8a300 3835 "@
3836 sxtb%?\\t%0, %1
3837 ldr%?sb\\t%0, %1"
a2cd141b 3838 [(set_attr "type" "alu_shift,load_byte")
3839 (set_attr "predicable" "yes")
a2cd141b 3840 (set_attr "pool_range" "*,256")
3841 (set_attr "neg_pool_range" "*,244")]
3842)
3843
3844(define_insn "*arm_extendqisi2addsi"
3845 [(set (match_operand:SI 0 "s_register_operand" "=r")
3846 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3847 (match_operand:SI 2 "s_register_operand" "r")))]
3848 "TARGET_ARM && arm_arch6"
3849 "sxtab%?\\t%0, %2, %1"
3850 [(set_attr "type" "alu_shift")
3851 (set_attr "predicable" "yes")]
3852)
3853
a2cd141b 3854(define_insn "*thumb_extendqisi2"
3855 [(set (match_operand:SI 0 "register_operand" "=l,l")
3856 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3857 "TARGET_THUMB && !arm_arch6"
cffb2a26 3858 "*
3859 {
3860 rtx ops[3];
3861 rtx mem = XEXP (operands[1], 0);
3862
3863 if (GET_CODE (mem) == CONST)
3864 mem = XEXP (mem, 0);
3865
3866 if (GET_CODE (mem) == LABEL_REF)
3867 return \"ldr\\t%0, %1\";
3868
3869 if (GET_CODE (mem) == PLUS
3870 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3871 return \"ldr\\t%0, %1\";
3872
3873 if (which_alternative == 0)
3874 return \"ldrsb\\t%0, %1\";
3875
3876 ops[0] = operands[0];
3877
3878 if (GET_CODE (mem) == PLUS)
3879 {
3880 rtx a = XEXP (mem, 0);
3881 rtx b = XEXP (mem, 1);
3882
3883 ops[1] = a;
3884 ops[2] = b;
3885
3886 if (GET_CODE (a) == REG)
3887 {
3888 if (GET_CODE (b) == REG)
3889 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3890 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 3891 {
3892 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3893 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3894 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3895 }
cffb2a26 3896 else
3897 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3898 }
cffb2a26 3899 else
3900 {
ed29c566 3901 gcc_assert (GET_CODE (b) == REG);
cffb2a26 3902 if (REGNO (b) == REGNO (ops[0]))
215b30b3 3903 {
3904 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3905 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3906 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3907 }
cffb2a26 3908 else
3909 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3910 }
3911 }
3912 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3913 {
215b30b3 3914 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3915 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3916 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 3917 }
3918 else
3919 {
3920 ops[1] = mem;
3921 ops[2] = const0_rtx;
3922
3923 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3924 }
3925 return \"\";
3926 }"
3927 [(set_attr "length" "2,6")
a2cd141b 3928 (set_attr "type" "load_byte,load_byte")
cffb2a26 3929 (set_attr "pool_range" "32,32")]
3930)
3931
a2cd141b 3932(define_insn "*thumb_extendqisi2_v6"
3933 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3934 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3935 "TARGET_THUMB && arm_arch6"
3936 "*
3937 {
3938 rtx ops[3];
3939 rtx mem;
3940
3941 if (which_alternative == 0)
3942 return \"sxtb\\t%0, %1\";
3943
3944 mem = XEXP (operands[1], 0);
3945
3946 if (GET_CODE (mem) == CONST)
3947 mem = XEXP (mem, 0);
3948
3949 if (GET_CODE (mem) == LABEL_REF)
3950 return \"ldr\\t%0, %1\";
3951
3952 if (GET_CODE (mem) == PLUS
3953 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3954 return \"ldr\\t%0, %1\";
3955
3956 if (which_alternative == 0)
3957 return \"ldrsb\\t%0, %1\";
3958
3959 ops[0] = operands[0];
3960
3961 if (GET_CODE (mem) == PLUS)
3962 {
3963 rtx a = XEXP (mem, 0);
3964 rtx b = XEXP (mem, 1);
3965
3966 ops[1] = a;
3967 ops[2] = b;
3968
3969 if (GET_CODE (a) == REG)
3970 {
3971 if (GET_CODE (b) == REG)
3972 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3973 else if (REGNO (a) == REGNO (ops[0]))
3974 {
3975 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3976 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3977 }
3978 else
3979 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3980 }
a2cd141b 3981 else
3982 {
ed29c566 3983 gcc_assert (GET_CODE (b) == REG);
a2cd141b 3984 if (REGNO (b) == REGNO (ops[0]))
3985 {
3986 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3987 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3988 }
3989 else
3990 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3991 }
3992 }
3993 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3994 {
3995 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3996 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3997 }
3998 else
3999 {
4000 ops[1] = mem;
4001 ops[2] = const0_rtx;
4002
4003 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4004 }
4005 return \"\";
4006 }"
4007 [(set_attr "length" "2,2,4")
4008 (set_attr "type" "alu_shift,load_byte,load_byte")
4009 (set_attr "pool_range" "*,32,32")]
4010)
4011
caedf871 4012(define_expand "extendsfdf2"
4013 [(set (match_operand:DF 0 "s_register_operand" "")
4014 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 4015 "TARGET_ARM && TARGET_HARD_FLOAT"
caedf871 4016 ""
4017)
b11cae9e 4018\f
4019;; Move insns (including loads and stores)
4020
4021;; XXX Just some ideas about movti.
9c08d1fa 4022;; I don't think these are a good idea on the arm, there just aren't enough
4023;; registers
b11cae9e 4024;;(define_expand "loadti"
9c08d1fa 4025;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4026;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4027;; "" "")
4028
4029;;(define_expand "storeti"
4030;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4031;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4032;; "" "")
4033
4034;;(define_expand "movti"
4035;; [(set (match_operand:TI 0 "general_operand" "")
4036;; (match_operand:TI 1 "general_operand" ""))]
4037;; ""
4038;; "
4039;;{
4040;; rtx insn;
4041;;
4042;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4043;; operands[1] = copy_to_reg (operands[1]);
4044;; if (GET_CODE (operands[0]) == MEM)
4045;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4046;; else if (GET_CODE (operands[1]) == MEM)
4047;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4048;; else
4049;; FAIL;
4050;;
4051;; emit_insn (insn);
4052;; DONE;
4053;;}")
4054
a2f10574 4055;; Recognize garbage generated above.
b11cae9e 4056
4057;;(define_insn ""
4058;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4059;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4060;; ""
4061;; "*
4062;; {
4063;; register mem = (which_alternative < 3);
0d66636f 4064;; register const char *template;
b11cae9e 4065;;
4066;; operands[mem] = XEXP (operands[mem], 0);
4067;; switch (which_alternative)
4068;; {
4069;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4070;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4071;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4072;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4073;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4074;; case 5: template = \"stmia\\t%0, %M1\"; break;
4075;; }
e2348bcb 4076;; output_asm_insn (template, operands);
4077;; return \"\";
b11cae9e 4078;; }")
4079
cffb2a26 4080(define_expand "movdi"
4081 [(set (match_operand:DI 0 "general_operand" "")
4082 (match_operand:DI 1 "general_operand" ""))]
4083 "TARGET_EITHER"
4084 "
4085 if (TARGET_THUMB)
4086 {
215b30b3 4087 if (!no_new_pseudos)
cffb2a26 4088 {
4089 if (GET_CODE (operands[0]) != REG)
4090 operands[1] = force_reg (DImode, operands[1]);
4091 }
4092 }
4093 "
4094)
b11cae9e 4095
cffb2a26 4096(define_insn "*arm_movdi"
d51f92df 4097 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4098 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4099 "TARGET_ARM
4100 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4101 && !TARGET_IWMMXT"
b11cae9e 4102 "*
d51f92df 4103 switch (which_alternative)
4104 {
4105 case 0:
4106 case 1:
4107 case 2:
4108 return \"#\";
4109 default:
4110 return output_move_double (operands);
4111 }
cffb2a26 4112 "
359a6e9f 4113 [(set_attr "length" "8,12,16,8,8")
4114 (set_attr "type" "*,*,*,load2,store2")
4115 (set_attr "pool_range" "*,*,*,1020,*")
4116 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4117)
4118
d51f92df 4119(define_split
4120 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4121 (match_operand:ANY64 1 "const_double_operand" ""))]
4122 "TARGET_ARM
4123 && reload_completed
4124 && (arm_const_double_inline_cost (operands[1])
4125 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4126 [(const_int 0)]
4127 "
4128 arm_split_constant (SET, SImode, curr_insn,
4129 INTVAL (gen_lowpart (SImode, operands[1])),
4130 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4131 arm_split_constant (SET, SImode, curr_insn,
4132 INTVAL (gen_highpart_mode (SImode,
4133 GET_MODE (operands[0]),
4134 operands[1])),
4135 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4136 DONE;
4137 "
4138)
4139
e5ba9289 4140; If optimizing for size, or if we have load delay slots, then
4141; we want to split the constant into two separate operations.
4142; In both cases this may split a trivial part into a single data op
4143; leaving a single complex constant to load. We can also get longer
4144; offsets in a LDR which means we get better chances of sharing the pool
4145; entries. Finally, we can normally do a better job of scheduling
4146; LDR instructions than we can with LDM.
4147; This pattern will only match if the one above did not.
4148(define_split
4149 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4150 (match_operand:ANY64 1 "const_double_operand" ""))]
4151 "TARGET_ARM && reload_completed
4152 && arm_const_double_by_parts (operands[1])"
4153 [(set (match_dup 0) (match_dup 1))
4154 (set (match_dup 2) (match_dup 3))]
4155 "
4156 operands[2] = gen_highpart (SImode, operands[0]);
4157 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4158 operands[1]);
4159 operands[0] = gen_lowpart (SImode, operands[0]);
4160 operands[1] = gen_lowpart (SImode, operands[1]);
4161 "
4162)
4163
d51f92df 4164(define_split
4165 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4166 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4167 "TARGET_EITHER && reload_completed"
4168 [(set (match_dup 0) (match_dup 1))
4169 (set (match_dup 2) (match_dup 3))]
4170 "
4171 operands[2] = gen_highpart (SImode, operands[0]);
4172 operands[3] = gen_highpart (SImode, operands[1]);
4173 operands[0] = gen_lowpart (SImode, operands[0]);
4174 operands[1] = gen_lowpart (SImode, operands[1]);
4175
4176 /* Handle a partial overlap. */
4177 if (rtx_equal_p (operands[0], operands[3]))
4178 {
4179 rtx tmp0 = operands[0];
4180 rtx tmp1 = operands[1];
4181
4182 operands[0] = operands[2];
4183 operands[1] = operands[3];
4184 operands[2] = tmp0;
4185 operands[3] = tmp1;
4186 }
4187 "
4188)
4189
a8a3b539 4190;; We can't actually do base+index doubleword loads if the index and
4191;; destination overlap. Split here so that we at least have chance to
4192;; schedule.
4193(define_split
4194 [(set (match_operand:DI 0 "s_register_operand" "")
4195 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4196 (match_operand:SI 2 "s_register_operand" ""))))]
4197 "TARGET_LDRD
4198 && reg_overlap_mentioned_p (operands[0], operands[1])
4199 && reg_overlap_mentioned_p (operands[0], operands[2])"
4200 [(set (match_dup 4)
4201 (plus:SI (match_dup 1)
4202 (match_dup 2)))
4203 (set (match_dup 0)
4204 (mem:DI (match_dup 4)))]
4205 "
4206 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4207 "
4208)
4209
cffb2a26 4210;;; ??? This should have alternatives for constants.
4211;;; ??? This was originally identical to the movdf_insn pattern.
4212;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4213;;; thumb_reorg with a memory reference.
4214(define_insn "*thumb_movdi_insn"
215b30b3 4215 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4216 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
cffb2a26 4217 "TARGET_THUMB
a2cd141b 4218 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4219 && ( register_operand (operands[0], DImode)
4220 || register_operand (operands[1], DImode))"
4221 "*
4222 {
4223 switch (which_alternative)
4224 {
4225 default:
4226 case 0:
4227 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4228 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4229 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4230 case 1:
4231 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4232 case 2:
4233 operands[1] = GEN_INT (- INTVAL (operands[1]));
4234 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4235 case 3:
4236 return \"ldmia\\t%1, {%0, %H0}\";
4237 case 4:
4238 return \"stmia\\t%0, {%1, %H1}\";
4239 case 5:
4240 return thumb_load_double_from_address (operands);
4241 case 6:
1a83b3ff 4242 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4243 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4244 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4245 return \"\";
4246 case 7:
4247 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4248 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4249 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4250 }
4251 }"
4252 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4253 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4254 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4255)
b11cae9e 4256
9c08d1fa 4257(define_expand "movsi"
4258 [(set (match_operand:SI 0 "general_operand" "")
4259 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4260 "TARGET_EITHER"
9c08d1fa 4261 "
cffb2a26 4262 if (TARGET_ARM)
9c08d1fa 4263 {
674a8f0b 4264 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4265 if (GET_CODE (operands[0]) == MEM)
4266 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4267 if (arm_general_register_operand (operands[0], SImode)
4268 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4269 && !(const_ok_for_arm (INTVAL (operands[1]))
4270 || const_ok_for_arm (~INTVAL (operands[1]))))
4271 {
96f57e36 4272 arm_split_constant (SET, SImode, NULL_RTX,
4273 INTVAL (operands[1]), operands[0], NULL_RTX,
615caa51 4274 optimize && !no_new_pseudos);
cffb2a26 4275 DONE;
4276 }
4277 }
674a8f0b 4278 else /* TARGET_THUMB.... */
cffb2a26 4279 {
215b30b3 4280 if (!no_new_pseudos)
cffb2a26 4281 {
4282 if (GET_CODE (operands[0]) != REG)
4283 operands[1] = force_reg (SImode, operands[1]);
4284 }
9c08d1fa 4285 }
f655717d 4286
4287 /* Recognize the case where operand[1] is a reference to thread-local
4288 data and load its address to a register. */
4289 if (arm_tls_referenced_p (operands[1]))
4290 {
4291 rtx tmp = operands[1];
4292 rtx addend = NULL;
4293
4294 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4295 {
4296 addend = XEXP (XEXP (tmp, 0), 1);
4297 tmp = XEXP (XEXP (tmp, 0), 0);
4298 }
4299
4300 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4301 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4302
4303 tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4304 if (addend)
4305 {
4306 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4307 tmp = force_operand (tmp, operands[0]);
4308 }
4309 operands[1] = tmp;
4310 }
4311 else if (flag_pic
4312 && (CONSTANT_P (operands[1])
4313 || symbol_mentioned_p (operands[1])
4314 || label_mentioned_p (operands[1])))
4315 operands[1] = legitimize_pic_address (operands[1], SImode,
4316 (no_new_pseudos ? operands[0] : 0));
215b30b3 4317 "
4318)
9c08d1fa 4319
cffb2a26 4320(define_insn "*arm_movsi_insn"
215b30b3 4321 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4322 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
755eb2b4 4323 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 4324 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 4325 && ( register_operand (operands[0], SImode)
4326 || register_operand (operands[1], SImode))"
f7fbdd4a 4327 "@
4328 mov%?\\t%0, %1
4329 mvn%?\\t%0, #%B1
4330 ldr%?\\t%0, %1
4331 str%?\\t%1, %0"
a2cd141b 4332 [(set_attr "type" "*,*,load1,store1")
0d66636f 4333 (set_attr "predicable" "yes")
cffb2a26 4334 (set_attr "pool_range" "*,*,4096,*")
4335 (set_attr "neg_pool_range" "*,*,4084,*")]
4336)
87b22bf7 4337
4338(define_split
a2cd141b 4339 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 4340 (match_operand:SI 1 "const_int_operand" ""))]
cffb2a26 4341 "TARGET_ARM
215b30b3 4342 && (!(const_ok_for_arm (INTVAL (operands[1]))
4343 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4344 [(clobber (const_int 0))]
4345 "
96f57e36 4346 arm_split_constant (SET, SImode, NULL_RTX,
4347 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 4348 DONE;
215b30b3 4349 "
4350)
9c08d1fa 4351
cffb2a26 4352(define_insn "*thumb_movsi_insn"
215b30b3 4353 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4354 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
cffb2a26 4355 "TARGET_THUMB
4356 && ( register_operand (operands[0], SImode)
4357 || register_operand (operands[1], SImode))"
4358 "@
4359 mov %0, %1
4360 mov %0, %1
4361 #
4362 #
4363 ldmia\\t%1, {%0}
4364 stmia\\t%0, {%1}
4365 ldr\\t%0, %1
4366 str\\t%1, %0
4367 mov\\t%0, %1"
4368 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 4369 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 4370 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4371)
4372
4373(define_split
4374 [(set (match_operand:SI 0 "register_operand" "")
4375 (match_operand:SI 1 "const_int_operand" ""))]
4376 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4377 [(set (match_dup 0) (match_dup 1))
4378 (set (match_dup 0) (neg:SI (match_dup 0)))]
4379 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4380)
4381
4382(define_split
4383 [(set (match_operand:SI 0 "register_operand" "")
4384 (match_operand:SI 1 "const_int_operand" ""))]
4385 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4386 [(set (match_dup 0) (match_dup 1))
4387 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4388 "
4389 {
4390 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4391 unsigned HOST_WIDE_INT mask = 0xff;
4392 int i;
4393
4394 for (i = 0; i < 25; i++)
4395 if ((val & (mask << i)) == val)
4396 break;
4397
f5b3169c 4398 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4399 if (i == 0)
4400 FAIL;
4401
4402 operands[1] = GEN_INT (val >> i);
4403 operands[2] = GEN_INT (i);
4404 }"
4405)
4406
67336bcf 4407;; When generating pic, we need to load the symbol offset into a register.
4408;; So that the optimizer does not confuse this with a normal symbol load
4409;; we use an unspec. The offset will be loaded from a constant pool entry,
4410;; since that is the only type of relocation we can use.
4411
4412;; The rather odd constraints on the following are to force reload to leave
4413;; the insn alone, and to force the minipool generation pass to then move
4414;; the GOT symbol to memory.
849170fd 4415
8c4d8060 4416(define_insn "pic_load_addr_arm"
849170fd 4417 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4418 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4419 "TARGET_ARM && flag_pic"
67336bcf 4420 "ldr%?\\t%0, %1"
a2cd141b 4421 [(set_attr "type" "load1")
8c4d8060 4422 (set (attr "pool_range") (const_int 4096))
4423 (set (attr "neg_pool_range") (const_int 4084))]
4424)
4425
4426(define_insn "pic_load_addr_thumb"
4427 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4428 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4429 "TARGET_THUMB && flag_pic"
4430 "ldr\\t%0, %1"
a2cd141b 4431 [(set_attr "type" "load1")
8c4d8060 4432 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4433)
849170fd 4434
4435;; This variant is used for AOF assembly, since it needs to mention the
4436;; pic register in the rtl.
4437(define_expand "pic_load_addr_based"
7db9af5d 4438 [(set (match_operand:SI 0 "s_register_operand" "")
e1159bbe 4439 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
cffb2a26 4440 "TARGET_ARM && flag_pic"
4441 "operands[2] = pic_offset_table_rtx;"
4442)
849170fd 4443
4444(define_insn "*pic_load_addr_based_insn"
4445 [(set (match_operand:SI 0 "s_register_operand" "=r")
4446 (unspec:SI [(match_operand 1 "" "")
e1159bbe 4447 (match_operand 2 "s_register_operand" "r")]
4448 UNSPEC_PIC_SYM))]
cffb2a26 4449 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
849170fd 4450 "*
4451#ifdef AOF_ASSEMBLER
4452 operands[1] = aof_pic_entry (operands[1]);
4453#endif
4454 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4455 return \"\";
cffb2a26 4456 "
a2cd141b 4457 [(set_attr "type" "load1")
cffb2a26 4458 (set (attr "pool_range")
4459 (if_then_else (eq_attr "is_thumb" "yes")
4460 (const_int 1024)
4461 (const_int 4096)))
4462 (set (attr "neg_pool_range")
4463 (if_then_else (eq_attr "is_thumb" "yes")
4464 (const_int 0)
4465 (const_int 4084)))]
4466)
4467
4468(define_insn "pic_add_dot_plus_four"
15d5d060 4469 [(set (match_operand:SI 0 "register_operand" "=r")
4470 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
2c96dc5a 4471 (const (plus:SI (pc) (const_int 4))))]
4472 UNSPEC_PIC_BASE))
6cdcb15c 4473 (use (match_operand 2 "" ""))]
f655717d 4474 "TARGET_THUMB"
cffb2a26 4475 "*
6cdcb15c 4476 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4477 INTVAL (operands[2]));
cffb2a26 4478 return \"add\\t%0, %|pc\";
4479 "
4480 [(set_attr "length" "2")]
4481)
849170fd 4482
4483(define_insn "pic_add_dot_plus_eight"
15d5d060 4484 [(set (match_operand:SI 0 "register_operand" "=r")
4485 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
2c96dc5a 4486 (const (plus:SI (pc) (const_int 8))))]
4487 UNSPEC_PIC_BASE))
6cdcb15c 4488 (use (match_operand 2 "" ""))]
f655717d 4489 "TARGET_ARM"
c4034607 4490 "*
6cdcb15c 4491 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4492 INTVAL (operands[2]));
15d5d060 4493 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 4494 "
0d66636f 4495 [(set_attr "predicable" "yes")]
cffb2a26 4496)
849170fd 4497
f655717d 4498(define_insn "tls_load_dot_plus_eight"
4499 [(set (match_operand:SI 0 "register_operand" "+r")
4500 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4501 (const (plus:SI (pc) (const_int 8))))]
4502 UNSPEC_PIC_BASE)))
6cdcb15c 4503 (use (match_operand 2 "" ""))]
f655717d 4504 "TARGET_ARM"
4505 "*
6cdcb15c 4506 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4507 INTVAL (operands[2]));
f655717d 4508 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4509 "
4510 [(set_attr "predicable" "yes")]
4511)
4512
4513;; PIC references to local variables can generate pic_add_dot_plus_eight
4514;; followed by a load. These sequences can be crunched down to
4515;; tls_load_dot_plus_eight by a peephole.
4516
4517(define_peephole2
4518 [(parallel [(set (match_operand:SI 0 "register_operand" "")
15d5d060 4519 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
f655717d 4520 (const (plus:SI (pc) (const_int 8))))]
4521 UNSPEC_PIC_BASE))
4522 (use (label_ref (match_operand 1 "" "")))])
4523 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4524 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
15d5d060 4525 [(parallel [(set (match_dup 2)
4526 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
f655717d 4527 (const (plus:SI (pc) (const_int 8))))]
4528 UNSPEC_PIC_BASE)))
15d5d060 4529 (use (label_ref (match_dup 1)))])]
f655717d 4530 ""
4531)
4532
95373f08 4533(define_expand "builtin_setjmp_receiver"
4534 [(label_ref (match_operand 0 "" ""))]
4535 "flag_pic"
4536 "
4537{
b935b306 4538 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4539 register. */
4540 arm_load_pic_register (3);
95373f08 4541 DONE;
4542}")
4543
9c08d1fa 4544;; If copying one reg to another we can set the condition codes according to
4545;; its value. Such a move is common after a return from subroutine and the
4546;; result is being tested against zero.
4547
f7fbdd4a 4548(define_insn "*movsi_compare0"
bd5b4116 4549 [(set (reg:CC CC_REGNUM)
cffb2a26 4550 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4551 (const_int 0)))
4552 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4553 (match_dup 1))]
4554 "TARGET_ARM"
e2348bcb 4555 "@
40dbec34 4556 cmp%?\\t%0, #0
4557 sub%?s\\t%0, %1, #0"
cffb2a26 4558 [(set_attr "conds" "set")]
4559)
b11cae9e 4560
b11cae9e 4561;; Subroutine to store a half word from a register into memory.
4562;; Operand 0 is the source register (HImode)
c8f69309 4563;; Operand 1 is the destination address in a register (SImode)
b11cae9e 4564
9c08d1fa 4565;; In both this routine and the next, we must be careful not to spill
01cc3b75 4566;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 4567;; can generate unrecognizable rtl.
4568
b11cae9e 4569(define_expand "storehi"
c8f69309 4570 [;; store the low byte
f082f1c4 4571 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 4572 ;; extract the high byte
c8f69309 4573 (set (match_dup 2)
4574 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 4575 ;; store the high byte
787f8210 4576 (set (match_dup 4) (match_dup 5))]
cffb2a26 4577 "TARGET_ARM"
b11cae9e 4578 "
215b30b3 4579 {
537ffcfc 4580 rtx op1 = operands[1];
4581 rtx addr = XEXP (op1, 0);
215b30b3 4582 enum rtx_code code = GET_CODE (addr);
4583
4584 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4585 || code == MINUS)
537ffcfc 4586 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 4587
537ffcfc 4588 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4589 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4590 operands[3] = gen_lowpart (QImode, operands[0]);
4591 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 4592 operands[2] = gen_reg_rtx (SImode);
4593 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4594 }"
4595)
b11cae9e 4596
c7597b5d 4597(define_expand "storehi_bigend"
f082f1c4 4598 [(set (match_dup 4) (match_dup 3))
c7597b5d 4599 (set (match_dup 2)
4600 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 4601 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 4602 "TARGET_ARM"
b11cae9e 4603 "
215b30b3 4604 {
537ffcfc 4605 rtx op1 = operands[1];
4606 rtx addr = XEXP (op1, 0);
215b30b3 4607 enum rtx_code code = GET_CODE (addr);
4608
4609 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4610 || code == MINUS)
537ffcfc 4611 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 4612
537ffcfc 4613 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4614 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4615 operands[3] = gen_lowpart (QImode, operands[0]);
4616 operands[0] = gen_lowpart (SImode, operands[0]);
4617 operands[2] = gen_reg_rtx (SImode);
787f8210 4618 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4619 }"
4620)
c7597b5d 4621
4622;; Subroutine to store a half word integer constant into memory.
4623(define_expand "storeinthi"
f082f1c4 4624 [(set (match_operand 0 "" "")
787f8210 4625 (match_operand 1 "" ""))
9e8503e6 4626 (set (match_dup 3) (match_dup 2))]
cffb2a26 4627 "TARGET_ARM"
c7597b5d 4628 "
215b30b3 4629 {
4630 HOST_WIDE_INT value = INTVAL (operands[1]);
4631 rtx addr = XEXP (operands[0], 0);
537ffcfc 4632 rtx op0 = operands[0];
215b30b3 4633 enum rtx_code code = GET_CODE (addr);
c7597b5d 4634
215b30b3 4635 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4636 || code == MINUS)
537ffcfc 4637 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 4638
215b30b3 4639 operands[1] = gen_reg_rtx (SImode);
4640 if (BYTES_BIG_ENDIAN)
4641 {
4642 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4643 if ((value & 255) == ((value >> 8) & 255))
4644 operands[2] = operands[1];
4645 else
4646 {
4647 operands[2] = gen_reg_rtx (SImode);
4648 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4649 }
4650 }
4651 else
4652 {
4653 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4654 if ((value & 255) == ((value >> 8) & 255))
4655 operands[2] = operands[1];
4656 else
4657 {
4658 operands[2] = gen_reg_rtx (SImode);
4659 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4660 }
4661 }
c7597b5d 4662
537ffcfc 4663 operands[3] = adjust_address (op0, QImode, 1);
e513d163 4664 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 4665 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 4666 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 4667 }"
4668)
b11cae9e 4669
f7fbdd4a 4670(define_expand "storehi_single_op"
4671 [(set (match_operand:HI 0 "memory_operand" "")
4672 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4673 "TARGET_ARM && arm_arch4"
f7fbdd4a 4674 "
215b30b3 4675 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 4676 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 4677 "
4678)
f7fbdd4a 4679
b11cae9e 4680(define_expand "movhi"
4681 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 4682 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4683 "TARGET_EITHER"
b11cae9e 4684 "
cffb2a26 4685 if (TARGET_ARM)
b11cae9e 4686 {
215b30b3 4687 if (!no_new_pseudos)
cffb2a26 4688 {
4689 if (GET_CODE (operands[0]) == MEM)
b11cae9e 4690 {
cffb2a26 4691 if (arm_arch4)
4692 {
4693 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4694 DONE;
4695 }
4696 if (GET_CODE (operands[1]) == CONST_INT)
4697 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 4698 else
cffb2a26 4699 {
4700 if (GET_CODE (operands[1]) == MEM)
4701 operands[1] = force_reg (HImode, operands[1]);
4702 if (BYTES_BIG_ENDIAN)
4703 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4704 else
4705 emit_insn (gen_storehi (operands[1], operands[0]));
4706 }
4707 DONE;
b11cae9e 4708 }
cffb2a26 4709 /* Sign extend a constant, and keep it in an SImode reg. */
4710 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 4711 {
cffb2a26 4712 rtx reg = gen_reg_rtx (SImode);
4713 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4714
4715 /* If the constant is already valid, leave it alone. */
215b30b3 4716 if (!const_ok_for_arm (val))
cffb2a26 4717 {
4718 /* If setting all the top bits will make the constant
4719 loadable in a single instruction, then set them.
4720 Otherwise, sign extend the number. */
4721
215b30b3 4722 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 4723 val |= ~0xffff;
4724 else if (val & 0x8000)
4725 val |= ~0xffff;
4726 }
4727
4728 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 4729 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 4730 }
615caa51 4731 else if (arm_arch4 && optimize && !no_new_pseudos
0045890a 4732 && GET_CODE (operands[1]) == MEM)
4733 {
4734 rtx reg = gen_reg_rtx (SImode);
4735
4736 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4737 operands[1] = gen_lowpart (HImode, reg);
4738 }
215b30b3 4739 else if (!arm_arch4)
f7fbdd4a 4740 {
cffb2a26 4741 if (GET_CODE (operands[1]) == MEM)
4742 {
c1a66faf 4743 rtx base;
4744 rtx offset = const0_rtx;
4745 rtx reg = gen_reg_rtx (SImode);
4746
4747 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4748 || (GET_CODE (base) == PLUS
4749 && (GET_CODE (offset = XEXP (base, 1))
4750 == CONST_INT)
4751 && ((INTVAL(offset) & 1) != 1)
4752 && GET_CODE (base = XEXP (base, 0)) == REG))
4753 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 4754 {
c1a66faf 4755 rtx new;
4756
788fcce0 4757 new = widen_memory_access (operands[1], SImode,
4758 ((INTVAL (offset) & ~3)
4759 - INTVAL (offset)));
c1a66faf 4760 emit_insn (gen_movsi (reg, new));
4761 if (((INTVAL (offset) & 2) != 0)
4762 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4763 {
4764 rtx reg2 = gen_reg_rtx (SImode);
4765
4766 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4767 reg = reg2;
4768 }
206ee9a2 4769 }
c1a66faf 4770 else
4771 emit_insn (gen_movhi_bytes (reg, operands[1]));
4772
4773 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 4774 }
4775 }
4776 }
674a8f0b 4777 /* Handle loading a large integer during reload. */
cffb2a26 4778 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4779 && !const_ok_for_arm (INTVAL (operands[1]))
4780 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 4781 {
4782 /* Writing a constant to memory needs a scratch, which should
4783 be handled with SECONDARY_RELOADs. */
ed29c566 4784 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 4785
4786 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4787 emit_insn (gen_movsi (operands[0], operands[1]));
4788 DONE;
4789 }
4790 }
4791 else /* TARGET_THUMB */
4792 {
215b30b3 4793 if (!no_new_pseudos)
cffb2a26 4794 {
6cffc037 4795 if (GET_CODE (operands[1]) == CONST_INT)
4796 {
4797 rtx reg = gen_reg_rtx (SImode);
4798
4799 emit_insn (gen_movsi (reg, operands[1]));
4800 operands[1] = gen_lowpart (HImode, reg);
4801 }
cffb2a26 4802
4803 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4804 happen if we are passed a SP (never OK for HImode/QImode) or
4805 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4806 HImode/QImode) relative address. */
cffb2a26 4807 /* ??? This should perhaps be fixed elsewhere, for instance, in
4808 fixup_stack_1, by checking for other kinds of invalid addresses,
4809 e.g. a bare reference to a virtual register. This may confuse the
4810 alpha though, which must handle this case differently. */
4811 if (GET_CODE (operands[0]) == MEM
215b30b3 4812 && !memory_address_p (GET_MODE (operands[0]),
4813 XEXP (operands[0], 0)))
537ffcfc 4814 operands[0]
4815 = replace_equiv_address (operands[0],
4816 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 4817
4818 if (GET_CODE (operands[1]) == MEM
215b30b3 4819 && !memory_address_p (GET_MODE (operands[1]),
4820 XEXP (operands[1], 0)))
537ffcfc 4821 operands[1]
4822 = replace_equiv_address (operands[1],
4823 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 4824
4825 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4826 {
4827 rtx reg = gen_reg_rtx (SImode);
4828
4829 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4830 operands[1] = gen_lowpart (HImode, reg);
4831 }
4832
4833 if (GET_CODE (operands[0]) == MEM)
4834 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 4835 }
cffb2a26 4836 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4837 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
cffb2a26 4838 {
6cffc037 4839 /* Handle loading a large integer during reload. */
4840
cffb2a26 4841 /* Writing a constant to memory needs a scratch, which should
4842 be handled with SECONDARY_RELOADs. */
ed29c566 4843 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 4844
1a83b3ff 4845 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 4846 emit_insn (gen_movsi (operands[0], operands[1]));
4847 DONE;
4848 }
b11cae9e 4849 }
cffb2a26 4850 "
4851)
4852
4853(define_insn "*thumb_movhi_insn"
a941568e 4854 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4855 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
cffb2a26 4856 "TARGET_THUMB
4857 && ( register_operand (operands[0], HImode)
4858 || register_operand (operands[1], HImode))"
4859 "*
4860 switch (which_alternative)
d79300ac 4861 {
cffb2a26 4862 case 0: return \"add %0, %1, #0\";
4863 case 2: return \"strh %1, %0\";
4864 case 3: return \"mov %0, %1\";
4865 case 4: return \"mov %0, %1\";
4866 case 5: return \"mov %0, %1\";
ed29c566 4867 default: gcc_unreachable ();
cffb2a26 4868 case 1:
4869 /* The stack pointer can end up being taken as an index register.
4870 Catch this case here and deal with it. */
4871 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4872 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4873 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4874 {
4875 rtx ops[2];
4876 ops[0] = operands[0];
4877 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4878
4879 output_asm_insn (\"mov %0, %1\", ops);
4880
4881 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4882
4883 }
4884 return \"ldrh %0, %1\";
4885 }"
4886 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 4887 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 4888)
d79300ac 4889
b11cae9e 4890
25f7a26e 4891(define_expand "movhi_bytes"
eab14235 4892 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4893 (set (match_dup 3)
eab14235 4894 (zero_extend:SI (match_dup 6)))
25f7a26e 4895 (set (match_operand:SI 0 "" "")
4896 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 4897 "TARGET_ARM"
25f7a26e 4898 "
215b30b3 4899 {
4900 rtx mem1, mem2;
4901 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4902
788fcce0 4903 mem1 = change_address (operands[1], QImode, addr);
4904 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4905 operands[0] = gen_lowpart (SImode, operands[0]);
4906 operands[1] = mem1;
4907 operands[2] = gen_reg_rtx (SImode);
4908 operands[3] = gen_reg_rtx (SImode);
4909 operands[6] = mem2;
25f7a26e 4910
215b30b3 4911 if (BYTES_BIG_ENDIAN)
4912 {
4913 operands[4] = operands[2];
4914 operands[5] = operands[3];
4915 }
4916 else
4917 {
4918 operands[4] = operands[3];
4919 operands[5] = operands[2];
4920 }
4921 }"
4922)
25f7a26e 4923
c7597b5d 4924(define_expand "movhi_bigend"
4925 [(set (match_dup 2)
4926 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4927 (const_int 16)))
4928 (set (match_dup 3)
4929 (ashiftrt:SI (match_dup 2) (const_int 16)))
4930 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 4931 (match_dup 4))]
cffb2a26 4932 "TARGET_ARM"
c7597b5d 4933 "
4934 operands[2] = gen_reg_rtx (SImode);
4935 operands[3] = gen_reg_rtx (SImode);
787f8210 4936 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 4937 "
4938)
b11cae9e 4939
a2f10574 4940;; Pattern to recognize insn generated default case above
f7fbdd4a 4941(define_insn "*movhi_insn_arch4"
cffb2a26 4942 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 4943 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 4944 "TARGET_ARM
4945 && arm_arch4
f7fbdd4a 4946 && (GET_CODE (operands[1]) != CONST_INT
4947 || const_ok_for_arm (INTVAL (operands[1]))
4948 || const_ok_for_arm (~INTVAL (operands[1])))"
4949 "@
4950 mov%?\\t%0, %1\\t%@ movhi
4951 mvn%?\\t%0, #%B1\\t%@ movhi
aed179ae 4952 str%?h\\t%1, %0\\t%@ movhi
cffb2a26 4953 ldr%?h\\t%0, %1\\t%@ movhi"
a2cd141b 4954 [(set_attr "type" "*,*,store1,load1")
0d66636f 4955 (set_attr "predicable" "yes")
cffb2a26 4956 (set_attr "pool_range" "*,*,*,256")
4957 (set_attr "neg_pool_range" "*,*,*,244")]
4958)
f7fbdd4a 4959
f7fbdd4a 4960(define_insn "*movhi_bytes"
25f7a26e 4961 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4962 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 4963 "TARGET_ARM"
25f7a26e 4964 "@
4965 mov%?\\t%0, %1\\t%@ movhi
0d66636f 4966 mvn%?\\t%0, #%B1\\t%@ movhi"
4967 [(set_attr "predicable" "yes")]
4968)
25f7a26e 4969
f90b51f1 4970(define_expand "thumb_movhi_clobber"
4971 [(set (match_operand:HI 0 "memory_operand" "")
4972 (match_operand:HI 1 "register_operand" ""))
4973 (clobber (match_operand:DI 2 "register_operand" ""))]
cffb2a26 4974 "TARGET_THUMB"
f90b51f1 4975 "
4976 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4977 && REGNO (operands[1]) <= LAST_LO_REGNUM)
4978 {
4979 emit_insn (gen_movhi (operands[0], operands[1]));
4980 DONE;
4981 }
4982 /* XXX Fixme, need to handle other cases here as well. */
4983 gcc_unreachable ();
4984 "
cffb2a26 4985)
4986
bc5c7e08 4987;; We use a DImode scratch because we may occasionally need an additional
4988;; temporary if the address isn't offsettable -- push_reload doesn't seem
4989;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 4990(define_expand "reload_outhi"
cffb2a26 4991 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 4992 (match_operand:HI 1 "s_register_operand" "r")
4993 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 4994 "TARGET_EITHER"
4995 "if (TARGET_ARM)
4996 arm_reload_out_hi (operands);
4997 else
4998 thumb_reload_out_hi (operands);
d3373b54 4999 DONE;
cffb2a26 5000 "
5001)
d3373b54 5002
25f7a26e 5003(define_expand "reload_inhi"
5004 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5005 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5006 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5007 "TARGET_EITHER"
25f7a26e 5008 "
cffb2a26 5009 if (TARGET_ARM)
5010 arm_reload_in_hi (operands);
5011 else
5012 thumb_reload_out_hi (operands);
25f7a26e 5013 DONE;
5014")
5015
9c08d1fa 5016(define_expand "movqi"
5017 [(set (match_operand:QI 0 "general_operand" "")
5018 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5019 "TARGET_EITHER"
9c08d1fa 5020 "
6cffc037 5021 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5022
6cffc037 5023 if (!no_new_pseudos)
cffb2a26 5024 {
6cffc037 5025 if (GET_CODE (operands[1]) == CONST_INT)
5026 {
5027 rtx reg = gen_reg_rtx (SImode);
5028
5029 emit_insn (gen_movsi (reg, operands[1]));
5030 operands[1] = gen_lowpart (QImode, reg);
5031 }
cffb2a26 5032
6cffc037 5033 if (TARGET_THUMB)
5034 {
cffb2a26 5035 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5036 happen if we are passed a SP (never OK for HImode/QImode) or
5037 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5038 HImode/QImode) relative address. */
cffb2a26 5039 /* ??? This should perhaps be fixed elsewhere, for instance, in
5040 fixup_stack_1, by checking for other kinds of invalid addresses,
5041 e.g. a bare reference to a virtual register. This may confuse the
5042 alpha though, which must handle this case differently. */
5043 if (GET_CODE (operands[0]) == MEM
215b30b3 5044 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5045 XEXP (operands[0], 0)))
537ffcfc 5046 operands[0]
5047 = replace_equiv_address (operands[0],
5048 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5049 if (GET_CODE (operands[1]) == MEM
5050 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5051 XEXP (operands[1], 0)))
537ffcfc 5052 operands[1]
5053 = replace_equiv_address (operands[1],
5054 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5055 }
5056
5057 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5058 {
5059 rtx reg = gen_reg_rtx (SImode);
5060
5061 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5062 operands[1] = gen_lowpart (QImode, reg);
5063 }
5064
5065 if (GET_CODE (operands[0]) == MEM)
5066 operands[1] = force_reg (QImode, operands[1]);
5067 }
5068 else if (TARGET_THUMB
5069 && GET_CODE (operands[1]) == CONST_INT
5070 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5071 {
674a8f0b 5072 /* Handle loading a large integer during reload. */
cffb2a26 5073
6cffc037 5074 /* Writing a constant to memory needs a scratch, which should
5075 be handled with SECONDARY_RELOADs. */
5076 gcc_assert (GET_CODE (operands[0]) == REG);
5077
5078 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5079 emit_insn (gen_movsi (operands[0], operands[1]));
5080 DONE;
cffb2a26 5081 }
5082 "
5083)
b11cae9e 5084
9c08d1fa 5085
cffb2a26 5086(define_insn "*arm_movqi_insn"
5087 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5088 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
cffb2a26 5089 "TARGET_ARM
5090 && ( register_operand (operands[0], QImode)
5091 || register_operand (operands[1], QImode))"
5565501b 5092 "@
5093 mov%?\\t%0, %1
5094 mvn%?\\t%0, #%B1
5095 ldr%?b\\t%0, %1
5096 str%?b\\t%1, %0"
a2cd141b 5097 [(set_attr "type" "*,*,load1,store1")
0d66636f 5098 (set_attr "predicable" "yes")]
cffb2a26 5099)
5100
5101(define_insn "*thumb_movqi_insn"
5102 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5103 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
cffb2a26 5104 "TARGET_THUMB
5105 && ( register_operand (operands[0], QImode)
5106 || register_operand (operands[1], QImode))"
5107 "@
5108 add\\t%0, %1, #0
5109 ldrb\\t%0, %1
5110 strb\\t%1, %0
5111 mov\\t%0, %1
5112 mov\\t%0, %1
5113 mov\\t%0, %1"
5114 [(set_attr "length" "2")
a2cd141b 5115 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5116 (set_attr "pool_range" "*,32,*,*,*,*")]
5117)
b11cae9e 5118
87b22bf7 5119(define_expand "movsf"
5120 [(set (match_operand:SF 0 "general_operand" "")
5121 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5122 "TARGET_EITHER"
87b22bf7 5123 "
cffb2a26 5124 if (TARGET_ARM)
5125 {
5126 if (GET_CODE (operands[0]) == MEM)
5127 operands[1] = force_reg (SFmode, operands[1]);
5128 }
5129 else /* TARGET_THUMB */
5130 {
215b30b3 5131 if (!no_new_pseudos)
cffb2a26 5132 {
5133 if (GET_CODE (operands[0]) != REG)
5134 operands[1] = force_reg (SFmode, operands[1]);
5135 }
5136 }
5137 "
5138)
5139
5140(define_split
5141 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5142 (match_operand:SF 1 "immediate_operand" ""))]
5143 "TARGET_ARM
a2cd141b 5144 && !(TARGET_HARD_FLOAT && TARGET_FPA)
cffb2a26 5145 && reload_completed
5146 && GET_CODE (operands[1]) == CONST_DOUBLE"
5147 [(set (match_dup 2) (match_dup 3))]
5148 "
5149 operands[2] = gen_lowpart (SImode, operands[0]);
5150 operands[3] = gen_lowpart (SImode, operands[1]);
5151 if (operands[2] == 0 || operands[3] == 0)
5152 FAIL;
215b30b3 5153 "
5154)
87b22bf7 5155
cffb2a26 5156(define_insn "*arm_movsf_soft_insn"
5157 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5158 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5159 "TARGET_ARM
5160 && TARGET_SOFT_FLOAT
215b30b3 5161 && (GET_CODE (operands[0]) != MEM
5162 || register_operand (operands[1], SFmode))"
9a1112d7 5163 "@
5164 mov%?\\t%0, %1
5165 ldr%?\\t%0, %1\\t%@ float
5166 str%?\\t%1, %0\\t%@ float"
cffb2a26 5167 [(set_attr "length" "4,4,4")
0d66636f 5168 (set_attr "predicable" "yes")
a2cd141b 5169 (set_attr "type" "*,load1,store1")
cffb2a26 5170 (set_attr "pool_range" "*,4096,*")
5171 (set_attr "neg_pool_range" "*,4084,*")]
5172)
5173
5174;;; ??? This should have alternatives for constants.
5175(define_insn "*thumb_movsf_insn"
215b30b3 5176 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5177 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
cffb2a26 5178 "TARGET_THUMB
5179 && ( register_operand (operands[0], SFmode)
5180 || register_operand (operands[1], SFmode))"
5181 "@
5182 add\\t%0, %1, #0
5183 ldmia\\t%1, {%0}
5184 stmia\\t%0, {%1}
5185 ldr\\t%0, %1
5186 str\\t%1, %0
5187 mov\\t%0, %1
5188 mov\\t%0, %1"
5189 [(set_attr "length" "2")
a2cd141b 5190 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5191 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5192)
9a1112d7 5193
9c08d1fa 5194(define_expand "movdf"
87b22bf7 5195 [(set (match_operand:DF 0 "general_operand" "")
5196 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5197 "TARGET_EITHER"
9c08d1fa 5198 "
cffb2a26 5199 if (TARGET_ARM)
5200 {
5201 if (GET_CODE (operands[0]) == MEM)
5202 operands[1] = force_reg (DFmode, operands[1]);
5203 }
5204 else /* TARGET_THUMB */
5205 {
215b30b3 5206 if (!no_new_pseudos)
cffb2a26 5207 {
5208 if (GET_CODE (operands[0]) != REG)
5209 operands[1] = force_reg (DFmode, operands[1]);
5210 }
5211 }
5212 "
5213)
b11cae9e 5214
9c08d1fa 5215;; Reloading a df mode value stored in integer regs to memory can require a
5216;; scratch reg.
5217(define_expand "reload_outdf"
cffb2a26 5218 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5219 (match_operand:DF 1 "s_register_operand" "r")
5220 (match_operand:SI 2 "s_register_operand" "=&r")]
cffb2a26 5221 "TARGET_ARM"
87b22bf7 5222 "
215b30b3 5223 {
5224 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5225
215b30b3 5226 if (code == REG)
5227 operands[2] = XEXP (operands[0], 0);
5228 else if (code == POST_INC || code == PRE_DEC)
5229 {
5230 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5231 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5232 emit_insn (gen_movdi (operands[0], operands[1]));
5233 DONE;
5234 }
5235 else if (code == PRE_INC)
5236 {
5237 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5238
215b30b3 5239 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5240 operands[2] = reg;
5241 }
5242 else if (code == POST_DEC)
5243 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5244 else
5245 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5246 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5247
788fcce0 5248 emit_insn (gen_rtx_SET (VOIDmode,
5249 replace_equiv_address (operands[0], operands[2]),
215b30b3 5250 operands[1]));
f7fbdd4a 5251
215b30b3 5252 if (code == POST_DEC)
5253 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5254
5255 DONE;
5256 }"
5257)
9c08d1fa 5258
9a1112d7 5259(define_insn "*movdf_soft_insn"
359a6e9f 5260 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5261 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 5262 "TARGET_ARM && TARGET_SOFT_FLOAT
5263 "
d51f92df 5264 "*
5265 switch (which_alternative)
5266 {
5267 case 0:
5268 case 1:
5269 case 2:
5270 return \"#\";
5271 default:
5272 return output_move_double (operands);
5273 }
5274 "
359a6e9f 5275 [(set_attr "length" "8,12,16,8,8")
5276 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 5277 (set_attr "pool_range" "1020")
5278 (set_attr "neg_pool_range" "1008")]
cffb2a26 5279)
5280
5281;;; ??? This should have alternatives for constants.
5282;;; ??? This was originally identical to the movdi_insn pattern.
5283;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5284;;; thumb_reorg with a memory reference.
5285(define_insn "*thumb_movdf_insn"
215b30b3 5286 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5287 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
cffb2a26 5288 "TARGET_THUMB
5289 && ( register_operand (operands[0], DFmode)
5290 || register_operand (operands[1], DFmode))"
5291 "*
5292 switch (which_alternative)
5293 {
5294 default:
5295 case 0:
5296 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5297 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5298 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5299 case 1:
5300 return \"ldmia\\t%1, {%0, %H0}\";
5301 case 2:
5302 return \"stmia\\t%0, {%1, %H1}\";
5303 case 3:
5304 return thumb_load_double_from_address (operands);
5305 case 4:
1a83b3ff 5306 operands[2] = gen_rtx_MEM (SImode,
5307 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5308 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5309 return \"\";
5310 case 5:
5311 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5312 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5313 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5314 }
5315 "
5316 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 5317 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 5318 (set_attr "pool_range" "*,*,*,1020,*,*")]
5319)
755eb2b4 5320
ccd90aaa 5321(define_expand "movxf"
5322 [(set (match_operand:XF 0 "general_operand" "")
5323 (match_operand:XF 1 "general_operand" ""))]
5324 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5325 "
5326 if (GET_CODE (operands[0]) == MEM)
5327 operands[1] = force_reg (XFmode, operands[1]);
5328 "
5329)
5330
755eb2b4 5331;; Vector Moves
5332(define_expand "movv2si"
5333 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5334 (match_operand:V2SI 1 "general_operand" ""))]
5335 "TARGET_REALLY_IWMMXT"
5336{
5337})
5338
5339(define_expand "movv4hi"
5340 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5341 (match_operand:V4HI 1 "general_operand" ""))]
5342 "TARGET_REALLY_IWMMXT"
5343{
5344})
5345
5346(define_expand "movv8qi"
5347 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5348 (match_operand:V8QI 1 "general_operand" ""))]
5349 "TARGET_REALLY_IWMMXT"
5350{
5351})
b11cae9e 5352\f
b11cae9e 5353
9c08d1fa 5354;; load- and store-multiple insns
5355;; The arm can load/store any set of registers, provided that they are in
5356;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5357
9c08d1fa 5358(define_expand "load_multiple"
5359 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5360 (match_operand:SI 1 "" ""))
5361 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5362 "TARGET_ARM"
9580c25f 5363{
5364 HOST_WIDE_INT offset = 0;
5365
bd5b4116 5366 /* Support only fixed point registers. */
9c08d1fa 5367 if (GET_CODE (operands[2]) != CONST_INT
5368 || INTVAL (operands[2]) > 14
5369 || INTVAL (operands[2]) < 2
5370 || GET_CODE (operands[1]) != MEM
5371 || GET_CODE (operands[0]) != REG
bd5b4116 5372 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5373 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5374 FAIL;
5375
5376 operands[3]
f082f1c4 5377 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5378 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 5379 TRUE, FALSE, operands[1], &offset);
5380})
b11cae9e 5381
9c08d1fa 5382;; Load multiple with write-back
5383
2162064c 5384(define_insn "*ldmsi_postinc4"
9c08d1fa 5385 [(match_parallel 0 "load_multiple_operation"
13e9316a 5386 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5387 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5388 (const_int 16)))
5389 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5390 (mem:SI (match_dup 2)))
a0a72ac3 5391 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5392 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5393 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5394 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5395 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5396 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5397 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5398 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
a2cd141b 5399 [(set_attr "type" "load4")
2162064c 5400 (set_attr "predicable" "yes")]
5401)
b11cae9e 5402
ccd90aaa 5403(define_insn "*ldmsi_postinc4_thumb"
5404 [(match_parallel 0 "load_multiple_operation"
5405 [(set (match_operand:SI 1 "s_register_operand" "=l")
5406 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5407 (const_int 16)))
5408 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5409 (mem:SI (match_dup 2)))
5410 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5411 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5412 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5413 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5414 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5415 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5416 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5417 "ldmia\\t%1!, {%3, %4, %5, %6}"
5418 [(set_attr "type" "load4")]
5419)
5420
2162064c 5421(define_insn "*ldmsi_postinc3"
5422 [(match_parallel 0 "load_multiple_operation"
13e9316a 5423 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5424 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5425 (const_int 12)))
5426 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5427 (mem:SI (match_dup 2)))
5428 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5429 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5430 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5431 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5432 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5433 "ldm%?ia\\t%1!, {%3, %4, %5}"
a2cd141b 5434 [(set_attr "type" "load3")
2162064c 5435 (set_attr "predicable" "yes")]
5436)
b11cae9e 5437
2162064c 5438(define_insn "*ldmsi_postinc2"
5439 [(match_parallel 0 "load_multiple_operation"
13e9316a 5440 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5441 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5442 (const_int 8)))
5443 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5444 (mem:SI (match_dup 2)))
5445 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5446 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5447 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5448 "ldm%?ia\\t%1!, {%3, %4}"
a2cd141b 5449 [(set_attr "type" "load2")
0d66636f 5450 (set_attr "predicable" "yes")]
5451)
b11cae9e 5452
9c08d1fa 5453;; Ordinary load multiple
b11cae9e 5454
2162064c 5455(define_insn "*ldmsi4"
9c08d1fa 5456 [(match_parallel 0 "load_multiple_operation"
2162064c 5457 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5458 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5459 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5460 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5461 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5462 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5463 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5464 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5465 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5466 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
a2cd141b 5467 [(set_attr "type" "load4")
2162064c 5468 (set_attr "predicable" "yes")]
5469)
9c08d1fa 5470
2162064c 5471(define_insn "*ldmsi3"
5472 [(match_parallel 0 "load_multiple_operation"
5473 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5474 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5475 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5476 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5477 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5478 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5479 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5480 "ldm%?ia\\t%1, {%2, %3, %4}"
a2cd141b 5481 [(set_attr "type" "load3")
2162064c 5482 (set_attr "predicable" "yes")]
5483)
9c08d1fa 5484
2162064c 5485(define_insn "*ldmsi2"
5486 [(match_parallel 0 "load_multiple_operation"
5487 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5488 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5489 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5490 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5491 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5492 "ldm%?ia\\t%1, {%2, %3}"
a2cd141b 5493 [(set_attr "type" "load2")
0d66636f 5494 (set_attr "predicable" "yes")]
5495)
9c08d1fa 5496
5497(define_expand "store_multiple"
5498 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5499 (match_operand:SI 1 "" ""))
5500 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5501 "TARGET_ARM"
9580c25f 5502{
5503 HOST_WIDE_INT offset = 0;
5504
674a8f0b 5505 /* Support only fixed point registers. */
9c08d1fa 5506 if (GET_CODE (operands[2]) != CONST_INT
5507 || INTVAL (operands[2]) > 14
5508 || INTVAL (operands[2]) < 2
5509 || GET_CODE (operands[1]) != REG
5510 || GET_CODE (operands[0]) != MEM
bd5b4116 5511 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5512 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5513 FAIL;
5514
5515 operands[3]
f082f1c4 5516 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5517 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 5518 TRUE, FALSE, operands[0], &offset);
5519})
b11cae9e 5520
9c08d1fa 5521;; Store multiple with write-back
5522
2162064c 5523(define_insn "*stmsi_postinc4"
9c08d1fa 5524 [(match_parallel 0 "store_multiple_operation"
13e9316a 5525 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5526 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5527 (const_int 16)))
a0a72ac3 5528 (set (mem:SI (match_dup 2))
2162064c 5529 (match_operand:SI 3 "arm_hard_register_operand" ""))
5530 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5531 (match_operand:SI 4 "arm_hard_register_operand" ""))
5532 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5533 (match_operand:SI 5 "arm_hard_register_operand" ""))
5534 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5535 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5536 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5537 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5538 [(set_attr "predicable" "yes")
5539 (set_attr "type" "store4")]
5540)
b11cae9e 5541
ccd90aaa 5542(define_insn "*stmsi_postinc4_thumb"
5543 [(match_parallel 0 "store_multiple_operation"
5544 [(set (match_operand:SI 1 "s_register_operand" "=l")
5545 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5546 (const_int 16)))
5547 (set (mem:SI (match_dup 2))
5548 (match_operand:SI 3 "arm_hard_register_operand" ""))
5549 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5550 (match_operand:SI 4 "arm_hard_register_operand" ""))
5551 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5552 (match_operand:SI 5 "arm_hard_register_operand" ""))
5553 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5554 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5555 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5556 "stmia\\t%1!, {%3, %4, %5, %6}"
5557 [(set_attr "type" "store4")]
5558)
5559
2162064c 5560(define_insn "*stmsi_postinc3"
5561 [(match_parallel 0 "store_multiple_operation"
13e9316a 5562 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5563 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5564 (const_int 12)))
5565 (set (mem:SI (match_dup 2))
5566 (match_operand:SI 3 "arm_hard_register_operand" ""))
5567 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5568 (match_operand:SI 4 "arm_hard_register_operand" ""))
5569 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5570 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5571 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5572 "stm%?ia\\t%1!, {%3, %4, %5}"
5573 [(set_attr "predicable" "yes")
5574 (set_attr "type" "store3")]
5575)
9c08d1fa 5576
2162064c 5577(define_insn "*stmsi_postinc2"
5578 [(match_parallel 0 "store_multiple_operation"
13e9316a 5579 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5580 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5581 (const_int 8)))
5582 (set (mem:SI (match_dup 2))
5583 (match_operand:SI 3 "arm_hard_register_operand" ""))
5584 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5585 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5586 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5587 "stm%?ia\\t%1!, {%3, %4}"
0d66636f 5588 [(set_attr "predicable" "yes")
2162064c 5589 (set_attr "type" "store2")]
cffb2a26 5590)
9c08d1fa 5591
5592;; Ordinary store multiple
5593
2162064c 5594(define_insn "*stmsi4"
9c08d1fa 5595 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 5596 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 5597 (match_operand:SI 2 "arm_hard_register_operand" ""))
5598 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5599 (match_operand:SI 3 "arm_hard_register_operand" ""))
5600 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5601 (match_operand:SI 4 "arm_hard_register_operand" ""))
5602 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5603 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5604 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5605 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5606 [(set_attr "predicable" "yes")
5607 (set_attr "type" "store4")]
5608)
9c08d1fa 5609
2162064c 5610(define_insn "*stmsi3"
5611 [(match_parallel 0 "store_multiple_operation"
5612 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5613 (match_operand:SI 2 "arm_hard_register_operand" ""))
5614 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5615 (match_operand:SI 3 "arm_hard_register_operand" ""))
5616 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5617 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5618 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5619 "stm%?ia\\t%1, {%2, %3, %4}"
5620 [(set_attr "predicable" "yes")
5621 (set_attr "type" "store3")]
5622)
9c08d1fa 5623
2162064c 5624(define_insn "*stmsi2"
5625 [(match_parallel 0 "store_multiple_operation"
5626 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5627 (match_operand:SI 2 "arm_hard_register_operand" ""))
5628 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5629 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5630 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5631 "stm%?ia\\t%1, {%2, %3}"
0d66636f 5632 [(set_attr "predicable" "yes")
2162064c 5633 (set_attr "type" "store2")]
cffb2a26 5634)
9c08d1fa 5635
5636;; Move a block of memory if it is word aligned and MORE than 2 words long.
5637;; We could let this apply for blocks of less than this, but it clobbers so
5638;; many registers that there is then probably a better way.
5639
008c057d 5640(define_expand "movmemqi"
34191dd1 5641 [(match_operand:BLK 0 "general_operand" "")
5642 (match_operand:BLK 1 "general_operand" "")
5643 (match_operand:SI 2 "const_int_operand" "")
5644 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 5645 "TARGET_EITHER"
9c08d1fa 5646 "
cffb2a26 5647 if (TARGET_ARM)
5648 {
008c057d 5649 if (arm_gen_movmemqi (operands))
cffb2a26 5650 DONE;
5651 FAIL;
5652 }
5653 else /* TARGET_THUMB */
5654 {
5655 if ( INTVAL (operands[3]) != 4
5656 || INTVAL (operands[2]) > 48)
5657 FAIL;
5658
008c057d 5659 thumb_expand_movmemqi (operands);
cffb2a26 5660 DONE;
5661 }
5662 "
5663)
5664
2162064c 5665;; Thumb block-move insns
cffb2a26 5666
5667(define_insn "movmem12b"
960f3acf 5668 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5669 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5670 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5671 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5672 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5673 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5674 (set (match_operand:SI 0 "register_operand" "=l")
5675 (plus:SI (match_dup 2) (const_int 12)))
5676 (set (match_operand:SI 1 "register_operand" "=l")
5677 (plus:SI (match_dup 3) (const_int 12)))
5678 (clobber (match_scratch:SI 4 "=&l"))
5679 (clobber (match_scratch:SI 5 "=&l"))
5680 (clobber (match_scratch:SI 6 "=&l"))]
cffb2a26 5681 "TARGET_THUMB"
5682 "* return thumb_output_move_mem_multiple (3, operands);"
5683 [(set_attr "length" "4")
215b30b3 5684 ; This isn't entirely accurate... It loads as well, but in terms of
5685 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5686 (set_attr "type" "store3")]
5687)
5688
5689(define_insn "movmem8b"
960f3acf 5690 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5691 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5692 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5693 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5694 (set (match_operand:SI 0 "register_operand" "=l")
5695 (plus:SI (match_dup 2) (const_int 8)))
5696 (set (match_operand:SI 1 "register_operand" "=l")
5697 (plus:SI (match_dup 3) (const_int 8)))
5698 (clobber (match_scratch:SI 4 "=&l"))
5699 (clobber (match_scratch:SI 5 "=&l"))]
cffb2a26 5700 "TARGET_THUMB"
5701 "* return thumb_output_move_mem_multiple (2, operands);"
5702 [(set_attr "length" "4")
215b30b3 5703 ; This isn't entirely accurate... It loads as well, but in terms of
5704 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5705 (set_attr "type" "store2")]
5706)
5707
9c08d1fa 5708\f
b11cae9e 5709
341940e8 5710;; Compare & branch insns
8d232dc7 5711;; The range calculations are based as follows:
341940e8 5712;; For forward branches, the address calculation returns the address of
5713;; the next instruction. This is 2 beyond the branch instruction.
5714;; For backward branches, the address calculation returns the address of
5715;; the first instruction in this pattern (cmp). This is 2 before the branch
5716;; instruction for the shortest sequence, and 4 before the branch instruction
5717;; if we have to jump around an unconditional branch.
5718;; To the basic branch range the PC offset must be added (this is +4).
5719;; So for forward branches we have
5720;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5721;; And for backward branches we have
5722;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5723;;
5724;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5725;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 5726
aeac46d4 5727(define_expand "cbranchsi4"
5728 [(set (pc) (if_then_else
5729 (match_operator 0 "arm_comparison_operator"
5730 [(match_operand:SI 1 "s_register_operand" "")
5731 (match_operand:SI 2 "nonmemory_operand" "")])
5732 (label_ref (match_operand 3 "" ""))
5733 (pc)))]
5734 "TARGET_THUMB"
5735 "
5736 if (thumb_cmpneg_operand (operands[2], SImode))
5737 {
5738 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5739 operands[3], operands[0]));
5740 DONE;
5741 }
5742 if (!thumb_cmp_operand (operands[2], SImode))
5743 operands[2] = force_reg (SImode, operands[2]);
5744 ")
5745
5746(define_insn "*cbranchsi4_insn"
5747 [(set (pc) (if_then_else
5748 (match_operator 0 "arm_comparison_operator"
5749 [(match_operand:SI 1 "s_register_operand" "l,*h")
5750 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5751 (label_ref (match_operand 3 "" ""))
5752 (pc)))]
cffb2a26 5753 "TARGET_THUMB"
5754 "*
5755 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 5756
cffb2a26 5757 switch (get_attr_length (insn))
5758 {
5759 case 4: return \"b%d0\\t%l3\";
5760 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5761 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5762 }
5763 "
5764 [(set (attr "far_jump")
5765 (if_then_else
5766 (eq_attr "length" "8")
5767 (const_string "yes")
5768 (const_string "no")))
5769 (set (attr "length")
5770 (if_then_else
5771 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5772 (le (minus (match_dup 3) (pc)) (const_int 256)))
5773 (const_int 4)
5774 (if_then_else
5775 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 5776 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5777 (const_int 6)
5778 (const_int 8))))]
5779)
5780
aeac46d4 5781(define_insn "cbranchsi4_scratch"
5782 [(set (pc) (if_then_else
5783 (match_operator 4 "arm_comparison_operator"
5784 [(match_operand:SI 1 "s_register_operand" "l,0")
5785 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5786 (label_ref (match_operand 3 "" ""))
5787 (pc)))
5788 (clobber (match_scratch:SI 0 "=l,l"))]
5789 "TARGET_THUMB"
5790 "*
5791 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5792
5793 switch (get_attr_length (insn))
5794 {
5795 case 4: return \"b%d4\\t%l3\";
5796 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5797 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5798 }
5799 "
5800 [(set (attr "far_jump")
5801 (if_then_else
5802 (eq_attr "length" "8")
5803 (const_string "yes")
5804 (const_string "no")))
5805 (set (attr "length")
5806 (if_then_else
5807 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5808 (le (minus (match_dup 3) (pc)) (const_int 256)))
5809 (const_int 4)
5810 (if_then_else
5811 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5812 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5813 (const_int 6)
5814 (const_int 8))))]
5815)
5816(define_insn "*movsi_cbranchsi4"
5817 [(set (pc)
5818 (if_then_else
5819 (match_operator 3 "arm_comparison_operator"
5820 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5821 (const_int 0)])
5822 (label_ref (match_operand 2 "" ""))
5823 (pc)))
5824 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5825 (match_dup 1))]
5826 "TARGET_THUMB"
5827 "*{
5828 if (which_alternative == 0)
5829 output_asm_insn (\"cmp\t%0, #0\", operands);
5830 else if (which_alternative == 1)
5831 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5832 else
5833 {
5834 output_asm_insn (\"cmp\t%1, #0\", operands);
5835 if (which_alternative == 2)
5836 output_asm_insn (\"mov\t%0, %1\", operands);
5837 else
5838 output_asm_insn (\"str\t%1, %0\", operands);
5839 }
5840 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5841 {
5842 case 4: return \"b%d3\\t%l2\";
5843 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5844 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5845 }
5846 }"
5847 [(set (attr "far_jump")
5848 (if_then_else
5849 (ior (and (gt (symbol_ref ("which_alternative"))
5850 (const_int 1))
5851 (eq_attr "length" "8"))
5852 (eq_attr "length" "10"))
5853 (const_string "yes")
5854 (const_string "no")))
5855 (set (attr "length")
5856 (if_then_else
5857 (le (symbol_ref ("which_alternative"))
5858 (const_int 1))
5859 (if_then_else
5860 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5861 (le (minus (match_dup 2) (pc)) (const_int 256)))
5862 (const_int 4)
5863 (if_then_else
5864 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5865 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5866 (const_int 6)
5867 (const_int 8)))
5868 (if_then_else
5869 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5870 (le (minus (match_dup 2) (pc)) (const_int 256)))
5871 (const_int 6)
5872 (if_then_else
5873 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5874 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5875 (const_int 8)
5876 (const_int 10)))))]
5877)
5878
cffb2a26 5879(define_insn "*negated_cbranchsi4"
5880 [(set (pc)
5881 (if_then_else
aed179ae 5882 (match_operator 0 "equality_operator"
aeac46d4 5883 [(match_operand:SI 1 "s_register_operand" "l")
5884 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5885 (label_ref (match_operand 3 "" ""))
215b30b3 5886 (pc)))]
cffb2a26 5887 "TARGET_THUMB"
5888 "*
5889 output_asm_insn (\"cmn\\t%1, %2\", operands);
5890 switch (get_attr_length (insn))
5891 {
5892 case 4: return \"b%d0\\t%l3\";
5893 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5894 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5895 }
5896 "
5897 [(set (attr "far_jump")
5898 (if_then_else
5899 (eq_attr "length" "8")
5900 (const_string "yes")
5901 (const_string "no")))
5902 (set (attr "length")
5903 (if_then_else
5904 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 5905 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 5906 (const_int 4)
5907 (if_then_else
341940e8 5908 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5909 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5910 (const_int 6)
5911 (const_int 8))))]
5912)
5913
58d6528b 5914(define_insn "*tbit_cbranch"
5915 [(set (pc)
5916 (if_then_else
5917 (match_operator 0 "equality_operator"
5918 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5919 (const_int 1)
5920 (match_operand:SI 2 "const_int_operand" "i"))
5921 (const_int 0)])
5922 (label_ref (match_operand 3 "" ""))
5923 (pc)))
5924 (clobber (match_scratch:SI 4 "=l"))]
5925 "TARGET_THUMB"
5926 "*
5927 {
5928 rtx op[3];
5929 op[0] = operands[4];
5930 op[1] = operands[1];
5931 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5932
5933 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5934 switch (get_attr_length (insn))
5935 {
5936 case 4: return \"b%d0\\t%l3\";
5937 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5938 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5939 }
5940 }"
5941 [(set (attr "far_jump")
5942 (if_then_else
5943 (eq_attr "length" "8")
5944 (const_string "yes")
5945 (const_string "no")))
5946 (set (attr "length")
5947 (if_then_else
5948 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5949 (le (minus (match_dup 3) (pc)) (const_int 256)))
5950 (const_int 4)
5951 (if_then_else
5952 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5953 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5954 (const_int 6)
5955 (const_int 8))))]
5956)
5957
aeac46d4 5958(define_insn "*tstsi3_cbranch"
58d6528b 5959 [(set (pc)
5960 (if_then_else
aeac46d4 5961 (match_operator 3 "equality_operator"
5962 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5963 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 5964 (const_int 0)])
aeac46d4 5965 (label_ref (match_operand 2 "" ""))
5966 (pc)))]
58d6528b 5967 "TARGET_THUMB"
5968 "*
5969 {
aeac46d4 5970 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 5971 switch (get_attr_length (insn))
5972 {
aeac46d4 5973 case 4: return \"b%d3\\t%l2\";
5974 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5975 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 5976 }
5977 }"
5978 [(set (attr "far_jump")
5979 (if_then_else
5980 (eq_attr "length" "8")
5981 (const_string "yes")
5982 (const_string "no")))
5983 (set (attr "length")
5984 (if_then_else
aeac46d4 5985 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5986 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 5987 (const_int 4)
5988 (if_then_else
aeac46d4 5989 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5990 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 5991 (const_int 6)
5992 (const_int 8))))]
5993)
5994
5995(define_insn "*andsi3_cbranch"
5996 [(set (pc)
5997 (if_then_else
5998 (match_operator 5 "equality_operator"
5999 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6000 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6001 (const_int 0)])
6002 (label_ref (match_operand 4 "" ""))
6003 (pc)))
aeac46d4 6004 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6005 (and:SI (match_dup 2) (match_dup 3)))
6006 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6007 "TARGET_THUMB"
6008 "*
6009 {
6010 if (which_alternative == 0)
6011 output_asm_insn (\"and\\t%0, %3\", operands);
6012 else if (which_alternative == 1)
6013 {
6014 output_asm_insn (\"and\\t%1, %3\", operands);
6015 output_asm_insn (\"mov\\t%0, %1\", operands);
6016 }
6017 else
6018 {
6019 output_asm_insn (\"and\\t%1, %3\", operands);
6020 output_asm_insn (\"str\\t%1, %0\", operands);
6021 }
6022
6023 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6024 {
6025 case 4: return \"b%d5\\t%l4\";
6026 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6027 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6028 }
6029 }"
6030 [(set (attr "far_jump")
6031 (if_then_else
6032 (ior (and (eq (symbol_ref ("which_alternative"))
6033 (const_int 0))
6034 (eq_attr "length" "8"))
6035 (eq_attr "length" "10"))
6036 (const_string "yes")
6037 (const_string "no")))
6038 (set (attr "length")
6039 (if_then_else
6040 (eq (symbol_ref ("which_alternative"))
6041 (const_int 0))
6042 (if_then_else
6043 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6044 (le (minus (match_dup 4) (pc)) (const_int 256)))
6045 (const_int 4)
6046 (if_then_else
6047 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6048 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6049 (const_int 6)
6050 (const_int 8)))
6051 (if_then_else
6052 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6053 (le (minus (match_dup 4) (pc)) (const_int 256)))
6054 (const_int 6)
6055 (if_then_else
6056 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6057 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6058 (const_int 8)
6059 (const_int 10)))))]
6060)
6061
6062(define_insn "*orrsi3_cbranch_scratch"
6063 [(set (pc)
6064 (if_then_else
6065 (match_operator 4 "equality_operator"
6066 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6067 (match_operand:SI 2 "s_register_operand" "l"))
6068 (const_int 0)])
6069 (label_ref (match_operand 3 "" ""))
6070 (pc)))
6071 (clobber (match_scratch:SI 0 "=l"))]
6072 "TARGET_THUMB"
6073 "*
6074 {
6075 output_asm_insn (\"orr\\t%0, %2\", operands);
6076 switch (get_attr_length (insn))
6077 {
6078 case 4: return \"b%d4\\t%l3\";
6079 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6080 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6081 }
6082 }"
6083 [(set (attr "far_jump")
6084 (if_then_else
6085 (eq_attr "length" "8")
6086 (const_string "yes")
6087 (const_string "no")))
6088 (set (attr "length")
6089 (if_then_else
6090 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6091 (le (minus (match_dup 3) (pc)) (const_int 256)))
6092 (const_int 4)
6093 (if_then_else
6094 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6095 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6096 (const_int 6)
6097 (const_int 8))))]
6098)
6099
6100(define_insn "*orrsi3_cbranch"
6101 [(set (pc)
6102 (if_then_else
6103 (match_operator 5 "equality_operator"
6104 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6105 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6106 (const_int 0)])
6107 (label_ref (match_operand 4 "" ""))
6108 (pc)))
aeac46d4 6109 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6110 (ior:SI (match_dup 2) (match_dup 3)))
6111 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6112 "TARGET_THUMB"
6113 "*
6114 {
6115 if (which_alternative == 0)
6116 output_asm_insn (\"orr\\t%0, %3\", operands);
6117 else if (which_alternative == 1)
6118 {
6119 output_asm_insn (\"orr\\t%1, %3\", operands);
6120 output_asm_insn (\"mov\\t%0, %1\", operands);
6121 }
6122 else
6123 {
6124 output_asm_insn (\"orr\\t%1, %3\", operands);
6125 output_asm_insn (\"str\\t%1, %0\", operands);
6126 }
6127
6128 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6129 {
6130 case 4: return \"b%d5\\t%l4\";
6131 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6132 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6133 }
6134 }"
6135 [(set (attr "far_jump")
6136 (if_then_else
6137 (ior (and (eq (symbol_ref ("which_alternative"))
6138 (const_int 0))
6139 (eq_attr "length" "8"))
6140 (eq_attr "length" "10"))
6141 (const_string "yes")
6142 (const_string "no")))
6143 (set (attr "length")
6144 (if_then_else
6145 (eq (symbol_ref ("which_alternative"))
6146 (const_int 0))
6147 (if_then_else
6148 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6149 (le (minus (match_dup 4) (pc)) (const_int 256)))
6150 (const_int 4)
6151 (if_then_else
6152 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6153 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6154 (const_int 6)
6155 (const_int 8)))
6156 (if_then_else
6157 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6158 (le (minus (match_dup 4) (pc)) (const_int 256)))
6159 (const_int 6)
6160 (if_then_else
6161 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6162 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6163 (const_int 8)
6164 (const_int 10)))))]
6165)
6166
6167(define_insn "*xorsi3_cbranch_scratch"
6168 [(set (pc)
6169 (if_then_else
6170 (match_operator 4 "equality_operator"
6171 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6172 (match_operand:SI 2 "s_register_operand" "l"))
6173 (const_int 0)])
6174 (label_ref (match_operand 3 "" ""))
6175 (pc)))
6176 (clobber (match_scratch:SI 0 "=l"))]
6177 "TARGET_THUMB"
6178 "*
6179 {
6180 output_asm_insn (\"eor\\t%0, %2\", operands);
6181 switch (get_attr_length (insn))
6182 {
6183 case 4: return \"b%d4\\t%l3\";
6184 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6185 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6186 }
6187 }"
6188 [(set (attr "far_jump")
6189 (if_then_else
6190 (eq_attr "length" "8")
6191 (const_string "yes")
6192 (const_string "no")))
6193 (set (attr "length")
6194 (if_then_else
6195 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6196 (le (minus (match_dup 3) (pc)) (const_int 256)))
6197 (const_int 4)
6198 (if_then_else
6199 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6200 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6201 (const_int 6)
6202 (const_int 8))))]
6203)
6204
6205(define_insn "*xorsi3_cbranch"
6206 [(set (pc)
6207 (if_then_else
6208 (match_operator 5 "equality_operator"
6209 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6210 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6211 (const_int 0)])
6212 (label_ref (match_operand 4 "" ""))
6213 (pc)))
aeac46d4 6214 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6215 (xor:SI (match_dup 2) (match_dup 3)))
6216 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6217 "TARGET_THUMB"
6218 "*
6219 {
6220 if (which_alternative == 0)
6221 output_asm_insn (\"eor\\t%0, %3\", operands);
6222 else if (which_alternative == 1)
6223 {
6224 output_asm_insn (\"eor\\t%1, %3\", operands);
6225 output_asm_insn (\"mov\\t%0, %1\", operands);
6226 }
6227 else
6228 {
6229 output_asm_insn (\"eor\\t%1, %3\", operands);
6230 output_asm_insn (\"str\\t%1, %0\", operands);
6231 }
6232
6233 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6234 {
6235 case 4: return \"b%d5\\t%l4\";
6236 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6237 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6238 }
6239 }"
6240 [(set (attr "far_jump")
6241 (if_then_else
6242 (ior (and (eq (symbol_ref ("which_alternative"))
6243 (const_int 0))
6244 (eq_attr "length" "8"))
6245 (eq_attr "length" "10"))
6246 (const_string "yes")
6247 (const_string "no")))
6248 (set (attr "length")
6249 (if_then_else
6250 (eq (symbol_ref ("which_alternative"))
6251 (const_int 0))
6252 (if_then_else
6253 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6254 (le (minus (match_dup 4) (pc)) (const_int 256)))
6255 (const_int 4)
6256 (if_then_else
6257 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6258 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6259 (const_int 6)
6260 (const_int 8)))
6261 (if_then_else
6262 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6263 (le (minus (match_dup 4) (pc)) (const_int 256)))
6264 (const_int 6)
6265 (if_then_else
6266 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6267 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6268 (const_int 8)
6269 (const_int 10)))))]
6270)
6271
aeac46d4 6272(define_insn "*bicsi3_cbranch_scratch"
6273 [(set (pc)
6274 (if_then_else
6275 (match_operator 4 "equality_operator"
6276 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6277 (match_operand:SI 1 "s_register_operand" "0"))
6278 (const_int 0)])
6279 (label_ref (match_operand 3 "" ""))
6280 (pc)))
6281 (clobber (match_scratch:SI 0 "=l"))]
6282 "TARGET_THUMB"
6283 "*
6284 {
6285 output_asm_insn (\"bic\\t%0, %2\", operands);
6286 switch (get_attr_length (insn))
6287 {
6288 case 4: return \"b%d4\\t%l3\";
6289 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6290 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6291 }
6292 }"
6293 [(set (attr "far_jump")
6294 (if_then_else
6295 (eq_attr "length" "8")
6296 (const_string "yes")
6297 (const_string "no")))
6298 (set (attr "length")
6299 (if_then_else
6300 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6301 (le (minus (match_dup 3) (pc)) (const_int 256)))
6302 (const_int 4)
6303 (if_then_else
6304 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6305 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6306 (const_int 6)
6307 (const_int 8))))]
6308)
6309
6310(define_insn "*bicsi3_cbranch"
6311 [(set (pc)
6312 (if_then_else
6313 (match_operator 5 "equality_operator"
01145ae6 6314 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6315 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 6316 (const_int 0)])
6317 (label_ref (match_operand 4 "" ""))
6318 (pc)))
01145ae6 6319 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 6320 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 6321 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
aeac46d4 6322 "TARGET_THUMB"
6323 "*
6324 {
6325 if (which_alternative == 0)
6326 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 6327 else if (which_alternative <= 2)
aeac46d4 6328 {
6329 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 6330 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6331 conditions again, since we're only testing for equality. */
aeac46d4 6332 output_asm_insn (\"mov\\t%0, %1\", operands);
6333 }
6334 else
6335 {
6336 output_asm_insn (\"bic\\t%1, %3\", operands);
6337 output_asm_insn (\"str\\t%1, %0\", operands);
6338 }
6339
6340 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6341 {
6342 case 4: return \"b%d5\\t%l4\";
6343 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6344 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6345 }
6346 }"
6347 [(set (attr "far_jump")
6348 (if_then_else
6349 (ior (and (eq (symbol_ref ("which_alternative"))
6350 (const_int 0))
6351 (eq_attr "length" "8"))
6352 (eq_attr "length" "10"))
6353 (const_string "yes")
6354 (const_string "no")))
6355 (set (attr "length")
6356 (if_then_else
6357 (eq (symbol_ref ("which_alternative"))
6358 (const_int 0))
6359 (if_then_else
6360 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6361 (le (minus (match_dup 4) (pc)) (const_int 256)))
6362 (const_int 4)
6363 (if_then_else
6364 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6365 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6366 (const_int 6)
6367 (const_int 8)))
6368 (if_then_else
6369 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6370 (le (minus (match_dup 4) (pc)) (const_int 256)))
6371 (const_int 6)
6372 (if_then_else
6373 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6374 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6375 (const_int 8)
6376 (const_int 10)))))]
6377)
6378
203c488f 6379(define_insn "*cbranchne_decr1"
6380 [(set (pc)
6381 (if_then_else (match_operator 3 "equality_operator"
6382 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6383 (const_int 0)])
6384 (label_ref (match_operand 4 "" ""))
6385 (pc)))
aeac46d4 6386 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6387 (plus:SI (match_dup 2) (const_int -1)))
6388 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6389 "TARGET_THUMB"
6390 "*
6391 {
6392 rtx cond[2];
6393 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6394 ? GEU : LTU),
58d6528b 6395 VOIDmode, operands[2], const1_rtx);
203c488f 6396 cond[1] = operands[4];
6397
6398 if (which_alternative == 0)
6399 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6400 else if (which_alternative == 1)
6401 {
6402 /* We must provide an alternative for a hi reg because reload
6403 cannot handle output reloads on a jump instruction, but we
6404 can't subtract into that. Fortunately a mov from lo to hi
6405 does not clobber the condition codes. */
6406 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6407 output_asm_insn (\"mov\\t%0, %1\", operands);
6408 }
6409 else
6410 {
6411 /* Similarly, but the target is memory. */
6412 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6413 output_asm_insn (\"str\\t%1, %0\", operands);
6414 }
6415
6416 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6417 {
6418 case 4:
8aea555f 6419 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6420 return \"\";
6421 case 6:
8aea555f 6422 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6423 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6424 default:
8aea555f 6425 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6426 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6427 }
6428 }
6429 "
6430 [(set (attr "far_jump")
6431 (if_then_else
6432 (ior (and (eq (symbol_ref ("which_alternative"))
6433 (const_int 0))
6434 (eq_attr "length" "8"))
6435 (eq_attr "length" "10"))
6436 (const_string "yes")
6437 (const_string "no")))
6438 (set_attr_alternative "length"
6439 [
6440 ;; Alternative 0
6441 (if_then_else
6442 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6443 (le (minus (match_dup 4) (pc)) (const_int 256)))
6444 (const_int 4)
6445 (if_then_else
6446 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6447 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6448 (const_int 6)
6449 (const_int 8)))
6450 ;; Alternative 1
6451 (if_then_else
6452 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6453 (le (minus (match_dup 4) (pc)) (const_int 256)))
6454 (const_int 6)
6455 (if_then_else
6456 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6457 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6458 (const_int 8)
6459 (const_int 10)))
6460 ;; Alternative 2
6461 (if_then_else
6462 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6463 (le (minus (match_dup 4) (pc)) (const_int 256)))
6464 (const_int 6)
6465 (if_then_else
6466 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6467 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6468 (const_int 8)
6469 (const_int 10)))
6470 ;; Alternative 3
6471 (if_then_else
6472 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6473 (le (minus (match_dup 4) (pc)) (const_int 256)))
6474 (const_int 6)
6475 (if_then_else
6476 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6477 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6478 (const_int 8)
6479 (const_int 10)))])]
6480)
cffb2a26 6481
58d6528b 6482(define_insn "*addsi3_cbranch"
6483 [(set (pc)
6484 (if_then_else
6485 (match_operator 4 "comparison_operator"
6486 [(plus:SI
6487 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6488 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6489 (const_int 0)])
6490 (label_ref (match_operand 5 "" ""))
6491 (pc)))
aeac46d4 6492 (set
6493 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6494 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 6495 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6496 "TARGET_THUMB
6497 && (GET_CODE (operands[4]) == EQ
6498 || GET_CODE (operands[4]) == NE
6499 || GET_CODE (operands[4]) == GE
6500 || GET_CODE (operands[4]) == LT)"
6501 "*
6502 {
6503 rtx cond[3];
6504
6505
6506 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6507 cond[1] = operands[2];
6508 cond[2] = operands[3];
6509
6510 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6511 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6512 else
6513 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6514
6515 if (which_alternative >= 3
6516 && which_alternative < 4)
6517 output_asm_insn (\"mov\\t%0, %1\", operands);
6518 else if (which_alternative >= 4)
6519 output_asm_insn (\"str\\t%1, %0\", operands);
6520
6521 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6522 {
6523 case 4:
6524 return \"b%d4\\t%l5\";
6525 case 6:
6526 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6527 default:
6528 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6529 }
6530 }
6531 "
6532 [(set (attr "far_jump")
6533 (if_then_else
6534 (ior (and (lt (symbol_ref ("which_alternative"))
6535 (const_int 3))
6536 (eq_attr "length" "8"))
6537 (eq_attr "length" "10"))
6538 (const_string "yes")
6539 (const_string "no")))
6540 (set (attr "length")
6541 (if_then_else
6542 (lt (symbol_ref ("which_alternative"))
6543 (const_int 3))
6544 (if_then_else
6545 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6546 (le (minus (match_dup 5) (pc)) (const_int 256)))
6547 (const_int 4)
6548 (if_then_else
6549 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6550 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6551 (const_int 6)
6552 (const_int 8)))
6553 (if_then_else
6554 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6555 (le (minus (match_dup 5) (pc)) (const_int 256)))
6556 (const_int 6)
6557 (if_then_else
6558 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6559 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6560 (const_int 8)
6561 (const_int 10)))))]
6562)
6563
6564(define_insn "*addsi3_cbranch_scratch"
6565 [(set (pc)
6566 (if_then_else
6567 (match_operator 3 "comparison_operator"
6568 [(plus:SI
6569 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 6570 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 6571 (const_int 0)])
6572 (label_ref (match_operand 4 "" ""))
6573 (pc)))
6574 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6575 "TARGET_THUMB
6576 && (GET_CODE (operands[3]) == EQ
6577 || GET_CODE (operands[3]) == NE
6578 || GET_CODE (operands[3]) == GE
6579 || GET_CODE (operands[3]) == LT)"
6580 "*
6581 {
6582 switch (which_alternative)
6583 {
6584 case 0:
6585 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6586 break;
6587 case 1:
6588 output_asm_insn (\"cmn\t%1, %2\", operands);
6589 break;
0f5e9701 6590 case 2:
3a445a04 6591 if (INTVAL (operands[2]) < 0)
6592 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6593 else
6594 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 6595 break;
0f5e9701 6596 case 3:
3a445a04 6597 if (INTVAL (operands[2]) < 0)
6598 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6599 else
6600 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 6601 break;
6602 }
6603
6604 switch (get_attr_length (insn))
6605 {
6606 case 4:
6607 return \"b%d3\\t%l4\";
6608 case 6:
6609 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6610 default:
6611 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6612 }
6613 }
6614 "
6615 [(set (attr "far_jump")
6616 (if_then_else
6617 (eq_attr "length" "8")
6618 (const_string "yes")
6619 (const_string "no")))
6620 (set (attr "length")
6621 (if_then_else
6622 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6623 (le (minus (match_dup 4) (pc)) (const_int 256)))
6624 (const_int 4)
6625 (if_then_else
6626 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6627 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6628 (const_int 6)
6629 (const_int 8))))]
6630)
6631
6632(define_insn "*subsi3_cbranch"
6633 [(set (pc)
6634 (if_then_else
6635 (match_operator 4 "comparison_operator"
6636 [(minus:SI
6637 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6638 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6639 (const_int 0)])
6640 (label_ref (match_operand 5 "" ""))
6641 (pc)))
aeac46d4 6642 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6643 (minus:SI (match_dup 2) (match_dup 3)))
6644 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6645 "TARGET_THUMB
6646 && (GET_CODE (operands[4]) == EQ
6647 || GET_CODE (operands[4]) == NE
6648 || GET_CODE (operands[4]) == GE
6649 || GET_CODE (operands[4]) == LT)"
6650 "*
6651 {
6652 if (which_alternative == 0)
6653 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6654 else if (which_alternative == 1)
6655 {
6656 /* We must provide an alternative for a hi reg because reload
6657 cannot handle output reloads on a jump instruction, but we
6658 can't subtract into that. Fortunately a mov from lo to hi
6659 does not clobber the condition codes. */
6660 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6661 output_asm_insn (\"mov\\t%0, %1\", operands);
6662 }
6663 else
6664 {
6665 /* Similarly, but the target is memory. */
6666 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6667 output_asm_insn (\"str\\t%1, %0\", operands);
6668 }
6669
6670 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6671 {
6672 case 4:
6673 return \"b%d4\\t%l5\";
6674 case 6:
6675 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6676 default:
6677 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6678 }
6679 }
6680 "
6681 [(set (attr "far_jump")
6682 (if_then_else
6683 (ior (and (eq (symbol_ref ("which_alternative"))
6684 (const_int 0))
6685 (eq_attr "length" "8"))
6686 (eq_attr "length" "10"))
6687 (const_string "yes")
6688 (const_string "no")))
6689 (set (attr "length")
6690 (if_then_else
6691 (eq (symbol_ref ("which_alternative"))
6692 (const_int 0))
6693 (if_then_else
6694 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6695 (le (minus (match_dup 5) (pc)) (const_int 256)))
6696 (const_int 4)
6697 (if_then_else
6698 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6699 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6700 (const_int 6)
6701 (const_int 8)))
6702 (if_then_else
6703 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6704 (le (minus (match_dup 5) (pc)) (const_int 256)))
6705 (const_int 6)
6706 (if_then_else
6707 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6708 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6709 (const_int 8)
6710 (const_int 10)))))]
6711)
6712
6713(define_insn "*subsi3_cbranch_scratch"
6714 [(set (pc)
6715 (if_then_else
6716 (match_operator 0 "arm_comparison_operator"
6717 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6718 (match_operand:SI 2 "nonmemory_operand" "l"))
6719 (const_int 0)])
6720 (label_ref (match_operand 3 "" ""))
6721 (pc)))]
6722 "TARGET_THUMB
6723 && (GET_CODE (operands[0]) == EQ
6724 || GET_CODE (operands[0]) == NE
6725 || GET_CODE (operands[0]) == GE
6726 || GET_CODE (operands[0]) == LT)"
6727 "*
6728 output_asm_insn (\"cmp\\t%1, %2\", operands);
6729 switch (get_attr_length (insn))
6730 {
6731 case 4: return \"b%d0\\t%l3\";
6732 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6733 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6734 }
6735 "
6736 [(set (attr "far_jump")
6737 (if_then_else
6738 (eq_attr "length" "8")
6739 (const_string "yes")
6740 (const_string "no")))
6741 (set (attr "length")
6742 (if_then_else
6743 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6744 (le (minus (match_dup 3) (pc)) (const_int 256)))
6745 (const_int 4)
6746 (if_then_else
6747 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6748 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6749 (const_int 6)
6750 (const_int 8))))]
6751)
6752
9c08d1fa 6753;; Comparison and test insns
6754
6755(define_expand "cmpsi"
aea4c774 6756 [(match_operand:SI 0 "s_register_operand" "")
6757 (match_operand:SI 1 "arm_add_operand" "")]
cffb2a26 6758 "TARGET_ARM"
6759 "{
6760 arm_compare_op0 = operands[0];
6761 arm_compare_op1 = operands[1];
6762 DONE;
6763 }"
6764)
b11cae9e 6765
9c08d1fa 6766(define_expand "cmpsf"
aea4c774 6767 [(match_operand:SF 0 "s_register_operand" "")
a2cd141b 6768 (match_operand:SF 1 "arm_float_compare_operand" "")]
6769 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6770 "
9c08d1fa 6771 arm_compare_op0 = operands[0];
6772 arm_compare_op1 = operands[1];
9c08d1fa 6773 DONE;
215b30b3 6774 "
6775)
b11cae9e 6776
9c08d1fa 6777(define_expand "cmpdf"
aea4c774 6778 [(match_operand:DF 0 "s_register_operand" "")
a2cd141b 6779 (match_operand:DF 1 "arm_float_compare_operand" "")]
6780 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6781 "
9c08d1fa 6782 arm_compare_op0 = operands[0];
6783 arm_compare_op1 = operands[1];
9c08d1fa 6784 DONE;
215b30b3 6785 "
6786)
b11cae9e 6787
cffb2a26 6788(define_insn "*arm_cmpsi_insn"
bd5b4116 6789 [(set (reg:CC CC_REGNUM)
aea4c774 6790 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 6791 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6792 "TARGET_ARM"
5565501b 6793 "@
aea4c774 6794 cmp%?\\t%0, %1
6795 cmn%?\\t%0, #%n1"
cffb2a26 6796 [(set_attr "conds" "set")]
6797)
b11cae9e 6798
aea4c774 6799(define_insn "*cmpsi_shiftsi"
bd5b4116 6800 [(set (reg:CC CC_REGNUM)
cffb2a26 6801 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6802 (match_operator:SI 3 "shift_operator"
aea4c774 6803 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 6804 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6805 "TARGET_ARM"
aea4c774 6806 "cmp%?\\t%0, %1%S3"
344495ea 6807 [(set_attr "conds" "set")
331beb1a 6808 (set_attr "shift" "1")
a2cd141b 6809 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6810 (const_string "alu_shift")
6811 (const_string "alu_shift_reg")))]
0d66636f 6812)
b11cae9e 6813
aea4c774 6814(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6815 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6816 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6817 [(match_operand:SI 1 "s_register_operand" "r")
6818 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6819 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6820 "TARGET_ARM"
aea4c774 6821 "cmp%?\\t%0, %1%S3"
344495ea 6822 [(set_attr "conds" "set")
331beb1a 6823 (set_attr "shift" "1")
a2cd141b 6824 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6825 (const_string "alu_shift")
6826 (const_string "alu_shift_reg")))]
0d66636f 6827)
b11cae9e 6828
aed179ae 6829(define_insn "*cmpsi_negshiftsi_si"
6830 [(set (reg:CC_Z CC_REGNUM)
6831 (compare:CC_Z
6832 (neg:SI (match_operator:SI 1 "shift_operator"
6833 [(match_operand:SI 2 "s_register_operand" "r")
6834 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6835 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6836 "TARGET_ARM"
aed179ae 6837 "cmn%?\\t%0, %2%S1"
344495ea 6838 [(set_attr "conds" "set")
aed179ae 6839 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6840 (const_string "alu_shift")
6841 (const_string "alu_shift_reg")))]
0d66636f 6842)
b11cae9e 6843
7d57ec45 6844;; Cirrus SF compare instruction
6845(define_insn "*cirrus_cmpsf"
6846 [(set (reg:CCFP CC_REGNUM)
6847 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6848 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 6849 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6850 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 6851 [(set_attr "type" "mav_farith")
7d57ec45 6852 (set_attr "cirrus" "compare")]
6853)
6854
6855;; Cirrus DF compare instruction
6856(define_insn "*cirrus_cmpdf"
6857 [(set (reg:CCFP CC_REGNUM)
6858 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6859 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 6860 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6861 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 6862 [(set_attr "type" "mav_farith")
7d57ec45 6863 (set_attr "cirrus" "compare")]
6864)
6865
6866;; Cirrus DI compare instruction
6867(define_expand "cmpdi"
6868 [(match_operand:DI 0 "cirrus_fp_register" "")
6869 (match_operand:DI 1 "cirrus_fp_register" "")]
a2cd141b 6870 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6871 "{
6872 arm_compare_op0 = operands[0];
6873 arm_compare_op1 = operands[1];
6874 DONE;
6875 }")
6876
6877(define_insn "*cirrus_cmpdi"
6878 [(set (reg:CC CC_REGNUM)
6879 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6880 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 6881 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6882 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 6883 [(set_attr "type" "mav_farith")
7d57ec45 6884 (set_attr "cirrus" "compare")]
6885)
6886
9c08d1fa 6887; This insn allows redundant compares to be removed by cse, nothing should
6888; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6889; is deleted later on. The match_dup will match the mode here, so that
6890; mode changes of the condition codes aren't lost by this even though we don't
6891; specify what they are.
6892
8a18b90c 6893(define_insn "*deleted_compare"
9c08d1fa 6894 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
cffb2a26 6895 "TARGET_ARM"
40dbec34 6896 "\\t%@ deleted compare"
cffb2a26 6897 [(set_attr "conds" "set")
6898 (set_attr "length" "0")]
6899)
9c08d1fa 6900
6901\f
6902;; Conditional branch insns
6903
6904(define_expand "beq"
6905 [(set (pc)
6906 (if_then_else (eq (match_dup 1) (const_int 0))
6907 (label_ref (match_operand 0 "" ""))
6908 (pc)))]
cffb2a26 6909 "TARGET_ARM"
6910 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6911)
5c951228 6912
9c08d1fa 6913(define_expand "bne"
6914 [(set (pc)
6915 (if_then_else (ne (match_dup 1) (const_int 0))
6916 (label_ref (match_operand 0 "" ""))
6917 (pc)))]
cffb2a26 6918 "TARGET_ARM"
6919 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6920)
5c951228 6921
9c08d1fa 6922(define_expand "bgt"
6923 [(set (pc)
6924 (if_then_else (gt (match_dup 1) (const_int 0))
6925 (label_ref (match_operand 0 "" ""))
6926 (pc)))]
cffb2a26 6927 "TARGET_ARM"
6928 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6929)
5c951228 6930
9c08d1fa 6931(define_expand "ble"
6932 [(set (pc)
6933 (if_then_else (le (match_dup 1) (const_int 0))
6934 (label_ref (match_operand 0 "" ""))
6935 (pc)))]
cffb2a26 6936 "TARGET_ARM"
6937 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6938)
5c951228 6939
9c08d1fa 6940(define_expand "bge"
6941 [(set (pc)
6942 (if_then_else (ge (match_dup 1) (const_int 0))
6943 (label_ref (match_operand 0 "" ""))
6944 (pc)))]
cffb2a26 6945 "TARGET_ARM"
6946 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6947)
5c951228 6948
9c08d1fa 6949(define_expand "blt"
6950 [(set (pc)
6951 (if_then_else (lt (match_dup 1) (const_int 0))
6952 (label_ref (match_operand 0 "" ""))
6953 (pc)))]
cffb2a26 6954 "TARGET_ARM"
6955 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6956)
5c951228 6957
9c08d1fa 6958(define_expand "bgtu"
6959 [(set (pc)
6960 (if_then_else (gtu (match_dup 1) (const_int 0))
6961 (label_ref (match_operand 0 "" ""))
6962 (pc)))]
cffb2a26 6963 "TARGET_ARM"
6964 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6965)
5c951228 6966
9c08d1fa 6967(define_expand "bleu"
b11cae9e 6968 [(set (pc)
9c08d1fa 6969 (if_then_else (leu (match_dup 1) (const_int 0))
6970 (label_ref (match_operand 0 "" ""))
6971 (pc)))]
cffb2a26 6972 "TARGET_ARM"
6973 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6974)
b11cae9e 6975
9c08d1fa 6976(define_expand "bgeu"
b11cae9e 6977 [(set (pc)
9c08d1fa 6978 (if_then_else (geu (match_dup 1) (const_int 0))
6979 (label_ref (match_operand 0 "" ""))
6980 (pc)))]
cffb2a26 6981 "TARGET_ARM"
6982 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6983)
b11cae9e 6984
9c08d1fa 6985(define_expand "bltu"
6986 [(set (pc)
6987 (if_then_else (ltu (match_dup 1) (const_int 0))
6988 (label_ref (match_operand 0 "" ""))
6989 (pc)))]
cffb2a26 6990 "TARGET_ARM"
6991 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6992)
b11cae9e 6993
8fa3ba89 6994(define_expand "bunordered"
6995 [(set (pc)
6996 (if_then_else (unordered (match_dup 1) (const_int 0))
6997 (label_ref (match_operand 0 "" ""))
6998 (pc)))]
c0e1af52 6999 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7000 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7001 arm_compare_op1);"
7002)
7003
7004(define_expand "bordered"
7005 [(set (pc)
7006 (if_then_else (ordered (match_dup 1) (const_int 0))
7007 (label_ref (match_operand 0 "" ""))
7008 (pc)))]
c0e1af52 7009 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7010 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7011 arm_compare_op1);"
7012)
7013
7014(define_expand "bungt"
7015 [(set (pc)
7016 (if_then_else (ungt (match_dup 1) (const_int 0))
7017 (label_ref (match_operand 0 "" ""))
7018 (pc)))]
c0e1af52 7019 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7020 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7021)
7022
7023(define_expand "bunlt"
7024 [(set (pc)
7025 (if_then_else (unlt (match_dup 1) (const_int 0))
7026 (label_ref (match_operand 0 "" ""))
7027 (pc)))]
c0e1af52 7028 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7029 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7030)
7031
7032(define_expand "bunge"
7033 [(set (pc)
7034 (if_then_else (unge (match_dup 1) (const_int 0))
7035 (label_ref (match_operand 0 "" ""))
7036 (pc)))]
c0e1af52 7037 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7038 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7039)
7040
7041(define_expand "bunle"
7042 [(set (pc)
7043 (if_then_else (unle (match_dup 1) (const_int 0))
7044 (label_ref (match_operand 0 "" ""))
7045 (pc)))]
c0e1af52 7046 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7047 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7048)
7049
7050;; The following two patterns need two branch instructions, since there is
7051;; no single instruction that will handle all cases.
7052(define_expand "buneq"
7053 [(set (pc)
7054 (if_then_else (uneq (match_dup 1) (const_int 0))
7055 (label_ref (match_operand 0 "" ""))
7056 (pc)))]
c0e1af52 7057 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7058 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7059)
7060
7061(define_expand "bltgt"
7062 [(set (pc)
7063 (if_then_else (ltgt (match_dup 1) (const_int 0))
7064 (label_ref (match_operand 0 "" ""))
7065 (pc)))]
c0e1af52 7066 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7067 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7068)
7069
7070;;
7071;; Patterns to match conditional branch insns.
7072;;
7073
7074; Special pattern to match UNEQ.
7075(define_insn "*arm_buneq"
7076 [(set (pc)
7077 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7078 (label_ref (match_operand 0 "" ""))
7079 (pc)))]
c0e1af52 7080 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7081 "*
ed29c566 7082 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7083
278b301d 7084 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7085 "
7086 [(set_attr "conds" "jump_clob")
7087 (set_attr "length" "8")]
7088)
7089
7090; Special pattern to match LTGT.
7091(define_insn "*arm_bltgt"
7092 [(set (pc)
7093 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7094 (label_ref (match_operand 0 "" ""))
7095 (pc)))]
c0e1af52 7096 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7097 "*
ed29c566 7098 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7099
278b301d 7100 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7101 "
7102 [(set_attr "conds" "jump_clob")
7103 (set_attr "length" "8")]
7104)
9c08d1fa 7105
cffb2a26 7106(define_insn "*arm_cond_branch"
9c08d1fa 7107 [(set (pc)
8fa3ba89 7108 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7109 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7110 (label_ref (match_operand 0 "" ""))
7111 (pc)))]
cffb2a26 7112 "TARGET_ARM"
d75350ce 7113 "*
9c08d1fa 7114 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7115 {
7116 arm_ccfsm_state += 2;
7117 return \"\";
7118 }
e2348bcb 7119 return \"b%d1\\t%l0\";
cffb2a26 7120 "
a2cd141b 7121 [(set_attr "conds" "use")
7122 (set_attr "type" "branch")]
cffb2a26 7123)
d75350ce 7124
8fa3ba89 7125; Special pattern to match reversed UNEQ.
7126(define_insn "*arm_buneq_reversed"
7127 [(set (pc)
7128 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7129 (pc)
7130 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7131 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7132 "*
ed29c566 7133 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7134
278b301d 7135 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7136 "
7137 [(set_attr "conds" "jump_clob")
7138 (set_attr "length" "8")]
7139)
7140
7141; Special pattern to match reversed LTGT.
7142(define_insn "*arm_bltgt_reversed"
7143 [(set (pc)
7144 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7145 (pc)
7146 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7147 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7148 "*
ed29c566 7149 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7150
278b301d 7151 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7152 "
7153 [(set_attr "conds" "jump_clob")
7154 (set_attr "length" "8")]
7155)
7156
cffb2a26 7157(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7158 [(set (pc)
8fa3ba89 7159 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7160 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7161 (pc)
7162 (label_ref (match_operand 0 "" ""))))]
cffb2a26 7163 "TARGET_ARM"
d75350ce 7164 "*
9c08d1fa 7165 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7166 {
7167 arm_ccfsm_state += 2;
7168 return \"\";
7169 }
e2348bcb 7170 return \"b%D1\\t%l0\";
cffb2a26 7171 "
a2cd141b 7172 [(set_attr "conds" "use")
7173 (set_attr "type" "branch")]
cffb2a26 7174)
7175
b11cae9e 7176\f
9c08d1fa 7177
7178; scc insns
7179
7180(define_expand "seq"
7db9af5d 7181 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7182 (eq:SI (match_dup 1) (const_int 0)))]
cffb2a26 7183 "TARGET_ARM"
7184 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7185)
9c08d1fa 7186
7187(define_expand "sne"
7db9af5d 7188 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7189 (ne:SI (match_dup 1) (const_int 0)))]
cffb2a26 7190 "TARGET_ARM"
7191 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7192)
9c08d1fa 7193
7194(define_expand "sgt"
7db9af5d 7195 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7196 (gt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7197 "TARGET_ARM"
7198 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7199)
9c08d1fa 7200
7201(define_expand "sle"
7db9af5d 7202 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7203 (le:SI (match_dup 1) (const_int 0)))]
cffb2a26 7204 "TARGET_ARM"
7205 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7206)
9c08d1fa 7207
7208(define_expand "sge"
7db9af5d 7209 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7210 (ge:SI (match_dup 1) (const_int 0)))]
cffb2a26 7211 "TARGET_ARM"
7212 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7213)
9c08d1fa 7214
7215(define_expand "slt"
7db9af5d 7216 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7217 (lt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7218 "TARGET_ARM"
7219 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7220)
9c08d1fa 7221
7222(define_expand "sgtu"
7db9af5d 7223 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7224 (gtu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7225 "TARGET_ARM"
7226 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7227)
9c08d1fa 7228
7229(define_expand "sleu"
7db9af5d 7230 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7231 (leu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7232 "TARGET_ARM"
7233 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7234)
9c08d1fa 7235
7236(define_expand "sgeu"
7db9af5d 7237 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7238 (geu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7239 "TARGET_ARM"
7240 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7241)
9c08d1fa 7242
7243(define_expand "sltu"
7db9af5d 7244 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7245 (ltu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7246 "TARGET_ARM"
7247 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7248)
9c08d1fa 7249
8fa3ba89 7250(define_expand "sunordered"
7db9af5d 7251 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7252 (unordered:SI (match_dup 1) (const_int 0)))]
c0e1af52 7253 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7254 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7255 arm_compare_op1);"
7256)
7257
7258(define_expand "sordered"
7db9af5d 7259 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7260 (ordered:SI (match_dup 1) (const_int 0)))]
c0e1af52 7261 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7262 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7263 arm_compare_op1);"
7264)
7265
7266(define_expand "sungt"
7db9af5d 7267 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7268 (ungt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7269 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7270 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7271 arm_compare_op1);"
7272)
7273
7274(define_expand "sunge"
7db9af5d 7275 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7276 (unge:SI (match_dup 1) (const_int 0)))]
c0e1af52 7277 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7278 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7279 arm_compare_op1);"
7280)
7281
7282(define_expand "sunlt"
7db9af5d 7283 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7284 (unlt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7285 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7286 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7287 arm_compare_op1);"
7288)
7289
7290(define_expand "sunle"
7db9af5d 7291 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7292 (unle:SI (match_dup 1) (const_int 0)))]
c0e1af52 7293 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7294 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7295 arm_compare_op1);"
7296)
7297
7298;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7299;;; simple ARM instructions.
7300;
7301; (define_expand "suneq"
7db9af5d 7302; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7303; (uneq:SI (match_dup 1) (const_int 0)))]
c0e1af52 7304; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7305; "gcc_unreachable ();"
8fa3ba89 7306; )
7307;
7308; (define_expand "sltgt"
7db9af5d 7309; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7310; (ltgt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7311; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7312; "gcc_unreachable ();"
8fa3ba89 7313; )
7314
f7fbdd4a 7315(define_insn "*mov_scc"
9c08d1fa 7316 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7317 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7318 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7319 "TARGET_ARM"
4d61e570 7320 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7321 [(set_attr "conds" "use")
7322 (set_attr "length" "8")]
7323)
9c08d1fa 7324
f7fbdd4a 7325(define_insn "*mov_negscc"
9c08d1fa 7326 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7327 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7328 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7329 "TARGET_ARM"
4d61e570 7330 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7331 [(set_attr "conds" "use")
7332 (set_attr "length" "8")]
7333)
9c08d1fa 7334
f7fbdd4a 7335(define_insn "*mov_notscc"
9c08d1fa 7336 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7337 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7338 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7339 "TARGET_ARM"
4d61e570 7340 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7341 [(set_attr "conds" "use")
7342 (set_attr "length" "8")]
7343)
9c08d1fa 7344
7345\f
39b5e676 7346;; Conditional move insns
7347
7348(define_expand "movsicc"
8a18b90c 7349 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7350 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7351 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7352 (match_operand:SI 3 "arm_not_operand" "")))]
cffb2a26 7353 "TARGET_ARM"
39b5e676 7354 "
215b30b3 7355 {
7356 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7357 rtx ccreg;
7358
7359 if (code == UNEQ || code == LTGT)
7360 FAIL;
39b5e676 7361
278b301d 7362 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7363 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7364 }"
7365)
39b5e676 7366
7367(define_expand "movsfcc"
8a18b90c 7368 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7369 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7370 (match_operand:SF 2 "s_register_operand" "")
7371 (match_operand:SF 3 "nonmemory_operand" "")))]
cffb2a26 7372 "TARGET_ARM"
39b5e676 7373 "
215b30b3 7374 {
7375 enum rtx_code code = GET_CODE (operands[1]);
7376 rtx ccreg;
f082f1c4 7377
278b301d 7378 if (code == UNEQ || code == LTGT)
7379 FAIL;
7380
215b30b3 7381 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7382 Otherwise, ensure it is a valid FP add operand */
7383 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7384 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7385 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7386
215b30b3 7387 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7388 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7389 }"
7390)
39b5e676 7391
7392(define_expand "movdfcc"
8a18b90c 7393 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7394 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7395 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7396 (match_operand:DF 3 "arm_float_add_operand" "")))]
7397 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 7398 "
215b30b3 7399 {
7400 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7401 rtx ccreg;
39b5e676 7402
278b301d 7403 if (code == UNEQ || code == LTGT)
7404 FAIL;
7405
7406 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7407 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7408 }"
7409)
39b5e676 7410
7411(define_insn "*movsicc_insn"
f082f1c4 7412 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7413 (if_then_else:SI
8fa3ba89 7414 (match_operator 3 "arm_comparison_operator"
8a18b90c 7415 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7416 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7417 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7418 "TARGET_ARM"
39b5e676 7419 "@
8a18b90c 7420 mov%D3\\t%0, %2
7421 mvn%D3\\t%0, #%B2
f082f1c4 7422 mov%d3\\t%0, %1
7423 mvn%d3\\t%0, #%B1
8a18b90c 7424 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7425 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7426 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7427 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7428 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 7429 (set_attr "conds" "use")]
7430)
39b5e676 7431
39b5e676 7432(define_insn "*movsfcc_soft_insn"
f082f1c4 7433 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7434 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7435 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7436 (match_operand:SF 1 "s_register_operand" "0,r")
7437 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7438 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7439 "@
7440 mov%D3\\t%0, %2
7441 mov%d3\\t%0, %1"
8fa3ba89 7442 [(set_attr "conds" "use")]
7443)
39b5e676 7444
39b5e676 7445\f
9c08d1fa 7446;; Jump and linkage insns
7447
cffb2a26 7448(define_expand "jump"
9c08d1fa 7449 [(set (pc)
7450 (label_ref (match_operand 0 "" "")))]
cffb2a26 7451 "TARGET_EITHER"
9c08d1fa 7452 ""
cffb2a26 7453)
7454
7455(define_insn "*arm_jump"
7456 [(set (pc)
7457 (label_ref (match_operand 0 "" "")))]
7458 "TARGET_ARM"
9c08d1fa 7459 "*
0d66636f 7460 {
7461 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7462 {
7463 arm_ccfsm_state += 2;
7464 return \"\";
7465 }
7466 return \"b%?\\t%l0\";
7467 }
7468 "
7469 [(set_attr "predicable" "yes")]
7470)
9c08d1fa 7471
cffb2a26 7472(define_insn "*thumb_jump"
7473 [(set (pc)
7474 (label_ref (match_operand 0 "" "")))]
7475 "TARGET_THUMB"
7476 "*
7477 if (get_attr_length (insn) == 2)
7478 return \"b\\t%l0\";
7479 return \"bl\\t%l0\\t%@ far jump\";
7480 "
7481 [(set (attr "far_jump")
7482 (if_then_else
7483 (eq_attr "length" "4")
7484 (const_string "yes")
7485 (const_string "no")))
7486 (set (attr "length")
7487 (if_then_else
911ed8af 7488 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7489 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7490 (const_int 2)
7491 (const_int 4)))]
7492)
7493
d3373b54 7494(define_expand "call"
7495 [(parallel [(call (match_operand 0 "memory_operand" "")
7496 (match_operand 1 "general_operand" ""))
cffb2a26 7497 (use (match_operand 2 "" ""))
bd5b4116 7498 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7499 "TARGET_EITHER"
6c4c2133 7500 "
7501 {
78fe751b 7502 rtx callee;
bbe777ea 7503
bbe777ea 7504 /* In an untyped call, we can get NULL for operand 2. */
7505 if (operands[2] == NULL_RTX)
7506 operands[2] = const0_rtx;
7507
78fe751b 7508 /* This is to decide if we should generate indirect calls by loading the
7509 32 bit address of the callee into a register before performing the
7510 branch and link. operand[2] encodes the long_call/short_call
7511 attribute of the function being called. This attribute is set whenever
7512 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7513 is used, and the short_call attribute can also be set if function is
7514 declared as static or if it has already been defined in the current
7515 compilation unit. See arm.c and arm.h for info about this. The third
7516 parameter to arm_is_longcall_p is used to tell it which pattern
7517 invoked it. */
7518 callee = XEXP (operands[0], 0);
7519
e44b56b6 7520 if ((GET_CODE (callee) == SYMBOL_REF
7521 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7522 || (GET_CODE (callee) != SYMBOL_REF
7523 && GET_CODE (callee) != REG))
bbe777ea 7524 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6c4c2133 7525 }"
7526)
d3373b54 7527
f1039640 7528(define_insn "*call_reg_armv5"
d3373b54 7529 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7530 (match_operand 1 "" ""))
7531 (use (match_operand 2 "" ""))
bd5b4116 7532 (clobber (reg:SI LR_REGNUM))]
f1039640 7533 "TARGET_ARM && arm_arch5"
7534 "blx%?\\t%0"
7535 [(set_attr "type" "call")]
7536)
7537
7538(define_insn "*call_reg_arm"
7539 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7540 (match_operand 1 "" ""))
7541 (use (match_operand 2 "" ""))
7542 (clobber (reg:SI LR_REGNUM))]
7543 "TARGET_ARM && !arm_arch5"
9c08d1fa 7544 "*
5565501b 7545 return output_call (operands);
cffb2a26 7546 "
7547 ;; length is worst case, normally it is only two
7548 [(set_attr "length" "12")
7549 (set_attr "type" "call")]
7550)
9c08d1fa 7551
f7fbdd4a 7552(define_insn "*call_mem"
6c4c2133 7553 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
cffb2a26 7554 (match_operand 1 "" ""))
7555 (use (match_operand 2 "" ""))
bd5b4116 7556 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7557 "TARGET_ARM"
9c08d1fa 7558 "*
5565501b 7559 return output_call_mem (operands);
cffb2a26 7560 "
7561 [(set_attr "length" "12")
7562 (set_attr "type" "call")]
7563)
7564
f1039640 7565(define_insn "*call_reg_thumb_v5"
cffb2a26 7566 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7567 (match_operand 1 "" ""))
7568 (use (match_operand 2 "" ""))
bd5b4116 7569 (clobber (reg:SI LR_REGNUM))]
f1039640 7570 "TARGET_THUMB && arm_arch5"
7571 "blx\\t%0"
7572 [(set_attr "length" "2")
7573 (set_attr "type" "call")]
cffb2a26 7574)
7575
f1039640 7576(define_insn "*call_reg_thumb"
7577 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7578 (match_operand 1 "" ""))
7579 (use (match_operand 2 "" ""))
bd5b4116 7580 (clobber (reg:SI LR_REGNUM))]
f1039640 7581 "TARGET_THUMB && !arm_arch5"
cffb2a26 7582 "*
7583 {
150502c9 7584 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7585 return thumb_call_via_reg (operands[0]);
150502c9 7586 else if (operands[1] == const0_rtx)
f1039640 7587 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7588 else if (frame_pointer_needed)
7589 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7590 else
150502c9 7591 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7592 }"
7593 [(set_attr "type" "call")]
7594)
9c08d1fa 7595
d3373b54 7596(define_expand "call_value"
e0698af7 7597 [(parallel [(set (match_operand 0 "" "")
7598 (call (match_operand 1 "memory_operand" "")
7599 (match_operand 2 "general_operand" "")))
cffb2a26 7600 (use (match_operand 3 "" ""))
bd5b4116 7601 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7602 "TARGET_EITHER"
6c4c2133 7603 "
7604 {
bbe777ea 7605 rtx callee = XEXP (operands[1], 0);
7606
7607 /* In an untyped call, we can get NULL for operand 2. */
7608 if (operands[3] == 0)
7609 operands[3] = const0_rtx;
7610
7611 /* See the comment in define_expand \"call\". */
e44b56b6 7612 if ((GET_CODE (callee) == SYMBOL_REF
7613 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7614 || (GET_CODE (callee) != SYMBOL_REF
7615 && GET_CODE (callee) != REG))
78fe751b 7616 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6c4c2133 7617 }"
7618)
d3373b54 7619
f1039640 7620(define_insn "*call_value_reg_armv5"
27ed6835 7621 [(set (match_operand 0 "" "")
755eb2b4 7622 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7623 (match_operand 2 "" "")))
bbe777ea 7624 (use (match_operand 3 "" ""))
bd5b4116 7625 (clobber (reg:SI LR_REGNUM))]
f1039640 7626 "TARGET_ARM && arm_arch5"
7627 "blx%?\\t%1"
7628 [(set_attr "type" "call")]
7629)
7630
7631(define_insn "*call_value_reg_arm"
7632 [(set (match_operand 0 "" "")
7633 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7634 (match_operand 2 "" "")))
7635 (use (match_operand 3 "" ""))
7636 (clobber (reg:SI LR_REGNUM))]
7637 "TARGET_ARM && !arm_arch5"
9c08d1fa 7638 "*
215b30b3 7639 return output_call (&operands[1]);
cffb2a26 7640 "
7641 [(set_attr "length" "12")
7642 (set_attr "type" "call")]
7643)
9c08d1fa 7644
f7fbdd4a 7645(define_insn "*call_value_mem"
27ed6835 7646 [(set (match_operand 0 "" "")
755eb2b4 7647 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
cffb2a26 7648 (match_operand 2 "" "")))
bbe777ea 7649 (use (match_operand 3 "" ""))
bd5b4116 7650 (clobber (reg:SI LR_REGNUM))]
215b30b3 7651 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7652 "*
215b30b3 7653 return output_call_mem (&operands[1]);
cffb2a26 7654 "
7655 [(set_attr "length" "12")
7656 (set_attr "type" "call")]
7657)
9c08d1fa 7658
f1039640 7659(define_insn "*call_value_reg_thumb_v5"
7660 [(set (match_operand 0 "" "")
7661 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7662 (match_operand 2 "" "")))
7663 (use (match_operand 3 "" ""))
7664 (clobber (reg:SI LR_REGNUM))]
7665 "TARGET_THUMB && arm_arch5"
7666 "blx\\t%1"
7667 [(set_attr "length" "2")
7668 (set_attr "type" "call")]
7669)
7670
7671(define_insn "*call_value_reg_thumb"
7672 [(set (match_operand 0 "" "")
7673 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7674 (match_operand 2 "" "")))
7675 (use (match_operand 3 "" ""))
7676 (clobber (reg:SI LR_REGNUM))]
7677 "TARGET_THUMB && !arm_arch5"
7678 "*
7679 {
150502c9 7680 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7681 return thumb_call_via_reg (operands[1]);
150502c9 7682 else if (operands[2] == const0_rtx)
f1039640 7683 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7684 else if (frame_pointer_needed)
7685 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7686 else
150502c9 7687 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7688 }"
7689 [(set_attr "type" "call")]
7690)
7691
9c08d1fa 7692;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7693;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7694
f7fbdd4a 7695(define_insn "*call_symbol"
27ed6835 7696 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7697 (match_operand 1 "" ""))
bbe777ea 7698 (use (match_operand 2 "" ""))
bd5b4116 7699 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7700 "TARGET_ARM
7701 && (GET_CODE (operands[0]) == SYMBOL_REF)
215b30b3 7702 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6ebaa29d 7703 "*
7704 {
55c1e470 7705 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7706 }"
cffb2a26 7707 [(set_attr "type" "call")]
7708)
9c08d1fa 7709
f7fbdd4a 7710(define_insn "*call_value_symbol"
ccd90aaa 7711 [(set (match_operand 0 "" "")
27ed6835 7712 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7713 (match_operand:SI 2 "" "")))
bbe777ea 7714 (use (match_operand 3 "" ""))
bd5b4116 7715 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7716 "TARGET_ARM
7717 && (GET_CODE (operands[1]) == SYMBOL_REF)
215b30b3 7718 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6ebaa29d 7719 "*
7720 {
55c1e470 7721 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7722 }"
cffb2a26 7723 [(set_attr "type" "call")]
7724)
7725
7726(define_insn "*call_insn"
27ed6835 7727 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7728 (match_operand:SI 1 "" ""))
7729 (use (match_operand 2 "" ""))
bd5b4116 7730 (clobber (reg:SI LR_REGNUM))]
1c494086 7731 "TARGET_THUMB
1675c6e9 7732 && GET_CODE (operands[0]) == SYMBOL_REF
7733 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
cffb2a26 7734 "bl\\t%a0"
7735 [(set_attr "length" "4")
7736 (set_attr "type" "call")]
7737)
7738
7739(define_insn "*call_value_insn"
ccd90aaa 7740 [(set (match_operand 0 "" "")
27ed6835 7741 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 7742 (match_operand 2 "" "")))
7743 (use (match_operand 3 "" ""))
bd5b4116 7744 (clobber (reg:SI LR_REGNUM))]
1c494086 7745 "TARGET_THUMB
1675c6e9 7746 && GET_CODE (operands[1]) == SYMBOL_REF
7747 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
cffb2a26 7748 "bl\\t%a1"
7749 [(set_attr "length" "4")
7750 (set_attr "type" "call")]
7751)
9c08d1fa 7752
1c494086 7753;; We may also be able to do sibcalls for Thumb, but it's much harder...
7754(define_expand "sibcall"
7755 [(parallel [(call (match_operand 0 "memory_operand" "")
7756 (match_operand 1 "general_operand" ""))
2ba80634 7757 (return)
7758 (use (match_operand 2 "" ""))])]
1c494086 7759 "TARGET_ARM"
7760 "
7761 {
7762 if (operands[2] == NULL_RTX)
7763 operands[2] = const0_rtx;
1c494086 7764 }"
7765)
7766
7767(define_expand "sibcall_value"
ccd90aaa 7768 [(parallel [(set (match_operand 0 "" "")
1c494086 7769 (call (match_operand 1 "memory_operand" "")
7770 (match_operand 2 "general_operand" "")))
2ba80634 7771 (return)
7772 (use (match_operand 3 "" ""))])]
1c494086 7773 "TARGET_ARM"
7774 "
7775 {
7776 if (operands[3] == NULL_RTX)
7777 operands[3] = const0_rtx;
1c494086 7778 }"
7779)
7780
7781(define_insn "*sibcall_insn"
7782 [(call (mem:SI (match_operand:SI 0 "" "X"))
7783 (match_operand 1 "" ""))
2ba80634 7784 (return)
7785 (use (match_operand 2 "" ""))]
1c494086 7786 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7787 "*
7788 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7789 "
7790 [(set_attr "type" "call")]
7791)
7792
7793(define_insn "*sibcall_value_insn"
ccd90aaa 7794 [(set (match_operand 0 "" "")
755eb2b4 7795 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 7796 (match_operand 2 "" "")))
2ba80634 7797 (return)
7798 (use (match_operand 3 "" ""))]
1c494086 7799 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7800 "*
7801 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7802 "
7803 [(set_attr "type" "call")]
7804)
7805
9c08d1fa 7806;; Often the return insn will be the same as loading from memory, so set attr
7807(define_insn "return"
7808 [(return)]
cffb2a26 7809 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7810 "*
9c08d1fa 7811 {
cffb2a26 7812 if (arm_ccfsm_state == 2)
7813 {
7814 arm_ccfsm_state += 2;
7815 return \"\";
7816 }
5db468b7 7817 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 7818 }"
a2cd141b 7819 [(set_attr "type" "load1")
755eb2b4 7820 (set_attr "length" "12")
0d66636f 7821 (set_attr "predicable" "yes")]
cffb2a26 7822)
9c08d1fa 7823
f7fbdd4a 7824(define_insn "*cond_return"
9c08d1fa 7825 [(set (pc)
8fa3ba89 7826 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7827 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7828 (return)
7829 (pc)))]
cffb2a26 7830 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7831 "*
8fa3ba89 7832 {
7833 if (arm_ccfsm_state == 2)
7834 {
7835 arm_ccfsm_state += 2;
7836 return \"\";
7837 }
7838 return output_return_instruction (operands[0], TRUE, FALSE);
7839 }"
7840 [(set_attr "conds" "use")
755eb2b4 7841 (set_attr "length" "12")
a2cd141b 7842 (set_attr "type" "load1")]
8fa3ba89 7843)
9c08d1fa 7844
f7fbdd4a 7845(define_insn "*cond_return_inverted"
9c08d1fa 7846 [(set (pc)
8fa3ba89 7847 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7848 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7849 (pc)
7850 (return)))]
cffb2a26 7851 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7852 "*
8fa3ba89 7853 {
7854 if (arm_ccfsm_state == 2)
7855 {
7856 arm_ccfsm_state += 2;
7857 return \"\";
7858 }
7859 return output_return_instruction (operands[0], TRUE, TRUE);
7860 }"
7861 [(set_attr "conds" "use")
37a1317b 7862 (set_attr "length" "12")
a2cd141b 7863 (set_attr "type" "load1")]
8fa3ba89 7864)
9c08d1fa 7865
68121397 7866;; Generate a sequence of instructions to determine if the processor is
7867;; in 26-bit or 32-bit mode, and return the appropriate return address
7868;; mask.
7869
7870(define_expand "return_addr_mask"
7871 [(set (match_dup 1)
7872 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7873 (const_int 0)))
7874 (set (match_operand:SI 0 "s_register_operand" "")
7875 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7876 (const_int -1)
7877 (const_int 67108860)))] ; 0x03fffffc
7878 "TARGET_ARM"
7879 "
62eddbd4 7880 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7881 ")
7882
7883(define_insn "*check_arch2"
7884 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7885 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7886 (const_int 0)))]
7887 "TARGET_ARM"
7888 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7889 [(set_attr "length" "8")
7890 (set_attr "conds" "set")]
7891)
7892
9c08d1fa 7893;; Call subroutine returning any type.
7894
7895(define_expand "untyped_call"
7896 [(parallel [(call (match_operand 0 "" "")
7897 (const_int 0))
7898 (match_operand 1 "" "")
7899 (match_operand 2 "" "")])]
ccd90aaa 7900 "TARGET_EITHER"
9c08d1fa 7901 "
215b30b3 7902 {
7903 int i;
ccd90aaa 7904 rtx par = gen_rtx_PARALLEL (VOIDmode,
7905 rtvec_alloc (XVECLEN (operands[2], 0)));
7906 rtx addr = gen_reg_rtx (Pmode);
7907 rtx mem;
7908 int size = 0;
9c08d1fa 7909
ccd90aaa 7910 emit_move_insn (addr, XEXP (operands[1], 0));
7911 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7912
215b30b3 7913 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7914 {
ccd90aaa 7915 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7916
ccd90aaa 7917 /* Default code only uses r0 as a return value, but we could
7918 be using anything up to 4 registers. */
7919 if (REGNO (src) == R0_REGNUM)
7920 src = gen_rtx_REG (TImode, R0_REGNUM);
7921
7922 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7923 GEN_INT (size));
7924 size += GET_MODE_SIZE (GET_MODE (src));
7925 }
7926
7927 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7928 const0_rtx));
7929
7930 size = 0;
7931
7932 for (i = 0; i < XVECLEN (par, 0); i++)
7933 {
7934 HOST_WIDE_INT offset = 0;
7935 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7936
7937 if (size != 0)
7938 emit_move_insn (addr, plus_constant (addr, size));
7939
7940 mem = change_address (mem, GET_MODE (reg), NULL);
7941 if (REGNO (reg) == R0_REGNUM)
7942 {
7943 /* On thumb we have to use a write-back instruction. */
7944 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7945 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7946 size = TARGET_ARM ? 16 : 0;
7947 }
7948 else
7949 {
7950 emit_move_insn (mem, reg);
7951 size = GET_MODE_SIZE (GET_MODE (reg));
7952 }
215b30b3 7953 }
9c08d1fa 7954
215b30b3 7955 /* The optimizer does not know that the call sets the function value
7956 registers we stored in the result block. We avoid problems by
7957 claiming that all hard registers are used and clobbered at this
7958 point. */
7959 emit_insn (gen_blockage ());
7960
7961 DONE;
7962 }"
7963)
9c08d1fa 7964
ccd90aaa 7965(define_expand "untyped_return"
7966 [(match_operand:BLK 0 "memory_operand" "")
7967 (match_operand 1 "" "")]
7968 "TARGET_EITHER"
7969 "
7970 {
7971 int i;
7972 rtx addr = gen_reg_rtx (Pmode);
7973 rtx mem;
7974 int size = 0;
7975
7976 emit_move_insn (addr, XEXP (operands[0], 0));
7977 mem = change_address (operands[0], BLKmode, addr);
7978
7979 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7980 {
7981 HOST_WIDE_INT offset = 0;
7982 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7983
7984 if (size != 0)
7985 emit_move_insn (addr, plus_constant (addr, size));
7986
7987 mem = change_address (mem, GET_MODE (reg), NULL);
7988 if (REGNO (reg) == R0_REGNUM)
7989 {
7990 /* On thumb we have to use a write-back instruction. */
7991 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7992 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7993 size = TARGET_ARM ? 16 : 0;
7994 }
7995 else
7996 {
7997 emit_move_insn (reg, mem);
7998 size = GET_MODE_SIZE (GET_MODE (reg));
7999 }
8000 }
8001
8002 /* Emit USE insns before the return. */
8003 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8004 emit_insn (gen_rtx_USE (VOIDmode,
8005 SET_DEST (XVECEXP (operands[1], 0, i))));
8006
8007 /* Construct the return. */
8008 expand_naked_return ();
8009
8010 DONE;
8011 }"
8012)
8013
9c08d1fa 8014;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8015;; all of memory. This blocks insns from being moved across this point.
8016
8017(define_insn "blockage"
e1159bbe 8018 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8019 "TARGET_EITHER"
9c08d1fa 8020 ""
cffb2a26 8021 [(set_attr "length" "0")
8022 (set_attr "type" "block")]
8023)
9c08d1fa 8024
f7fbdd4a 8025(define_expand "casesi"
8026 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8027 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8028 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8029 (match_operand:SI 3 "" "") ; table label
8030 (match_operand:SI 4 "" "")] ; Out of range label
cffb2a26 8031 "TARGET_ARM"
f7fbdd4a 8032 "
215b30b3 8033 {
8034 rtx reg;
8035 if (operands[1] != const0_rtx)
8036 {
8037 reg = gen_reg_rtx (SImode);
f7fbdd4a 8038
215b30b3 8039 emit_insn (gen_addsi3 (reg, operands[0],
8040 GEN_INT (-INTVAL (operands[1]))));
8041 operands[0] = reg;
8042 }
9c08d1fa 8043
215b30b3 8044 if (!const_ok_for_arm (INTVAL (operands[2])))
8045 operands[2] = force_reg (SImode, operands[2]);
8046
8047 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8048 operands[4]));
8049 DONE;
8050 }"
8051)
f7fbdd4a 8052
f082f1c4 8053;; The USE in this pattern is needed to tell flow analysis that this is
8054;; a CASESI insn. It has no other purpose.
f7fbdd4a 8055(define_insn "casesi_internal"
f082f1c4 8056 [(parallel [(set (pc)
8057 (if_then_else
8058 (leu (match_operand:SI 0 "s_register_operand" "r")
8059 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8060 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8061 (label_ref (match_operand 2 "" ""))))
8062 (label_ref (match_operand 3 "" ""))))
bd5b4116 8063 (clobber (reg:CC CC_REGNUM))
f082f1c4 8064 (use (label_ref (match_dup 2)))])]
cffb2a26 8065 "TARGET_ARM"
f7fbdd4a 8066 "*
0d66636f 8067 if (flag_pic)
8068 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8069 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8070 "
8071 [(set_attr "conds" "clob")
8072 (set_attr "length" "12")]
8073)
9c08d1fa 8074
cffb2a26 8075(define_expand "indirect_jump"
9c08d1fa 8076 [(set (pc)
cffb2a26 8077 (match_operand:SI 0 "s_register_operand" ""))]
8078 "TARGET_EITHER"
9c08d1fa 8079 ""
cffb2a26 8080)
8081
f1039640 8082;; NB Never uses BX.
cffb2a26 8083(define_insn "*arm_indirect_jump"
8084 [(set (pc)
8085 (match_operand:SI 0 "s_register_operand" "r"))]
8086 "TARGET_ARM"
8087 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8088 [(set_attr "predicable" "yes")]
cffb2a26 8089)
9c08d1fa 8090
f7fbdd4a 8091(define_insn "*load_indirect_jump"
9c08d1fa 8092 [(set (pc)
8093 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8094 "TARGET_ARM"
8095 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8096 [(set_attr "type" "load1")
61a2d04c 8097 (set_attr "pool_range" "4096")
8098 (set_attr "neg_pool_range" "4084")
0d66636f 8099 (set_attr "predicable" "yes")]
cffb2a26 8100)
8101
f1039640 8102;; NB Never uses BX.
cffb2a26 8103(define_insn "*thumb_indirect_jump"
8104 [(set (pc)
8105 (match_operand:SI 0 "register_operand" "l*r"))]
8106 "TARGET_THUMB"
8107 "mov\\tpc, %0"
8108 [(set_attr "conds" "clob")
8109 (set_attr "length" "2")]
8110)
8111
9c08d1fa 8112\f
8113;; Misc insns
8114
8115(define_insn "nop"
8116 [(const_int 0)]
cffb2a26 8117 "TARGET_EITHER"
8118 "*
8119 if (TARGET_ARM)
8120 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8121 return \"mov\\tr8, r8\";
8122 "
8123 [(set (attr "length")
8124 (if_then_else (eq_attr "is_thumb" "yes")
8125 (const_int 2)
8126 (const_int 4)))]
8127)
8128
9c08d1fa 8129\f
8130;; Patterns to allow combination of arithmetic, cond code and shifts
8131
f7fbdd4a 8132(define_insn "*arith_shiftsi"
9c08d1fa 8133 [(set (match_operand:SI 0 "s_register_operand" "=r")
8134 (match_operator:SI 1 "shiftable_operator"
8135 [(match_operator:SI 3 "shift_operator"
8136 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8137 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8138 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8139 "TARGET_ARM"
6c4c2133 8140 "%i1%?\\t%0, %2, %4%S3"
344495ea 8141 [(set_attr "predicable" "yes")
331beb1a 8142 (set_attr "shift" "4")
a2cd141b 8143 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8144 (const_string "alu_shift")
8145 (const_string "alu_shift_reg")))]
6c4c2133 8146)
9c08d1fa 8147
d7863cfe 8148(define_split
8149 [(set (match_operand:SI 0 "s_register_operand" "")
8150 (match_operator:SI 1 "shiftable_operator"
8151 [(match_operator:SI 2 "shiftable_operator"
8152 [(match_operator:SI 3 "shift_operator"
8153 [(match_operand:SI 4 "s_register_operand" "")
8154 (match_operand:SI 5 "reg_or_int_operand" "")])
8155 (match_operand:SI 6 "s_register_operand" "")])
8156 (match_operand:SI 7 "arm_rhs_operand" "")]))
8157 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8158 "TARGET_ARM"
8159 [(set (match_dup 8)
8160 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8161 (match_dup 6)]))
8162 (set (match_dup 0)
8163 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8164 "")
8165
f7fbdd4a 8166(define_insn "*arith_shiftsi_compare0"
bd5b4116 8167 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8168 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8169 [(match_operator:SI 3 "shift_operator"
8170 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8171 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8172 (match_operand:SI 2 "s_register_operand" "r")])
8173 (const_int 0)))
8174 (set (match_operand:SI 0 "s_register_operand" "=r")
8175 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8176 (match_dup 2)]))]
cffb2a26 8177 "TARGET_ARM"
87b22bf7 8178 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8179 [(set_attr "conds" "set")
331beb1a 8180 (set_attr "shift" "4")
a2cd141b 8181 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8182 (const_string "alu_shift")
8183 (const_string "alu_shift_reg")))]
0d66636f 8184)
9c08d1fa 8185
f7fbdd4a 8186(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8187 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8188 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8189 [(match_operator:SI 3 "shift_operator"
8190 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8191 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8192 (match_operand:SI 2 "s_register_operand" "r")])
8193 (const_int 0)))
8194 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8195 "TARGET_ARM"
87b22bf7 8196 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8197 [(set_attr "conds" "set")
331beb1a 8198 (set_attr "shift" "4")
a2cd141b 8199 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8200 (const_string "alu_shift")
8201 (const_string "alu_shift_reg")))]
0d66636f 8202)
9c08d1fa 8203
f7fbdd4a 8204(define_insn "*sub_shiftsi"
9c08d1fa 8205 [(set (match_operand:SI 0 "s_register_operand" "=r")
8206 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8207 (match_operator:SI 2 "shift_operator"
8208 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8209 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 8210 "TARGET_ARM"
6c4c2133 8211 "sub%?\\t%0, %1, %3%S2"
344495ea 8212 [(set_attr "predicable" "yes")
331beb1a 8213 (set_attr "shift" "3")
a2cd141b 8214 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8215 (const_string "alu_shift")
8216 (const_string "alu_shift_reg")))]
6c4c2133 8217)
9c08d1fa 8218
f7fbdd4a 8219(define_insn "*sub_shiftsi_compare0"
bd5b4116 8220 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8221 (compare:CC_NOOV
8222 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8223 (match_operator:SI 2 "shift_operator"
8224 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8225 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8226 (const_int 0)))
9c08d1fa 8227 (set (match_operand:SI 0 "s_register_operand" "=r")
8228 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8229 (match_dup 4)])))]
cffb2a26 8230 "TARGET_ARM"
87b22bf7 8231 "sub%?s\\t%0, %1, %3%S2"
344495ea 8232 [(set_attr "conds" "set")
a2cd141b 8233 (set_attr "shift" "3")
8234 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8235 (const_string "alu_shift")
8236 (const_string "alu_shift_reg")))]
0d66636f 8237)
9c08d1fa 8238
f7fbdd4a 8239(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8240 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8241 (compare:CC_NOOV
8242 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8243 (match_operator:SI 2 "shift_operator"
8244 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8245 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8246 (const_int 0)))
9c08d1fa 8247 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8248 "TARGET_ARM"
87b22bf7 8249 "sub%?s\\t%0, %1, %3%S2"
344495ea 8250 [(set_attr "conds" "set")
a2cd141b 8251 (set_attr "shift" "3")
8252 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8253 (const_string "alu_shift")
8254 (const_string "alu_shift_reg")))]
0d66636f 8255)
9c08d1fa 8256
9c08d1fa 8257\f
8258
f7fbdd4a 8259(define_insn "*and_scc"
9c08d1fa 8260 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8261 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8262 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8263 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8264 "TARGET_ARM"
e2348bcb 8265 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8266 [(set_attr "conds" "use")
8267 (set_attr "length" "8")]
8268)
9c08d1fa 8269
f7fbdd4a 8270(define_insn "*ior_scc"
9c08d1fa 8271 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8272 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8273 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8274 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8275 "TARGET_ARM"
e2348bcb 8276 "@
899850b0 8277 orr%d2\\t%0, %1, #1
8278 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8279 [(set_attr "conds" "use")
8280 (set_attr "length" "4,8")]
8281)
9c08d1fa 8282
f7fbdd4a 8283(define_insn "*compare_scc"
5565501b 8284 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8285 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8286 [(match_operand:SI 2 "s_register_operand" "r,r")
8287 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8288 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8289 "TARGET_ARM"
9c08d1fa 8290 "*
601f584c 8291 if (operands[3] == const0_rtx)
8292 {
8293 if (GET_CODE (operands[1]) == LT)
8294 return \"mov\\t%0, %2, lsr #31\";
8295
8296 if (GET_CODE (operands[1]) == GE)
8297 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 8298
601f584c 8299 if (GET_CODE (operands[1]) == EQ)
8300 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8301 }
e2348bcb 8302
8fa3ba89 8303 if (GET_CODE (operands[1]) == NE)
8304 {
8305 if (which_alternative == 1)
8306 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8307 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8308 }
8309 if (which_alternative == 1)
8310 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8311 else
8312 output_asm_insn (\"cmp\\t%2, %3\", operands);
8313 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8314 "
8315 [(set_attr "conds" "clob")
8316 (set_attr "length" "12")]
8317)
9c08d1fa 8318
f7fbdd4a 8319(define_insn "*cond_move"
9c08d1fa 8320 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8321 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8322 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8323 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8324 (const_int 0)])
8325 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8326 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8327 "TARGET_ARM"
9c08d1fa 8328 "*
8fa3ba89 8329 if (GET_CODE (operands[3]) == NE)
8330 {
8331 if (which_alternative != 1)
8332 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8333 if (which_alternative != 0)
8334 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8335 return \"\";
8336 }
8337 if (which_alternative != 0)
8338 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8339 if (which_alternative != 1)
8340 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8341 return \"\";
8342 "
8343 [(set_attr "conds" "use")
8344 (set_attr "length" "4,4,8")]
8345)
9c08d1fa 8346
f7fbdd4a 8347(define_insn "*cond_arith"
9c08d1fa 8348 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8349 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8350 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8351 [(match_operand:SI 2 "s_register_operand" "r,r")
8352 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8353 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8354 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8355 "TARGET_ARM"
9c08d1fa 8356 "*
8fa3ba89 8357 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8358 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8359
8fa3ba89 8360 output_asm_insn (\"cmp\\t%2, %3\", operands);
8361 if (GET_CODE (operands[5]) == AND)
8362 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8363 else if (GET_CODE (operands[5]) == MINUS)
8364 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8365 else if (which_alternative != 0)
8366 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8367 return \"%i5%d4\\t%0, %1, #1\";
8368 "
8369 [(set_attr "conds" "clob")
8370 (set_attr "length" "12")]
8371)
9c08d1fa 8372
f7fbdd4a 8373(define_insn "*cond_sub"
9c08d1fa 8374 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8375 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8376 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8377 [(match_operand:SI 2 "s_register_operand" "r,r")
8378 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8379 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8380 "TARGET_ARM"
9c08d1fa 8381 "*
8fa3ba89 8382 output_asm_insn (\"cmp\\t%2, %3\", operands);
8383 if (which_alternative != 0)
8384 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8385 return \"sub%d4\\t%0, %1, #1\";
8386 "
8387 [(set_attr "conds" "clob")
8388 (set_attr "length" "8,12")]
8389)
9c08d1fa 8390
aea4c774 8391(define_insn "*cmp_ite0"
cffb2a26 8392 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8393 (compare
8394 (if_then_else:SI
8fa3ba89 8395 (match_operator 4 "arm_comparison_operator"
aea4c774 8396 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8397 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8398 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8399 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8400 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8401 (const_int 0))
8402 (const_int 0)))]
cffb2a26 8403 "TARGET_ARM"
9c08d1fa 8404 "*
aea4c774 8405 {
8fa3ba89 8406 static const char * const opcodes[4][2] =
8407 {
8408 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8409 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8410 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8411 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8412 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8413 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8414 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8415 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8416 };
8417 int swap =
8418 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8419
8420 return opcodes[which_alternative][swap];
8421 }"
8422 [(set_attr "conds" "set")
8423 (set_attr "length" "8")]
8424)
9c08d1fa 8425
aea4c774 8426(define_insn "*cmp_ite1"
cffb2a26 8427 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8428 (compare
8429 (if_then_else:SI
8fa3ba89 8430 (match_operator 4 "arm_comparison_operator"
aea4c774 8431 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8432 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8433 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8434 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8435 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8436 (const_int 1))
8437 (const_int 0)))]
cffb2a26 8438 "TARGET_ARM"
9c08d1fa 8439 "*
9c08d1fa 8440 {
215b30b3 8441 static const char * const opcodes[4][2] =
8442 {
8443 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8444 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8445 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8446 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8447 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8448 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8449 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8450 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8451 };
8452 int swap =
8453 comparison_dominates_p (GET_CODE (operands[5]),
8454 reverse_condition (GET_CODE (operands[4])));
8455
8456 return opcodes[which_alternative][swap];
8457 }"
8fa3ba89 8458 [(set_attr "conds" "set")
8459 (set_attr "length" "8")]
8460)
9c08d1fa 8461
f6c53574 8462(define_insn "*cmp_and"
8463 [(set (match_operand 6 "dominant_cc_register" "")
8464 (compare
8465 (and:SI
8466 (match_operator 4 "arm_comparison_operator"
8467 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8468 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8469 (match_operator:SI 5 "arm_comparison_operator"
8470 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8471 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8472 (const_int 0)))]
8473 "TARGET_ARM"
8474 "*
8475 {
35823b64 8476 static const char *const opcodes[4][2] =
f6c53574 8477 {
8478 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8479 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8480 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8481 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8482 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8483 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8484 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8485 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8486 };
8487 int swap =
8488 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8489
8490 return opcodes[which_alternative][swap];
8491 }"
8492 [(set_attr "conds" "set")
8493 (set_attr "predicable" "no")
8494 (set_attr "length" "8")]
8495)
8496
8497(define_insn "*cmp_ior"
8498 [(set (match_operand 6 "dominant_cc_register" "")
8499 (compare
8500 (ior:SI
8501 (match_operator 4 "arm_comparison_operator"
8502 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8503 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8504 (match_operator:SI 5 "arm_comparison_operator"
8505 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8506 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8507 (const_int 0)))]
8508 "TARGET_ARM"
8509 "*
8510{
35823b64 8511 static const char *const opcodes[4][2] =
f6c53574 8512 {
8513 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8514 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8515 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8516 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8517 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8518 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8519 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8520 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8521 };
8522 int swap =
8523 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8524
8525 return opcodes[which_alternative][swap];
8526}
8527"
8528 [(set_attr "conds" "set")
8529 (set_attr "length" "8")]
8530)
8531
3c5afce6 8532(define_insn_and_split "*ior_scc_scc"
8533 [(set (match_operand:SI 0 "s_register_operand" "=r")
8534 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8535 [(match_operand:SI 1 "s_register_operand" "r")
8536 (match_operand:SI 2 "arm_add_operand" "rIL")])
8537 (match_operator:SI 6 "arm_comparison_operator"
8538 [(match_operand:SI 4 "s_register_operand" "r")
8539 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8540 (clobber (reg:CC CC_REGNUM))]
8541 "TARGET_ARM
8542 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8543 != CCmode)"
8544 "#"
8545 "TARGET_ARM && reload_completed"
8546 [(set (match_dup 7)
8547 (compare
8548 (ior:SI
8549 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8550 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8551 (const_int 0)))
8552 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8553 "operands[7]
8554 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8555 DOM_CC_X_OR_Y),
601f584c 8556 CC_REGNUM);"
8557 [(set_attr "conds" "clob")
8558 (set_attr "length" "16")])
8559
8560; If the above pattern is followed by a CMP insn, then the compare is
8561; redundant, since we can rework the conditional instruction that follows.
8562(define_insn_and_split "*ior_scc_scc_cmp"
8563 [(set (match_operand 0 "dominant_cc_register" "")
8564 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8565 [(match_operand:SI 1 "s_register_operand" "r")
8566 (match_operand:SI 2 "arm_add_operand" "rIL")])
8567 (match_operator:SI 6 "arm_comparison_operator"
8568 [(match_operand:SI 4 "s_register_operand" "r")
8569 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8570 (const_int 0)))
8571 (set (match_operand:SI 7 "s_register_operand" "=r")
8572 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8573 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8574 "TARGET_ARM"
8575 "#"
8576 "TARGET_ARM && reload_completed"
8577 [(set (match_dup 0)
8578 (compare
8579 (ior:SI
8580 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8581 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8582 (const_int 0)))
8583 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8584 ""
8585 [(set_attr "conds" "set")
8586 (set_attr "length" "16")])
3c5afce6 8587
8588(define_insn_and_split "*and_scc_scc"
8589 [(set (match_operand:SI 0 "s_register_operand" "=r")
8590 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8591 [(match_operand:SI 1 "s_register_operand" "r")
8592 (match_operand:SI 2 "arm_add_operand" "rIL")])
8593 (match_operator:SI 6 "arm_comparison_operator"
8594 [(match_operand:SI 4 "s_register_operand" "r")
8595 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8596 (clobber (reg:CC CC_REGNUM))]
8597 "TARGET_ARM
8598 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8599 != CCmode)"
8600 "#"
601f584c 8601 "TARGET_ARM && reload_completed
8602 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8603 != CCmode)"
3c5afce6 8604 [(set (match_dup 7)
8605 (compare
8606 (and:SI
8607 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8608 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8609 (const_int 0)))
8610 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8611 "operands[7]
8612 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8613 DOM_CC_X_AND_Y),
601f584c 8614 CC_REGNUM);"
8615 [(set_attr "conds" "clob")
8616 (set_attr "length" "16")])
8617
8618; If the above pattern is followed by a CMP insn, then the compare is
8619; redundant, since we can rework the conditional instruction that follows.
8620(define_insn_and_split "*and_scc_scc_cmp"
8621 [(set (match_operand 0 "dominant_cc_register" "")
8622 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8623 [(match_operand:SI 1 "s_register_operand" "r")
8624 (match_operand:SI 2 "arm_add_operand" "rIL")])
8625 (match_operator:SI 6 "arm_comparison_operator"
8626 [(match_operand:SI 4 "s_register_operand" "r")
8627 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8628 (const_int 0)))
8629 (set (match_operand:SI 7 "s_register_operand" "=r")
8630 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8631 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8632 "TARGET_ARM"
8633 "#"
8634 "TARGET_ARM && reload_completed"
8635 [(set (match_dup 0)
8636 (compare
8637 (and:SI
8638 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8639 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8640 (const_int 0)))
8641 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8642 ""
8643 [(set_attr "conds" "set")
8644 (set_attr "length" "16")])
8645
8646;; If there is no dominance in the comparison, then we can still save an
8647;; instruction in the AND case, since we can know that the second compare
8648;; need only zero the value if false (if true, then the value is already
8649;; correct).
8650(define_insn_and_split "*and_scc_scc_nodom"
8651 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8652 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8653 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8654 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8655 (match_operator:SI 6 "arm_comparison_operator"
8656 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8657 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8658 (clobber (reg:CC CC_REGNUM))]
8659 "TARGET_ARM
8660 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8661 == CCmode)"
8662 "#"
8663 "TARGET_ARM && reload_completed"
8664 [(parallel [(set (match_dup 0)
8665 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8666 (clobber (reg:CC CC_REGNUM))])
8667 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8668 (set (match_dup 0)
8669 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8670 (match_dup 0)
8671 (const_int 0)))]
8672 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8673 operands[4], operands[5]),
8674 CC_REGNUM);
8675 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8676 operands[5]);"
8677 [(set_attr "conds" "clob")
8678 (set_attr "length" "20")])
3c5afce6 8679
3a0bdee0 8680(define_split
8681 [(set (reg:CC_NOOV CC_REGNUM)
8682 (compare:CC_NOOV (ior:SI
8683 (and:SI (match_operand:SI 0 "s_register_operand" "")
8684 (const_int 1))
8685 (match_operator:SI 1 "comparison_operator"
8686 [(match_operand:SI 2 "s_register_operand" "")
8687 (match_operand:SI 3 "arm_add_operand" "")]))
8688 (const_int 0)))
8689 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8690 "TARGET_ARM"
8691 [(set (match_dup 4)
8692 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8693 (match_dup 0)))
8694 (set (reg:CC_NOOV CC_REGNUM)
8695 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8696 (const_int 0)))]
8697 "")
8698
8699(define_split
8700 [(set (reg:CC_NOOV CC_REGNUM)
8701 (compare:CC_NOOV (ior:SI
8702 (match_operator:SI 1 "comparison_operator"
8703 [(match_operand:SI 2 "s_register_operand" "")
8704 (match_operand:SI 3 "arm_add_operand" "")])
8705 (and:SI (match_operand:SI 0 "s_register_operand" "")
8706 (const_int 1)))
8707 (const_int 0)))
8708 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8709 "TARGET_ARM"
8710 [(set (match_dup 4)
8711 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8712 (match_dup 0)))
8713 (set (reg:CC_NOOV CC_REGNUM)
8714 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8715 (const_int 0)))]
8716 "")
8717
f7fbdd4a 8718(define_insn "*negscc"
9c08d1fa 8719 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8720 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 8721 [(match_operand:SI 1 "s_register_operand" "r")
8722 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 8723 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8724 "TARGET_ARM"
9c08d1fa 8725 "*
f0e75574 8726 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
e2348bcb 8727 return \"mov\\t%0, %1, asr #31\";
8728
9c08d1fa 8729 if (GET_CODE (operands[3]) == NE)
e2348bcb 8730 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8731
9c08d1fa 8732 if (GET_CODE (operands[3]) == GT)
e2348bcb 8733 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8734
8735 output_asm_insn (\"cmp\\t%1, %2\", operands);
8736 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8737 return \"mvn%d3\\t%0, #0\";
215b30b3 8738 "
8fa3ba89 8739 [(set_attr "conds" "clob")
8740 (set_attr "length" "12")]
8741)
9c08d1fa 8742
8743(define_insn "movcond"
8744 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 8745 (if_then_else:SI
8fa3ba89 8746 (match_operator 5 "arm_comparison_operator"
5565501b 8747 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8748 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8749 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8750 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 8751 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8752 "TARGET_ARM"
9c08d1fa 8753 "*
8754 if (GET_CODE (operands[5]) == LT
8755 && (operands[4] == const0_rtx))
8756 {
5565501b 8757 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 8758 {
9c08d1fa 8759 if (operands[2] == const0_rtx)
e2348bcb 8760 return \"and\\t%0, %1, %3, asr #31\";
8761 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 8762 }
8763 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8764 {
9c08d1fa 8765 if (operands[1] == const0_rtx)
e2348bcb 8766 return \"bic\\t%0, %2, %3, asr #31\";
8767 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 8768 }
8769 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8770 are constants. */
9c08d1fa 8771 }
e2348bcb 8772
9c08d1fa 8773 if (GET_CODE (operands[5]) == GE
8774 && (operands[4] == const0_rtx))
8775 {
8776 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8777 {
9c08d1fa 8778 if (operands[2] == const0_rtx)
e2348bcb 8779 return \"bic\\t%0, %1, %3, asr #31\";
8780 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 8781 }
8782 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8783 {
9c08d1fa 8784 if (operands[1] == const0_rtx)
e2348bcb 8785 return \"and\\t%0, %2, %3, asr #31\";
8786 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 8787 }
8788 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8789 are constants. */
9c08d1fa 8790 }
8791 if (GET_CODE (operands[4]) == CONST_INT
8792 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 8793 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 8794 else
e2348bcb 8795 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 8796 if (which_alternative != 0)
e2348bcb 8797 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 8798 if (which_alternative != 1)
e2348bcb 8799 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 8800 return \"\";
215b30b3 8801 "
8fa3ba89 8802 [(set_attr "conds" "clob")
8803 (set_attr "length" "8,8,12")]
8804)
9c08d1fa 8805
8a18b90c 8806(define_insn "*ifcompare_plus_move"
8807 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8808 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8809 [(match_operand:SI 4 "s_register_operand" "r,r")
8810 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8811 (plus:SI
8812 (match_operand:SI 2 "s_register_operand" "r,r")
8813 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 8814 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8815 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8816 "TARGET_ARM"
8a18b90c 8817 "#"
8fa3ba89 8818 [(set_attr "conds" "clob")
8819 (set_attr "length" "8,12")]
8820)
8a18b90c 8821
8822(define_insn "*if_plus_move"
129a2fe4 8823 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8824 (if_then_else:SI
8fa3ba89 8825 (match_operator 4 "arm_comparison_operator"
8a18b90c 8826 [(match_operand 5 "cc_register" "") (const_int 0)])
8827 (plus:SI
129a2fe4 8828 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8829 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8830 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 8831 "TARGET_ARM"
8a18b90c 8832 "@
8833 add%d4\\t%0, %2, %3
8834 sub%d4\\t%0, %2, #%n3
8835 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 8836 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 8837 [(set_attr "conds" "use")
8838 (set_attr "length" "4,4,8,8")
8839 (set_attr "type" "*,*,*,*")]
8840)
8a18b90c 8841
8842(define_insn "*ifcompare_move_plus"
5565501b 8843 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8844 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8845 [(match_operand:SI 4 "s_register_operand" "r,r")
8846 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8847 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8848 (plus:SI
8849 (match_operand:SI 2 "s_register_operand" "r,r")
8850 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 8851 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8852 "TARGET_ARM"
8a18b90c 8853 "#"
8fa3ba89 8854 [(set_attr "conds" "clob")
8855 (set_attr "length" "8,12")]
8856)
8a18b90c 8857
8858(define_insn "*if_move_plus"
129a2fe4 8859 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8860 (if_then_else:SI
8fa3ba89 8861 (match_operator 4 "arm_comparison_operator"
8a18b90c 8862 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 8863 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 8864 (plus:SI
129a2fe4 8865 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8866 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 8867 "TARGET_ARM"
8a18b90c 8868 "@
8869 add%D4\\t%0, %2, %3
8870 sub%D4\\t%0, %2, #%n3
8871 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 8872 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 8873 [(set_attr "conds" "use")
8874 (set_attr "length" "4,4,8,8")
8875 (set_attr "type" "*,*,*,*")]
8876)
8a18b90c 8877
8878(define_insn "*ifcompare_arith_arith"
8879 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8880 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 8881 [(match_operand:SI 5 "s_register_operand" "r")
8882 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 8883 (match_operator:SI 8 "shiftable_operator"
8a18b90c 8884 [(match_operand:SI 1 "s_register_operand" "r")
8885 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 8886 (match_operator:SI 7 "shiftable_operator"
8a18b90c 8887 [(match_operand:SI 3 "s_register_operand" "r")
8888 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 8889 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8890 "TARGET_ARM"
8a18b90c 8891 "#"
8fa3ba89 8892 [(set_attr "conds" "clob")
8893 (set_attr "length" "12")]
8894)
9c08d1fa 8895
8a18b90c 8896(define_insn "*if_arith_arith"
8897 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8898 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 8899 [(match_operand 8 "cc_register" "") (const_int 0)])
8900 (match_operator:SI 6 "shiftable_operator"
8901 [(match_operand:SI 1 "s_register_operand" "r")
8902 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8903 (match_operator:SI 7 "shiftable_operator"
8904 [(match_operand:SI 3 "s_register_operand" "r")
8905 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 8906 "TARGET_ARM"
8a18b90c 8907 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 8908 [(set_attr "conds" "use")
8909 (set_attr "length" "8")]
8910)
8a18b90c 8911
f7fbdd4a 8912(define_insn "*ifcompare_arith_move"
9c08d1fa 8913 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8914 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8915 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 8916 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 8917 (match_operator:SI 7 "shiftable_operator"
8918 [(match_operand:SI 4 "s_register_operand" "r,r")
8919 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 8920 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8921 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8922 "TARGET_ARM"
9c08d1fa 8923 "*
9c08d1fa 8924 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8925 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 8926 everything is in registers then we can do this in two instructions. */
9c08d1fa 8927 if (operands[3] == const0_rtx
8928 && GET_CODE (operands[7]) != AND
8929 && GET_CODE (operands[5]) == REG
8930 && GET_CODE (operands[1]) == REG
8931 && REGNO (operands[1]) == REGNO (operands[4])
8932 && REGNO (operands[4]) != REGNO (operands[0]))
8933 {
8934 if (GET_CODE (operands[6]) == LT)
40dbec34 8935 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8936 else if (GET_CODE (operands[6]) == GE)
40dbec34 8937 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8938 }
8939 if (GET_CODE (operands[3]) == CONST_INT
8940 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 8941 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 8942 else
e2348bcb 8943 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 8944 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 8945 if (which_alternative != 0)
129a2fe4 8946 return \"mov%D6\\t%0, %1\";
9c08d1fa 8947 return \"\";
215b30b3 8948 "
8fa3ba89 8949 [(set_attr "conds" "clob")
8950 (set_attr "length" "8,12")]
8951)
9c08d1fa 8952
8a18b90c 8953(define_insn "*if_arith_move"
129a2fe4 8954 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8955 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 8956 [(match_operand 6 "cc_register" "") (const_int 0)])
8957 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8958 [(match_operand:SI 2 "s_register_operand" "r,r")
8959 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8960 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 8961 "TARGET_ARM"
8a18b90c 8962 "@
8963 %I5%d4\\t%0, %2, %3
129a2fe4 8964 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 8965 [(set_attr "conds" "use")
8966 (set_attr "length" "4,8")
8967 (set_attr "type" "*,*")]
8968)
8a18b90c 8969
f7fbdd4a 8970(define_insn "*ifcompare_move_arith"
9c08d1fa 8971 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8972 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8973 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 8974 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8975 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 8976 (match_operator:SI 7 "shiftable_operator"
8977 [(match_operand:SI 2 "s_register_operand" "r,r")
8978 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8979 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8980 "TARGET_ARM"
9c08d1fa 8981 "*
9c08d1fa 8982 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8983 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 8984 everything is in registers then we can do this in two instructions */
8985 if (operands[5] == const0_rtx
8986 && GET_CODE (operands[7]) != AND
8987 && GET_CODE (operands[3]) == REG
8988 && GET_CODE (operands[1]) == REG
8989 && REGNO (operands[1]) == REGNO (operands[2])
8990 && REGNO (operands[2]) != REGNO (operands[0]))
8991 {
8992 if (GET_CODE (operands[6]) == GE)
40dbec34 8993 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8994 else if (GET_CODE (operands[6]) == LT)
40dbec34 8995 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8996 }
40dbec34 8997
9c08d1fa 8998 if (GET_CODE (operands[5]) == CONST_INT
8999 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9000 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9001 else
e2348bcb 9002 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9003
9c08d1fa 9004 if (which_alternative != 0)
129a2fe4 9005 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9006 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9007 "
8fa3ba89 9008 [(set_attr "conds" "clob")
9009 (set_attr "length" "8,12")]
9010)
9c08d1fa 9011
8a18b90c 9012(define_insn "*if_move_arith"
129a2fe4 9013 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9014 (if_then_else:SI
8fa3ba89 9015 (match_operator 4 "arm_comparison_operator"
8a18b90c 9016 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9017 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9018 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9019 [(match_operand:SI 2 "s_register_operand" "r,r")
9020 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9021 "TARGET_ARM"
8a18b90c 9022 "@
9023 %I5%D4\\t%0, %2, %3
129a2fe4 9024 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9025 [(set_attr "conds" "use")
9026 (set_attr "length" "4,8")
9027 (set_attr "type" "*,*")]
9028)
8a18b90c 9029
9030(define_insn "*ifcompare_move_not"
9c08d1fa 9031 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9032 (if_then_else:SI
8fa3ba89 9033 (match_operator 5 "arm_comparison_operator"
8a18b90c 9034 [(match_operand:SI 3 "s_register_operand" "r,r")
9035 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9036 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9037 (not:SI
9038 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9039 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9040 "TARGET_ARM"
8a18b90c 9041 "#"
8fa3ba89 9042 [(set_attr "conds" "clob")
9043 (set_attr "length" "8,12")]
9044)
9c08d1fa 9045
8a18b90c 9046(define_insn "*if_move_not"
9047 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9048 (if_then_else:SI
8fa3ba89 9049 (match_operator 4 "arm_comparison_operator"
8a18b90c 9050 [(match_operand 3 "cc_register" "") (const_int 0)])
9051 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9052 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9053 "TARGET_ARM"
8a18b90c 9054 "@
9055 mvn%D4\\t%0, %2
9056 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9057 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9058 [(set_attr "conds" "use")
9059 (set_attr "length" "4,8,8")]
9060)
8a18b90c 9061
9062(define_insn "*ifcompare_not_move"
9c08d1fa 9063 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9064 (if_then_else:SI
8fa3ba89 9065 (match_operator 5 "arm_comparison_operator"
8a18b90c 9066 [(match_operand:SI 3 "s_register_operand" "r,r")
9067 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9068 (not:SI
9069 (match_operand:SI 2 "s_register_operand" "r,r"))
9070 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9071 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9072 "TARGET_ARM"
8a18b90c 9073 "#"
8fa3ba89 9074 [(set_attr "conds" "clob")
9075 (set_attr "length" "8,12")]
9076)
9c08d1fa 9077
8a18b90c 9078(define_insn "*if_not_move"
9079 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9080 (if_then_else:SI
8fa3ba89 9081 (match_operator 4 "arm_comparison_operator"
8a18b90c 9082 [(match_operand 3 "cc_register" "") (const_int 0)])
9083 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9084 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9085 "TARGET_ARM"
8a18b90c 9086 "@
9087 mvn%d4\\t%0, %2
9088 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9089 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9090 [(set_attr "conds" "use")
9091 (set_attr "length" "4,8,8")]
9092)
8a18b90c 9093
9094(define_insn "*ifcompare_shift_move"
9c08d1fa 9095 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9096 (if_then_else:SI
8fa3ba89 9097 (match_operator 6 "arm_comparison_operator"
8a18b90c 9098 [(match_operand:SI 4 "s_register_operand" "r,r")
9099 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9100 (match_operator:SI 7 "shift_operator"
9101 [(match_operand:SI 2 "s_register_operand" "r,r")
9102 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9103 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9104 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9105 "TARGET_ARM"
9c08d1fa 9106 "#"
8fa3ba89 9107 [(set_attr "conds" "clob")
9108 (set_attr "length" "8,12")]
9109)
9c08d1fa 9110
8a18b90c 9111(define_insn "*if_shift_move"
9112 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9113 (if_then_else:SI
8fa3ba89 9114 (match_operator 5 "arm_comparison_operator"
8a18b90c 9115 [(match_operand 6 "cc_register" "") (const_int 0)])
9116 (match_operator:SI 4 "shift_operator"
9117 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9118 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9119 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9120 "TARGET_ARM"
5565501b 9121 "@
8a18b90c 9122 mov%d5\\t%0, %2%S4
9123 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9124 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9125 [(set_attr "conds" "use")
331beb1a 9126 (set_attr "shift" "2")
a2cd141b 9127 (set_attr "length" "4,8,8")
9128 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9129 (const_string "alu_shift")
9130 (const_string "alu_shift_reg")))]
8fa3ba89 9131)
5565501b 9132
8a18b90c 9133(define_insn "*ifcompare_move_shift"
9134 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9135 (if_then_else:SI
8fa3ba89 9136 (match_operator 6 "arm_comparison_operator"
8a18b90c 9137 [(match_operand:SI 4 "s_register_operand" "r,r")
9138 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9139 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9140 (match_operator:SI 7 "shift_operator"
8a18b90c 9141 [(match_operand:SI 2 "s_register_operand" "r,r")
9142 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9143 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9144 "TARGET_ARM"
8a18b90c 9145 "#"
8fa3ba89 9146 [(set_attr "conds" "clob")
9147 (set_attr "length" "8,12")]
9148)
5565501b 9149
8a18b90c 9150(define_insn "*if_move_shift"
9151 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9152 (if_then_else:SI
8fa3ba89 9153 (match_operator 5 "arm_comparison_operator"
8a18b90c 9154 [(match_operand 6 "cc_register" "") (const_int 0)])
9155 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9156 (match_operator:SI 4 "shift_operator"
9157 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9158 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9159 "TARGET_ARM"
5565501b 9160 "@
8a18b90c 9161 mov%D5\\t%0, %2%S4
9162 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9163 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9164 [(set_attr "conds" "use")
331beb1a 9165 (set_attr "shift" "2")
a2cd141b 9166 (set_attr "length" "4,8,8")
9167 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9168 (const_string "alu_shift")
9169 (const_string "alu_shift_reg")))]
8fa3ba89 9170)
9c08d1fa 9171
f7fbdd4a 9172(define_insn "*ifcompare_shift_shift"
8a18b90c 9173 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9174 (if_then_else:SI
8fa3ba89 9175 (match_operator 7 "arm_comparison_operator"
8a18b90c 9176 [(match_operand:SI 5 "s_register_operand" "r")
9177 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9178 (match_operator:SI 8 "shift_operator"
8a18b90c 9179 [(match_operand:SI 1 "s_register_operand" "r")
9180 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9181 (match_operator:SI 9 "shift_operator"
8a18b90c 9182 [(match_operand:SI 3 "s_register_operand" "r")
9183 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9184 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9185 "TARGET_ARM"
8a18b90c 9186 "#"
8fa3ba89 9187 [(set_attr "conds" "clob")
9188 (set_attr "length" "12")]
9189)
9c08d1fa 9190
8a18b90c 9191(define_insn "*if_shift_shift"
9192 [(set (match_operand:SI 0 "s_register_operand" "=r")
9193 (if_then_else:SI
8fa3ba89 9194 (match_operator 5 "arm_comparison_operator"
8a18b90c 9195 [(match_operand 8 "cc_register" "") (const_int 0)])
9196 (match_operator:SI 6 "shift_operator"
9197 [(match_operand:SI 1 "s_register_operand" "r")
9198 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9199 (match_operator:SI 7 "shift_operator"
9200 [(match_operand:SI 3 "s_register_operand" "r")
9201 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9202 "TARGET_ARM"
8a18b90c 9203 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9204 [(set_attr "conds" "use")
331beb1a 9205 (set_attr "shift" "1")
a2cd141b 9206 (set_attr "length" "8")
9207 (set (attr "type") (if_then_else
9208 (and (match_operand 2 "const_int_operand" "")
9209 (match_operand 4 "const_int_operand" ""))
9210 (const_string "alu_shift")
9211 (const_string "alu_shift_reg")))]
8fa3ba89 9212)
8a18b90c 9213
f7fbdd4a 9214(define_insn "*ifcompare_not_arith"
8a18b90c 9215 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9216 (if_then_else:SI
8fa3ba89 9217 (match_operator 6 "arm_comparison_operator"
8a18b90c 9218 [(match_operand:SI 4 "s_register_operand" "r")
9219 (match_operand:SI 5 "arm_add_operand" "rIL")])
9220 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9221 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9222 [(match_operand:SI 2 "s_register_operand" "r")
9223 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9224 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9225 "TARGET_ARM"
8a18b90c 9226 "#"
8fa3ba89 9227 [(set_attr "conds" "clob")
9228 (set_attr "length" "12")]
9229)
9c08d1fa 9230
8a18b90c 9231(define_insn "*if_not_arith"
9232 [(set (match_operand:SI 0 "s_register_operand" "=r")
9233 (if_then_else:SI
8fa3ba89 9234 (match_operator 5 "arm_comparison_operator"
8a18b90c 9235 [(match_operand 4 "cc_register" "") (const_int 0)])
9236 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9237 (match_operator:SI 6 "shiftable_operator"
9238 [(match_operand:SI 2 "s_register_operand" "r")
9239 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9240 "TARGET_ARM"
8a18b90c 9241 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9242 [(set_attr "conds" "use")
9243 (set_attr "length" "8")]
9244)
8a18b90c 9245
9246(define_insn "*ifcompare_arith_not"
9247 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9248 (if_then_else:SI
8fa3ba89 9249 (match_operator 6 "arm_comparison_operator"
8a18b90c 9250 [(match_operand:SI 4 "s_register_operand" "r")
9251 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9252 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9253 [(match_operand:SI 2 "s_register_operand" "r")
9254 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9255 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9256 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9257 "TARGET_ARM"
8a18b90c 9258 "#"
8fa3ba89 9259 [(set_attr "conds" "clob")
9260 (set_attr "length" "12")]
9261)
9c08d1fa 9262
8a18b90c 9263(define_insn "*if_arith_not"
9264 [(set (match_operand:SI 0 "s_register_operand" "=r")
9265 (if_then_else:SI
8fa3ba89 9266 (match_operator 5 "arm_comparison_operator"
8a18b90c 9267 [(match_operand 4 "cc_register" "") (const_int 0)])
9268 (match_operator:SI 6 "shiftable_operator"
9269 [(match_operand:SI 2 "s_register_operand" "r")
9270 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9271 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9272 "TARGET_ARM"
8a18b90c 9273 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9274 [(set_attr "conds" "use")
9275 (set_attr "length" "8")]
9276)
8a18b90c 9277
f7fbdd4a 9278(define_insn "*ifcompare_neg_move"
8a18b90c 9279 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9280 (if_then_else:SI
8fa3ba89 9281 (match_operator 5 "arm_comparison_operator"
8a18b90c 9282 [(match_operand:SI 3 "s_register_operand" "r,r")
9283 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9284 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9285 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9286 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9287 "TARGET_ARM"
8a18b90c 9288 "#"
8fa3ba89 9289 [(set_attr "conds" "clob")
9290 (set_attr "length" "8,12")]
9291)
8a18b90c 9292
9293(define_insn "*if_neg_move"
9294 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9295 (if_then_else:SI
8fa3ba89 9296 (match_operator 4 "arm_comparison_operator"
8a18b90c 9297 [(match_operand 3 "cc_register" "") (const_int 0)])
9298 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9299 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9300 "TARGET_ARM"
8a18b90c 9301 "@
9302 rsb%d4\\t%0, %2, #0
9303 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9304 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9305 [(set_attr "conds" "use")
9306 (set_attr "length" "4,8,8")]
9307)
9c08d1fa 9308
f7fbdd4a 9309(define_insn "*ifcompare_move_neg"
8a18b90c 9310 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9311 (if_then_else:SI
8fa3ba89 9312 (match_operator 5 "arm_comparison_operator"
8a18b90c 9313 [(match_operand:SI 3 "s_register_operand" "r,r")
9314 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9315 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9316 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9317 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9318 "TARGET_ARM"
8a18b90c 9319 "#"
8fa3ba89 9320 [(set_attr "conds" "clob")
9321 (set_attr "length" "8,12")]
9322)
8a18b90c 9323
9324(define_insn "*if_move_neg"
9325 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9326 (if_then_else:SI
8fa3ba89 9327 (match_operator 4 "arm_comparison_operator"
8a18b90c 9328 [(match_operand 3 "cc_register" "") (const_int 0)])
9329 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9330 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9331 "TARGET_ARM"
8a18b90c 9332 "@
9333 rsb%D4\\t%0, %2, #0
9334 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9335 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9336 [(set_attr "conds" "use")
9337 (set_attr "length" "4,8,8")]
9338)
9c08d1fa 9339
f7fbdd4a 9340(define_insn "*arith_adjacentmem"
9c08d1fa 9341 [(set (match_operand:SI 0 "s_register_operand" "=r")
9342 (match_operator:SI 1 "shiftable_operator"
9343 [(match_operand:SI 2 "memory_operand" "m")
9344 (match_operand:SI 3 "memory_operand" "m")]))
9345 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9346 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9347 "*
215b30b3 9348 {
9349 rtx ldm[3];
9350 rtx arith[4];
94dee231 9351 rtx base_reg;
9352 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9353
215b30b3 9354 if (REGNO (operands[0]) > REGNO (operands[4]))
9355 {
9356 ldm[1] = operands[4];
9357 ldm[2] = operands[0];
9358 }
9359 else
9360 {
9361 ldm[1] = operands[0];
9362 ldm[2] = operands[4];
9363 }
94dee231 9364
9365 base_reg = XEXP (operands[2], 0);
9366
9367 if (!REG_P (base_reg))
9368 {
9369 val1 = INTVAL (XEXP (base_reg, 1));
9370 base_reg = XEXP (base_reg, 0);
9371 }
9372
9373 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9374 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9375
215b30b3 9376 arith[0] = operands[0];
9377 arith[3] = operands[1];
94dee231 9378
215b30b3 9379 if (val1 < val2)
9380 {
9381 arith[1] = ldm[1];
9382 arith[2] = ldm[2];
9383 }
9384 else
9385 {
9386 arith[1] = ldm[2];
9387 arith[2] = ldm[1];
9388 }
94dee231 9389
9390 ldm[0] = base_reg;
9391 if (val1 !=0 && val2 != 0)
215b30b3 9392 {
94dee231 9393 if (val1 == 4 || val2 == 4)
9394 /* Other val must be 8, since we know they are adjacent and neither
9395 is zero. */
9396 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
215b30b3 9397 else
94dee231 9398 {
9399 rtx ops[3];
9400
9401 ldm[0] = ops[0] = operands[4];
9402 ops[1] = base_reg;
9403 ops[2] = GEN_INT (val1);
9404 output_add_immediate (ops);
9405 if (val1 < val2)
9406 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9407 else
9408 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9409 }
215b30b3 9410 }
94dee231 9411 else if (val1 != 0)
215b30b3 9412 {
215b30b3 9413 if (val1 < val2)
9414 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9415 else
9416 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9417 }
9418 else
9419 {
215b30b3 9420 if (val1 < val2)
9421 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9422 else
9423 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9424 }
9425 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9426 return \"\";
9427 }"
9428 [(set_attr "length" "12")
9429 (set_attr "predicable" "yes")
a2cd141b 9430 (set_attr "type" "load1")]
215b30b3 9431)
9c08d1fa 9432
9c08d1fa 9433; This pattern is never tried by combine, so do it as a peephole
9434
a0f94409 9435(define_peephole2
372575c7 9436 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9437 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9438 (set (reg:CC CC_REGNUM)
aea4c774 9439 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9440 "TARGET_ARM"
a0f94409 9441 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9442 (set (match_dup 0) (match_dup 1))])]
9443 ""
0d66636f 9444)
9c08d1fa 9445
675d848d 9446; Peepholes to spot possible load- and store-multiples, if the ordering is
9447; reversed, check that the memory references aren't volatile.
9c08d1fa 9448
9449(define_peephole
9450 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9451 (match_operand:SI 4 "memory_operand" "m"))
9452 (set (match_operand:SI 1 "s_register_operand" "=r")
9453 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 9454 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9455 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 9456 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 9457 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 9458 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9459 "*
9460 return emit_ldm_seq (operands, 4);
215b30b3 9461 "
9462)
9c08d1fa 9463
9464(define_peephole
9465 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9466 (match_operand:SI 3 "memory_operand" "m"))
9467 (set (match_operand:SI 1 "s_register_operand" "=r")
9468 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 9469 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9470 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 9471 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9472 "*
9473 return emit_ldm_seq (operands, 3);
215b30b3 9474 "
9475)
9c08d1fa 9476
9477(define_peephole
9478 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9479 (match_operand:SI 2 "memory_operand" "m"))
9480 (set (match_operand:SI 1 "s_register_operand" "=r")
9481 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 9482 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9483 "*
9484 return emit_ldm_seq (operands, 2);
215b30b3 9485 "
9486)
9c08d1fa 9487
9488(define_peephole
aea4c774 9489 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 9490 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9491 (set (match_operand:SI 5 "memory_operand" "=m")
9492 (match_operand:SI 1 "s_register_operand" "r"))
9493 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 9494 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 9495 (set (match_operand:SI 7 "memory_operand" "=m")
9496 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 9497 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9498 "*
9499 return emit_stm_seq (operands, 4);
215b30b3 9500 "
9501)
9c08d1fa 9502
9503(define_peephole
aea4c774 9504 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 9505 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9506 (set (match_operand:SI 4 "memory_operand" "=m")
9507 (match_operand:SI 1 "s_register_operand" "r"))
9508 (set (match_operand:SI 5 "memory_operand" "=m")
9509 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 9510 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9511 "*
9512 return emit_stm_seq (operands, 3);
215b30b3 9513 "
9514)
9c08d1fa 9515
9516(define_peephole
aea4c774 9517 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 9518 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9519 (set (match_operand:SI 3 "memory_operand" "=m")
9520 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 9521 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9522 "*
9523 return emit_stm_seq (operands, 2);
215b30b3 9524 "
9525)
9c08d1fa 9526
9c08d1fa 9527(define_split
9528 [(set (match_operand:SI 0 "s_register_operand" "")
9529 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9530 (const_int 0))
8fa3ba89 9531 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9532 [(match_operand:SI 3 "s_register_operand" "")
9533 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9534 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9535 "TARGET_ARM"
9c08d1fa 9536 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9537 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9538 (match_dup 5)))]
215b30b3 9539 ""
9540)
9c08d1fa 9541
aea4c774 9542;; This split can be used because CC_Z mode implies that the following
9543;; branch will be an equality, or an unsigned inequality, so the sign
9544;; extension is not needed.
9c08d1fa 9545
aea4c774 9546(define_split
bd5b4116 9547 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9548 (compare:CC_Z
9549 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9550 (const_int 24))
aea4c774 9551 (match_operand 1 "const_int_operand" "")))
9552 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9553 "TARGET_ARM
9554 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9555 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9556 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9557 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9558 "
9c08d1fa 9559 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9560 "
9561)
9c08d1fa 9562
87b22bf7 9563(define_expand "prologue"
9564 [(clobber (const_int 0))]
cffb2a26 9565 "TARGET_EITHER"
9566 "if (TARGET_ARM)
9567 arm_expand_prologue ();
9568 else
9569 thumb_expand_prologue ();
87b22bf7 9570 DONE;
cffb2a26 9571 "
9572)
87b22bf7 9573
56d27660 9574(define_expand "epilogue"
4c44712e 9575 [(clobber (const_int 0))]
cffb2a26 9576 "TARGET_EITHER"
56d27660 9577 "
4c44712e 9578 if (current_function_calls_eh_return)
9579 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
cffb2a26 9580 if (TARGET_THUMB)
9581 thumb_expand_epilogue ();
9582 else if (USE_RETURN_INSN (FALSE))
56d27660 9583 {
9584 emit_jump_insn (gen_return ());
9585 DONE;
9586 }
cffb2a26 9587 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9588 gen_rtvec (1,
9589 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9590 VUNSPEC_EPILOGUE));
cffb2a26 9591 DONE;
9592 "
9593)
56d27660 9594
ef5651d0 9595;; Note - although unspec_volatile's USE all hard registers,
9596;; USEs are ignored after relaod has completed. Thus we need
9597;; to add an unspec of the link register to ensure that flow
9598;; does not think that it is unused by the sibcall branch that
9599;; will replace the standard function epilogue.
1c494086 9600(define_insn "sibcall_epilogue"
ef5651d0 9601 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9602 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
1c494086 9603 "TARGET_ARM"
9604 "*
ffc9d00c 9605 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9606 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9607 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9608 "
9609;; Length is absolute worst case
9610 [(set_attr "length" "44")
defc47cf 9611 (set_attr "type" "block")
9612 ;; We don't clobber the conditions, but the potential length of this
9613 ;; operation is sufficient to make conditionalizing the sequence
9614 ;; unlikely to be profitable.
9615 (set_attr "conds" "clob")]
1c494086 9616)
9617
cffb2a26 9618(define_insn "*epilogue_insns"
e1159bbe 9619 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9620 "TARGET_EITHER"
56d27660 9621 "*
cffb2a26 9622 if (TARGET_ARM)
ffc9d00c 9623 return arm_output_epilogue (NULL);
cffb2a26 9624 else /* TARGET_THUMB */
9625 return thumb_unexpanded_epilogue ();
9626 "
215b30b3 9627 ; Length is absolute worst case
cffb2a26 9628 [(set_attr "length" "44")
defc47cf 9629 (set_attr "type" "block")
9630 ;; We don't clobber the conditions, but the potential length of this
9631 ;; operation is sufficient to make conditionalizing the sequence
9632 ;; unlikely to be profitable.
9633 (set_attr "conds" "clob")]
cffb2a26 9634)
9635
9636(define_expand "eh_epilogue"
7db9af5d 9637 [(use (match_operand:SI 0 "register_operand" ""))
9638 (use (match_operand:SI 1 "register_operand" ""))
9639 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 9640 "TARGET_EITHER"
9641 "
215b30b3 9642 {
9643 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9644 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9645 {
9646 rtx ra = gen_rtx_REG (Pmode, 2);
9647
9648 emit_move_insn (ra, operands[2]);
9649 operands[2] = ra;
9650 }
5cf3595a 9651 /* This is a hack -- we may have crystalized the function type too
9652 early. */
9653 cfun->machine->func_type = 0;
215b30b3 9654 }"
9655)
56d27660 9656
9c08d1fa 9657;; This split is only used during output to reduce the number of patterns
9658;; that need assembler instructions adding to them. We allowed the setting
9659;; of the conditions to be implicit during rtl generation so that
9660;; the conditional compare patterns would work. However this conflicts to
8a18b90c 9661;; some extent with the conditional data operations, so we have to split them
9c08d1fa 9662;; up again here.
9663
9664(define_split
9665 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 9666 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9667 [(match_operand 2 "" "") (match_operand 3 "" "")])
9668 (match_dup 0)
9669 (match_operand 4 "" "")))
bd5b4116 9670 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9671 "TARGET_ARM && reload_completed"
8fa3ba89 9672 [(set (match_dup 5) (match_dup 6))
9673 (cond_exec (match_dup 7)
9674 (set (match_dup 0) (match_dup 4)))]
9675 "
9676 {
9677 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9678 operands[2], operands[3]);
9679 enum rtx_code rc = GET_CODE (operands[1]);
9680
bd5b4116 9681 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9682 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9683 if (mode == CCFPmode || mode == CCFPEmode)
9684 rc = reverse_condition_maybe_unordered (rc);
9685 else
9686 rc = reverse_condition (rc);
9687
9688 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9689 }"
9690)
9691
9692(define_split
9693 [(set (match_operand:SI 0 "s_register_operand" "")
9694 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9695 [(match_operand 2 "" "") (match_operand 3 "" "")])
9696 (match_operand 4 "" "")
9697 (match_dup 0)))
bd5b4116 9698 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9699 "TARGET_ARM && reload_completed"
8fa3ba89 9700 [(set (match_dup 5) (match_dup 6))
9701 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9702 (set (match_dup 0) (match_dup 4)))]
9703 "
9704 {
9705 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9706 operands[2], operands[3]);
9707
bd5b4116 9708 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9709 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9710 }"
9711)
9712
9713(define_split
9714 [(set (match_operand:SI 0 "s_register_operand" "")
9715 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 9716 [(match_operand 2 "" "") (match_operand 3 "" "")])
9717 (match_operand 4 "" "")
9718 (match_operand 5 "" "")))
bd5b4116 9719 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9720 "TARGET_ARM && reload_completed"
8fa3ba89 9721 [(set (match_dup 6) (match_dup 7))
9722 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9723 (set (match_dup 0) (match_dup 4)))
9724 (cond_exec (match_dup 8)
9725 (set (match_dup 0) (match_dup 5)))]
9726 "
9727 {
9728 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9729 operands[2], operands[3]);
9730 enum rtx_code rc = GET_CODE (operands[1]);
9731
bd5b4116 9732 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9733 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9734 if (mode == CCFPmode || mode == CCFPEmode)
9735 rc = reverse_condition_maybe_unordered (rc);
9736 else
9737 rc = reverse_condition (rc);
9738
9739 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9740 }"
9741)
9742
cffb2a26 9743(define_split
9744 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 9745 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 9746 [(match_operand:SI 2 "s_register_operand" "")
9747 (match_operand:SI 3 "arm_add_operand" "")])
9748 (match_operand:SI 4 "arm_rhs_operand" "")
9749 (not:SI
9750 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 9751 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9752 "TARGET_ARM && reload_completed"
cffb2a26 9753 [(set (match_dup 6) (match_dup 7))
f6c53574 9754 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9755 (set (match_dup 0) (match_dup 4)))
9756 (cond_exec (match_dup 8)
9757 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 9758 "
215b30b3 9759 {
9760 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9761 operands[2], operands[3]);
f6c53574 9762 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 9763
bd5b4116 9764 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 9765 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 9766 if (mode == CCFPmode || mode == CCFPEmode)
9767 rc = reverse_condition_maybe_unordered (rc);
9768 else
9769 rc = reverse_condition (rc);
9770
9771 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 9772 }"
9773)
cffb2a26 9774
9775(define_insn "*cond_move_not"
9776 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9777 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 9778 [(match_operand 3 "cc_register" "") (const_int 0)])
9779 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9780 (not:SI
9781 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9782 "TARGET_ARM"
9783 "@
9784 mvn%D4\\t%0, %2
9785 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 9786 [(set_attr "conds" "use")
9787 (set_attr "length" "4,8")]
9788)
cffb2a26 9789
9c08d1fa 9790;; The next two patterns occur when an AND operation is followed by a
9791;; scc insn sequence
9792
f7fbdd4a 9793(define_insn "*sign_extract_onebit"
9c08d1fa 9794 [(set (match_operand:SI 0 "s_register_operand" "=r")
9795 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9796 (const_int 1)
ed750274 9797 (match_operand:SI 2 "const_int_operand" "n")))
9798 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9799 "TARGET_ARM"
9c08d1fa 9800 "*
0d66636f 9801 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9802 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9803 return \"mvnne\\t%0, #0\";
9804 "
9805 [(set_attr "conds" "clob")
9806 (set_attr "length" "8")]
9807)
9c08d1fa 9808
f7fbdd4a 9809(define_insn "*not_signextract_onebit"
9c08d1fa 9810 [(set (match_operand:SI 0 "s_register_operand" "=r")
9811 (not:SI
9812 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9813 (const_int 1)
ed750274 9814 (match_operand:SI 2 "const_int_operand" "n"))))
9815 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9816 "TARGET_ARM"
9c08d1fa 9817 "*
0d66636f 9818 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9819 output_asm_insn (\"tst\\t%1, %2\", operands);
9820 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9821 return \"movne\\t%0, #0\";
9822 "
9823 [(set_attr "conds" "clob")
9824 (set_attr "length" "12")]
9825)
87b22bf7 9826
0d66636f 9827;; Push multiple registers to the stack. Registers are in parallel (use ...)
9828;; expressions. For simplicity, the first register is also in the unspec
9829;; part.
f7fbdd4a 9830(define_insn "*push_multi"
87b22bf7 9831 [(match_parallel 2 "multi_register_push"
9832 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 9833 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9834 UNSPEC_PUSH_MULT))])]
cffb2a26 9835 "TARGET_ARM"
87b22bf7 9836 "*
215b30b3 9837 {
9838 int num_saves = XVECLEN (operands[2], 0);
ed593f11 9839
215b30b3 9840 /* For the StrongARM at least it is faster to
9841 use STR to store only a single register. */
6079f055 9842 if (num_saves == 1)
215b30b3 9843 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9844 else
9845 {
9846 int i;
9847 char pattern[100];
ed593f11 9848
215b30b3 9849 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9850
6079f055 9851 for (i = 1; i < num_saves; i++)
215b30b3 9852 {
9853 strcat (pattern, \", %|\");
9854 strcat (pattern,
9855 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9856 }
9857
9858 strcat (pattern, \"}\");
9859 output_asm_insn (pattern, operands);
9860 }
9861
9862 return \"\";
9863 }"
9864 [(set_attr "type" "store4")]
9865)
f7fbdd4a 9866
4c58c898 9867(define_insn "stack_tie"
9868 [(set (mem:BLK (scratch))
9869 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9870 (match_operand:SI 1 "s_register_operand" "r")]
9871 UNSPEC_PRLG_STK))]
9872 ""
9873 ""
9874 [(set_attr "length" "0")]
9875)
9876
3398e91d 9877;; Similarly for the floating point registers
7b1d2fc4 9878(define_insn "*push_fp_multi"
9879 [(match_parallel 2 "multi_register_push"
9880 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 9881 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9882 UNSPEC_PUSH_MULT))])]
a2cd141b 9883 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 9884 "*
215b30b3 9885 {
9886 char pattern[100];
7b1d2fc4 9887
215b30b3 9888 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9889 output_asm_insn (pattern, operands);
9890 return \"\";
9891 }"
9892 [(set_attr "type" "f_store")]
9893)
7b1d2fc4 9894
f7fbdd4a 9895;; Special patterns for dealing with the constant pool
9896
cffb2a26 9897(define_insn "align_4"
e1159bbe 9898 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 9899 "TARGET_EITHER"
f7fbdd4a 9900 "*
cffb2a26 9901 assemble_align (32);
f7fbdd4a 9902 return \"\";
cffb2a26 9903 "
9904)
f7fbdd4a 9905
755eb2b4 9906(define_insn "align_8"
9907 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 9908 "TARGET_EITHER"
755eb2b4 9909 "*
9910 assemble_align (64);
9911 return \"\";
9912 "
9913)
9914
cffb2a26 9915(define_insn "consttable_end"
e1159bbe 9916 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 9917 "TARGET_EITHER"
f7fbdd4a 9918 "*
cffb2a26 9919 making_const_table = FALSE;
f7fbdd4a 9920 return \"\";
cffb2a26 9921 "
9922)
f7fbdd4a 9923
cffb2a26 9924(define_insn "consttable_1"
e1159bbe 9925 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
cffb2a26 9926 "TARGET_THUMB"
f7fbdd4a 9927 "*
cffb2a26 9928 making_const_table = TRUE;
09d688ff 9929 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 9930 assemble_zeros (3);
f7fbdd4a 9931 return \"\";
cffb2a26 9932 "
9933 [(set_attr "length" "4")]
9934)
f7fbdd4a 9935
cffb2a26 9936(define_insn "consttable_2"
e1159bbe 9937 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
cffb2a26 9938 "TARGET_THUMB"
f7fbdd4a 9939 "*
cffb2a26 9940 making_const_table = TRUE;
09d688ff 9941 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 9942 assemble_zeros (2);
f7fbdd4a 9943 return \"\";
cffb2a26 9944 "
9945 [(set_attr "length" "4")]
9946)
9947
9948(define_insn "consttable_4"
e1159bbe 9949 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 9950 "TARGET_EITHER"
9951 "*
9952 {
9953 making_const_table = TRUE;
9954 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9955 {
9956 case MODE_FLOAT:
9957 {
badfe841 9958 REAL_VALUE_TYPE r;
9959 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9960 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 9961 break;
9962 }
9963 default:
09d688ff 9964 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 9965 break;
9966 }
9967 return \"\";
9968 }"
9969 [(set_attr "length" "4")]
9970)
9971
9972(define_insn "consttable_8"
e1159bbe 9973 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 9974 "TARGET_EITHER"
9975 "*
9976 {
9977 making_const_table = TRUE;
9978 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9979 {
9980 case MODE_FLOAT:
9981 {
badfe841 9982 REAL_VALUE_TYPE r;
9983 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9984 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 9985 break;
9986 }
9987 default:
09d688ff 9988 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 9989 break;
9990 }
9991 return \"\";
9992 }"
9993 [(set_attr "length" "8")]
9994)
9995
9996;; Miscellaneous Thumb patterns
9997
fd957ef3 9998(define_expand "tablejump"
7db9af5d 9999 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10000 (use (label_ref (match_operand 1 "" "")))])]
10001 "TARGET_THUMB"
10002 "
10003 if (flag_pic)
10004 {
10005 /* Hopefully, CSE will eliminate this copy. */
10006 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10007 rtx reg2 = gen_reg_rtx (SImode);
10008
10009 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10010 operands[0] = reg2;
10011 }
10012 "
10013)
10014
f1039640 10015;; NB never uses BX.
fd957ef3 10016(define_insn "*thumb_tablejump"
cffb2a26 10017 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10018 (use (label_ref (match_operand 1 "" "")))]
10019 "TARGET_THUMB"
fd957ef3 10020 "mov\\t%|pc, %0"
cffb2a26 10021 [(set_attr "length" "2")]
10022)
0d66636f 10023
331beb1a 10024;; V5 Instructions,
10025
8f4be2be 10026(define_insn "clzsi2"
10027 [(set (match_operand:SI 0 "s_register_operand" "=r")
10028 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
e1159bbe 10029 "TARGET_ARM && arm_arch5"
ee7cbe0e 10030 "clz%?\\t%0, %1"
10031 [(set_attr "predicable" "yes")])
331beb1a 10032
e1159bbe 10033(define_expand "ffssi2"
10034 [(set (match_operand:SI 0 "s_register_operand" "")
10035 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10036 "TARGET_ARM && arm_arch5"
10037 "
10038 {
10039 rtx t1, t2, t3;
10040
10041 t1 = gen_reg_rtx (SImode);
10042 t2 = gen_reg_rtx (SImode);
10043 t3 = gen_reg_rtx (SImode);
10044
10045 emit_insn (gen_negsi2 (t1, operands[1]));
10046 emit_insn (gen_andsi3 (t2, operands[1], t1));
8f4be2be 10047 emit_insn (gen_clzsi2 (t3, t2));
e1159bbe 10048 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10049 DONE;
10050 }"
10051)
10052
8f4be2be 10053(define_expand "ctzsi2"
10054 [(set (match_operand:SI 0 "s_register_operand" "")
10055 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10056 "TARGET_ARM && arm_arch5"
10057 "
10058 {
10059 rtx t1, t2, t3;
10060
10061 t1 = gen_reg_rtx (SImode);
10062 t2 = gen_reg_rtx (SImode);
10063 t3 = gen_reg_rtx (SImode);
10064
10065 emit_insn (gen_negsi2 (t1, operands[1]));
10066 emit_insn (gen_andsi3 (t2, operands[1], t1));
10067 emit_insn (gen_clzsi2 (t3, t2));
10068 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10069 DONE;
10070 }"
10071)
10072
e1159bbe 10073;; V5E instructions.
331beb1a 10074
10075(define_insn "prefetch"
f4e79814 10076 [(prefetch (match_operand:SI 0 "address_operand" "p")
10077 (match_operand:SI 1 "" "")
10078 (match_operand:SI 2 "" ""))]
e1159bbe 10079 "TARGET_ARM && arm_arch5e"
bcb7a8f6 10080 "pld\\t%a0")
331beb1a 10081
0d66636f 10082;; General predication pattern
10083
10084(define_cond_exec
10085 [(match_operator 0 "arm_comparison_operator"
10086 [(match_operand 1 "cc_register" "")
10087 (const_int 0)])]
10088 "TARGET_ARM"
10089 ""
10090)
10091
063a05c7 10092(define_insn "prologue_use"
10093 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10094 ""
10095 "%@ %0 needed for prologue"
10096)
7db9af5d 10097
4c44712e 10098
10099;; Patterns for exception handling
10100
10101(define_expand "eh_return"
10102 [(use (match_operand 0 "general_operand" ""))]
10103 "TARGET_EITHER"
10104 "
10105 {
10106 if (TARGET_ARM)
10107 emit_insn (gen_arm_eh_return (operands[0]));
10108 else
10109 emit_insn (gen_thumb_eh_return (operands[0]));
10110 DONE;
10111 }"
10112)
10113
10114;; We can't expand this before we know where the link register is stored.
10115(define_insn_and_split "arm_eh_return"
10116 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10117 VUNSPEC_EH_RETURN)
10118 (clobber (match_scratch:SI 1 "=&r"))]
10119 "TARGET_ARM"
10120 "#"
10121 "&& reload_completed"
10122 [(const_int 0)]
10123 "
10124 {
10125 arm_set_return_address (operands[0], operands[1]);
10126 DONE;
10127 }"
10128)
10129
10130(define_insn_and_split "thumb_eh_return"
10131 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10132 VUNSPEC_EH_RETURN)
10133 (clobber (match_scratch:SI 1 "=&l"))]
10134 "TARGET_THUMB"
10135 "#"
10136 "&& reload_completed"
10137 [(const_int 0)]
10138 "
10139 {
10140 thumb_set_return_address (operands[0], operands[1]);
10141 DONE;
10142 }"
10143)
10144
f655717d 10145\f
10146;; TLS support
10147
10148(define_insn "load_tp_hard"
10149 [(set (match_operand:SI 0 "register_operand" "=r")
10150 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10151 "TARGET_HARD_TP"
10152 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10153 [(set_attr "predicable" "yes")]
10154)
10155
10156;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10157(define_insn "load_tp_soft"
10158 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10159 (clobber (reg:SI LR_REGNUM))
10160 (clobber (reg:SI IP_REGNUM))
10161 (clobber (reg:CC CC_REGNUM))]
10162 "TARGET_SOFT_TP"
10163 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10164 [(set_attr "conds" "clob")]
10165)
10166
7db9af5d 10167;; Load the FPA co-processor patterns
10168(include "fpa.md")
10169;; Load the Maverick co-processor patterns
10170(include "cirrus.md")
755eb2b4 10171;; Load the Intel Wireless Multimedia Extension patterns
10172(include "iwmmxt.md")
a2cd141b 10173;; Load the VFP co-processor patterns
10174(include "vfp.md")
10175