]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2005-05-11 Richard Guenther <rguenth@gcc.gnu.org>
[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
9b754436 22;; the Free Software Foundation, 59 Temple Place - Suite 330,
cebb6efe 23;; Boston, MA 02111-1307, 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.
e1159bbe 93 ]
94)
95
215b30b3 96;; UNSPEC_VOLATILE Usage:
e1159bbe 97
98(define_constants
99 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
100 ; insn in the code.
101 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102 ; instruction epilogue sequence that isn't expanded
103 ; into normal RTL. Used for both normal and sibcall
104 ; epilogues.
105 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
106 ; for inlined constants.
107 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
108 ; table.
109 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
110 ; an 8-bit object.
111 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
112 ; a 16-bit object.
113 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
114 ; a 32-bit object.
115 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
116 ; a 64-bit object.
755eb2b4 117 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
118 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
119 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
120 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
121 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 123 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 124 ; handling.
e1159bbe 125 ]
126)
b11cae9e 127\f
e1159bbe 128;;---------------------------------------------------------------------------
9c08d1fa 129;; Attributes
130
215b30b3 131; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132; generating ARM code. This is used to control the length of some insn
133; patterns that share the same RTL in both ARM and Thumb code.
1c494086 134(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 135
215b30b3 136; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137; scheduling decisions for the load unit and the multiplier.
74a71f7d 138(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 139
5ecb8da7 140; IS_XSCALE is set to 'yes' when compiling for XScale.
141(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
142
331beb1a 143;; Operand number of an input operand that is shifted. Zero if the
144;; given instruction does not shift one of its input operands.
331beb1a 145(define_attr "shift" "" (const_int 0))
146
3d91c5d6 147; Floating Point Unit. If we only have floating point emulation, then there
148; is no point in scheduling the floating point insns. (Well, for best
149; performance we should try and group them together).
a2cd141b 150(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 151 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 152
094e994f 153; LENGTH of an instruction (in bytes)
154(define_attr "length" "" (const_int 4))
9c08d1fa 155
56d27660 156; POOL_RANGE is how far away from a constant pool entry that this insn
157; can be placed. If the distance is zero, then this insn will never
158; reference the pool.
cffb2a26 159; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160; before its address.
56d27660 161(define_attr "pool_range" "" (const_int 0))
cffb2a26 162(define_attr "neg_pool_range" "" (const_int 0))
56d27660 163
215b30b3 164; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 165; If such an insn references the pool, then we have no way of knowing how,
166; so use the most conservative value for pool_range.
9c08d1fa 167(define_asm_attributes
4d7a8451 168 [(set_attr "conds" "clob")
169 (set_attr "length" "4")
170 (set_attr "pool_range" "250")])
9c08d1fa 171
a2cd141b 172;; The instruction used to implement a particular pattern. This
173;; information is used by pipeline descriptions to provide accurate
174;; scheduling information.
175
176(define_attr "insn"
177 "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"
178 (const_string "other"))
179
9c08d1fa 180; TYPE attribute is used to detect floating point instructions which, if
181; running on a co-processor can run in parallel with other, basic instructions
182; If write-buffer scheduling is enabled then it can also be used in the
183; scheduling of writes.
184
185; Classification of each insn
a2cd141b 186; alu any alu instruction that doesn't hit memory or fp
187; regs or have a shifted source operand
188; alu_shift any data instruction that doesn't hit memory or fp
189; regs, but has a source operand shifted by a constant
190; alu_shift_reg any data instruction that doesn't hit memory or fp
191; regs, but has a source operand shifted by a register value
f7fbdd4a 192; mult a multiply instruction
9c08d1fa 193; block blockage insn, this blocks all functional units
194; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 195; fdivd DFmode floating point division
196; fdivs SFmode floating point division
197; fmul Floating point multiply
198; ffmul Fast floating point multiply
199; farith Floating point arithmetic (4 cycle)
200; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 201; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 202; even on a machine with an fpa.
9c08d1fa 203; f_load a floating point load from memory
204; f_store a floating point store to memory
205; f_mem_r a transfer of a floating point register to a real reg via mem
206; r_mem_f the reverse of f_mem_r
207; f_2_r fast transfer float to arm (no memory needed)
208; r_2_f fast transfer arm to float
a2cd141b 209; branch a branch
9c08d1fa 210; call a subroutine call
a2cd141b 211; load_byte load byte(s) from memory to arm registers
212; load1 load 1 word from memory to arm registers
213; load2 load 2 words from memory to arm registers
214; load3 load 3 words from memory to arm registers
215; load4 load 4 words from memory to arm registers
216; store store 1 word to memory from arm registers
9c08d1fa 217; store2 store 2 words
218; store3 store 3 words
a2cd141b 219; store4 store 4 (or more) words
2c6c7d8b 220; Additions for Cirrus Maverick co-processor:
221; mav_farith Floating point arithmetic (4 cycle)
222; mav_dmult Double multiplies (7 cycle)
9c08d1fa 223;
224(define_attr "type"
a2cd141b 225 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
226 (if_then_else
227 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228 (const_string "mult")
229 (const_string "alu")))
9c08d1fa 230
9888ad6d 231; Load scheduling, set from the arm_ld_sched variable
457275b6 232; initialized by arm_override_options()
9888ad6d 233(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 234
f7fbdd4a 235; condition codes: this one is used by final_prescan_insn to speed up
236; conditionalizing instructions. It saves having to scan the rtl to see if
237; it uses or alters the condition codes.
215b30b3 238;
f7fbdd4a 239; USE means that the condition codes are used by the insn in the process of
215b30b3 240; outputting code, this means (at present) that we can't use the insn in
241; inlined branches
242;
f7fbdd4a 243; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 244; well defined manner.
245;
f7fbdd4a 246; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 247; they are altered at all
248;
8fa3ba89 249; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 250; instruction (UNEQ and LTGT). These cannot be predicated.
251;
f7fbdd4a 252; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 253; output of this insn
f7fbdd4a 254
255(define_attr "conds" "use,set,clob,jump_clob,nocond"
256 (if_then_else (eq_attr "type" "call")
c1a66faf 257 (const_string "clob")
f7fbdd4a 258 (const_string "nocond")))
259
215b30b3 260; Predicable means that the insn can be conditionally executed based on
261; an automatically added predicate (additional patterns are generated by
262; gen...). We default to 'no' because no Thumb patterns match this rule
263; and not all ARM patterns do.
0d66636f 264(define_attr "predicable" "no,yes" (const_string "no"))
265
129a2fe4 266; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
267; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 268; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 269; affect the schedule).
74a71f7d 270(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 271
215b30b3 272; WRITE_CONFLICT implies that a read following an unrelated write is likely
273; to stall the processor. Used with model_wbuf above.
9c08d1fa 274(define_attr "write_conflict" "no,yes"
275 (if_then_else (eq_attr "type"
a2cd141b 276 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 277 (const_string "yes")
278 (const_string "no")))
279
215b30b3 280; Classify the insns into those that take one cycle and those that take more
281; than one on the main cpu execution unit.
f7fbdd4a 282(define_attr "core_cycles" "single,multi"
283 (if_then_else (eq_attr "type"
a2cd141b 284 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 285 (const_string "single")
286 (const_string "multi")))
287
cffb2a26 288;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 289;; distant label. Only applicable to Thumb code.
cffb2a26 290(define_attr "far_jump" "yes,no" (const_string "no"))
291
d51f92df 292
293;;---------------------------------------------------------------------------
294;; Mode macros
295
296; A list of modes that are exactly 64 bits in size. We use this to expand
297; some splits that are the same for all modes when operating on ARM
298; registers.
299(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
300
301;;---------------------------------------------------------------------------
302;; Predicates
303
9c9db025 304(include "predicates.md")
305
a2cd141b 306;;---------------------------------------------------------------------------
307;; Pipeline descriptions
215b30b3 308
06469f9e 309;; Processor type. This is created automatically from arm-cores.def.
310(include "arm-tune.md")
331beb1a 311
a2cd141b 312;; True if the generic scheduling description should be used.
313
314(define_attr "generic_sched" "yes,no"
4d5cb40d 315 (const (if_then_else
316 (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs")
317 (const_string "no")
318 (const_string "yes"))))
319
a2cd141b 320(include "arm-generic.md")
321(include "arm926ejs.md")
322(include "arm1026ejs.md")
323(include "arm1136jfs.md")
3586df96 324
9c08d1fa 325\f
215b30b3 326;;---------------------------------------------------------------------------
e1159bbe 327;; Insn patterns
328;;
a0f94409 329;; Addition insns.
215b30b3 330
9c08d1fa 331;; Note: For DImode insns, there is normally no reason why operands should
332;; not be in the same register, what we don't want is for something being
333;; written to partially overlap something that is an input.
7d57ec45 334;; Cirrus 64bit additions should not be split because we have a native
335;; 64bit addition instructions.
9c08d1fa 336
cffb2a26 337(define_expand "adddi3"
338 [(parallel
215b30b3 339 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 340 (plus:DI (match_operand:DI 1 "s_register_operand" "")
341 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 342 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 343 "TARGET_EITHER"
344 "
a2cd141b 345 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 346 {
347 if (!cirrus_fp_register (operands[0], DImode))
348 operands[0] = force_reg (DImode, operands[0]);
349 if (!cirrus_fp_register (operands[1], DImode))
350 operands[1] = force_reg (DImode, operands[1]);
351 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
352 DONE;
353 }
354
cffb2a26 355 if (TARGET_THUMB)
356 {
357 if (GET_CODE (operands[1]) != REG)
358 operands[1] = force_reg (SImode, operands[1]);
359 if (GET_CODE (operands[2]) != REG)
360 operands[2] = force_reg (SImode, operands[2]);
361 }
362 "
363)
364
365(define_insn "*thumb_adddi3"
366 [(set (match_operand:DI 0 "register_operand" "=l")
367 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 368 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 369 (clobber (reg:CC CC_REGNUM))
cffb2a26 370 ]
371 "TARGET_THUMB"
372 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
373 [(set_attr "length" "4")]
374)
375
a0f94409 376(define_insn_and_split "*arm_adddi3"
cffb2a26 377 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 378 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
379 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 380 (clobber (reg:CC CC_REGNUM))]
a2cd141b 381 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 382 "#"
a0f94409 383 "TARGET_ARM && reload_completed"
384 [(parallel [(set (reg:CC_C CC_REGNUM)
385 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
386 (match_dup 1)))
387 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
388 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
389 (plus:SI (match_dup 4) (match_dup 5))))]
390 "
391 {
392 operands[3] = gen_highpart (SImode, operands[0]);
393 operands[0] = gen_lowpart (SImode, operands[0]);
394 operands[4] = gen_highpart (SImode, operands[1]);
395 operands[1] = gen_lowpart (SImode, operands[1]);
396 operands[5] = gen_highpart (SImode, operands[2]);
397 operands[2] = gen_lowpart (SImode, operands[2]);
398 }"
cffb2a26 399 [(set_attr "conds" "clob")
400 (set_attr "length" "8")]
401)
9c08d1fa 402
a0f94409 403(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 404 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
405 (plus:DI (sign_extend:DI
97499065 406 (match_operand:SI 2 "s_register_operand" "r,r"))
407 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 408 (clobber (reg:CC CC_REGNUM))]
a2cd141b 409 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 410 "#"
a0f94409 411 "TARGET_ARM && reload_completed"
412 [(parallel [(set (reg:CC_C CC_REGNUM)
413 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
414 (match_dup 1)))
415 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
416 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
417 (plus:SI (ashiftrt:SI (match_dup 2)
418 (const_int 31))
419 (match_dup 4))))]
420 "
421 {
422 operands[3] = gen_highpart (SImode, operands[0]);
423 operands[0] = gen_lowpart (SImode, operands[0]);
424 operands[4] = gen_highpart (SImode, operands[1]);
425 operands[1] = gen_lowpart (SImode, operands[1]);
426 operands[2] = gen_lowpart (SImode, operands[2]);
427 }"
215b30b3 428 [(set_attr "conds" "clob")
429 (set_attr "length" "8")]
430)
9c08d1fa 431
a0f94409 432(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 433 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
434 (plus:DI (zero_extend:DI
97499065 435 (match_operand:SI 2 "s_register_operand" "r,r"))
436 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 437 (clobber (reg:CC CC_REGNUM))]
a2cd141b 438 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 439 "#"
a0f94409 440 "TARGET_ARM && reload_completed"
441 [(parallel [(set (reg:CC_C CC_REGNUM)
442 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
443 (match_dup 1)))
444 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
445 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
446 (plus:SI (match_dup 4) (const_int 0))))]
447 "
448 {
449 operands[3] = gen_highpart (SImode, operands[0]);
450 operands[0] = gen_lowpart (SImode, operands[0]);
451 operands[4] = gen_highpart (SImode, operands[1]);
452 operands[1] = gen_lowpart (SImode, operands[1]);
453 operands[2] = gen_lowpart (SImode, operands[2]);
454 }"
cffb2a26 455 [(set_attr "conds" "clob")
456 (set_attr "length" "8")]
457)
b11cae9e 458
87b22bf7 459(define_expand "addsi3"
cffb2a26 460 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 461 (plus:SI (match_operand:SI 1 "s_register_operand" "")
462 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 463 "TARGET_EITHER"
87b22bf7 464 "
cffb2a26 465 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 466 {
96f57e36 467 arm_split_constant (PLUS, SImode, NULL_RTX,
468 INTVAL (operands[2]), operands[0], operands[1],
615caa51 469 optimize && !no_new_pseudos);
87b22bf7 470 DONE;
471 }
cffb2a26 472 "
473)
87b22bf7 474
5bd751ff 475; If there is a scratch available, this will be faster than synthesizing the
a0f94409 476; addition.
477(define_peephole2
478 [(match_scratch:SI 3 "r")
372575c7 479 (set (match_operand:SI 0 "arm_general_register_operand" "")
480 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 481 (match_operand:SI 2 "const_int_operand" "")))]
482 "TARGET_ARM &&
a0f94409 483 !(const_ok_for_arm (INTVAL (operands[2]))
484 || const_ok_for_arm (-INTVAL (operands[2])))
485 && const_ok_for_arm (~INTVAL (operands[2]))"
486 [(set (match_dup 3) (match_dup 2))
487 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
488 ""
489)
87b22bf7 490
a0f94409 491(define_insn_and_split "*arm_addsi3"
cffb2a26 492 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0f94409 493 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
87b22bf7 494 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
cffb2a26 495 "TARGET_ARM"
5565501b 496 "@
497 add%?\\t%0, %1, %2
87b22bf7 498 sub%?\\t%0, %1, #%n2
499 #"
a0f94409 500 "TARGET_ARM &&
501 GET_CODE (operands[2]) == CONST_INT
502 && !(const_ok_for_arm (INTVAL (operands[2]))
503 || const_ok_for_arm (-INTVAL (operands[2])))"
504 [(clobber (const_int 0))]
505 "
96f57e36 506 arm_split_constant (PLUS, SImode, curr_insn,
507 INTVAL (operands[2]), operands[0],
a0f94409 508 operands[1], 0);
509 DONE;
510 "
0d66636f 511 [(set_attr "length" "4,4,16")
512 (set_attr "predicable" "yes")]
cffb2a26 513)
514
515;; Register group 'k' is a single register group containing only the stack
516;; register. Trying to reload it will always fail catastrophically,
517;; so never allow those alternatives to match if reloading is needed.
518
519(define_insn "*thumb_addsi3"
520 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
521 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
522 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
523 "TARGET_THUMB"
524 "*
0d66636f 525 static const char * const asms[] =
cffb2a26 526 {
527 \"add\\t%0, %0, %2\",
528 \"sub\\t%0, %0, #%n2\",
529 \"add\\t%0, %1, %2\",
530 \"add\\t%0, %0, %2\",
531 \"add\\t%0, %0, %2\",
532 \"add\\t%0, %1, %2\",
533 \"add\\t%0, %1, %2\"
534 };
535 if ((which_alternative == 2 || which_alternative == 6)
536 && GET_CODE (operands[2]) == CONST_INT
537 && INTVAL (operands[2]) < 0)
538 return \"sub\\t%0, %1, #%n2\";
539 return asms[which_alternative];
540 "
541 [(set_attr "length" "2")]
542)
543
544;; Reloading and elimination of the frame pointer can
545;; sometimes cause this optimization to be missed.
a0f94409 546(define_peephole2
372575c7 547 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 548 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 549 (set (match_dup 0)
372575c7 550 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
cffb2a26 551 "TARGET_THUMB
cffb2a26 552 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
553 && (INTVAL (operands[1]) & 3) == 0"
372575c7 554 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 555 ""
cffb2a26 556)
b11cae9e 557
f7fbdd4a 558(define_insn "*addsi3_compare0"
bd5b4116 559 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 560 (compare:CC_NOOV
215b30b3 561 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
562 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 563 (const_int 0)))
564 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 565 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 566 "TARGET_ARM"
5565501b 567 "@
568 add%?s\\t%0, %1, %2
569 sub%?s\\t%0, %1, #%n2"
cffb2a26 570 [(set_attr "conds" "set")]
571)
9c08d1fa 572
aea4c774 573(define_insn "*addsi3_compare0_scratch"
bd5b4116 574 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 575 (compare:CC_NOOV
215b30b3 576 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
577 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 578 (const_int 0)))]
cffb2a26 579 "TARGET_ARM"
580 "@
581 cmn%?\\t%0, %1
582 cmp%?\\t%0, #%n1"
0d66636f 583 [(set_attr "conds" "set")]
584)
cffb2a26 585
aed179ae 586(define_insn "*compare_negsi_si"
587 [(set (reg:CC_Z CC_REGNUM)
588 (compare:CC_Z
589 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
590 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 591 "TARGET_ARM"
aed179ae 592 "cmn%?\\t%1, %0"
0d66636f 593 [(set_attr "conds" "set")]
594)
aea4c774 595
203c488f 596;; This is the canonicalization of addsi3_compare0_for_combiner when the
597;; addend is a constant.
598(define_insn "*cmpsi2_addneg"
599 [(set (reg:CC CC_REGNUM)
600 (compare:CC
601 (match_operand:SI 1 "s_register_operand" "r,r")
602 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
603 (set (match_operand:SI 0 "s_register_operand" "=r,r")
604 (plus:SI (match_dup 1)
605 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
606 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
607 "@
608 sub%?s\\t%0, %1, %2
609 add%?s\\t%0, %1, #%n2"
610 [(set_attr "conds" "set")]
611)
612
613;; Convert the sequence
614;; sub rd, rn, #1
615;; cmn rd, #1 (equivalent to cmp rd, #-1)
616;; bne dest
617;; into
618;; subs rd, rn, #1
619;; bcs dest ((unsigned)rn >= 1)
620;; similarly for the beq variant using bcc.
621;; This is a common looping idiom (while (n--))
622(define_peephole2
372575c7 623 [(set (match_operand:SI 0 "arm_general_register_operand" "")
624 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 625 (const_int -1)))
626 (set (match_operand 2 "cc_register" "")
627 (compare (match_dup 0) (const_int -1)))
628 (set (pc)
629 (if_then_else (match_operator 3 "equality_operator"
630 [(match_dup 2) (const_int 0)])
631 (match_operand 4 "" "")
632 (match_operand 5 "" "")))]
633 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
634 [(parallel[
635 (set (match_dup 2)
636 (compare:CC
637 (match_dup 1) (const_int 1)))
638 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
639 (set (pc)
640 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
641 (match_dup 4)
642 (match_dup 5)))]
643 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
644 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
645 ? GEU : LTU),
646 VOIDmode,
647 operands[2], const0_rtx);"
648)
649
ebcc79bc 650;; The next four insns work because they compare the result with one of
651;; the operands, and we know that the use of the condition code is
652;; either GEU or LTU, so we can use the carry flag from the addition
653;; instead of doing the compare a second time.
654(define_insn "*addsi3_compare_op1"
bd5b4116 655 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 656 (compare:CC_C
657 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
658 (match_operand:SI 2 "arm_add_operand" "rI,L"))
659 (match_dup 1)))
660 (set (match_operand:SI 0 "s_register_operand" "=r,r")
661 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 662 "TARGET_ARM"
ebcc79bc 663 "@
664 add%?s\\t%0, %1, %2
665 sub%?s\\t%0, %1, #%n2"
0d66636f 666 [(set_attr "conds" "set")]
667)
ebcc79bc 668
669(define_insn "*addsi3_compare_op2"
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 2)))
5565501b 675 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 676 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 677 "TARGET_ARM"
5565501b 678 "@
679 add%?s\\t%0, %1, %2
680 sub%?s\\t%0, %1, #%n2"
0d66636f 681 [(set_attr "conds" "set")]
682)
9c08d1fa 683
ebcc79bc 684(define_insn "*compare_addsi2_op0"
bd5b4116 685 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 686 (compare:CC_C
687 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
688 (match_operand:SI 1 "arm_add_operand" "rI,L"))
689 (match_dup 0)))]
cffb2a26 690 "TARGET_ARM"
ebcc79bc 691 "@
692 cmn%?\\t%0, %1
693 cmp%?\\t%0, #%n1"
0d66636f 694 [(set_attr "conds" "set")]
695)
ebcc79bc 696
697(define_insn "*compare_addsi2_op1"
bd5b4116 698 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 699 (compare:CC_C
700 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
701 (match_operand:SI 1 "arm_add_operand" "rI,L"))
702 (match_dup 1)))]
cffb2a26 703 "TARGET_ARM"
ebcc79bc 704 "@
705 cmn%?\\t%0, %1
706 cmp%?\\t%0, #%n1"
0d66636f 707 [(set_attr "conds" "set")]
708)
ebcc79bc 709
710(define_insn "*addsi3_carryin"
711 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 712 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 713 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
714 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
cffb2a26 715 "TARGET_ARM"
ebcc79bc 716 "adc%?\\t%0, %1, %2"
cffb2a26 717 [(set_attr "conds" "use")]
718)
ebcc79bc 719
33782ec7 720(define_insn "*addsi3_carryin_shift"
7b63a8dd 721 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 722 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 723 (plus:SI
724 (match_operator:SI 2 "shift_operator"
7b63a8dd 725 [(match_operand:SI 3 "s_register_operand" "r")
726 (match_operand:SI 4 "reg_or_int_operand" "rM")])
727 (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 728 "TARGET_ARM"
33782ec7 729 "adc%?\\t%0, %1, %3%S2"
a2cd141b 730 [(set_attr "conds" "use")
731 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
732 (const_string "alu_shift")
733 (const_string "alu_shift_reg")))]
33782ec7 734)
735
ebcc79bc 736(define_insn "*addsi3_carryin_alt1"
737 [(set (match_operand:SI 0 "s_register_operand" "=r")
738 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
739 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 740 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
cffb2a26 741 "TARGET_ARM"
ebcc79bc 742 "adc%?\\t%0, %1, %2"
cffb2a26 743 [(set_attr "conds" "use")]
744)
ebcc79bc 745
746(define_insn "*addsi3_carryin_alt2"
747 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 748 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 749 (match_operand:SI 1 "s_register_operand" "r"))
750 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 751 "TARGET_ARM"
ebcc79bc 752 "adc%?\\t%0, %1, %2"
0d66636f 753 [(set_attr "conds" "use")]
754)
ebcc79bc 755
756(define_insn "*addsi3_carryin_alt3"
757 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 758 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 759 (match_operand:SI 2 "arm_rhs_operand" "rI"))
760 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 761 "TARGET_ARM"
ebcc79bc 762 "adc%?\\t%0, %1, %2"
cffb2a26 763 [(set_attr "conds" "use")]
764)
ebcc79bc 765
9c08d1fa 766(define_insn "incscc"
767 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 768 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 769 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 770 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 771 "TARGET_ARM"
5565501b 772 "@
773 add%d2\\t%0, %1, #1
774 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 775 [(set_attr "conds" "use")
215b30b3 776 (set_attr "length" "4,8")]
777)
9c08d1fa 778
d795fb69 779; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
780(define_split
781 [(set (match_operand:SI 0 "s_register_operand" "")
782 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
783 (match_operand:SI 2 "s_register_operand" ""))
784 (const_int -1)))
785 (clobber (match_operand:SI 3 "s_register_operand" ""))]
786 "TARGET_ARM"
787 [(set (match_dup 3) (match_dup 1))
788 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
789 "
790 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
791")
792
604f3a0a 793(define_expand "addsf3"
794 [(set (match_operand:SF 0 "s_register_operand" "")
795 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 796 (match_operand:SF 2 "arm_float_add_operand" "")))]
797 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 798 "
a2cd141b 799 if (TARGET_MAVERICK
604f3a0a 800 && !cirrus_fp_register (operands[2], SFmode))
801 operands[2] = force_reg (SFmode, operands[2]);
802")
803
604f3a0a 804(define_expand "adddf3"
805 [(set (match_operand:DF 0 "s_register_operand" "")
806 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 807 (match_operand:DF 2 "arm_float_add_operand" "")))]
808 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 809 "
a2cd141b 810 if (TARGET_MAVERICK
604f3a0a 811 && !cirrus_fp_register (operands[2], DFmode))
812 operands[2] = force_reg (DFmode, operands[2]);
813")
814
cffb2a26 815(define_expand "subdi3"
816 [(parallel
817 [(set (match_operand:DI 0 "s_register_operand" "")
818 (minus:DI (match_operand:DI 1 "s_register_operand" "")
819 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 820 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 821 "TARGET_EITHER"
822 "
a2cd141b 823 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
7d57ec45 824 && TARGET_ARM
825 && cirrus_fp_register (operands[0], DImode)
826 && cirrus_fp_register (operands[1], DImode))
827 {
828 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
829 DONE;
830 }
831
cffb2a26 832 if (TARGET_THUMB)
833 {
834 if (GET_CODE (operands[1]) != REG)
835 operands[1] = force_reg (SImode, operands[1]);
836 if (GET_CODE (operands[2]) != REG)
837 operands[2] = force_reg (SImode, operands[2]);
838 }
839 "
840)
841
842(define_insn "*arm_subdi3"
843 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 844 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
845 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 846 (clobber (reg:CC CC_REGNUM))]
cffb2a26 847 "TARGET_ARM"
97499065 848 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 849 [(set_attr "conds" "clob")
850 (set_attr "length" "8")]
851)
852
853(define_insn "*thumb_subdi3"
854 [(set (match_operand:DI 0 "register_operand" "=l")
855 (minus:DI (match_operand:DI 1 "register_operand" "0")
856 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 857 (clobber (reg:CC CC_REGNUM))]
cffb2a26 858 "TARGET_THUMB"
859 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
860 [(set_attr "length" "4")]
861)
9c08d1fa 862
f7fbdd4a 863(define_insn "*subdi_di_zesidi"
cffb2a26 864 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
865 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 866 (zero_extend:DI
cffb2a26 867 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 868 (clobber (reg:CC CC_REGNUM))]
cffb2a26 869 "TARGET_ARM"
97499065 870 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 871 [(set_attr "conds" "clob")
872 (set_attr "length" "8")]
873)
9c08d1fa 874
f7fbdd4a 875(define_insn "*subdi_di_sesidi"
cffb2a26 876 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
877 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 878 (sign_extend:DI
cffb2a26 879 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 880 (clobber (reg:CC CC_REGNUM))]
cffb2a26 881 "TARGET_ARM"
97499065 882 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 883 [(set_attr "conds" "clob")
884 (set_attr "length" "8")]
885)
9c08d1fa 886
f7fbdd4a 887(define_insn "*subdi_zesidi_di"
cffb2a26 888 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 889 (minus:DI (zero_extend:DI
cffb2a26 890 (match_operand:SI 2 "s_register_operand" "r,r"))
891 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 892 (clobber (reg:CC CC_REGNUM))]
cffb2a26 893 "TARGET_ARM"
97499065 894 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 895 [(set_attr "conds" "clob")
896 (set_attr "length" "8")]
897)
9c08d1fa 898
f7fbdd4a 899(define_insn "*subdi_sesidi_di"
cffb2a26 900 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 901 (minus:DI (sign_extend:DI
cffb2a26 902 (match_operand:SI 2 "s_register_operand" "r,r"))
903 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 904 (clobber (reg:CC CC_REGNUM))]
cffb2a26 905 "TARGET_ARM"
97499065 906 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 907 [(set_attr "conds" "clob")
908 (set_attr "length" "8")]
909)
9c08d1fa 910
f7fbdd4a 911(define_insn "*subdi_zesidi_zesidi"
cffb2a26 912 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 913 (minus:DI (zero_extend:DI
cffb2a26 914 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 915 (zero_extend:DI
cffb2a26 916 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 917 (clobber (reg:CC CC_REGNUM))]
cffb2a26 918 "TARGET_ARM"
97499065 919 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
cffb2a26 920 [(set_attr "conds" "clob")
921 (set_attr "length" "8")]
922)
b11cae9e 923
87b22bf7 924(define_expand "subsi3"
cffb2a26 925 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 926 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
927 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 928 "TARGET_EITHER"
87b22bf7 929 "
930 if (GET_CODE (operands[1]) == CONST_INT)
931 {
cffb2a26 932 if (TARGET_ARM)
933 {
96f57e36 934 arm_split_constant (MINUS, SImode, NULL_RTX,
935 INTVAL (operands[1]), operands[0],
615caa51 936 operands[2], optimize && !no_new_pseudos);
cffb2a26 937 DONE;
938 }
939 else /* TARGET_THUMB */
940 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 941 }
cffb2a26 942 "
943)
87b22bf7 944
cffb2a26 945(define_insn "*thumb_subsi3_insn"
946 [(set (match_operand:SI 0 "register_operand" "=l")
947 (minus:SI (match_operand:SI 1 "register_operand" "l")
948 (match_operand:SI 2 "register_operand" "l")))]
949 "TARGET_THUMB"
950 "sub\\t%0, %1, %2"
951 [(set_attr "length" "2")]
952)
953
a0f94409 954(define_insn_and_split "*arm_subsi3_insn"
cffb2a26 955 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 956 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
957 (match_operand:SI 2 "s_register_operand" "r,r")))]
cffb2a26 958 "TARGET_ARM"
e2348bcb 959 "@
87b22bf7 960 rsb%?\\t%0, %2, %1
961 #"
a0f94409 962 "TARGET_ARM
963 && GET_CODE (operands[1]) == CONST_INT
964 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 965 [(clobber (const_int 0))]
966 "
96f57e36 967 arm_split_constant (MINUS, SImode, curr_insn,
968 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 969 DONE;
cffb2a26 970 "
a0f94409 971 [(set_attr "length" "4,16")
972 (set_attr "predicable" "yes")]
973)
974
975(define_peephole2
976 [(match_scratch:SI 3 "r")
372575c7 977 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 978 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 979 (match_operand:SI 2 "arm_general_register_operand" "")))]
a0f94409 980 "TARGET_ARM
981 && !const_ok_for_arm (INTVAL (operands[1]))
982 && const_ok_for_arm (~INTVAL (operands[1]))"
983 [(set (match_dup 3) (match_dup 1))
984 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
985 ""
cffb2a26 986)
b11cae9e 987
f7fbdd4a 988(define_insn "*subsi3_compare0"
bd5b4116 989 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 990 (compare:CC_NOOV
991 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
992 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
993 (const_int 0)))
9c08d1fa 994 (set (match_operand:SI 0 "s_register_operand" "=r,r")
995 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 996 "TARGET_ARM"
e2348bcb 997 "@
40dbec34 998 sub%?s\\t%0, %1, %2
999 rsb%?s\\t%0, %2, %1"
cffb2a26 1000 [(set_attr "conds" "set")]
1001)
9c08d1fa 1002
1003(define_insn "decscc"
cffb2a26 1004 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1005 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1006 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1007 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1008 "TARGET_ARM"
e2348bcb 1009 "@
215b30b3 1010 sub%d2\\t%0, %1, #1
1011 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1012 [(set_attr "conds" "use")
1013 (set_attr "length" "*,8")]
1014)
9c08d1fa 1015
604f3a0a 1016(define_expand "subsf3"
1017 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1018 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1019 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1020 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1021 "
a2cd141b 1022 if (TARGET_MAVERICK)
604f3a0a 1023 {
1024 if (!cirrus_fp_register (operands[1], SFmode))
1025 operands[1] = force_reg (SFmode, operands[1]);
1026 if (!cirrus_fp_register (operands[2], SFmode))
1027 operands[2] = force_reg (SFmode, operands[2]);
1028 }
1029")
1030
604f3a0a 1031(define_expand "subdf3"
1032 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1033 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1034 (match_operand:DF 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], DFmode))
1040 operands[1] = force_reg (DFmode, operands[1]);
1041 if (!cirrus_fp_register (operands[2], DFmode))
1042 operands[2] = force_reg (DFmode, operands[2]);
1043 }
1044")
1045
b11cae9e 1046\f
1047;; Multiplication insns
1048
cffb2a26 1049(define_expand "mulsi3"
1050 [(set (match_operand:SI 0 "s_register_operand" "")
1051 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1052 (match_operand:SI 1 "s_register_operand" "")))]
1053 "TARGET_EITHER"
1054 ""
1055)
1056
9c08d1fa 1057;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1058(define_insn "*arm_mulsi3"
1059 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1060 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1061 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
cffb2a26 1062 "TARGET_ARM"
f7fbdd4a 1063 "mul%?\\t%0, %2, %1"
a2cd141b 1064 [(set_attr "insn" "mul")
0d66636f 1065 (set_attr "predicable" "yes")]
cffb2a26 1066)
1067
215b30b3 1068; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1069; 1 and 2; are the same, because reload will make operand 0 match
1070; operand 1 without realizing that this conflicts with operand 2. We fix
1071; this by adding another alternative to match this case, and then `reload'
1072; it ourselves. This alternative must come first.
cffb2a26 1073(define_insn "*thumb_mulsi3"
1074 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1075 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1076 (match_operand:SI 2 "register_operand" "l,l,l")))]
1077 "TARGET_THUMB"
1078 "*
1079 if (which_alternative < 2)
20c4e896 1080 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1081 else
20c4e896 1082 return \"mul\\t%0, %2\";
cffb2a26 1083 "
1084 [(set_attr "length" "4,4,2")
a2cd141b 1085 (set_attr "insn" "mul")]
cffb2a26 1086)
b11cae9e 1087
f7fbdd4a 1088(define_insn "*mulsi3_compare0"
bd5b4116 1089 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1090 (compare:CC_NOOV (mult:SI
1091 (match_operand:SI 2 "s_register_operand" "r,r")
1092 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1093 (const_int 0)))
1094 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1095 (mult:SI (match_dup 2) (match_dup 1)))]
e8a4aa75 1096 "TARGET_ARM"
40dbec34 1097 "mul%?s\\t%0, %2, %1"
cffb2a26 1098 [(set_attr "conds" "set")
a2cd141b 1099 (set_attr "insn" "muls")]
cffb2a26 1100)
9c08d1fa 1101
f7fbdd4a 1102(define_insn "*mulsi_compare0_scratch"
bd5b4116 1103 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1104 (compare:CC_NOOV (mult:SI
1105 (match_operand:SI 2 "s_register_operand" "r,r")
1106 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1107 (const_int 0)))
1108 (clobber (match_scratch:SI 0 "=&r,&r"))]
e8a4aa75 1109 "TARGET_ARM"
40dbec34 1110 "mul%?s\\t%0, %2, %1"
cffb2a26 1111 [(set_attr "conds" "set")
a2cd141b 1112 (set_attr "insn" "muls")]
cffb2a26 1113)
9c08d1fa 1114
b11cae9e 1115;; Unnamed templates to match MLA instruction.
1116
f7fbdd4a 1117(define_insn "*mulsi3addsi"
9c08d1fa 1118 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1119 (plus:SI
9c08d1fa 1120 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1121 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1122 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
cffb2a26 1123 "TARGET_ARM"
f7fbdd4a 1124 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1125 [(set_attr "insn" "mla")
0d66636f 1126 (set_attr "predicable" "yes")]
1127)
b11cae9e 1128
f7fbdd4a 1129(define_insn "*mulsi3addsi_compare0"
bd5b4116 1130 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1131 (compare:CC_NOOV
1132 (plus:SI (mult:SI
1133 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1134 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1135 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1136 (const_int 0)))
9c08d1fa 1137 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1138 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1139 (match_dup 3)))]
e8a4aa75 1140 "TARGET_ARM"
40dbec34 1141 "mla%?s\\t%0, %2, %1, %3"
0d66636f 1142 [(set_attr "conds" "set")
a2cd141b 1143 (set_attr "insn" "mlas")]
0d66636f 1144)
9c08d1fa 1145
f7fbdd4a 1146(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1147 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1148 (compare:CC_NOOV
1149 (plus:SI (mult:SI
1150 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1151 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1152 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1153 (const_int 0)))
9c08d1fa 1154 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
e8a4aa75 1155 "TARGET_ARM"
40dbec34 1156 "mla%?s\\t%0, %2, %1, %3"
cffb2a26 1157 [(set_attr "conds" "set")
a2cd141b 1158 (set_attr "insn" "mlas")]
cffb2a26 1159)
f7fbdd4a 1160
efee20da 1161;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1162
1163(define_insn "*mulsidi3adddi"
fe8dbf85 1164 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1165 (plus:DI
215b30b3 1166 (mult:DI
fe8dbf85 1167 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1168 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1169 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1170 "TARGET_ARM && arm_arch3m"
fe8dbf85 1171 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1172 [(set_attr "insn" "smlal")
0d66636f 1173 (set_attr "predicable" "yes")]
1174)
82b85d08 1175
f7fbdd4a 1176(define_insn "mulsidi3"
1177 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1178 (mult:DI
1179 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1180 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1181 "TARGET_ARM && arm_arch3m"
97499065 1182 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1183 [(set_attr "insn" "smull")
0d66636f 1184 (set_attr "predicable" "yes")]
1185)
f7fbdd4a 1186
1187(define_insn "umulsidi3"
1188 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1189 (mult:DI
1190 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1191 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1192 "TARGET_ARM && arm_arch3m"
97499065 1193 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1194 [(set_attr "insn" "umull")
0d66636f 1195 (set_attr "predicable" "yes")]
1196)
b11cae9e 1197
efee20da 1198;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1199
1200(define_insn "*umulsidi3adddi"
8ead09f9 1201 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1202 (plus:DI
215b30b3 1203 (mult:DI
fe8dbf85 1204 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1205 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1206 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1207 "TARGET_ARM && arm_arch3m"
fe8dbf85 1208 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1209 [(set_attr "insn" "umlal")
0d66636f 1210 (set_attr "predicable" "yes")]
1211)
82b85d08 1212
f082f1c4 1213(define_insn "smulsi3_highpart"
1214 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1215 (truncate:SI
1216 (lshiftrt:DI
215b30b3 1217 (mult:DI
1218 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1219 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1220 (const_int 32))))
1221 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1222 "TARGET_ARM && arm_arch3m"
f082f1c4 1223 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1224 [(set_attr "insn" "smull")
0d66636f 1225 (set_attr "predicable" "yes")]
cffb2a26 1226)
f082f1c4 1227
1228(define_insn "umulsi3_highpart"
1229 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230 (truncate:SI
1231 (lshiftrt:DI
215b30b3 1232 (mult:DI
1233 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234 (zero_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 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1239 [(set_attr "insn" "umull")
0d66636f 1240 (set_attr "predicable" "yes")]
cffb2a26 1241)
f082f1c4 1242
331beb1a 1243(define_insn "mulhisi3"
1244 [(set (match_operand:SI 0 "s_register_operand" "=r")
1245 (mult:SI (sign_extend:SI
1246 (match_operand:HI 1 "s_register_operand" "%r"))
1247 (sign_extend:SI
1248 (match_operand:HI 2 "s_register_operand" "r"))))]
fec538d9 1249 "TARGET_ARM && arm_arch5e"
61a2d04c 1250 "smulbb%?\\t%0, %1, %2"
a2cd141b 1251 [(set_attr "insn" "smulxy")
fec538d9 1252 (set_attr "predicable" "yes")]
1253)
1254
1255(define_insn "*mulhisi3tb"
1256 [(set (match_operand:SI 0 "s_register_operand" "=r")
1257 (mult:SI (ashiftrt:SI
1258 (match_operand:SI 1 "s_register_operand" "r")
1259 (const_int 16))
1260 (sign_extend:SI
1261 (match_operand:HI 2 "s_register_operand" "r"))))]
1262 "TARGET_ARM && arm_arch5e"
1263 "smultb%?\\t%0, %1, %2"
a2cd141b 1264 [(set_attr "insn" "smulxy")
fec538d9 1265 (set_attr "predicable" "yes")]
1266)
1267
1268(define_insn "*mulhisi3bt"
1269 [(set (match_operand:SI 0 "s_register_operand" "=r")
1270 (mult:SI (sign_extend:SI
1271 (match_operand:HI 1 "s_register_operand" "r"))
1272 (ashiftrt:SI
1273 (match_operand:SI 2 "s_register_operand" "r")
1274 (const_int 16))))]
1275 "TARGET_ARM && arm_arch5e"
1276 "smulbt%?\\t%0, %1, %2"
a2cd141b 1277 [(set_attr "insn" "smulxy")
fec538d9 1278 (set_attr "predicable" "yes")]
1279)
1280
1281(define_insn "*mulhisi3tt"
1282 [(set (match_operand:SI 0 "s_register_operand" "=r")
1283 (mult:SI (ashiftrt:SI
1284 (match_operand:SI 1 "s_register_operand" "r")
1285 (const_int 16))
1286 (ashiftrt:SI
1287 (match_operand:SI 2 "s_register_operand" "r")
1288 (const_int 16))))]
1289 "TARGET_ARM && arm_arch5e"
1290 "smultt%?\\t%0, %1, %2"
a2cd141b 1291 [(set_attr "insn" "smulxy")
fec538d9 1292 (set_attr "predicable" "yes")]
331beb1a 1293)
1294
1295(define_insn "*mulhisi3addsi"
1296 [(set (match_operand:SI 0 "s_register_operand" "=r")
1297 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1298 (mult:SI (sign_extend:SI
1299 (match_operand:HI 2 "s_register_operand" "%r"))
1300 (sign_extend:SI
1301 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1302 "TARGET_ARM && arm_arch5e"
61a2d04c 1303 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1304 [(set_attr "insn" "smlaxy")
fec538d9 1305 (set_attr "predicable" "yes")]
331beb1a 1306)
1307
1308(define_insn "*mulhidi3adddi"
1309 [(set (match_operand:DI 0 "s_register_operand" "=r")
1310 (plus:DI
1311 (match_operand:DI 1 "s_register_operand" "0")
1312 (mult:DI (sign_extend:DI
1313 (match_operand:HI 2 "s_register_operand" "%r"))
1314 (sign_extend:DI
1315 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1316 "TARGET_ARM && arm_arch5e"
331beb1a 1317 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1318 [(set_attr "insn" "smlalxy")
fec538d9 1319 (set_attr "predicable" "yes")])
331beb1a 1320
604f3a0a 1321(define_expand "mulsf3"
1322 [(set (match_operand:SF 0 "s_register_operand" "")
1323 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1324 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1325 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1326 "
a2cd141b 1327 if (TARGET_MAVERICK
604f3a0a 1328 && !cirrus_fp_register (operands[2], SFmode))
1329 operands[2] = force_reg (SFmode, operands[2]);
1330")
1331
604f3a0a 1332(define_expand "muldf3"
1333 [(set (match_operand:DF 0 "s_register_operand" "")
1334 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1335 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1336 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1337 "
a2cd141b 1338 if (TARGET_MAVERICK
604f3a0a 1339 && !cirrus_fp_register (operands[2], DFmode))
1340 operands[2] = force_reg (DFmode, operands[2]);
1341")
b11cae9e 1342\f
1343;; Division insns
1344
7db9af5d 1345(define_expand "divsf3"
1346 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1347 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1348 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1349 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1350 "")
9c08d1fa 1351
7db9af5d 1352(define_expand "divdf3"
1353 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1354 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1355 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1356 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1357 "")
b11cae9e 1358\f
1359;; Modulo insns
1360
7db9af5d 1361(define_expand "modsf3"
1362 [(set (match_operand:SF 0 "s_register_operand" "")
1363 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1364 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1365 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1366 "")
9c08d1fa 1367
7db9af5d 1368(define_expand "moddf3"
1369 [(set (match_operand:DF 0 "s_register_operand" "")
1370 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1371 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1372 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1373 "")
b11cae9e 1374\f
1375;; Boolean and,ior,xor insns
1376
f6ebffac 1377;; Split up double word logical operations
1378
1379;; Split up simple DImode logical operations. Simply perform the logical
1380;; operation on the upper and lower halves of the registers.
1381(define_split
1382 [(set (match_operand:DI 0 "s_register_operand" "")
1383 (match_operator:DI 6 "logical_binary_operator"
1384 [(match_operand:DI 1 "s_register_operand" "")
1385 (match_operand:DI 2 "s_register_operand" "")]))]
755eb2b4 1386 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1387 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1388 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1389 "
215b30b3 1390 {
1391 operands[3] = gen_highpart (SImode, operands[0]);
1392 operands[0] = gen_lowpart (SImode, operands[0]);
1393 operands[4] = gen_highpart (SImode, operands[1]);
1394 operands[1] = gen_lowpart (SImode, operands[1]);
1395 operands[5] = gen_highpart (SImode, operands[2]);
1396 operands[2] = gen_lowpart (SImode, operands[2]);
1397 }"
1398)
f6ebffac 1399
f6ebffac 1400(define_split
1401 [(set (match_operand:DI 0 "s_register_operand" "")
1402 (match_operator:DI 6 "logical_binary_operator"
1403 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1404 (match_operand:DI 1 "s_register_operand" "")]))]
cffb2a26 1405 "TARGET_ARM && reload_completed"
f6ebffac 1406 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1407 (set (match_dup 3) (match_op_dup:SI 6
1408 [(ashiftrt:SI (match_dup 2) (const_int 31))
1409 (match_dup 4)]))]
1410 "
215b30b3 1411 {
1412 operands[3] = gen_highpart (SImode, operands[0]);
1413 operands[0] = gen_lowpart (SImode, operands[0]);
1414 operands[4] = gen_highpart (SImode, operands[1]);
1415 operands[1] = gen_lowpart (SImode, operands[1]);
1416 operands[5] = gen_highpart (SImode, operands[2]);
1417 operands[2] = gen_lowpart (SImode, operands[2]);
1418 }"
1419)
f6ebffac 1420
f6ebffac 1421;; The zero extend of operand 2 means we can just copy the high part of
1422;; operand1 into operand0.
1423(define_split
1424 [(set (match_operand:DI 0 "s_register_operand" "")
1425 (ior:DI
1426 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1427 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1428 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1429 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1430 (set (match_dup 3) (match_dup 4))]
1431 "
215b30b3 1432 {
1433 operands[4] = gen_highpart (SImode, operands[1]);
1434 operands[3] = gen_highpart (SImode, operands[0]);
1435 operands[0] = gen_lowpart (SImode, operands[0]);
1436 operands[1] = gen_lowpart (SImode, operands[1]);
1437 }"
1438)
f6ebffac 1439
1440;; The zero extend of operand 2 means we can just copy the high part of
1441;; operand1 into operand0.
1442(define_split
1443 [(set (match_operand:DI 0 "s_register_operand" "")
1444 (xor:DI
1445 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1446 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1447 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1448 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1449 (set (match_dup 3) (match_dup 4))]
1450 "
215b30b3 1451 {
1452 operands[4] = gen_highpart (SImode, operands[1]);
1453 operands[3] = gen_highpart (SImode, operands[0]);
1454 operands[0] = gen_lowpart (SImode, operands[0]);
1455 operands[1] = gen_lowpart (SImode, operands[1]);
1456 }"
1457)
f6ebffac 1458
b11cae9e 1459(define_insn "anddi3"
cffb2a26 1460 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1461 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1462 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 1463 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 1464 "#"
215b30b3 1465 [(set_attr "length" "8")]
1466)
b11cae9e 1467
a0f94409 1468(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1469 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1470 (and:DI (zero_extend:DI
1471 (match_operand:SI 2 "s_register_operand" "r,r"))
1472 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 1473 "TARGET_ARM"
f6ebffac 1474 "#"
a0f94409 1475 "TARGET_ARM && reload_completed"
1476 ; The zero extend of operand 2 clears the high word of the output
1477 ; operand.
1478 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1479 (set (match_dup 3) (const_int 0))]
1480 "
1481 {
1482 operands[3] = gen_highpart (SImode, operands[0]);
1483 operands[0] = gen_lowpart (SImode, operands[0]);
1484 operands[1] = gen_lowpart (SImode, operands[1]);
1485 }"
215b30b3 1486 [(set_attr "length" "8")]
1487)
b11cae9e 1488
f7fbdd4a 1489(define_insn "*anddi_sesdi_di"
cffb2a26 1490 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1491 (and:DI (sign_extend:DI
1492 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1493 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1494 "TARGET_ARM"
f6ebffac 1495 "#"
cffb2a26 1496 [(set_attr "length" "8")]
1497)
b11cae9e 1498
87b22bf7 1499(define_expand "andsi3"
cffb2a26 1500 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1501 (and:SI (match_operand:SI 1 "s_register_operand" "")
1502 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1503 "TARGET_EITHER"
87b22bf7 1504 "
cffb2a26 1505 if (TARGET_ARM)
87b22bf7 1506 {
cffb2a26 1507 if (GET_CODE (operands[2]) == CONST_INT)
1508 {
96f57e36 1509 arm_split_constant (AND, SImode, NULL_RTX,
1510 INTVAL (operands[2]), operands[0],
615caa51 1511 operands[1], optimize && !no_new_pseudos);
1512
cffb2a26 1513 DONE;
1514 }
87b22bf7 1515 }
cffb2a26 1516 else /* TARGET_THUMB */
1517 {
1518 if (GET_CODE (operands[2]) != CONST_INT)
1519 operands[2] = force_reg (SImode, operands[2]);
1520 else
1521 {
1522 int i;
1523
215b30b3 1524 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1525 {
215b30b3 1526 operands[2] = force_reg (SImode,
1527 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1528
1529 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1530
1531 DONE;
1532 }
87b22bf7 1533
cffb2a26 1534 for (i = 9; i <= 31; i++)
1535 {
1536 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1537 {
1538 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1539 const0_rtx));
1540 DONE;
1541 }
215b30b3 1542 else if ((((HOST_WIDE_INT) 1) << i) - 1
1543 == ~INTVAL (operands[2]))
cffb2a26 1544 {
1545 rtx shift = GEN_INT (i);
1546 rtx reg = gen_reg_rtx (SImode);
1547
1548 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1549 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1550
1551 DONE;
1552 }
1553 }
1554
1555 operands[2] = force_reg (SImode, operands[2]);
1556 }
215b30b3 1557 }
1558 "
cffb2a26 1559)
1560
a0f94409 1561(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1562 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1563 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1564 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
cffb2a26 1565 "TARGET_ARM"
5565501b 1566 "@
1567 and%?\\t%0, %1, %2
87b22bf7 1568 bic%?\\t%0, %1, #%B2
1569 #"
a0f94409 1570 "TARGET_ARM
1571 && GET_CODE (operands[2]) == CONST_INT
1572 && !(const_ok_for_arm (INTVAL (operands[2]))
1573 || const_ok_for_arm (~INTVAL (operands[2])))"
1574 [(clobber (const_int 0))]
1575 "
96f57e36 1576 arm_split_constant (AND, SImode, curr_insn,
1577 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1578 DONE;
1579 "
0d66636f 1580 [(set_attr "length" "4,4,16")
1581 (set_attr "predicable" "yes")]
cffb2a26 1582)
1583
1584(define_insn "*thumb_andsi3_insn"
1585 [(set (match_operand:SI 0 "register_operand" "=l")
1586 (and:SI (match_operand:SI 1 "register_operand" "%0")
1587 (match_operand:SI 2 "register_operand" "l")))]
1588 "TARGET_THUMB"
1589 "and\\t%0, %0, %2"
1590 [(set_attr "length" "2")]
1591)
87b22bf7 1592
f7fbdd4a 1593(define_insn "*andsi3_compare0"
bd5b4116 1594 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1595 (compare:CC_NOOV
1596 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1597 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1598 (const_int 0)))
cffb2a26 1599 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1600 (and:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1601 "TARGET_ARM"
5565501b 1602 "@
1603 and%?s\\t%0, %1, %2
1604 bic%?s\\t%0, %1, #%B2"
cffb2a26 1605 [(set_attr "conds" "set")]
1606)
9c08d1fa 1607
f7fbdd4a 1608(define_insn "*andsi3_compare0_scratch"
bd5b4116 1609 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1610 (compare:CC_NOOV
1611 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1612 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1613 (const_int 0)))
dd193d7c 1614 (clobber (match_scratch:SI 2 "=X,r"))]
cffb2a26 1615 "TARGET_ARM"
5565501b 1616 "@
1617 tst%?\\t%0, %1
dd193d7c 1618 bic%?s\\t%2, %0, #%B1"
0d66636f 1619 [(set_attr "conds" "set")]
1620)
9c08d1fa 1621
f7fbdd4a 1622(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 1623 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1624 (compare:CC_NOOV (zero_extract:SI
1625 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 1626 (match_operand 1 "const_int_operand" "n")
1627 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 1628 (const_int 0)))]
cffb2a26 1629 "TARGET_ARM
1630 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1631 && INTVAL (operands[1]) > 0
1632 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1633 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 1634 "*
5c49a439 1635 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1636 << INTVAL (operands[2]));
40dbec34 1637 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 1638 return \"\";
0d66636f 1639 "
1640 [(set_attr "conds" "set")]
1641)
9c08d1fa 1642
f4462328 1643(define_insn_and_split "*ne_zeroextractsi"
c4034607 1644 [(set (match_operand:SI 0 "s_register_operand" "=r")
1645 (ne:SI (zero_extract:SI
1646 (match_operand:SI 1 "s_register_operand" "r")
1647 (match_operand:SI 2 "const_int_operand" "n")
1648 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 1649 (const_int 0)))
1650 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1651 "TARGET_ARM
1652 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1653 && INTVAL (operands[2]) > 0
1654 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1655 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 1656 "#"
1657 "TARGET_ARM
1658 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1659 && INTVAL (operands[2]) > 0
1660 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1661 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1662 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1663 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1664 (const_int 0)))
1665 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1666 (set (match_dup 0)
1667 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1668 (match_dup 0) (const_int 1)))]
1669 "
1670 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1671 << INTVAL (operands[3]));
1672 "
1673 [(set_attr "conds" "clob")
1674 (set_attr "length" "8")]
1675)
1676
1677(define_insn_and_split "*ne_zeroextractsi_shifted"
1678 [(set (match_operand:SI 0 "s_register_operand" "=r")
1679 (ne:SI (zero_extract:SI
1680 (match_operand:SI 1 "s_register_operand" "r")
1681 (match_operand:SI 2 "const_int_operand" "n")
1682 (const_int 0))
1683 (const_int 0)))
1684 (clobber (reg:CC CC_REGNUM))]
1685 "TARGET_ARM"
1686 "#"
1687 "TARGET_ARM"
1688 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1689 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1690 (const_int 0)))
1691 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1692 (set (match_dup 0)
1693 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1694 (match_dup 0) (const_int 1)))]
1695 "
1696 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1697 "
1698 [(set_attr "conds" "clob")
1699 (set_attr "length" "8")]
1700)
1701
1702(define_insn_and_split "*ite_ne_zeroextractsi"
1703 [(set (match_operand:SI 0 "s_register_operand" "=r")
1704 (if_then_else:SI (ne (zero_extract:SI
1705 (match_operand:SI 1 "s_register_operand" "r")
1706 (match_operand:SI 2 "const_int_operand" "n")
1707 (match_operand:SI 3 "const_int_operand" "n"))
1708 (const_int 0))
1709 (match_operand:SI 4 "arm_not_operand" "rIK")
1710 (const_int 0)))
1711 (clobber (reg:CC CC_REGNUM))]
1712 "TARGET_ARM
1713 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1714 && INTVAL (operands[2]) > 0
1715 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1716 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1717 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1718 "#"
1719 "TARGET_ARM
1720 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1721 && INTVAL (operands[2]) > 0
1722 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1723 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1724 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1725 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1726 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1727 (const_int 0)))
1728 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1729 (set (match_dup 0)
1730 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1731 (match_dup 0) (match_dup 4)))]
1732 "
c4034607 1733 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 1734 << INTVAL (operands[3]));
1735 "
1736 [(set_attr "conds" "clob")
1737 (set_attr "length" "8")]
1738)
1739
1740(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1741 [(set (match_operand:SI 0 "s_register_operand" "=r")
1742 (if_then_else:SI (ne (zero_extract:SI
1743 (match_operand:SI 1 "s_register_operand" "r")
1744 (match_operand:SI 2 "const_int_operand" "n")
1745 (const_int 0))
1746 (const_int 0))
1747 (match_operand:SI 3 "arm_not_operand" "rIK")
1748 (const_int 0)))
1749 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 1750 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1751 "#"
f8d7bf2f 1752 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1753 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1754 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1755 (const_int 0)))
1756 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1757 (set (match_dup 0)
1758 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1759 (match_dup 0) (match_dup 3)))]
1760 "
1761 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 1762 "
1763 [(set_attr "conds" "clob")
215b30b3 1764 (set_attr "length" "8")]
1765)
9c08d1fa 1766
58d6528b 1767(define_split
1768 [(set (match_operand:SI 0 "s_register_operand" "")
1769 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1770 (match_operand:SI 2 "const_int_operand" "")
1771 (match_operand:SI 3 "const_int_operand" "")))
1772 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1773 "TARGET_THUMB"
1774 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1775 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1776 "{
1777 HOST_WIDE_INT temp = INTVAL (operands[2]);
1778
1779 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1780 operands[3] = GEN_INT (32 - temp);
1781 }"
1782)
1783
d7863cfe 1784(define_split
1785 [(set (match_operand:SI 0 "s_register_operand" "")
1786 (match_operator:SI 1 "shiftable_operator"
1787 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1788 (match_operand:SI 3 "const_int_operand" "")
1789 (match_operand:SI 4 "const_int_operand" ""))
1790 (match_operand:SI 5 "s_register_operand" "")]))
1791 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1792 "TARGET_ARM"
1793 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1794 (set (match_dup 0)
1795 (match_op_dup 1
1796 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1797 (match_dup 5)]))]
1798 "{
1799 HOST_WIDE_INT temp = INTVAL (operands[3]);
1800
1801 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1802 operands[4] = GEN_INT (32 - temp);
1803 }"
1804)
1805
58d6528b 1806(define_split
1807 [(set (match_operand:SI 0 "s_register_operand" "")
1808 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1809 (match_operand:SI 2 "const_int_operand" "")
1810 (match_operand:SI 3 "const_int_operand" "")))]
1811 "TARGET_THUMB"
1812 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1813 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1814 "{
1815 HOST_WIDE_INT temp = INTVAL (operands[2]);
1816
1817 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1818 operands[3] = GEN_INT (32 - temp);
1819 }"
1820)
1821
d7863cfe 1822(define_split
1823 [(set (match_operand:SI 0 "s_register_operand" "")
1824 (match_operator:SI 1 "shiftable_operator"
1825 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1826 (match_operand:SI 3 "const_int_operand" "")
1827 (match_operand:SI 4 "const_int_operand" ""))
1828 (match_operand:SI 5 "s_register_operand" "")]))
1829 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1830 "TARGET_ARM"
1831 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1832 (set (match_dup 0)
1833 (match_op_dup 1
1834 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1835 (match_dup 5)]))]
1836 "{
1837 HOST_WIDE_INT temp = INTVAL (operands[3]);
1838
1839 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1840 operands[4] = GEN_INT (32 - temp);
1841 }"
1842)
1843
a42059fd 1844;;; ??? This pattern is bogus. If operand3 has bits outside the range
1845;;; represented by the bitfield, then this will produce incorrect results.
1846;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 1847;;; which have a real bit-field insert instruction, the truncation happens
1848;;; in the bit-field insert instruction itself. Since arm does not have a
1849;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 1850;;; the value before we insert. This loses some of the advantage of having
1851;;; this insv pattern, so this pattern needs to be reevalutated.
1852
8a18b90c 1853(define_expand "insv"
1854 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1855 (match_operand:SI 1 "general_operand" "")
1856 (match_operand:SI 2 "general_operand" ""))
19335226 1857 (match_operand:SI 3 "reg_or_int_operand" ""))]
cffb2a26 1858 "TARGET_ARM"
8a18b90c 1859 "
215b30b3 1860 {
1861 int start_bit = INTVAL (operands[2]);
1862 int width = INTVAL (operands[1]);
1863 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1864 rtx target, subtarget;
1865
1866 target = operands[0];
1867 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1868 subreg as the final target. */
1869 if (GET_CODE (target) == SUBREG)
1870 {
1871 subtarget = gen_reg_rtx (SImode);
1872 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1873 < GET_MODE_SIZE (SImode))
1874 target = SUBREG_REG (target);
1875 }
1876 else
1877 subtarget = target;
8a18b90c 1878
215b30b3 1879 if (GET_CODE (operands[3]) == CONST_INT)
1880 {
1881 /* Since we are inserting a known constant, we may be able to
1882 reduce the number of bits that we have to clear so that
1883 the mask becomes simple. */
1884 /* ??? This code does not check to see if the new mask is actually
1885 simpler. It may not be. */
1886 rtx op1 = gen_reg_rtx (SImode);
1887 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1888 start of this pattern. */
1889 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1890 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1891
1892 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1893 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 1894 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 1895 }
1896 else if (start_bit == 0
1897 && !(const_ok_for_arm (mask)
1898 || const_ok_for_arm (~mask)))
1899 {
1900 /* A Trick, since we are setting the bottom bits in the word,
1901 we can shift operand[3] up, operand[0] down, OR them together
1902 and rotate the result back again. This takes 3 insns, and
5910bb95 1903 the third might be mergeable into another op. */
215b30b3 1904 /* The shift up copes with the possibility that operand[3] is
1905 wider than the bitfield. */
1906 rtx op0 = gen_reg_rtx (SImode);
1907 rtx op1 = gen_reg_rtx (SImode);
1908
1909 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1910 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1911 emit_insn (gen_iorsi3 (op1, op1, op0));
1912 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1913 }
1914 else if ((width + start_bit == 32)
1915 && !(const_ok_for_arm (mask)
1916 || const_ok_for_arm (~mask)))
1917 {
1918 /* Similar trick, but slightly less efficient. */
8a18b90c 1919
215b30b3 1920 rtx op0 = gen_reg_rtx (SImode);
1921 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 1922
215b30b3 1923 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1924 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1925 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1926 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1927 }
1928 else
1929 {
1930 rtx op0 = GEN_INT (mask);
1931 rtx op1 = gen_reg_rtx (SImode);
1932 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 1933
215b30b3 1934 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1935 {
1936 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1937
215b30b3 1938 emit_insn (gen_movsi (tmp, op0));
1939 op0 = tmp;
1940 }
8a18b90c 1941
215b30b3 1942 /* Mask out any bits in operand[3] that are not needed. */
1943 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 1944
215b30b3 1945 if (GET_CODE (op0) == CONST_INT
1946 && (const_ok_for_arm (mask << start_bit)
1947 || const_ok_for_arm (~(mask << start_bit))))
1948 {
1949 op0 = GEN_INT (~(mask << start_bit));
1950 emit_insn (gen_andsi3 (op2, operands[0], op0));
1951 }
1952 else
1953 {
1954 if (GET_CODE (op0) == CONST_INT)
1955 {
1956 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1957
215b30b3 1958 emit_insn (gen_movsi (tmp, op0));
1959 op0 = tmp;
1960 }
1961
1962 if (start_bit != 0)
1963 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 1964
215b30b3 1965 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1966 }
8a18b90c 1967
215b30b3 1968 if (start_bit != 0)
1969 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 1970
215b30b3 1971 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1972 }
f082f1c4 1973
215b30b3 1974 if (subtarget != target)
1975 {
1976 /* If TARGET is still a SUBREG, then it must be wider than a word,
1977 so we must be careful only to set the subword we were asked to. */
1978 if (GET_CODE (target) == SUBREG)
1979 emit_move_insn (target, subtarget);
1980 else
1981 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1982 }
8a18b90c 1983
215b30b3 1984 DONE;
1985 }"
1986)
8a18b90c 1987
215b30b3 1988; constants for op 2 will never be given to these patterns.
a0f94409 1989(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 1990 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 1991 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1992 (match_operand:DI 2 "s_register_operand" "0,r")))]
cffb2a26 1993 "TARGET_ARM"
f6ebffac 1994 "#"
755eb2b4 1995 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 1996 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1997 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1998 "
1999 {
2000 operands[3] = gen_highpart (SImode, operands[0]);
2001 operands[0] = gen_lowpart (SImode, operands[0]);
2002 operands[4] = gen_highpart (SImode, operands[1]);
2003 operands[1] = gen_lowpart (SImode, operands[1]);
2004 operands[5] = gen_highpart (SImode, operands[2]);
2005 operands[2] = gen_lowpart (SImode, operands[2]);
2006 }"
0d66636f 2007 [(set_attr "length" "8")
2008 (set_attr "predicable" "yes")]
2009)
9c08d1fa 2010
a0f94409 2011(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2012 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2013 (and:DI (not:DI (zero_extend:DI
2014 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2015 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2016 "TARGET_ARM"
e2348bcb 2017 "@
97499065 2018 bic%?\\t%Q0, %Q1, %2
f6ebffac 2019 #"
a0f94409 2020 ; (not (zero_extend ...)) allows us to just copy the high word from
2021 ; operand1 to operand0.
2022 "TARGET_ARM
2023 && reload_completed
2024 && operands[0] != operands[1]"
5a097f7d 2025 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2026 (set (match_dup 3) (match_dup 4))]
2027 "
2028 {
2029 operands[3] = gen_highpart (SImode, operands[0]);
2030 operands[0] = gen_lowpart (SImode, operands[0]);
2031 operands[4] = gen_highpart (SImode, operands[1]);
2032 operands[1] = gen_lowpart (SImode, operands[1]);
2033 }"
0d66636f 2034 [(set_attr "length" "4,8")
2035 (set_attr "predicable" "yes")]
2036)
9c08d1fa 2037
a0f94409 2038(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2039 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2040 (and:DI (not:DI (sign_extend:DI
2041 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2042 (match_operand:DI 1 "s_register_operand" "0,r")))]
cffb2a26 2043 "TARGET_ARM"
f6ebffac 2044 "#"
a0f94409 2045 "TARGET_ARM && reload_completed"
5a097f7d 2046 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2047 (set (match_dup 3) (and:SI (not:SI
2048 (ashiftrt:SI (match_dup 2) (const_int 31)))
2049 (match_dup 4)))]
2050 "
2051 {
2052 operands[3] = gen_highpart (SImode, operands[0]);
2053 operands[0] = gen_lowpart (SImode, operands[0]);
2054 operands[4] = gen_highpart (SImode, operands[1]);
2055 operands[1] = gen_lowpart (SImode, operands[1]);
2056 }"
0d66636f 2057 [(set_attr "length" "8")
2058 (set_attr "predicable" "yes")]
2059)
9c08d1fa 2060
8a18b90c 2061(define_insn "andsi_notsi_si"
9c08d1fa 2062 [(set (match_operand:SI 0 "s_register_operand" "=r")
2063 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2064 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2065 "TARGET_ARM"
0d66636f 2066 "bic%?\\t%0, %1, %2"
2067 [(set_attr "predicable" "yes")]
2068)
b11cae9e 2069
cffb2a26 2070(define_insn "bicsi3"
2071 [(set (match_operand:SI 0 "register_operand" "=l")
2072 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2073 (match_operand:SI 2 "register_operand" "0")))]
2074 "TARGET_THUMB"
2075 "bic\\t%0, %0, %1"
2076 [(set_attr "length" "2")]
2077)
2078
8a18b90c 2079(define_insn "andsi_not_shiftsi_si"
a2cd141b 2080 [(set (match_operand:SI 0 "s_register_operand" "=r")
2081 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2082 [(match_operand:SI 2 "s_register_operand" "r")
2083 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2084 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2085 "TARGET_ARM"
6c4c2133 2086 "bic%?\\t%0, %1, %2%S4"
344495ea 2087 [(set_attr "predicable" "yes")
331beb1a 2088 (set_attr "shift" "2")
a2cd141b 2089 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2090 (const_string "alu_shift")
2091 (const_string "alu_shift_reg")))]
6c4c2133 2092)
8a18b90c 2093
f7fbdd4a 2094(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2095 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2096 (compare:CC_NOOV
2097 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2098 (match_operand:SI 1 "s_register_operand" "r"))
2099 (const_int 0)))
9c08d1fa 2100 (set (match_operand:SI 0 "s_register_operand" "=r")
2101 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
cffb2a26 2102 "TARGET_ARM"
40dbec34 2103 "bic%?s\\t%0, %1, %2"
0d66636f 2104 [(set_attr "conds" "set")]
2105)
9c08d1fa 2106
f7fbdd4a 2107(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2108 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2109 (compare:CC_NOOV
2110 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2111 (match_operand:SI 1 "s_register_operand" "r"))
2112 (const_int 0)))
9c08d1fa 2113 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2114 "TARGET_ARM"
40dbec34 2115 "bic%?s\\t%0, %1, %2"
0d66636f 2116 [(set_attr "conds" "set")]
2117)
9c08d1fa 2118
2119(define_insn "iordi3"
cffb2a26 2120 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2121 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2122 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2123 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 2124 "#"
0d66636f 2125 [(set_attr "length" "8")
2126 (set_attr "predicable" "yes")]
cffb2a26 2127)
9c08d1fa 2128
f7fbdd4a 2129(define_insn "*iordi_zesidi_di"
9c08d1fa 2130 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2131 (ior:DI (zero_extend:DI
2132 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2133 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2134 "TARGET_ARM"
e2348bcb 2135 "@
97499065 2136 orr%?\\t%Q0, %Q1, %2
f6ebffac 2137 #"
0d66636f 2138 [(set_attr "length" "4,8")
2139 (set_attr "predicable" "yes")]
cffb2a26 2140)
9c08d1fa 2141
f7fbdd4a 2142(define_insn "*iordi_sesidi_di"
9c08d1fa 2143 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2144 (ior:DI (sign_extend:DI
2145 (match_operand:SI 2 "s_register_operand" "r,r"))
2146 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2147 "TARGET_ARM"
f6ebffac 2148 "#"
0d66636f 2149 [(set_attr "length" "8")
2150 (set_attr "predicable" "yes")]
cffb2a26 2151)
9c08d1fa 2152
87b22bf7 2153(define_expand "iorsi3"
cffb2a26 2154 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2155 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2156 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2157 "TARGET_EITHER"
87b22bf7 2158 "
2159 if (GET_CODE (operands[2]) == CONST_INT)
2160 {
cffb2a26 2161 if (TARGET_ARM)
2162 {
96f57e36 2163 arm_split_constant (IOR, SImode, NULL_RTX,
2164 INTVAL (operands[2]), operands[0], operands[1],
615caa51 2165 optimize && !no_new_pseudos);
cffb2a26 2166 DONE;
2167 }
2168 else /* TARGET_THUMB */
2169 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2170 }
cffb2a26 2171 "
2172)
87b22bf7 2173
a0f94409 2174(define_insn_and_split "*arm_iorsi3"
cffb2a26 2175 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2176 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2177 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
cffb2a26 2178 "TARGET_ARM"
87b22bf7 2179 "@
2180 orr%?\\t%0, %1, %2
2181 #"
a0f94409 2182 "TARGET_ARM
2183 && GET_CODE (operands[2]) == CONST_INT
2184 && !const_ok_for_arm (INTVAL (operands[2]))"
2185 [(clobber (const_int 0))]
2186 "
96f57e36 2187 arm_split_constant (IOR, SImode, curr_insn,
2188 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2189 DONE;
2190 "
0d66636f 2191 [(set_attr "length" "4,16")
2192 (set_attr "predicable" "yes")]
cffb2a26 2193)
2194
2195(define_insn "*thumb_iorsi3"
2196 [(set (match_operand:SI 0 "register_operand" "=l")
2197 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2198 (match_operand:SI 2 "register_operand" "l")))]
2199 "TARGET_THUMB"
2200 "orr\\t%0, %0, %2"
2201 [(set_attr "length" "2")]
2202)
9c08d1fa 2203
a0f94409 2204(define_peephole2
2205 [(match_scratch:SI 3 "r")
372575c7 2206 (set (match_operand:SI 0 "arm_general_register_operand" "")
2207 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2208 (match_operand:SI 2 "const_int_operand" "")))]
a0f94409 2209 "TARGET_ARM
2210 && !const_ok_for_arm (INTVAL (operands[2]))
2211 && const_ok_for_arm (~INTVAL (operands[2]))"
2212 [(set (match_dup 3) (match_dup 2))
2213 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2214 ""
215b30b3 2215)
a0f94409 2216
f7fbdd4a 2217(define_insn "*iorsi3_compare0"
bd5b4116 2218 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2219 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2220 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2221 (const_int 0)))
2222 (set (match_operand:SI 0 "s_register_operand" "=r")
2223 (ior:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2224 "TARGET_ARM"
40dbec34 2225 "orr%?s\\t%0, %1, %2"
cffb2a26 2226 [(set_attr "conds" "set")]
2227)
9c08d1fa 2228
f7fbdd4a 2229(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2230 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2231 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233 (const_int 0)))
2234 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2235 "TARGET_ARM"
40dbec34 2236 "orr%?s\\t%0, %1, %2"
0d66636f 2237 [(set_attr "conds" "set")]
2238)
9c08d1fa 2239
2240(define_insn "xordi3"
cffb2a26 2241 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2242 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2243 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2244 "TARGET_ARM && !TARGET_IWMMXT"
f6ebffac 2245 "#"
0d66636f 2246 [(set_attr "length" "8")
2247 (set_attr "predicable" "yes")]
cffb2a26 2248)
9c08d1fa 2249
f7fbdd4a 2250(define_insn "*xordi_zesidi_di"
9c08d1fa 2251 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2252 (xor:DI (zero_extend:DI
2253 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2254 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2255 "TARGET_ARM"
e2348bcb 2256 "@
97499065 2257 eor%?\\t%Q0, %Q1, %2
f6ebffac 2258 #"
0d66636f 2259 [(set_attr "length" "4,8")
2260 (set_attr "predicable" "yes")]
cffb2a26 2261)
9c08d1fa 2262
f7fbdd4a 2263(define_insn "*xordi_sesidi_di"
9c08d1fa 2264 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2265 (xor:DI (sign_extend:DI
2266 (match_operand:SI 2 "s_register_operand" "r,r"))
2267 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2268 "TARGET_ARM"
f6ebffac 2269 "#"
0d66636f 2270 [(set_attr "length" "8")
2271 (set_attr "predicable" "yes")]
cffb2a26 2272)
9c08d1fa 2273
cffb2a26 2274(define_expand "xorsi3"
2275 [(set (match_operand:SI 0 "s_register_operand" "")
2276 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2277 (match_operand:SI 2 "arm_rhs_operand" "")))]
2278 "TARGET_EITHER"
2279 "if (TARGET_THUMB)
2280 if (GET_CODE (operands[2]) == CONST_INT)
2281 operands[2] = force_reg (SImode, operands[2]);
2282 "
2283)
2284
2285(define_insn "*arm_xorsi3"
2286 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2287 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2288 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 2289 "TARGET_ARM"
2290 "eor%?\\t%0, %1, %2"
0d66636f 2291 [(set_attr "predicable" "yes")]
cffb2a26 2292)
2293
2294(define_insn "*thumb_xorsi3"
2295 [(set (match_operand:SI 0 "register_operand" "=l")
2296 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2297 (match_operand:SI 2 "register_operand" "l")))]
2298 "TARGET_THUMB"
2299 "eor\\t%0, %0, %2"
2300 [(set_attr "length" "2")]
2301)
9c08d1fa 2302
f7fbdd4a 2303(define_insn "*xorsi3_compare0"
bd5b4116 2304 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2305 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2306 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2307 (const_int 0)))
2308 (set (match_operand:SI 0 "s_register_operand" "=r")
2309 (xor:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2310 "TARGET_ARM"
40dbec34 2311 "eor%?s\\t%0, %1, %2"
0d66636f 2312 [(set_attr "conds" "set")]
2313)
9c08d1fa 2314
f7fbdd4a 2315(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2316 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2317 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2318 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2319 (const_int 0)))]
cffb2a26 2320 "TARGET_ARM"
40dbec34 2321 "teq%?\\t%0, %1"
cffb2a26 2322 [(set_attr "conds" "set")]
2323)
9c08d1fa 2324
215b30b3 2325; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2326; (NOT D) we can sometimes merge the final NOT into one of the following
2327; insns.
9c08d1fa 2328
2329(define_split
a058e94a 2330 [(set (match_operand:SI 0 "s_register_operand" "")
2331 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2332 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2333 (match_operand:SI 3 "arm_rhs_operand" "")))
2334 (clobber (match_operand:SI 4 "s_register_operand" ""))]
cffb2a26 2335 "TARGET_ARM"
9c08d1fa 2336 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2337 (not:SI (match_dup 3))))
2338 (set (match_dup 0) (not:SI (match_dup 4)))]
2339 ""
2340)
2341
f7fbdd4a 2342(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2343 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2344 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2345 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2346 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
cffb2a26 2347 "TARGET_ARM"
40dbec34 2348 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2349 [(set_attr "length" "8")
2350 (set_attr "predicable" "yes")]
cffb2a26 2351)
9c08d1fa 2352
d7863cfe 2353(define_split
2354 [(set (match_operand:SI 0 "s_register_operand" "")
2355 (match_operator:SI 1 "logical_binary_operator"
2356 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357 (match_operand:SI 3 "const_int_operand" "")
2358 (match_operand:SI 4 "const_int_operand" ""))
2359 (match_operator:SI 9 "logical_binary_operator"
2360 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2361 (match_operand:SI 6 "const_int_operand" ""))
2362 (match_operand:SI 7 "s_register_operand" "")])]))
2363 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2364 "TARGET_ARM
2365 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2366 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2367 [(set (match_dup 8)
2368 (match_op_dup 1
2369 [(ashift:SI (match_dup 2) (match_dup 4))
2370 (match_dup 5)]))
2371 (set (match_dup 0)
2372 (match_op_dup 1
2373 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2374 (match_dup 7)]))]
2375 "
2376 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2377")
2378
2379(define_split
2380 [(set (match_operand:SI 0 "s_register_operand" "")
2381 (match_operator:SI 1 "logical_binary_operator"
2382 [(match_operator:SI 9 "logical_binary_operator"
2383 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2384 (match_operand:SI 6 "const_int_operand" ""))
2385 (match_operand:SI 7 "s_register_operand" "")])
2386 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2387 (match_operand:SI 3 "const_int_operand" "")
2388 (match_operand:SI 4 "const_int_operand" ""))]))
2389 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2390 "TARGET_ARM
2391 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2392 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2393 [(set (match_dup 8)
2394 (match_op_dup 1
2395 [(ashift:SI (match_dup 2) (match_dup 4))
2396 (match_dup 5)]))
2397 (set (match_dup 0)
2398 (match_op_dup 1
2399 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2400 (match_dup 7)]))]
2401 "
2402 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2403")
2404
2405(define_split
2406 [(set (match_operand:SI 0 "s_register_operand" "")
2407 (match_operator:SI 1 "logical_binary_operator"
2408 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2409 (match_operand:SI 3 "const_int_operand" "")
2410 (match_operand:SI 4 "const_int_operand" ""))
2411 (match_operator:SI 9 "logical_binary_operator"
2412 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2413 (match_operand:SI 6 "const_int_operand" ""))
2414 (match_operand:SI 7 "s_register_operand" "")])]))
2415 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2416 "TARGET_ARM
2417 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2418 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2419 [(set (match_dup 8)
2420 (match_op_dup 1
2421 [(ashift:SI (match_dup 2) (match_dup 4))
2422 (match_dup 5)]))
2423 (set (match_dup 0)
2424 (match_op_dup 1
2425 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2426 (match_dup 7)]))]
2427 "
2428 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2429")
2430
2431(define_split
2432 [(set (match_operand:SI 0 "s_register_operand" "")
2433 (match_operator:SI 1 "logical_binary_operator"
2434 [(match_operator:SI 9 "logical_binary_operator"
2435 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2436 (match_operand:SI 6 "const_int_operand" ""))
2437 (match_operand:SI 7 "s_register_operand" "")])
2438 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2439 (match_operand:SI 3 "const_int_operand" "")
2440 (match_operand:SI 4 "const_int_operand" ""))]))
2441 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2442 "TARGET_ARM
2443 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2444 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2445 [(set (match_dup 8)
2446 (match_op_dup 1
2447 [(ashift:SI (match_dup 2) (match_dup 4))
2448 (match_dup 5)]))
2449 (set (match_dup 0)
2450 (match_op_dup 1
2451 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2452 (match_dup 7)]))]
2453 "
2454 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2455")
9c08d1fa 2456\f
2457
2458;; Minimum and maximum insns
2459
2460(define_insn "smaxsi3"
cffb2a26 2461 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2462 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2463 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2464 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2465 "TARGET_ARM"
e2348bcb 2466 "@
2467 cmp\\t%1, %2\;movlt\\t%0, %2
2468 cmp\\t%1, %2\;movge\\t%0, %1
2469 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2470 [(set_attr "conds" "clob")
2471 (set_attr "length" "8,8,12")]
2472)
9c08d1fa 2473
2474(define_insn "sminsi3"
2475 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2476 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2477 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2478 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2479 "TARGET_ARM"
e2348bcb 2480 "@
2481 cmp\\t%1, %2\;movge\\t%0, %2
2482 cmp\\t%1, %2\;movlt\\t%0, %1
2483 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 2484 [(set_attr "conds" "clob")
2485 (set_attr "length" "8,8,12")]
2486)
9c08d1fa 2487
2488(define_insn "umaxsi3"
2489 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2490 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2491 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2492 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2493 "TARGET_ARM"
e2348bcb 2494 "@
2495 cmp\\t%1, %2\;movcc\\t%0, %2
2496 cmp\\t%1, %2\;movcs\\t%0, %1
2497 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 2498 [(set_attr "conds" "clob")
2499 (set_attr "length" "8,8,12")]
2500)
9c08d1fa 2501
2502(define_insn "uminsi3"
2503 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2504 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2505 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2506 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2507 "TARGET_ARM"
e2348bcb 2508 "@
2509 cmp\\t%1, %2\;movcs\\t%0, %2
2510 cmp\\t%1, %2\;movcc\\t%0, %1
2511 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 2512 [(set_attr "conds" "clob")
2513 (set_attr "length" "8,8,12")]
2514)
9c08d1fa 2515
8a18b90c 2516(define_insn "*store_minmaxsi"
9c08d1fa 2517 [(set (match_operand:SI 0 "memory_operand" "=m")
2518 (match_operator:SI 3 "minmax_operator"
2519 [(match_operand:SI 1 "s_register_operand" "r")
2520 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 2521 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2522 "TARGET_ARM"
9c08d1fa 2523 "*
dc55b8a9 2524 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2525 operands[1], operands[2]);
e2348bcb 2526 output_asm_insn (\"cmp\\t%1, %2\", operands);
2527 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2528 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2529 return \"\";
0d66636f 2530 "
2531 [(set_attr "conds" "clob")
2532 (set_attr "length" "12")
2533 (set_attr "type" "store1")]
2534)
9c08d1fa 2535
8a18b90c 2536; Reject the frame pointer in operand[1], since reloading this after
2537; it has been eliminated can cause carnage.
f7fbdd4a 2538(define_insn "*minmax_arithsi"
9c08d1fa 2539 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2540 (match_operator:SI 4 "shiftable_operator"
2541 [(match_operator:SI 5 "minmax_operator"
2542 [(match_operand:SI 2 "s_register_operand" "r,r")
2543 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2544 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 2545 (clobber (reg:CC CC_REGNUM))]
da45ccee 2546 "TARGET_ARM && !arm_eliminable_register (operands[1])"
9c08d1fa 2547 "*
0d66636f 2548 {
2549 enum rtx_code code = GET_CODE (operands[4]);
2550
dc55b8a9 2551 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2552 operands[2], operands[3]);
0d66636f 2553 output_asm_insn (\"cmp\\t%2, %3\", operands);
2554 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2555 if (which_alternative != 0 || operands[3] != const0_rtx
2556 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2557 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2558 return \"\";
215b30b3 2559 }"
0d66636f 2560 [(set_attr "conds" "clob")
2561 (set_attr "length" "12")]
2562)
9c08d1fa 2563
b11cae9e 2564\f
2565;; Shift and rotation insns
2566
a2cd141b 2567(define_expand "ashldi3"
2568 [(set (match_operand:DI 0 "s_register_operand" "")
2569 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2570 (match_operand:SI 2 "reg_or_int_operand" "")))]
2571 "TARGET_ARM"
2572 "
2573 if (GET_CODE (operands[2]) == CONST_INT)
2574 {
2575 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2576 {
2577 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2578 DONE;
2579 }
2580 /* Ideally we shouldn't fail here if we could know that operands[1]
2581 ends up already living in an iwmmxt register. Otherwise it's
2582 cheaper to have the alternate code being generated than moving
1d60d981 2583 values to iwmmxt regs and back. */
a2cd141b 2584 FAIL;
2585 }
2586 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2587 FAIL;
2588 "
2589)
2590
2591(define_insn "arm_ashldi3_1bit"
2592 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2593 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2594 (const_int 1)))
2595 (clobber (reg:CC CC_REGNUM))]
2596 "TARGET_ARM"
2597 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2598 [(set_attr "conds" "clob")
2599 (set_attr "length" "8")]
2600)
2601
87b22bf7 2602(define_expand "ashlsi3"
cffb2a26 2603 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2604 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2605 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2606 "TARGET_EITHER"
87b22bf7 2607 "
2608 if (GET_CODE (operands[2]) == CONST_INT
2609 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2610 {
2611 emit_insn (gen_movsi (operands[0], const0_rtx));
2612 DONE;
2613 }
cffb2a26 2614 "
2615)
2616
2617(define_insn "*thumb_ashlsi3"
2618 [(set (match_operand:SI 0 "register_operand" "=l,l")
2619 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2620 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2621 "TARGET_THUMB"
2622 "lsl\\t%0, %1, %2"
2623 [(set_attr "length" "2")]
2624)
b11cae9e 2625
a2cd141b 2626(define_expand "ashrdi3"
2627 [(set (match_operand:DI 0 "s_register_operand" "")
2628 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2629 (match_operand:SI 2 "reg_or_int_operand" "")))]
2630 "TARGET_ARM"
2631 "
2632 if (GET_CODE (operands[2]) == CONST_INT)
2633 {
2634 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2635 {
2636 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2637 DONE;
2638 }
2639 /* Ideally we shouldn't fail here if we could know that operands[1]
2640 ends up already living in an iwmmxt register. Otherwise it's
2641 cheaper to have the alternate code being generated than moving
1d60d981 2642 values to iwmmxt regs and back. */
a2cd141b 2643 FAIL;
2644 }
2645 else if (!TARGET_REALLY_IWMMXT)
2646 FAIL;
2647 "
2648)
2649
2650(define_insn "arm_ashrdi3_1bit"
2651 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2652 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2653 (const_int 1)))
2654 (clobber (reg:CC CC_REGNUM))]
2655 "TARGET_ARM"
2656 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2657 [(set_attr "conds" "clob")
2658 (set_attr "length" "8")]
2659)
2660
87b22bf7 2661(define_expand "ashrsi3"
cffb2a26 2662 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2663 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2664 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2665 "TARGET_EITHER"
87b22bf7 2666 "
2667 if (GET_CODE (operands[2]) == CONST_INT
2668 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2669 operands[2] = GEN_INT (31);
cffb2a26 2670 "
2671)
2672
2673(define_insn "*thumb_ashrsi3"
2674 [(set (match_operand:SI 0 "register_operand" "=l,l")
2675 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2676 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2677 "TARGET_THUMB"
2678 "asr\\t%0, %1, %2"
2679 [(set_attr "length" "2")]
2680)
b11cae9e 2681
a2cd141b 2682(define_expand "lshrdi3"
2683 [(set (match_operand:DI 0 "s_register_operand" "")
2684 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2685 (match_operand:SI 2 "reg_or_int_operand" "")))]
2686 "TARGET_ARM"
2687 "
2688 if (GET_CODE (operands[2]) == CONST_INT)
2689 {
2690 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2691 {
2692 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2693 DONE;
2694 }
2695 /* Ideally we shouldn't fail here if we could know that operands[1]
2696 ends up already living in an iwmmxt register. Otherwise it's
2697 cheaper to have the alternate code being generated than moving
1d60d981 2698 values to iwmmxt regs and back. */
a2cd141b 2699 FAIL;
2700 }
2701 else if (!TARGET_REALLY_IWMMXT)
2702 FAIL;
2703 "
2704)
2705
2706(define_insn "arm_lshrdi3_1bit"
2707 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2708 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2709 (const_int 1)))
2710 (clobber (reg:CC CC_REGNUM))]
2711 "TARGET_ARM"
2712 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2713 [(set_attr "conds" "clob")
2714 (set_attr "length" "8")]
2715)
2716
87b22bf7 2717(define_expand "lshrsi3"
cffb2a26 2718 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2719 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2720 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2721 "TARGET_EITHER"
87b22bf7 2722 "
2723 if (GET_CODE (operands[2]) == CONST_INT
2724 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2725 {
2726 emit_insn (gen_movsi (operands[0], const0_rtx));
2727 DONE;
2728 }
cffb2a26 2729 "
2730)
2731
2732(define_insn "*thumb_lshrsi3"
2733 [(set (match_operand:SI 0 "register_operand" "=l,l")
2734 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2735 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2736 "TARGET_THUMB"
2737 "lsr\\t%0, %1, %2"
2738 [(set_attr "length" "2")]
2739)
b11cae9e 2740
87b22bf7 2741(define_expand "rotlsi3"
cffb2a26 2742 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2743 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2744 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2745 "TARGET_ARM"
87b22bf7 2746 "
2747 if (GET_CODE (operands[2]) == CONST_INT)
2748 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2749 else
b11cae9e 2750 {
87b22bf7 2751 rtx reg = gen_reg_rtx (SImode);
2752 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2753 operands[2] = reg;
b11cae9e 2754 }
cffb2a26 2755 "
2756)
9c08d1fa 2757
87b22bf7 2758(define_expand "rotrsi3"
cffb2a26 2759 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2760 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2761 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2762 "TARGET_EITHER"
87b22bf7 2763 "
cffb2a26 2764 if (TARGET_ARM)
2765 {
2766 if (GET_CODE (operands[2]) == CONST_INT
2767 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2768 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2769 }
2770 else /* TARGET_THUMB */
2771 {
2772 if (GET_CODE (operands [2]) == CONST_INT)
2773 operands [2] = force_reg (SImode, operands[2]);
2774 }
2775 "
2776)
87b22bf7 2777
cffb2a26 2778(define_insn "*thumb_rotrsi3"
2779 [(set (match_operand:SI 0 "register_operand" "=l")
2780 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2781 (match_operand:SI 2 "register_operand" "l")))]
2782 "TARGET_THUMB"
2783 "ror\\t%0, %0, %2"
2784 [(set_attr "length" "2")]
2785)
2786
2787(define_insn "*arm_shiftsi3"
2788 [(set (match_operand:SI 0 "s_register_operand" "=r")
2789 (match_operator:SI 3 "shift_operator"
2790 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 2791 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
cffb2a26 2792 "TARGET_ARM"
6c4c2133 2793 "mov%?\\t%0, %1%S3"
344495ea 2794 [(set_attr "predicable" "yes")
331beb1a 2795 (set_attr "shift" "1")
a2cd141b 2796 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2797 (const_string "alu_shift")
2798 (const_string "alu_shift_reg")))]
6c4c2133 2799)
87b22bf7 2800
f7fbdd4a 2801(define_insn "*shiftsi3_compare0"
bd5b4116 2802 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2803 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2804 [(match_operand:SI 1 "s_register_operand" "r")
2805 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2806 (const_int 0)))
2807 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2808 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
cffb2a26 2809 "TARGET_ARM"
87b22bf7 2810 "mov%?s\\t%0, %1%S3"
344495ea 2811 [(set_attr "conds" "set")
331beb1a 2812 (set_attr "shift" "1")
a2cd141b 2813 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2814 (const_string "alu_shift")
2815 (const_string "alu_shift_reg")))]
0d66636f 2816)
9c08d1fa 2817
f7fbdd4a 2818(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 2819 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2820 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2821 [(match_operand:SI 1 "s_register_operand" "r")
2822 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2823 (const_int 0)))
2824 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2825 "TARGET_ARM"
87b22bf7 2826 "mov%?s\\t%0, %1%S3"
344495ea 2827 [(set_attr "conds" "set")
a2cd141b 2828 (set_attr "shift" "1")]
0d66636f 2829)
9c08d1fa 2830
f7fbdd4a 2831(define_insn "*notsi_shiftsi"
9c08d1fa 2832 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2833 (not:SI (match_operator:SI 3 "shift_operator"
2834 [(match_operand:SI 1 "s_register_operand" "r")
2835 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 2836 "TARGET_ARM"
6c4c2133 2837 "mvn%?\\t%0, %1%S3"
344495ea 2838 [(set_attr "predicable" "yes")
331beb1a 2839 (set_attr "shift" "1")
a2cd141b 2840 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2841 (const_string "alu_shift")
2842 (const_string "alu_shift_reg")))]
0d66636f 2843)
9c08d1fa 2844
f7fbdd4a 2845(define_insn "*notsi_shiftsi_compare0"
bd5b4116 2846 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2847 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2848 [(match_operand:SI 1 "s_register_operand" "r")
2849 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2850 (const_int 0)))
2851 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2852 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 2853 "TARGET_ARM"
87b22bf7 2854 "mvn%?s\\t%0, %1%S3"
344495ea 2855 [(set_attr "conds" "set")
331beb1a 2856 (set_attr "shift" "1")
a2cd141b 2857 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2858 (const_string "alu_shift")
2859 (const_string "alu_shift_reg")))]
0d66636f 2860)
9c08d1fa 2861
f7fbdd4a 2862(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 2863 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2864 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2865 [(match_operand:SI 1 "s_register_operand" "r")
2866 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2867 (const_int 0)))
2868 (clobber (match_scratch:SI 0 "=r"))]
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
cffb2a26 2878;; We don't really have extzv, but defining this using shifts helps
2879;; to reduce register pressure later on.
2880
2881(define_expand "extzv"
2882 [(set (match_dup 4)
2883 (ashift:SI (match_operand:SI 1 "register_operand" "")
2884 (match_operand:SI 2 "const_int_operand" "")))
2885 (set (match_operand:SI 0 "register_operand" "")
2886 (lshiftrt:SI (match_dup 4)
215b30b3 2887 (match_operand:SI 3 "const_int_operand" "")))]
cffb2a26 2888 "TARGET_THUMB"
2889 "
2890 {
2891 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2892 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2893
2894 operands[3] = GEN_INT (rshift);
2895
2896 if (lshift == 0)
2897 {
2898 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2899 DONE;
2900 }
2901
2902 operands[2] = GEN_INT (lshift);
2903 operands[4] = gen_reg_rtx (SImode);
215b30b3 2904 }"
cffb2a26 2905)
2906
b11cae9e 2907\f
2908;; Unary arithmetic insns
2909
cffb2a26 2910(define_expand "negdi2"
2911 [(parallel
2912 [(set (match_operand:DI 0 "s_register_operand" "")
2913 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 2914 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 2915 "TARGET_EITHER"
2916 "
2917 if (TARGET_THUMB)
2918 {
2919 if (GET_CODE (operands[1]) != REG)
2920 operands[1] = force_reg (SImode, operands[1]);
2921 }
215b30b3 2922 "
cffb2a26 2923)
2924
2925;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2926;; The second alternative is to allow the common case of a *full* overlap.
2927(define_insn "*arm_negdi2"
2928 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2929 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 2930 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2931 "TARGET_ARM"
97499065 2932 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 2933 [(set_attr "conds" "clob")
2934 (set_attr "length" "8")]
2935)
b11cae9e 2936
cffb2a26 2937(define_insn "*thumb_negdi2"
2938 [(set (match_operand:DI 0 "register_operand" "=&l")
2939 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 2940 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2941 "TARGET_THUMB"
2942 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2943 [(set_attr "length" "6")]
2944)
2945
2946(define_expand "negsi2"
2947 [(set (match_operand:SI 0 "s_register_operand" "")
2948 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2949 "TARGET_EITHER"
b11cae9e 2950 ""
cffb2a26 2951)
2952
2953(define_insn "*arm_negsi2"
2954 [(set (match_operand:SI 0 "s_register_operand" "=r")
2955 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2956 "TARGET_ARM"
2957 "rsb%?\\t%0, %1, #0"
0d66636f 2958 [(set_attr "predicable" "yes")]
cffb2a26 2959)
2960
2961(define_insn "*thumb_negsi2"
2962 [(set (match_operand:SI 0 "register_operand" "=l")
2963 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2964 "TARGET_THUMB"
2965 "neg\\t%0, %1"
2966 [(set_attr "length" "2")]
2967)
b11cae9e 2968
604f3a0a 2969(define_expand "negsf2"
2970 [(set (match_operand:SF 0 "s_register_operand" "")
2971 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 2972 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
604f3a0a 2973 ""
2974)
2975
2976(define_expand "negdf2"
2977 [(set (match_operand:DF 0 "s_register_operand" "")
2978 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 2979 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
604f3a0a 2980 "")
2981
9c08d1fa 2982;; abssi2 doesn't really clobber the condition codes if a different register
2983;; is being set. To keep things simple, assume during rtl manipulations that
2984;; it does, but tell the final scan operator the truth. Similarly for
2985;; (neg (abs...))
2986
604f3a0a 2987(define_expand "abssi2"
2988 [(parallel
2989 [(set (match_operand:SI 0 "s_register_operand" "")
2990 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2991 (clobber (reg:CC CC_REGNUM))])]
2992 "TARGET_ARM"
2993 "")
2994
7d57ec45 2995(define_insn "*arm_abssi2"
722f9800 2996 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 2997 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 2998 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2999 "TARGET_ARM"
e2348bcb 3000 "@
3001 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3002 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3003 [(set_attr "conds" "clob,*")
331beb1a 3004 (set_attr "shift" "1")
0d66636f 3005 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3006 (set_attr "length" "8")]
3007)
9c08d1fa 3008
f7fbdd4a 3009(define_insn "*neg_abssi2"
9c08d1fa 3010 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3011 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3012 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3013 "TARGET_ARM"
e2348bcb 3014 "@
3015 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3016 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3017 [(set_attr "conds" "clob,*")
331beb1a 3018 (set_attr "shift" "1")
0d66636f 3019 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3020 (set_attr "length" "8")]
3021)
b11cae9e 3022
604f3a0a 3023(define_expand "abssf2"
3024 [(set (match_operand:SF 0 "s_register_operand" "")
3025 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3026 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3027 "")
3028
604f3a0a 3029(define_expand "absdf2"
3030 [(set (match_operand:DF 0 "s_register_operand" "")
3031 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3032 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3033 "")
3034
7db9af5d 3035(define_expand "sqrtsf2"
3036 [(set (match_operand:SF 0 "s_register_operand" "")
3037 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3038 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3039 "")
9c08d1fa 3040
7db9af5d 3041(define_expand "sqrtdf2"
3042 [(set (match_operand:DF 0 "s_register_operand" "")
3043 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3044 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3045 "")
9c08d1fa 3046
a0f94409 3047(define_insn_and_split "one_cmpldi2"
9c08d1fa 3048 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3049 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 3050 "TARGET_ARM"
f6ebffac 3051 "#"
a0f94409 3052 "TARGET_ARM && reload_completed"
3053 [(set (match_dup 0) (not:SI (match_dup 1)))
3054 (set (match_dup 2) (not:SI (match_dup 3)))]
3055 "
3056 {
3057 operands[2] = gen_highpart (SImode, operands[0]);
3058 operands[0] = gen_lowpart (SImode, operands[0]);
3059 operands[3] = gen_highpart (SImode, operands[1]);
3060 operands[1] = gen_lowpart (SImode, operands[1]);
3061 }"
0d66636f 3062 [(set_attr "length" "8")
3063 (set_attr "predicable" "yes")]
cffb2a26 3064)
b11cae9e 3065
cffb2a26 3066(define_expand "one_cmplsi2"
3067 [(set (match_operand:SI 0 "s_register_operand" "")
3068 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3069 "TARGET_EITHER"
b11cae9e 3070 ""
cffb2a26 3071)
3072
3073(define_insn "*arm_one_cmplsi2"
3074 [(set (match_operand:SI 0 "s_register_operand" "=r")
3075 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3076 "TARGET_ARM"
3077 "mvn%?\\t%0, %1"
0d66636f 3078 [(set_attr "predicable" "yes")]
cffb2a26 3079)
3080
3081(define_insn "*thumb_one_cmplsi2"
3082 [(set (match_operand:SI 0 "register_operand" "=l")
3083 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3084 "TARGET_THUMB"
3085 "mvn\\t%0, %1"
3086 [(set_attr "length" "2")]
3087)
9c08d1fa 3088
f7fbdd4a 3089(define_insn "*notsi_compare0"
bd5b4116 3090 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3091 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3092 (const_int 0)))
3093 (set (match_operand:SI 0 "s_register_operand" "=r")
3094 (not:SI (match_dup 1)))]
cffb2a26 3095 "TARGET_ARM"
40dbec34 3096 "mvn%?s\\t%0, %1"
cffb2a26 3097 [(set_attr "conds" "set")]
3098)
9c08d1fa 3099
f7fbdd4a 3100(define_insn "*notsi_compare0_scratch"
bd5b4116 3101 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3102 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3103 (const_int 0)))
3104 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3105 "TARGET_ARM"
40dbec34 3106 "mvn%?s\\t%0, %1"
cffb2a26 3107 [(set_attr "conds" "set")]
3108)
b11cae9e 3109\f
3110;; Fixed <--> Floating conversion insns
3111
604f3a0a 3112(define_expand "floatsisf2"
3113 [(set (match_operand:SF 0 "s_register_operand" "")
3114 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3115 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3116 "
a2cd141b 3117 if (TARGET_MAVERICK)
604f3a0a 3118 {
3119 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3120 DONE;
3121 }
3122")
3123
604f3a0a 3124(define_expand "floatsidf2"
3125 [(set (match_operand:DF 0 "s_register_operand" "")
3126 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3127 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3128 "
a2cd141b 3129 if (TARGET_MAVERICK)
604f3a0a 3130 {
3131 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3132 DONE;
3133 }
3134")
3135
604f3a0a 3136(define_expand "fix_truncsfsi2"
3137 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3138 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
a2cd141b 3139 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3140 "
a2cd141b 3141 if (TARGET_MAVERICK)
604f3a0a 3142 {
3143 if (!cirrus_fp_register (operands[0], SImode))
3144 operands[0] = force_reg (SImode, operands[0]);
3145 if (!cirrus_fp_register (operands[1], SFmode))
3146 operands[1] = force_reg (SFmode, operands[0]);
3147 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3148 DONE;
3149 }
3150")
3151
604f3a0a 3152(define_expand "fix_truncdfsi2"
3153 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3154 (fix:SI (fix:DF (match_operand:DF 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[1], DFmode))
3160 operands[1] = force_reg (DFmode, operands[0]);
3161 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3162 DONE;
3163 }
3164")
3165
f544c6d2 3166;; Truncation insns
b11cae9e 3167
604f3a0a 3168(define_expand "truncdfsf2"
3169 [(set (match_operand:SF 0 "s_register_operand" "")
3170 (float_truncate:SF
3171 (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3172 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3173 ""
3174)
b11cae9e 3175\f
9c08d1fa 3176;; Zero and sign extension instructions.
b11cae9e 3177
9c08d1fa 3178(define_insn "zero_extendsidi2"
3179 [(set (match_operand:DI 0 "s_register_operand" "=r")
3180 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3181 "TARGET_ARM"
9c08d1fa 3182 "*
0d66636f 3183 if (REGNO (operands[1])
3184 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3185 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3186 return \"mov%?\\t%R0, #0\";
3187 "
3188 [(set_attr "length" "8")
3189 (set_attr "predicable" "yes")]
3190)
9c08d1fa 3191
3192(define_insn "zero_extendqidi2"
cffb2a26 3193 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3194 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3195 "TARGET_ARM"
e2348bcb 3196 "@
97499065 3197 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3198 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3199 [(set_attr "length" "8")
0d66636f 3200 (set_attr "predicable" "yes")
a2cd141b 3201 (set_attr "type" "*,load_byte")
cffb2a26 3202 (set_attr "pool_range" "*,4092")
3203 (set_attr "neg_pool_range" "*,4084")]
3204)
9c08d1fa 3205
3206(define_insn "extendsidi2"
3207 [(set (match_operand:DI 0 "s_register_operand" "=r")
3208 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3209 "TARGET_ARM"
9c08d1fa 3210 "*
0d66636f 3211 if (REGNO (operands[1])
3212 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3213 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3214 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3215 "
3216 [(set_attr "length" "8")
331beb1a 3217 (set_attr "shift" "1")
0d66636f 3218 (set_attr "predicable" "yes")]
3219)
9c08d1fa 3220
3221(define_expand "zero_extendhisi2"
cffb2a26 3222 [(set (match_dup 2)
0d66636f 3223 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3224 (const_int 16)))
9c08d1fa 3225 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3226 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3227 "TARGET_EITHER"
9c08d1fa 3228 "
cffb2a26 3229 {
a2cd141b 3230 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3231 {
a2cd141b 3232 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3233 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3234 DONE;
cffb2a26 3235 }
cffb2a26 3236
c1a66faf 3237 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3238 {
3239 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3240 DONE;
3241 }
cffb2a26 3242
a2cd141b 3243 if (!s_register_operand (operands[1], HImode))
3244 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3245
a2cd141b 3246 if (arm_arch6)
3247 {
3248 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250 DONE;
cffb2a26 3251 }
a2cd141b 3252
3253 operands[1] = gen_lowpart (SImode, operands[1]);
3254 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3255 }"
3256)
3257
3258(define_insn "*thumb_zero_extendhisi2"
a2cd141b 3259 [(set (match_operand:SI 0 "register_operand" "=l")
3260 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3261 "TARGET_THUMB && !arm_arch6"
cffb2a26 3262 "*
3263 rtx mem = XEXP (operands[1], 0);
3264
3265 if (GET_CODE (mem) == CONST)
3266 mem = XEXP (mem, 0);
3267
3268 if (GET_CODE (mem) == LABEL_REF)
3269 return \"ldr\\t%0, %1\";
3270
3271 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3272 {
cffb2a26 3273 rtx a = XEXP (mem, 0);
3274 rtx b = XEXP (mem, 1);
3275
3276 /* This can happen due to bugs in reload. */
3277 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3278 {
3279 rtx ops[2];
3280 ops[0] = operands[0];
3281 ops[1] = a;
3282
3283 output_asm_insn (\"mov %0, %1\", ops);
3284
3285 XEXP (mem, 0) = operands[0];
3286 }
3287
3288 else if ( GET_CODE (a) == LABEL_REF
3289 && GET_CODE (b) == CONST_INT)
3290 return \"ldr\\t%0, %1\";
25f7a26e 3291 }
cffb2a26 3292
3293 return \"ldrh\\t%0, %1\";
3294 "
3295 [(set_attr "length" "4")
a2cd141b 3296 (set_attr "type" "load_byte")
cffb2a26 3297 (set_attr "pool_range" "60")]
3298)
9c08d1fa 3299
a2cd141b 3300(define_insn "*thumb_zero_extendhisi2_v6"
3301 [(set (match_operand:SI 0 "register_operand" "=l,l")
3302 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3303 "TARGET_THUMB && arm_arch6"
3304 "*
3305 rtx mem;
3306
3307 if (which_alternative == 0)
3308 return \"uxth\\t%0, %1\";
3309
3310 mem = XEXP (operands[1], 0);
3311
3312 if (GET_CODE (mem) == CONST)
3313 mem = XEXP (mem, 0);
3314
3315 if (GET_CODE (mem) == LABEL_REF)
3316 return \"ldr\\t%0, %1\";
3317
3318 if (GET_CODE (mem) == PLUS)
3319 {
3320 rtx a = XEXP (mem, 0);
3321 rtx b = XEXP (mem, 1);
3322
3323 /* This can happen due to bugs in reload. */
3324 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3325 {
3326 rtx ops[2];
3327 ops[0] = operands[0];
3328 ops[1] = a;
3329
3330 output_asm_insn (\"mov %0, %1\", ops);
3331
3332 XEXP (mem, 0) = operands[0];
3333 }
3334
3335 else if ( GET_CODE (a) == LABEL_REF
3336 && GET_CODE (b) == CONST_INT)
3337 return \"ldr\\t%0, %1\";
3338 }
3339
3340 return \"ldrh\\t%0, %1\";
3341 "
3342 [(set_attr "length" "2,4")
3343 (set_attr "type" "alu_shift,load_byte")
3344 (set_attr "pool_range" "*,60")]
3345)
3346
cffb2a26 3347(define_insn "*arm_zero_extendhisi2"
a2cd141b 3348 [(set (match_operand:SI 0 "s_register_operand" "=r")
3349 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3350 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3351 "ldr%?h\\t%0, %1"
a2cd141b 3352 [(set_attr "type" "load_byte")
0d66636f 3353 (set_attr "predicable" "yes")
cffb2a26 3354 (set_attr "pool_range" "256")
3355 (set_attr "neg_pool_range" "244")]
3356)
f7fbdd4a 3357
a2cd141b 3358(define_insn "*arm_zero_extendhisi2_v6"
3359 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3360 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3361 "TARGET_ARM && arm_arch6"
3362 "@
3363 uxth%?\\t%0, %1
3364 ldr%?h\\t%0, %1"
3365 [(set_attr "type" "alu_shift,load_byte")
3366 (set_attr "predicable" "yes")
3367 (set_attr "pool_range" "*,256")
3368 (set_attr "neg_pool_range" "*,244")]
3369)
3370
3371(define_insn "*arm_zero_extendhisi2addsi"
3372 [(set (match_operand:SI 0 "s_register_operand" "=r")
3373 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3374 (match_operand:SI 2 "s_register_operand" "r")))]
3375 "TARGET_ARM && arm_arch6"
3376 "uxtah%?\\t%0, %2, %1"
3377 [(set_attr "type" "alu_shift")
3378 (set_attr "predicable" "yes")]
3379)
3380
206ee9a2 3381(define_split
3382 [(set (match_operand:SI 0 "s_register_operand" "")
3383 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3384 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3385 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3386 [(set (match_dup 2) (match_dup 1))
3387 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3388 "
cffb2a26 3389 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3390 FAIL;
215b30b3 3391 "
3392)
206ee9a2 3393
3394(define_split
3395 [(set (match_operand:SI 0 "s_register_operand" "")
3396 (match_operator:SI 3 "shiftable_operator"
3397 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3398 (match_operand:SI 4 "s_register_operand" "")]))
3399 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3400 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3401 [(set (match_dup 2) (match_dup 1))
3402 (set (match_dup 0)
3403 (match_op_dup 3
3404 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3405 "
cffb2a26 3406 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3407 FAIL;
215b30b3 3408 "
3409)
206ee9a2 3410
87b22bf7 3411(define_expand "zero_extendqisi2"
cffb2a26 3412 [(set (match_operand:SI 0 "s_register_operand" "")
3413 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3414 "TARGET_EITHER"
87b22bf7 3415 "
a2cd141b 3416 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 3417 {
cffb2a26 3418 if (TARGET_ARM)
3419 {
215b30b3 3420 emit_insn (gen_andsi3 (operands[0],
3421 gen_lowpart (SImode, operands[1]),
cffb2a26 3422 GEN_INT (255)));
3423 }
3424 else /* TARGET_THUMB */
3425 {
3426 rtx temp = gen_reg_rtx (SImode);
3427 rtx ops[3];
3428
3429 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3430 operands[1] = gen_lowpart (SImode, operands[1]);
3431
3432 ops[0] = temp;
3433 ops[1] = operands[1];
3434 ops[2] = GEN_INT (24);
3435
215b30b3 3436 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3437 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3438
3439 ops[0] = operands[0];
3440 ops[1] = temp;
3441 ops[2] = GEN_INT (24);
3442
215b30b3 3443 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3445 }
87b22bf7 3446 DONE;
3447 }
215b30b3 3448 "
3449)
9c08d1fa 3450
cffb2a26 3451(define_insn "*thumb_zero_extendqisi2"
a2cd141b 3452 [(set (match_operand:SI 0 "register_operand" "=l")
3453 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3454 "TARGET_THUMB && !arm_arch6"
cffb2a26 3455 "ldrb\\t%0, %1"
3456 [(set_attr "length" "2")
a2cd141b 3457 (set_attr "type" "load_byte")
cffb2a26 3458 (set_attr "pool_range" "32")]
3459)
3460
a2cd141b 3461(define_insn "*thumb_zero_extendqisi2_v6"
3462 [(set (match_operand:SI 0 "register_operand" "=l,l")
3463 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3464 "TARGET_THUMB && arm_arch6"
3465 "@
3466 uxtb\\t%0, %1
3467 ldrb\\t%0, %1"
3468 [(set_attr "length" "2,2")
3469 (set_attr "type" "alu_shift,load_byte")
3470 (set_attr "pool_range" "*,32")]
3471)
3472
cffb2a26 3473(define_insn "*arm_zero_extendqisi2"
a2cd141b 3474 [(set (match_operand:SI 0 "s_register_operand" "=r")
3475 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3476 "TARGET_ARM && !arm_arch6"
87b22bf7 3477 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3478 [(set_attr "type" "load_byte")
0d66636f 3479 (set_attr "predicable" "yes")
cffb2a26 3480 (set_attr "pool_range" "4096")
3481 (set_attr "neg_pool_range" "4084")]
3482)
87b22bf7 3483
a2cd141b 3484(define_insn "*arm_zero_extendqisi2_v6"
3485 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3486 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3487 "TARGET_ARM && arm_arch6"
3488 "@
3489 uxtb%?\\t%0, %1
3490 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3491 [(set_attr "type" "alu_shift,load_byte")
3492 (set_attr "predicable" "yes")
3493 (set_attr "pool_range" "*,4096")
3494 (set_attr "neg_pool_range" "*,4084")]
3495)
3496
3497(define_insn "*arm_zero_extendqisi2addsi"
3498 [(set (match_operand:SI 0 "s_register_operand" "=r")
3499 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3500 (match_operand:SI 2 "s_register_operand" "r")))]
3501 "TARGET_ARM && arm_arch6"
3502 "uxtab%?\\t%0, %2, %1"
3503 [(set_attr "predicable" "yes")
3504 (set_attr "type" "alu_shift")]
3505)
3506
87b22bf7 3507(define_split
3508 [(set (match_operand:SI 0 "s_register_operand" "")
3509 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3510 (clobber (match_operand:SI 2 "s_register_operand" ""))]
9e8503e6 3511 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 3512 [(set (match_dup 2) (match_dup 1))
3513 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 3514 ""
3515)
9c08d1fa 3516
f7fbdd4a 3517(define_insn "*compareqi_eq0"
bd5b4116 3518 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 3519 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 3520 (const_int 0)))]
cffb2a26 3521 "TARGET_ARM"
87b22bf7 3522 "tst\\t%0, #255"
cffb2a26 3523 [(set_attr "conds" "set")]
3524)
b11cae9e 3525
b11cae9e 3526(define_expand "extendhisi2"
c8f69309 3527 [(set (match_dup 2)
25f7a26e 3528 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 3529 (const_int 16)))
9c08d1fa 3530 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3531 (ashiftrt:SI (match_dup 2)
3532 (const_int 16)))]
cffb2a26 3533 "TARGET_EITHER"
b11cae9e 3534 "
cffb2a26 3535 {
a2cd141b 3536 if (GET_CODE (operands[1]) == MEM)
cffb2a26 3537 {
a2cd141b 3538 if (TARGET_THUMB)
3539 {
3540 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3541 DONE;
3542 }
3543 else if (arm_arch4)
3544 {
a2cd141b 3545 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3546 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3547 DONE;
3548 }
cffb2a26 3549 }
7bd8ccc9 3550
c1a66faf 3551 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 3552 {
3553 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3554 DONE;
3555 }
a2cd141b 3556
215b30b3 3557 if (!s_register_operand (operands[1], HImode))
cffb2a26 3558 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3559
a2cd141b 3560 if (arm_arch6)
cffb2a26 3561 {
a2cd141b 3562 if (TARGET_THUMB)
3563 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3564 else
3565 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3566 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3567
cffb2a26 3568 DONE;
3569 }
a2cd141b 3570
3571 operands[1] = gen_lowpart (SImode, operands[1]);
3572 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3573 }"
3574)
3575
a2cd141b 3576(define_insn "thumb_extendhisi2"
3577 [(set (match_operand:SI 0 "register_operand" "=l")
3578 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3579 (clobber (match_scratch:SI 2 "=&l"))]
3580 "TARGET_THUMB && !arm_arch6"
cffb2a26 3581 "*
3582 {
3583 rtx ops[4];
3584 rtx mem = XEXP (operands[1], 0);
3585
3586 /* This code used to try to use 'V', and fix the address only if it was
3587 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3588 range of QImode offsets, and offsettable_address_p does a QImode
3589 address check. */
3590
3591 if (GET_CODE (mem) == CONST)
3592 mem = XEXP (mem, 0);
3593
3594 if (GET_CODE (mem) == LABEL_REF)
3595 return \"ldr\\t%0, %1\";
3596
3597 if (GET_CODE (mem) == PLUS)
3598 {
3599 rtx a = XEXP (mem, 0);
3600 rtx b = XEXP (mem, 1);
3601
3602 if (GET_CODE (a) == LABEL_REF
3603 && GET_CODE (b) == CONST_INT)
3604 return \"ldr\\t%0, %1\";
3605
3606 if (GET_CODE (b) == REG)
3607 return \"ldrsh\\t%0, %1\";
3608
3609 ops[1] = a;
3610 ops[2] = b;
3611 }
3612 else
3613 {
3614 ops[1] = mem;
3615 ops[2] = const0_rtx;
3616 }
ed29c566 3617
3618 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 3619
3620 ops[0] = operands[0];
3621 ops[3] = operands[2];
3622 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3623 return \"\";
3624 }"
3625 [(set_attr "length" "4")
a2cd141b 3626 (set_attr "type" "load_byte")
cffb2a26 3627 (set_attr "pool_range" "1020")]
3628)
25f7a26e 3629
a2cd141b 3630;; We used to have an early-clobber on the scratch register here.
3631;; However, there's a bug somewhere in reload which means that this
3632;; can be partially ignored during spill allocation if the memory
ed29c566 3633;; address also needs reloading; this causes us to die later on when
a2cd141b 3634;; we try to verify the operands. Fortunately, we don't really need
3635;; the early-clobber: we can always use operand 0 if operand 2
3636;; overlaps the address.
3637(define_insn "*thumb_extendhisi2_insn_v6"
3638 [(set (match_operand:SI 0 "register_operand" "=l,l")
3639 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3640 (clobber (match_scratch:SI 2 "=X,l"))]
3641 "TARGET_THUMB && arm_arch6"
3642 "*
3643 {
3644 rtx ops[4];
3645 rtx mem;
3646
3647 if (which_alternative == 0)
3648 return \"sxth\\t%0, %1\";
3649
3650 mem = XEXP (operands[1], 0);
3651
3652 /* This code used to try to use 'V', and fix the address only if it was
3653 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3654 range of QImode offsets, and offsettable_address_p does a QImode
3655 address check. */
3656
3657 if (GET_CODE (mem) == CONST)
3658 mem = XEXP (mem, 0);
3659
3660 if (GET_CODE (mem) == LABEL_REF)
3661 return \"ldr\\t%0, %1\";
3662
3663 if (GET_CODE (mem) == PLUS)
3664 {
3665 rtx a = XEXP (mem, 0);
3666 rtx b = XEXP (mem, 1);
3667
3668 if (GET_CODE (a) == LABEL_REF
3669 && GET_CODE (b) == CONST_INT)
3670 return \"ldr\\t%0, %1\";
3671
3672 if (GET_CODE (b) == REG)
3673 return \"ldrsh\\t%0, %1\";
3674
3675 ops[1] = a;
3676 ops[2] = b;
3677 }
3678 else
3679 {
3680 ops[1] = mem;
3681 ops[2] = const0_rtx;
3682 }
3683
ed29c566 3684 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 3685
3686 ops[0] = operands[0];
3687 if (reg_mentioned_p (operands[2], ops[1]))
3688 ops[3] = ops[0];
3689 else
3690 ops[3] = operands[2];
3691 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3692 return \"\";
3693 }"
3694 [(set_attr "length" "2,4")
3695 (set_attr "type" "alu_shift,load_byte")
3696 (set_attr "pool_range" "*,1020")]
3697)
3698
25f7a26e 3699(define_expand "extendhisi2_mem"
eab14235 3700 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 3701 (set (match_dup 3)
eab14235 3702 (zero_extend:SI (match_dup 7)))
25f7a26e 3703 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3704 (set (match_operand:SI 0 "" "")
3705 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 3706 "TARGET_ARM"
25f7a26e 3707 "
215b30b3 3708 {
3709 rtx mem1, mem2;
3710 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3711
3712 mem1 = gen_rtx_MEM (QImode, addr);
3713 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3714 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3715 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3716 operands[0] = gen_lowpart (SImode, operands[0]);
3717 operands[1] = mem1;
3718 operands[2] = gen_reg_rtx (SImode);
3719 operands[3] = gen_reg_rtx (SImode);
3720 operands[6] = gen_reg_rtx (SImode);
3721 operands[7] = mem2;
25f7a26e 3722
215b30b3 3723 if (BYTES_BIG_ENDIAN)
3724 {
3725 operands[4] = operands[2];
3726 operands[5] = operands[3];
3727 }
3728 else
3729 {
3730 operands[4] = operands[3];
3731 operands[5] = operands[2];
3732 }
3733 }"
3734)
b11cae9e 3735
a2cd141b 3736(define_insn "*arm_extendhisi2"
3737 [(set (match_operand:SI 0 "s_register_operand" "=r")
3738 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3739 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3740 "ldr%?sh\\t%0, %1"
a2cd141b 3741 [(set_attr "type" "load_byte")
0d66636f 3742 (set_attr "predicable" "yes")
cffb2a26 3743 (set_attr "pool_range" "256")
3744 (set_attr "neg_pool_range" "244")]
3745)
f7fbdd4a 3746
a2cd141b 3747(define_insn "*arm_extendhisi2_v6"
3748 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3749 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3750 "TARGET_ARM && arm_arch6"
3751 "@
3752 sxth%?\\t%0, %1
3753 ldr%?sh\\t%0, %1"
3754 [(set_attr "type" "alu_shift,load_byte")
3755 (set_attr "predicable" "yes")
3756 (set_attr "pool_range" "*,256")
3757 (set_attr "neg_pool_range" "*,244")]
3758)
3759
3760(define_insn "*arm_extendhisi2addsi"
3761 [(set (match_operand:SI 0 "s_register_operand" "=r")
3762 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3763 (match_operand:SI 2 "s_register_operand" "r")))]
3764 "TARGET_ARM && arm_arch6"
3765 "sxtah%?\\t%0, %2, %1"
3766)
3767
206ee9a2 3768(define_split
cffb2a26 3769 [(set (match_operand:SI 0 "s_register_operand" "")
206ee9a2 3770 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
cffb2a26 3771 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3772 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3773 [(set (match_dup 2) (match_dup 1))
3774 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3775 "
cffb2a26 3776 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3777 FAIL;
cffb2a26 3778 "
3779)
206ee9a2 3780
3781(define_split
cffb2a26 3782 [(set (match_operand:SI 0 "s_register_operand" "")
3783 (match_operator:SI 3 "shiftable_operator"
206ee9a2 3784 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
cffb2a26 3785 (match_operand:SI 4 "s_register_operand" "")]))
3786 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3787 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3788 [(set (match_dup 2) (match_dup 1))
3789 (set (match_dup 0)
3790 (match_op_dup 3
3791 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
cffb2a26 3792 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3793 FAIL;
206ee9a2 3794 "
cffb2a26 3795)
206ee9a2 3796
c8f69309 3797(define_expand "extendqihi2"
3798 [(set (match_dup 2)
f7fbdd4a 3799 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 3800 (const_int 24)))
9c08d1fa 3801 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 3802 (ashiftrt:SI (match_dup 2)
3803 (const_int 24)))]
cffb2a26 3804 "TARGET_ARM"
c8f69309 3805 "
215b30b3 3806 {
3807 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3808 {
3809 emit_insn (gen_rtx_SET (VOIDmode,
3810 operands[0],
3811 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3812 DONE;
3813 }
3814 if (!s_register_operand (operands[1], QImode))
3815 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3816 operands[0] = gen_lowpart (SImode, operands[0]);
3817 operands[1] = gen_lowpart (SImode, operands[1]);
3818 operands[2] = gen_reg_rtx (SImode);
3819 }"
3820)
f7fbdd4a 3821
3822(define_insn "*extendqihi_insn"
b4e8a300 3823 [(set (match_operand:HI 0 "s_register_operand" "=r")
3824 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
cffb2a26 3825 "TARGET_ARM && arm_arch4"
b4e8a300 3826 "ldr%?sb\\t%0, %1"
a2cd141b 3827 [(set_attr "type" "load_byte")
0d66636f 3828 (set_attr "predicable" "yes")
cffb2a26 3829 (set_attr "pool_range" "256")
3830 (set_attr "neg_pool_range" "244")]
3831)
3fc2009e 3832
b11cae9e 3833(define_expand "extendqisi2"
c8f69309 3834 [(set (match_dup 2)
3fc2009e 3835 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 3836 (const_int 24)))
9c08d1fa 3837 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3838 (ashiftrt:SI (match_dup 2)
3839 (const_int 24)))]
cffb2a26 3840 "TARGET_EITHER"
b11cae9e 3841 "
cffb2a26 3842 {
a2cd141b 3843 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3844 {
a2cd141b 3845 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 3846 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3847 DONE;
3848 }
a2cd141b 3849
215b30b3 3850 if (!s_register_operand (operands[1], QImode))
cffb2a26 3851 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 3852
a2cd141b 3853 if (arm_arch6)
3854 {
3855 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3856 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3857 DONE;
cffb2a26 3858 }
a2cd141b 3859
3860 operands[1] = gen_lowpart (SImode, operands[1]);
3861 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3862 }"
3863)
f7fbdd4a 3864
a2cd141b 3865(define_insn "*arm_extendqisi"
3866 [(set (match_operand:SI 0 "s_register_operand" "=r")
b4e8a300 3867 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
a2cd141b 3868 "TARGET_ARM && arm_arch4 && !arm_arch6"
b4e8a300 3869 "ldr%?sb\\t%0, %1"
a2cd141b 3870 [(set_attr "type" "load_byte")
0d66636f 3871 (set_attr "predicable" "yes")
cffb2a26 3872 (set_attr "pool_range" "256")
3873 (set_attr "neg_pool_range" "244")]
3874)
3fc2009e 3875
a2cd141b 3876(define_insn "*arm_extendqisi_v6"
3877 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
b4e8a300 3878 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
a2cd141b 3879 "TARGET_ARM && arm_arch6"
b4e8a300 3880 "@
3881 sxtb%?\\t%0, %1
3882 ldr%?sb\\t%0, %1"
a2cd141b 3883 [(set_attr "type" "alu_shift,load_byte")
3884 (set_attr "predicable" "yes")
a2cd141b 3885 (set_attr "pool_range" "*,256")
3886 (set_attr "neg_pool_range" "*,244")]
3887)
3888
3889(define_insn "*arm_extendqisi2addsi"
3890 [(set (match_operand:SI 0 "s_register_operand" "=r")
3891 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3892 (match_operand:SI 2 "s_register_operand" "r")))]
3893 "TARGET_ARM && arm_arch6"
3894 "sxtab%?\\t%0, %2, %1"
3895 [(set_attr "type" "alu_shift")
3896 (set_attr "predicable" "yes")]
3897)
3898
a2cd141b 3899(define_insn "*thumb_extendqisi2"
3900 [(set (match_operand:SI 0 "register_operand" "=l,l")
3901 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3902 "TARGET_THUMB && !arm_arch6"
cffb2a26 3903 "*
3904 {
3905 rtx ops[3];
3906 rtx mem = XEXP (operands[1], 0);
3907
3908 if (GET_CODE (mem) == CONST)
3909 mem = XEXP (mem, 0);
3910
3911 if (GET_CODE (mem) == LABEL_REF)
3912 return \"ldr\\t%0, %1\";
3913
3914 if (GET_CODE (mem) == PLUS
3915 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3916 return \"ldr\\t%0, %1\";
3917
3918 if (which_alternative == 0)
3919 return \"ldrsb\\t%0, %1\";
3920
3921 ops[0] = operands[0];
3922
3923 if (GET_CODE (mem) == PLUS)
3924 {
3925 rtx a = XEXP (mem, 0);
3926 rtx b = XEXP (mem, 1);
3927
3928 ops[1] = a;
3929 ops[2] = b;
3930
3931 if (GET_CODE (a) == REG)
3932 {
3933 if (GET_CODE (b) == REG)
3934 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3935 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 3936 {
3937 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3938 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3939 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3940 }
cffb2a26 3941 else
3942 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3943 }
cffb2a26 3944 else
3945 {
ed29c566 3946 gcc_assert (GET_CODE (b) == REG);
cffb2a26 3947 if (REGNO (b) == REGNO (ops[0]))
215b30b3 3948 {
3949 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3950 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3951 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3952 }
cffb2a26 3953 else
3954 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3955 }
3956 }
3957 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3958 {
215b30b3 3959 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3960 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3961 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 3962 }
3963 else
3964 {
3965 ops[1] = mem;
3966 ops[2] = const0_rtx;
3967
3968 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3969 }
3970 return \"\";
3971 }"
3972 [(set_attr "length" "2,6")
a2cd141b 3973 (set_attr "type" "load_byte,load_byte")
cffb2a26 3974 (set_attr "pool_range" "32,32")]
3975)
3976
a2cd141b 3977(define_insn "*thumb_extendqisi2_v6"
3978 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3979 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3980 "TARGET_THUMB && arm_arch6"
3981 "*
3982 {
3983 rtx ops[3];
3984 rtx mem;
3985
3986 if (which_alternative == 0)
3987 return \"sxtb\\t%0, %1\";
3988
3989 mem = XEXP (operands[1], 0);
3990
3991 if (GET_CODE (mem) == CONST)
3992 mem = XEXP (mem, 0);
3993
3994 if (GET_CODE (mem) == LABEL_REF)
3995 return \"ldr\\t%0, %1\";
3996
3997 if (GET_CODE (mem) == PLUS
3998 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3999 return \"ldr\\t%0, %1\";
4000
4001 if (which_alternative == 0)
4002 return \"ldrsb\\t%0, %1\";
4003
4004 ops[0] = operands[0];
4005
4006 if (GET_CODE (mem) == PLUS)
4007 {
4008 rtx a = XEXP (mem, 0);
4009 rtx b = XEXP (mem, 1);
4010
4011 ops[1] = a;
4012 ops[2] = b;
4013
4014 if (GET_CODE (a) == REG)
4015 {
4016 if (GET_CODE (b) == REG)
4017 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4018 else if (REGNO (a) == REGNO (ops[0]))
4019 {
4020 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4021 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4022 }
4023 else
4024 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4025 }
a2cd141b 4026 else
4027 {
ed29c566 4028 gcc_assert (GET_CODE (b) == REG);
a2cd141b 4029 if (REGNO (b) == REGNO (ops[0]))
4030 {
4031 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4032 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4033 }
4034 else
4035 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4036 }
4037 }
4038 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4039 {
4040 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4041 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4042 }
4043 else
4044 {
4045 ops[1] = mem;
4046 ops[2] = const0_rtx;
4047
4048 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4049 }
4050 return \"\";
4051 }"
4052 [(set_attr "length" "2,2,4")
4053 (set_attr "type" "alu_shift,load_byte,load_byte")
4054 (set_attr "pool_range" "*,32,32")]
4055)
4056
caedf871 4057(define_expand "extendsfdf2"
4058 [(set (match_operand:DF 0 "s_register_operand" "")
4059 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 4060 "TARGET_ARM && TARGET_HARD_FLOAT"
caedf871 4061 ""
4062)
b11cae9e 4063\f
4064;; Move insns (including loads and stores)
4065
4066;; XXX Just some ideas about movti.
9c08d1fa 4067;; I don't think these are a good idea on the arm, there just aren't enough
4068;; registers
b11cae9e 4069;;(define_expand "loadti"
9c08d1fa 4070;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4071;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4072;; "" "")
4073
4074;;(define_expand "storeti"
4075;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4076;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4077;; "" "")
4078
4079;;(define_expand "movti"
4080;; [(set (match_operand:TI 0 "general_operand" "")
4081;; (match_operand:TI 1 "general_operand" ""))]
4082;; ""
4083;; "
4084;;{
4085;; rtx insn;
4086;;
4087;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4088;; operands[1] = copy_to_reg (operands[1]);
4089;; if (GET_CODE (operands[0]) == MEM)
4090;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4091;; else if (GET_CODE (operands[1]) == MEM)
4092;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4093;; else
4094;; FAIL;
4095;;
4096;; emit_insn (insn);
4097;; DONE;
4098;;}")
4099
a2f10574 4100;; Recognize garbage generated above.
b11cae9e 4101
4102;;(define_insn ""
4103;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4104;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4105;; ""
4106;; "*
4107;; {
4108;; register mem = (which_alternative < 3);
0d66636f 4109;; register const char *template;
b11cae9e 4110;;
4111;; operands[mem] = XEXP (operands[mem], 0);
4112;; switch (which_alternative)
4113;; {
4114;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4115;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4116;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4117;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4118;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4119;; case 5: template = \"stmia\\t%0, %M1\"; break;
4120;; }
e2348bcb 4121;; output_asm_insn (template, operands);
4122;; return \"\";
b11cae9e 4123;; }")
4124
cffb2a26 4125(define_expand "movdi"
4126 [(set (match_operand:DI 0 "general_operand" "")
4127 (match_operand:DI 1 "general_operand" ""))]
4128 "TARGET_EITHER"
4129 "
4130 if (TARGET_THUMB)
4131 {
215b30b3 4132 if (!no_new_pseudos)
cffb2a26 4133 {
4134 if (GET_CODE (operands[0]) != REG)
4135 operands[1] = force_reg (DImode, operands[1]);
4136 }
4137 }
4138 "
4139)
b11cae9e 4140
cffb2a26 4141(define_insn "*arm_movdi"
d51f92df 4142 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4143 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4144 "TARGET_ARM
4145 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4146 && !TARGET_IWMMXT"
b11cae9e 4147 "*
d51f92df 4148 switch (which_alternative)
4149 {
4150 case 0:
4151 case 1:
4152 case 2:
4153 return \"#\";
4154 default:
4155 return output_move_double (operands);
4156 }
cffb2a26 4157 "
359a6e9f 4158 [(set_attr "length" "8,12,16,8,8")
4159 (set_attr "type" "*,*,*,load2,store2")
4160 (set_attr "pool_range" "*,*,*,1020,*")
4161 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4162)
4163
d51f92df 4164(define_split
4165 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4166 (match_operand:ANY64 1 "const_double_operand" ""))]
4167 "TARGET_ARM
4168 && reload_completed
4169 && (arm_const_double_inline_cost (operands[1])
4170 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4171 [(const_int 0)]
4172 "
4173 arm_split_constant (SET, SImode, curr_insn,
4174 INTVAL (gen_lowpart (SImode, operands[1])),
4175 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4176 arm_split_constant (SET, SImode, curr_insn,
4177 INTVAL (gen_highpart_mode (SImode,
4178 GET_MODE (operands[0]),
4179 operands[1])),
4180 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4181 DONE;
4182 "
4183)
4184
e5ba9289 4185; If optimizing for size, or if we have load delay slots, then
4186; we want to split the constant into two separate operations.
4187; In both cases this may split a trivial part into a single data op
4188; leaving a single complex constant to load. We can also get longer
4189; offsets in a LDR which means we get better chances of sharing the pool
4190; entries. Finally, we can normally do a better job of scheduling
4191; LDR instructions than we can with LDM.
4192; This pattern will only match if the one above did not.
4193(define_split
4194 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4195 (match_operand:ANY64 1 "const_double_operand" ""))]
4196 "TARGET_ARM && reload_completed
4197 && arm_const_double_by_parts (operands[1])"
4198 [(set (match_dup 0) (match_dup 1))
4199 (set (match_dup 2) (match_dup 3))]
4200 "
4201 operands[2] = gen_highpart (SImode, operands[0]);
4202 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4203 operands[1]);
4204 operands[0] = gen_lowpart (SImode, operands[0]);
4205 operands[1] = gen_lowpart (SImode, operands[1]);
4206 "
4207)
4208
d51f92df 4209(define_split
4210 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4211 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4212 "TARGET_EITHER && reload_completed"
4213 [(set (match_dup 0) (match_dup 1))
4214 (set (match_dup 2) (match_dup 3))]
4215 "
4216 operands[2] = gen_highpart (SImode, operands[0]);
4217 operands[3] = gen_highpart (SImode, operands[1]);
4218 operands[0] = gen_lowpart (SImode, operands[0]);
4219 operands[1] = gen_lowpart (SImode, operands[1]);
4220
4221 /* Handle a partial overlap. */
4222 if (rtx_equal_p (operands[0], operands[3]))
4223 {
4224 rtx tmp0 = operands[0];
4225 rtx tmp1 = operands[1];
4226
4227 operands[0] = operands[2];
4228 operands[1] = operands[3];
4229 operands[2] = tmp0;
4230 operands[3] = tmp1;
4231 }
4232 "
4233)
4234
a8a3b539 4235;; We can't actually do base+index doubleword loads if the index and
4236;; destination overlap. Split here so that we at least have chance to
4237;; schedule.
4238(define_split
4239 [(set (match_operand:DI 0 "s_register_operand" "")
4240 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4241 (match_operand:SI 2 "s_register_operand" ""))))]
4242 "TARGET_LDRD
4243 && reg_overlap_mentioned_p (operands[0], operands[1])
4244 && reg_overlap_mentioned_p (operands[0], operands[2])"
4245 [(set (match_dup 4)
4246 (plus:SI (match_dup 1)
4247 (match_dup 2)))
4248 (set (match_dup 0)
4249 (mem:DI (match_dup 4)))]
4250 "
4251 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4252 "
4253)
4254
cffb2a26 4255;;; ??? This should have alternatives for constants.
4256;;; ??? This was originally identical to the movdf_insn pattern.
4257;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4258;;; thumb_reorg with a memory reference.
4259(define_insn "*thumb_movdi_insn"
215b30b3 4260 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4261 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
cffb2a26 4262 "TARGET_THUMB
a2cd141b 4263 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4264 && ( register_operand (operands[0], DImode)
4265 || register_operand (operands[1], DImode))"
4266 "*
4267 {
4268 switch (which_alternative)
4269 {
4270 default:
4271 case 0:
4272 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4273 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4274 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4275 case 1:
4276 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4277 case 2:
4278 operands[1] = GEN_INT (- INTVAL (operands[1]));
4279 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4280 case 3:
4281 return \"ldmia\\t%1, {%0, %H0}\";
4282 case 4:
4283 return \"stmia\\t%0, {%1, %H1}\";
4284 case 5:
4285 return thumb_load_double_from_address (operands);
4286 case 6:
1a83b3ff 4287 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4288 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4289 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4290 return \"\";
4291 case 7:
4292 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4293 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4294 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4295 }
4296 }"
4297 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4298 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4299 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4300)
b11cae9e 4301
9c08d1fa 4302(define_expand "movsi"
4303 [(set (match_operand:SI 0 "general_operand" "")
4304 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4305 "TARGET_EITHER"
9c08d1fa 4306 "
cffb2a26 4307 if (TARGET_ARM)
9c08d1fa 4308 {
674a8f0b 4309 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4310 if (GET_CODE (operands[0]) == MEM)
4311 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4312 if (arm_general_register_operand (operands[0], SImode)
4313 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4314 && !(const_ok_for_arm (INTVAL (operands[1]))
4315 || const_ok_for_arm (~INTVAL (operands[1]))))
4316 {
96f57e36 4317 arm_split_constant (SET, SImode, NULL_RTX,
4318 INTVAL (operands[1]), operands[0], NULL_RTX,
615caa51 4319 optimize && !no_new_pseudos);
cffb2a26 4320 DONE;
4321 }
4322 }
674a8f0b 4323 else /* TARGET_THUMB.... */
cffb2a26 4324 {
215b30b3 4325 if (!no_new_pseudos)
cffb2a26 4326 {
4327 if (GET_CODE (operands[0]) != REG)
4328 operands[1] = force_reg (SImode, operands[1]);
4329 }
9c08d1fa 4330 }
af1b847e 4331
bbe777ea 4332 if (flag_pic
4333 && (CONSTANT_P (operands[1])
4334 || symbol_mentioned_p (operands[1])
4335 || label_mentioned_p (operands[1])))
849170fd 4336 operands[1] = legitimize_pic_address (operands[1], SImode,
935d87ee 4337 (no_new_pseudos ? operands[0] : 0));
215b30b3 4338 "
4339)
9c08d1fa 4340
cffb2a26 4341(define_insn "*arm_movsi_insn"
215b30b3 4342 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4343 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
755eb2b4 4344 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 4345 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 4346 && ( register_operand (operands[0], SImode)
4347 || register_operand (operands[1], SImode))"
f7fbdd4a 4348 "@
4349 mov%?\\t%0, %1
4350 mvn%?\\t%0, #%B1
4351 ldr%?\\t%0, %1
4352 str%?\\t%1, %0"
a2cd141b 4353 [(set_attr "type" "*,*,load1,store1")
0d66636f 4354 (set_attr "predicable" "yes")
cffb2a26 4355 (set_attr "pool_range" "*,*,4096,*")
4356 (set_attr "neg_pool_range" "*,*,4084,*")]
4357)
87b22bf7 4358
4359(define_split
a2cd141b 4360 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 4361 (match_operand:SI 1 "const_int_operand" ""))]
cffb2a26 4362 "TARGET_ARM
215b30b3 4363 && (!(const_ok_for_arm (INTVAL (operands[1]))
4364 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4365 [(clobber (const_int 0))]
4366 "
96f57e36 4367 arm_split_constant (SET, SImode, NULL_RTX,
4368 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 4369 DONE;
215b30b3 4370 "
4371)
9c08d1fa 4372
cffb2a26 4373(define_insn "*thumb_movsi_insn"
215b30b3 4374 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4375 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
cffb2a26 4376 "TARGET_THUMB
4377 && ( register_operand (operands[0], SImode)
4378 || register_operand (operands[1], SImode))"
4379 "@
4380 mov %0, %1
4381 mov %0, %1
4382 #
4383 #
4384 ldmia\\t%1, {%0}
4385 stmia\\t%0, {%1}
4386 ldr\\t%0, %1
4387 str\\t%1, %0
4388 mov\\t%0, %1"
4389 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 4390 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 4391 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4392)
4393
4394(define_split
4395 [(set (match_operand:SI 0 "register_operand" "")
4396 (match_operand:SI 1 "const_int_operand" ""))]
4397 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4398 [(set (match_dup 0) (match_dup 1))
4399 (set (match_dup 0) (neg:SI (match_dup 0)))]
4400 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4401)
4402
4403(define_split
4404 [(set (match_operand:SI 0 "register_operand" "")
4405 (match_operand:SI 1 "const_int_operand" ""))]
4406 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4407 [(set (match_dup 0) (match_dup 1))
4408 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4409 "
4410 {
4411 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4412 unsigned HOST_WIDE_INT mask = 0xff;
4413 int i;
4414
4415 for (i = 0; i < 25; i++)
4416 if ((val & (mask << i)) == val)
4417 break;
4418
f5b3169c 4419 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4420 if (i == 0)
4421 FAIL;
4422
4423 operands[1] = GEN_INT (val >> i);
4424 operands[2] = GEN_INT (i);
4425 }"
4426)
4427
67336bcf 4428;; When generating pic, we need to load the symbol offset into a register.
4429;; So that the optimizer does not confuse this with a normal symbol load
4430;; we use an unspec. The offset will be loaded from a constant pool entry,
4431;; since that is the only type of relocation we can use.
4432
4433;; The rather odd constraints on the following are to force reload to leave
4434;; the insn alone, and to force the minipool generation pass to then move
4435;; the GOT symbol to memory.
849170fd 4436
8c4d8060 4437(define_insn "pic_load_addr_arm"
849170fd 4438 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4439 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4440 "TARGET_ARM && flag_pic"
67336bcf 4441 "ldr%?\\t%0, %1"
a2cd141b 4442 [(set_attr "type" "load1")
8c4d8060 4443 (set (attr "pool_range") (const_int 4096))
4444 (set (attr "neg_pool_range") (const_int 4084))]
4445)
4446
4447(define_insn "pic_load_addr_thumb"
4448 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4449 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4450 "TARGET_THUMB && flag_pic"
4451 "ldr\\t%0, %1"
a2cd141b 4452 [(set_attr "type" "load1")
8c4d8060 4453 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4454)
849170fd 4455
4456;; This variant is used for AOF assembly, since it needs to mention the
4457;; pic register in the rtl.
4458(define_expand "pic_load_addr_based"
7db9af5d 4459 [(set (match_operand:SI 0 "s_register_operand" "")
e1159bbe 4460 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
cffb2a26 4461 "TARGET_ARM && flag_pic"
4462 "operands[2] = pic_offset_table_rtx;"
4463)
849170fd 4464
4465(define_insn "*pic_load_addr_based_insn"
4466 [(set (match_operand:SI 0 "s_register_operand" "=r")
4467 (unspec:SI [(match_operand 1 "" "")
e1159bbe 4468 (match_operand 2 "s_register_operand" "r")]
4469 UNSPEC_PIC_SYM))]
cffb2a26 4470 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
849170fd 4471 "*
4472#ifdef AOF_ASSEMBLER
4473 operands[1] = aof_pic_entry (operands[1]);
4474#endif
4475 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4476 return \"\";
cffb2a26 4477 "
a2cd141b 4478 [(set_attr "type" "load1")
cffb2a26 4479 (set (attr "pool_range")
4480 (if_then_else (eq_attr "is_thumb" "yes")
4481 (const_int 1024)
4482 (const_int 4096)))
4483 (set (attr "neg_pool_range")
4484 (if_then_else (eq_attr "is_thumb" "yes")
4485 (const_int 0)
4486 (const_int 4084)))]
4487)
4488
4489(define_insn "pic_add_dot_plus_four"
4490 [(set (match_operand:SI 0 "register_operand" "+r")
2c96dc5a 4491 (unspec:SI [(plus:SI (match_dup 0)
4492 (const (plus:SI (pc) (const_int 4))))]
4493 UNSPEC_PIC_BASE))
cffb2a26 4494 (use (label_ref (match_operand 1 "" "")))]
4495 "TARGET_THUMB && flag_pic"
4496 "*
805e22b2 4497 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
cffb2a26 4498 CODE_LABEL_NUMBER (operands[1]));
4499 return \"add\\t%0, %|pc\";
4500 "
4501 [(set_attr "length" "2")]
4502)
849170fd 4503
4504(define_insn "pic_add_dot_plus_eight"
6c4c2133 4505 [(set (match_operand:SI 0 "register_operand" "+r")
2c96dc5a 4506 (unspec:SI [(plus:SI (match_dup 0)
4507 (const (plus:SI (pc) (const_int 8))))]
4508 UNSPEC_PIC_BASE))
c4034607 4509 (use (label_ref (match_operand 1 "" "")))]
cffb2a26 4510 "TARGET_ARM && flag_pic"
c4034607 4511 "*
805e22b2 4512 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
0d66636f 4513 CODE_LABEL_NUMBER (operands[1]));
4514 return \"add%?\\t%0, %|pc, %0\";
cffb2a26 4515 "
0d66636f 4516 [(set_attr "predicable" "yes")]
cffb2a26 4517)
849170fd 4518
95373f08 4519(define_expand "builtin_setjmp_receiver"
4520 [(label_ref (match_operand 0 "" ""))]
4521 "flag_pic"
4522 "
4523{
b935b306 4524 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4525 register. */
4526 arm_load_pic_register (3);
95373f08 4527 DONE;
4528}")
4529
9c08d1fa 4530;; If copying one reg to another we can set the condition codes according to
4531;; its value. Such a move is common after a return from subroutine and the
4532;; result is being tested against zero.
4533
f7fbdd4a 4534(define_insn "*movsi_compare0"
bd5b4116 4535 [(set (reg:CC CC_REGNUM)
cffb2a26 4536 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4537 (const_int 0)))
4538 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4539 (match_dup 1))]
4540 "TARGET_ARM"
e2348bcb 4541 "@
40dbec34 4542 cmp%?\\t%0, #0
4543 sub%?s\\t%0, %1, #0"
cffb2a26 4544 [(set_attr "conds" "set")]
4545)
b11cae9e 4546
b11cae9e 4547;; Subroutine to store a half word from a register into memory.
4548;; Operand 0 is the source register (HImode)
c8f69309 4549;; Operand 1 is the destination address in a register (SImode)
b11cae9e 4550
9c08d1fa 4551;; In both this routine and the next, we must be careful not to spill
01cc3b75 4552;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 4553;; can generate unrecognizable rtl.
4554
b11cae9e 4555(define_expand "storehi"
c8f69309 4556 [;; store the low byte
f082f1c4 4557 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 4558 ;; extract the high byte
c8f69309 4559 (set (match_dup 2)
4560 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 4561 ;; store the high byte
787f8210 4562 (set (match_dup 4) (match_dup 5))]
cffb2a26 4563 "TARGET_ARM"
b11cae9e 4564 "
215b30b3 4565 {
537ffcfc 4566 rtx op1 = operands[1];
4567 rtx addr = XEXP (op1, 0);
215b30b3 4568 enum rtx_code code = GET_CODE (addr);
4569
4570 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4571 || code == MINUS)
537ffcfc 4572 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 4573
537ffcfc 4574 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4575 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4576 operands[3] = gen_lowpart (QImode, operands[0]);
4577 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 4578 operands[2] = gen_reg_rtx (SImode);
4579 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4580 }"
4581)
b11cae9e 4582
c7597b5d 4583(define_expand "storehi_bigend"
f082f1c4 4584 [(set (match_dup 4) (match_dup 3))
c7597b5d 4585 (set (match_dup 2)
4586 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 4587 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 4588 "TARGET_ARM"
b11cae9e 4589 "
215b30b3 4590 {
537ffcfc 4591 rtx op1 = operands[1];
4592 rtx addr = XEXP (op1, 0);
215b30b3 4593 enum rtx_code code = GET_CODE (addr);
4594
4595 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4596 || code == MINUS)
537ffcfc 4597 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 4598
537ffcfc 4599 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4600 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4601 operands[3] = gen_lowpart (QImode, operands[0]);
4602 operands[0] = gen_lowpart (SImode, operands[0]);
4603 operands[2] = gen_reg_rtx (SImode);
787f8210 4604 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4605 }"
4606)
c7597b5d 4607
4608;; Subroutine to store a half word integer constant into memory.
4609(define_expand "storeinthi"
f082f1c4 4610 [(set (match_operand 0 "" "")
787f8210 4611 (match_operand 1 "" ""))
9e8503e6 4612 (set (match_dup 3) (match_dup 2))]
cffb2a26 4613 "TARGET_ARM"
c7597b5d 4614 "
215b30b3 4615 {
4616 HOST_WIDE_INT value = INTVAL (operands[1]);
4617 rtx addr = XEXP (operands[0], 0);
537ffcfc 4618 rtx op0 = operands[0];
215b30b3 4619 enum rtx_code code = GET_CODE (addr);
c7597b5d 4620
215b30b3 4621 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4622 || code == MINUS)
537ffcfc 4623 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 4624
215b30b3 4625 operands[1] = gen_reg_rtx (SImode);
4626 if (BYTES_BIG_ENDIAN)
4627 {
4628 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4629 if ((value & 255) == ((value >> 8) & 255))
4630 operands[2] = operands[1];
4631 else
4632 {
4633 operands[2] = gen_reg_rtx (SImode);
4634 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4635 }
4636 }
4637 else
4638 {
4639 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4640 if ((value & 255) == ((value >> 8) & 255))
4641 operands[2] = operands[1];
4642 else
4643 {
4644 operands[2] = gen_reg_rtx (SImode);
4645 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4646 }
4647 }
c7597b5d 4648
537ffcfc 4649 operands[3] = adjust_address (op0, QImode, 1);
e513d163 4650 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 4651 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 4652 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 4653 }"
4654)
b11cae9e 4655
f7fbdd4a 4656(define_expand "storehi_single_op"
4657 [(set (match_operand:HI 0 "memory_operand" "")
4658 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4659 "TARGET_ARM && arm_arch4"
f7fbdd4a 4660 "
215b30b3 4661 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 4662 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 4663 "
4664)
f7fbdd4a 4665
b11cae9e 4666(define_expand "movhi"
4667 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 4668 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4669 "TARGET_EITHER"
b11cae9e 4670 "
cffb2a26 4671 if (TARGET_ARM)
b11cae9e 4672 {
215b30b3 4673 if (!no_new_pseudos)
cffb2a26 4674 {
4675 if (GET_CODE (operands[0]) == MEM)
b11cae9e 4676 {
cffb2a26 4677 if (arm_arch4)
4678 {
4679 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4680 DONE;
4681 }
4682 if (GET_CODE (operands[1]) == CONST_INT)
4683 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 4684 else
cffb2a26 4685 {
4686 if (GET_CODE (operands[1]) == MEM)
4687 operands[1] = force_reg (HImode, operands[1]);
4688 if (BYTES_BIG_ENDIAN)
4689 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4690 else
4691 emit_insn (gen_storehi (operands[1], operands[0]));
4692 }
4693 DONE;
b11cae9e 4694 }
cffb2a26 4695 /* Sign extend a constant, and keep it in an SImode reg. */
4696 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 4697 {
cffb2a26 4698 rtx reg = gen_reg_rtx (SImode);
4699 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4700
4701 /* If the constant is already valid, leave it alone. */
215b30b3 4702 if (!const_ok_for_arm (val))
cffb2a26 4703 {
4704 /* If setting all the top bits will make the constant
4705 loadable in a single instruction, then set them.
4706 Otherwise, sign extend the number. */
4707
215b30b3 4708 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 4709 val |= ~0xffff;
4710 else if (val & 0x8000)
4711 val |= ~0xffff;
4712 }
4713
4714 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 4715 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 4716 }
615caa51 4717 else if (arm_arch4 && optimize && !no_new_pseudos
0045890a 4718 && GET_CODE (operands[1]) == MEM)
4719 {
4720 rtx reg = gen_reg_rtx (SImode);
4721
4722 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4723 operands[1] = gen_lowpart (HImode, reg);
4724 }
215b30b3 4725 else if (!arm_arch4)
f7fbdd4a 4726 {
cffb2a26 4727 if (GET_CODE (operands[1]) == MEM)
4728 {
c1a66faf 4729 rtx base;
4730 rtx offset = const0_rtx;
4731 rtx reg = gen_reg_rtx (SImode);
4732
4733 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4734 || (GET_CODE (base) == PLUS
4735 && (GET_CODE (offset = XEXP (base, 1))
4736 == CONST_INT)
4737 && ((INTVAL(offset) & 1) != 1)
4738 && GET_CODE (base = XEXP (base, 0)) == REG))
4739 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 4740 {
c1a66faf 4741 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4742 rtx new;
4743
4744 new = gen_rtx_MEM (SImode,
4745 plus_constant (base, new_offset));
4746 MEM_COPY_ATTRIBUTES (new, operands[1]);
4747 emit_insn (gen_movsi (reg, new));
4748 if (((INTVAL (offset) & 2) != 0)
4749 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4750 {
4751 rtx reg2 = gen_reg_rtx (SImode);
4752
4753 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4754 reg = reg2;
4755 }
206ee9a2 4756 }
c1a66faf 4757 else
4758 emit_insn (gen_movhi_bytes (reg, operands[1]));
4759
4760 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 4761 }
4762 }
4763 }
674a8f0b 4764 /* Handle loading a large integer during reload. */
cffb2a26 4765 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4766 && !const_ok_for_arm (INTVAL (operands[1]))
4767 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 4768 {
4769 /* Writing a constant to memory needs a scratch, which should
4770 be handled with SECONDARY_RELOADs. */
ed29c566 4771 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 4772
4773 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4774 emit_insn (gen_movsi (operands[0], operands[1]));
4775 DONE;
4776 }
4777 }
4778 else /* TARGET_THUMB */
4779 {
215b30b3 4780 if (!no_new_pseudos)
cffb2a26 4781 {
4782 if (GET_CODE (operands[0]) != REG)
4783 operands[1] = force_reg (HImode, operands[1]);
4784
4785 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4786 happen if we are passed a SP (never OK for HImode/QImode) or
4787 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4788 HImode/QImode) relative address. */
cffb2a26 4789 /* ??? This should perhaps be fixed elsewhere, for instance, in
4790 fixup_stack_1, by checking for other kinds of invalid addresses,
4791 e.g. a bare reference to a virtual register. This may confuse the
4792 alpha though, which must handle this case differently. */
4793 if (GET_CODE (operands[0]) == MEM
215b30b3 4794 && !memory_address_p (GET_MODE (operands[0]),
4795 XEXP (operands[0], 0)))
537ffcfc 4796 operands[0]
4797 = replace_equiv_address (operands[0],
4798 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 4799
4800 if (GET_CODE (operands[1]) == MEM
215b30b3 4801 && !memory_address_p (GET_MODE (operands[1]),
4802 XEXP (operands[1], 0)))
537ffcfc 4803 operands[1]
4804 = replace_equiv_address (operands[1],
4805 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 4806 }
674a8f0b 4807 /* Handle loading a large integer during reload. */
cffb2a26 4808 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4809 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
cffb2a26 4810 {
4811 /* Writing a constant to memory needs a scratch, which should
4812 be handled with SECONDARY_RELOADs. */
ed29c566 4813 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 4814
1a83b3ff 4815 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 4816 emit_insn (gen_movsi (operands[0], operands[1]));
4817 DONE;
4818 }
b11cae9e 4819 }
cffb2a26 4820 "
4821)
4822
4823(define_insn "*thumb_movhi_insn"
a941568e 4824 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4825 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
cffb2a26 4826 "TARGET_THUMB
4827 && ( register_operand (operands[0], HImode)
4828 || register_operand (operands[1], HImode))"
4829 "*
4830 switch (which_alternative)
d79300ac 4831 {
cffb2a26 4832 case 0: return \"add %0, %1, #0\";
4833 case 2: return \"strh %1, %0\";
4834 case 3: return \"mov %0, %1\";
4835 case 4: return \"mov %0, %1\";
4836 case 5: return \"mov %0, %1\";
ed29c566 4837 default: gcc_unreachable ();
cffb2a26 4838 case 1:
4839 /* The stack pointer can end up being taken as an index register.
4840 Catch this case here and deal with it. */
4841 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4842 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4843 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4844 {
4845 rtx ops[2];
4846 ops[0] = operands[0];
4847 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4848
4849 output_asm_insn (\"mov %0, %1\", ops);
4850
4851 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4852
4853 }
4854 return \"ldrh %0, %1\";
4855 }"
4856 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 4857 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 4858)
d79300ac 4859
b11cae9e 4860
25f7a26e 4861(define_expand "movhi_bytes"
eab14235 4862 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4863 (set (match_dup 3)
eab14235 4864 (zero_extend:SI (match_dup 6)))
25f7a26e 4865 (set (match_operand:SI 0 "" "")
4866 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 4867 "TARGET_ARM"
25f7a26e 4868 "
215b30b3 4869 {
4870 rtx mem1, mem2;
4871 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4872
4873 mem1 = gen_rtx_MEM (QImode, addr);
4874 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4875 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4876 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4877 operands[0] = gen_lowpart (SImode, operands[0]);
4878 operands[1] = mem1;
4879 operands[2] = gen_reg_rtx (SImode);
4880 operands[3] = gen_reg_rtx (SImode);
4881 operands[6] = mem2;
25f7a26e 4882
215b30b3 4883 if (BYTES_BIG_ENDIAN)
4884 {
4885 operands[4] = operands[2];
4886 operands[5] = operands[3];
4887 }
4888 else
4889 {
4890 operands[4] = operands[3];
4891 operands[5] = operands[2];
4892 }
4893 }"
4894)
25f7a26e 4895
c7597b5d 4896(define_expand "movhi_bigend"
4897 [(set (match_dup 2)
4898 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4899 (const_int 16)))
4900 (set (match_dup 3)
4901 (ashiftrt:SI (match_dup 2) (const_int 16)))
4902 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 4903 (match_dup 4))]
cffb2a26 4904 "TARGET_ARM"
c7597b5d 4905 "
4906 operands[2] = gen_reg_rtx (SImode);
4907 operands[3] = gen_reg_rtx (SImode);
787f8210 4908 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 4909 "
4910)
b11cae9e 4911
a2f10574 4912;; Pattern to recognize insn generated default case above
f7fbdd4a 4913(define_insn "*movhi_insn_arch4"
cffb2a26 4914 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 4915 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 4916 "TARGET_ARM
4917 && arm_arch4
f7fbdd4a 4918 && (GET_CODE (operands[1]) != CONST_INT
4919 || const_ok_for_arm (INTVAL (operands[1]))
4920 || const_ok_for_arm (~INTVAL (operands[1])))"
4921 "@
4922 mov%?\\t%0, %1\\t%@ movhi
4923 mvn%?\\t%0, #%B1\\t%@ movhi
aed179ae 4924 str%?h\\t%1, %0\\t%@ movhi
cffb2a26 4925 ldr%?h\\t%0, %1\\t%@ movhi"
a2cd141b 4926 [(set_attr "type" "*,*,store1,load1")
0d66636f 4927 (set_attr "predicable" "yes")
cffb2a26 4928 (set_attr "pool_range" "*,*,*,256")
4929 (set_attr "neg_pool_range" "*,*,*,244")]
4930)
f7fbdd4a 4931
f7fbdd4a 4932(define_insn "*movhi_bytes"
25f7a26e 4933 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4934 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 4935 "TARGET_ARM"
25f7a26e 4936 "@
4937 mov%?\\t%0, %1\\t%@ movhi
0d66636f 4938 mvn%?\\t%0, #%B1\\t%@ movhi"
4939 [(set_attr "predicable" "yes")]
4940)
25f7a26e 4941
cffb2a26 4942(define_insn "thumb_movhi_clobber"
4943 [(set (match_operand:HI 0 "memory_operand" "=m")
4944 (match_operand:HI 1 "register_operand" "l"))
4945 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4946 "TARGET_THUMB"
344495ea 4947 "*
ed29c566 4948 gcc_unreachable ();"
cffb2a26 4949)
4950
bc5c7e08 4951;; We use a DImode scratch because we may occasionally need an additional
4952;; temporary if the address isn't offsettable -- push_reload doesn't seem
4953;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 4954(define_expand "reload_outhi"
cffb2a26 4955 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 4956 (match_operand:HI 1 "s_register_operand" "r")
4957 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 4958 "TARGET_EITHER"
4959 "if (TARGET_ARM)
4960 arm_reload_out_hi (operands);
4961 else
4962 thumb_reload_out_hi (operands);
d3373b54 4963 DONE;
cffb2a26 4964 "
4965)
d3373b54 4966
25f7a26e 4967(define_expand "reload_inhi"
4968 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 4969 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 4970 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 4971 "TARGET_EITHER"
25f7a26e 4972 "
cffb2a26 4973 if (TARGET_ARM)
4974 arm_reload_in_hi (operands);
4975 else
4976 thumb_reload_out_hi (operands);
25f7a26e 4977 DONE;
4978")
4979
9c08d1fa 4980(define_expand "movqi"
4981 [(set (match_operand:QI 0 "general_operand" "")
4982 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 4983 "TARGET_EITHER"
9c08d1fa 4984 "
cffb2a26 4985 if (TARGET_ARM)
9c08d1fa 4986 {
cffb2a26 4987 /* Everything except mem = const or mem = mem can be done easily */
c7597b5d 4988
935d87ee 4989 if (!no_new_pseudos)
cffb2a26 4990 {
4991 if (GET_CODE (operands[1]) == CONST_INT)
4992 {
4993 rtx reg = gen_reg_rtx (SImode);
4994
4995 emit_insn (gen_movsi (reg, operands[1]));
9e8503e6 4996 operands[1] = gen_lowpart (QImode, reg);
cffb2a26 4997 }
0045890a 4998 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4999 {
5000 rtx reg = gen_reg_rtx (SImode);
5001
5002 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5003 operands[1] = gen_lowpart (QImode, reg);
5004 }
5005 if (GET_CODE (operands[0]) == MEM)
5006 operands[1] = force_reg (QImode, operands[1]);
5007 }
b11cae9e 5008 }
cffb2a26 5009 else /* TARGET_THUMB */
5010 {
215b30b3 5011 if (!no_new_pseudos)
cffb2a26 5012 {
5013 if (GET_CODE (operands[0]) != REG)
5014 operands[1] = force_reg (QImode, operands[1]);
5015
5016 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5017 happen if we are passed a SP (never OK for HImode/QImode) or
5018 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5019 HImode/QImode) relative address. */
cffb2a26 5020 /* ??? This should perhaps be fixed elsewhere, for instance, in
5021 fixup_stack_1, by checking for other kinds of invalid addresses,
5022 e.g. a bare reference to a virtual register. This may confuse the
5023 alpha though, which must handle this case differently. */
5024 if (GET_CODE (operands[0]) == MEM
215b30b3 5025 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5026 XEXP (operands[0], 0)))
537ffcfc 5027 operands[0]
5028 = replace_equiv_address (operands[0],
5029 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5030 if (GET_CODE (operands[1]) == MEM
5031 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5032 XEXP (operands[1], 0)))
537ffcfc 5033 operands[1]
5034 = replace_equiv_address (operands[1],
5035 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 5036 }
674a8f0b 5037 /* Handle loading a large integer during reload. */
cffb2a26 5038 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5039 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
cffb2a26 5040 {
5041 /* Writing a constant to memory needs a scratch, which should
5042 be handled with SECONDARY_RELOADs. */
ed29c566 5043 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 5044
9e8503e6 5045 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5046 emit_insn (gen_movsi (operands[0], operands[1]));
5047 DONE;
5048 }
5049 }
5050 "
5051)
b11cae9e 5052
9c08d1fa 5053
cffb2a26 5054(define_insn "*arm_movqi_insn"
5055 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5056 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
cffb2a26 5057 "TARGET_ARM
5058 && ( register_operand (operands[0], QImode)
5059 || register_operand (operands[1], QImode))"
5565501b 5060 "@
5061 mov%?\\t%0, %1
5062 mvn%?\\t%0, #%B1
5063 ldr%?b\\t%0, %1
5064 str%?b\\t%1, %0"
a2cd141b 5065 [(set_attr "type" "*,*,load1,store1")
0d66636f 5066 (set_attr "predicable" "yes")]
cffb2a26 5067)
5068
5069(define_insn "*thumb_movqi_insn"
5070 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5071 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
cffb2a26 5072 "TARGET_THUMB
5073 && ( register_operand (operands[0], QImode)
5074 || register_operand (operands[1], QImode))"
5075 "@
5076 add\\t%0, %1, #0
5077 ldrb\\t%0, %1
5078 strb\\t%1, %0
5079 mov\\t%0, %1
5080 mov\\t%0, %1
5081 mov\\t%0, %1"
5082 [(set_attr "length" "2")
a2cd141b 5083 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5084 (set_attr "pool_range" "*,32,*,*,*,*")]
5085)
b11cae9e 5086
87b22bf7 5087(define_expand "movsf"
5088 [(set (match_operand:SF 0 "general_operand" "")
5089 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5090 "TARGET_EITHER"
87b22bf7 5091 "
cffb2a26 5092 if (TARGET_ARM)
5093 {
5094 if (GET_CODE (operands[0]) == MEM)
5095 operands[1] = force_reg (SFmode, operands[1]);
5096 }
5097 else /* TARGET_THUMB */
5098 {
215b30b3 5099 if (!no_new_pseudos)
cffb2a26 5100 {
5101 if (GET_CODE (operands[0]) != REG)
5102 operands[1] = force_reg (SFmode, operands[1]);
5103 }
5104 }
5105 "
5106)
5107
5108(define_split
5109 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5110 (match_operand:SF 1 "immediate_operand" ""))]
5111 "TARGET_ARM
a2cd141b 5112 && !(TARGET_HARD_FLOAT && TARGET_FPA)
cffb2a26 5113 && reload_completed
5114 && GET_CODE (operands[1]) == CONST_DOUBLE"
5115 [(set (match_dup 2) (match_dup 3))]
5116 "
5117 operands[2] = gen_lowpart (SImode, operands[0]);
5118 operands[3] = gen_lowpart (SImode, operands[1]);
5119 if (operands[2] == 0 || operands[3] == 0)
5120 FAIL;
215b30b3 5121 "
5122)
87b22bf7 5123
cffb2a26 5124(define_insn "*arm_movsf_soft_insn"
5125 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5126 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5127 "TARGET_ARM
5128 && TARGET_SOFT_FLOAT
215b30b3 5129 && (GET_CODE (operands[0]) != MEM
5130 || register_operand (operands[1], SFmode))"
9a1112d7 5131 "@
5132 mov%?\\t%0, %1
5133 ldr%?\\t%0, %1\\t%@ float
5134 str%?\\t%1, %0\\t%@ float"
cffb2a26 5135 [(set_attr "length" "4,4,4")
0d66636f 5136 (set_attr "predicable" "yes")
a2cd141b 5137 (set_attr "type" "*,load1,store1")
cffb2a26 5138 (set_attr "pool_range" "*,4096,*")
5139 (set_attr "neg_pool_range" "*,4084,*")]
5140)
5141
5142;;; ??? This should have alternatives for constants.
5143(define_insn "*thumb_movsf_insn"
215b30b3 5144 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5145 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
cffb2a26 5146 "TARGET_THUMB
5147 && ( register_operand (operands[0], SFmode)
5148 || register_operand (operands[1], SFmode))"
5149 "@
5150 add\\t%0, %1, #0
5151 ldmia\\t%1, {%0}
5152 stmia\\t%0, {%1}
5153 ldr\\t%0, %1
5154 str\\t%1, %0
5155 mov\\t%0, %1
5156 mov\\t%0, %1"
5157 [(set_attr "length" "2")
a2cd141b 5158 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5159 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5160)
9a1112d7 5161
9c08d1fa 5162(define_expand "movdf"
87b22bf7 5163 [(set (match_operand:DF 0 "general_operand" "")
5164 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5165 "TARGET_EITHER"
9c08d1fa 5166 "
cffb2a26 5167 if (TARGET_ARM)
5168 {
5169 if (GET_CODE (operands[0]) == MEM)
5170 operands[1] = force_reg (DFmode, operands[1]);
5171 }
5172 else /* TARGET_THUMB */
5173 {
215b30b3 5174 if (!no_new_pseudos)
cffb2a26 5175 {
5176 if (GET_CODE (operands[0]) != REG)
5177 operands[1] = force_reg (DFmode, operands[1]);
5178 }
5179 }
5180 "
5181)
b11cae9e 5182
9c08d1fa 5183;; Reloading a df mode value stored in integer regs to memory can require a
5184;; scratch reg.
5185(define_expand "reload_outdf"
cffb2a26 5186 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5187 (match_operand:DF 1 "s_register_operand" "r")
5188 (match_operand:SI 2 "s_register_operand" "=&r")]
cffb2a26 5189 "TARGET_ARM"
87b22bf7 5190 "
215b30b3 5191 {
5192 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5193
215b30b3 5194 if (code == REG)
5195 operands[2] = XEXP (operands[0], 0);
5196 else if (code == POST_INC || code == PRE_DEC)
5197 {
5198 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5199 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5200 emit_insn (gen_movdi (operands[0], operands[1]));
5201 DONE;
5202 }
5203 else if (code == PRE_INC)
5204 {
5205 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5206
215b30b3 5207 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5208 operands[2] = reg;
5209 }
5210 else if (code == POST_DEC)
5211 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5212 else
5213 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5214 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5215
215b30b3 5216 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5217 operands[1]));
f7fbdd4a 5218
215b30b3 5219 if (code == POST_DEC)
5220 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5221
5222 DONE;
5223 }"
5224)
9c08d1fa 5225
9a1112d7 5226(define_insn "*movdf_soft_insn"
359a6e9f 5227 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5228 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 5229 "TARGET_ARM && TARGET_SOFT_FLOAT
5230 "
d51f92df 5231 "*
5232 switch (which_alternative)
5233 {
5234 case 0:
5235 case 1:
5236 case 2:
5237 return \"#\";
5238 default:
5239 return output_move_double (operands);
5240 }
5241 "
359a6e9f 5242 [(set_attr "length" "8,12,16,8,8")
5243 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 5244 (set_attr "pool_range" "1020")
5245 (set_attr "neg_pool_range" "1008")]
cffb2a26 5246)
5247
5248;;; ??? This should have alternatives for constants.
5249;;; ??? This was originally identical to the movdi_insn pattern.
5250;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5251;;; thumb_reorg with a memory reference.
5252(define_insn "*thumb_movdf_insn"
215b30b3 5253 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5254 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
cffb2a26 5255 "TARGET_THUMB
5256 && ( register_operand (operands[0], DFmode)
5257 || register_operand (operands[1], DFmode))"
5258 "*
5259 switch (which_alternative)
5260 {
5261 default:
5262 case 0:
5263 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5264 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5265 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5266 case 1:
5267 return \"ldmia\\t%1, {%0, %H0}\";
5268 case 2:
5269 return \"stmia\\t%0, {%1, %H1}\";
5270 case 3:
5271 return thumb_load_double_from_address (operands);
5272 case 4:
1a83b3ff 5273 operands[2] = gen_rtx_MEM (SImode,
5274 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5275 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5276 return \"\";
5277 case 5:
5278 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5279 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5280 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5281 }
5282 "
5283 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 5284 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 5285 (set_attr "pool_range" "*,*,*,1020,*,*")]
5286)
755eb2b4 5287
ccd90aaa 5288(define_expand "movxf"
5289 [(set (match_operand:XF 0 "general_operand" "")
5290 (match_operand:XF 1 "general_operand" ""))]
5291 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5292 "
5293 if (GET_CODE (operands[0]) == MEM)
5294 operands[1] = force_reg (XFmode, operands[1]);
5295 "
5296)
5297
755eb2b4 5298;; Vector Moves
5299(define_expand "movv2si"
5300 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5301 (match_operand:V2SI 1 "general_operand" ""))]
5302 "TARGET_REALLY_IWMMXT"
5303{
5304})
5305
5306(define_expand "movv4hi"
5307 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5308 (match_operand:V4HI 1 "general_operand" ""))]
5309 "TARGET_REALLY_IWMMXT"
5310{
5311})
5312
5313(define_expand "movv8qi"
5314 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5315 (match_operand:V8QI 1 "general_operand" ""))]
5316 "TARGET_REALLY_IWMMXT"
5317{
5318})
b11cae9e 5319\f
b11cae9e 5320
9c08d1fa 5321;; load- and store-multiple insns
5322;; The arm can load/store any set of registers, provided that they are in
5323;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5324
9c08d1fa 5325(define_expand "load_multiple"
5326 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5327 (match_operand:SI 1 "" ""))
5328 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5329 "TARGET_ARM"
9580c25f 5330{
5331 HOST_WIDE_INT offset = 0;
5332
bd5b4116 5333 /* Support only fixed point registers. */
9c08d1fa 5334 if (GET_CODE (operands[2]) != CONST_INT
5335 || INTVAL (operands[2]) > 14
5336 || INTVAL (operands[2]) < 2
5337 || GET_CODE (operands[1]) != MEM
5338 || GET_CODE (operands[0]) != REG
bd5b4116 5339 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5340 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5341 FAIL;
5342
5343 operands[3]
f082f1c4 5344 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5345 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 5346 TRUE, FALSE, operands[1], &offset);
5347})
b11cae9e 5348
9c08d1fa 5349;; Load multiple with write-back
5350
2162064c 5351(define_insn "*ldmsi_postinc4"
9c08d1fa 5352 [(match_parallel 0 "load_multiple_operation"
13e9316a 5353 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5354 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5355 (const_int 16)))
5356 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5357 (mem:SI (match_dup 2)))
a0a72ac3 5358 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5359 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5360 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5361 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5362 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5363 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5364 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5365 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
a2cd141b 5366 [(set_attr "type" "load4")
2162064c 5367 (set_attr "predicable" "yes")]
5368)
b11cae9e 5369
ccd90aaa 5370(define_insn "*ldmsi_postinc4_thumb"
5371 [(match_parallel 0 "load_multiple_operation"
5372 [(set (match_operand:SI 1 "s_register_operand" "=l")
5373 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5374 (const_int 16)))
5375 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5376 (mem:SI (match_dup 2)))
5377 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5378 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5379 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5380 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5381 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5382 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5383 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5384 "ldmia\\t%1!, {%3, %4, %5, %6}"
5385 [(set_attr "type" "load4")]
5386)
5387
2162064c 5388(define_insn "*ldmsi_postinc3"
5389 [(match_parallel 0 "load_multiple_operation"
13e9316a 5390 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5391 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5392 (const_int 12)))
5393 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5394 (mem:SI (match_dup 2)))
5395 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5396 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5397 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5398 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5399 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5400 "ldm%?ia\\t%1!, {%3, %4, %5}"
a2cd141b 5401 [(set_attr "type" "load3")
2162064c 5402 (set_attr "predicable" "yes")]
5403)
b11cae9e 5404
2162064c 5405(define_insn "*ldmsi_postinc2"
5406 [(match_parallel 0 "load_multiple_operation"
13e9316a 5407 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5408 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5409 (const_int 8)))
5410 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5411 (mem:SI (match_dup 2)))
5412 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5413 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5414 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5415 "ldm%?ia\\t%1!, {%3, %4}"
a2cd141b 5416 [(set_attr "type" "load2")
0d66636f 5417 (set_attr "predicable" "yes")]
5418)
b11cae9e 5419
9c08d1fa 5420;; Ordinary load multiple
b11cae9e 5421
2162064c 5422(define_insn "*ldmsi4"
9c08d1fa 5423 [(match_parallel 0 "load_multiple_operation"
2162064c 5424 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5425 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5426 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5427 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5428 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5429 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5430 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5431 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5432 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5433 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
a2cd141b 5434 [(set_attr "type" "load4")
2162064c 5435 (set_attr "predicable" "yes")]
5436)
9c08d1fa 5437
2162064c 5438(define_insn "*ldmsi3"
5439 [(match_parallel 0 "load_multiple_operation"
5440 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5441 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5442 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5443 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5444 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5445 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5446 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5447 "ldm%?ia\\t%1, {%2, %3, %4}"
a2cd141b 5448 [(set_attr "type" "load3")
2162064c 5449 (set_attr "predicable" "yes")]
5450)
9c08d1fa 5451
2162064c 5452(define_insn "*ldmsi2"
5453 [(match_parallel 0 "load_multiple_operation"
5454 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5455 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5456 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5457 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5458 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5459 "ldm%?ia\\t%1, {%2, %3}"
a2cd141b 5460 [(set_attr "type" "load2")
0d66636f 5461 (set_attr "predicable" "yes")]
5462)
9c08d1fa 5463
5464(define_expand "store_multiple"
5465 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5466 (match_operand:SI 1 "" ""))
5467 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5468 "TARGET_ARM"
9580c25f 5469{
5470 HOST_WIDE_INT offset = 0;
5471
674a8f0b 5472 /* Support only fixed point registers. */
9c08d1fa 5473 if (GET_CODE (operands[2]) != CONST_INT
5474 || INTVAL (operands[2]) > 14
5475 || INTVAL (operands[2]) < 2
5476 || GET_CODE (operands[1]) != REG
5477 || GET_CODE (operands[0]) != MEM
bd5b4116 5478 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5479 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5480 FAIL;
5481
5482 operands[3]
f082f1c4 5483 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5484 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 5485 TRUE, FALSE, operands[0], &offset);
5486})
b11cae9e 5487
9c08d1fa 5488;; Store multiple with write-back
5489
2162064c 5490(define_insn "*stmsi_postinc4"
9c08d1fa 5491 [(match_parallel 0 "store_multiple_operation"
13e9316a 5492 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5493 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5494 (const_int 16)))
a0a72ac3 5495 (set (mem:SI (match_dup 2))
2162064c 5496 (match_operand:SI 3 "arm_hard_register_operand" ""))
5497 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5498 (match_operand:SI 4 "arm_hard_register_operand" ""))
5499 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5500 (match_operand:SI 5 "arm_hard_register_operand" ""))
5501 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5502 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5503 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5504 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5505 [(set_attr "predicable" "yes")
5506 (set_attr "type" "store4")]
5507)
b11cae9e 5508
ccd90aaa 5509(define_insn "*stmsi_postinc4_thumb"
5510 [(match_parallel 0 "store_multiple_operation"
5511 [(set (match_operand:SI 1 "s_register_operand" "=l")
5512 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5513 (const_int 16)))
5514 (set (mem:SI (match_dup 2))
5515 (match_operand:SI 3 "arm_hard_register_operand" ""))
5516 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5517 (match_operand:SI 4 "arm_hard_register_operand" ""))
5518 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5519 (match_operand:SI 5 "arm_hard_register_operand" ""))
5520 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5521 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5522 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5523 "stmia\\t%1!, {%3, %4, %5, %6}"
5524 [(set_attr "type" "store4")]
5525)
5526
2162064c 5527(define_insn "*stmsi_postinc3"
5528 [(match_parallel 0 "store_multiple_operation"
13e9316a 5529 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5530 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5531 (const_int 12)))
5532 (set (mem:SI (match_dup 2))
5533 (match_operand:SI 3 "arm_hard_register_operand" ""))
5534 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5535 (match_operand:SI 4 "arm_hard_register_operand" ""))
5536 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5537 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5538 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5539 "stm%?ia\\t%1!, {%3, %4, %5}"
5540 [(set_attr "predicable" "yes")
5541 (set_attr "type" "store3")]
5542)
9c08d1fa 5543
2162064c 5544(define_insn "*stmsi_postinc2"
5545 [(match_parallel 0 "store_multiple_operation"
13e9316a 5546 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5547 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5548 (const_int 8)))
5549 (set (mem:SI (match_dup 2))
5550 (match_operand:SI 3 "arm_hard_register_operand" ""))
5551 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5552 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5553 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5554 "stm%?ia\\t%1!, {%3, %4}"
0d66636f 5555 [(set_attr "predicable" "yes")
2162064c 5556 (set_attr "type" "store2")]
cffb2a26 5557)
9c08d1fa 5558
5559;; Ordinary store multiple
5560
2162064c 5561(define_insn "*stmsi4"
9c08d1fa 5562 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 5563 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 5564 (match_operand:SI 2 "arm_hard_register_operand" ""))
5565 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5566 (match_operand:SI 3 "arm_hard_register_operand" ""))
5567 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5568 (match_operand:SI 4 "arm_hard_register_operand" ""))
5569 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5570 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5571 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5572 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5573 [(set_attr "predicable" "yes")
5574 (set_attr "type" "store4")]
5575)
9c08d1fa 5576
2162064c 5577(define_insn "*stmsi3"
5578 [(match_parallel 0 "store_multiple_operation"
5579 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5580 (match_operand:SI 2 "arm_hard_register_operand" ""))
5581 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5582 (match_operand:SI 3 "arm_hard_register_operand" ""))
5583 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5584 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5585 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5586 "stm%?ia\\t%1, {%2, %3, %4}"
5587 [(set_attr "predicable" "yes")
5588 (set_attr "type" "store3")]
5589)
9c08d1fa 5590
2162064c 5591(define_insn "*stmsi2"
5592 [(match_parallel 0 "store_multiple_operation"
5593 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5594 (match_operand:SI 2 "arm_hard_register_operand" ""))
5595 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5596 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5597 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5598 "stm%?ia\\t%1, {%2, %3}"
0d66636f 5599 [(set_attr "predicable" "yes")
2162064c 5600 (set_attr "type" "store2")]
cffb2a26 5601)
9c08d1fa 5602
5603;; Move a block of memory if it is word aligned and MORE than 2 words long.
5604;; We could let this apply for blocks of less than this, but it clobbers so
5605;; many registers that there is then probably a better way.
5606
008c057d 5607(define_expand "movmemqi"
34191dd1 5608 [(match_operand:BLK 0 "general_operand" "")
5609 (match_operand:BLK 1 "general_operand" "")
5610 (match_operand:SI 2 "const_int_operand" "")
5611 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 5612 "TARGET_EITHER"
9c08d1fa 5613 "
cffb2a26 5614 if (TARGET_ARM)
5615 {
008c057d 5616 if (arm_gen_movmemqi (operands))
cffb2a26 5617 DONE;
5618 FAIL;
5619 }
5620 else /* TARGET_THUMB */
5621 {
5622 if ( INTVAL (operands[3]) != 4
5623 || INTVAL (operands[2]) > 48)
5624 FAIL;
5625
008c057d 5626 thumb_expand_movmemqi (operands);
cffb2a26 5627 DONE;
5628 }
5629 "
5630)
5631
2162064c 5632;; Thumb block-move insns
cffb2a26 5633
5634(define_insn "movmem12b"
960f3acf 5635 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5636 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5637 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5638 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5639 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5640 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5641 (set (match_operand:SI 0 "register_operand" "=l")
5642 (plus:SI (match_dup 2) (const_int 12)))
5643 (set (match_operand:SI 1 "register_operand" "=l")
5644 (plus:SI (match_dup 3) (const_int 12)))
5645 (clobber (match_scratch:SI 4 "=&l"))
5646 (clobber (match_scratch:SI 5 "=&l"))
5647 (clobber (match_scratch:SI 6 "=&l"))]
cffb2a26 5648 "TARGET_THUMB"
5649 "* return thumb_output_move_mem_multiple (3, operands);"
5650 [(set_attr "length" "4")
215b30b3 5651 ; This isn't entirely accurate... It loads as well, but in terms of
5652 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5653 (set_attr "type" "store3")]
5654)
5655
5656(define_insn "movmem8b"
960f3acf 5657 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5658 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5659 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5660 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5661 (set (match_operand:SI 0 "register_operand" "=l")
5662 (plus:SI (match_dup 2) (const_int 8)))
5663 (set (match_operand:SI 1 "register_operand" "=l")
5664 (plus:SI (match_dup 3) (const_int 8)))
5665 (clobber (match_scratch:SI 4 "=&l"))
5666 (clobber (match_scratch:SI 5 "=&l"))]
cffb2a26 5667 "TARGET_THUMB"
5668 "* return thumb_output_move_mem_multiple (2, operands);"
5669 [(set_attr "length" "4")
215b30b3 5670 ; This isn't entirely accurate... It loads as well, but in terms of
5671 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5672 (set_attr "type" "store2")]
5673)
5674
9c08d1fa 5675\f
b11cae9e 5676
341940e8 5677;; Compare & branch insns
8d232dc7 5678;; The range calculations are based as follows:
341940e8 5679;; For forward branches, the address calculation returns the address of
5680;; the next instruction. This is 2 beyond the branch instruction.
5681;; For backward branches, the address calculation returns the address of
5682;; the first instruction in this pattern (cmp). This is 2 before the branch
5683;; instruction for the shortest sequence, and 4 before the branch instruction
5684;; if we have to jump around an unconditional branch.
5685;; To the basic branch range the PC offset must be added (this is +4).
5686;; So for forward branches we have
5687;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5688;; And for backward branches we have
5689;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5690;;
5691;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5692;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 5693
aeac46d4 5694(define_expand "cbranchsi4"
5695 [(set (pc) (if_then_else
5696 (match_operator 0 "arm_comparison_operator"
5697 [(match_operand:SI 1 "s_register_operand" "")
5698 (match_operand:SI 2 "nonmemory_operand" "")])
5699 (label_ref (match_operand 3 "" ""))
5700 (pc)))]
5701 "TARGET_THUMB"
5702 "
5703 if (thumb_cmpneg_operand (operands[2], SImode))
5704 {
5705 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5706 operands[3], operands[0]));
5707 DONE;
5708 }
5709 if (!thumb_cmp_operand (operands[2], SImode))
5710 operands[2] = force_reg (SImode, operands[2]);
5711 ")
5712
5713(define_insn "*cbranchsi4_insn"
5714 [(set (pc) (if_then_else
5715 (match_operator 0 "arm_comparison_operator"
5716 [(match_operand:SI 1 "s_register_operand" "l,*h")
5717 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5718 (label_ref (match_operand 3 "" ""))
5719 (pc)))]
cffb2a26 5720 "TARGET_THUMB"
5721 "*
5722 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 5723
cffb2a26 5724 switch (get_attr_length (insn))
5725 {
5726 case 4: return \"b%d0\\t%l3\";
5727 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5728 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5729 }
5730 "
5731 [(set (attr "far_jump")
5732 (if_then_else
5733 (eq_attr "length" "8")
5734 (const_string "yes")
5735 (const_string "no")))
5736 (set (attr "length")
5737 (if_then_else
5738 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5739 (le (minus (match_dup 3) (pc)) (const_int 256)))
5740 (const_int 4)
5741 (if_then_else
5742 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 5743 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5744 (const_int 6)
5745 (const_int 8))))]
5746)
5747
aeac46d4 5748(define_insn "cbranchsi4_scratch"
5749 [(set (pc) (if_then_else
5750 (match_operator 4 "arm_comparison_operator"
5751 [(match_operand:SI 1 "s_register_operand" "l,0")
5752 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5753 (label_ref (match_operand 3 "" ""))
5754 (pc)))
5755 (clobber (match_scratch:SI 0 "=l,l"))]
5756 "TARGET_THUMB"
5757 "*
5758 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5759
5760 switch (get_attr_length (insn))
5761 {
5762 case 4: return \"b%d4\\t%l3\";
5763 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5764 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5765 }
5766 "
5767 [(set (attr "far_jump")
5768 (if_then_else
5769 (eq_attr "length" "8")
5770 (const_string "yes")
5771 (const_string "no")))
5772 (set (attr "length")
5773 (if_then_else
5774 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5775 (le (minus (match_dup 3) (pc)) (const_int 256)))
5776 (const_int 4)
5777 (if_then_else
5778 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5779 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5780 (const_int 6)
5781 (const_int 8))))]
5782)
5783(define_insn "*movsi_cbranchsi4"
5784 [(set (pc)
5785 (if_then_else
5786 (match_operator 3 "arm_comparison_operator"
5787 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5788 (const_int 0)])
5789 (label_ref (match_operand 2 "" ""))
5790 (pc)))
5791 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5792 (match_dup 1))]
5793 "TARGET_THUMB"
5794 "*{
5795 if (which_alternative == 0)
5796 output_asm_insn (\"cmp\t%0, #0\", operands);
5797 else if (which_alternative == 1)
5798 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5799 else
5800 {
5801 output_asm_insn (\"cmp\t%1, #0\", operands);
5802 if (which_alternative == 2)
5803 output_asm_insn (\"mov\t%0, %1\", operands);
5804 else
5805 output_asm_insn (\"str\t%1, %0\", operands);
5806 }
5807 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5808 {
5809 case 4: return \"b%d3\\t%l2\";
5810 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5811 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5812 }
5813 }"
5814 [(set (attr "far_jump")
5815 (if_then_else
5816 (ior (and (gt (symbol_ref ("which_alternative"))
5817 (const_int 1))
5818 (eq_attr "length" "8"))
5819 (eq_attr "length" "10"))
5820 (const_string "yes")
5821 (const_string "no")))
5822 (set (attr "length")
5823 (if_then_else
5824 (le (symbol_ref ("which_alternative"))
5825 (const_int 1))
5826 (if_then_else
5827 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5828 (le (minus (match_dup 2) (pc)) (const_int 256)))
5829 (const_int 4)
5830 (if_then_else
5831 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5832 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5833 (const_int 6)
5834 (const_int 8)))
5835 (if_then_else
5836 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5837 (le (minus (match_dup 2) (pc)) (const_int 256)))
5838 (const_int 6)
5839 (if_then_else
5840 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5841 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5842 (const_int 8)
5843 (const_int 10)))))]
5844)
5845
cffb2a26 5846(define_insn "*negated_cbranchsi4"
5847 [(set (pc)
5848 (if_then_else
aed179ae 5849 (match_operator 0 "equality_operator"
aeac46d4 5850 [(match_operand:SI 1 "s_register_operand" "l")
5851 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5852 (label_ref (match_operand 3 "" ""))
215b30b3 5853 (pc)))]
cffb2a26 5854 "TARGET_THUMB"
5855 "*
5856 output_asm_insn (\"cmn\\t%1, %2\", operands);
5857 switch (get_attr_length (insn))
5858 {
5859 case 4: return \"b%d0\\t%l3\";
5860 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5861 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5862 }
5863 "
5864 [(set (attr "far_jump")
5865 (if_then_else
5866 (eq_attr "length" "8")
5867 (const_string "yes")
5868 (const_string "no")))
5869 (set (attr "length")
5870 (if_then_else
5871 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 5872 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 5873 (const_int 4)
5874 (if_then_else
341940e8 5875 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5876 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5877 (const_int 6)
5878 (const_int 8))))]
5879)
5880
58d6528b 5881(define_insn "*tbit_cbranch"
5882 [(set (pc)
5883 (if_then_else
5884 (match_operator 0 "equality_operator"
5885 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5886 (const_int 1)
5887 (match_operand:SI 2 "const_int_operand" "i"))
5888 (const_int 0)])
5889 (label_ref (match_operand 3 "" ""))
5890 (pc)))
5891 (clobber (match_scratch:SI 4 "=l"))]
5892 "TARGET_THUMB"
5893 "*
5894 {
5895 rtx op[3];
5896 op[0] = operands[4];
5897 op[1] = operands[1];
5898 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5899
5900 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5901 switch (get_attr_length (insn))
5902 {
5903 case 4: return \"b%d0\\t%l3\";
5904 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5905 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5906 }
5907 }"
5908 [(set (attr "far_jump")
5909 (if_then_else
5910 (eq_attr "length" "8")
5911 (const_string "yes")
5912 (const_string "no")))
5913 (set (attr "length")
5914 (if_then_else
5915 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5916 (le (minus (match_dup 3) (pc)) (const_int 256)))
5917 (const_int 4)
5918 (if_then_else
5919 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5920 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5921 (const_int 6)
5922 (const_int 8))))]
5923)
5924
aeac46d4 5925(define_insn "*tstsi3_cbranch"
58d6528b 5926 [(set (pc)
5927 (if_then_else
aeac46d4 5928 (match_operator 3 "equality_operator"
5929 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5930 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 5931 (const_int 0)])
aeac46d4 5932 (label_ref (match_operand 2 "" ""))
5933 (pc)))]
58d6528b 5934 "TARGET_THUMB"
5935 "*
5936 {
aeac46d4 5937 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 5938 switch (get_attr_length (insn))
5939 {
aeac46d4 5940 case 4: return \"b%d3\\t%l2\";
5941 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5942 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 5943 }
5944 }"
5945 [(set (attr "far_jump")
5946 (if_then_else
5947 (eq_attr "length" "8")
5948 (const_string "yes")
5949 (const_string "no")))
5950 (set (attr "length")
5951 (if_then_else
aeac46d4 5952 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5953 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 5954 (const_int 4)
5955 (if_then_else
aeac46d4 5956 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5957 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 5958 (const_int 6)
5959 (const_int 8))))]
5960)
5961
5962(define_insn "*andsi3_cbranch"
5963 [(set (pc)
5964 (if_then_else
5965 (match_operator 5 "equality_operator"
5966 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5967 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5968 (const_int 0)])
5969 (label_ref (match_operand 4 "" ""))
5970 (pc)))
aeac46d4 5971 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 5972 (and:SI (match_dup 2) (match_dup 3)))
5973 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5974 "TARGET_THUMB"
5975 "*
5976 {
5977 if (which_alternative == 0)
5978 output_asm_insn (\"and\\t%0, %3\", operands);
5979 else if (which_alternative == 1)
5980 {
5981 output_asm_insn (\"and\\t%1, %3\", operands);
5982 output_asm_insn (\"mov\\t%0, %1\", operands);
5983 }
5984 else
5985 {
5986 output_asm_insn (\"and\\t%1, %3\", operands);
5987 output_asm_insn (\"str\\t%1, %0\", operands);
5988 }
5989
5990 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5991 {
5992 case 4: return \"b%d5\\t%l4\";
5993 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5994 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5995 }
5996 }"
5997 [(set (attr "far_jump")
5998 (if_then_else
5999 (ior (and (eq (symbol_ref ("which_alternative"))
6000 (const_int 0))
6001 (eq_attr "length" "8"))
6002 (eq_attr "length" "10"))
6003 (const_string "yes")
6004 (const_string "no")))
6005 (set (attr "length")
6006 (if_then_else
6007 (eq (symbol_ref ("which_alternative"))
6008 (const_int 0))
6009 (if_then_else
6010 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6011 (le (minus (match_dup 4) (pc)) (const_int 256)))
6012 (const_int 4)
6013 (if_then_else
6014 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6015 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6016 (const_int 6)
6017 (const_int 8)))
6018 (if_then_else
6019 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6020 (le (minus (match_dup 4) (pc)) (const_int 256)))
6021 (const_int 6)
6022 (if_then_else
6023 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6024 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6025 (const_int 8)
6026 (const_int 10)))))]
6027)
6028
6029(define_insn "*orrsi3_cbranch_scratch"
6030 [(set (pc)
6031 (if_then_else
6032 (match_operator 4 "equality_operator"
6033 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6034 (match_operand:SI 2 "s_register_operand" "l"))
6035 (const_int 0)])
6036 (label_ref (match_operand 3 "" ""))
6037 (pc)))
6038 (clobber (match_scratch:SI 0 "=l"))]
6039 "TARGET_THUMB"
6040 "*
6041 {
6042 output_asm_insn (\"orr\\t%0, %2\", operands);
6043 switch (get_attr_length (insn))
6044 {
6045 case 4: return \"b%d4\\t%l3\";
6046 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6047 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6048 }
6049 }"
6050 [(set (attr "far_jump")
6051 (if_then_else
6052 (eq_attr "length" "8")
6053 (const_string "yes")
6054 (const_string "no")))
6055 (set (attr "length")
6056 (if_then_else
6057 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6058 (le (minus (match_dup 3) (pc)) (const_int 256)))
6059 (const_int 4)
6060 (if_then_else
6061 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6062 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6063 (const_int 6)
6064 (const_int 8))))]
6065)
6066
6067(define_insn "*orrsi3_cbranch"
6068 [(set (pc)
6069 (if_then_else
6070 (match_operator 5 "equality_operator"
6071 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6072 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6073 (const_int 0)])
6074 (label_ref (match_operand 4 "" ""))
6075 (pc)))
aeac46d4 6076 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6077 (ior:SI (match_dup 2) (match_dup 3)))
6078 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6079 "TARGET_THUMB"
6080 "*
6081 {
6082 if (which_alternative == 0)
6083 output_asm_insn (\"orr\\t%0, %3\", operands);
6084 else if (which_alternative == 1)
6085 {
6086 output_asm_insn (\"orr\\t%1, %3\", operands);
6087 output_asm_insn (\"mov\\t%0, %1\", operands);
6088 }
6089 else
6090 {
6091 output_asm_insn (\"orr\\t%1, %3\", operands);
6092 output_asm_insn (\"str\\t%1, %0\", operands);
6093 }
6094
6095 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6096 {
6097 case 4: return \"b%d5\\t%l4\";
6098 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6099 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6100 }
6101 }"
6102 [(set (attr "far_jump")
6103 (if_then_else
6104 (ior (and (eq (symbol_ref ("which_alternative"))
6105 (const_int 0))
6106 (eq_attr "length" "8"))
6107 (eq_attr "length" "10"))
6108 (const_string "yes")
6109 (const_string "no")))
6110 (set (attr "length")
6111 (if_then_else
6112 (eq (symbol_ref ("which_alternative"))
6113 (const_int 0))
6114 (if_then_else
6115 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6116 (le (minus (match_dup 4) (pc)) (const_int 256)))
6117 (const_int 4)
6118 (if_then_else
6119 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6120 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6121 (const_int 6)
6122 (const_int 8)))
6123 (if_then_else
6124 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6125 (le (minus (match_dup 4) (pc)) (const_int 256)))
6126 (const_int 6)
6127 (if_then_else
6128 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6129 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6130 (const_int 8)
6131 (const_int 10)))))]
6132)
6133
6134(define_insn "*xorsi3_cbranch_scratch"
6135 [(set (pc)
6136 (if_then_else
6137 (match_operator 4 "equality_operator"
6138 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6139 (match_operand:SI 2 "s_register_operand" "l"))
6140 (const_int 0)])
6141 (label_ref (match_operand 3 "" ""))
6142 (pc)))
6143 (clobber (match_scratch:SI 0 "=l"))]
6144 "TARGET_THUMB"
6145 "*
6146 {
6147 output_asm_insn (\"eor\\t%0, %2\", operands);
6148 switch (get_attr_length (insn))
6149 {
6150 case 4: return \"b%d4\\t%l3\";
6151 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6152 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6153 }
6154 }"
6155 [(set (attr "far_jump")
6156 (if_then_else
6157 (eq_attr "length" "8")
6158 (const_string "yes")
6159 (const_string "no")))
6160 (set (attr "length")
6161 (if_then_else
6162 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6163 (le (minus (match_dup 3) (pc)) (const_int 256)))
6164 (const_int 4)
6165 (if_then_else
6166 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6167 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6168 (const_int 6)
6169 (const_int 8))))]
6170)
6171
6172(define_insn "*xorsi3_cbranch"
6173 [(set (pc)
6174 (if_then_else
6175 (match_operator 5 "equality_operator"
6176 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6177 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6178 (const_int 0)])
6179 (label_ref (match_operand 4 "" ""))
6180 (pc)))
aeac46d4 6181 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6182 (xor:SI (match_dup 2) (match_dup 3)))
6183 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6184 "TARGET_THUMB"
6185 "*
6186 {
6187 if (which_alternative == 0)
6188 output_asm_insn (\"eor\\t%0, %3\", operands);
6189 else if (which_alternative == 1)
6190 {
6191 output_asm_insn (\"eor\\t%1, %3\", operands);
6192 output_asm_insn (\"mov\\t%0, %1\", operands);
6193 }
6194 else
6195 {
6196 output_asm_insn (\"eor\\t%1, %3\", operands);
6197 output_asm_insn (\"str\\t%1, %0\", operands);
6198 }
6199
6200 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6201 {
6202 case 4: return \"b%d5\\t%l4\";
6203 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6204 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6205 }
6206 }"
6207 [(set (attr "far_jump")
6208 (if_then_else
6209 (ior (and (eq (symbol_ref ("which_alternative"))
6210 (const_int 0))
6211 (eq_attr "length" "8"))
6212 (eq_attr "length" "10"))
6213 (const_string "yes")
6214 (const_string "no")))
6215 (set (attr "length")
6216 (if_then_else
6217 (eq (symbol_ref ("which_alternative"))
6218 (const_int 0))
6219 (if_then_else
6220 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6221 (le (minus (match_dup 4) (pc)) (const_int 256)))
6222 (const_int 4)
6223 (if_then_else
6224 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6225 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6226 (const_int 6)
6227 (const_int 8)))
6228 (if_then_else
6229 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6230 (le (minus (match_dup 4) (pc)) (const_int 256)))
6231 (const_int 6)
6232 (if_then_else
6233 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6234 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6235 (const_int 8)
6236 (const_int 10)))))]
6237)
6238
aeac46d4 6239(define_insn "*bicsi3_cbranch_scratch"
6240 [(set (pc)
6241 (if_then_else
6242 (match_operator 4 "equality_operator"
6243 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6244 (match_operand:SI 1 "s_register_operand" "0"))
6245 (const_int 0)])
6246 (label_ref (match_operand 3 "" ""))
6247 (pc)))
6248 (clobber (match_scratch:SI 0 "=l"))]
6249 "TARGET_THUMB"
6250 "*
6251 {
6252 output_asm_insn (\"bic\\t%0, %2\", operands);
6253 switch (get_attr_length (insn))
6254 {
6255 case 4: return \"b%d4\\t%l3\";
6256 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6257 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6258 }
6259 }"
6260 [(set (attr "far_jump")
6261 (if_then_else
6262 (eq_attr "length" "8")
6263 (const_string "yes")
6264 (const_string "no")))
6265 (set (attr "length")
6266 (if_then_else
6267 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6268 (le (minus (match_dup 3) (pc)) (const_int 256)))
6269 (const_int 4)
6270 (if_then_else
6271 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6272 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6273 (const_int 6)
6274 (const_int 8))))]
6275)
6276
6277(define_insn "*bicsi3_cbranch"
6278 [(set (pc)
6279 (if_then_else
6280 (match_operator 5 "equality_operator"
01145ae6 6281 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6282 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 6283 (const_int 0)])
6284 (label_ref (match_operand 4 "" ""))
6285 (pc)))
01145ae6 6286 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 6287 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 6288 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
aeac46d4 6289 "TARGET_THUMB"
6290 "*
6291 {
6292 if (which_alternative == 0)
6293 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 6294 else if (which_alternative <= 2)
aeac46d4 6295 {
6296 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 6297 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6298 conditions again, since we're only testing for equality. */
aeac46d4 6299 output_asm_insn (\"mov\\t%0, %1\", operands);
6300 }
6301 else
6302 {
6303 output_asm_insn (\"bic\\t%1, %3\", operands);
6304 output_asm_insn (\"str\\t%1, %0\", operands);
6305 }
6306
6307 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6308 {
6309 case 4: return \"b%d5\\t%l4\";
6310 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6311 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6312 }
6313 }"
6314 [(set (attr "far_jump")
6315 (if_then_else
6316 (ior (and (eq (symbol_ref ("which_alternative"))
6317 (const_int 0))
6318 (eq_attr "length" "8"))
6319 (eq_attr "length" "10"))
6320 (const_string "yes")
6321 (const_string "no")))
6322 (set (attr "length")
6323 (if_then_else
6324 (eq (symbol_ref ("which_alternative"))
6325 (const_int 0))
6326 (if_then_else
6327 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6328 (le (minus (match_dup 4) (pc)) (const_int 256)))
6329 (const_int 4)
6330 (if_then_else
6331 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6332 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6333 (const_int 6)
6334 (const_int 8)))
6335 (if_then_else
6336 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6337 (le (minus (match_dup 4) (pc)) (const_int 256)))
6338 (const_int 6)
6339 (if_then_else
6340 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6341 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6342 (const_int 8)
6343 (const_int 10)))))]
6344)
6345
203c488f 6346(define_insn "*cbranchne_decr1"
6347 [(set (pc)
6348 (if_then_else (match_operator 3 "equality_operator"
6349 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6350 (const_int 0)])
6351 (label_ref (match_operand 4 "" ""))
6352 (pc)))
aeac46d4 6353 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6354 (plus:SI (match_dup 2) (const_int -1)))
6355 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6356 "TARGET_THUMB"
6357 "*
6358 {
6359 rtx cond[2];
6360 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6361 ? GEU : LTU),
58d6528b 6362 VOIDmode, operands[2], const1_rtx);
203c488f 6363 cond[1] = operands[4];
6364
6365 if (which_alternative == 0)
6366 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6367 else if (which_alternative == 1)
6368 {
6369 /* We must provide an alternative for a hi reg because reload
6370 cannot handle output reloads on a jump instruction, but we
6371 can't subtract into that. Fortunately a mov from lo to hi
6372 does not clobber the condition codes. */
6373 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6374 output_asm_insn (\"mov\\t%0, %1\", operands);
6375 }
6376 else
6377 {
6378 /* Similarly, but the target is memory. */
6379 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6380 output_asm_insn (\"str\\t%1, %0\", operands);
6381 }
6382
6383 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6384 {
6385 case 4:
8aea555f 6386 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6387 return \"\";
6388 case 6:
8aea555f 6389 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6390 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6391 default:
8aea555f 6392 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6393 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6394 }
6395 }
6396 "
6397 [(set (attr "far_jump")
6398 (if_then_else
6399 (ior (and (eq (symbol_ref ("which_alternative"))
6400 (const_int 0))
6401 (eq_attr "length" "8"))
6402 (eq_attr "length" "10"))
6403 (const_string "yes")
6404 (const_string "no")))
6405 (set_attr_alternative "length"
6406 [
6407 ;; Alternative 0
6408 (if_then_else
6409 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6410 (le (minus (match_dup 4) (pc)) (const_int 256)))
6411 (const_int 4)
6412 (if_then_else
6413 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6414 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6415 (const_int 6)
6416 (const_int 8)))
6417 ;; Alternative 1
6418 (if_then_else
6419 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6420 (le (minus (match_dup 4) (pc)) (const_int 256)))
6421 (const_int 6)
6422 (if_then_else
6423 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6424 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6425 (const_int 8)
6426 (const_int 10)))
6427 ;; Alternative 2
6428 (if_then_else
6429 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6430 (le (minus (match_dup 4) (pc)) (const_int 256)))
6431 (const_int 6)
6432 (if_then_else
6433 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6434 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6435 (const_int 8)
6436 (const_int 10)))
6437 ;; Alternative 3
6438 (if_then_else
6439 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6440 (le (minus (match_dup 4) (pc)) (const_int 256)))
6441 (const_int 6)
6442 (if_then_else
6443 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6444 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6445 (const_int 8)
6446 (const_int 10)))])]
6447)
cffb2a26 6448
58d6528b 6449(define_insn "*addsi3_cbranch"
6450 [(set (pc)
6451 (if_then_else
6452 (match_operator 4 "comparison_operator"
6453 [(plus:SI
6454 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6455 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6456 (const_int 0)])
6457 (label_ref (match_operand 5 "" ""))
6458 (pc)))
aeac46d4 6459 (set
6460 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6461 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 6462 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6463 "TARGET_THUMB
6464 && (GET_CODE (operands[4]) == EQ
6465 || GET_CODE (operands[4]) == NE
6466 || GET_CODE (operands[4]) == GE
6467 || GET_CODE (operands[4]) == LT)"
6468 "*
6469 {
6470 rtx cond[3];
6471
6472
6473 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6474 cond[1] = operands[2];
6475 cond[2] = operands[3];
6476
6477 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6478 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6479 else
6480 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6481
6482 if (which_alternative >= 3
6483 && which_alternative < 4)
6484 output_asm_insn (\"mov\\t%0, %1\", operands);
6485 else if (which_alternative >= 4)
6486 output_asm_insn (\"str\\t%1, %0\", operands);
6487
6488 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6489 {
6490 case 4:
6491 return \"b%d4\\t%l5\";
6492 case 6:
6493 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6494 default:
6495 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6496 }
6497 }
6498 "
6499 [(set (attr "far_jump")
6500 (if_then_else
6501 (ior (and (lt (symbol_ref ("which_alternative"))
6502 (const_int 3))
6503 (eq_attr "length" "8"))
6504 (eq_attr "length" "10"))
6505 (const_string "yes")
6506 (const_string "no")))
6507 (set (attr "length")
6508 (if_then_else
6509 (lt (symbol_ref ("which_alternative"))
6510 (const_int 3))
6511 (if_then_else
6512 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6513 (le (minus (match_dup 5) (pc)) (const_int 256)))
6514 (const_int 4)
6515 (if_then_else
6516 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6517 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6518 (const_int 6)
6519 (const_int 8)))
6520 (if_then_else
6521 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6522 (le (minus (match_dup 5) (pc)) (const_int 256)))
6523 (const_int 6)
6524 (if_then_else
6525 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6526 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6527 (const_int 8)
6528 (const_int 10)))))]
6529)
6530
6531(define_insn "*addsi3_cbranch_scratch"
6532 [(set (pc)
6533 (if_then_else
6534 (match_operator 3 "comparison_operator"
6535 [(plus:SI
6536 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 6537 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 6538 (const_int 0)])
6539 (label_ref (match_operand 4 "" ""))
6540 (pc)))
6541 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6542 "TARGET_THUMB
6543 && (GET_CODE (operands[3]) == EQ
6544 || GET_CODE (operands[3]) == NE
6545 || GET_CODE (operands[3]) == GE
6546 || GET_CODE (operands[3]) == LT)"
6547 "*
6548 {
6549 switch (which_alternative)
6550 {
6551 case 0:
6552 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6553 break;
6554 case 1:
6555 output_asm_insn (\"cmn\t%1, %2\", operands);
6556 break;
0f5e9701 6557 case 2:
3a445a04 6558 if (INTVAL (operands[2]) < 0)
6559 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6560 else
6561 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 6562 break;
0f5e9701 6563 case 3:
3a445a04 6564 if (INTVAL (operands[2]) < 0)
6565 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6566 else
6567 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 6568 break;
6569 }
6570
6571 switch (get_attr_length (insn))
6572 {
6573 case 4:
6574 return \"b%d3\\t%l4\";
6575 case 6:
6576 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6577 default:
6578 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6579 }
6580 }
6581 "
6582 [(set (attr "far_jump")
6583 (if_then_else
6584 (eq_attr "length" "8")
6585 (const_string "yes")
6586 (const_string "no")))
6587 (set (attr "length")
6588 (if_then_else
6589 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6590 (le (minus (match_dup 4) (pc)) (const_int 256)))
6591 (const_int 4)
6592 (if_then_else
6593 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6594 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6595 (const_int 6)
6596 (const_int 8))))]
6597)
6598
6599(define_insn "*subsi3_cbranch"
6600 [(set (pc)
6601 (if_then_else
6602 (match_operator 4 "comparison_operator"
6603 [(minus:SI
6604 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6605 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6606 (const_int 0)])
6607 (label_ref (match_operand 5 "" ""))
6608 (pc)))
aeac46d4 6609 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6610 (minus:SI (match_dup 2) (match_dup 3)))
6611 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6612 "TARGET_THUMB
6613 && (GET_CODE (operands[4]) == EQ
6614 || GET_CODE (operands[4]) == NE
6615 || GET_CODE (operands[4]) == GE
6616 || GET_CODE (operands[4]) == LT)"
6617 "*
6618 {
6619 if (which_alternative == 0)
6620 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6621 else if (which_alternative == 1)
6622 {
6623 /* We must provide an alternative for a hi reg because reload
6624 cannot handle output reloads on a jump instruction, but we
6625 can't subtract into that. Fortunately a mov from lo to hi
6626 does not clobber the condition codes. */
6627 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6628 output_asm_insn (\"mov\\t%0, %1\", operands);
6629 }
6630 else
6631 {
6632 /* Similarly, but the target is memory. */
6633 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6634 output_asm_insn (\"str\\t%1, %0\", operands);
6635 }
6636
6637 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6638 {
6639 case 4:
6640 return \"b%d4\\t%l5\";
6641 case 6:
6642 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6643 default:
6644 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6645 }
6646 }
6647 "
6648 [(set (attr "far_jump")
6649 (if_then_else
6650 (ior (and (eq (symbol_ref ("which_alternative"))
6651 (const_int 0))
6652 (eq_attr "length" "8"))
6653 (eq_attr "length" "10"))
6654 (const_string "yes")
6655 (const_string "no")))
6656 (set (attr "length")
6657 (if_then_else
6658 (eq (symbol_ref ("which_alternative"))
6659 (const_int 0))
6660 (if_then_else
6661 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6662 (le (minus (match_dup 5) (pc)) (const_int 256)))
6663 (const_int 4)
6664 (if_then_else
6665 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6666 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6667 (const_int 6)
6668 (const_int 8)))
6669 (if_then_else
6670 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6671 (le (minus (match_dup 5) (pc)) (const_int 256)))
6672 (const_int 6)
6673 (if_then_else
6674 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6675 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6676 (const_int 8)
6677 (const_int 10)))))]
6678)
6679
6680(define_insn "*subsi3_cbranch_scratch"
6681 [(set (pc)
6682 (if_then_else
6683 (match_operator 0 "arm_comparison_operator"
6684 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6685 (match_operand:SI 2 "nonmemory_operand" "l"))
6686 (const_int 0)])
6687 (label_ref (match_operand 3 "" ""))
6688 (pc)))]
6689 "TARGET_THUMB
6690 && (GET_CODE (operands[0]) == EQ
6691 || GET_CODE (operands[0]) == NE
6692 || GET_CODE (operands[0]) == GE
6693 || GET_CODE (operands[0]) == LT)"
6694 "*
6695 output_asm_insn (\"cmp\\t%1, %2\", operands);
6696 switch (get_attr_length (insn))
6697 {
6698 case 4: return \"b%d0\\t%l3\";
6699 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6700 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6701 }
6702 "
6703 [(set (attr "far_jump")
6704 (if_then_else
6705 (eq_attr "length" "8")
6706 (const_string "yes")
6707 (const_string "no")))
6708 (set (attr "length")
6709 (if_then_else
6710 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6711 (le (minus (match_dup 3) (pc)) (const_int 256)))
6712 (const_int 4)
6713 (if_then_else
6714 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6715 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6716 (const_int 6)
6717 (const_int 8))))]
6718)
6719
9c08d1fa 6720;; Comparison and test insns
6721
6722(define_expand "cmpsi"
aea4c774 6723 [(match_operand:SI 0 "s_register_operand" "")
6724 (match_operand:SI 1 "arm_add_operand" "")]
cffb2a26 6725 "TARGET_ARM"
6726 "{
6727 arm_compare_op0 = operands[0];
6728 arm_compare_op1 = operands[1];
6729 DONE;
6730 }"
6731)
b11cae9e 6732
9c08d1fa 6733(define_expand "cmpsf"
aea4c774 6734 [(match_operand:SF 0 "s_register_operand" "")
a2cd141b 6735 (match_operand:SF 1 "arm_float_compare_operand" "")]
6736 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6737 "
9c08d1fa 6738 arm_compare_op0 = operands[0];
6739 arm_compare_op1 = operands[1];
9c08d1fa 6740 DONE;
215b30b3 6741 "
6742)
b11cae9e 6743
9c08d1fa 6744(define_expand "cmpdf"
aea4c774 6745 [(match_operand:DF 0 "s_register_operand" "")
a2cd141b 6746 (match_operand:DF 1 "arm_float_compare_operand" "")]
6747 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6748 "
9c08d1fa 6749 arm_compare_op0 = operands[0];
6750 arm_compare_op1 = operands[1];
9c08d1fa 6751 DONE;
215b30b3 6752 "
6753)
b11cae9e 6754
cffb2a26 6755(define_insn "*arm_cmpsi_insn"
bd5b4116 6756 [(set (reg:CC CC_REGNUM)
aea4c774 6757 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 6758 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6759 "TARGET_ARM"
5565501b 6760 "@
aea4c774 6761 cmp%?\\t%0, %1
6762 cmn%?\\t%0, #%n1"
cffb2a26 6763 [(set_attr "conds" "set")]
6764)
b11cae9e 6765
aea4c774 6766(define_insn "*cmpsi_shiftsi"
bd5b4116 6767 [(set (reg:CC CC_REGNUM)
cffb2a26 6768 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6769 (match_operator:SI 3 "shift_operator"
aea4c774 6770 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 6771 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6772 "TARGET_ARM"
aea4c774 6773 "cmp%?\\t%0, %1%S3"
344495ea 6774 [(set_attr "conds" "set")
331beb1a 6775 (set_attr "shift" "1")
a2cd141b 6776 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6777 (const_string "alu_shift")
6778 (const_string "alu_shift_reg")))]
0d66636f 6779)
b11cae9e 6780
aea4c774 6781(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6782 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6783 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6784 [(match_operand:SI 1 "s_register_operand" "r")
6785 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6786 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6787 "TARGET_ARM"
aea4c774 6788 "cmp%?\\t%0, %1%S3"
344495ea 6789 [(set_attr "conds" "set")
331beb1a 6790 (set_attr "shift" "1")
a2cd141b 6791 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6792 (const_string "alu_shift")
6793 (const_string "alu_shift_reg")))]
0d66636f 6794)
b11cae9e 6795
aed179ae 6796(define_insn "*cmpsi_negshiftsi_si"
6797 [(set (reg:CC_Z CC_REGNUM)
6798 (compare:CC_Z
6799 (neg:SI (match_operator:SI 1 "shift_operator"
6800 [(match_operand:SI 2 "s_register_operand" "r")
6801 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6802 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6803 "TARGET_ARM"
aed179ae 6804 "cmn%?\\t%0, %2%S1"
344495ea 6805 [(set_attr "conds" "set")
aed179ae 6806 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6807 (const_string "alu_shift")
6808 (const_string "alu_shift_reg")))]
0d66636f 6809)
b11cae9e 6810
7d57ec45 6811;; Cirrus SF compare instruction
6812(define_insn "*cirrus_cmpsf"
6813 [(set (reg:CCFP CC_REGNUM)
6814 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6815 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 6816 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6817 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 6818 [(set_attr "type" "mav_farith")
7d57ec45 6819 (set_attr "cirrus" "compare")]
6820)
6821
6822;; Cirrus DF compare instruction
6823(define_insn "*cirrus_cmpdf"
6824 [(set (reg:CCFP CC_REGNUM)
6825 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6826 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 6827 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6828 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 6829 [(set_attr "type" "mav_farith")
7d57ec45 6830 (set_attr "cirrus" "compare")]
6831)
6832
6833;; Cirrus DI compare instruction
6834(define_expand "cmpdi"
6835 [(match_operand:DI 0 "cirrus_fp_register" "")
6836 (match_operand:DI 1 "cirrus_fp_register" "")]
a2cd141b 6837 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6838 "{
6839 arm_compare_op0 = operands[0];
6840 arm_compare_op1 = operands[1];
6841 DONE;
6842 }")
6843
6844(define_insn "*cirrus_cmpdi"
6845 [(set (reg:CC CC_REGNUM)
6846 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6847 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 6848 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6849 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 6850 [(set_attr "type" "mav_farith")
7d57ec45 6851 (set_attr "cirrus" "compare")]
6852)
6853
9c08d1fa 6854; This insn allows redundant compares to be removed by cse, nothing should
6855; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6856; is deleted later on. The match_dup will match the mode here, so that
6857; mode changes of the condition codes aren't lost by this even though we don't
6858; specify what they are.
6859
8a18b90c 6860(define_insn "*deleted_compare"
9c08d1fa 6861 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
cffb2a26 6862 "TARGET_ARM"
40dbec34 6863 "\\t%@ deleted compare"
cffb2a26 6864 [(set_attr "conds" "set")
6865 (set_attr "length" "0")]
6866)
9c08d1fa 6867
6868\f
6869;; Conditional branch insns
6870
6871(define_expand "beq"
6872 [(set (pc)
6873 (if_then_else (eq (match_dup 1) (const_int 0))
6874 (label_ref (match_operand 0 "" ""))
6875 (pc)))]
cffb2a26 6876 "TARGET_ARM"
6877 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6878)
5c951228 6879
9c08d1fa 6880(define_expand "bne"
6881 [(set (pc)
6882 (if_then_else (ne (match_dup 1) (const_int 0))
6883 (label_ref (match_operand 0 "" ""))
6884 (pc)))]
cffb2a26 6885 "TARGET_ARM"
6886 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6887)
5c951228 6888
9c08d1fa 6889(define_expand "bgt"
6890 [(set (pc)
6891 (if_then_else (gt (match_dup 1) (const_int 0))
6892 (label_ref (match_operand 0 "" ""))
6893 (pc)))]
cffb2a26 6894 "TARGET_ARM"
6895 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6896)
5c951228 6897
9c08d1fa 6898(define_expand "ble"
6899 [(set (pc)
6900 (if_then_else (le (match_dup 1) (const_int 0))
6901 (label_ref (match_operand 0 "" ""))
6902 (pc)))]
cffb2a26 6903 "TARGET_ARM"
6904 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6905)
5c951228 6906
9c08d1fa 6907(define_expand "bge"
6908 [(set (pc)
6909 (if_then_else (ge (match_dup 1) (const_int 0))
6910 (label_ref (match_operand 0 "" ""))
6911 (pc)))]
cffb2a26 6912 "TARGET_ARM"
6913 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6914)
5c951228 6915
9c08d1fa 6916(define_expand "blt"
6917 [(set (pc)
6918 (if_then_else (lt (match_dup 1) (const_int 0))
6919 (label_ref (match_operand 0 "" ""))
6920 (pc)))]
cffb2a26 6921 "TARGET_ARM"
6922 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6923)
5c951228 6924
9c08d1fa 6925(define_expand "bgtu"
6926 [(set (pc)
6927 (if_then_else (gtu (match_dup 1) (const_int 0))
6928 (label_ref (match_operand 0 "" ""))
6929 (pc)))]
cffb2a26 6930 "TARGET_ARM"
6931 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6932)
5c951228 6933
9c08d1fa 6934(define_expand "bleu"
b11cae9e 6935 [(set (pc)
9c08d1fa 6936 (if_then_else (leu (match_dup 1) (const_int 0))
6937 (label_ref (match_operand 0 "" ""))
6938 (pc)))]
cffb2a26 6939 "TARGET_ARM"
6940 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6941)
b11cae9e 6942
9c08d1fa 6943(define_expand "bgeu"
b11cae9e 6944 [(set (pc)
9c08d1fa 6945 (if_then_else (geu (match_dup 1) (const_int 0))
6946 (label_ref (match_operand 0 "" ""))
6947 (pc)))]
cffb2a26 6948 "TARGET_ARM"
6949 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6950)
b11cae9e 6951
9c08d1fa 6952(define_expand "bltu"
6953 [(set (pc)
6954 (if_then_else (ltu (match_dup 1) (const_int 0))
6955 (label_ref (match_operand 0 "" ""))
6956 (pc)))]
cffb2a26 6957 "TARGET_ARM"
6958 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6959)
b11cae9e 6960
8fa3ba89 6961(define_expand "bunordered"
6962 [(set (pc)
6963 (if_then_else (unordered (match_dup 1) (const_int 0))
6964 (label_ref (match_operand 0 "" ""))
6965 (pc)))]
a2cd141b 6966 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6967 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6968 arm_compare_op1);"
6969)
6970
6971(define_expand "bordered"
6972 [(set (pc)
6973 (if_then_else (ordered (match_dup 1) (const_int 0))
6974 (label_ref (match_operand 0 "" ""))
6975 (pc)))]
a2cd141b 6976 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6977 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6978 arm_compare_op1);"
6979)
6980
6981(define_expand "bungt"
6982 [(set (pc)
6983 (if_then_else (ungt (match_dup 1) (const_int 0))
6984 (label_ref (match_operand 0 "" ""))
6985 (pc)))]
a2cd141b 6986 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6987 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6988)
6989
6990(define_expand "bunlt"
6991 [(set (pc)
6992 (if_then_else (unlt (match_dup 1) (const_int 0))
6993 (label_ref (match_operand 0 "" ""))
6994 (pc)))]
a2cd141b 6995 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6996 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6997)
6998
6999(define_expand "bunge"
7000 [(set (pc)
7001 (if_then_else (unge (match_dup 1) (const_int 0))
7002 (label_ref (match_operand 0 "" ""))
7003 (pc)))]
a2cd141b 7004 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7005 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7006)
7007
7008(define_expand "bunle"
7009 [(set (pc)
7010 (if_then_else (unle (match_dup 1) (const_int 0))
7011 (label_ref (match_operand 0 "" ""))
7012 (pc)))]
a2cd141b 7013 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7014 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7015)
7016
7017;; The following two patterns need two branch instructions, since there is
7018;; no single instruction that will handle all cases.
7019(define_expand "buneq"
7020 [(set (pc)
7021 (if_then_else (uneq (match_dup 1) (const_int 0))
7022 (label_ref (match_operand 0 "" ""))
7023 (pc)))]
a2cd141b 7024 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7025 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7026)
7027
7028(define_expand "bltgt"
7029 [(set (pc)
7030 (if_then_else (ltgt (match_dup 1) (const_int 0))
7031 (label_ref (match_operand 0 "" ""))
7032 (pc)))]
a2cd141b 7033 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7034 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7035)
7036
7037;;
7038;; Patterns to match conditional branch insns.
7039;;
7040
7041; Special pattern to match UNEQ.
7042(define_insn "*arm_buneq"
7043 [(set (pc)
7044 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7045 (label_ref (match_operand 0 "" ""))
7046 (pc)))]
a2cd141b 7047 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7048 "*
ed29c566 7049 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7050
278b301d 7051 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7052 "
7053 [(set_attr "conds" "jump_clob")
7054 (set_attr "length" "8")]
7055)
7056
7057; Special pattern to match LTGT.
7058(define_insn "*arm_bltgt"
7059 [(set (pc)
7060 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7061 (label_ref (match_operand 0 "" ""))
7062 (pc)))]
a2cd141b 7063 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7064 "*
ed29c566 7065 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7066
278b301d 7067 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7068 "
7069 [(set_attr "conds" "jump_clob")
7070 (set_attr "length" "8")]
7071)
9c08d1fa 7072
cffb2a26 7073(define_insn "*arm_cond_branch"
9c08d1fa 7074 [(set (pc)
8fa3ba89 7075 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7076 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7077 (label_ref (match_operand 0 "" ""))
7078 (pc)))]
cffb2a26 7079 "TARGET_ARM"
d75350ce 7080 "*
9c08d1fa 7081 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7082 {
7083 arm_ccfsm_state += 2;
7084 return \"\";
7085 }
e2348bcb 7086 return \"b%d1\\t%l0\";
cffb2a26 7087 "
a2cd141b 7088 [(set_attr "conds" "use")
7089 (set_attr "type" "branch")]
cffb2a26 7090)
d75350ce 7091
8fa3ba89 7092; Special pattern to match reversed UNEQ.
7093(define_insn "*arm_buneq_reversed"
7094 [(set (pc)
7095 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7096 (pc)
7097 (label_ref (match_operand 0 "" ""))))]
a2cd141b 7098 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7099 "*
ed29c566 7100 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7101
278b301d 7102 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7103 "
7104 [(set_attr "conds" "jump_clob")
7105 (set_attr "length" "8")]
7106)
7107
7108; Special pattern to match reversed LTGT.
7109(define_insn "*arm_bltgt_reversed"
7110 [(set (pc)
7111 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7112 (pc)
7113 (label_ref (match_operand 0 "" ""))))]
a2cd141b 7114 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7115 "*
ed29c566 7116 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7117
278b301d 7118 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7119 "
7120 [(set_attr "conds" "jump_clob")
7121 (set_attr "length" "8")]
7122)
7123
cffb2a26 7124(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7125 [(set (pc)
8fa3ba89 7126 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7127 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7128 (pc)
7129 (label_ref (match_operand 0 "" ""))))]
cffb2a26 7130 "TARGET_ARM"
d75350ce 7131 "*
9c08d1fa 7132 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7133 {
7134 arm_ccfsm_state += 2;
7135 return \"\";
7136 }
e2348bcb 7137 return \"b%D1\\t%l0\";
cffb2a26 7138 "
a2cd141b 7139 [(set_attr "conds" "use")
7140 (set_attr "type" "branch")]
cffb2a26 7141)
7142
b11cae9e 7143\f
9c08d1fa 7144
7145; scc insns
7146
7147(define_expand "seq"
7db9af5d 7148 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7149 (eq:SI (match_dup 1) (const_int 0)))]
cffb2a26 7150 "TARGET_ARM"
7151 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7152)
9c08d1fa 7153
7154(define_expand "sne"
7db9af5d 7155 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7156 (ne:SI (match_dup 1) (const_int 0)))]
cffb2a26 7157 "TARGET_ARM"
7158 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7159)
9c08d1fa 7160
7161(define_expand "sgt"
7db9af5d 7162 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7163 (gt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7164 "TARGET_ARM"
7165 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7166)
9c08d1fa 7167
7168(define_expand "sle"
7db9af5d 7169 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7170 (le:SI (match_dup 1) (const_int 0)))]
cffb2a26 7171 "TARGET_ARM"
7172 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7173)
9c08d1fa 7174
7175(define_expand "sge"
7db9af5d 7176 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7177 (ge:SI (match_dup 1) (const_int 0)))]
cffb2a26 7178 "TARGET_ARM"
7179 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7180)
9c08d1fa 7181
7182(define_expand "slt"
7db9af5d 7183 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7184 (lt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7185 "TARGET_ARM"
7186 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7187)
9c08d1fa 7188
7189(define_expand "sgtu"
7db9af5d 7190 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7191 (gtu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7192 "TARGET_ARM"
7193 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7194)
9c08d1fa 7195
7196(define_expand "sleu"
7db9af5d 7197 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7198 (leu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7199 "TARGET_ARM"
7200 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7201)
9c08d1fa 7202
7203(define_expand "sgeu"
7db9af5d 7204 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7205 (geu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7206 "TARGET_ARM"
7207 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7208)
9c08d1fa 7209
7210(define_expand "sltu"
7db9af5d 7211 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7212 (ltu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7213 "TARGET_ARM"
7214 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7215)
9c08d1fa 7216
8fa3ba89 7217(define_expand "sunordered"
7db9af5d 7218 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7219 (unordered:SI (match_dup 1) (const_int 0)))]
a2cd141b 7220 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7221 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7222 arm_compare_op1);"
7223)
7224
7225(define_expand "sordered"
7db9af5d 7226 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7227 (ordered:SI (match_dup 1) (const_int 0)))]
a2cd141b 7228 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7229 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7230 arm_compare_op1);"
7231)
7232
7233(define_expand "sungt"
7db9af5d 7234 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7235 (ungt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7236 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7237 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7238 arm_compare_op1);"
7239)
7240
7241(define_expand "sunge"
7db9af5d 7242 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7243 (unge:SI (match_dup 1) (const_int 0)))]
a2cd141b 7244 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7245 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7246 arm_compare_op1);"
7247)
7248
7249(define_expand "sunlt"
7db9af5d 7250 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7251 (unlt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7252 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7253 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7254 arm_compare_op1);"
7255)
7256
7257(define_expand "sunle"
7db9af5d 7258 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7259 (unle:SI (match_dup 1) (const_int 0)))]
a2cd141b 7260 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7261 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7262 arm_compare_op1);"
7263)
7264
7265;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7266;;; simple ARM instructions.
7267;
7268; (define_expand "suneq"
7db9af5d 7269; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7270; (uneq:SI (match_dup 1) (const_int 0)))]
a2cd141b 7271; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
ed29c566 7272; "gcc_unreachable ();"
8fa3ba89 7273; )
7274;
7275; (define_expand "sltgt"
7db9af5d 7276; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7277; (ltgt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7278; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
ed29c566 7279; "gcc_unreachable ();"
8fa3ba89 7280; )
7281
f7fbdd4a 7282(define_insn "*mov_scc"
9c08d1fa 7283 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7284 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7285 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7286 "TARGET_ARM"
4d61e570 7287 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7288 [(set_attr "conds" "use")
7289 (set_attr "length" "8")]
7290)
9c08d1fa 7291
f7fbdd4a 7292(define_insn "*mov_negscc"
9c08d1fa 7293 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7294 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7295 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7296 "TARGET_ARM"
4d61e570 7297 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7298 [(set_attr "conds" "use")
7299 (set_attr "length" "8")]
7300)
9c08d1fa 7301
f7fbdd4a 7302(define_insn "*mov_notscc"
9c08d1fa 7303 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7304 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7305 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7306 "TARGET_ARM"
4d61e570 7307 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7308 [(set_attr "conds" "use")
7309 (set_attr "length" "8")]
7310)
9c08d1fa 7311
7312\f
39b5e676 7313;; Conditional move insns
7314
7315(define_expand "movsicc"
8a18b90c 7316 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7317 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7318 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7319 (match_operand:SI 3 "arm_not_operand" "")))]
cffb2a26 7320 "TARGET_ARM"
39b5e676 7321 "
215b30b3 7322 {
7323 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7324 rtx ccreg;
7325
7326 if (code == UNEQ || code == LTGT)
7327 FAIL;
39b5e676 7328
278b301d 7329 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7330 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7331 }"
7332)
39b5e676 7333
7334(define_expand "movsfcc"
8a18b90c 7335 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7336 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7337 (match_operand:SF 2 "s_register_operand" "")
7338 (match_operand:SF 3 "nonmemory_operand" "")))]
cffb2a26 7339 "TARGET_ARM"
39b5e676 7340 "
215b30b3 7341 {
7342 enum rtx_code code = GET_CODE (operands[1]);
7343 rtx ccreg;
f082f1c4 7344
278b301d 7345 if (code == UNEQ || code == LTGT)
7346 FAIL;
7347
215b30b3 7348 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7349 Otherwise, ensure it is a valid FP add operand */
7350 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7351 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7352 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7353
215b30b3 7354 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7355 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7356 }"
7357)
39b5e676 7358
7359(define_expand "movdfcc"
8a18b90c 7360 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7361 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7362 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7363 (match_operand:DF 3 "arm_float_add_operand" "")))]
7364 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 7365 "
215b30b3 7366 {
7367 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7368 rtx ccreg;
39b5e676 7369
278b301d 7370 if (code == UNEQ || code == LTGT)
7371 FAIL;
7372
7373 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7374 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7375 }"
7376)
39b5e676 7377
7378(define_insn "*movsicc_insn"
f082f1c4 7379 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7380 (if_then_else:SI
8fa3ba89 7381 (match_operator 3 "arm_comparison_operator"
8a18b90c 7382 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7383 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7384 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7385 "TARGET_ARM"
39b5e676 7386 "@
8a18b90c 7387 mov%D3\\t%0, %2
7388 mvn%D3\\t%0, #%B2
f082f1c4 7389 mov%d3\\t%0, %1
7390 mvn%d3\\t%0, #%B1
8a18b90c 7391 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7392 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7393 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7394 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7395 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 7396 (set_attr "conds" "use")]
7397)
39b5e676 7398
39b5e676 7399(define_insn "*movsfcc_soft_insn"
f082f1c4 7400 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7401 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7402 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7403 (match_operand:SF 1 "s_register_operand" "0,r")
7404 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7405 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7406 "@
7407 mov%D3\\t%0, %2
7408 mov%d3\\t%0, %1"
8fa3ba89 7409 [(set_attr "conds" "use")]
7410)
39b5e676 7411
39b5e676 7412\f
9c08d1fa 7413;; Jump and linkage insns
7414
cffb2a26 7415(define_expand "jump"
9c08d1fa 7416 [(set (pc)
7417 (label_ref (match_operand 0 "" "")))]
cffb2a26 7418 "TARGET_EITHER"
9c08d1fa 7419 ""
cffb2a26 7420)
7421
7422(define_insn "*arm_jump"
7423 [(set (pc)
7424 (label_ref (match_operand 0 "" "")))]
7425 "TARGET_ARM"
9c08d1fa 7426 "*
0d66636f 7427 {
7428 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7429 {
7430 arm_ccfsm_state += 2;
7431 return \"\";
7432 }
7433 return \"b%?\\t%l0\";
7434 }
7435 "
7436 [(set_attr "predicable" "yes")]
7437)
9c08d1fa 7438
cffb2a26 7439(define_insn "*thumb_jump"
7440 [(set (pc)
7441 (label_ref (match_operand 0 "" "")))]
7442 "TARGET_THUMB"
7443 "*
7444 if (get_attr_length (insn) == 2)
7445 return \"b\\t%l0\";
7446 return \"bl\\t%l0\\t%@ far jump\";
7447 "
7448 [(set (attr "far_jump")
7449 (if_then_else
7450 (eq_attr "length" "4")
7451 (const_string "yes")
7452 (const_string "no")))
7453 (set (attr "length")
7454 (if_then_else
911ed8af 7455 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7456 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7457 (const_int 2)
7458 (const_int 4)))]
7459)
7460
d3373b54 7461(define_expand "call"
7462 [(parallel [(call (match_operand 0 "memory_operand" "")
7463 (match_operand 1 "general_operand" ""))
cffb2a26 7464 (use (match_operand 2 "" ""))
bd5b4116 7465 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7466 "TARGET_EITHER"
6c4c2133 7467 "
7468 {
78fe751b 7469 rtx callee;
bbe777ea 7470
bbe777ea 7471 /* In an untyped call, we can get NULL for operand 2. */
7472 if (operands[2] == NULL_RTX)
7473 operands[2] = const0_rtx;
7474
78fe751b 7475 /* This is to decide if we should generate indirect calls by loading the
7476 32 bit address of the callee into a register before performing the
7477 branch and link. operand[2] encodes the long_call/short_call
7478 attribute of the function being called. This attribute is set whenever
7479 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7480 is used, and the short_call attribute can also be set if function is
7481 declared as static or if it has already been defined in the current
7482 compilation unit. See arm.c and arm.h for info about this. The third
7483 parameter to arm_is_longcall_p is used to tell it which pattern
7484 invoked it. */
7485 callee = XEXP (operands[0], 0);
7486
bbe777ea 7487 if (GET_CODE (callee) != REG
7488 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7489 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6c4c2133 7490 }"
7491)
d3373b54 7492
f1039640 7493(define_insn "*call_reg_armv5"
d3373b54 7494 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7495 (match_operand 1 "" ""))
7496 (use (match_operand 2 "" ""))
bd5b4116 7497 (clobber (reg:SI LR_REGNUM))]
f1039640 7498 "TARGET_ARM && arm_arch5"
7499 "blx%?\\t%0"
7500 [(set_attr "type" "call")]
7501)
7502
7503(define_insn "*call_reg_arm"
7504 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7505 (match_operand 1 "" ""))
7506 (use (match_operand 2 "" ""))
7507 (clobber (reg:SI LR_REGNUM))]
7508 "TARGET_ARM && !arm_arch5"
9c08d1fa 7509 "*
5565501b 7510 return output_call (operands);
cffb2a26 7511 "
7512 ;; length is worst case, normally it is only two
7513 [(set_attr "length" "12")
7514 (set_attr "type" "call")]
7515)
9c08d1fa 7516
f7fbdd4a 7517(define_insn "*call_mem"
6c4c2133 7518 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
cffb2a26 7519 (match_operand 1 "" ""))
7520 (use (match_operand 2 "" ""))
bd5b4116 7521 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7522 "TARGET_ARM"
9c08d1fa 7523 "*
5565501b 7524 return output_call_mem (operands);
cffb2a26 7525 "
7526 [(set_attr "length" "12")
7527 (set_attr "type" "call")]
7528)
7529
f1039640 7530(define_insn "*call_reg_thumb_v5"
cffb2a26 7531 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7532 (match_operand 1 "" ""))
7533 (use (match_operand 2 "" ""))
bd5b4116 7534 (clobber (reg:SI LR_REGNUM))]
f1039640 7535 "TARGET_THUMB && arm_arch5"
7536 "blx\\t%0"
7537 [(set_attr "length" "2")
7538 (set_attr "type" "call")]
cffb2a26 7539)
7540
f1039640 7541(define_insn "*call_reg_thumb"
7542 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7543 (match_operand 1 "" ""))
7544 (use (match_operand 2 "" ""))
bd5b4116 7545 (clobber (reg:SI LR_REGNUM))]
f1039640 7546 "TARGET_THUMB && !arm_arch5"
cffb2a26 7547 "*
7548 {
150502c9 7549 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7550 return thumb_call_via_reg (operands[0]);
150502c9 7551 else if (operands[1] == const0_rtx)
f1039640 7552 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7553 else if (frame_pointer_needed)
7554 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7555 else
150502c9 7556 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7557 }"
7558 [(set_attr "type" "call")]
7559)
9c08d1fa 7560
d3373b54 7561(define_expand "call_value"
e0698af7 7562 [(parallel [(set (match_operand 0 "" "")
7563 (call (match_operand 1 "memory_operand" "")
7564 (match_operand 2 "general_operand" "")))
cffb2a26 7565 (use (match_operand 3 "" ""))
bd5b4116 7566 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7567 "TARGET_EITHER"
6c4c2133 7568 "
7569 {
bbe777ea 7570 rtx callee = XEXP (operands[1], 0);
7571
7572 /* In an untyped call, we can get NULL for operand 2. */
7573 if (operands[3] == 0)
7574 operands[3] = const0_rtx;
7575
7576 /* See the comment in define_expand \"call\". */
7577 if (GET_CODE (callee) != REG
7578 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
78fe751b 7579 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6c4c2133 7580 }"
7581)
d3373b54 7582
f1039640 7583(define_insn "*call_value_reg_armv5"
27ed6835 7584 [(set (match_operand 0 "" "")
755eb2b4 7585 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7586 (match_operand 2 "" "")))
bbe777ea 7587 (use (match_operand 3 "" ""))
bd5b4116 7588 (clobber (reg:SI LR_REGNUM))]
f1039640 7589 "TARGET_ARM && arm_arch5"
7590 "blx%?\\t%1"
7591 [(set_attr "type" "call")]
7592)
7593
7594(define_insn "*call_value_reg_arm"
7595 [(set (match_operand 0 "" "")
7596 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7597 (match_operand 2 "" "")))
7598 (use (match_operand 3 "" ""))
7599 (clobber (reg:SI LR_REGNUM))]
7600 "TARGET_ARM && !arm_arch5"
9c08d1fa 7601 "*
215b30b3 7602 return output_call (&operands[1]);
cffb2a26 7603 "
7604 [(set_attr "length" "12")
7605 (set_attr "type" "call")]
7606)
9c08d1fa 7607
f7fbdd4a 7608(define_insn "*call_value_mem"
27ed6835 7609 [(set (match_operand 0 "" "")
755eb2b4 7610 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
cffb2a26 7611 (match_operand 2 "" "")))
bbe777ea 7612 (use (match_operand 3 "" ""))
bd5b4116 7613 (clobber (reg:SI LR_REGNUM))]
215b30b3 7614 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7615 "*
215b30b3 7616 return output_call_mem (&operands[1]);
cffb2a26 7617 "
7618 [(set_attr "length" "12")
7619 (set_attr "type" "call")]
7620)
9c08d1fa 7621
f1039640 7622(define_insn "*call_value_reg_thumb_v5"
7623 [(set (match_operand 0 "" "")
7624 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7625 (match_operand 2 "" "")))
7626 (use (match_operand 3 "" ""))
7627 (clobber (reg:SI LR_REGNUM))]
7628 "TARGET_THUMB && arm_arch5"
7629 "blx\\t%1"
7630 [(set_attr "length" "2")
7631 (set_attr "type" "call")]
7632)
7633
7634(define_insn "*call_value_reg_thumb"
7635 [(set (match_operand 0 "" "")
7636 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7637 (match_operand 2 "" "")))
7638 (use (match_operand 3 "" ""))
7639 (clobber (reg:SI LR_REGNUM))]
7640 "TARGET_THUMB && !arm_arch5"
7641 "*
7642 {
150502c9 7643 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7644 return thumb_call_via_reg (operands[1]);
150502c9 7645 else if (operands[2] == const0_rtx)
f1039640 7646 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7647 else if (frame_pointer_needed)
7648 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7649 else
150502c9 7650 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7651 }"
7652 [(set_attr "type" "call")]
7653)
7654
9c08d1fa 7655;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7656;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7657
f7fbdd4a 7658(define_insn "*call_symbol"
27ed6835 7659 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7660 (match_operand 1 "" ""))
bbe777ea 7661 (use (match_operand 2 "" ""))
bd5b4116 7662 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7663 "TARGET_ARM
7664 && (GET_CODE (operands[0]) == SYMBOL_REF)
215b30b3 7665 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6ebaa29d 7666 "*
7667 {
55c1e470 7668 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7669 }"
cffb2a26 7670 [(set_attr "type" "call")]
7671)
9c08d1fa 7672
f7fbdd4a 7673(define_insn "*call_value_symbol"
ccd90aaa 7674 [(set (match_operand 0 "" "")
27ed6835 7675 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7676 (match_operand:SI 2 "" "")))
bbe777ea 7677 (use (match_operand 3 "" ""))
bd5b4116 7678 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7679 "TARGET_ARM
7680 && (GET_CODE (operands[1]) == SYMBOL_REF)
215b30b3 7681 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6ebaa29d 7682 "*
7683 {
55c1e470 7684 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7685 }"
cffb2a26 7686 [(set_attr "type" "call")]
7687)
7688
7689(define_insn "*call_insn"
27ed6835 7690 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7691 (match_operand:SI 1 "" ""))
7692 (use (match_operand 2 "" ""))
bd5b4116 7693 (clobber (reg:SI LR_REGNUM))]
1c494086 7694 "TARGET_THUMB
1675c6e9 7695 && GET_CODE (operands[0]) == SYMBOL_REF
7696 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
cffb2a26 7697 "bl\\t%a0"
7698 [(set_attr "length" "4")
7699 (set_attr "type" "call")]
7700)
7701
7702(define_insn "*call_value_insn"
ccd90aaa 7703 [(set (match_operand 0 "" "")
27ed6835 7704 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 7705 (match_operand 2 "" "")))
7706 (use (match_operand 3 "" ""))
bd5b4116 7707 (clobber (reg:SI LR_REGNUM))]
1c494086 7708 "TARGET_THUMB
1675c6e9 7709 && GET_CODE (operands[1]) == SYMBOL_REF
7710 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
cffb2a26 7711 "bl\\t%a1"
7712 [(set_attr "length" "4")
7713 (set_attr "type" "call")]
7714)
9c08d1fa 7715
1c494086 7716;; We may also be able to do sibcalls for Thumb, but it's much harder...
7717(define_expand "sibcall"
7718 [(parallel [(call (match_operand 0 "memory_operand" "")
7719 (match_operand 1 "general_operand" ""))
2ba80634 7720 (return)
7721 (use (match_operand 2 "" ""))])]
1c494086 7722 "TARGET_ARM"
7723 "
7724 {
7725 if (operands[2] == NULL_RTX)
7726 operands[2] = const0_rtx;
1c494086 7727 }"
7728)
7729
7730(define_expand "sibcall_value"
ccd90aaa 7731 [(parallel [(set (match_operand 0 "" "")
1c494086 7732 (call (match_operand 1 "memory_operand" "")
7733 (match_operand 2 "general_operand" "")))
2ba80634 7734 (return)
7735 (use (match_operand 3 "" ""))])]
1c494086 7736 "TARGET_ARM"
7737 "
7738 {
7739 if (operands[3] == NULL_RTX)
7740 operands[3] = const0_rtx;
1c494086 7741 }"
7742)
7743
7744(define_insn "*sibcall_insn"
7745 [(call (mem:SI (match_operand:SI 0 "" "X"))
7746 (match_operand 1 "" ""))
2ba80634 7747 (return)
7748 (use (match_operand 2 "" ""))]
1c494086 7749 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7750 "*
7751 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7752 "
7753 [(set_attr "type" "call")]
7754)
7755
7756(define_insn "*sibcall_value_insn"
ccd90aaa 7757 [(set (match_operand 0 "" "")
755eb2b4 7758 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 7759 (match_operand 2 "" "")))
2ba80634 7760 (return)
7761 (use (match_operand 3 "" ""))]
1c494086 7762 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7763 "*
7764 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7765 "
7766 [(set_attr "type" "call")]
7767)
7768
9c08d1fa 7769;; Often the return insn will be the same as loading from memory, so set attr
7770(define_insn "return"
7771 [(return)]
cffb2a26 7772 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7773 "*
9c08d1fa 7774 {
cffb2a26 7775 if (arm_ccfsm_state == 2)
7776 {
7777 arm_ccfsm_state += 2;
7778 return \"\";
7779 }
5db468b7 7780 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 7781 }"
a2cd141b 7782 [(set_attr "type" "load1")
755eb2b4 7783 (set_attr "length" "12")
0d66636f 7784 (set_attr "predicable" "yes")]
cffb2a26 7785)
9c08d1fa 7786
f7fbdd4a 7787(define_insn "*cond_return"
9c08d1fa 7788 [(set (pc)
8fa3ba89 7789 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7790 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7791 (return)
7792 (pc)))]
cffb2a26 7793 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7794 "*
8fa3ba89 7795 {
7796 if (arm_ccfsm_state == 2)
7797 {
7798 arm_ccfsm_state += 2;
7799 return \"\";
7800 }
7801 return output_return_instruction (operands[0], TRUE, FALSE);
7802 }"
7803 [(set_attr "conds" "use")
755eb2b4 7804 (set_attr "length" "12")
a2cd141b 7805 (set_attr "type" "load1")]
8fa3ba89 7806)
9c08d1fa 7807
f7fbdd4a 7808(define_insn "*cond_return_inverted"
9c08d1fa 7809 [(set (pc)
8fa3ba89 7810 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7811 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7812 (pc)
7813 (return)))]
cffb2a26 7814 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7815 "*
8fa3ba89 7816 {
7817 if (arm_ccfsm_state == 2)
7818 {
7819 arm_ccfsm_state += 2;
7820 return \"\";
7821 }
7822 return output_return_instruction (operands[0], TRUE, TRUE);
7823 }"
7824 [(set_attr "conds" "use")
37a1317b 7825 (set_attr "length" "12")
a2cd141b 7826 (set_attr "type" "load1")]
8fa3ba89 7827)
9c08d1fa 7828
68121397 7829;; Generate a sequence of instructions to determine if the processor is
7830;; in 26-bit or 32-bit mode, and return the appropriate return address
7831;; mask.
7832
7833(define_expand "return_addr_mask"
7834 [(set (match_dup 1)
7835 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7836 (const_int 0)))
7837 (set (match_operand:SI 0 "s_register_operand" "")
7838 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7839 (const_int -1)
7840 (const_int 67108860)))] ; 0x03fffffc
7841 "TARGET_ARM"
7842 "
62eddbd4 7843 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7844 ")
7845
7846(define_insn "*check_arch2"
7847 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7848 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7849 (const_int 0)))]
7850 "TARGET_ARM"
7851 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7852 [(set_attr "length" "8")
7853 (set_attr "conds" "set")]
7854)
7855
9c08d1fa 7856;; Call subroutine returning any type.
7857
7858(define_expand "untyped_call"
7859 [(parallel [(call (match_operand 0 "" "")
7860 (const_int 0))
7861 (match_operand 1 "" "")
7862 (match_operand 2 "" "")])]
ccd90aaa 7863 "TARGET_EITHER"
9c08d1fa 7864 "
215b30b3 7865 {
7866 int i;
ccd90aaa 7867 rtx par = gen_rtx_PARALLEL (VOIDmode,
7868 rtvec_alloc (XVECLEN (operands[2], 0)));
7869 rtx addr = gen_reg_rtx (Pmode);
7870 rtx mem;
7871 int size = 0;
9c08d1fa 7872
ccd90aaa 7873 emit_move_insn (addr, XEXP (operands[1], 0));
7874 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7875
215b30b3 7876 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7877 {
ccd90aaa 7878 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7879
ccd90aaa 7880 /* Default code only uses r0 as a return value, but we could
7881 be using anything up to 4 registers. */
7882 if (REGNO (src) == R0_REGNUM)
7883 src = gen_rtx_REG (TImode, R0_REGNUM);
7884
7885 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7886 GEN_INT (size));
7887 size += GET_MODE_SIZE (GET_MODE (src));
7888 }
7889
7890 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7891 const0_rtx));
7892
7893 size = 0;
7894
7895 for (i = 0; i < XVECLEN (par, 0); i++)
7896 {
7897 HOST_WIDE_INT offset = 0;
7898 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7899
7900 if (size != 0)
7901 emit_move_insn (addr, plus_constant (addr, size));
7902
7903 mem = change_address (mem, GET_MODE (reg), NULL);
7904 if (REGNO (reg) == R0_REGNUM)
7905 {
7906 /* On thumb we have to use a write-back instruction. */
7907 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7908 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7909 size = TARGET_ARM ? 16 : 0;
7910 }
7911 else
7912 {
7913 emit_move_insn (mem, reg);
7914 size = GET_MODE_SIZE (GET_MODE (reg));
7915 }
215b30b3 7916 }
9c08d1fa 7917
215b30b3 7918 /* The optimizer does not know that the call sets the function value
7919 registers we stored in the result block. We avoid problems by
7920 claiming that all hard registers are used and clobbered at this
7921 point. */
7922 emit_insn (gen_blockage ());
7923
7924 DONE;
7925 }"
7926)
9c08d1fa 7927
ccd90aaa 7928(define_expand "untyped_return"
7929 [(match_operand:BLK 0 "memory_operand" "")
7930 (match_operand 1 "" "")]
7931 "TARGET_EITHER"
7932 "
7933 {
7934 int i;
7935 rtx addr = gen_reg_rtx (Pmode);
7936 rtx mem;
7937 int size = 0;
7938
7939 emit_move_insn (addr, XEXP (operands[0], 0));
7940 mem = change_address (operands[0], BLKmode, addr);
7941
7942 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7943 {
7944 HOST_WIDE_INT offset = 0;
7945 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7946
7947 if (size != 0)
7948 emit_move_insn (addr, plus_constant (addr, size));
7949
7950 mem = change_address (mem, GET_MODE (reg), NULL);
7951 if (REGNO (reg) == R0_REGNUM)
7952 {
7953 /* On thumb we have to use a write-back instruction. */
7954 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7955 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7956 size = TARGET_ARM ? 16 : 0;
7957 }
7958 else
7959 {
7960 emit_move_insn (reg, mem);
7961 size = GET_MODE_SIZE (GET_MODE (reg));
7962 }
7963 }
7964
7965 /* Emit USE insns before the return. */
7966 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7967 emit_insn (gen_rtx_USE (VOIDmode,
7968 SET_DEST (XVECEXP (operands[1], 0, i))));
7969
7970 /* Construct the return. */
7971 expand_naked_return ();
7972
7973 DONE;
7974 }"
7975)
7976
9c08d1fa 7977;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7978;; all of memory. This blocks insns from being moved across this point.
7979
7980(define_insn "blockage"
e1159bbe 7981 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 7982 "TARGET_EITHER"
9c08d1fa 7983 ""
cffb2a26 7984 [(set_attr "length" "0")
7985 (set_attr "type" "block")]
7986)
9c08d1fa 7987
f7fbdd4a 7988(define_expand "casesi"
7989 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 7990 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7991 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 7992 (match_operand:SI 3 "" "") ; table label
7993 (match_operand:SI 4 "" "")] ; Out of range label
cffb2a26 7994 "TARGET_ARM"
f7fbdd4a 7995 "
215b30b3 7996 {
7997 rtx reg;
7998 if (operands[1] != const0_rtx)
7999 {
8000 reg = gen_reg_rtx (SImode);
f7fbdd4a 8001
215b30b3 8002 emit_insn (gen_addsi3 (reg, operands[0],
8003 GEN_INT (-INTVAL (operands[1]))));
8004 operands[0] = reg;
8005 }
9c08d1fa 8006
215b30b3 8007 if (!const_ok_for_arm (INTVAL (operands[2])))
8008 operands[2] = force_reg (SImode, operands[2]);
8009
8010 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8011 operands[4]));
8012 DONE;
8013 }"
8014)
f7fbdd4a 8015
f082f1c4 8016;; The USE in this pattern is needed to tell flow analysis that this is
8017;; a CASESI insn. It has no other purpose.
f7fbdd4a 8018(define_insn "casesi_internal"
f082f1c4 8019 [(parallel [(set (pc)
8020 (if_then_else
8021 (leu (match_operand:SI 0 "s_register_operand" "r")
8022 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8023 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8024 (label_ref (match_operand 2 "" ""))))
8025 (label_ref (match_operand 3 "" ""))))
bd5b4116 8026 (clobber (reg:CC CC_REGNUM))
f082f1c4 8027 (use (label_ref (match_dup 2)))])]
cffb2a26 8028 "TARGET_ARM"
f7fbdd4a 8029 "*
0d66636f 8030 if (flag_pic)
8031 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8032 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8033 "
8034 [(set_attr "conds" "clob")
8035 (set_attr "length" "12")]
8036)
9c08d1fa 8037
cffb2a26 8038(define_expand "indirect_jump"
9c08d1fa 8039 [(set (pc)
cffb2a26 8040 (match_operand:SI 0 "s_register_operand" ""))]
8041 "TARGET_EITHER"
9c08d1fa 8042 ""
cffb2a26 8043)
8044
f1039640 8045;; NB Never uses BX.
cffb2a26 8046(define_insn "*arm_indirect_jump"
8047 [(set (pc)
8048 (match_operand:SI 0 "s_register_operand" "r"))]
8049 "TARGET_ARM"
8050 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8051 [(set_attr "predicable" "yes")]
cffb2a26 8052)
9c08d1fa 8053
f7fbdd4a 8054(define_insn "*load_indirect_jump"
9c08d1fa 8055 [(set (pc)
8056 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8057 "TARGET_ARM"
8058 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8059 [(set_attr "type" "load1")
61a2d04c 8060 (set_attr "pool_range" "4096")
8061 (set_attr "neg_pool_range" "4084")
0d66636f 8062 (set_attr "predicable" "yes")]
cffb2a26 8063)
8064
f1039640 8065;; NB Never uses BX.
cffb2a26 8066(define_insn "*thumb_indirect_jump"
8067 [(set (pc)
8068 (match_operand:SI 0 "register_operand" "l*r"))]
8069 "TARGET_THUMB"
8070 "mov\\tpc, %0"
8071 [(set_attr "conds" "clob")
8072 (set_attr "length" "2")]
8073)
8074
9c08d1fa 8075\f
8076;; Misc insns
8077
8078(define_insn "nop"
8079 [(const_int 0)]
cffb2a26 8080 "TARGET_EITHER"
8081 "*
8082 if (TARGET_ARM)
8083 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8084 return \"mov\\tr8, r8\";
8085 "
8086 [(set (attr "length")
8087 (if_then_else (eq_attr "is_thumb" "yes")
8088 (const_int 2)
8089 (const_int 4)))]
8090)
8091
9c08d1fa 8092\f
8093;; Patterns to allow combination of arithmetic, cond code and shifts
8094
f7fbdd4a 8095(define_insn "*arith_shiftsi"
9c08d1fa 8096 [(set (match_operand:SI 0 "s_register_operand" "=r")
8097 (match_operator:SI 1 "shiftable_operator"
8098 [(match_operator:SI 3 "shift_operator"
8099 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8100 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8101 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8102 "TARGET_ARM"
6c4c2133 8103 "%i1%?\\t%0, %2, %4%S3"
344495ea 8104 [(set_attr "predicable" "yes")
331beb1a 8105 (set_attr "shift" "4")
a2cd141b 8106 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8107 (const_string "alu_shift")
8108 (const_string "alu_shift_reg")))]
6c4c2133 8109)
9c08d1fa 8110
d7863cfe 8111(define_split
8112 [(set (match_operand:SI 0 "s_register_operand" "")
8113 (match_operator:SI 1 "shiftable_operator"
8114 [(match_operator:SI 2 "shiftable_operator"
8115 [(match_operator:SI 3 "shift_operator"
8116 [(match_operand:SI 4 "s_register_operand" "")
8117 (match_operand:SI 5 "reg_or_int_operand" "")])
8118 (match_operand:SI 6 "s_register_operand" "")])
8119 (match_operand:SI 7 "arm_rhs_operand" "")]))
8120 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8121 "TARGET_ARM"
8122 [(set (match_dup 8)
8123 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8124 (match_dup 6)]))
8125 (set (match_dup 0)
8126 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8127 "")
8128
f7fbdd4a 8129(define_insn "*arith_shiftsi_compare0"
bd5b4116 8130 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8131 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8132 [(match_operator:SI 3 "shift_operator"
8133 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8134 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8135 (match_operand:SI 2 "s_register_operand" "r")])
8136 (const_int 0)))
8137 (set (match_operand:SI 0 "s_register_operand" "=r")
8138 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8139 (match_dup 2)]))]
cffb2a26 8140 "TARGET_ARM"
87b22bf7 8141 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8142 [(set_attr "conds" "set")
331beb1a 8143 (set_attr "shift" "4")
a2cd141b 8144 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8145 (const_string "alu_shift")
8146 (const_string "alu_shift_reg")))]
0d66636f 8147)
9c08d1fa 8148
f7fbdd4a 8149(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8150 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8151 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8152 [(match_operator:SI 3 "shift_operator"
8153 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8154 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8155 (match_operand:SI 2 "s_register_operand" "r")])
8156 (const_int 0)))
8157 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8158 "TARGET_ARM"
87b22bf7 8159 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8160 [(set_attr "conds" "set")
331beb1a 8161 (set_attr "shift" "4")
a2cd141b 8162 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8163 (const_string "alu_shift")
8164 (const_string "alu_shift_reg")))]
0d66636f 8165)
9c08d1fa 8166
f7fbdd4a 8167(define_insn "*sub_shiftsi"
9c08d1fa 8168 [(set (match_operand:SI 0 "s_register_operand" "=r")
8169 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8170 (match_operator:SI 2 "shift_operator"
8171 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8172 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 8173 "TARGET_ARM"
6c4c2133 8174 "sub%?\\t%0, %1, %3%S2"
344495ea 8175 [(set_attr "predicable" "yes")
331beb1a 8176 (set_attr "shift" "3")
a2cd141b 8177 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8178 (const_string "alu_shift")
8179 (const_string "alu_shift_reg")))]
6c4c2133 8180)
9c08d1fa 8181
f7fbdd4a 8182(define_insn "*sub_shiftsi_compare0"
bd5b4116 8183 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8184 (compare:CC_NOOV
8185 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8186 (match_operator:SI 2 "shift_operator"
8187 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8188 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8189 (const_int 0)))
9c08d1fa 8190 (set (match_operand:SI 0 "s_register_operand" "=r")
8191 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8192 (match_dup 4)])))]
cffb2a26 8193 "TARGET_ARM"
87b22bf7 8194 "sub%?s\\t%0, %1, %3%S2"
344495ea 8195 [(set_attr "conds" "set")
a2cd141b 8196 (set_attr "shift" "3")
8197 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8198 (const_string "alu_shift")
8199 (const_string "alu_shift_reg")))]
0d66636f 8200)
9c08d1fa 8201
f7fbdd4a 8202(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8203 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8204 (compare:CC_NOOV
8205 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8206 (match_operator:SI 2 "shift_operator"
8207 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8208 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8209 (const_int 0)))
9c08d1fa 8210 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8211 "TARGET_ARM"
87b22bf7 8212 "sub%?s\\t%0, %1, %3%S2"
344495ea 8213 [(set_attr "conds" "set")
a2cd141b 8214 (set_attr "shift" "3")
8215 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8216 (const_string "alu_shift")
8217 (const_string "alu_shift_reg")))]
0d66636f 8218)
9c08d1fa 8219
9c08d1fa 8220\f
8221
f7fbdd4a 8222(define_insn "*and_scc"
9c08d1fa 8223 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8224 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8225 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8226 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8227 "TARGET_ARM"
e2348bcb 8228 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8229 [(set_attr "conds" "use")
8230 (set_attr "length" "8")]
8231)
9c08d1fa 8232
f7fbdd4a 8233(define_insn "*ior_scc"
9c08d1fa 8234 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8235 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8236 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8237 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8238 "TARGET_ARM"
e2348bcb 8239 "@
899850b0 8240 orr%d2\\t%0, %1, #1
8241 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8242 [(set_attr "conds" "use")
8243 (set_attr "length" "4,8")]
8244)
9c08d1fa 8245
f7fbdd4a 8246(define_insn "*compare_scc"
5565501b 8247 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8248 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8249 [(match_operand:SI 2 "s_register_operand" "r,r")
8250 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8251 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8252 "TARGET_ARM"
9c08d1fa 8253 "*
601f584c 8254 if (operands[3] == const0_rtx)
8255 {
8256 if (GET_CODE (operands[1]) == LT)
8257 return \"mov\\t%0, %2, lsr #31\";
8258
8259 if (GET_CODE (operands[1]) == GE)
8260 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 8261
601f584c 8262 if (GET_CODE (operands[1]) == EQ)
8263 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8264 }
e2348bcb 8265
8fa3ba89 8266 if (GET_CODE (operands[1]) == NE)
8267 {
8268 if (which_alternative == 1)
8269 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8270 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8271 }
8272 if (which_alternative == 1)
8273 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8274 else
8275 output_asm_insn (\"cmp\\t%2, %3\", operands);
8276 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8277 "
8278 [(set_attr "conds" "clob")
8279 (set_attr "length" "12")]
8280)
9c08d1fa 8281
f7fbdd4a 8282(define_insn "*cond_move"
9c08d1fa 8283 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8284 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8285 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8286 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8287 (const_int 0)])
8288 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8289 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8290 "TARGET_ARM"
9c08d1fa 8291 "*
8fa3ba89 8292 if (GET_CODE (operands[3]) == NE)
8293 {
8294 if (which_alternative != 1)
8295 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8296 if (which_alternative != 0)
8297 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8298 return \"\";
8299 }
8300 if (which_alternative != 0)
8301 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8302 if (which_alternative != 1)
8303 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8304 return \"\";
8305 "
8306 [(set_attr "conds" "use")
8307 (set_attr "length" "4,4,8")]
8308)
9c08d1fa 8309
f7fbdd4a 8310(define_insn "*cond_arith"
9c08d1fa 8311 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8312 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8313 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8314 [(match_operand:SI 2 "s_register_operand" "r,r")
8315 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8316 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8317 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8318 "TARGET_ARM"
9c08d1fa 8319 "*
8fa3ba89 8320 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8321 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8322
8fa3ba89 8323 output_asm_insn (\"cmp\\t%2, %3\", operands);
8324 if (GET_CODE (operands[5]) == AND)
8325 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8326 else if (GET_CODE (operands[5]) == MINUS)
8327 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8328 else if (which_alternative != 0)
8329 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8330 return \"%i5%d4\\t%0, %1, #1\";
8331 "
8332 [(set_attr "conds" "clob")
8333 (set_attr "length" "12")]
8334)
9c08d1fa 8335
f7fbdd4a 8336(define_insn "*cond_sub"
9c08d1fa 8337 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8338 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8339 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8340 [(match_operand:SI 2 "s_register_operand" "r,r")
8341 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8342 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8343 "TARGET_ARM"
9c08d1fa 8344 "*
8fa3ba89 8345 output_asm_insn (\"cmp\\t%2, %3\", operands);
8346 if (which_alternative != 0)
8347 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8348 return \"sub%d4\\t%0, %1, #1\";
8349 "
8350 [(set_attr "conds" "clob")
8351 (set_attr "length" "8,12")]
8352)
9c08d1fa 8353
aea4c774 8354(define_insn "*cmp_ite0"
cffb2a26 8355 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8356 (compare
8357 (if_then_else:SI
8fa3ba89 8358 (match_operator 4 "arm_comparison_operator"
aea4c774 8359 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8360 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8361 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8362 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8363 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8364 (const_int 0))
8365 (const_int 0)))]
cffb2a26 8366 "TARGET_ARM"
9c08d1fa 8367 "*
aea4c774 8368 {
8fa3ba89 8369 static const char * const opcodes[4][2] =
8370 {
8371 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8372 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8373 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8374 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8375 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8376 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8377 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8378 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8379 };
8380 int swap =
8381 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8382
8383 return opcodes[which_alternative][swap];
8384 }"
8385 [(set_attr "conds" "set")
8386 (set_attr "length" "8")]
8387)
9c08d1fa 8388
aea4c774 8389(define_insn "*cmp_ite1"
cffb2a26 8390 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8391 (compare
8392 (if_then_else:SI
8fa3ba89 8393 (match_operator 4 "arm_comparison_operator"
aea4c774 8394 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8395 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8396 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8397 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8398 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8399 (const_int 1))
8400 (const_int 0)))]
cffb2a26 8401 "TARGET_ARM"
9c08d1fa 8402 "*
9c08d1fa 8403 {
215b30b3 8404 static const char * const opcodes[4][2] =
8405 {
8406 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8407 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8408 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8409 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8410 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8411 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8412 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8413 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8414 };
8415 int swap =
8416 comparison_dominates_p (GET_CODE (operands[5]),
8417 reverse_condition (GET_CODE (operands[4])));
8418
8419 return opcodes[which_alternative][swap];
8420 }"
8fa3ba89 8421 [(set_attr "conds" "set")
8422 (set_attr "length" "8")]
8423)
9c08d1fa 8424
f6c53574 8425(define_insn "*cmp_and"
8426 [(set (match_operand 6 "dominant_cc_register" "")
8427 (compare
8428 (and:SI
8429 (match_operator 4 "arm_comparison_operator"
8430 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8431 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8432 (match_operator:SI 5 "arm_comparison_operator"
8433 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8434 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8435 (const_int 0)))]
8436 "TARGET_ARM"
8437 "*
8438 {
35823b64 8439 static const char *const opcodes[4][2] =
f6c53574 8440 {
8441 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8442 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8443 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8444 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8445 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8446 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8447 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8448 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8449 };
8450 int swap =
8451 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8452
8453 return opcodes[which_alternative][swap];
8454 }"
8455 [(set_attr "conds" "set")
8456 (set_attr "predicable" "no")
8457 (set_attr "length" "8")]
8458)
8459
8460(define_insn "*cmp_ior"
8461 [(set (match_operand 6 "dominant_cc_register" "")
8462 (compare
8463 (ior:SI
8464 (match_operator 4 "arm_comparison_operator"
8465 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8466 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8467 (match_operator:SI 5 "arm_comparison_operator"
8468 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8469 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8470 (const_int 0)))]
8471 "TARGET_ARM"
8472 "*
8473{
35823b64 8474 static const char *const opcodes[4][2] =
f6c53574 8475 {
8476 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8477 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8478 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8479 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8480 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8481 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8482 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8483 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8484 };
8485 int swap =
8486 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8487
8488 return opcodes[which_alternative][swap];
8489}
8490"
8491 [(set_attr "conds" "set")
8492 (set_attr "length" "8")]
8493)
8494
3c5afce6 8495(define_insn_and_split "*ior_scc_scc"
8496 [(set (match_operand:SI 0 "s_register_operand" "=r")
8497 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8498 [(match_operand:SI 1 "s_register_operand" "r")
8499 (match_operand:SI 2 "arm_add_operand" "rIL")])
8500 (match_operator:SI 6 "arm_comparison_operator"
8501 [(match_operand:SI 4 "s_register_operand" "r")
8502 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8503 (clobber (reg:CC CC_REGNUM))]
8504 "TARGET_ARM
8505 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8506 != CCmode)"
8507 "#"
8508 "TARGET_ARM && reload_completed"
8509 [(set (match_dup 7)
8510 (compare
8511 (ior:SI
8512 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8513 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8514 (const_int 0)))
8515 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8516 "operands[7]
8517 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8518 DOM_CC_X_OR_Y),
601f584c 8519 CC_REGNUM);"
8520 [(set_attr "conds" "clob")
8521 (set_attr "length" "16")])
8522
8523; If the above pattern is followed by a CMP insn, then the compare is
8524; redundant, since we can rework the conditional instruction that follows.
8525(define_insn_and_split "*ior_scc_scc_cmp"
8526 [(set (match_operand 0 "dominant_cc_register" "")
8527 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8528 [(match_operand:SI 1 "s_register_operand" "r")
8529 (match_operand:SI 2 "arm_add_operand" "rIL")])
8530 (match_operator:SI 6 "arm_comparison_operator"
8531 [(match_operand:SI 4 "s_register_operand" "r")
8532 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8533 (const_int 0)))
8534 (set (match_operand:SI 7 "s_register_operand" "=r")
8535 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8536 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8537 "TARGET_ARM"
8538 "#"
8539 "TARGET_ARM && reload_completed"
8540 [(set (match_dup 0)
8541 (compare
8542 (ior:SI
8543 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8544 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8545 (const_int 0)))
8546 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8547 ""
8548 [(set_attr "conds" "set")
8549 (set_attr "length" "16")])
3c5afce6 8550
8551(define_insn_and_split "*and_scc_scc"
8552 [(set (match_operand:SI 0 "s_register_operand" "=r")
8553 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8554 [(match_operand:SI 1 "s_register_operand" "r")
8555 (match_operand:SI 2 "arm_add_operand" "rIL")])
8556 (match_operator:SI 6 "arm_comparison_operator"
8557 [(match_operand:SI 4 "s_register_operand" "r")
8558 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8559 (clobber (reg:CC CC_REGNUM))]
8560 "TARGET_ARM
8561 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8562 != CCmode)"
8563 "#"
601f584c 8564 "TARGET_ARM && reload_completed
8565 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8566 != CCmode)"
3c5afce6 8567 [(set (match_dup 7)
8568 (compare
8569 (and:SI
8570 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8571 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8572 (const_int 0)))
8573 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8574 "operands[7]
8575 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8576 DOM_CC_X_AND_Y),
601f584c 8577 CC_REGNUM);"
8578 [(set_attr "conds" "clob")
8579 (set_attr "length" "16")])
8580
8581; If the above pattern is followed by a CMP insn, then the compare is
8582; redundant, since we can rework the conditional instruction that follows.
8583(define_insn_and_split "*and_scc_scc_cmp"
8584 [(set (match_operand 0 "dominant_cc_register" "")
8585 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8586 [(match_operand:SI 1 "s_register_operand" "r")
8587 (match_operand:SI 2 "arm_add_operand" "rIL")])
8588 (match_operator:SI 6 "arm_comparison_operator"
8589 [(match_operand:SI 4 "s_register_operand" "r")
8590 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8591 (const_int 0)))
8592 (set (match_operand:SI 7 "s_register_operand" "=r")
8593 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8594 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8595 "TARGET_ARM"
8596 "#"
8597 "TARGET_ARM && reload_completed"
8598 [(set (match_dup 0)
8599 (compare
8600 (and:SI
8601 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8602 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8603 (const_int 0)))
8604 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8605 ""
8606 [(set_attr "conds" "set")
8607 (set_attr "length" "16")])
8608
8609;; If there is no dominance in the comparison, then we can still save an
8610;; instruction in the AND case, since we can know that the second compare
8611;; need only zero the value if false (if true, then the value is already
8612;; correct).
8613(define_insn_and_split "*and_scc_scc_nodom"
8614 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8615 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8616 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8617 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8618 (match_operator:SI 6 "arm_comparison_operator"
8619 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8620 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8621 (clobber (reg:CC CC_REGNUM))]
8622 "TARGET_ARM
8623 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8624 == CCmode)"
8625 "#"
8626 "TARGET_ARM && reload_completed"
8627 [(parallel [(set (match_dup 0)
8628 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8629 (clobber (reg:CC CC_REGNUM))])
8630 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8631 (set (match_dup 0)
8632 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8633 (match_dup 0)
8634 (const_int 0)))]
8635 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8636 operands[4], operands[5]),
8637 CC_REGNUM);
8638 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8639 operands[5]);"
8640 [(set_attr "conds" "clob")
8641 (set_attr "length" "20")])
3c5afce6 8642
3a0bdee0 8643(define_split
8644 [(set (reg:CC_NOOV CC_REGNUM)
8645 (compare:CC_NOOV (ior:SI
8646 (and:SI (match_operand:SI 0 "s_register_operand" "")
8647 (const_int 1))
8648 (match_operator:SI 1 "comparison_operator"
8649 [(match_operand:SI 2 "s_register_operand" "")
8650 (match_operand:SI 3 "arm_add_operand" "")]))
8651 (const_int 0)))
8652 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8653 "TARGET_ARM"
8654 [(set (match_dup 4)
8655 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8656 (match_dup 0)))
8657 (set (reg:CC_NOOV CC_REGNUM)
8658 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8659 (const_int 0)))]
8660 "")
8661
8662(define_split
8663 [(set (reg:CC_NOOV CC_REGNUM)
8664 (compare:CC_NOOV (ior:SI
8665 (match_operator:SI 1 "comparison_operator"
8666 [(match_operand:SI 2 "s_register_operand" "")
8667 (match_operand:SI 3 "arm_add_operand" "")])
8668 (and:SI (match_operand:SI 0 "s_register_operand" "")
8669 (const_int 1)))
8670 (const_int 0)))
8671 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8672 "TARGET_ARM"
8673 [(set (match_dup 4)
8674 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8675 (match_dup 0)))
8676 (set (reg:CC_NOOV CC_REGNUM)
8677 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8678 (const_int 0)))]
8679 "")
8680
f7fbdd4a 8681(define_insn "*negscc"
9c08d1fa 8682 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8683 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 8684 [(match_operand:SI 1 "s_register_operand" "r")
8685 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 8686 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8687 "TARGET_ARM"
9c08d1fa 8688 "*
f0e75574 8689 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
e2348bcb 8690 return \"mov\\t%0, %1, asr #31\";
8691
9c08d1fa 8692 if (GET_CODE (operands[3]) == NE)
e2348bcb 8693 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8694
9c08d1fa 8695 if (GET_CODE (operands[3]) == GT)
e2348bcb 8696 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8697
8698 output_asm_insn (\"cmp\\t%1, %2\", operands);
8699 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8700 return \"mvn%d3\\t%0, #0\";
215b30b3 8701 "
8fa3ba89 8702 [(set_attr "conds" "clob")
8703 (set_attr "length" "12")]
8704)
9c08d1fa 8705
8706(define_insn "movcond"
8707 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 8708 (if_then_else:SI
8fa3ba89 8709 (match_operator 5 "arm_comparison_operator"
5565501b 8710 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8711 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8712 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8713 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 8714 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8715 "TARGET_ARM"
9c08d1fa 8716 "*
8717 if (GET_CODE (operands[5]) == LT
8718 && (operands[4] == const0_rtx))
8719 {
5565501b 8720 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 8721 {
9c08d1fa 8722 if (operands[2] == const0_rtx)
e2348bcb 8723 return \"and\\t%0, %1, %3, asr #31\";
8724 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 8725 }
8726 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8727 {
9c08d1fa 8728 if (operands[1] == const0_rtx)
e2348bcb 8729 return \"bic\\t%0, %2, %3, asr #31\";
8730 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 8731 }
8732 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8733 are constants. */
9c08d1fa 8734 }
e2348bcb 8735
9c08d1fa 8736 if (GET_CODE (operands[5]) == GE
8737 && (operands[4] == const0_rtx))
8738 {
8739 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8740 {
9c08d1fa 8741 if (operands[2] == const0_rtx)
e2348bcb 8742 return \"bic\\t%0, %1, %3, asr #31\";
8743 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 8744 }
8745 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8746 {
9c08d1fa 8747 if (operands[1] == const0_rtx)
e2348bcb 8748 return \"and\\t%0, %2, %3, asr #31\";
8749 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 8750 }
8751 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8752 are constants. */
9c08d1fa 8753 }
8754 if (GET_CODE (operands[4]) == CONST_INT
8755 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 8756 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 8757 else
e2348bcb 8758 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 8759 if (which_alternative != 0)
e2348bcb 8760 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 8761 if (which_alternative != 1)
e2348bcb 8762 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 8763 return \"\";
215b30b3 8764 "
8fa3ba89 8765 [(set_attr "conds" "clob")
8766 (set_attr "length" "8,8,12")]
8767)
9c08d1fa 8768
8a18b90c 8769(define_insn "*ifcompare_plus_move"
8770 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8771 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8772 [(match_operand:SI 4 "s_register_operand" "r,r")
8773 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8774 (plus:SI
8775 (match_operand:SI 2 "s_register_operand" "r,r")
8776 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 8777 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8778 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8779 "TARGET_ARM"
8a18b90c 8780 "#"
8fa3ba89 8781 [(set_attr "conds" "clob")
8782 (set_attr "length" "8,12")]
8783)
8a18b90c 8784
8785(define_insn "*if_plus_move"
129a2fe4 8786 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8787 (if_then_else:SI
8fa3ba89 8788 (match_operator 4 "arm_comparison_operator"
8a18b90c 8789 [(match_operand 5 "cc_register" "") (const_int 0)])
8790 (plus:SI
129a2fe4 8791 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8792 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8793 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 8794 "TARGET_ARM"
8a18b90c 8795 "@
8796 add%d4\\t%0, %2, %3
8797 sub%d4\\t%0, %2, #%n3
8798 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 8799 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 8800 [(set_attr "conds" "use")
8801 (set_attr "length" "4,4,8,8")
8802 (set_attr "type" "*,*,*,*")]
8803)
8a18b90c 8804
8805(define_insn "*ifcompare_move_plus"
5565501b 8806 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8807 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8808 [(match_operand:SI 4 "s_register_operand" "r,r")
8809 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8810 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8811 (plus:SI
8812 (match_operand:SI 2 "s_register_operand" "r,r")
8813 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 8814 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8815 "TARGET_ARM"
8a18b90c 8816 "#"
8fa3ba89 8817 [(set_attr "conds" "clob")
8818 (set_attr "length" "8,12")]
8819)
8a18b90c 8820
8821(define_insn "*if_move_plus"
129a2fe4 8822 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8823 (if_then_else:SI
8fa3ba89 8824 (match_operator 4 "arm_comparison_operator"
8a18b90c 8825 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 8826 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 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"))))]
cffb2a26 8830 "TARGET_ARM"
8a18b90c 8831 "@
8832 add%D4\\t%0, %2, %3
8833 sub%D4\\t%0, %2, #%n3
8834 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 8835 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 8836 [(set_attr "conds" "use")
8837 (set_attr "length" "4,4,8,8")
8838 (set_attr "type" "*,*,*,*")]
8839)
8a18b90c 8840
8841(define_insn "*ifcompare_arith_arith"
8842 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8843 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 8844 [(match_operand:SI 5 "s_register_operand" "r")
8845 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 8846 (match_operator:SI 8 "shiftable_operator"
8a18b90c 8847 [(match_operand:SI 1 "s_register_operand" "r")
8848 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 8849 (match_operator:SI 7 "shiftable_operator"
8a18b90c 8850 [(match_operand:SI 3 "s_register_operand" "r")
8851 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 8852 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8853 "TARGET_ARM"
8a18b90c 8854 "#"
8fa3ba89 8855 [(set_attr "conds" "clob")
8856 (set_attr "length" "12")]
8857)
9c08d1fa 8858
8a18b90c 8859(define_insn "*if_arith_arith"
8860 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8861 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 8862 [(match_operand 8 "cc_register" "") (const_int 0)])
8863 (match_operator:SI 6 "shiftable_operator"
8864 [(match_operand:SI 1 "s_register_operand" "r")
8865 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8866 (match_operator:SI 7 "shiftable_operator"
8867 [(match_operand:SI 3 "s_register_operand" "r")
8868 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 8869 "TARGET_ARM"
8a18b90c 8870 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 8871 [(set_attr "conds" "use")
8872 (set_attr "length" "8")]
8873)
8a18b90c 8874
f7fbdd4a 8875(define_insn "*ifcompare_arith_move"
9c08d1fa 8876 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8877 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8878 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 8879 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 8880 (match_operator:SI 7 "shiftable_operator"
8881 [(match_operand:SI 4 "s_register_operand" "r,r")
8882 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 8883 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8884 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8885 "TARGET_ARM"
9c08d1fa 8886 "*
9c08d1fa 8887 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8888 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 8889 everything is in registers then we can do this in two instructions. */
9c08d1fa 8890 if (operands[3] == const0_rtx
8891 && GET_CODE (operands[7]) != AND
8892 && GET_CODE (operands[5]) == REG
8893 && GET_CODE (operands[1]) == REG
8894 && REGNO (operands[1]) == REGNO (operands[4])
8895 && REGNO (operands[4]) != REGNO (operands[0]))
8896 {
8897 if (GET_CODE (operands[6]) == LT)
40dbec34 8898 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8899 else if (GET_CODE (operands[6]) == GE)
40dbec34 8900 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8901 }
8902 if (GET_CODE (operands[3]) == CONST_INT
8903 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 8904 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 8905 else
e2348bcb 8906 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 8907 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 8908 if (which_alternative != 0)
129a2fe4 8909 return \"mov%D6\\t%0, %1\";
9c08d1fa 8910 return \"\";
215b30b3 8911 "
8fa3ba89 8912 [(set_attr "conds" "clob")
8913 (set_attr "length" "8,12")]
8914)
9c08d1fa 8915
8a18b90c 8916(define_insn "*if_arith_move"
129a2fe4 8917 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8918 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 8919 [(match_operand 6 "cc_register" "") (const_int 0)])
8920 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8921 [(match_operand:SI 2 "s_register_operand" "r,r")
8922 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8923 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 8924 "TARGET_ARM"
8a18b90c 8925 "@
8926 %I5%d4\\t%0, %2, %3
129a2fe4 8927 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 8928 [(set_attr "conds" "use")
8929 (set_attr "length" "4,8")
8930 (set_attr "type" "*,*")]
8931)
8a18b90c 8932
f7fbdd4a 8933(define_insn "*ifcompare_move_arith"
9c08d1fa 8934 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8935 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8936 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 8937 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8938 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 8939 (match_operator:SI 7 "shiftable_operator"
8940 [(match_operand:SI 2 "s_register_operand" "r,r")
8941 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8942 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8943 "TARGET_ARM"
9c08d1fa 8944 "*
9c08d1fa 8945 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8946 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 8947 everything is in registers then we can do this in two instructions */
8948 if (operands[5] == const0_rtx
8949 && GET_CODE (operands[7]) != AND
8950 && GET_CODE (operands[3]) == REG
8951 && GET_CODE (operands[1]) == REG
8952 && REGNO (operands[1]) == REGNO (operands[2])
8953 && REGNO (operands[2]) != REGNO (operands[0]))
8954 {
8955 if (GET_CODE (operands[6]) == GE)
40dbec34 8956 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8957 else if (GET_CODE (operands[6]) == LT)
40dbec34 8958 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8959 }
40dbec34 8960
9c08d1fa 8961 if (GET_CODE (operands[5]) == CONST_INT
8962 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 8963 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 8964 else
e2348bcb 8965 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 8966
9c08d1fa 8967 if (which_alternative != 0)
129a2fe4 8968 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 8969 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 8970 "
8fa3ba89 8971 [(set_attr "conds" "clob")
8972 (set_attr "length" "8,12")]
8973)
9c08d1fa 8974
8a18b90c 8975(define_insn "*if_move_arith"
129a2fe4 8976 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 8977 (if_then_else:SI
8fa3ba89 8978 (match_operator 4 "arm_comparison_operator"
8a18b90c 8979 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 8980 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8981 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8982 [(match_operand:SI 2 "s_register_operand" "r,r")
8983 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 8984 "TARGET_ARM"
8a18b90c 8985 "@
8986 %I5%D4\\t%0, %2, %3
129a2fe4 8987 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 8988 [(set_attr "conds" "use")
8989 (set_attr "length" "4,8")
8990 (set_attr "type" "*,*")]
8991)
8a18b90c 8992
8993(define_insn "*ifcompare_move_not"
9c08d1fa 8994 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 8995 (if_then_else:SI
8fa3ba89 8996 (match_operator 5 "arm_comparison_operator"
8a18b90c 8997 [(match_operand:SI 3 "s_register_operand" "r,r")
8998 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8999 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9000 (not:SI
9001 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9002 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9003 "TARGET_ARM"
8a18b90c 9004 "#"
8fa3ba89 9005 [(set_attr "conds" "clob")
9006 (set_attr "length" "8,12")]
9007)
9c08d1fa 9008
8a18b90c 9009(define_insn "*if_move_not"
9010 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9011 (if_then_else:SI
8fa3ba89 9012 (match_operator 4 "arm_comparison_operator"
8a18b90c 9013 [(match_operand 3 "cc_register" "") (const_int 0)])
9014 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9015 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9016 "TARGET_ARM"
8a18b90c 9017 "@
9018 mvn%D4\\t%0, %2
9019 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9020 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9021 [(set_attr "conds" "use")
9022 (set_attr "length" "4,8,8")]
9023)
8a18b90c 9024
9025(define_insn "*ifcompare_not_move"
9c08d1fa 9026 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9027 (if_then_else:SI
8fa3ba89 9028 (match_operator 5 "arm_comparison_operator"
8a18b90c 9029 [(match_operand:SI 3 "s_register_operand" "r,r")
9030 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9031 (not:SI
9032 (match_operand:SI 2 "s_register_operand" "r,r"))
9033 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9034 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9035 "TARGET_ARM"
8a18b90c 9036 "#"
8fa3ba89 9037 [(set_attr "conds" "clob")
9038 (set_attr "length" "8,12")]
9039)
9c08d1fa 9040
8a18b90c 9041(define_insn "*if_not_move"
9042 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9043 (if_then_else:SI
8fa3ba89 9044 (match_operator 4 "arm_comparison_operator"
8a18b90c 9045 [(match_operand 3 "cc_register" "") (const_int 0)])
9046 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9047 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9048 "TARGET_ARM"
8a18b90c 9049 "@
9050 mvn%d4\\t%0, %2
9051 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9052 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9053 [(set_attr "conds" "use")
9054 (set_attr "length" "4,8,8")]
9055)
8a18b90c 9056
9057(define_insn "*ifcompare_shift_move"
9c08d1fa 9058 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9059 (if_then_else:SI
8fa3ba89 9060 (match_operator 6 "arm_comparison_operator"
8a18b90c 9061 [(match_operand:SI 4 "s_register_operand" "r,r")
9062 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9063 (match_operator:SI 7 "shift_operator"
9064 [(match_operand:SI 2 "s_register_operand" "r,r")
9065 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9066 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9067 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9068 "TARGET_ARM"
9c08d1fa 9069 "#"
8fa3ba89 9070 [(set_attr "conds" "clob")
9071 (set_attr "length" "8,12")]
9072)
9c08d1fa 9073
8a18b90c 9074(define_insn "*if_shift_move"
9075 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9076 (if_then_else:SI
8fa3ba89 9077 (match_operator 5 "arm_comparison_operator"
8a18b90c 9078 [(match_operand 6 "cc_register" "") (const_int 0)])
9079 (match_operator:SI 4 "shift_operator"
9080 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9081 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9082 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9083 "TARGET_ARM"
5565501b 9084 "@
8a18b90c 9085 mov%d5\\t%0, %2%S4
9086 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9087 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9088 [(set_attr "conds" "use")
331beb1a 9089 (set_attr "shift" "2")
a2cd141b 9090 (set_attr "length" "4,8,8")
9091 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9092 (const_string "alu_shift")
9093 (const_string "alu_shift_reg")))]
8fa3ba89 9094)
5565501b 9095
8a18b90c 9096(define_insn "*ifcompare_move_shift"
9097 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9098 (if_then_else:SI
8fa3ba89 9099 (match_operator 6 "arm_comparison_operator"
8a18b90c 9100 [(match_operand:SI 4 "s_register_operand" "r,r")
9101 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9102 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9103 (match_operator:SI 7 "shift_operator"
8a18b90c 9104 [(match_operand:SI 2 "s_register_operand" "r,r")
9105 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9106 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9107 "TARGET_ARM"
8a18b90c 9108 "#"
8fa3ba89 9109 [(set_attr "conds" "clob")
9110 (set_attr "length" "8,12")]
9111)
5565501b 9112
8a18b90c 9113(define_insn "*if_move_shift"
9114 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9115 (if_then_else:SI
8fa3ba89 9116 (match_operator 5 "arm_comparison_operator"
8a18b90c 9117 [(match_operand 6 "cc_register" "") (const_int 0)])
9118 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9119 (match_operator:SI 4 "shift_operator"
9120 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9121 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9122 "TARGET_ARM"
5565501b 9123 "@
8a18b90c 9124 mov%D5\\t%0, %2%S4
9125 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9126 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9127 [(set_attr "conds" "use")
331beb1a 9128 (set_attr "shift" "2")
a2cd141b 9129 (set_attr "length" "4,8,8")
9130 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9131 (const_string "alu_shift")
9132 (const_string "alu_shift_reg")))]
8fa3ba89 9133)
9c08d1fa 9134
f7fbdd4a 9135(define_insn "*ifcompare_shift_shift"
8a18b90c 9136 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9137 (if_then_else:SI
8fa3ba89 9138 (match_operator 7 "arm_comparison_operator"
8a18b90c 9139 [(match_operand:SI 5 "s_register_operand" "r")
9140 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9141 (match_operator:SI 8 "shift_operator"
8a18b90c 9142 [(match_operand:SI 1 "s_register_operand" "r")
9143 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9144 (match_operator:SI 9 "shift_operator"
8a18b90c 9145 [(match_operand:SI 3 "s_register_operand" "r")
9146 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9147 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9148 "TARGET_ARM"
8a18b90c 9149 "#"
8fa3ba89 9150 [(set_attr "conds" "clob")
9151 (set_attr "length" "12")]
9152)
9c08d1fa 9153
8a18b90c 9154(define_insn "*if_shift_shift"
9155 [(set (match_operand:SI 0 "s_register_operand" "=r")
9156 (if_then_else:SI
8fa3ba89 9157 (match_operator 5 "arm_comparison_operator"
8a18b90c 9158 [(match_operand 8 "cc_register" "") (const_int 0)])
9159 (match_operator:SI 6 "shift_operator"
9160 [(match_operand:SI 1 "s_register_operand" "r")
9161 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9162 (match_operator:SI 7 "shift_operator"
9163 [(match_operand:SI 3 "s_register_operand" "r")
9164 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9165 "TARGET_ARM"
8a18b90c 9166 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9167 [(set_attr "conds" "use")
331beb1a 9168 (set_attr "shift" "1")
a2cd141b 9169 (set_attr "length" "8")
9170 (set (attr "type") (if_then_else
9171 (and (match_operand 2 "const_int_operand" "")
9172 (match_operand 4 "const_int_operand" ""))
9173 (const_string "alu_shift")
9174 (const_string "alu_shift_reg")))]
8fa3ba89 9175)
8a18b90c 9176
f7fbdd4a 9177(define_insn "*ifcompare_not_arith"
8a18b90c 9178 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9179 (if_then_else:SI
8fa3ba89 9180 (match_operator 6 "arm_comparison_operator"
8a18b90c 9181 [(match_operand:SI 4 "s_register_operand" "r")
9182 (match_operand:SI 5 "arm_add_operand" "rIL")])
9183 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9184 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9185 [(match_operand:SI 2 "s_register_operand" "r")
9186 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9187 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9188 "TARGET_ARM"
8a18b90c 9189 "#"
8fa3ba89 9190 [(set_attr "conds" "clob")
9191 (set_attr "length" "12")]
9192)
9c08d1fa 9193
8a18b90c 9194(define_insn "*if_not_arith"
9195 [(set (match_operand:SI 0 "s_register_operand" "=r")
9196 (if_then_else:SI
8fa3ba89 9197 (match_operator 5 "arm_comparison_operator"
8a18b90c 9198 [(match_operand 4 "cc_register" "") (const_int 0)])
9199 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9200 (match_operator:SI 6 "shiftable_operator"
9201 [(match_operand:SI 2 "s_register_operand" "r")
9202 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9203 "TARGET_ARM"
8a18b90c 9204 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9205 [(set_attr "conds" "use")
9206 (set_attr "length" "8")]
9207)
8a18b90c 9208
9209(define_insn "*ifcompare_arith_not"
9210 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9211 (if_then_else:SI
8fa3ba89 9212 (match_operator 6 "arm_comparison_operator"
8a18b90c 9213 [(match_operand:SI 4 "s_register_operand" "r")
9214 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9215 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9216 [(match_operand:SI 2 "s_register_operand" "r")
9217 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9218 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9219 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9220 "TARGET_ARM"
8a18b90c 9221 "#"
8fa3ba89 9222 [(set_attr "conds" "clob")
9223 (set_attr "length" "12")]
9224)
9c08d1fa 9225
8a18b90c 9226(define_insn "*if_arith_not"
9227 [(set (match_operand:SI 0 "s_register_operand" "=r")
9228 (if_then_else:SI
8fa3ba89 9229 (match_operator 5 "arm_comparison_operator"
8a18b90c 9230 [(match_operand 4 "cc_register" "") (const_int 0)])
9231 (match_operator:SI 6 "shiftable_operator"
9232 [(match_operand:SI 2 "s_register_operand" "r")
9233 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9234 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9235 "TARGET_ARM"
8a18b90c 9236 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9237 [(set_attr "conds" "use")
9238 (set_attr "length" "8")]
9239)
8a18b90c 9240
f7fbdd4a 9241(define_insn "*ifcompare_neg_move"
8a18b90c 9242 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9243 (if_then_else:SI
8fa3ba89 9244 (match_operator 5 "arm_comparison_operator"
8a18b90c 9245 [(match_operand:SI 3 "s_register_operand" "r,r")
9246 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9247 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9248 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9249 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9250 "TARGET_ARM"
8a18b90c 9251 "#"
8fa3ba89 9252 [(set_attr "conds" "clob")
9253 (set_attr "length" "8,12")]
9254)
8a18b90c 9255
9256(define_insn "*if_neg_move"
9257 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9258 (if_then_else:SI
8fa3ba89 9259 (match_operator 4 "arm_comparison_operator"
8a18b90c 9260 [(match_operand 3 "cc_register" "") (const_int 0)])
9261 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9262 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9263 "TARGET_ARM"
8a18b90c 9264 "@
9265 rsb%d4\\t%0, %2, #0
9266 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9267 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9268 [(set_attr "conds" "use")
9269 (set_attr "length" "4,8,8")]
9270)
9c08d1fa 9271
f7fbdd4a 9272(define_insn "*ifcompare_move_neg"
8a18b90c 9273 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9274 (if_then_else:SI
8fa3ba89 9275 (match_operator 5 "arm_comparison_operator"
8a18b90c 9276 [(match_operand:SI 3 "s_register_operand" "r,r")
9277 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9278 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9279 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9280 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9281 "TARGET_ARM"
8a18b90c 9282 "#"
8fa3ba89 9283 [(set_attr "conds" "clob")
9284 (set_attr "length" "8,12")]
9285)
8a18b90c 9286
9287(define_insn "*if_move_neg"
9288 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9289 (if_then_else:SI
8fa3ba89 9290 (match_operator 4 "arm_comparison_operator"
8a18b90c 9291 [(match_operand 3 "cc_register" "") (const_int 0)])
9292 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9293 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9294 "TARGET_ARM"
8a18b90c 9295 "@
9296 rsb%D4\\t%0, %2, #0
9297 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9298 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9299 [(set_attr "conds" "use")
9300 (set_attr "length" "4,8,8")]
9301)
9c08d1fa 9302
f7fbdd4a 9303(define_insn "*arith_adjacentmem"
9c08d1fa 9304 [(set (match_operand:SI 0 "s_register_operand" "=r")
9305 (match_operator:SI 1 "shiftable_operator"
9306 [(match_operand:SI 2 "memory_operand" "m")
9307 (match_operand:SI 3 "memory_operand" "m")]))
9308 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9309 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9310 "*
215b30b3 9311 {
9312 rtx ldm[3];
9313 rtx arith[4];
94dee231 9314 rtx base_reg;
9315 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9316
215b30b3 9317 if (REGNO (operands[0]) > REGNO (operands[4]))
9318 {
9319 ldm[1] = operands[4];
9320 ldm[2] = operands[0];
9321 }
9322 else
9323 {
9324 ldm[1] = operands[0];
9325 ldm[2] = operands[4];
9326 }
94dee231 9327
9328 base_reg = XEXP (operands[2], 0);
9329
9330 if (!REG_P (base_reg))
9331 {
9332 val1 = INTVAL (XEXP (base_reg, 1));
9333 base_reg = XEXP (base_reg, 0);
9334 }
9335
9336 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9337 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9338
215b30b3 9339 arith[0] = operands[0];
9340 arith[3] = operands[1];
94dee231 9341
215b30b3 9342 if (val1 < val2)
9343 {
9344 arith[1] = ldm[1];
9345 arith[2] = ldm[2];
9346 }
9347 else
9348 {
9349 arith[1] = ldm[2];
9350 arith[2] = ldm[1];
9351 }
94dee231 9352
9353 ldm[0] = base_reg;
9354 if (val1 !=0 && val2 != 0)
215b30b3 9355 {
94dee231 9356 if (val1 == 4 || val2 == 4)
9357 /* Other val must be 8, since we know they are adjacent and neither
9358 is zero. */
9359 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
215b30b3 9360 else
94dee231 9361 {
9362 rtx ops[3];
9363
9364 ldm[0] = ops[0] = operands[4];
9365 ops[1] = base_reg;
9366 ops[2] = GEN_INT (val1);
9367 output_add_immediate (ops);
9368 if (val1 < val2)
9369 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9370 else
9371 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9372 }
215b30b3 9373 }
94dee231 9374 else if (val1 != 0)
215b30b3 9375 {
215b30b3 9376 if (val1 < val2)
9377 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9378 else
9379 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9380 }
9381 else
9382 {
215b30b3 9383 if (val1 < val2)
9384 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9385 else
9386 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9387 }
9388 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9389 return \"\";
9390 }"
9391 [(set_attr "length" "12")
9392 (set_attr "predicable" "yes")
a2cd141b 9393 (set_attr "type" "load1")]
215b30b3 9394)
9c08d1fa 9395
9396;; the arm can support extended pre-inc instructions
9397
9398;; In all these cases, we use operands 0 and 1 for the register being
9399;; incremented because those are the operands that local-alloc will
9400;; tie and these are the pair most likely to be tieable (and the ones
9401;; that will benefit the most).
9402
9403;; We reject the frame pointer if it occurs anywhere in these patterns since
9404;; elimination will cause too many headaches.
9405
f7fbdd4a 9406(define_insn "*strqi_preinc"
9c08d1fa 9407 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9408 (match_operand:SI 2 "index_operand" "rJ")))
9409 (match_operand:QI 3 "s_register_operand" "r"))
9410 (set (match_operand:SI 0 "s_register_operand" "=r")
9411 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9412 "TARGET_ARM
da45ccee 9413 && !arm_eliminable_register (operands[0])
9414 && !arm_eliminable_register (operands[1])
9415 && !arm_eliminable_register (operands[2])"
40dbec34 9416 "str%?b\\t%3, [%0, %2]!"
0d66636f 9417 [(set_attr "type" "store1")
9418 (set_attr "predicable" "yes")]
9419)
9c08d1fa 9420
f7fbdd4a 9421(define_insn "*strqi_predec"
9c08d1fa 9422 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9423 (match_operand:SI 2 "s_register_operand" "r")))
9424 (match_operand:QI 3 "s_register_operand" "r"))
9425 (set (match_operand:SI 0 "s_register_operand" "=r")
9426 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9427 "TARGET_ARM
da45ccee 9428 && !arm_eliminable_register (operands[0])
9429 && !arm_eliminable_register (operands[1])
9430 && !arm_eliminable_register (operands[2])"
40dbec34 9431 "str%?b\\t%3, [%0, -%2]!"
0d66636f 9432 [(set_attr "type" "store1")
9433 (set_attr "predicable" "yes")]
9434)
9c08d1fa 9435
f7fbdd4a 9436(define_insn "*loadqi_preinc"
9c08d1fa 9437 [(set (match_operand:QI 3 "s_register_operand" "=r")
9438 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9439 (match_operand:SI 2 "index_operand" "rJ"))))
9440 (set (match_operand:SI 0 "s_register_operand" "=r")
9441 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9442 "TARGET_ARM
da45ccee 9443 && !arm_eliminable_register (operands[0])
9444 && !arm_eliminable_register (operands[1])
9445 && !arm_eliminable_register (operands[2])"
40dbec34 9446 "ldr%?b\\t%3, [%0, %2]!"
a2cd141b 9447 [(set_attr "type" "load_byte")
0d66636f 9448 (set_attr "predicable" "yes")]
9449)
9c08d1fa 9450
f7fbdd4a 9451(define_insn "*loadqi_predec"
9c08d1fa 9452 [(set (match_operand:QI 3 "s_register_operand" "=r")
9453 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9454 (match_operand:SI 2 "s_register_operand" "r"))))
9455 (set (match_operand:SI 0 "s_register_operand" "=r")
9456 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9457 "TARGET_ARM
da45ccee 9458 && !arm_eliminable_register (operands[0])
9459 && !arm_eliminable_register (operands[1])
9460 && !arm_eliminable_register (operands[2])"
40dbec34 9461 "ldr%?b\\t%3, [%0, -%2]!"
a2cd141b 9462 [(set_attr "type" "load_byte")
0d66636f 9463 (set_attr "predicable" "yes")]
9464)
9c08d1fa 9465
f7fbdd4a 9466(define_insn "*loadqisi_preinc"
9c08d1fa 9467 [(set (match_operand:SI 3 "s_register_operand" "=r")
9468 (zero_extend:SI
9469 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9470 (match_operand:SI 2 "index_operand" "rJ")))))
9471 (set (match_operand:SI 0 "s_register_operand" "=r")
9472 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9473 "TARGET_ARM
da45ccee 9474 && !arm_eliminable_register (operands[0])
9475 && !arm_eliminable_register (operands[1])
9476 && !arm_eliminable_register (operands[2])"
40dbec34 9477 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
a2cd141b 9478 [(set_attr "type" "load_byte")
0d66636f 9479 (set_attr "predicable" "yes")]
9480)
9c08d1fa 9481
f7fbdd4a 9482(define_insn "*loadqisi_predec"
9c08d1fa 9483 [(set (match_operand:SI 3 "s_register_operand" "=r")
9484 (zero_extend:SI
9485 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9486 (match_operand:SI 2 "s_register_operand" "r")))))
9487 (set (match_operand:SI 0 "s_register_operand" "=r")
9488 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9489 "TARGET_ARM
da45ccee 9490 && !arm_eliminable_register (operands[0])
9491 && !arm_eliminable_register (operands[1])
9492 && !arm_eliminable_register (operands[2])"
40dbec34 9493 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
a2cd141b 9494 [(set_attr "type" "load_byte")
0d66636f 9495 (set_attr "predicable" "yes")]
9496)
9c08d1fa 9497
f7fbdd4a 9498(define_insn "*strsi_preinc"
9c08d1fa 9499 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9500 (match_operand:SI 2 "index_operand" "rJ")))
9501 (match_operand:SI 3 "s_register_operand" "r"))
9502 (set (match_operand:SI 0 "s_register_operand" "=r")
9503 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9504 "TARGET_ARM
da45ccee 9505 && !arm_eliminable_register (operands[0])
9506 && !arm_eliminable_register (operands[1])
9507 && !arm_eliminable_register (operands[2])"
40dbec34 9508 "str%?\\t%3, [%0, %2]!"
0d66636f 9509 [(set_attr "type" "store1")
9510 (set_attr "predicable" "yes")]
9511)
9c08d1fa 9512
cbd60e74 9513(define_insn "*strsi_predec"
9c08d1fa 9514 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9515 (match_operand:SI 2 "s_register_operand" "r")))
9516 (match_operand:SI 3 "s_register_operand" "r"))
9517 (set (match_operand:SI 0 "s_register_operand" "=r")
9518 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9519 "TARGET_ARM
da45ccee 9520 && !arm_eliminable_register (operands[0])
9521 && !arm_eliminable_register (operands[1])
9522 && !arm_eliminable_register (operands[2])"
40dbec34 9523 "str%?\\t%3, [%0, -%2]!"
0d66636f 9524 [(set_attr "type" "store1")
9525 (set_attr "predicable" "yes")]
9526)
9c08d1fa 9527
f7fbdd4a 9528(define_insn "*loadsi_preinc"
9c08d1fa 9529 [(set (match_operand:SI 3 "s_register_operand" "=r")
9530 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9531 (match_operand:SI 2 "index_operand" "rJ"))))
9532 (set (match_operand:SI 0 "s_register_operand" "=r")
9533 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9534 "TARGET_ARM
da45ccee 9535 && !arm_eliminable_register (operands[0])
9536 && !arm_eliminable_register (operands[1])
9537 && !arm_eliminable_register (operands[2])"
40dbec34 9538 "ldr%?\\t%3, [%0, %2]!"
a2cd141b 9539 [(set_attr "type" "load1")
0d66636f 9540 (set_attr "predicable" "yes")]
9541)
9c08d1fa 9542
f7fbdd4a 9543(define_insn "*loadsi_predec"
9c08d1fa 9544 [(set (match_operand:SI 3 "s_register_operand" "=r")
9545 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9546 (match_operand:SI 2 "s_register_operand" "r"))))
9547 (set (match_operand:SI 0 "s_register_operand" "=r")
9548 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9549 "TARGET_ARM
da45ccee 9550 && !arm_eliminable_register (operands[0])
9551 && !arm_eliminable_register (operands[1])
9552 && !arm_eliminable_register (operands[2])"
40dbec34 9553 "ldr%?\\t%3, [%0, -%2]!"
a2cd141b 9554 [(set_attr "type" "load1")
0d66636f 9555 (set_attr "predicable" "yes")]
9556)
9c08d1fa 9557
f7fbdd4a 9558(define_insn "*strqi_shiftpreinc"
9c08d1fa 9559 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9560 [(match_operand:SI 3 "s_register_operand" "r")
9561 (match_operand:SI 4 "const_shift_operand" "n")])
9562 (match_operand:SI 1 "s_register_operand" "0")))
9563 (match_operand:QI 5 "s_register_operand" "r"))
9564 (set (match_operand:SI 0 "s_register_operand" "=r")
9565 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9566 (match_dup 1)))]
cffb2a26 9567 "TARGET_ARM
da45ccee 9568 && !arm_eliminable_register (operands[0])
9569 && !arm_eliminable_register (operands[1])
9570 && !arm_eliminable_register (operands[3])"
87b22bf7 9571 "str%?b\\t%5, [%0, %3%S2]!"
0d66636f 9572 [(set_attr "type" "store1")
9573 (set_attr "predicable" "yes")]
9574)
9c08d1fa 9575
f7fbdd4a 9576(define_insn "*strqi_shiftpredec"
9c08d1fa 9577 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9578 (match_operator:SI 2 "shift_operator"
9579 [(match_operand:SI 3 "s_register_operand" "r")
9580 (match_operand:SI 4 "const_shift_operand" "n")])))
9581 (match_operand:QI 5 "s_register_operand" "r"))
9582 (set (match_operand:SI 0 "s_register_operand" "=r")
9583 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9584 (match_dup 4)])))]
cffb2a26 9585 "TARGET_ARM
da45ccee 9586 && !arm_eliminable_register (operands[0])
9587 && !arm_eliminable_register (operands[1])
9588 && !arm_eliminable_register (operands[3])"
87b22bf7 9589 "str%?b\\t%5, [%0, -%3%S2]!"
0d66636f 9590 [(set_attr "type" "store1")
9591 (set_attr "predicable" "yes")]
9592)
9c08d1fa 9593
f7fbdd4a 9594(define_insn "*loadqi_shiftpreinc"
9c08d1fa 9595 [(set (match_operand:QI 5 "s_register_operand" "=r")
9596 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9597 [(match_operand:SI 3 "s_register_operand" "r")
9598 (match_operand:SI 4 "const_shift_operand" "n")])
9599 (match_operand:SI 1 "s_register_operand" "0"))))
9600 (set (match_operand:SI 0 "s_register_operand" "=r")
9601 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9602 (match_dup 1)))]
cffb2a26 9603 "TARGET_ARM
da45ccee 9604 && !arm_eliminable_register (operands[0])
9605 && !arm_eliminable_register (operands[1])
9606 && !arm_eliminable_register (operands[3])"
87b22bf7 9607 "ldr%?b\\t%5, [%0, %3%S2]!"
a2cd141b 9608 [(set_attr "type" "load_byte")
0d66636f 9609 (set_attr "predicable" "yes")]
9610)
9c08d1fa 9611
f7fbdd4a 9612(define_insn "*loadqi_shiftpredec"
9c08d1fa 9613 [(set (match_operand:QI 5 "s_register_operand" "=r")
9614 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9615 (match_operator:SI 2 "shift_operator"
9616 [(match_operand:SI 3 "s_register_operand" "r")
9617 (match_operand:SI 4 "const_shift_operand" "n")]))))
9618 (set (match_operand:SI 0 "s_register_operand" "=r")
9619 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9620 (match_dup 4)])))]
cffb2a26 9621 "TARGET_ARM
da45ccee 9622 && !arm_eliminable_register (operands[0])
9623 && !arm_eliminable_register (operands[1])
9624 && !arm_eliminable_register (operands[3])"
87b22bf7 9625 "ldr%?b\\t%5, [%0, -%3%S2]!"
a2cd141b 9626 [(set_attr "type" "load_byte")
0d66636f 9627 (set_attr "predicable" "yes")]
9628)
9c08d1fa 9629
f7fbdd4a 9630(define_insn "*strsi_shiftpreinc"
9c08d1fa 9631 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9632 [(match_operand:SI 3 "s_register_operand" "r")
9633 (match_operand:SI 4 "const_shift_operand" "n")])
9634 (match_operand:SI 1 "s_register_operand" "0")))
9635 (match_operand:SI 5 "s_register_operand" "r"))
9636 (set (match_operand:SI 0 "s_register_operand" "=r")
9637 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9638 (match_dup 1)))]
cffb2a26 9639 "TARGET_ARM
da45ccee 9640 && !arm_eliminable_register (operands[0])
9641 && !arm_eliminable_register (operands[1])
9642 && !arm_eliminable_register (operands[3])"
87b22bf7 9643 "str%?\\t%5, [%0, %3%S2]!"
0d66636f 9644 [(set_attr "type" "store1")
9645 (set_attr "predicable" "yes")]
9646)
9c08d1fa 9647
f7fbdd4a 9648(define_insn "*strsi_shiftpredec"
9c08d1fa 9649 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9650 (match_operator:SI 2 "shift_operator"
9651 [(match_operand:SI 3 "s_register_operand" "r")
9652 (match_operand:SI 4 "const_shift_operand" "n")])))
9653 (match_operand:SI 5 "s_register_operand" "r"))
9654 (set (match_operand:SI 0 "s_register_operand" "=r")
9655 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9656 (match_dup 4)])))]
cffb2a26 9657 "TARGET_ARM
da45ccee 9658 && !arm_eliminable_register (operands[0])
9659 && !arm_eliminable_register (operands[1])
9660 && !arm_eliminable_register (operands[3])"
87b22bf7 9661 "str%?\\t%5, [%0, -%3%S2]!"
0d66636f 9662 [(set_attr "type" "store1")
9663 (set_attr "predicable" "yes")]
9664)
9c08d1fa 9665
cbd60e74 9666(define_insn "*loadsi_shiftpreinc"
9c08d1fa 9667 [(set (match_operand:SI 5 "s_register_operand" "=r")
9668 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9669 [(match_operand:SI 3 "s_register_operand" "r")
9670 (match_operand:SI 4 "const_shift_operand" "n")])
9671 (match_operand:SI 1 "s_register_operand" "0"))))
9672 (set (match_operand:SI 0 "s_register_operand" "=r")
9673 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9674 (match_dup 1)))]
cffb2a26 9675 "TARGET_ARM
da45ccee 9676 && !arm_eliminable_register (operands[0])
9677 && !arm_eliminable_register (operands[1])
9678 && !arm_eliminable_register (operands[3])"
87b22bf7 9679 "ldr%?\\t%5, [%0, %3%S2]!"
a2cd141b 9680 [(set_attr "type" "load1")
0d66636f 9681 (set_attr "predicable" "yes")]
9682)
9c08d1fa 9683
cbd60e74 9684(define_insn "*loadsi_shiftpredec"
9c08d1fa 9685 [(set (match_operand:SI 5 "s_register_operand" "=r")
9686 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9687 (match_operator:SI 2 "shift_operator"
9688 [(match_operand:SI 3 "s_register_operand" "r")
9689 (match_operand:SI 4 "const_shift_operand" "n")]))))
9690 (set (match_operand:SI 0 "s_register_operand" "=r")
9691 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9692 (match_dup 4)])))]
cffb2a26 9693 "TARGET_ARM
da45ccee 9694 && !arm_eliminable_register (operands[0])
9695 && !arm_eliminable_register (operands[1])
9696 && !arm_eliminable_register (operands[3])"
87b22bf7 9697 "ldr%?\\t%5, [%0, -%3%S2]!"
a2cd141b 9698 [(set_attr "type" "load1")
0d66636f 9699 (set_attr "predicable" "yes")])
9c08d1fa 9700
9c08d1fa 9701; It can also support extended post-inc expressions, but combine doesn't
9702; try these....
9703; It doesn't seem worth adding peepholes for anything but the most common
9704; cases since, unlike combine, the increment must immediately follow the load
9705; for this pattern to match.
fc40f3ac 9706; We must watch to see that the source/destination register isn't also the
9707; same as the base address register, and that if the index is a register,
9708; that it is not the same as the base address register. In such cases the
e3e08e7f 9709; instruction that we would generate would have UNPREDICTABLE behavior so
fc40f3ac 9710; we cannot use it.
9c08d1fa 9711
9712(define_peephole
9713 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9714 (match_operand:QI 2 "s_register_operand" "r"))
9715 (set (match_dup 0)
9716 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 9717 "TARGET_ARM
9718 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9719 && (GET_CODE (operands[1]) != REG
9720 || (REGNO (operands[1]) != REGNO (operands[0])))"
9721 "str%?b\\t%2, [%0], %1"
9722)
9c08d1fa 9723
9724(define_peephole
9725 [(set (match_operand:QI 0 "s_register_operand" "=r")
9726 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9727 (set (match_dup 1)
9728 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
fc40f3ac 9729 "TARGET_ARM
9730 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 9731 && (GET_CODE (operands[2]) != REG
9732 || REGNO(operands[0]) != REGNO (operands[2]))"
9733 "ldr%?b\\t%0, [%1], %2"
9734)
9c08d1fa 9735
9736(define_peephole
9737 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9738 (match_operand:SI 2 "s_register_operand" "r"))
9739 (set (match_dup 0)
9740 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 9741 "TARGET_ARM
9742 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9743 && (GET_CODE (operands[1]) != REG
9744 || (REGNO (operands[1]) != REGNO (operands[0])))"
9745 "str%?\\t%2, [%0], %1"
9746)
9c08d1fa 9747
9c08d1fa 9748(define_peephole
9749 [(set (match_operand:SI 0 "s_register_operand" "=r")
9750 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9751 (set (match_dup 1)
9752 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
cffb2a26 9753 "TARGET_ARM
fc40f3ac 9754 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 9755 && (GET_CODE (operands[2]) != REG
9756 || REGNO(operands[0]) != REGNO (operands[2]))"
9757 "ldr%?\\t%0, [%1], %2"
9758)
9c08d1fa 9759
c7597b5d 9760(define_peephole
9761 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9762 (match_operand:SI 1 "index_operand" "rJ")))
9763 (match_operand:QI 2 "s_register_operand" "r"))
9764 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
fc40f3ac 9765 "TARGET_ARM
9766 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9767 && (GET_CODE (operands[1]) != REG
9768 || (REGNO (operands[1]) != REGNO (operands[0])))"
9769 "str%?b\\t%2, [%0, %1]!"
9770)
c7597b5d 9771
9772(define_peephole
9773 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9774 [(match_operand:SI 0 "s_register_operand" "r")
87b22bf7 9775 (match_operand:SI 1 "const_int_operand" "n")])
c7597b5d 9776 (match_operand:SI 2 "s_register_operand" "+r")))
9777 (match_operand:QI 3 "s_register_operand" "r"))
9778 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9779 (match_dup 2)))]
fc40f3ac 9780 "TARGET_ARM
9781 && (REGNO (operands[3]) != REGNO (operands[2]))
9782 && (REGNO (operands[0]) != REGNO (operands[2]))"
215b30b3 9783 "str%?b\\t%3, [%2, %0%S4]!"
9784)
c7597b5d 9785
9c08d1fa 9786; This pattern is never tried by combine, so do it as a peephole
9787
a0f94409 9788(define_peephole2
372575c7 9789 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9790 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9791 (set (reg:CC CC_REGNUM)
aea4c774 9792 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9793 "TARGET_ARM"
a0f94409 9794 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9795 (set (match_dup 0) (match_dup 1))])]
9796 ""
0d66636f 9797)
9c08d1fa 9798
675d848d 9799; Peepholes to spot possible load- and store-multiples, if the ordering is
9800; reversed, check that the memory references aren't volatile.
9c08d1fa 9801
9802(define_peephole
9803 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9804 (match_operand:SI 4 "memory_operand" "m"))
9805 (set (match_operand:SI 1 "s_register_operand" "=r")
9806 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 9807 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9808 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 9809 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 9810 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 9811 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9812 "*
9813 return emit_ldm_seq (operands, 4);
215b30b3 9814 "
9815)
9c08d1fa 9816
9817(define_peephole
9818 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9819 (match_operand:SI 3 "memory_operand" "m"))
9820 (set (match_operand:SI 1 "s_register_operand" "=r")
9821 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 9822 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9823 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 9824 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9825 "*
9826 return emit_ldm_seq (operands, 3);
215b30b3 9827 "
9828)
9c08d1fa 9829
9830(define_peephole
9831 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9832 (match_operand:SI 2 "memory_operand" "m"))
9833 (set (match_operand:SI 1 "s_register_operand" "=r")
9834 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 9835 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9836 "*
9837 return emit_ldm_seq (operands, 2);
215b30b3 9838 "
9839)
9c08d1fa 9840
9841(define_peephole
aea4c774 9842 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 9843 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9844 (set (match_operand:SI 5 "memory_operand" "=m")
9845 (match_operand:SI 1 "s_register_operand" "r"))
9846 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 9847 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 9848 (set (match_operand:SI 7 "memory_operand" "=m")
9849 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 9850 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9851 "*
9852 return emit_stm_seq (operands, 4);
215b30b3 9853 "
9854)
9c08d1fa 9855
9856(define_peephole
aea4c774 9857 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 9858 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9859 (set (match_operand:SI 4 "memory_operand" "=m")
9860 (match_operand:SI 1 "s_register_operand" "r"))
9861 (set (match_operand:SI 5 "memory_operand" "=m")
9862 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 9863 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9864 "*
9865 return emit_stm_seq (operands, 3);
215b30b3 9866 "
9867)
9c08d1fa 9868
9869(define_peephole
aea4c774 9870 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 9871 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9872 (set (match_operand:SI 3 "memory_operand" "=m")
9873 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 9874 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9875 "*
9876 return emit_stm_seq (operands, 2);
215b30b3 9877 "
9878)
9c08d1fa 9879
9c08d1fa 9880(define_split
9881 [(set (match_operand:SI 0 "s_register_operand" "")
9882 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9883 (const_int 0))
8fa3ba89 9884 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9885 [(match_operand:SI 3 "s_register_operand" "")
9886 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9887 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9888 "TARGET_ARM"
9c08d1fa 9889 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9890 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9891 (match_dup 5)))]
215b30b3 9892 ""
9893)
9c08d1fa 9894
aea4c774 9895;; This split can be used because CC_Z mode implies that the following
9896;; branch will be an equality, or an unsigned inequality, so the sign
9897;; extension is not needed.
9c08d1fa 9898
aea4c774 9899(define_split
bd5b4116 9900 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9901 (compare:CC_Z
9902 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9903 (const_int 24))
aea4c774 9904 (match_operand 1 "const_int_operand" "")))
9905 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9906 "TARGET_ARM
9907 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9908 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9909 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9910 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9911 "
9c08d1fa 9912 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9913 "
9914)
9c08d1fa 9915
87b22bf7 9916(define_expand "prologue"
9917 [(clobber (const_int 0))]
cffb2a26 9918 "TARGET_EITHER"
9919 "if (TARGET_ARM)
9920 arm_expand_prologue ();
9921 else
9922 thumb_expand_prologue ();
87b22bf7 9923 DONE;
cffb2a26 9924 "
9925)
87b22bf7 9926
56d27660 9927(define_expand "epilogue"
4c44712e 9928 [(clobber (const_int 0))]
cffb2a26 9929 "TARGET_EITHER"
56d27660 9930 "
4c44712e 9931 if (current_function_calls_eh_return)
9932 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
cffb2a26 9933 if (TARGET_THUMB)
9934 thumb_expand_epilogue ();
9935 else if (USE_RETURN_INSN (FALSE))
56d27660 9936 {
9937 emit_jump_insn (gen_return ());
9938 DONE;
9939 }
cffb2a26 9940 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9941 gen_rtvec (1,
9942 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9943 VUNSPEC_EPILOGUE));
cffb2a26 9944 DONE;
9945 "
9946)
56d27660 9947
ef5651d0 9948;; Note - although unspec_volatile's USE all hard registers,
9949;; USEs are ignored after relaod has completed. Thus we need
9950;; to add an unspec of the link register to ensure that flow
9951;; does not think that it is unused by the sibcall branch that
9952;; will replace the standard function epilogue.
1c494086 9953(define_insn "sibcall_epilogue"
ef5651d0 9954 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9955 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
1c494086 9956 "TARGET_ARM"
9957 "*
ffc9d00c 9958 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9959 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9960 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9961 "
9962;; Length is absolute worst case
9963 [(set_attr "length" "44")
defc47cf 9964 (set_attr "type" "block")
9965 ;; We don't clobber the conditions, but the potential length of this
9966 ;; operation is sufficient to make conditionalizing the sequence
9967 ;; unlikely to be profitable.
9968 (set_attr "conds" "clob")]
1c494086 9969)
9970
cffb2a26 9971(define_insn "*epilogue_insns"
e1159bbe 9972 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9973 "TARGET_EITHER"
56d27660 9974 "*
cffb2a26 9975 if (TARGET_ARM)
ffc9d00c 9976 return arm_output_epilogue (NULL);
cffb2a26 9977 else /* TARGET_THUMB */
9978 return thumb_unexpanded_epilogue ();
9979 "
215b30b3 9980 ; Length is absolute worst case
cffb2a26 9981 [(set_attr "length" "44")
defc47cf 9982 (set_attr "type" "block")
9983 ;; We don't clobber the conditions, but the potential length of this
9984 ;; operation is sufficient to make conditionalizing the sequence
9985 ;; unlikely to be profitable.
9986 (set_attr "conds" "clob")]
cffb2a26 9987)
9988
9989(define_expand "eh_epilogue"
7db9af5d 9990 [(use (match_operand:SI 0 "register_operand" ""))
9991 (use (match_operand:SI 1 "register_operand" ""))
9992 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 9993 "TARGET_EITHER"
9994 "
215b30b3 9995 {
9996 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9997 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9998 {
9999 rtx ra = gen_rtx_REG (Pmode, 2);
10000
10001 emit_move_insn (ra, operands[2]);
10002 operands[2] = ra;
10003 }
5cf3595a 10004 /* This is a hack -- we may have crystalized the function type too
10005 early. */
10006 cfun->machine->func_type = 0;
215b30b3 10007 }"
10008)
56d27660 10009
9c08d1fa 10010;; This split is only used during output to reduce the number of patterns
10011;; that need assembler instructions adding to them. We allowed the setting
10012;; of the conditions to be implicit during rtl generation so that
10013;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10014;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10015;; up again here.
10016
10017(define_split
10018 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10019 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10020 [(match_operand 2 "" "") (match_operand 3 "" "")])
10021 (match_dup 0)
10022 (match_operand 4 "" "")))
bd5b4116 10023 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10024 "TARGET_ARM && reload_completed"
8fa3ba89 10025 [(set (match_dup 5) (match_dup 6))
10026 (cond_exec (match_dup 7)
10027 (set (match_dup 0) (match_dup 4)))]
10028 "
10029 {
10030 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10031 operands[2], operands[3]);
10032 enum rtx_code rc = GET_CODE (operands[1]);
10033
bd5b4116 10034 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10035 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10036 if (mode == CCFPmode || mode == CCFPEmode)
10037 rc = reverse_condition_maybe_unordered (rc);
10038 else
10039 rc = reverse_condition (rc);
10040
10041 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10042 }"
10043)
10044
10045(define_split
10046 [(set (match_operand:SI 0 "s_register_operand" "")
10047 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10048 [(match_operand 2 "" "") (match_operand 3 "" "")])
10049 (match_operand 4 "" "")
10050 (match_dup 0)))
bd5b4116 10051 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10052 "TARGET_ARM && reload_completed"
8fa3ba89 10053 [(set (match_dup 5) (match_dup 6))
10054 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10055 (set (match_dup 0) (match_dup 4)))]
10056 "
10057 {
10058 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10059 operands[2], operands[3]);
10060
bd5b4116 10061 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10062 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10063 }"
10064)
10065
10066(define_split
10067 [(set (match_operand:SI 0 "s_register_operand" "")
10068 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10069 [(match_operand 2 "" "") (match_operand 3 "" "")])
10070 (match_operand 4 "" "")
10071 (match_operand 5 "" "")))
bd5b4116 10072 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10073 "TARGET_ARM && reload_completed"
8fa3ba89 10074 [(set (match_dup 6) (match_dup 7))
10075 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10076 (set (match_dup 0) (match_dup 4)))
10077 (cond_exec (match_dup 8)
10078 (set (match_dup 0) (match_dup 5)))]
10079 "
10080 {
10081 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10082 operands[2], operands[3]);
10083 enum rtx_code rc = GET_CODE (operands[1]);
10084
bd5b4116 10085 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10086 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10087 if (mode == CCFPmode || mode == CCFPEmode)
10088 rc = reverse_condition_maybe_unordered (rc);
10089 else
10090 rc = reverse_condition (rc);
10091
10092 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10093 }"
10094)
10095
cffb2a26 10096(define_split
10097 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10098 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10099 [(match_operand:SI 2 "s_register_operand" "")
10100 (match_operand:SI 3 "arm_add_operand" "")])
10101 (match_operand:SI 4 "arm_rhs_operand" "")
10102 (not:SI
10103 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10104 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10105 "TARGET_ARM && reload_completed"
cffb2a26 10106 [(set (match_dup 6) (match_dup 7))
f6c53574 10107 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10108 (set (match_dup 0) (match_dup 4)))
10109 (cond_exec (match_dup 8)
10110 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10111 "
215b30b3 10112 {
10113 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10114 operands[2], operands[3]);
f6c53574 10115 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10116
bd5b4116 10117 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10118 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10119 if (mode == CCFPmode || mode == CCFPEmode)
10120 rc = reverse_condition_maybe_unordered (rc);
10121 else
10122 rc = reverse_condition (rc);
10123
10124 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10125 }"
10126)
cffb2a26 10127
10128(define_insn "*cond_move_not"
10129 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10130 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10131 [(match_operand 3 "cc_register" "") (const_int 0)])
10132 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10133 (not:SI
10134 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10135 "TARGET_ARM"
10136 "@
10137 mvn%D4\\t%0, %2
10138 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10139 [(set_attr "conds" "use")
10140 (set_attr "length" "4,8")]
10141)
cffb2a26 10142
9c08d1fa 10143;; The next two patterns occur when an AND operation is followed by a
10144;; scc insn sequence
10145
f7fbdd4a 10146(define_insn "*sign_extract_onebit"
9c08d1fa 10147 [(set (match_operand:SI 0 "s_register_operand" "=r")
10148 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10149 (const_int 1)
ed750274 10150 (match_operand:SI 2 "const_int_operand" "n")))
10151 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10152 "TARGET_ARM"
9c08d1fa 10153 "*
0d66636f 10154 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10155 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10156 return \"mvnne\\t%0, #0\";
10157 "
10158 [(set_attr "conds" "clob")
10159 (set_attr "length" "8")]
10160)
9c08d1fa 10161
f7fbdd4a 10162(define_insn "*not_signextract_onebit"
9c08d1fa 10163 [(set (match_operand:SI 0 "s_register_operand" "=r")
10164 (not:SI
10165 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10166 (const_int 1)
ed750274 10167 (match_operand:SI 2 "const_int_operand" "n"))))
10168 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10169 "TARGET_ARM"
9c08d1fa 10170 "*
0d66636f 10171 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10172 output_asm_insn (\"tst\\t%1, %2\", operands);
10173 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10174 return \"movne\\t%0, #0\";
10175 "
10176 [(set_attr "conds" "clob")
10177 (set_attr "length" "12")]
10178)
87b22bf7 10179
0d66636f 10180;; Push multiple registers to the stack. Registers are in parallel (use ...)
10181;; expressions. For simplicity, the first register is also in the unspec
10182;; part.
f7fbdd4a 10183(define_insn "*push_multi"
87b22bf7 10184 [(match_parallel 2 "multi_register_push"
10185 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10186 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10187 UNSPEC_PUSH_MULT))])]
cffb2a26 10188 "TARGET_ARM"
87b22bf7 10189 "*
215b30b3 10190 {
10191 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10192
215b30b3 10193 /* For the StrongARM at least it is faster to
10194 use STR to store only a single register. */
6079f055 10195 if (num_saves == 1)
215b30b3 10196 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10197 else
10198 {
10199 int i;
10200 char pattern[100];
ed593f11 10201
215b30b3 10202 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10203
6079f055 10204 for (i = 1; i < num_saves; i++)
215b30b3 10205 {
10206 strcat (pattern, \", %|\");
10207 strcat (pattern,
10208 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10209 }
10210
10211 strcat (pattern, \"}\");
10212 output_asm_insn (pattern, operands);
10213 }
10214
10215 return \"\";
10216 }"
10217 [(set_attr "type" "store4")]
10218)
f7fbdd4a 10219
4c58c898 10220(define_insn "stack_tie"
10221 [(set (mem:BLK (scratch))
10222 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10223 (match_operand:SI 1 "s_register_operand" "r")]
10224 UNSPEC_PRLG_STK))]
10225 ""
10226 ""
10227 [(set_attr "length" "0")]
10228)
10229
3398e91d 10230;; Similarly for the floating point registers
7b1d2fc4 10231(define_insn "*push_fp_multi"
10232 [(match_parallel 2 "multi_register_push"
10233 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10234 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10235 UNSPEC_PUSH_MULT))])]
a2cd141b 10236 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10237 "*
215b30b3 10238 {
10239 char pattern[100];
7b1d2fc4 10240
215b30b3 10241 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10242 output_asm_insn (pattern, operands);
10243 return \"\";
10244 }"
10245 [(set_attr "type" "f_store")]
10246)
7b1d2fc4 10247
f7fbdd4a 10248;; Special patterns for dealing with the constant pool
10249
cffb2a26 10250(define_insn "align_4"
e1159bbe 10251 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10252 "TARGET_EITHER"
f7fbdd4a 10253 "*
cffb2a26 10254 assemble_align (32);
f7fbdd4a 10255 return \"\";
cffb2a26 10256 "
10257)
f7fbdd4a 10258
755eb2b4 10259(define_insn "align_8"
10260 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10261 "TARGET_EITHER"
755eb2b4 10262 "*
10263 assemble_align (64);
10264 return \"\";
10265 "
10266)
10267
cffb2a26 10268(define_insn "consttable_end"
e1159bbe 10269 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10270 "TARGET_EITHER"
f7fbdd4a 10271 "*
cffb2a26 10272 making_const_table = FALSE;
f7fbdd4a 10273 return \"\";
cffb2a26 10274 "
10275)
f7fbdd4a 10276
cffb2a26 10277(define_insn "consttable_1"
e1159bbe 10278 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
cffb2a26 10279 "TARGET_THUMB"
f7fbdd4a 10280 "*
cffb2a26 10281 making_const_table = TRUE;
09d688ff 10282 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10283 assemble_zeros (3);
f7fbdd4a 10284 return \"\";
cffb2a26 10285 "
10286 [(set_attr "length" "4")]
10287)
f7fbdd4a 10288
cffb2a26 10289(define_insn "consttable_2"
e1159bbe 10290 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
cffb2a26 10291 "TARGET_THUMB"
f7fbdd4a 10292 "*
cffb2a26 10293 making_const_table = TRUE;
09d688ff 10294 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10295 assemble_zeros (2);
f7fbdd4a 10296 return \"\";
cffb2a26 10297 "
10298 [(set_attr "length" "4")]
10299)
10300
10301(define_insn "consttable_4"
e1159bbe 10302 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10303 "TARGET_EITHER"
10304 "*
10305 {
10306 making_const_table = TRUE;
10307 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10308 {
10309 case MODE_FLOAT:
10310 {
badfe841 10311 REAL_VALUE_TYPE r;
10312 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10313 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10314 break;
10315 }
10316 default:
09d688ff 10317 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 10318 break;
10319 }
10320 return \"\";
10321 }"
10322 [(set_attr "length" "4")]
10323)
10324
10325(define_insn "consttable_8"
e1159bbe 10326 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10327 "TARGET_EITHER"
10328 "*
10329 {
10330 making_const_table = TRUE;
10331 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10332 {
10333 case MODE_FLOAT:
10334 {
badfe841 10335 REAL_VALUE_TYPE r;
10336 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10337 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10338 break;
10339 }
10340 default:
09d688ff 10341 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10342 break;
10343 }
10344 return \"\";
10345 }"
10346 [(set_attr "length" "8")]
10347)
10348
10349;; Miscellaneous Thumb patterns
10350
fd957ef3 10351(define_expand "tablejump"
7db9af5d 10352 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10353 (use (label_ref (match_operand 1 "" "")))])]
10354 "TARGET_THUMB"
10355 "
10356 if (flag_pic)
10357 {
10358 /* Hopefully, CSE will eliminate this copy. */
10359 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10360 rtx reg2 = gen_reg_rtx (SImode);
10361
10362 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10363 operands[0] = reg2;
10364 }
10365 "
10366)
10367
f1039640 10368;; NB never uses BX.
fd957ef3 10369(define_insn "*thumb_tablejump"
cffb2a26 10370 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10371 (use (label_ref (match_operand 1 "" "")))]
10372 "TARGET_THUMB"
fd957ef3 10373 "mov\\t%|pc, %0"
cffb2a26 10374 [(set_attr "length" "2")]
10375)
0d66636f 10376
331beb1a 10377;; V5 Instructions,
10378
8f4be2be 10379(define_insn "clzsi2"
10380 [(set (match_operand:SI 0 "s_register_operand" "=r")
10381 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
e1159bbe 10382 "TARGET_ARM && arm_arch5"
ee7cbe0e 10383 "clz%?\\t%0, %1"
10384 [(set_attr "predicable" "yes")])
331beb1a 10385
e1159bbe 10386(define_expand "ffssi2"
10387 [(set (match_operand:SI 0 "s_register_operand" "")
10388 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10389 "TARGET_ARM && arm_arch5"
10390 "
10391 {
10392 rtx t1, t2, t3;
10393
10394 t1 = gen_reg_rtx (SImode);
10395 t2 = gen_reg_rtx (SImode);
10396 t3 = gen_reg_rtx (SImode);
10397
10398 emit_insn (gen_negsi2 (t1, operands[1]));
10399 emit_insn (gen_andsi3 (t2, operands[1], t1));
8f4be2be 10400 emit_insn (gen_clzsi2 (t3, t2));
e1159bbe 10401 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10402 DONE;
10403 }"
10404)
10405
8f4be2be 10406(define_expand "ctzsi2"
10407 [(set (match_operand:SI 0 "s_register_operand" "")
10408 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10409 "TARGET_ARM && arm_arch5"
10410 "
10411 {
10412 rtx t1, t2, t3;
10413
10414 t1 = gen_reg_rtx (SImode);
10415 t2 = gen_reg_rtx (SImode);
10416 t3 = gen_reg_rtx (SImode);
10417
10418 emit_insn (gen_negsi2 (t1, operands[1]));
10419 emit_insn (gen_andsi3 (t2, operands[1], t1));
10420 emit_insn (gen_clzsi2 (t3, t2));
10421 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10422 DONE;
10423 }"
10424)
10425
e1159bbe 10426;; V5E instructions.
331beb1a 10427
10428(define_insn "prefetch"
f4e79814 10429 [(prefetch (match_operand:SI 0 "address_operand" "p")
10430 (match_operand:SI 1 "" "")
10431 (match_operand:SI 2 "" ""))]
e1159bbe 10432 "TARGET_ARM && arm_arch5e"
bcb7a8f6 10433 "pld\\t%a0")
331beb1a 10434
0d66636f 10435;; General predication pattern
10436
10437(define_cond_exec
10438 [(match_operator 0 "arm_comparison_operator"
10439 [(match_operand 1 "cc_register" "")
10440 (const_int 0)])]
10441 "TARGET_ARM"
10442 ""
10443)
10444
063a05c7 10445(define_insn "prologue_use"
10446 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10447 ""
10448 "%@ %0 needed for prologue"
10449)
7db9af5d 10450
4c44712e 10451
10452;; Patterns for exception handling
10453
10454(define_expand "eh_return"
10455 [(use (match_operand 0 "general_operand" ""))]
10456 "TARGET_EITHER"
10457 "
10458 {
10459 if (TARGET_ARM)
10460 emit_insn (gen_arm_eh_return (operands[0]));
10461 else
10462 emit_insn (gen_thumb_eh_return (operands[0]));
10463 DONE;
10464 }"
10465)
10466
10467;; We can't expand this before we know where the link register is stored.
10468(define_insn_and_split "arm_eh_return"
10469 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10470 VUNSPEC_EH_RETURN)
10471 (clobber (match_scratch:SI 1 "=&r"))]
10472 "TARGET_ARM"
10473 "#"
10474 "&& reload_completed"
10475 [(const_int 0)]
10476 "
10477 {
10478 arm_set_return_address (operands[0], operands[1]);
10479 DONE;
10480 }"
10481)
10482
10483(define_insn_and_split "thumb_eh_return"
10484 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10485 VUNSPEC_EH_RETURN)
10486 (clobber (match_scratch:SI 1 "=&l"))]
10487 "TARGET_THUMB"
10488 "#"
10489 "&& reload_completed"
10490 [(const_int 0)]
10491 "
10492 {
10493 thumb_set_return_address (operands[0], operands[1]);
10494 DONE;
10495 }"
10496)
10497
7db9af5d 10498;; Load the FPA co-processor patterns
10499(include "fpa.md")
10500;; Load the Maverick co-processor patterns
10501(include "cirrus.md")
755eb2b4 10502;; Load the Intel Wireless Multimedia Extension patterns
10503(include "iwmmxt.md")
a2cd141b 10504;; Load the VFP co-processor patterns
10505(include "vfp.md")
10506