]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
* config/mips/mips.c (mips_legitimize_tls_address): Use
[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)
1080 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1081 else
1082 return \"mul\\t%0, %0, %2\";
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 }
3617
3618 if (GET_CODE (ops[1]) != REG)
3619 {
3620 debug_rtx (ops[1]);
3621 abort ();
3622 }
3623
3624 ops[0] = operands[0];
3625 ops[3] = operands[2];
3626 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3627 return \"\";
3628 }"
3629 [(set_attr "length" "4")
a2cd141b 3630 (set_attr "type" "load_byte")
cffb2a26 3631 (set_attr "pool_range" "1020")]
3632)
25f7a26e 3633
a2cd141b 3634;; We used to have an early-clobber on the scratch register here.
3635;; However, there's a bug somewhere in reload which means that this
3636;; can be partially ignored during spill allocation if the memory
3637;; address also needs reloading; this causes an abort later on when
3638;; we try to verify the operands. Fortunately, we don't really need
3639;; the early-clobber: we can always use operand 0 if operand 2
3640;; overlaps the address.
3641(define_insn "*thumb_extendhisi2_insn_v6"
3642 [(set (match_operand:SI 0 "register_operand" "=l,l")
3643 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3644 (clobber (match_scratch:SI 2 "=X,l"))]
3645 "TARGET_THUMB && arm_arch6"
3646 "*
3647 {
3648 rtx ops[4];
3649 rtx mem;
3650
3651 if (which_alternative == 0)
3652 return \"sxth\\t%0, %1\";
3653
3654 mem = XEXP (operands[1], 0);
3655
3656 /* This code used to try to use 'V', and fix the address only if it was
3657 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3658 range of QImode offsets, and offsettable_address_p does a QImode
3659 address check. */
3660
3661 if (GET_CODE (mem) == CONST)
3662 mem = XEXP (mem, 0);
3663
3664 if (GET_CODE (mem) == LABEL_REF)
3665 return \"ldr\\t%0, %1\";
3666
3667 if (GET_CODE (mem) == PLUS)
3668 {
3669 rtx a = XEXP (mem, 0);
3670 rtx b = XEXP (mem, 1);
3671
3672 if (GET_CODE (a) == LABEL_REF
3673 && GET_CODE (b) == CONST_INT)
3674 return \"ldr\\t%0, %1\";
3675
3676 if (GET_CODE (b) == REG)
3677 return \"ldrsh\\t%0, %1\";
3678
3679 ops[1] = a;
3680 ops[2] = b;
3681 }
3682 else
3683 {
3684 ops[1] = mem;
3685 ops[2] = const0_rtx;
3686 }
3687
3688 if (GET_CODE (ops[1]) != REG)
3689 {
3690 debug_rtx (ops[1]);
3691 abort ();
3692 }
3693
3694 ops[0] = operands[0];
3695 if (reg_mentioned_p (operands[2], ops[1]))
3696 ops[3] = ops[0];
3697 else
3698 ops[3] = operands[2];
3699 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3700 return \"\";
3701 }"
3702 [(set_attr "length" "2,4")
3703 (set_attr "type" "alu_shift,load_byte")
3704 (set_attr "pool_range" "*,1020")]
3705)
3706
25f7a26e 3707(define_expand "extendhisi2_mem"
eab14235 3708 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 3709 (set (match_dup 3)
eab14235 3710 (zero_extend:SI (match_dup 7)))
25f7a26e 3711 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3712 (set (match_operand:SI 0 "" "")
3713 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 3714 "TARGET_ARM"
25f7a26e 3715 "
215b30b3 3716 {
3717 rtx mem1, mem2;
3718 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3719
3720 mem1 = gen_rtx_MEM (QImode, addr);
3721 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3722 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3723 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3724 operands[0] = gen_lowpart (SImode, operands[0]);
3725 operands[1] = mem1;
3726 operands[2] = gen_reg_rtx (SImode);
3727 operands[3] = gen_reg_rtx (SImode);
3728 operands[6] = gen_reg_rtx (SImode);
3729 operands[7] = mem2;
25f7a26e 3730
215b30b3 3731 if (BYTES_BIG_ENDIAN)
3732 {
3733 operands[4] = operands[2];
3734 operands[5] = operands[3];
3735 }
3736 else
3737 {
3738 operands[4] = operands[3];
3739 operands[5] = operands[2];
3740 }
3741 }"
3742)
b11cae9e 3743
a2cd141b 3744(define_insn "*arm_extendhisi2"
3745 [(set (match_operand:SI 0 "s_register_operand" "=r")
3746 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3747 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3748 "ldr%?sh\\t%0, %1"
a2cd141b 3749 [(set_attr "type" "load_byte")
0d66636f 3750 (set_attr "predicable" "yes")
cffb2a26 3751 (set_attr "pool_range" "256")
3752 (set_attr "neg_pool_range" "244")]
3753)
f7fbdd4a 3754
a2cd141b 3755(define_insn "*arm_extendhisi2_v6"
3756 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3757 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3758 "TARGET_ARM && arm_arch6"
3759 "@
3760 sxth%?\\t%0, %1
3761 ldr%?sh\\t%0, %1"
3762 [(set_attr "type" "alu_shift,load_byte")
3763 (set_attr "predicable" "yes")
3764 (set_attr "pool_range" "*,256")
3765 (set_attr "neg_pool_range" "*,244")]
3766)
3767
3768(define_insn "*arm_extendhisi2addsi"
3769 [(set (match_operand:SI 0 "s_register_operand" "=r")
3770 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3771 (match_operand:SI 2 "s_register_operand" "r")))]
3772 "TARGET_ARM && arm_arch6"
3773 "sxtah%?\\t%0, %2, %1"
3774)
3775
206ee9a2 3776(define_split
cffb2a26 3777 [(set (match_operand:SI 0 "s_register_operand" "")
206ee9a2 3778 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
cffb2a26 3779 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3780 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3781 [(set (match_dup 2) (match_dup 1))
3782 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3783 "
cffb2a26 3784 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3785 FAIL;
cffb2a26 3786 "
3787)
206ee9a2 3788
3789(define_split
cffb2a26 3790 [(set (match_operand:SI 0 "s_register_operand" "")
3791 (match_operator:SI 3 "shiftable_operator"
206ee9a2 3792 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
cffb2a26 3793 (match_operand:SI 4 "s_register_operand" "")]))
3794 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3795 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3796 [(set (match_dup 2) (match_dup 1))
3797 (set (match_dup 0)
3798 (match_op_dup 3
3799 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
cffb2a26 3800 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3801 FAIL;
206ee9a2 3802 "
cffb2a26 3803)
206ee9a2 3804
c8f69309 3805(define_expand "extendqihi2"
3806 [(set (match_dup 2)
f7fbdd4a 3807 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 3808 (const_int 24)))
9c08d1fa 3809 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 3810 (ashiftrt:SI (match_dup 2)
3811 (const_int 24)))]
cffb2a26 3812 "TARGET_ARM"
c8f69309 3813 "
215b30b3 3814 {
3815 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3816 {
3817 emit_insn (gen_rtx_SET (VOIDmode,
3818 operands[0],
3819 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3820 DONE;
3821 }
3822 if (!s_register_operand (operands[1], QImode))
3823 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3824 operands[0] = gen_lowpart (SImode, operands[0]);
3825 operands[1] = gen_lowpart (SImode, operands[1]);
3826 operands[2] = gen_reg_rtx (SImode);
3827 }"
3828)
f7fbdd4a 3829
3830(define_insn "*extendqihi_insn"
b4e8a300 3831 [(set (match_operand:HI 0 "s_register_operand" "=r")
3832 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
cffb2a26 3833 "TARGET_ARM && arm_arch4"
b4e8a300 3834 "ldr%?sb\\t%0, %1"
a2cd141b 3835 [(set_attr "type" "load_byte")
0d66636f 3836 (set_attr "predicable" "yes")
cffb2a26 3837 (set_attr "pool_range" "256")
3838 (set_attr "neg_pool_range" "244")]
3839)
3fc2009e 3840
b11cae9e 3841(define_expand "extendqisi2"
c8f69309 3842 [(set (match_dup 2)
3fc2009e 3843 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 3844 (const_int 24)))
9c08d1fa 3845 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3846 (ashiftrt:SI (match_dup 2)
3847 (const_int 24)))]
cffb2a26 3848 "TARGET_EITHER"
b11cae9e 3849 "
cffb2a26 3850 {
a2cd141b 3851 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3852 {
a2cd141b 3853 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 3854 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3855 DONE;
3856 }
a2cd141b 3857
215b30b3 3858 if (!s_register_operand (operands[1], QImode))
cffb2a26 3859 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 3860
a2cd141b 3861 if (arm_arch6)
3862 {
3863 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3864 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3865 DONE;
cffb2a26 3866 }
a2cd141b 3867
3868 operands[1] = gen_lowpart (SImode, operands[1]);
3869 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3870 }"
3871)
f7fbdd4a 3872
a2cd141b 3873(define_insn "*arm_extendqisi"
3874 [(set (match_operand:SI 0 "s_register_operand" "=r")
b4e8a300 3875 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
a2cd141b 3876 "TARGET_ARM && arm_arch4 && !arm_arch6"
b4e8a300 3877 "ldr%?sb\\t%0, %1"
a2cd141b 3878 [(set_attr "type" "load_byte")
0d66636f 3879 (set_attr "predicable" "yes")
cffb2a26 3880 (set_attr "pool_range" "256")
3881 (set_attr "neg_pool_range" "244")]
3882)
3fc2009e 3883
a2cd141b 3884(define_insn "*arm_extendqisi_v6"
3885 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
b4e8a300 3886 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
a2cd141b 3887 "TARGET_ARM && arm_arch6"
b4e8a300 3888 "@
3889 sxtb%?\\t%0, %1
3890 ldr%?sb\\t%0, %1"
a2cd141b 3891 [(set_attr "type" "alu_shift,load_byte")
3892 (set_attr "predicable" "yes")
a2cd141b 3893 (set_attr "pool_range" "*,256")
3894 (set_attr "neg_pool_range" "*,244")]
3895)
3896
3897(define_insn "*arm_extendqisi2addsi"
3898 [(set (match_operand:SI 0 "s_register_operand" "=r")
3899 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3900 (match_operand:SI 2 "s_register_operand" "r")))]
3901 "TARGET_ARM && arm_arch6"
3902 "sxtab%?\\t%0, %2, %1"
3903 [(set_attr "type" "alu_shift")
3904 (set_attr "predicable" "yes")]
3905)
3906
a2cd141b 3907(define_insn "*thumb_extendqisi2"
3908 [(set (match_operand:SI 0 "register_operand" "=l,l")
3909 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3910 "TARGET_THUMB && !arm_arch6"
cffb2a26 3911 "*
3912 {
3913 rtx ops[3];
3914 rtx mem = XEXP (operands[1], 0);
3915
3916 if (GET_CODE (mem) == CONST)
3917 mem = XEXP (mem, 0);
3918
3919 if (GET_CODE (mem) == LABEL_REF)
3920 return \"ldr\\t%0, %1\";
3921
3922 if (GET_CODE (mem) == PLUS
3923 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3924 return \"ldr\\t%0, %1\";
3925
3926 if (which_alternative == 0)
3927 return \"ldrsb\\t%0, %1\";
3928
3929 ops[0] = operands[0];
3930
3931 if (GET_CODE (mem) == PLUS)
3932 {
3933 rtx a = XEXP (mem, 0);
3934 rtx b = XEXP (mem, 1);
3935
3936 ops[1] = a;
3937 ops[2] = b;
3938
3939 if (GET_CODE (a) == REG)
3940 {
3941 if (GET_CODE (b) == REG)
3942 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3943 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 3944 {
3945 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3946 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3947 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3948 }
cffb2a26 3949 else
3950 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3951 }
3952 else if (GET_CODE (b) != REG)
3953 abort ();
3954 else
3955 {
3956 if (REGNO (b) == REGNO (ops[0]))
215b30b3 3957 {
3958 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3959 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3960 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3961 }
cffb2a26 3962 else
3963 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3964 }
3965 }
3966 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3967 {
215b30b3 3968 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3969 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3970 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 3971 }
3972 else
3973 {
3974 ops[1] = mem;
3975 ops[2] = const0_rtx;
3976
3977 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3978 }
3979 return \"\";
3980 }"
3981 [(set_attr "length" "2,6")
a2cd141b 3982 (set_attr "type" "load_byte,load_byte")
cffb2a26 3983 (set_attr "pool_range" "32,32")]
3984)
3985
a2cd141b 3986(define_insn "*thumb_extendqisi2_v6"
3987 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3988 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3989 "TARGET_THUMB && arm_arch6"
3990 "*
3991 {
3992 rtx ops[3];
3993 rtx mem;
3994
3995 if (which_alternative == 0)
3996 return \"sxtb\\t%0, %1\";
3997
3998 mem = XEXP (operands[1], 0);
3999
4000 if (GET_CODE (mem) == CONST)
4001 mem = XEXP (mem, 0);
4002
4003 if (GET_CODE (mem) == LABEL_REF)
4004 return \"ldr\\t%0, %1\";
4005
4006 if (GET_CODE (mem) == PLUS
4007 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4008 return \"ldr\\t%0, %1\";
4009
4010 if (which_alternative == 0)
4011 return \"ldrsb\\t%0, %1\";
4012
4013 ops[0] = operands[0];
4014
4015 if (GET_CODE (mem) == PLUS)
4016 {
4017 rtx a = XEXP (mem, 0);
4018 rtx b = XEXP (mem, 1);
4019
4020 ops[1] = a;
4021 ops[2] = b;
4022
4023 if (GET_CODE (a) == REG)
4024 {
4025 if (GET_CODE (b) == REG)
4026 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4027 else if (REGNO (a) == REGNO (ops[0]))
4028 {
4029 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4030 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4031 }
4032 else
4033 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4034 }
4035 else if (GET_CODE (b) != REG)
4036 abort ();
4037 else
4038 {
4039 if (REGNO (b) == REGNO (ops[0]))
4040 {
4041 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4042 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4043 }
4044 else
4045 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4046 }
4047 }
4048 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4049 {
4050 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4051 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4052 }
4053 else
4054 {
4055 ops[1] = mem;
4056 ops[2] = const0_rtx;
4057
4058 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4059 }
4060 return \"\";
4061 }"
4062 [(set_attr "length" "2,2,4")
4063 (set_attr "type" "alu_shift,load_byte,load_byte")
4064 (set_attr "pool_range" "*,32,32")]
4065)
4066
caedf871 4067(define_expand "extendsfdf2"
4068 [(set (match_operand:DF 0 "s_register_operand" "")
4069 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 4070 "TARGET_ARM && TARGET_HARD_FLOAT"
caedf871 4071 ""
4072)
b11cae9e 4073\f
4074;; Move insns (including loads and stores)
4075
4076;; XXX Just some ideas about movti.
9c08d1fa 4077;; I don't think these are a good idea on the arm, there just aren't enough
4078;; registers
b11cae9e 4079;;(define_expand "loadti"
9c08d1fa 4080;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4081;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4082;; "" "")
4083
4084;;(define_expand "storeti"
4085;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4086;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4087;; "" "")
4088
4089;;(define_expand "movti"
4090;; [(set (match_operand:TI 0 "general_operand" "")
4091;; (match_operand:TI 1 "general_operand" ""))]
4092;; ""
4093;; "
4094;;{
4095;; rtx insn;
4096;;
4097;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4098;; operands[1] = copy_to_reg (operands[1]);
4099;; if (GET_CODE (operands[0]) == MEM)
4100;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4101;; else if (GET_CODE (operands[1]) == MEM)
4102;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4103;; else
4104;; FAIL;
4105;;
4106;; emit_insn (insn);
4107;; DONE;
4108;;}")
4109
a2f10574 4110;; Recognize garbage generated above.
b11cae9e 4111
4112;;(define_insn ""
4113;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4114;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4115;; ""
4116;; "*
4117;; {
4118;; register mem = (which_alternative < 3);
0d66636f 4119;; register const char *template;
b11cae9e 4120;;
4121;; operands[mem] = XEXP (operands[mem], 0);
4122;; switch (which_alternative)
4123;; {
4124;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4125;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4126;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4127;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4128;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4129;; case 5: template = \"stmia\\t%0, %M1\"; break;
4130;; }
e2348bcb 4131;; output_asm_insn (template, operands);
4132;; return \"\";
b11cae9e 4133;; }")
4134
cffb2a26 4135(define_expand "movdi"
4136 [(set (match_operand:DI 0 "general_operand" "")
4137 (match_operand:DI 1 "general_operand" ""))]
4138 "TARGET_EITHER"
4139 "
4140 if (TARGET_THUMB)
4141 {
215b30b3 4142 if (!no_new_pseudos)
cffb2a26 4143 {
4144 if (GET_CODE (operands[0]) != REG)
4145 operands[1] = force_reg (DImode, operands[1]);
4146 }
4147 }
4148 "
4149)
b11cae9e 4150
cffb2a26 4151(define_insn "*arm_movdi"
d51f92df 4152 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4153 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4154 "TARGET_ARM
4155 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4156 && !TARGET_IWMMXT"
b11cae9e 4157 "*
d51f92df 4158 switch (which_alternative)
4159 {
4160 case 0:
4161 case 1:
4162 case 2:
4163 return \"#\";
4164 default:
4165 return output_move_double (operands);
4166 }
cffb2a26 4167 "
359a6e9f 4168 [(set_attr "length" "8,12,16,8,8")
4169 (set_attr "type" "*,*,*,load2,store2")
4170 (set_attr "pool_range" "*,*,*,1020,*")
4171 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4172)
4173
d51f92df 4174(define_split
4175 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4176 (match_operand:ANY64 1 "const_double_operand" ""))]
4177 "TARGET_ARM
4178 && reload_completed
4179 && (arm_const_double_inline_cost (operands[1])
4180 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4181 [(const_int 0)]
4182 "
4183 arm_split_constant (SET, SImode, curr_insn,
4184 INTVAL (gen_lowpart (SImode, operands[1])),
4185 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4186 arm_split_constant (SET, SImode, curr_insn,
4187 INTVAL (gen_highpart_mode (SImode,
4188 GET_MODE (operands[0]),
4189 operands[1])),
4190 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4191 DONE;
4192 "
4193)
4194
e5ba9289 4195; If optimizing for size, or if we have load delay slots, then
4196; we want to split the constant into two separate operations.
4197; In both cases this may split a trivial part into a single data op
4198; leaving a single complex constant to load. We can also get longer
4199; offsets in a LDR which means we get better chances of sharing the pool
4200; entries. Finally, we can normally do a better job of scheduling
4201; LDR instructions than we can with LDM.
4202; This pattern will only match if the one above did not.
4203(define_split
4204 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4205 (match_operand:ANY64 1 "const_double_operand" ""))]
4206 "TARGET_ARM && reload_completed
4207 && arm_const_double_by_parts (operands[1])"
4208 [(set (match_dup 0) (match_dup 1))
4209 (set (match_dup 2) (match_dup 3))]
4210 "
4211 operands[2] = gen_highpart (SImode, operands[0]);
4212 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4213 operands[1]);
4214 operands[0] = gen_lowpart (SImode, operands[0]);
4215 operands[1] = gen_lowpart (SImode, operands[1]);
4216 "
4217)
4218
d51f92df 4219(define_split
4220 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4221 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4222 "TARGET_EITHER && reload_completed"
4223 [(set (match_dup 0) (match_dup 1))
4224 (set (match_dup 2) (match_dup 3))]
4225 "
4226 operands[2] = gen_highpart (SImode, operands[0]);
4227 operands[3] = gen_highpart (SImode, operands[1]);
4228 operands[0] = gen_lowpart (SImode, operands[0]);
4229 operands[1] = gen_lowpart (SImode, operands[1]);
4230
4231 /* Handle a partial overlap. */
4232 if (rtx_equal_p (operands[0], operands[3]))
4233 {
4234 rtx tmp0 = operands[0];
4235 rtx tmp1 = operands[1];
4236
4237 operands[0] = operands[2];
4238 operands[1] = operands[3];
4239 operands[2] = tmp0;
4240 operands[3] = tmp1;
4241 }
4242 "
4243)
4244
a8a3b539 4245;; We can't actually do base+index doubleword loads if the index and
4246;; destination overlap. Split here so that we at least have chance to
4247;; schedule.
4248(define_split
4249 [(set (match_operand:DI 0 "s_register_operand" "")
4250 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4251 (match_operand:SI 2 "s_register_operand" ""))))]
4252 "TARGET_LDRD
4253 && reg_overlap_mentioned_p (operands[0], operands[1])
4254 && reg_overlap_mentioned_p (operands[0], operands[2])"
4255 [(set (match_dup 4)
4256 (plus:SI (match_dup 1)
4257 (match_dup 2)))
4258 (set (match_dup 0)
4259 (mem:DI (match_dup 4)))]
4260 "
4261 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4262 "
4263)
4264
cffb2a26 4265;;; ??? This should have alternatives for constants.
4266;;; ??? This was originally identical to the movdf_insn pattern.
4267;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4268;;; thumb_reorg with a memory reference.
4269(define_insn "*thumb_movdi_insn"
215b30b3 4270 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4271 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
cffb2a26 4272 "TARGET_THUMB
a2cd141b 4273 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4274 && ( register_operand (operands[0], DImode)
4275 || register_operand (operands[1], DImode))"
4276 "*
4277 {
4278 switch (which_alternative)
4279 {
4280 default:
4281 case 0:
4282 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4283 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4284 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4285 case 1:
4286 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4287 case 2:
4288 operands[1] = GEN_INT (- INTVAL (operands[1]));
4289 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4290 case 3:
4291 return \"ldmia\\t%1, {%0, %H0}\";
4292 case 4:
4293 return \"stmia\\t%0, {%1, %H1}\";
4294 case 5:
4295 return thumb_load_double_from_address (operands);
4296 case 6:
1a83b3ff 4297 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4298 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4299 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4300 return \"\";
4301 case 7:
4302 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4303 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4304 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4305 }
4306 }"
4307 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4308 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4309 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4310)
b11cae9e 4311
9c08d1fa 4312(define_expand "movsi"
4313 [(set (match_operand:SI 0 "general_operand" "")
4314 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4315 "TARGET_EITHER"
9c08d1fa 4316 "
cffb2a26 4317 if (TARGET_ARM)
9c08d1fa 4318 {
674a8f0b 4319 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4320 if (GET_CODE (operands[0]) == MEM)
4321 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4322 if (arm_general_register_operand (operands[0], SImode)
4323 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4324 && !(const_ok_for_arm (INTVAL (operands[1]))
4325 || const_ok_for_arm (~INTVAL (operands[1]))))
4326 {
96f57e36 4327 arm_split_constant (SET, SImode, NULL_RTX,
4328 INTVAL (operands[1]), operands[0], NULL_RTX,
615caa51 4329 optimize && !no_new_pseudos);
cffb2a26 4330 DONE;
4331 }
4332 }
674a8f0b 4333 else /* TARGET_THUMB.... */
cffb2a26 4334 {
215b30b3 4335 if (!no_new_pseudos)
cffb2a26 4336 {
4337 if (GET_CODE (operands[0]) != REG)
4338 operands[1] = force_reg (SImode, operands[1]);
4339 }
9c08d1fa 4340 }
af1b847e 4341
bbe777ea 4342 if (flag_pic
4343 && (CONSTANT_P (operands[1])
4344 || symbol_mentioned_p (operands[1])
4345 || label_mentioned_p (operands[1])))
849170fd 4346 operands[1] = legitimize_pic_address (operands[1], SImode,
935d87ee 4347 (no_new_pseudos ? operands[0] : 0));
215b30b3 4348 "
4349)
9c08d1fa 4350
cffb2a26 4351(define_insn "*arm_movsi_insn"
215b30b3 4352 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4353 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
755eb2b4 4354 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 4355 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 4356 && ( register_operand (operands[0], SImode)
4357 || register_operand (operands[1], SImode))"
f7fbdd4a 4358 "@
4359 mov%?\\t%0, %1
4360 mvn%?\\t%0, #%B1
4361 ldr%?\\t%0, %1
4362 str%?\\t%1, %0"
a2cd141b 4363 [(set_attr "type" "*,*,load1,store1")
0d66636f 4364 (set_attr "predicable" "yes")
cffb2a26 4365 (set_attr "pool_range" "*,*,4096,*")
4366 (set_attr "neg_pool_range" "*,*,4084,*")]
4367)
87b22bf7 4368
4369(define_split
a2cd141b 4370 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 4371 (match_operand:SI 1 "const_int_operand" ""))]
cffb2a26 4372 "TARGET_ARM
215b30b3 4373 && (!(const_ok_for_arm (INTVAL (operands[1]))
4374 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4375 [(clobber (const_int 0))]
4376 "
96f57e36 4377 arm_split_constant (SET, SImode, NULL_RTX,
4378 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 4379 DONE;
215b30b3 4380 "
4381)
9c08d1fa 4382
cffb2a26 4383(define_insn "*thumb_movsi_insn"
215b30b3 4384 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4385 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
cffb2a26 4386 "TARGET_THUMB
4387 && ( register_operand (operands[0], SImode)
4388 || register_operand (operands[1], SImode))"
4389 "@
4390 mov %0, %1
4391 mov %0, %1
4392 #
4393 #
4394 ldmia\\t%1, {%0}
4395 stmia\\t%0, {%1}
4396 ldr\\t%0, %1
4397 str\\t%1, %0
4398 mov\\t%0, %1"
4399 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 4400 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 4401 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4402)
4403
4404(define_split
4405 [(set (match_operand:SI 0 "register_operand" "")
4406 (match_operand:SI 1 "const_int_operand" ""))]
4407 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4408 [(set (match_dup 0) (match_dup 1))
4409 (set (match_dup 0) (neg:SI (match_dup 0)))]
4410 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4411)
4412
4413(define_split
4414 [(set (match_operand:SI 0 "register_operand" "")
4415 (match_operand:SI 1 "const_int_operand" ""))]
4416 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4417 [(set (match_dup 0) (match_dup 1))
4418 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4419 "
4420 {
4421 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4422 unsigned HOST_WIDE_INT mask = 0xff;
4423 int i;
4424
4425 for (i = 0; i < 25; i++)
4426 if ((val & (mask << i)) == val)
4427 break;
4428
f5b3169c 4429 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4430 if (i == 0)
4431 FAIL;
4432
4433 operands[1] = GEN_INT (val >> i);
4434 operands[2] = GEN_INT (i);
4435 }"
4436)
4437
67336bcf 4438;; When generating pic, we need to load the symbol offset into a register.
4439;; So that the optimizer does not confuse this with a normal symbol load
4440;; we use an unspec. The offset will be loaded from a constant pool entry,
4441;; since that is the only type of relocation we can use.
4442
4443;; The rather odd constraints on the following are to force reload to leave
4444;; the insn alone, and to force the minipool generation pass to then move
4445;; the GOT symbol to memory.
849170fd 4446
8c4d8060 4447(define_insn "pic_load_addr_arm"
849170fd 4448 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4449 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4450 "TARGET_ARM && flag_pic"
67336bcf 4451 "ldr%?\\t%0, %1"
a2cd141b 4452 [(set_attr "type" "load1")
8c4d8060 4453 (set (attr "pool_range") (const_int 4096))
4454 (set (attr "neg_pool_range") (const_int 4084))]
4455)
4456
4457(define_insn "pic_load_addr_thumb"
4458 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4459 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4460 "TARGET_THUMB && flag_pic"
4461 "ldr\\t%0, %1"
a2cd141b 4462 [(set_attr "type" "load1")
8c4d8060 4463 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4464)
849170fd 4465
4466;; This variant is used for AOF assembly, since it needs to mention the
4467;; pic register in the rtl.
4468(define_expand "pic_load_addr_based"
7db9af5d 4469 [(set (match_operand:SI 0 "s_register_operand" "")
e1159bbe 4470 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
cffb2a26 4471 "TARGET_ARM && flag_pic"
4472 "operands[2] = pic_offset_table_rtx;"
4473)
849170fd 4474
4475(define_insn "*pic_load_addr_based_insn"
4476 [(set (match_operand:SI 0 "s_register_operand" "=r")
4477 (unspec:SI [(match_operand 1 "" "")
e1159bbe 4478 (match_operand 2 "s_register_operand" "r")]
4479 UNSPEC_PIC_SYM))]
cffb2a26 4480 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
849170fd 4481 "*
4482#ifdef AOF_ASSEMBLER
4483 operands[1] = aof_pic_entry (operands[1]);
4484#endif
4485 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4486 return \"\";
cffb2a26 4487 "
a2cd141b 4488 [(set_attr "type" "load1")
cffb2a26 4489 (set (attr "pool_range")
4490 (if_then_else (eq_attr "is_thumb" "yes")
4491 (const_int 1024)
4492 (const_int 4096)))
4493 (set (attr "neg_pool_range")
4494 (if_then_else (eq_attr "is_thumb" "yes")
4495 (const_int 0)
4496 (const_int 4084)))]
4497)
4498
4499(define_insn "pic_add_dot_plus_four"
4500 [(set (match_operand:SI 0 "register_operand" "+r")
2c96dc5a 4501 (unspec:SI [(plus:SI (match_dup 0)
4502 (const (plus:SI (pc) (const_int 4))))]
4503 UNSPEC_PIC_BASE))
cffb2a26 4504 (use (label_ref (match_operand 1 "" "")))]
4505 "TARGET_THUMB && flag_pic"
4506 "*
805e22b2 4507 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
cffb2a26 4508 CODE_LABEL_NUMBER (operands[1]));
4509 return \"add\\t%0, %|pc\";
4510 "
4511 [(set_attr "length" "2")]
4512)
849170fd 4513
4514(define_insn "pic_add_dot_plus_eight"
6c4c2133 4515 [(set (match_operand:SI 0 "register_operand" "+r")
2c96dc5a 4516 (unspec:SI [(plus:SI (match_dup 0)
4517 (const (plus:SI (pc) (const_int 8))))]
4518 UNSPEC_PIC_BASE))
c4034607 4519 (use (label_ref (match_operand 1 "" "")))]
cffb2a26 4520 "TARGET_ARM && flag_pic"
c4034607 4521 "*
805e22b2 4522 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
0d66636f 4523 CODE_LABEL_NUMBER (operands[1]));
4524 return \"add%?\\t%0, %|pc, %0\";
cffb2a26 4525 "
0d66636f 4526 [(set_attr "predicable" "yes")]
cffb2a26 4527)
849170fd 4528
95373f08 4529(define_expand "builtin_setjmp_receiver"
4530 [(label_ref (match_operand 0 "" ""))]
4531 "flag_pic"
4532 "
4533{
b935b306 4534 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4535 register. */
4536 arm_load_pic_register (3);
95373f08 4537 DONE;
4538}")
4539
9c08d1fa 4540;; If copying one reg to another we can set the condition codes according to
4541;; its value. Such a move is common after a return from subroutine and the
4542;; result is being tested against zero.
4543
f7fbdd4a 4544(define_insn "*movsi_compare0"
bd5b4116 4545 [(set (reg:CC CC_REGNUM)
cffb2a26 4546 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4547 (const_int 0)))
4548 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4549 (match_dup 1))]
4550 "TARGET_ARM"
e2348bcb 4551 "@
40dbec34 4552 cmp%?\\t%0, #0
4553 sub%?s\\t%0, %1, #0"
cffb2a26 4554 [(set_attr "conds" "set")]
4555)
b11cae9e 4556
b11cae9e 4557;; Subroutine to store a half word from a register into memory.
4558;; Operand 0 is the source register (HImode)
c8f69309 4559;; Operand 1 is the destination address in a register (SImode)
b11cae9e 4560
9c08d1fa 4561;; In both this routine and the next, we must be careful not to spill
01cc3b75 4562;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 4563;; can generate unrecognizable rtl.
4564
b11cae9e 4565(define_expand "storehi"
c8f69309 4566 [;; store the low byte
f082f1c4 4567 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 4568 ;; extract the high byte
c8f69309 4569 (set (match_dup 2)
4570 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 4571 ;; store the high byte
787f8210 4572 (set (match_dup 4) (match_dup 5))]
cffb2a26 4573 "TARGET_ARM"
b11cae9e 4574 "
215b30b3 4575 {
537ffcfc 4576 rtx op1 = operands[1];
4577 rtx addr = XEXP (op1, 0);
215b30b3 4578 enum rtx_code code = GET_CODE (addr);
4579
4580 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4581 || code == MINUS)
537ffcfc 4582 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 4583
537ffcfc 4584 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4585 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4586 operands[3] = gen_lowpart (QImode, operands[0]);
4587 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 4588 operands[2] = gen_reg_rtx (SImode);
4589 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4590 }"
4591)
b11cae9e 4592
c7597b5d 4593(define_expand "storehi_bigend"
f082f1c4 4594 [(set (match_dup 4) (match_dup 3))
c7597b5d 4595 (set (match_dup 2)
4596 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 4597 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 4598 "TARGET_ARM"
b11cae9e 4599 "
215b30b3 4600 {
537ffcfc 4601 rtx op1 = operands[1];
4602 rtx addr = XEXP (op1, 0);
215b30b3 4603 enum rtx_code code = GET_CODE (addr);
4604
4605 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4606 || code == MINUS)
537ffcfc 4607 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 4608
537ffcfc 4609 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4610 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4611 operands[3] = gen_lowpart (QImode, operands[0]);
4612 operands[0] = gen_lowpart (SImode, operands[0]);
4613 operands[2] = gen_reg_rtx (SImode);
787f8210 4614 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4615 }"
4616)
c7597b5d 4617
4618;; Subroutine to store a half word integer constant into memory.
4619(define_expand "storeinthi"
f082f1c4 4620 [(set (match_operand 0 "" "")
787f8210 4621 (match_operand 1 "" ""))
9e8503e6 4622 (set (match_dup 3) (match_dup 2))]
cffb2a26 4623 "TARGET_ARM"
c7597b5d 4624 "
215b30b3 4625 {
4626 HOST_WIDE_INT value = INTVAL (operands[1]);
4627 rtx addr = XEXP (operands[0], 0);
537ffcfc 4628 rtx op0 = operands[0];
215b30b3 4629 enum rtx_code code = GET_CODE (addr);
c7597b5d 4630
215b30b3 4631 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4632 || code == MINUS)
537ffcfc 4633 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 4634
215b30b3 4635 operands[1] = gen_reg_rtx (SImode);
4636 if (BYTES_BIG_ENDIAN)
4637 {
4638 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4639 if ((value & 255) == ((value >> 8) & 255))
4640 operands[2] = operands[1];
4641 else
4642 {
4643 operands[2] = gen_reg_rtx (SImode);
4644 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4645 }
4646 }
4647 else
4648 {
4649 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4650 if ((value & 255) == ((value >> 8) & 255))
4651 operands[2] = operands[1];
4652 else
4653 {
4654 operands[2] = gen_reg_rtx (SImode);
4655 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4656 }
4657 }
c7597b5d 4658
537ffcfc 4659 operands[3] = adjust_address (op0, QImode, 1);
e513d163 4660 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 4661 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 4662 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 4663 }"
4664)
b11cae9e 4665
f7fbdd4a 4666(define_expand "storehi_single_op"
4667 [(set (match_operand:HI 0 "memory_operand" "")
4668 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4669 "TARGET_ARM && arm_arch4"
f7fbdd4a 4670 "
215b30b3 4671 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 4672 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 4673 "
4674)
f7fbdd4a 4675
b11cae9e 4676(define_expand "movhi"
4677 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 4678 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4679 "TARGET_EITHER"
b11cae9e 4680 "
cffb2a26 4681 if (TARGET_ARM)
b11cae9e 4682 {
215b30b3 4683 if (!no_new_pseudos)
cffb2a26 4684 {
4685 if (GET_CODE (operands[0]) == MEM)
b11cae9e 4686 {
cffb2a26 4687 if (arm_arch4)
4688 {
4689 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4690 DONE;
4691 }
4692 if (GET_CODE (operands[1]) == CONST_INT)
4693 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 4694 else
cffb2a26 4695 {
4696 if (GET_CODE (operands[1]) == MEM)
4697 operands[1] = force_reg (HImode, operands[1]);
4698 if (BYTES_BIG_ENDIAN)
4699 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4700 else
4701 emit_insn (gen_storehi (operands[1], operands[0]));
4702 }
4703 DONE;
b11cae9e 4704 }
cffb2a26 4705 /* Sign extend a constant, and keep it in an SImode reg. */
4706 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 4707 {
cffb2a26 4708 rtx reg = gen_reg_rtx (SImode);
4709 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4710
4711 /* If the constant is already valid, leave it alone. */
215b30b3 4712 if (!const_ok_for_arm (val))
cffb2a26 4713 {
4714 /* If setting all the top bits will make the constant
4715 loadable in a single instruction, then set them.
4716 Otherwise, sign extend the number. */
4717
215b30b3 4718 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 4719 val |= ~0xffff;
4720 else if (val & 0x8000)
4721 val |= ~0xffff;
4722 }
4723
4724 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 4725 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 4726 }
615caa51 4727 else if (arm_arch4 && optimize && !no_new_pseudos
0045890a 4728 && GET_CODE (operands[1]) == MEM)
4729 {
4730 rtx reg = gen_reg_rtx (SImode);
4731
4732 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4733 operands[1] = gen_lowpart (HImode, reg);
4734 }
215b30b3 4735 else if (!arm_arch4)
f7fbdd4a 4736 {
cffb2a26 4737 if (GET_CODE (operands[1]) == MEM)
4738 {
c1a66faf 4739 rtx base;
4740 rtx offset = const0_rtx;
4741 rtx reg = gen_reg_rtx (SImode);
4742
4743 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4744 || (GET_CODE (base) == PLUS
4745 && (GET_CODE (offset = XEXP (base, 1))
4746 == CONST_INT)
4747 && ((INTVAL(offset) & 1) != 1)
4748 && GET_CODE (base = XEXP (base, 0)) == REG))
4749 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 4750 {
c1a66faf 4751 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4752 rtx new;
4753
4754 new = gen_rtx_MEM (SImode,
4755 plus_constant (base, new_offset));
4756 MEM_COPY_ATTRIBUTES (new, operands[1]);
4757 emit_insn (gen_movsi (reg, new));
4758 if (((INTVAL (offset) & 2) != 0)
4759 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4760 {
4761 rtx reg2 = gen_reg_rtx (SImode);
4762
4763 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4764 reg = reg2;
4765 }
206ee9a2 4766 }
c1a66faf 4767 else
4768 emit_insn (gen_movhi_bytes (reg, operands[1]));
4769
4770 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 4771 }
4772 }
4773 }
674a8f0b 4774 /* Handle loading a large integer during reload. */
cffb2a26 4775 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4776 && !const_ok_for_arm (INTVAL (operands[1]))
4777 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 4778 {
4779 /* Writing a constant to memory needs a scratch, which should
4780 be handled with SECONDARY_RELOADs. */
4781 if (GET_CODE (operands[0]) != REG)
4782 abort ();
4783
4784 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4785 emit_insn (gen_movsi (operands[0], operands[1]));
4786 DONE;
4787 }
4788 }
4789 else /* TARGET_THUMB */
4790 {
215b30b3 4791 if (!no_new_pseudos)
cffb2a26 4792 {
4793 if (GET_CODE (operands[0]) != REG)
4794 operands[1] = force_reg (HImode, operands[1]);
4795
4796 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4797 happen if we are passed a SP (never OK for HImode/QImode) or
4798 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4799 HImode/QImode) relative address. */
cffb2a26 4800 /* ??? This should perhaps be fixed elsewhere, for instance, in
4801 fixup_stack_1, by checking for other kinds of invalid addresses,
4802 e.g. a bare reference to a virtual register. This may confuse the
4803 alpha though, which must handle this case differently. */
4804 if (GET_CODE (operands[0]) == MEM
215b30b3 4805 && !memory_address_p (GET_MODE (operands[0]),
4806 XEXP (operands[0], 0)))
537ffcfc 4807 operands[0]
4808 = replace_equiv_address (operands[0],
4809 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 4810
4811 if (GET_CODE (operands[1]) == MEM
215b30b3 4812 && !memory_address_p (GET_MODE (operands[1]),
4813 XEXP (operands[1], 0)))
537ffcfc 4814 operands[1]
4815 = replace_equiv_address (operands[1],
4816 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 4817 }
674a8f0b 4818 /* Handle loading a large integer during reload. */
cffb2a26 4819 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4820 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
cffb2a26 4821 {
4822 /* Writing a constant to memory needs a scratch, which should
4823 be handled with SECONDARY_RELOADs. */
4824 if (GET_CODE (operands[0]) != REG)
4825 abort ();
4826
1a83b3ff 4827 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 4828 emit_insn (gen_movsi (operands[0], operands[1]));
4829 DONE;
4830 }
b11cae9e 4831 }
cffb2a26 4832 "
4833)
4834
4835(define_insn "*thumb_movhi_insn"
a941568e 4836 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4837 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
cffb2a26 4838 "TARGET_THUMB
4839 && ( register_operand (operands[0], HImode)
4840 || register_operand (operands[1], HImode))"
4841 "*
4842 switch (which_alternative)
d79300ac 4843 {
cffb2a26 4844 case 0: return \"add %0, %1, #0\";
4845 case 2: return \"strh %1, %0\";
4846 case 3: return \"mov %0, %1\";
4847 case 4: return \"mov %0, %1\";
4848 case 5: return \"mov %0, %1\";
4849 default: abort ();
4850 case 1:
4851 /* The stack pointer can end up being taken as an index register.
4852 Catch this case here and deal with it. */
4853 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4854 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4855 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4856 {
4857 rtx ops[2];
4858 ops[0] = operands[0];
4859 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4860
4861 output_asm_insn (\"mov %0, %1\", ops);
4862
4863 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4864
4865 }
4866 return \"ldrh %0, %1\";
4867 }"
4868 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 4869 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 4870)
d79300ac 4871
b11cae9e 4872
25f7a26e 4873(define_expand "movhi_bytes"
eab14235 4874 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4875 (set (match_dup 3)
eab14235 4876 (zero_extend:SI (match_dup 6)))
25f7a26e 4877 (set (match_operand:SI 0 "" "")
4878 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 4879 "TARGET_ARM"
25f7a26e 4880 "
215b30b3 4881 {
4882 rtx mem1, mem2;
4883 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4884
4885 mem1 = gen_rtx_MEM (QImode, addr);
4886 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4887 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4888 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4889 operands[0] = gen_lowpart (SImode, operands[0]);
4890 operands[1] = mem1;
4891 operands[2] = gen_reg_rtx (SImode);
4892 operands[3] = gen_reg_rtx (SImode);
4893 operands[6] = mem2;
25f7a26e 4894
215b30b3 4895 if (BYTES_BIG_ENDIAN)
4896 {
4897 operands[4] = operands[2];
4898 operands[5] = operands[3];
4899 }
4900 else
4901 {
4902 operands[4] = operands[3];
4903 operands[5] = operands[2];
4904 }
4905 }"
4906)
25f7a26e 4907
c7597b5d 4908(define_expand "movhi_bigend"
4909 [(set (match_dup 2)
4910 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4911 (const_int 16)))
4912 (set (match_dup 3)
4913 (ashiftrt:SI (match_dup 2) (const_int 16)))
4914 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 4915 (match_dup 4))]
cffb2a26 4916 "TARGET_ARM"
c7597b5d 4917 "
4918 operands[2] = gen_reg_rtx (SImode);
4919 operands[3] = gen_reg_rtx (SImode);
787f8210 4920 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 4921 "
4922)
b11cae9e 4923
a2f10574 4924;; Pattern to recognize insn generated default case above
f7fbdd4a 4925(define_insn "*movhi_insn_arch4"
cffb2a26 4926 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 4927 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 4928 "TARGET_ARM
4929 && arm_arch4
f7fbdd4a 4930 && (GET_CODE (operands[1]) != CONST_INT
4931 || const_ok_for_arm (INTVAL (operands[1]))
4932 || const_ok_for_arm (~INTVAL (operands[1])))"
4933 "@
4934 mov%?\\t%0, %1\\t%@ movhi
4935 mvn%?\\t%0, #%B1\\t%@ movhi
aed179ae 4936 str%?h\\t%1, %0\\t%@ movhi
cffb2a26 4937 ldr%?h\\t%0, %1\\t%@ movhi"
a2cd141b 4938 [(set_attr "type" "*,*,store1,load1")
0d66636f 4939 (set_attr "predicable" "yes")
cffb2a26 4940 (set_attr "pool_range" "*,*,*,256")
4941 (set_attr "neg_pool_range" "*,*,*,244")]
4942)
f7fbdd4a 4943
f7fbdd4a 4944(define_insn "*movhi_bytes"
25f7a26e 4945 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4946 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 4947 "TARGET_ARM"
25f7a26e 4948 "@
4949 mov%?\\t%0, %1\\t%@ movhi
0d66636f 4950 mvn%?\\t%0, #%B1\\t%@ movhi"
4951 [(set_attr "predicable" "yes")]
4952)
25f7a26e 4953
cffb2a26 4954(define_insn "thumb_movhi_clobber"
4955 [(set (match_operand:HI 0 "memory_operand" "=m")
4956 (match_operand:HI 1 "register_operand" "l"))
4957 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4958 "TARGET_THUMB"
344495ea 4959 "*
4960 abort ();"
cffb2a26 4961)
4962
bc5c7e08 4963;; We use a DImode scratch because we may occasionally need an additional
4964;; temporary if the address isn't offsettable -- push_reload doesn't seem
4965;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 4966(define_expand "reload_outhi"
cffb2a26 4967 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 4968 (match_operand:HI 1 "s_register_operand" "r")
4969 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 4970 "TARGET_EITHER"
4971 "if (TARGET_ARM)
4972 arm_reload_out_hi (operands);
4973 else
4974 thumb_reload_out_hi (operands);
d3373b54 4975 DONE;
cffb2a26 4976 "
4977)
d3373b54 4978
25f7a26e 4979(define_expand "reload_inhi"
4980 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 4981 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 4982 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 4983 "TARGET_EITHER"
25f7a26e 4984 "
cffb2a26 4985 if (TARGET_ARM)
4986 arm_reload_in_hi (operands);
4987 else
4988 thumb_reload_out_hi (operands);
25f7a26e 4989 DONE;
4990")
4991
9c08d1fa 4992(define_expand "movqi"
4993 [(set (match_operand:QI 0 "general_operand" "")
4994 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 4995 "TARGET_EITHER"
9c08d1fa 4996 "
cffb2a26 4997 if (TARGET_ARM)
9c08d1fa 4998 {
cffb2a26 4999 /* Everything except mem = const or mem = mem can be done easily */
c7597b5d 5000
935d87ee 5001 if (!no_new_pseudos)
cffb2a26 5002 {
5003 if (GET_CODE (operands[1]) == CONST_INT)
5004 {
5005 rtx reg = gen_reg_rtx (SImode);
5006
5007 emit_insn (gen_movsi (reg, operands[1]));
9e8503e6 5008 operands[1] = gen_lowpart (QImode, reg);
cffb2a26 5009 }
0045890a 5010 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5011 {
5012 rtx reg = gen_reg_rtx (SImode);
5013
5014 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5015 operands[1] = gen_lowpart (QImode, reg);
5016 }
5017 if (GET_CODE (operands[0]) == MEM)
5018 operands[1] = force_reg (QImode, operands[1]);
5019 }
b11cae9e 5020 }
cffb2a26 5021 else /* TARGET_THUMB */
5022 {
215b30b3 5023 if (!no_new_pseudos)
cffb2a26 5024 {
5025 if (GET_CODE (operands[0]) != REG)
5026 operands[1] = force_reg (QImode, operands[1]);
5027
5028 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5029 happen if we are passed a SP (never OK for HImode/QImode) or
5030 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5031 HImode/QImode) relative address. */
cffb2a26 5032 /* ??? This should perhaps be fixed elsewhere, for instance, in
5033 fixup_stack_1, by checking for other kinds of invalid addresses,
5034 e.g. a bare reference to a virtual register. This may confuse the
5035 alpha though, which must handle this case differently. */
5036 if (GET_CODE (operands[0]) == MEM
215b30b3 5037 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5038 XEXP (operands[0], 0)))
537ffcfc 5039 operands[0]
5040 = replace_equiv_address (operands[0],
5041 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5042 if (GET_CODE (operands[1]) == MEM
5043 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5044 XEXP (operands[1], 0)))
537ffcfc 5045 operands[1]
5046 = replace_equiv_address (operands[1],
5047 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 5048 }
674a8f0b 5049 /* Handle loading a large integer during reload. */
cffb2a26 5050 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 5051 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
cffb2a26 5052 {
5053 /* Writing a constant to memory needs a scratch, which should
5054 be handled with SECONDARY_RELOADs. */
5055 if (GET_CODE (operands[0]) != REG)
5056 abort ();
5057
9e8503e6 5058 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 5059 emit_insn (gen_movsi (operands[0], operands[1]));
5060 DONE;
5061 }
5062 }
5063 "
5064)
b11cae9e 5065
9c08d1fa 5066
cffb2a26 5067(define_insn "*arm_movqi_insn"
5068 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5069 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
cffb2a26 5070 "TARGET_ARM
5071 && ( register_operand (operands[0], QImode)
5072 || register_operand (operands[1], QImode))"
5565501b 5073 "@
5074 mov%?\\t%0, %1
5075 mvn%?\\t%0, #%B1
5076 ldr%?b\\t%0, %1
5077 str%?b\\t%1, %0"
a2cd141b 5078 [(set_attr "type" "*,*,load1,store1")
0d66636f 5079 (set_attr "predicable" "yes")]
cffb2a26 5080)
5081
5082(define_insn "*thumb_movqi_insn"
5083 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5084 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
cffb2a26 5085 "TARGET_THUMB
5086 && ( register_operand (operands[0], QImode)
5087 || register_operand (operands[1], QImode))"
5088 "@
5089 add\\t%0, %1, #0
5090 ldrb\\t%0, %1
5091 strb\\t%1, %0
5092 mov\\t%0, %1
5093 mov\\t%0, %1
5094 mov\\t%0, %1"
5095 [(set_attr "length" "2")
a2cd141b 5096 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5097 (set_attr "pool_range" "*,32,*,*,*,*")]
5098)
b11cae9e 5099
87b22bf7 5100(define_expand "movsf"
5101 [(set (match_operand:SF 0 "general_operand" "")
5102 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5103 "TARGET_EITHER"
87b22bf7 5104 "
cffb2a26 5105 if (TARGET_ARM)
5106 {
5107 if (GET_CODE (operands[0]) == MEM)
5108 operands[1] = force_reg (SFmode, operands[1]);
5109 }
5110 else /* TARGET_THUMB */
5111 {
215b30b3 5112 if (!no_new_pseudos)
cffb2a26 5113 {
5114 if (GET_CODE (operands[0]) != REG)
5115 operands[1] = force_reg (SFmode, operands[1]);
5116 }
5117 }
5118 "
5119)
5120
5121(define_split
5122 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5123 (match_operand:SF 1 "immediate_operand" ""))]
5124 "TARGET_ARM
a2cd141b 5125 && !(TARGET_HARD_FLOAT && TARGET_FPA)
cffb2a26 5126 && reload_completed
5127 && GET_CODE (operands[1]) == CONST_DOUBLE"
5128 [(set (match_dup 2) (match_dup 3))]
5129 "
5130 operands[2] = gen_lowpart (SImode, operands[0]);
5131 operands[3] = gen_lowpart (SImode, operands[1]);
5132 if (operands[2] == 0 || operands[3] == 0)
5133 FAIL;
215b30b3 5134 "
5135)
87b22bf7 5136
cffb2a26 5137(define_insn "*arm_movsf_soft_insn"
5138 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5139 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5140 "TARGET_ARM
5141 && TARGET_SOFT_FLOAT
215b30b3 5142 && (GET_CODE (operands[0]) != MEM
5143 || register_operand (operands[1], SFmode))"
9a1112d7 5144 "@
5145 mov%?\\t%0, %1
5146 ldr%?\\t%0, %1\\t%@ float
5147 str%?\\t%1, %0\\t%@ float"
cffb2a26 5148 [(set_attr "length" "4,4,4")
0d66636f 5149 (set_attr "predicable" "yes")
a2cd141b 5150 (set_attr "type" "*,load1,store1")
cffb2a26 5151 (set_attr "pool_range" "*,4096,*")
5152 (set_attr "neg_pool_range" "*,4084,*")]
5153)
5154
5155;;; ??? This should have alternatives for constants.
5156(define_insn "*thumb_movsf_insn"
215b30b3 5157 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5158 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
cffb2a26 5159 "TARGET_THUMB
5160 && ( register_operand (operands[0], SFmode)
5161 || register_operand (operands[1], SFmode))"
5162 "@
5163 add\\t%0, %1, #0
5164 ldmia\\t%1, {%0}
5165 stmia\\t%0, {%1}
5166 ldr\\t%0, %1
5167 str\\t%1, %0
5168 mov\\t%0, %1
5169 mov\\t%0, %1"
5170 [(set_attr "length" "2")
a2cd141b 5171 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5172 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5173)
9a1112d7 5174
9c08d1fa 5175(define_expand "movdf"
87b22bf7 5176 [(set (match_operand:DF 0 "general_operand" "")
5177 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5178 "TARGET_EITHER"
9c08d1fa 5179 "
cffb2a26 5180 if (TARGET_ARM)
5181 {
5182 if (GET_CODE (operands[0]) == MEM)
5183 operands[1] = force_reg (DFmode, operands[1]);
5184 }
5185 else /* TARGET_THUMB */
5186 {
215b30b3 5187 if (!no_new_pseudos)
cffb2a26 5188 {
5189 if (GET_CODE (operands[0]) != REG)
5190 operands[1] = force_reg (DFmode, operands[1]);
5191 }
5192 }
5193 "
5194)
b11cae9e 5195
9c08d1fa 5196;; Reloading a df mode value stored in integer regs to memory can require a
5197;; scratch reg.
5198(define_expand "reload_outdf"
cffb2a26 5199 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5200 (match_operand:DF 1 "s_register_operand" "r")
5201 (match_operand:SI 2 "s_register_operand" "=&r")]
cffb2a26 5202 "TARGET_ARM"
87b22bf7 5203 "
215b30b3 5204 {
5205 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5206
215b30b3 5207 if (code == REG)
5208 operands[2] = XEXP (operands[0], 0);
5209 else if (code == POST_INC || code == PRE_DEC)
5210 {
5211 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5212 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5213 emit_insn (gen_movdi (operands[0], operands[1]));
5214 DONE;
5215 }
5216 else if (code == PRE_INC)
5217 {
5218 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5219
215b30b3 5220 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5221 operands[2] = reg;
5222 }
5223 else if (code == POST_DEC)
5224 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5225 else
5226 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5227 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5228
215b30b3 5229 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5230 operands[1]));
f7fbdd4a 5231
215b30b3 5232 if (code == POST_DEC)
5233 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5234
5235 DONE;
5236 }"
5237)
9c08d1fa 5238
9a1112d7 5239(define_insn "*movdf_soft_insn"
359a6e9f 5240 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5241 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 5242 "TARGET_ARM && TARGET_SOFT_FLOAT
5243 "
d51f92df 5244 "*
5245 switch (which_alternative)
5246 {
5247 case 0:
5248 case 1:
5249 case 2:
5250 return \"#\";
5251 default:
5252 return output_move_double (operands);
5253 }
5254 "
359a6e9f 5255 [(set_attr "length" "8,12,16,8,8")
5256 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 5257 (set_attr "pool_range" "1020")
5258 (set_attr "neg_pool_range" "1008")]
cffb2a26 5259)
5260
5261;;; ??? This should have alternatives for constants.
5262;;; ??? This was originally identical to the movdi_insn pattern.
5263;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5264;;; thumb_reorg with a memory reference.
5265(define_insn "*thumb_movdf_insn"
215b30b3 5266 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5267 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
cffb2a26 5268 "TARGET_THUMB
5269 && ( register_operand (operands[0], DFmode)
5270 || register_operand (operands[1], DFmode))"
5271 "*
5272 switch (which_alternative)
5273 {
5274 default:
5275 case 0:
5276 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5277 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5278 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5279 case 1:
5280 return \"ldmia\\t%1, {%0, %H0}\";
5281 case 2:
5282 return \"stmia\\t%0, {%1, %H1}\";
5283 case 3:
5284 return thumb_load_double_from_address (operands);
5285 case 4:
1a83b3ff 5286 operands[2] = gen_rtx_MEM (SImode,
5287 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5288 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5289 return \"\";
5290 case 5:
5291 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5292 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5293 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5294 }
5295 "
5296 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 5297 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 5298 (set_attr "pool_range" "*,*,*,1020,*,*")]
5299)
755eb2b4 5300
ccd90aaa 5301(define_expand "movxf"
5302 [(set (match_operand:XF 0 "general_operand" "")
5303 (match_operand:XF 1 "general_operand" ""))]
5304 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5305 "
5306 if (GET_CODE (operands[0]) == MEM)
5307 operands[1] = force_reg (XFmode, operands[1]);
5308 "
5309)
5310
755eb2b4 5311;; Vector Moves
5312(define_expand "movv2si"
5313 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5314 (match_operand:V2SI 1 "general_operand" ""))]
5315 "TARGET_REALLY_IWMMXT"
5316{
5317})
5318
5319(define_expand "movv4hi"
5320 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5321 (match_operand:V4HI 1 "general_operand" ""))]
5322 "TARGET_REALLY_IWMMXT"
5323{
5324})
5325
5326(define_expand "movv8qi"
5327 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5328 (match_operand:V8QI 1 "general_operand" ""))]
5329 "TARGET_REALLY_IWMMXT"
5330{
5331})
b11cae9e 5332\f
b11cae9e 5333
9c08d1fa 5334;; load- and store-multiple insns
5335;; The arm can load/store any set of registers, provided that they are in
5336;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5337
9c08d1fa 5338(define_expand "load_multiple"
5339 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5340 (match_operand:SI 1 "" ""))
5341 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5342 "TARGET_ARM"
9580c25f 5343{
5344 HOST_WIDE_INT offset = 0;
5345
bd5b4116 5346 /* Support only fixed point registers. */
9c08d1fa 5347 if (GET_CODE (operands[2]) != CONST_INT
5348 || INTVAL (operands[2]) > 14
5349 || INTVAL (operands[2]) < 2
5350 || GET_CODE (operands[1]) != MEM
5351 || GET_CODE (operands[0]) != REG
bd5b4116 5352 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5353 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5354 FAIL;
5355
5356 operands[3]
f082f1c4 5357 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5358 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 5359 TRUE, FALSE, operands[1], &offset);
5360})
b11cae9e 5361
9c08d1fa 5362;; Load multiple with write-back
5363
2162064c 5364(define_insn "*ldmsi_postinc4"
9c08d1fa 5365 [(match_parallel 0 "load_multiple_operation"
13e9316a 5366 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5367 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5368 (const_int 16)))
5369 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5370 (mem:SI (match_dup 2)))
a0a72ac3 5371 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5372 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5373 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5374 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5375 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5376 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5377 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5378 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
a2cd141b 5379 [(set_attr "type" "load4")
2162064c 5380 (set_attr "predicable" "yes")]
5381)
b11cae9e 5382
ccd90aaa 5383(define_insn "*ldmsi_postinc4_thumb"
5384 [(match_parallel 0 "load_multiple_operation"
5385 [(set (match_operand:SI 1 "s_register_operand" "=l")
5386 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5387 (const_int 16)))
5388 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5389 (mem:SI (match_dup 2)))
5390 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5391 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5392 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5393 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5394 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5395 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5396 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5397 "ldmia\\t%1!, {%3, %4, %5, %6}"
5398 [(set_attr "type" "load4")]
5399)
5400
2162064c 5401(define_insn "*ldmsi_postinc3"
5402 [(match_parallel 0 "load_multiple_operation"
13e9316a 5403 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5404 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5405 (const_int 12)))
5406 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5407 (mem:SI (match_dup 2)))
5408 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5409 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5410 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5411 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5412 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5413 "ldm%?ia\\t%1!, {%3, %4, %5}"
a2cd141b 5414 [(set_attr "type" "load3")
2162064c 5415 (set_attr "predicable" "yes")]
5416)
b11cae9e 5417
2162064c 5418(define_insn "*ldmsi_postinc2"
5419 [(match_parallel 0 "load_multiple_operation"
13e9316a 5420 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5421 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5422 (const_int 8)))
5423 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5424 (mem:SI (match_dup 2)))
5425 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5426 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5427 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5428 "ldm%?ia\\t%1!, {%3, %4}"
a2cd141b 5429 [(set_attr "type" "load2")
0d66636f 5430 (set_attr "predicable" "yes")]
5431)
b11cae9e 5432
9c08d1fa 5433;; Ordinary load multiple
b11cae9e 5434
2162064c 5435(define_insn "*ldmsi4"
9c08d1fa 5436 [(match_parallel 0 "load_multiple_operation"
2162064c 5437 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5438 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5439 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5440 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5441 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5442 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5443 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5444 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5445 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5446 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
a2cd141b 5447 [(set_attr "type" "load4")
2162064c 5448 (set_attr "predicable" "yes")]
5449)
9c08d1fa 5450
2162064c 5451(define_insn "*ldmsi3"
5452 [(match_parallel 0 "load_multiple_operation"
5453 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5454 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5455 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5456 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5457 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5458 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5459 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5460 "ldm%?ia\\t%1, {%2, %3, %4}"
a2cd141b 5461 [(set_attr "type" "load3")
2162064c 5462 (set_attr "predicable" "yes")]
5463)
9c08d1fa 5464
2162064c 5465(define_insn "*ldmsi2"
5466 [(match_parallel 0 "load_multiple_operation"
5467 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5468 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5469 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5470 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5471 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5472 "ldm%?ia\\t%1, {%2, %3}"
a2cd141b 5473 [(set_attr "type" "load2")
0d66636f 5474 (set_attr "predicable" "yes")]
5475)
9c08d1fa 5476
5477(define_expand "store_multiple"
5478 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5479 (match_operand:SI 1 "" ""))
5480 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5481 "TARGET_ARM"
9580c25f 5482{
5483 HOST_WIDE_INT offset = 0;
5484
674a8f0b 5485 /* Support only fixed point registers. */
9c08d1fa 5486 if (GET_CODE (operands[2]) != CONST_INT
5487 || INTVAL (operands[2]) > 14
5488 || INTVAL (operands[2]) < 2
5489 || GET_CODE (operands[1]) != REG
5490 || GET_CODE (operands[0]) != MEM
bd5b4116 5491 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5492 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5493 FAIL;
5494
5495 operands[3]
f082f1c4 5496 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5497 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 5498 TRUE, FALSE, operands[0], &offset);
5499})
b11cae9e 5500
9c08d1fa 5501;; Store multiple with write-back
5502
2162064c 5503(define_insn "*stmsi_postinc4"
9c08d1fa 5504 [(match_parallel 0 "store_multiple_operation"
13e9316a 5505 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5506 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5507 (const_int 16)))
a0a72ac3 5508 (set (mem:SI (match_dup 2))
2162064c 5509 (match_operand:SI 3 "arm_hard_register_operand" ""))
5510 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5511 (match_operand:SI 4 "arm_hard_register_operand" ""))
5512 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5513 (match_operand:SI 5 "arm_hard_register_operand" ""))
5514 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5515 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5516 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5517 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5518 [(set_attr "predicable" "yes")
5519 (set_attr "type" "store4")]
5520)
b11cae9e 5521
ccd90aaa 5522(define_insn "*stmsi_postinc4_thumb"
5523 [(match_parallel 0 "store_multiple_operation"
5524 [(set (match_operand:SI 1 "s_register_operand" "=l")
5525 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5526 (const_int 16)))
5527 (set (mem:SI (match_dup 2))
5528 (match_operand:SI 3 "arm_hard_register_operand" ""))
5529 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5530 (match_operand:SI 4 "arm_hard_register_operand" ""))
5531 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5532 (match_operand:SI 5 "arm_hard_register_operand" ""))
5533 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5534 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5535 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5536 "stmia\\t%1!, {%3, %4, %5, %6}"
5537 [(set_attr "type" "store4")]
5538)
5539
2162064c 5540(define_insn "*stmsi_postinc3"
5541 [(match_parallel 0 "store_multiple_operation"
13e9316a 5542 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5543 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5544 (const_int 12)))
5545 (set (mem:SI (match_dup 2))
5546 (match_operand:SI 3 "arm_hard_register_operand" ""))
5547 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5548 (match_operand:SI 4 "arm_hard_register_operand" ""))
5549 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5550 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5551 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5552 "stm%?ia\\t%1!, {%3, %4, %5}"
5553 [(set_attr "predicable" "yes")
5554 (set_attr "type" "store3")]
5555)
9c08d1fa 5556
2162064c 5557(define_insn "*stmsi_postinc2"
5558 [(match_parallel 0 "store_multiple_operation"
13e9316a 5559 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5560 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5561 (const_int 8)))
5562 (set (mem:SI (match_dup 2))
5563 (match_operand:SI 3 "arm_hard_register_operand" ""))
5564 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5565 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5566 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5567 "stm%?ia\\t%1!, {%3, %4}"
0d66636f 5568 [(set_attr "predicable" "yes")
2162064c 5569 (set_attr "type" "store2")]
cffb2a26 5570)
9c08d1fa 5571
5572;; Ordinary store multiple
5573
2162064c 5574(define_insn "*stmsi4"
9c08d1fa 5575 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 5576 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 5577 (match_operand:SI 2 "arm_hard_register_operand" ""))
5578 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5579 (match_operand:SI 3 "arm_hard_register_operand" ""))
5580 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5581 (match_operand:SI 4 "arm_hard_register_operand" ""))
5582 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5583 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5584 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5585 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5586 [(set_attr "predicable" "yes")
5587 (set_attr "type" "store4")]
5588)
9c08d1fa 5589
2162064c 5590(define_insn "*stmsi3"
5591 [(match_parallel 0 "store_multiple_operation"
5592 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5593 (match_operand:SI 2 "arm_hard_register_operand" ""))
5594 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5595 (match_operand:SI 3 "arm_hard_register_operand" ""))
5596 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5597 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5598 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5599 "stm%?ia\\t%1, {%2, %3, %4}"
5600 [(set_attr "predicable" "yes")
5601 (set_attr "type" "store3")]
5602)
9c08d1fa 5603
2162064c 5604(define_insn "*stmsi2"
5605 [(match_parallel 0 "store_multiple_operation"
5606 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5607 (match_operand:SI 2 "arm_hard_register_operand" ""))
5608 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5609 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5610 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5611 "stm%?ia\\t%1, {%2, %3}"
0d66636f 5612 [(set_attr "predicable" "yes")
2162064c 5613 (set_attr "type" "store2")]
cffb2a26 5614)
9c08d1fa 5615
5616;; Move a block of memory if it is word aligned and MORE than 2 words long.
5617;; We could let this apply for blocks of less than this, but it clobbers so
5618;; many registers that there is then probably a better way.
5619
008c057d 5620(define_expand "movmemqi"
34191dd1 5621 [(match_operand:BLK 0 "general_operand" "")
5622 (match_operand:BLK 1 "general_operand" "")
5623 (match_operand:SI 2 "const_int_operand" "")
5624 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 5625 "TARGET_EITHER"
9c08d1fa 5626 "
cffb2a26 5627 if (TARGET_ARM)
5628 {
008c057d 5629 if (arm_gen_movmemqi (operands))
cffb2a26 5630 DONE;
5631 FAIL;
5632 }
5633 else /* TARGET_THUMB */
5634 {
5635 if ( INTVAL (operands[3]) != 4
5636 || INTVAL (operands[2]) > 48)
5637 FAIL;
5638
008c057d 5639 thumb_expand_movmemqi (operands);
cffb2a26 5640 DONE;
5641 }
5642 "
5643)
5644
2162064c 5645;; Thumb block-move insns
cffb2a26 5646
5647(define_insn "movmem12b"
960f3acf 5648 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5649 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5650 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5651 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5652 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5653 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5654 (set (match_operand:SI 0 "register_operand" "=l")
5655 (plus:SI (match_dup 2) (const_int 12)))
5656 (set (match_operand:SI 1 "register_operand" "=l")
5657 (plus:SI (match_dup 3) (const_int 12)))
5658 (clobber (match_scratch:SI 4 "=&l"))
5659 (clobber (match_scratch:SI 5 "=&l"))
5660 (clobber (match_scratch:SI 6 "=&l"))]
cffb2a26 5661 "TARGET_THUMB"
5662 "* return thumb_output_move_mem_multiple (3, operands);"
5663 [(set_attr "length" "4")
215b30b3 5664 ; This isn't entirely accurate... It loads as well, but in terms of
5665 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5666 (set_attr "type" "store3")]
5667)
5668
5669(define_insn "movmem8b"
960f3acf 5670 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5671 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5672 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5673 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5674 (set (match_operand:SI 0 "register_operand" "=l")
5675 (plus:SI (match_dup 2) (const_int 8)))
5676 (set (match_operand:SI 1 "register_operand" "=l")
5677 (plus:SI (match_dup 3) (const_int 8)))
5678 (clobber (match_scratch:SI 4 "=&l"))
5679 (clobber (match_scratch:SI 5 "=&l"))]
cffb2a26 5680 "TARGET_THUMB"
5681 "* return thumb_output_move_mem_multiple (2, operands);"
5682 [(set_attr "length" "4")
215b30b3 5683 ; This isn't entirely accurate... It loads as well, but in terms of
5684 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5685 (set_attr "type" "store2")]
5686)
5687
9c08d1fa 5688\f
b11cae9e 5689
341940e8 5690;; Compare & branch insns
8d232dc7 5691;; The range calculations are based as follows:
341940e8 5692;; For forward branches, the address calculation returns the address of
5693;; the next instruction. This is 2 beyond the branch instruction.
5694;; For backward branches, the address calculation returns the address of
5695;; the first instruction in this pattern (cmp). This is 2 before the branch
5696;; instruction for the shortest sequence, and 4 before the branch instruction
5697;; if we have to jump around an unconditional branch.
5698;; To the basic branch range the PC offset must be added (this is +4).
5699;; So for forward branches we have
5700;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5701;; And for backward branches we have
5702;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5703;;
5704;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5705;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 5706
aeac46d4 5707(define_expand "cbranchsi4"
5708 [(set (pc) (if_then_else
5709 (match_operator 0 "arm_comparison_operator"
5710 [(match_operand:SI 1 "s_register_operand" "")
5711 (match_operand:SI 2 "nonmemory_operand" "")])
5712 (label_ref (match_operand 3 "" ""))
5713 (pc)))]
5714 "TARGET_THUMB"
5715 "
5716 if (thumb_cmpneg_operand (operands[2], SImode))
5717 {
5718 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5719 operands[3], operands[0]));
5720 DONE;
5721 }
5722 if (!thumb_cmp_operand (operands[2], SImode))
5723 operands[2] = force_reg (SImode, operands[2]);
5724 ")
5725
5726(define_insn "*cbranchsi4_insn"
5727 [(set (pc) (if_then_else
5728 (match_operator 0 "arm_comparison_operator"
5729 [(match_operand:SI 1 "s_register_operand" "l,*h")
5730 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5731 (label_ref (match_operand 3 "" ""))
5732 (pc)))]
cffb2a26 5733 "TARGET_THUMB"
5734 "*
5735 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 5736
cffb2a26 5737 switch (get_attr_length (insn))
5738 {
5739 case 4: return \"b%d0\\t%l3\";
5740 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5741 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5742 }
5743 "
5744 [(set (attr "far_jump")
5745 (if_then_else
5746 (eq_attr "length" "8")
5747 (const_string "yes")
5748 (const_string "no")))
5749 (set (attr "length")
5750 (if_then_else
5751 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5752 (le (minus (match_dup 3) (pc)) (const_int 256)))
5753 (const_int 4)
5754 (if_then_else
5755 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 5756 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5757 (const_int 6)
5758 (const_int 8))))]
5759)
5760
aeac46d4 5761(define_insn "cbranchsi4_scratch"
5762 [(set (pc) (if_then_else
5763 (match_operator 4 "arm_comparison_operator"
5764 [(match_operand:SI 1 "s_register_operand" "l,0")
5765 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5766 (label_ref (match_operand 3 "" ""))
5767 (pc)))
5768 (clobber (match_scratch:SI 0 "=l,l"))]
5769 "TARGET_THUMB"
5770 "*
5771 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5772
5773 switch (get_attr_length (insn))
5774 {
5775 case 4: return \"b%d4\\t%l3\";
5776 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5777 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5778 }
5779 "
5780 [(set (attr "far_jump")
5781 (if_then_else
5782 (eq_attr "length" "8")
5783 (const_string "yes")
5784 (const_string "no")))
5785 (set (attr "length")
5786 (if_then_else
5787 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5788 (le (minus (match_dup 3) (pc)) (const_int 256)))
5789 (const_int 4)
5790 (if_then_else
5791 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5792 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5793 (const_int 6)
5794 (const_int 8))))]
5795)
5796(define_insn "*movsi_cbranchsi4"
5797 [(set (pc)
5798 (if_then_else
5799 (match_operator 3 "arm_comparison_operator"
5800 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5801 (const_int 0)])
5802 (label_ref (match_operand 2 "" ""))
5803 (pc)))
5804 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5805 (match_dup 1))]
5806 "TARGET_THUMB"
5807 "*{
5808 if (which_alternative == 0)
5809 output_asm_insn (\"cmp\t%0, #0\", operands);
5810 else if (which_alternative == 1)
5811 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5812 else
5813 {
5814 output_asm_insn (\"cmp\t%1, #0\", operands);
5815 if (which_alternative == 2)
5816 output_asm_insn (\"mov\t%0, %1\", operands);
5817 else
5818 output_asm_insn (\"str\t%1, %0\", operands);
5819 }
5820 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5821 {
5822 case 4: return \"b%d3\\t%l2\";
5823 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5824 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5825 }
5826 }"
5827 [(set (attr "far_jump")
5828 (if_then_else
5829 (ior (and (gt (symbol_ref ("which_alternative"))
5830 (const_int 1))
5831 (eq_attr "length" "8"))
5832 (eq_attr "length" "10"))
5833 (const_string "yes")
5834 (const_string "no")))
5835 (set (attr "length")
5836 (if_then_else
5837 (le (symbol_ref ("which_alternative"))
5838 (const_int 1))
5839 (if_then_else
5840 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5841 (le (minus (match_dup 2) (pc)) (const_int 256)))
5842 (const_int 4)
5843 (if_then_else
5844 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5845 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5846 (const_int 6)
5847 (const_int 8)))
5848 (if_then_else
5849 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5850 (le (minus (match_dup 2) (pc)) (const_int 256)))
5851 (const_int 6)
5852 (if_then_else
5853 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5854 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5855 (const_int 8)
5856 (const_int 10)))))]
5857)
5858
cffb2a26 5859(define_insn "*negated_cbranchsi4"
5860 [(set (pc)
5861 (if_then_else
aed179ae 5862 (match_operator 0 "equality_operator"
aeac46d4 5863 [(match_operand:SI 1 "s_register_operand" "l")
5864 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5865 (label_ref (match_operand 3 "" ""))
215b30b3 5866 (pc)))]
cffb2a26 5867 "TARGET_THUMB"
5868 "*
5869 output_asm_insn (\"cmn\\t%1, %2\", operands);
5870 switch (get_attr_length (insn))
5871 {
5872 case 4: return \"b%d0\\t%l3\";
5873 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5874 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5875 }
5876 "
5877 [(set (attr "far_jump")
5878 (if_then_else
5879 (eq_attr "length" "8")
5880 (const_string "yes")
5881 (const_string "no")))
5882 (set (attr "length")
5883 (if_then_else
5884 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 5885 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 5886 (const_int 4)
5887 (if_then_else
341940e8 5888 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5889 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5890 (const_int 6)
5891 (const_int 8))))]
5892)
5893
58d6528b 5894(define_insn "*tbit_cbranch"
5895 [(set (pc)
5896 (if_then_else
5897 (match_operator 0 "equality_operator"
5898 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5899 (const_int 1)
5900 (match_operand:SI 2 "const_int_operand" "i"))
5901 (const_int 0)])
5902 (label_ref (match_operand 3 "" ""))
5903 (pc)))
5904 (clobber (match_scratch:SI 4 "=l"))]
5905 "TARGET_THUMB"
5906 "*
5907 {
5908 rtx op[3];
5909 op[0] = operands[4];
5910 op[1] = operands[1];
5911 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5912
5913 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5914 switch (get_attr_length (insn))
5915 {
5916 case 4: return \"b%d0\\t%l3\";
5917 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5918 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5919 }
5920 }"
5921 [(set (attr "far_jump")
5922 (if_then_else
5923 (eq_attr "length" "8")
5924 (const_string "yes")
5925 (const_string "no")))
5926 (set (attr "length")
5927 (if_then_else
5928 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5929 (le (minus (match_dup 3) (pc)) (const_int 256)))
5930 (const_int 4)
5931 (if_then_else
5932 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5933 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5934 (const_int 6)
5935 (const_int 8))))]
5936)
5937
aeac46d4 5938(define_insn "*tstsi3_cbranch"
58d6528b 5939 [(set (pc)
5940 (if_then_else
aeac46d4 5941 (match_operator 3 "equality_operator"
5942 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5943 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 5944 (const_int 0)])
aeac46d4 5945 (label_ref (match_operand 2 "" ""))
5946 (pc)))]
58d6528b 5947 "TARGET_THUMB"
5948 "*
5949 {
aeac46d4 5950 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 5951 switch (get_attr_length (insn))
5952 {
aeac46d4 5953 case 4: return \"b%d3\\t%l2\";
5954 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5955 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 5956 }
5957 }"
5958 [(set (attr "far_jump")
5959 (if_then_else
5960 (eq_attr "length" "8")
5961 (const_string "yes")
5962 (const_string "no")))
5963 (set (attr "length")
5964 (if_then_else
aeac46d4 5965 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5966 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 5967 (const_int 4)
5968 (if_then_else
aeac46d4 5969 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5970 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 5971 (const_int 6)
5972 (const_int 8))))]
5973)
5974
5975(define_insn "*andsi3_cbranch"
5976 [(set (pc)
5977 (if_then_else
5978 (match_operator 5 "equality_operator"
5979 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5980 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5981 (const_int 0)])
5982 (label_ref (match_operand 4 "" ""))
5983 (pc)))
aeac46d4 5984 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 5985 (and:SI (match_dup 2) (match_dup 3)))
5986 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5987 "TARGET_THUMB"
5988 "*
5989 {
5990 if (which_alternative == 0)
5991 output_asm_insn (\"and\\t%0, %3\", operands);
5992 else if (which_alternative == 1)
5993 {
5994 output_asm_insn (\"and\\t%1, %3\", operands);
5995 output_asm_insn (\"mov\\t%0, %1\", operands);
5996 }
5997 else
5998 {
5999 output_asm_insn (\"and\\t%1, %3\", operands);
6000 output_asm_insn (\"str\\t%1, %0\", operands);
6001 }
6002
6003 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6004 {
6005 case 4: return \"b%d5\\t%l4\";
6006 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6007 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6008 }
6009 }"
6010 [(set (attr "far_jump")
6011 (if_then_else
6012 (ior (and (eq (symbol_ref ("which_alternative"))
6013 (const_int 0))
6014 (eq_attr "length" "8"))
6015 (eq_attr "length" "10"))
6016 (const_string "yes")
6017 (const_string "no")))
6018 (set (attr "length")
6019 (if_then_else
6020 (eq (symbol_ref ("which_alternative"))
6021 (const_int 0))
6022 (if_then_else
6023 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6024 (le (minus (match_dup 4) (pc)) (const_int 256)))
6025 (const_int 4)
6026 (if_then_else
6027 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6028 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6029 (const_int 6)
6030 (const_int 8)))
6031 (if_then_else
6032 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6033 (le (minus (match_dup 4) (pc)) (const_int 256)))
6034 (const_int 6)
6035 (if_then_else
6036 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6037 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6038 (const_int 8)
6039 (const_int 10)))))]
6040)
6041
6042(define_insn "*orrsi3_cbranch_scratch"
6043 [(set (pc)
6044 (if_then_else
6045 (match_operator 4 "equality_operator"
6046 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6047 (match_operand:SI 2 "s_register_operand" "l"))
6048 (const_int 0)])
6049 (label_ref (match_operand 3 "" ""))
6050 (pc)))
6051 (clobber (match_scratch:SI 0 "=l"))]
6052 "TARGET_THUMB"
6053 "*
6054 {
6055 output_asm_insn (\"orr\\t%0, %2\", operands);
6056 switch (get_attr_length (insn))
6057 {
6058 case 4: return \"b%d4\\t%l3\";
6059 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6060 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6061 }
6062 }"
6063 [(set (attr "far_jump")
6064 (if_then_else
6065 (eq_attr "length" "8")
6066 (const_string "yes")
6067 (const_string "no")))
6068 (set (attr "length")
6069 (if_then_else
6070 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6071 (le (minus (match_dup 3) (pc)) (const_int 256)))
6072 (const_int 4)
6073 (if_then_else
6074 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6075 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6076 (const_int 6)
6077 (const_int 8))))]
6078)
6079
6080(define_insn "*orrsi3_cbranch"
6081 [(set (pc)
6082 (if_then_else
6083 (match_operator 5 "equality_operator"
6084 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6085 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6086 (const_int 0)])
6087 (label_ref (match_operand 4 "" ""))
6088 (pc)))
aeac46d4 6089 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6090 (ior:SI (match_dup 2) (match_dup 3)))
6091 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6092 "TARGET_THUMB"
6093 "*
6094 {
6095 if (which_alternative == 0)
6096 output_asm_insn (\"orr\\t%0, %3\", operands);
6097 else if (which_alternative == 1)
6098 {
6099 output_asm_insn (\"orr\\t%1, %3\", operands);
6100 output_asm_insn (\"mov\\t%0, %1\", operands);
6101 }
6102 else
6103 {
6104 output_asm_insn (\"orr\\t%1, %3\", operands);
6105 output_asm_insn (\"str\\t%1, %0\", operands);
6106 }
6107
6108 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6109 {
6110 case 4: return \"b%d5\\t%l4\";
6111 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6112 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6113 }
6114 }"
6115 [(set (attr "far_jump")
6116 (if_then_else
6117 (ior (and (eq (symbol_ref ("which_alternative"))
6118 (const_int 0))
6119 (eq_attr "length" "8"))
6120 (eq_attr "length" "10"))
6121 (const_string "yes")
6122 (const_string "no")))
6123 (set (attr "length")
6124 (if_then_else
6125 (eq (symbol_ref ("which_alternative"))
6126 (const_int 0))
6127 (if_then_else
6128 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6129 (le (minus (match_dup 4) (pc)) (const_int 256)))
6130 (const_int 4)
6131 (if_then_else
6132 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6133 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6134 (const_int 6)
6135 (const_int 8)))
6136 (if_then_else
6137 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6138 (le (minus (match_dup 4) (pc)) (const_int 256)))
6139 (const_int 6)
6140 (if_then_else
6141 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6142 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6143 (const_int 8)
6144 (const_int 10)))))]
6145)
6146
6147(define_insn "*xorsi3_cbranch_scratch"
6148 [(set (pc)
6149 (if_then_else
6150 (match_operator 4 "equality_operator"
6151 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6152 (match_operand:SI 2 "s_register_operand" "l"))
6153 (const_int 0)])
6154 (label_ref (match_operand 3 "" ""))
6155 (pc)))
6156 (clobber (match_scratch:SI 0 "=l"))]
6157 "TARGET_THUMB"
6158 "*
6159 {
6160 output_asm_insn (\"eor\\t%0, %2\", operands);
6161 switch (get_attr_length (insn))
6162 {
6163 case 4: return \"b%d4\\t%l3\";
6164 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6165 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6166 }
6167 }"
6168 [(set (attr "far_jump")
6169 (if_then_else
6170 (eq_attr "length" "8")
6171 (const_string "yes")
6172 (const_string "no")))
6173 (set (attr "length")
6174 (if_then_else
6175 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6176 (le (minus (match_dup 3) (pc)) (const_int 256)))
6177 (const_int 4)
6178 (if_then_else
6179 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6180 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6181 (const_int 6)
6182 (const_int 8))))]
6183)
6184
6185(define_insn "*xorsi3_cbranch"
6186 [(set (pc)
6187 (if_then_else
6188 (match_operator 5 "equality_operator"
6189 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6190 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6191 (const_int 0)])
6192 (label_ref (match_operand 4 "" ""))
6193 (pc)))
aeac46d4 6194 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6195 (xor:SI (match_dup 2) (match_dup 3)))
6196 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6197 "TARGET_THUMB"
6198 "*
6199 {
6200 if (which_alternative == 0)
6201 output_asm_insn (\"eor\\t%0, %3\", operands);
6202 else if (which_alternative == 1)
6203 {
6204 output_asm_insn (\"eor\\t%1, %3\", operands);
6205 output_asm_insn (\"mov\\t%0, %1\", operands);
6206 }
6207 else
6208 {
6209 output_asm_insn (\"eor\\t%1, %3\", operands);
6210 output_asm_insn (\"str\\t%1, %0\", operands);
6211 }
6212
6213 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6214 {
6215 case 4: return \"b%d5\\t%l4\";
6216 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6217 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6218 }
6219 }"
6220 [(set (attr "far_jump")
6221 (if_then_else
6222 (ior (and (eq (symbol_ref ("which_alternative"))
6223 (const_int 0))
6224 (eq_attr "length" "8"))
6225 (eq_attr "length" "10"))
6226 (const_string "yes")
6227 (const_string "no")))
6228 (set (attr "length")
6229 (if_then_else
6230 (eq (symbol_ref ("which_alternative"))
6231 (const_int 0))
6232 (if_then_else
6233 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6234 (le (minus (match_dup 4) (pc)) (const_int 256)))
6235 (const_int 4)
6236 (if_then_else
6237 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6238 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6239 (const_int 6)
6240 (const_int 8)))
6241 (if_then_else
6242 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6243 (le (minus (match_dup 4) (pc)) (const_int 256)))
6244 (const_int 6)
6245 (if_then_else
6246 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6247 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6248 (const_int 8)
6249 (const_int 10)))))]
6250)
6251
aeac46d4 6252(define_insn "*bicsi3_cbranch_scratch"
6253 [(set (pc)
6254 (if_then_else
6255 (match_operator 4 "equality_operator"
6256 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6257 (match_operand:SI 1 "s_register_operand" "0"))
6258 (const_int 0)])
6259 (label_ref (match_operand 3 "" ""))
6260 (pc)))
6261 (clobber (match_scratch:SI 0 "=l"))]
6262 "TARGET_THUMB"
6263 "*
6264 {
6265 output_asm_insn (\"bic\\t%0, %2\", operands);
6266 switch (get_attr_length (insn))
6267 {
6268 case 4: return \"b%d4\\t%l3\";
6269 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6270 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6271 }
6272 }"
6273 [(set (attr "far_jump")
6274 (if_then_else
6275 (eq_attr "length" "8")
6276 (const_string "yes")
6277 (const_string "no")))
6278 (set (attr "length")
6279 (if_then_else
6280 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6281 (le (minus (match_dup 3) (pc)) (const_int 256)))
6282 (const_int 4)
6283 (if_then_else
6284 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6285 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6286 (const_int 6)
6287 (const_int 8))))]
6288)
6289
6290(define_insn "*bicsi3_cbranch"
6291 [(set (pc)
6292 (if_then_else
6293 (match_operator 5 "equality_operator"
01145ae6 6294 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6295 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 6296 (const_int 0)])
6297 (label_ref (match_operand 4 "" ""))
6298 (pc)))
01145ae6 6299 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 6300 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 6301 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
aeac46d4 6302 "TARGET_THUMB"
6303 "*
6304 {
6305 if (which_alternative == 0)
6306 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 6307 else if (which_alternative <= 2)
aeac46d4 6308 {
6309 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 6310 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6311 conditions again, since we're only testing for equality. */
aeac46d4 6312 output_asm_insn (\"mov\\t%0, %1\", operands);
6313 }
6314 else
6315 {
6316 output_asm_insn (\"bic\\t%1, %3\", operands);
6317 output_asm_insn (\"str\\t%1, %0\", operands);
6318 }
6319
6320 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6321 {
6322 case 4: return \"b%d5\\t%l4\";
6323 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6324 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6325 }
6326 }"
6327 [(set (attr "far_jump")
6328 (if_then_else
6329 (ior (and (eq (symbol_ref ("which_alternative"))
6330 (const_int 0))
6331 (eq_attr "length" "8"))
6332 (eq_attr "length" "10"))
6333 (const_string "yes")
6334 (const_string "no")))
6335 (set (attr "length")
6336 (if_then_else
6337 (eq (symbol_ref ("which_alternative"))
6338 (const_int 0))
6339 (if_then_else
6340 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6341 (le (minus (match_dup 4) (pc)) (const_int 256)))
6342 (const_int 4)
6343 (if_then_else
6344 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6345 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6346 (const_int 6)
6347 (const_int 8)))
6348 (if_then_else
6349 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6350 (le (minus (match_dup 4) (pc)) (const_int 256)))
6351 (const_int 6)
6352 (if_then_else
6353 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6354 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6355 (const_int 8)
6356 (const_int 10)))))]
6357)
6358
203c488f 6359(define_insn "*cbranchne_decr1"
6360 [(set (pc)
6361 (if_then_else (match_operator 3 "equality_operator"
6362 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6363 (const_int 0)])
6364 (label_ref (match_operand 4 "" ""))
6365 (pc)))
aeac46d4 6366 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6367 (plus:SI (match_dup 2) (const_int -1)))
6368 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6369 "TARGET_THUMB"
6370 "*
6371 {
6372 rtx cond[2];
6373 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6374 ? GEU : LTU),
58d6528b 6375 VOIDmode, operands[2], const1_rtx);
203c488f 6376 cond[1] = operands[4];
6377
6378 if (which_alternative == 0)
6379 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6380 else if (which_alternative == 1)
6381 {
6382 /* We must provide an alternative for a hi reg because reload
6383 cannot handle output reloads on a jump instruction, but we
6384 can't subtract into that. Fortunately a mov from lo to hi
6385 does not clobber the condition codes. */
6386 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6387 output_asm_insn (\"mov\\t%0, %1\", operands);
6388 }
6389 else
6390 {
6391 /* Similarly, but the target is memory. */
6392 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6393 output_asm_insn (\"str\\t%1, %0\", operands);
6394 }
6395
6396 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6397 {
6398 case 4:
8aea555f 6399 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6400 return \"\";
6401 case 6:
8aea555f 6402 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6403 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6404 default:
8aea555f 6405 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6406 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6407 }
6408 }
6409 "
6410 [(set (attr "far_jump")
6411 (if_then_else
6412 (ior (and (eq (symbol_ref ("which_alternative"))
6413 (const_int 0))
6414 (eq_attr "length" "8"))
6415 (eq_attr "length" "10"))
6416 (const_string "yes")
6417 (const_string "no")))
6418 (set_attr_alternative "length"
6419 [
6420 ;; Alternative 0
6421 (if_then_else
6422 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6423 (le (minus (match_dup 4) (pc)) (const_int 256)))
6424 (const_int 4)
6425 (if_then_else
6426 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6427 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6428 (const_int 6)
6429 (const_int 8)))
6430 ;; Alternative 1
6431 (if_then_else
6432 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6433 (le (minus (match_dup 4) (pc)) (const_int 256)))
6434 (const_int 6)
6435 (if_then_else
6436 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6437 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6438 (const_int 8)
6439 (const_int 10)))
6440 ;; Alternative 2
6441 (if_then_else
6442 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6443 (le (minus (match_dup 4) (pc)) (const_int 256)))
6444 (const_int 6)
6445 (if_then_else
6446 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6447 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6448 (const_int 8)
6449 (const_int 10)))
6450 ;; Alternative 3
6451 (if_then_else
6452 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6453 (le (minus (match_dup 4) (pc)) (const_int 256)))
6454 (const_int 6)
6455 (if_then_else
6456 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6457 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6458 (const_int 8)
6459 (const_int 10)))])]
6460)
cffb2a26 6461
58d6528b 6462(define_insn "*addsi3_cbranch"
6463 [(set (pc)
6464 (if_then_else
6465 (match_operator 4 "comparison_operator"
6466 [(plus:SI
6467 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6468 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6469 (const_int 0)])
6470 (label_ref (match_operand 5 "" ""))
6471 (pc)))
aeac46d4 6472 (set
6473 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6474 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 6475 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6476 "TARGET_THUMB
6477 && (GET_CODE (operands[4]) == EQ
6478 || GET_CODE (operands[4]) == NE
6479 || GET_CODE (operands[4]) == GE
6480 || GET_CODE (operands[4]) == LT)"
6481 "*
6482 {
6483 rtx cond[3];
6484
6485
6486 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6487 cond[1] = operands[2];
6488 cond[2] = operands[3];
6489
6490 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6491 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6492 else
6493 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6494
6495 if (which_alternative >= 3
6496 && which_alternative < 4)
6497 output_asm_insn (\"mov\\t%0, %1\", operands);
6498 else if (which_alternative >= 4)
6499 output_asm_insn (\"str\\t%1, %0\", operands);
6500
6501 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6502 {
6503 case 4:
6504 return \"b%d4\\t%l5\";
6505 case 6:
6506 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6507 default:
6508 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6509 }
6510 }
6511 "
6512 [(set (attr "far_jump")
6513 (if_then_else
6514 (ior (and (lt (symbol_ref ("which_alternative"))
6515 (const_int 3))
6516 (eq_attr "length" "8"))
6517 (eq_attr "length" "10"))
6518 (const_string "yes")
6519 (const_string "no")))
6520 (set (attr "length")
6521 (if_then_else
6522 (lt (symbol_ref ("which_alternative"))
6523 (const_int 3))
6524 (if_then_else
6525 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6526 (le (minus (match_dup 5) (pc)) (const_int 256)))
6527 (const_int 4)
6528 (if_then_else
6529 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6530 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6531 (const_int 6)
6532 (const_int 8)))
6533 (if_then_else
6534 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6535 (le (minus (match_dup 5) (pc)) (const_int 256)))
6536 (const_int 6)
6537 (if_then_else
6538 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6539 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6540 (const_int 8)
6541 (const_int 10)))))]
6542)
6543
6544(define_insn "*addsi3_cbranch_scratch"
6545 [(set (pc)
6546 (if_then_else
6547 (match_operator 3 "comparison_operator"
6548 [(plus:SI
6549 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 6550 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 6551 (const_int 0)])
6552 (label_ref (match_operand 4 "" ""))
6553 (pc)))
6554 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6555 "TARGET_THUMB
6556 && (GET_CODE (operands[3]) == EQ
6557 || GET_CODE (operands[3]) == NE
6558 || GET_CODE (operands[3]) == GE
6559 || GET_CODE (operands[3]) == LT)"
6560 "*
6561 {
6562 switch (which_alternative)
6563 {
6564 case 0:
6565 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6566 break;
6567 case 1:
6568 output_asm_insn (\"cmn\t%1, %2\", operands);
6569 break;
0f5e9701 6570 case 2:
3a445a04 6571 if (INTVAL (operands[2]) < 0)
6572 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6573 else
6574 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 6575 break;
0f5e9701 6576 case 3:
3a445a04 6577 if (INTVAL (operands[2]) < 0)
6578 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6579 else
6580 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 6581 break;
6582 }
6583
6584 switch (get_attr_length (insn))
6585 {
6586 case 4:
6587 return \"b%d3\\t%l4\";
6588 case 6:
6589 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6590 default:
6591 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6592 }
6593 }
6594 "
6595 [(set (attr "far_jump")
6596 (if_then_else
6597 (eq_attr "length" "8")
6598 (const_string "yes")
6599 (const_string "no")))
6600 (set (attr "length")
6601 (if_then_else
6602 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6603 (le (minus (match_dup 4) (pc)) (const_int 256)))
6604 (const_int 4)
6605 (if_then_else
6606 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6607 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6608 (const_int 6)
6609 (const_int 8))))]
6610)
6611
6612(define_insn "*subsi3_cbranch"
6613 [(set (pc)
6614 (if_then_else
6615 (match_operator 4 "comparison_operator"
6616 [(minus:SI
6617 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6618 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6619 (const_int 0)])
6620 (label_ref (match_operand 5 "" ""))
6621 (pc)))
aeac46d4 6622 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6623 (minus:SI (match_dup 2) (match_dup 3)))
6624 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6625 "TARGET_THUMB
6626 && (GET_CODE (operands[4]) == EQ
6627 || GET_CODE (operands[4]) == NE
6628 || GET_CODE (operands[4]) == GE
6629 || GET_CODE (operands[4]) == LT)"
6630 "*
6631 {
6632 if (which_alternative == 0)
6633 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6634 else if (which_alternative == 1)
6635 {
6636 /* We must provide an alternative for a hi reg because reload
6637 cannot handle output reloads on a jump instruction, but we
6638 can't subtract into that. Fortunately a mov from lo to hi
6639 does not clobber the condition codes. */
6640 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6641 output_asm_insn (\"mov\\t%0, %1\", operands);
6642 }
6643 else
6644 {
6645 /* Similarly, but the target is memory. */
6646 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6647 output_asm_insn (\"str\\t%1, %0\", operands);
6648 }
6649
6650 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6651 {
6652 case 4:
6653 return \"b%d4\\t%l5\";
6654 case 6:
6655 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6656 default:
6657 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6658 }
6659 }
6660 "
6661 [(set (attr "far_jump")
6662 (if_then_else
6663 (ior (and (eq (symbol_ref ("which_alternative"))
6664 (const_int 0))
6665 (eq_attr "length" "8"))
6666 (eq_attr "length" "10"))
6667 (const_string "yes")
6668 (const_string "no")))
6669 (set (attr "length")
6670 (if_then_else
6671 (eq (symbol_ref ("which_alternative"))
6672 (const_int 0))
6673 (if_then_else
6674 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6675 (le (minus (match_dup 5) (pc)) (const_int 256)))
6676 (const_int 4)
6677 (if_then_else
6678 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6679 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6680 (const_int 6)
6681 (const_int 8)))
6682 (if_then_else
6683 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6684 (le (minus (match_dup 5) (pc)) (const_int 256)))
6685 (const_int 6)
6686 (if_then_else
6687 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6688 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6689 (const_int 8)
6690 (const_int 10)))))]
6691)
6692
6693(define_insn "*subsi3_cbranch_scratch"
6694 [(set (pc)
6695 (if_then_else
6696 (match_operator 0 "arm_comparison_operator"
6697 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6698 (match_operand:SI 2 "nonmemory_operand" "l"))
6699 (const_int 0)])
6700 (label_ref (match_operand 3 "" ""))
6701 (pc)))]
6702 "TARGET_THUMB
6703 && (GET_CODE (operands[0]) == EQ
6704 || GET_CODE (operands[0]) == NE
6705 || GET_CODE (operands[0]) == GE
6706 || GET_CODE (operands[0]) == LT)"
6707 "*
6708 output_asm_insn (\"cmp\\t%1, %2\", operands);
6709 switch (get_attr_length (insn))
6710 {
6711 case 4: return \"b%d0\\t%l3\";
6712 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6713 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6714 }
6715 "
6716 [(set (attr "far_jump")
6717 (if_then_else
6718 (eq_attr "length" "8")
6719 (const_string "yes")
6720 (const_string "no")))
6721 (set (attr "length")
6722 (if_then_else
6723 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6724 (le (minus (match_dup 3) (pc)) (const_int 256)))
6725 (const_int 4)
6726 (if_then_else
6727 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6728 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6729 (const_int 6)
6730 (const_int 8))))]
6731)
6732
9c08d1fa 6733;; Comparison and test insns
6734
6735(define_expand "cmpsi"
aea4c774 6736 [(match_operand:SI 0 "s_register_operand" "")
6737 (match_operand:SI 1 "arm_add_operand" "")]
cffb2a26 6738 "TARGET_ARM"
6739 "{
6740 arm_compare_op0 = operands[0];
6741 arm_compare_op1 = operands[1];
6742 DONE;
6743 }"
6744)
b11cae9e 6745
9c08d1fa 6746(define_expand "cmpsf"
aea4c774 6747 [(match_operand:SF 0 "s_register_operand" "")
a2cd141b 6748 (match_operand:SF 1 "arm_float_compare_operand" "")]
6749 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6750 "
9c08d1fa 6751 arm_compare_op0 = operands[0];
6752 arm_compare_op1 = operands[1];
9c08d1fa 6753 DONE;
215b30b3 6754 "
6755)
b11cae9e 6756
9c08d1fa 6757(define_expand "cmpdf"
aea4c774 6758 [(match_operand:DF 0 "s_register_operand" "")
a2cd141b 6759 (match_operand:DF 1 "arm_float_compare_operand" "")]
6760 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6761 "
9c08d1fa 6762 arm_compare_op0 = operands[0];
6763 arm_compare_op1 = operands[1];
9c08d1fa 6764 DONE;
215b30b3 6765 "
6766)
b11cae9e 6767
cffb2a26 6768(define_insn "*arm_cmpsi_insn"
bd5b4116 6769 [(set (reg:CC CC_REGNUM)
aea4c774 6770 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 6771 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6772 "TARGET_ARM"
5565501b 6773 "@
aea4c774 6774 cmp%?\\t%0, %1
6775 cmn%?\\t%0, #%n1"
cffb2a26 6776 [(set_attr "conds" "set")]
6777)
b11cae9e 6778
aea4c774 6779(define_insn "*cmpsi_shiftsi"
bd5b4116 6780 [(set (reg:CC CC_REGNUM)
cffb2a26 6781 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6782 (match_operator:SI 3 "shift_operator"
aea4c774 6783 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 6784 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6785 "TARGET_ARM"
aea4c774 6786 "cmp%?\\t%0, %1%S3"
344495ea 6787 [(set_attr "conds" "set")
331beb1a 6788 (set_attr "shift" "1")
a2cd141b 6789 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6790 (const_string "alu_shift")
6791 (const_string "alu_shift_reg")))]
0d66636f 6792)
b11cae9e 6793
aea4c774 6794(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6795 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6796 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6797 [(match_operand:SI 1 "s_register_operand" "r")
6798 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6799 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6800 "TARGET_ARM"
aea4c774 6801 "cmp%?\\t%0, %1%S3"
344495ea 6802 [(set_attr "conds" "set")
331beb1a 6803 (set_attr "shift" "1")
a2cd141b 6804 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6805 (const_string "alu_shift")
6806 (const_string "alu_shift_reg")))]
0d66636f 6807)
b11cae9e 6808
aed179ae 6809(define_insn "*cmpsi_negshiftsi_si"
6810 [(set (reg:CC_Z CC_REGNUM)
6811 (compare:CC_Z
6812 (neg:SI (match_operator:SI 1 "shift_operator"
6813 [(match_operand:SI 2 "s_register_operand" "r")
6814 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6815 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6816 "TARGET_ARM"
aed179ae 6817 "cmn%?\\t%0, %2%S1"
344495ea 6818 [(set_attr "conds" "set")
aed179ae 6819 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6820 (const_string "alu_shift")
6821 (const_string "alu_shift_reg")))]
0d66636f 6822)
b11cae9e 6823
7d57ec45 6824;; Cirrus SF compare instruction
6825(define_insn "*cirrus_cmpsf"
6826 [(set (reg:CCFP CC_REGNUM)
6827 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6828 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 6829 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6830 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 6831 [(set_attr "type" "mav_farith")
7d57ec45 6832 (set_attr "cirrus" "compare")]
6833)
6834
6835;; Cirrus DF compare instruction
6836(define_insn "*cirrus_cmpdf"
6837 [(set (reg:CCFP CC_REGNUM)
6838 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6839 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 6840 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6841 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 6842 [(set_attr "type" "mav_farith")
7d57ec45 6843 (set_attr "cirrus" "compare")]
6844)
6845
6846;; Cirrus DI compare instruction
6847(define_expand "cmpdi"
6848 [(match_operand:DI 0 "cirrus_fp_register" "")
6849 (match_operand:DI 1 "cirrus_fp_register" "")]
a2cd141b 6850 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6851 "{
6852 arm_compare_op0 = operands[0];
6853 arm_compare_op1 = operands[1];
6854 DONE;
6855 }")
6856
6857(define_insn "*cirrus_cmpdi"
6858 [(set (reg:CC CC_REGNUM)
6859 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6860 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 6861 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6862 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 6863 [(set_attr "type" "mav_farith")
7d57ec45 6864 (set_attr "cirrus" "compare")]
6865)
6866
9c08d1fa 6867; This insn allows redundant compares to be removed by cse, nothing should
6868; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6869; is deleted later on. The match_dup will match the mode here, so that
6870; mode changes of the condition codes aren't lost by this even though we don't
6871; specify what they are.
6872
8a18b90c 6873(define_insn "*deleted_compare"
9c08d1fa 6874 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
cffb2a26 6875 "TARGET_ARM"
40dbec34 6876 "\\t%@ deleted compare"
cffb2a26 6877 [(set_attr "conds" "set")
6878 (set_attr "length" "0")]
6879)
9c08d1fa 6880
6881\f
6882;; Conditional branch insns
6883
6884(define_expand "beq"
6885 [(set (pc)
6886 (if_then_else (eq (match_dup 1) (const_int 0))
6887 (label_ref (match_operand 0 "" ""))
6888 (pc)))]
cffb2a26 6889 "TARGET_ARM"
6890 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6891)
5c951228 6892
9c08d1fa 6893(define_expand "bne"
6894 [(set (pc)
6895 (if_then_else (ne (match_dup 1) (const_int 0))
6896 (label_ref (match_operand 0 "" ""))
6897 (pc)))]
cffb2a26 6898 "TARGET_ARM"
6899 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6900)
5c951228 6901
9c08d1fa 6902(define_expand "bgt"
6903 [(set (pc)
6904 (if_then_else (gt (match_dup 1) (const_int 0))
6905 (label_ref (match_operand 0 "" ""))
6906 (pc)))]
cffb2a26 6907 "TARGET_ARM"
6908 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6909)
5c951228 6910
9c08d1fa 6911(define_expand "ble"
6912 [(set (pc)
6913 (if_then_else (le (match_dup 1) (const_int 0))
6914 (label_ref (match_operand 0 "" ""))
6915 (pc)))]
cffb2a26 6916 "TARGET_ARM"
6917 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6918)
5c951228 6919
9c08d1fa 6920(define_expand "bge"
6921 [(set (pc)
6922 (if_then_else (ge (match_dup 1) (const_int 0))
6923 (label_ref (match_operand 0 "" ""))
6924 (pc)))]
cffb2a26 6925 "TARGET_ARM"
6926 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6927)
5c951228 6928
9c08d1fa 6929(define_expand "blt"
6930 [(set (pc)
6931 (if_then_else (lt (match_dup 1) (const_int 0))
6932 (label_ref (match_operand 0 "" ""))
6933 (pc)))]
cffb2a26 6934 "TARGET_ARM"
6935 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6936)
5c951228 6937
9c08d1fa 6938(define_expand "bgtu"
6939 [(set (pc)
6940 (if_then_else (gtu (match_dup 1) (const_int 0))
6941 (label_ref (match_operand 0 "" ""))
6942 (pc)))]
cffb2a26 6943 "TARGET_ARM"
6944 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6945)
5c951228 6946
9c08d1fa 6947(define_expand "bleu"
b11cae9e 6948 [(set (pc)
9c08d1fa 6949 (if_then_else (leu (match_dup 1) (const_int 0))
6950 (label_ref (match_operand 0 "" ""))
6951 (pc)))]
cffb2a26 6952 "TARGET_ARM"
6953 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6954)
b11cae9e 6955
9c08d1fa 6956(define_expand "bgeu"
b11cae9e 6957 [(set (pc)
9c08d1fa 6958 (if_then_else (geu (match_dup 1) (const_int 0))
6959 (label_ref (match_operand 0 "" ""))
6960 (pc)))]
cffb2a26 6961 "TARGET_ARM"
6962 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6963)
b11cae9e 6964
9c08d1fa 6965(define_expand "bltu"
6966 [(set (pc)
6967 (if_then_else (ltu (match_dup 1) (const_int 0))
6968 (label_ref (match_operand 0 "" ""))
6969 (pc)))]
cffb2a26 6970 "TARGET_ARM"
6971 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6972)
b11cae9e 6973
8fa3ba89 6974(define_expand "bunordered"
6975 [(set (pc)
6976 (if_then_else (unordered (match_dup 1) (const_int 0))
6977 (label_ref (match_operand 0 "" ""))
6978 (pc)))]
a2cd141b 6979 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6980 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6981 arm_compare_op1);"
6982)
6983
6984(define_expand "bordered"
6985 [(set (pc)
6986 (if_then_else (ordered (match_dup 1) (const_int 0))
6987 (label_ref (match_operand 0 "" ""))
6988 (pc)))]
a2cd141b 6989 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6990 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6991 arm_compare_op1);"
6992)
6993
6994(define_expand "bungt"
6995 [(set (pc)
6996 (if_then_else (ungt (match_dup 1) (const_int 0))
6997 (label_ref (match_operand 0 "" ""))
6998 (pc)))]
a2cd141b 6999 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7000 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7001)
7002
7003(define_expand "bunlt"
7004 [(set (pc)
7005 (if_then_else (unlt (match_dup 1) (const_int 0))
7006 (label_ref (match_operand 0 "" ""))
7007 (pc)))]
a2cd141b 7008 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7009 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7010)
7011
7012(define_expand "bunge"
7013 [(set (pc)
7014 (if_then_else (unge (match_dup 1) (const_int 0))
7015 (label_ref (match_operand 0 "" ""))
7016 (pc)))]
a2cd141b 7017 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7018 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7019)
7020
7021(define_expand "bunle"
7022 [(set (pc)
7023 (if_then_else (unle (match_dup 1) (const_int 0))
7024 (label_ref (match_operand 0 "" ""))
7025 (pc)))]
a2cd141b 7026 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7027 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7028)
7029
7030;; The following two patterns need two branch instructions, since there is
7031;; no single instruction that will handle all cases.
7032(define_expand "buneq"
7033 [(set (pc)
7034 (if_then_else (uneq (match_dup 1) (const_int 0))
7035 (label_ref (match_operand 0 "" ""))
7036 (pc)))]
a2cd141b 7037 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7038 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7039)
7040
7041(define_expand "bltgt"
7042 [(set (pc)
7043 (if_then_else (ltgt (match_dup 1) (const_int 0))
7044 (label_ref (match_operand 0 "" ""))
7045 (pc)))]
a2cd141b 7046 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7047 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7048)
7049
7050;;
7051;; Patterns to match conditional branch insns.
7052;;
7053
7054; Special pattern to match UNEQ.
7055(define_insn "*arm_buneq"
7056 [(set (pc)
7057 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7058 (label_ref (match_operand 0 "" ""))
7059 (pc)))]
a2cd141b 7060 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7061 "*
7062 if (arm_ccfsm_state != 0)
7063 abort ();
7064
278b301d 7065 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7066 "
7067 [(set_attr "conds" "jump_clob")
7068 (set_attr "length" "8")]
7069)
7070
7071; Special pattern to match LTGT.
7072(define_insn "*arm_bltgt"
7073 [(set (pc)
7074 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7075 (label_ref (match_operand 0 "" ""))
7076 (pc)))]
a2cd141b 7077 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7078 "*
7079 if (arm_ccfsm_state != 0)
7080 abort ();
7081
278b301d 7082 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7083 "
7084 [(set_attr "conds" "jump_clob")
7085 (set_attr "length" "8")]
7086)
9c08d1fa 7087
cffb2a26 7088(define_insn "*arm_cond_branch"
9c08d1fa 7089 [(set (pc)
8fa3ba89 7090 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7091 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7092 (label_ref (match_operand 0 "" ""))
7093 (pc)))]
cffb2a26 7094 "TARGET_ARM"
d75350ce 7095 "*
9c08d1fa 7096 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7097 {
7098 arm_ccfsm_state += 2;
7099 return \"\";
7100 }
e2348bcb 7101 return \"b%d1\\t%l0\";
cffb2a26 7102 "
a2cd141b 7103 [(set_attr "conds" "use")
7104 (set_attr "type" "branch")]
cffb2a26 7105)
d75350ce 7106
8fa3ba89 7107; Special pattern to match reversed UNEQ.
7108(define_insn "*arm_buneq_reversed"
7109 [(set (pc)
7110 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7111 (pc)
7112 (label_ref (match_operand 0 "" ""))))]
a2cd141b 7113 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7114 "*
7115 if (arm_ccfsm_state != 0)
7116 abort ();
7117
278b301d 7118 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7119 "
7120 [(set_attr "conds" "jump_clob")
7121 (set_attr "length" "8")]
7122)
7123
7124; Special pattern to match reversed LTGT.
7125(define_insn "*arm_bltgt_reversed"
7126 [(set (pc)
7127 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7128 (pc)
7129 (label_ref (match_operand 0 "" ""))))]
a2cd141b 7130 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7131 "*
7132 if (arm_ccfsm_state != 0)
7133 abort ();
7134
278b301d 7135 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7136 "
7137 [(set_attr "conds" "jump_clob")
7138 (set_attr "length" "8")]
7139)
7140
cffb2a26 7141(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7142 [(set (pc)
8fa3ba89 7143 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7144 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7145 (pc)
7146 (label_ref (match_operand 0 "" ""))))]
cffb2a26 7147 "TARGET_ARM"
d75350ce 7148 "*
9c08d1fa 7149 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7150 {
7151 arm_ccfsm_state += 2;
7152 return \"\";
7153 }
e2348bcb 7154 return \"b%D1\\t%l0\";
cffb2a26 7155 "
a2cd141b 7156 [(set_attr "conds" "use")
7157 (set_attr "type" "branch")]
cffb2a26 7158)
7159
b11cae9e 7160\f
9c08d1fa 7161
7162; scc insns
7163
7164(define_expand "seq"
7db9af5d 7165 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7166 (eq:SI (match_dup 1) (const_int 0)))]
cffb2a26 7167 "TARGET_ARM"
7168 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7169)
9c08d1fa 7170
7171(define_expand "sne"
7db9af5d 7172 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7173 (ne:SI (match_dup 1) (const_int 0)))]
cffb2a26 7174 "TARGET_ARM"
7175 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7176)
9c08d1fa 7177
7178(define_expand "sgt"
7db9af5d 7179 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7180 (gt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7181 "TARGET_ARM"
7182 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7183)
9c08d1fa 7184
7185(define_expand "sle"
7db9af5d 7186 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7187 (le:SI (match_dup 1) (const_int 0)))]
cffb2a26 7188 "TARGET_ARM"
7189 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7190)
9c08d1fa 7191
7192(define_expand "sge"
7db9af5d 7193 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7194 (ge:SI (match_dup 1) (const_int 0)))]
cffb2a26 7195 "TARGET_ARM"
7196 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7197)
9c08d1fa 7198
7199(define_expand "slt"
7db9af5d 7200 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7201 (lt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7202 "TARGET_ARM"
7203 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7204)
9c08d1fa 7205
7206(define_expand "sgtu"
7db9af5d 7207 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7208 (gtu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7209 "TARGET_ARM"
7210 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7211)
9c08d1fa 7212
7213(define_expand "sleu"
7db9af5d 7214 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7215 (leu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7216 "TARGET_ARM"
7217 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7218)
9c08d1fa 7219
7220(define_expand "sgeu"
7db9af5d 7221 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7222 (geu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7223 "TARGET_ARM"
7224 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7225)
9c08d1fa 7226
7227(define_expand "sltu"
7db9af5d 7228 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7229 (ltu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7230 "TARGET_ARM"
7231 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7232)
9c08d1fa 7233
8fa3ba89 7234(define_expand "sunordered"
7db9af5d 7235 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7236 (unordered:SI (match_dup 1) (const_int 0)))]
a2cd141b 7237 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7238 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7239 arm_compare_op1);"
7240)
7241
7242(define_expand "sordered"
7db9af5d 7243 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7244 (ordered:SI (match_dup 1) (const_int 0)))]
a2cd141b 7245 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7246 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7247 arm_compare_op1);"
7248)
7249
7250(define_expand "sungt"
7db9af5d 7251 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7252 (ungt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7253 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7254 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7255 arm_compare_op1);"
7256)
7257
7258(define_expand "sunge"
7db9af5d 7259 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7260 (unge:SI (match_dup 1) (const_int 0)))]
a2cd141b 7261 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7262 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7263 arm_compare_op1);"
7264)
7265
7266(define_expand "sunlt"
7db9af5d 7267 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7268 (unlt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7269 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7270 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7271 arm_compare_op1);"
7272)
7273
7274(define_expand "sunle"
7db9af5d 7275 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7276 (unle:SI (match_dup 1) (const_int 0)))]
a2cd141b 7277 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7278 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7279 arm_compare_op1);"
7280)
7281
7282;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7283;;; simple ARM instructions.
7284;
7285; (define_expand "suneq"
7db9af5d 7286; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7287; (uneq:SI (match_dup 1) (const_int 0)))]
a2cd141b 7288; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7289; "abort ();"
7290; )
7291;
7292; (define_expand "sltgt"
7db9af5d 7293; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7294; (ltgt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7295; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7296; "abort ();"
7297; )
7298
f7fbdd4a 7299(define_insn "*mov_scc"
9c08d1fa 7300 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7301 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7302 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7303 "TARGET_ARM"
4d61e570 7304 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7305 [(set_attr "conds" "use")
7306 (set_attr "length" "8")]
7307)
9c08d1fa 7308
f7fbdd4a 7309(define_insn "*mov_negscc"
9c08d1fa 7310 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7311 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7312 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7313 "TARGET_ARM"
4d61e570 7314 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7315 [(set_attr "conds" "use")
7316 (set_attr "length" "8")]
7317)
9c08d1fa 7318
f7fbdd4a 7319(define_insn "*mov_notscc"
9c08d1fa 7320 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7321 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7322 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7323 "TARGET_ARM"
4d61e570 7324 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7325 [(set_attr "conds" "use")
7326 (set_attr "length" "8")]
7327)
9c08d1fa 7328
7329\f
39b5e676 7330;; Conditional move insns
7331
7332(define_expand "movsicc"
8a18b90c 7333 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7334 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7335 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7336 (match_operand:SI 3 "arm_not_operand" "")))]
cffb2a26 7337 "TARGET_ARM"
39b5e676 7338 "
215b30b3 7339 {
7340 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7341 rtx ccreg;
7342
7343 if (code == UNEQ || code == LTGT)
7344 FAIL;
39b5e676 7345
278b301d 7346 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7347 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7348 }"
7349)
39b5e676 7350
7351(define_expand "movsfcc"
8a18b90c 7352 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7353 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7354 (match_operand:SF 2 "s_register_operand" "")
7355 (match_operand:SF 3 "nonmemory_operand" "")))]
cffb2a26 7356 "TARGET_ARM"
39b5e676 7357 "
215b30b3 7358 {
7359 enum rtx_code code = GET_CODE (operands[1]);
7360 rtx ccreg;
f082f1c4 7361
278b301d 7362 if (code == UNEQ || code == LTGT)
7363 FAIL;
7364
215b30b3 7365 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7366 Otherwise, ensure it is a valid FP add operand */
7367 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7368 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7369 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7370
215b30b3 7371 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7372 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7373 }"
7374)
39b5e676 7375
7376(define_expand "movdfcc"
8a18b90c 7377 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7378 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7379 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7380 (match_operand:DF 3 "arm_float_add_operand" "")))]
7381 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 7382 "
215b30b3 7383 {
7384 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7385 rtx ccreg;
39b5e676 7386
278b301d 7387 if (code == UNEQ || code == LTGT)
7388 FAIL;
7389
7390 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7391 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7392 }"
7393)
39b5e676 7394
7395(define_insn "*movsicc_insn"
f082f1c4 7396 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7397 (if_then_else:SI
8fa3ba89 7398 (match_operator 3 "arm_comparison_operator"
8a18b90c 7399 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7400 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7401 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7402 "TARGET_ARM"
39b5e676 7403 "@
8a18b90c 7404 mov%D3\\t%0, %2
7405 mvn%D3\\t%0, #%B2
f082f1c4 7406 mov%d3\\t%0, %1
7407 mvn%d3\\t%0, #%B1
8a18b90c 7408 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7409 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7410 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7411 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7412 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 7413 (set_attr "conds" "use")]
7414)
39b5e676 7415
39b5e676 7416(define_insn "*movsfcc_soft_insn"
f082f1c4 7417 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7418 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7419 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7420 (match_operand:SF 1 "s_register_operand" "0,r")
7421 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7422 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7423 "@
7424 mov%D3\\t%0, %2
7425 mov%d3\\t%0, %1"
8fa3ba89 7426 [(set_attr "conds" "use")]
7427)
39b5e676 7428
39b5e676 7429\f
9c08d1fa 7430;; Jump and linkage insns
7431
cffb2a26 7432(define_expand "jump"
9c08d1fa 7433 [(set (pc)
7434 (label_ref (match_operand 0 "" "")))]
cffb2a26 7435 "TARGET_EITHER"
9c08d1fa 7436 ""
cffb2a26 7437)
7438
7439(define_insn "*arm_jump"
7440 [(set (pc)
7441 (label_ref (match_operand 0 "" "")))]
7442 "TARGET_ARM"
9c08d1fa 7443 "*
0d66636f 7444 {
7445 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7446 {
7447 arm_ccfsm_state += 2;
7448 return \"\";
7449 }
7450 return \"b%?\\t%l0\";
7451 }
7452 "
7453 [(set_attr "predicable" "yes")]
7454)
9c08d1fa 7455
cffb2a26 7456(define_insn "*thumb_jump"
7457 [(set (pc)
7458 (label_ref (match_operand 0 "" "")))]
7459 "TARGET_THUMB"
7460 "*
7461 if (get_attr_length (insn) == 2)
7462 return \"b\\t%l0\";
7463 return \"bl\\t%l0\\t%@ far jump\";
7464 "
7465 [(set (attr "far_jump")
7466 (if_then_else
7467 (eq_attr "length" "4")
7468 (const_string "yes")
7469 (const_string "no")))
7470 (set (attr "length")
7471 (if_then_else
911ed8af 7472 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7473 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7474 (const_int 2)
7475 (const_int 4)))]
7476)
7477
d3373b54 7478(define_expand "call"
7479 [(parallel [(call (match_operand 0 "memory_operand" "")
7480 (match_operand 1 "general_operand" ""))
cffb2a26 7481 (use (match_operand 2 "" ""))
bd5b4116 7482 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7483 "TARGET_EITHER"
6c4c2133 7484 "
7485 {
78fe751b 7486 rtx callee;
bbe777ea 7487
bbe777ea 7488 /* In an untyped call, we can get NULL for operand 2. */
7489 if (operands[2] == NULL_RTX)
7490 operands[2] = const0_rtx;
7491
78fe751b 7492 /* This is to decide if we should generate indirect calls by loading the
7493 32 bit address of the callee into a register before performing the
7494 branch and link. operand[2] encodes the long_call/short_call
7495 attribute of the function being called. This attribute is set whenever
7496 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7497 is used, and the short_call attribute can also be set if function is
7498 declared as static or if it has already been defined in the current
7499 compilation unit. See arm.c and arm.h for info about this. The third
7500 parameter to arm_is_longcall_p is used to tell it which pattern
7501 invoked it. */
7502 callee = XEXP (operands[0], 0);
7503
bbe777ea 7504 if (GET_CODE (callee) != REG
7505 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7506 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6c4c2133 7507 }"
7508)
d3373b54 7509
f1039640 7510(define_insn "*call_reg_armv5"
d3373b54 7511 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7512 (match_operand 1 "" ""))
7513 (use (match_operand 2 "" ""))
bd5b4116 7514 (clobber (reg:SI LR_REGNUM))]
f1039640 7515 "TARGET_ARM && arm_arch5"
7516 "blx%?\\t%0"
7517 [(set_attr "type" "call")]
7518)
7519
7520(define_insn "*call_reg_arm"
7521 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7522 (match_operand 1 "" ""))
7523 (use (match_operand 2 "" ""))
7524 (clobber (reg:SI LR_REGNUM))]
7525 "TARGET_ARM && !arm_arch5"
9c08d1fa 7526 "*
5565501b 7527 return output_call (operands);
cffb2a26 7528 "
7529 ;; length is worst case, normally it is only two
7530 [(set_attr "length" "12")
7531 (set_attr "type" "call")]
7532)
9c08d1fa 7533
f7fbdd4a 7534(define_insn "*call_mem"
6c4c2133 7535 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
cffb2a26 7536 (match_operand 1 "" ""))
7537 (use (match_operand 2 "" ""))
bd5b4116 7538 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7539 "TARGET_ARM"
9c08d1fa 7540 "*
5565501b 7541 return output_call_mem (operands);
cffb2a26 7542 "
7543 [(set_attr "length" "12")
7544 (set_attr "type" "call")]
7545)
7546
f1039640 7547(define_insn "*call_reg_thumb_v5"
cffb2a26 7548 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7549 (match_operand 1 "" ""))
7550 (use (match_operand 2 "" ""))
bd5b4116 7551 (clobber (reg:SI LR_REGNUM))]
f1039640 7552 "TARGET_THUMB && arm_arch5"
7553 "blx\\t%0"
7554 [(set_attr "length" "2")
7555 (set_attr "type" "call")]
cffb2a26 7556)
7557
f1039640 7558(define_insn "*call_reg_thumb"
7559 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7560 (match_operand 1 "" ""))
7561 (use (match_operand 2 "" ""))
bd5b4116 7562 (clobber (reg:SI LR_REGNUM))]
f1039640 7563 "TARGET_THUMB && !arm_arch5"
cffb2a26 7564 "*
7565 {
150502c9 7566 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7567 return thumb_call_via_reg (operands[0]);
150502c9 7568 else if (operands[1] == const0_rtx)
f1039640 7569 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7570 else if (frame_pointer_needed)
7571 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7572 else
150502c9 7573 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7574 }"
7575 [(set_attr "type" "call")]
7576)
9c08d1fa 7577
d3373b54 7578(define_expand "call_value"
e0698af7 7579 [(parallel [(set (match_operand 0 "" "")
7580 (call (match_operand 1 "memory_operand" "")
7581 (match_operand 2 "general_operand" "")))
cffb2a26 7582 (use (match_operand 3 "" ""))
bd5b4116 7583 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7584 "TARGET_EITHER"
6c4c2133 7585 "
7586 {
bbe777ea 7587 rtx callee = XEXP (operands[1], 0);
7588
7589 /* In an untyped call, we can get NULL for operand 2. */
7590 if (operands[3] == 0)
7591 operands[3] = const0_rtx;
7592
7593 /* See the comment in define_expand \"call\". */
7594 if (GET_CODE (callee) != REG
7595 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
78fe751b 7596 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6c4c2133 7597 }"
7598)
d3373b54 7599
f1039640 7600(define_insn "*call_value_reg_armv5"
27ed6835 7601 [(set (match_operand 0 "" "")
755eb2b4 7602 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7603 (match_operand 2 "" "")))
bbe777ea 7604 (use (match_operand 3 "" ""))
bd5b4116 7605 (clobber (reg:SI LR_REGNUM))]
f1039640 7606 "TARGET_ARM && arm_arch5"
7607 "blx%?\\t%1"
7608 [(set_attr "type" "call")]
7609)
7610
7611(define_insn "*call_value_reg_arm"
7612 [(set (match_operand 0 "" "")
7613 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7614 (match_operand 2 "" "")))
7615 (use (match_operand 3 "" ""))
7616 (clobber (reg:SI LR_REGNUM))]
7617 "TARGET_ARM && !arm_arch5"
9c08d1fa 7618 "*
215b30b3 7619 return output_call (&operands[1]);
cffb2a26 7620 "
7621 [(set_attr "length" "12")
7622 (set_attr "type" "call")]
7623)
9c08d1fa 7624
f7fbdd4a 7625(define_insn "*call_value_mem"
27ed6835 7626 [(set (match_operand 0 "" "")
755eb2b4 7627 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
cffb2a26 7628 (match_operand 2 "" "")))
bbe777ea 7629 (use (match_operand 3 "" ""))
bd5b4116 7630 (clobber (reg:SI LR_REGNUM))]
215b30b3 7631 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7632 "*
215b30b3 7633 return output_call_mem (&operands[1]);
cffb2a26 7634 "
7635 [(set_attr "length" "12")
7636 (set_attr "type" "call")]
7637)
9c08d1fa 7638
f1039640 7639(define_insn "*call_value_reg_thumb_v5"
7640 [(set (match_operand 0 "" "")
7641 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7642 (match_operand 2 "" "")))
7643 (use (match_operand 3 "" ""))
7644 (clobber (reg:SI LR_REGNUM))]
7645 "TARGET_THUMB && arm_arch5"
7646 "blx\\t%1"
7647 [(set_attr "length" "2")
7648 (set_attr "type" "call")]
7649)
7650
7651(define_insn "*call_value_reg_thumb"
7652 [(set (match_operand 0 "" "")
7653 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7654 (match_operand 2 "" "")))
7655 (use (match_operand 3 "" ""))
7656 (clobber (reg:SI LR_REGNUM))]
7657 "TARGET_THUMB && !arm_arch5"
7658 "*
7659 {
150502c9 7660 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7661 return thumb_call_via_reg (operands[1]);
150502c9 7662 else if (operands[2] == const0_rtx)
f1039640 7663 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7664 else if (frame_pointer_needed)
7665 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7666 else
150502c9 7667 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7668 }"
7669 [(set_attr "type" "call")]
7670)
7671
9c08d1fa 7672;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7673;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7674
f7fbdd4a 7675(define_insn "*call_symbol"
27ed6835 7676 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7677 (match_operand 1 "" ""))
bbe777ea 7678 (use (match_operand 2 "" ""))
bd5b4116 7679 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7680 "TARGET_ARM
7681 && (GET_CODE (operands[0]) == SYMBOL_REF)
215b30b3 7682 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6ebaa29d 7683 "*
7684 {
55c1e470 7685 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7686 }"
cffb2a26 7687 [(set_attr "type" "call")]
7688)
9c08d1fa 7689
f7fbdd4a 7690(define_insn "*call_value_symbol"
ccd90aaa 7691 [(set (match_operand 0 "" "")
27ed6835 7692 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7693 (match_operand:SI 2 "" "")))
bbe777ea 7694 (use (match_operand 3 "" ""))
bd5b4116 7695 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7696 "TARGET_ARM
7697 && (GET_CODE (operands[1]) == SYMBOL_REF)
215b30b3 7698 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6ebaa29d 7699 "*
7700 {
55c1e470 7701 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7702 }"
cffb2a26 7703 [(set_attr "type" "call")]
7704)
7705
7706(define_insn "*call_insn"
27ed6835 7707 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7708 (match_operand:SI 1 "" ""))
7709 (use (match_operand 2 "" ""))
bd5b4116 7710 (clobber (reg:SI LR_REGNUM))]
1c494086 7711 "TARGET_THUMB
1675c6e9 7712 && GET_CODE (operands[0]) == SYMBOL_REF
7713 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
cffb2a26 7714 "bl\\t%a0"
7715 [(set_attr "length" "4")
7716 (set_attr "type" "call")]
7717)
7718
7719(define_insn "*call_value_insn"
ccd90aaa 7720 [(set (match_operand 0 "" "")
27ed6835 7721 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 7722 (match_operand 2 "" "")))
7723 (use (match_operand 3 "" ""))
bd5b4116 7724 (clobber (reg:SI LR_REGNUM))]
1c494086 7725 "TARGET_THUMB
1675c6e9 7726 && GET_CODE (operands[1]) == SYMBOL_REF
7727 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
cffb2a26 7728 "bl\\t%a1"
7729 [(set_attr "length" "4")
7730 (set_attr "type" "call")]
7731)
9c08d1fa 7732
1c494086 7733;; We may also be able to do sibcalls for Thumb, but it's much harder...
7734(define_expand "sibcall"
7735 [(parallel [(call (match_operand 0 "memory_operand" "")
7736 (match_operand 1 "general_operand" ""))
2ba80634 7737 (return)
7738 (use (match_operand 2 "" ""))])]
1c494086 7739 "TARGET_ARM"
7740 "
7741 {
7742 if (operands[2] == NULL_RTX)
7743 operands[2] = const0_rtx;
1c494086 7744 }"
7745)
7746
7747(define_expand "sibcall_value"
ccd90aaa 7748 [(parallel [(set (match_operand 0 "" "")
1c494086 7749 (call (match_operand 1 "memory_operand" "")
7750 (match_operand 2 "general_operand" "")))
2ba80634 7751 (return)
7752 (use (match_operand 3 "" ""))])]
1c494086 7753 "TARGET_ARM"
7754 "
7755 {
7756 if (operands[3] == NULL_RTX)
7757 operands[3] = const0_rtx;
1c494086 7758 }"
7759)
7760
7761(define_insn "*sibcall_insn"
7762 [(call (mem:SI (match_operand:SI 0 "" "X"))
7763 (match_operand 1 "" ""))
2ba80634 7764 (return)
7765 (use (match_operand 2 "" ""))]
1c494086 7766 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7767 "*
7768 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7769 "
7770 [(set_attr "type" "call")]
7771)
7772
7773(define_insn "*sibcall_value_insn"
ccd90aaa 7774 [(set (match_operand 0 "" "")
755eb2b4 7775 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 7776 (match_operand 2 "" "")))
2ba80634 7777 (return)
7778 (use (match_operand 3 "" ""))]
1c494086 7779 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7780 "*
7781 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7782 "
7783 [(set_attr "type" "call")]
7784)
7785
9c08d1fa 7786;; Often the return insn will be the same as loading from memory, so set attr
7787(define_insn "return"
7788 [(return)]
cffb2a26 7789 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7790 "*
9c08d1fa 7791 {
cffb2a26 7792 if (arm_ccfsm_state == 2)
7793 {
7794 arm_ccfsm_state += 2;
7795 return \"\";
7796 }
5db468b7 7797 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 7798 }"
a2cd141b 7799 [(set_attr "type" "load1")
755eb2b4 7800 (set_attr "length" "12")
0d66636f 7801 (set_attr "predicable" "yes")]
cffb2a26 7802)
9c08d1fa 7803
f7fbdd4a 7804(define_insn "*cond_return"
9c08d1fa 7805 [(set (pc)
8fa3ba89 7806 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7807 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7808 (return)
7809 (pc)))]
cffb2a26 7810 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7811 "*
8fa3ba89 7812 {
7813 if (arm_ccfsm_state == 2)
7814 {
7815 arm_ccfsm_state += 2;
7816 return \"\";
7817 }
7818 return output_return_instruction (operands[0], TRUE, FALSE);
7819 }"
7820 [(set_attr "conds" "use")
755eb2b4 7821 (set_attr "length" "12")
a2cd141b 7822 (set_attr "type" "load1")]
8fa3ba89 7823)
9c08d1fa 7824
f7fbdd4a 7825(define_insn "*cond_return_inverted"
9c08d1fa 7826 [(set (pc)
8fa3ba89 7827 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7828 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7829 (pc)
7830 (return)))]
cffb2a26 7831 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7832 "*
8fa3ba89 7833 {
7834 if (arm_ccfsm_state == 2)
7835 {
7836 arm_ccfsm_state += 2;
7837 return \"\";
7838 }
7839 return output_return_instruction (operands[0], TRUE, TRUE);
7840 }"
7841 [(set_attr "conds" "use")
37a1317b 7842 (set_attr "length" "12")
a2cd141b 7843 (set_attr "type" "load1")]
8fa3ba89 7844)
9c08d1fa 7845
68121397 7846;; Generate a sequence of instructions to determine if the processor is
7847;; in 26-bit or 32-bit mode, and return the appropriate return address
7848;; mask.
7849
7850(define_expand "return_addr_mask"
7851 [(set (match_dup 1)
7852 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7853 (const_int 0)))
7854 (set (match_operand:SI 0 "s_register_operand" "")
7855 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7856 (const_int -1)
7857 (const_int 67108860)))] ; 0x03fffffc
7858 "TARGET_ARM"
7859 "
62eddbd4 7860 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7861 ")
7862
7863(define_insn "*check_arch2"
7864 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7865 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7866 (const_int 0)))]
7867 "TARGET_ARM"
7868 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7869 [(set_attr "length" "8")
7870 (set_attr "conds" "set")]
7871)
7872
9c08d1fa 7873;; Call subroutine returning any type.
7874
7875(define_expand "untyped_call"
7876 [(parallel [(call (match_operand 0 "" "")
7877 (const_int 0))
7878 (match_operand 1 "" "")
7879 (match_operand 2 "" "")])]
ccd90aaa 7880 "TARGET_EITHER"
9c08d1fa 7881 "
215b30b3 7882 {
7883 int i;
ccd90aaa 7884 rtx par = gen_rtx_PARALLEL (VOIDmode,
7885 rtvec_alloc (XVECLEN (operands[2], 0)));
7886 rtx addr = gen_reg_rtx (Pmode);
7887 rtx mem;
7888 int size = 0;
9c08d1fa 7889
ccd90aaa 7890 emit_move_insn (addr, XEXP (operands[1], 0));
7891 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7892
215b30b3 7893 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7894 {
ccd90aaa 7895 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7896
ccd90aaa 7897 /* Default code only uses r0 as a return value, but we could
7898 be using anything up to 4 registers. */
7899 if (REGNO (src) == R0_REGNUM)
7900 src = gen_rtx_REG (TImode, R0_REGNUM);
7901
7902 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7903 GEN_INT (size));
7904 size += GET_MODE_SIZE (GET_MODE (src));
7905 }
7906
7907 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7908 const0_rtx));
7909
7910 size = 0;
7911
7912 for (i = 0; i < XVECLEN (par, 0); i++)
7913 {
7914 HOST_WIDE_INT offset = 0;
7915 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7916
7917 if (size != 0)
7918 emit_move_insn (addr, plus_constant (addr, size));
7919
7920 mem = change_address (mem, GET_MODE (reg), NULL);
7921 if (REGNO (reg) == R0_REGNUM)
7922 {
7923 /* On thumb we have to use a write-back instruction. */
7924 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7925 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7926 size = TARGET_ARM ? 16 : 0;
7927 }
7928 else
7929 {
7930 emit_move_insn (mem, reg);
7931 size = GET_MODE_SIZE (GET_MODE (reg));
7932 }
215b30b3 7933 }
9c08d1fa 7934
215b30b3 7935 /* The optimizer does not know that the call sets the function value
7936 registers we stored in the result block. We avoid problems by
7937 claiming that all hard registers are used and clobbered at this
7938 point. */
7939 emit_insn (gen_blockage ());
7940
7941 DONE;
7942 }"
7943)
9c08d1fa 7944
ccd90aaa 7945(define_expand "untyped_return"
7946 [(match_operand:BLK 0 "memory_operand" "")
7947 (match_operand 1 "" "")]
7948 "TARGET_EITHER"
7949 "
7950 {
7951 int i;
7952 rtx addr = gen_reg_rtx (Pmode);
7953 rtx mem;
7954 int size = 0;
7955
7956 emit_move_insn (addr, XEXP (operands[0], 0));
7957 mem = change_address (operands[0], BLKmode, addr);
7958
7959 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7960 {
7961 HOST_WIDE_INT offset = 0;
7962 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7963
7964 if (size != 0)
7965 emit_move_insn (addr, plus_constant (addr, size));
7966
7967 mem = change_address (mem, GET_MODE (reg), NULL);
7968 if (REGNO (reg) == R0_REGNUM)
7969 {
7970 /* On thumb we have to use a write-back instruction. */
7971 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7972 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7973 size = TARGET_ARM ? 16 : 0;
7974 }
7975 else
7976 {
7977 emit_move_insn (reg, mem);
7978 size = GET_MODE_SIZE (GET_MODE (reg));
7979 }
7980 }
7981
7982 /* Emit USE insns before the return. */
7983 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7984 emit_insn (gen_rtx_USE (VOIDmode,
7985 SET_DEST (XVECEXP (operands[1], 0, i))));
7986
7987 /* Construct the return. */
7988 expand_naked_return ();
7989
7990 DONE;
7991 }"
7992)
7993
9c08d1fa 7994;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7995;; all of memory. This blocks insns from being moved across this point.
7996
7997(define_insn "blockage"
e1159bbe 7998 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 7999 "TARGET_EITHER"
9c08d1fa 8000 ""
cffb2a26 8001 [(set_attr "length" "0")
8002 (set_attr "type" "block")]
8003)
9c08d1fa 8004
f7fbdd4a 8005(define_expand "casesi"
8006 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8007 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8008 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8009 (match_operand:SI 3 "" "") ; table label
8010 (match_operand:SI 4 "" "")] ; Out of range label
cffb2a26 8011 "TARGET_ARM"
f7fbdd4a 8012 "
215b30b3 8013 {
8014 rtx reg;
8015 if (operands[1] != const0_rtx)
8016 {
8017 reg = gen_reg_rtx (SImode);
f7fbdd4a 8018
215b30b3 8019 emit_insn (gen_addsi3 (reg, operands[0],
8020 GEN_INT (-INTVAL (operands[1]))));
8021 operands[0] = reg;
8022 }
9c08d1fa 8023
215b30b3 8024 if (!const_ok_for_arm (INTVAL (operands[2])))
8025 operands[2] = force_reg (SImode, operands[2]);
8026
8027 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8028 operands[4]));
8029 DONE;
8030 }"
8031)
f7fbdd4a 8032
f082f1c4 8033;; The USE in this pattern is needed to tell flow analysis that this is
8034;; a CASESI insn. It has no other purpose.
f7fbdd4a 8035(define_insn "casesi_internal"
f082f1c4 8036 [(parallel [(set (pc)
8037 (if_then_else
8038 (leu (match_operand:SI 0 "s_register_operand" "r")
8039 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8040 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8041 (label_ref (match_operand 2 "" ""))))
8042 (label_ref (match_operand 3 "" ""))))
bd5b4116 8043 (clobber (reg:CC CC_REGNUM))
f082f1c4 8044 (use (label_ref (match_dup 2)))])]
cffb2a26 8045 "TARGET_ARM"
f7fbdd4a 8046 "*
0d66636f 8047 if (flag_pic)
8048 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8049 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8050 "
8051 [(set_attr "conds" "clob")
8052 (set_attr "length" "12")]
8053)
9c08d1fa 8054
cffb2a26 8055(define_expand "indirect_jump"
9c08d1fa 8056 [(set (pc)
cffb2a26 8057 (match_operand:SI 0 "s_register_operand" ""))]
8058 "TARGET_EITHER"
9c08d1fa 8059 ""
cffb2a26 8060)
8061
f1039640 8062;; NB Never uses BX.
cffb2a26 8063(define_insn "*arm_indirect_jump"
8064 [(set (pc)
8065 (match_operand:SI 0 "s_register_operand" "r"))]
8066 "TARGET_ARM"
8067 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8068 [(set_attr "predicable" "yes")]
cffb2a26 8069)
9c08d1fa 8070
f7fbdd4a 8071(define_insn "*load_indirect_jump"
9c08d1fa 8072 [(set (pc)
8073 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8074 "TARGET_ARM"
8075 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8076 [(set_attr "type" "load1")
61a2d04c 8077 (set_attr "pool_range" "4096")
8078 (set_attr "neg_pool_range" "4084")
0d66636f 8079 (set_attr "predicable" "yes")]
cffb2a26 8080)
8081
f1039640 8082;; NB Never uses BX.
cffb2a26 8083(define_insn "*thumb_indirect_jump"
8084 [(set (pc)
8085 (match_operand:SI 0 "register_operand" "l*r"))]
8086 "TARGET_THUMB"
8087 "mov\\tpc, %0"
8088 [(set_attr "conds" "clob")
8089 (set_attr "length" "2")]
8090)
8091
9c08d1fa 8092\f
8093;; Misc insns
8094
8095(define_insn "nop"
8096 [(const_int 0)]
cffb2a26 8097 "TARGET_EITHER"
8098 "*
8099 if (TARGET_ARM)
8100 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8101 return \"mov\\tr8, r8\";
8102 "
8103 [(set (attr "length")
8104 (if_then_else (eq_attr "is_thumb" "yes")
8105 (const_int 2)
8106 (const_int 4)))]
8107)
8108
9c08d1fa 8109\f
8110;; Patterns to allow combination of arithmetic, cond code and shifts
8111
f7fbdd4a 8112(define_insn "*arith_shiftsi"
9c08d1fa 8113 [(set (match_operand:SI 0 "s_register_operand" "=r")
8114 (match_operator:SI 1 "shiftable_operator"
8115 [(match_operator:SI 3 "shift_operator"
8116 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8117 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8118 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8119 "TARGET_ARM"
6c4c2133 8120 "%i1%?\\t%0, %2, %4%S3"
344495ea 8121 [(set_attr "predicable" "yes")
331beb1a 8122 (set_attr "shift" "4")
a2cd141b 8123 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8124 (const_string "alu_shift")
8125 (const_string "alu_shift_reg")))]
6c4c2133 8126)
9c08d1fa 8127
d7863cfe 8128(define_split
8129 [(set (match_operand:SI 0 "s_register_operand" "")
8130 (match_operator:SI 1 "shiftable_operator"
8131 [(match_operator:SI 2 "shiftable_operator"
8132 [(match_operator:SI 3 "shift_operator"
8133 [(match_operand:SI 4 "s_register_operand" "")
8134 (match_operand:SI 5 "reg_or_int_operand" "")])
8135 (match_operand:SI 6 "s_register_operand" "")])
8136 (match_operand:SI 7 "arm_rhs_operand" "")]))
8137 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8138 "TARGET_ARM"
8139 [(set (match_dup 8)
8140 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8141 (match_dup 6)]))
8142 (set (match_dup 0)
8143 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8144 "")
8145
f7fbdd4a 8146(define_insn "*arith_shiftsi_compare0"
bd5b4116 8147 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8148 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8149 [(match_operator:SI 3 "shift_operator"
8150 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8151 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8152 (match_operand:SI 2 "s_register_operand" "r")])
8153 (const_int 0)))
8154 (set (match_operand:SI 0 "s_register_operand" "=r")
8155 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8156 (match_dup 2)]))]
cffb2a26 8157 "TARGET_ARM"
87b22bf7 8158 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8159 [(set_attr "conds" "set")
331beb1a 8160 (set_attr "shift" "4")
a2cd141b 8161 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8162 (const_string "alu_shift")
8163 (const_string "alu_shift_reg")))]
0d66636f 8164)
9c08d1fa 8165
f7fbdd4a 8166(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8167 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8168 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8169 [(match_operator:SI 3 "shift_operator"
8170 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8171 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8172 (match_operand:SI 2 "s_register_operand" "r")])
8173 (const_int 0)))
8174 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8175 "TARGET_ARM"
87b22bf7 8176 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8177 [(set_attr "conds" "set")
331beb1a 8178 (set_attr "shift" "4")
a2cd141b 8179 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8180 (const_string "alu_shift")
8181 (const_string "alu_shift_reg")))]
0d66636f 8182)
9c08d1fa 8183
f7fbdd4a 8184(define_insn "*sub_shiftsi"
9c08d1fa 8185 [(set (match_operand:SI 0 "s_register_operand" "=r")
8186 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8187 (match_operator:SI 2 "shift_operator"
8188 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8189 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 8190 "TARGET_ARM"
6c4c2133 8191 "sub%?\\t%0, %1, %3%S2"
344495ea 8192 [(set_attr "predicable" "yes")
331beb1a 8193 (set_attr "shift" "3")
a2cd141b 8194 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8195 (const_string "alu_shift")
8196 (const_string "alu_shift_reg")))]
6c4c2133 8197)
9c08d1fa 8198
f7fbdd4a 8199(define_insn "*sub_shiftsi_compare0"
bd5b4116 8200 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8201 (compare:CC_NOOV
8202 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8203 (match_operator:SI 2 "shift_operator"
8204 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8205 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8206 (const_int 0)))
9c08d1fa 8207 (set (match_operand:SI 0 "s_register_operand" "=r")
8208 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8209 (match_dup 4)])))]
cffb2a26 8210 "TARGET_ARM"
87b22bf7 8211 "sub%?s\\t%0, %1, %3%S2"
344495ea 8212 [(set_attr "conds" "set")
a2cd141b 8213 (set_attr "shift" "3")
8214 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8215 (const_string "alu_shift")
8216 (const_string "alu_shift_reg")))]
0d66636f 8217)
9c08d1fa 8218
f7fbdd4a 8219(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8220 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8221 (compare:CC_NOOV
8222 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8223 (match_operator:SI 2 "shift_operator"
8224 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8225 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8226 (const_int 0)))
9c08d1fa 8227 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8228 "TARGET_ARM"
87b22bf7 8229 "sub%?s\\t%0, %1, %3%S2"
344495ea 8230 [(set_attr "conds" "set")
a2cd141b 8231 (set_attr "shift" "3")
8232 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8233 (const_string "alu_shift")
8234 (const_string "alu_shift_reg")))]
0d66636f 8235)
9c08d1fa 8236
9c08d1fa 8237\f
8238
f7fbdd4a 8239(define_insn "*and_scc"
9c08d1fa 8240 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8241 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8242 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8243 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8244 "TARGET_ARM"
e2348bcb 8245 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8246 [(set_attr "conds" "use")
8247 (set_attr "length" "8")]
8248)
9c08d1fa 8249
f7fbdd4a 8250(define_insn "*ior_scc"
9c08d1fa 8251 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8252 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8253 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8254 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8255 "TARGET_ARM"
e2348bcb 8256 "@
899850b0 8257 orr%d2\\t%0, %1, #1
8258 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8259 [(set_attr "conds" "use")
8260 (set_attr "length" "4,8")]
8261)
9c08d1fa 8262
f7fbdd4a 8263(define_insn "*compare_scc"
5565501b 8264 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8265 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8266 [(match_operand:SI 2 "s_register_operand" "r,r")
8267 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8268 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8269 "TARGET_ARM"
9c08d1fa 8270 "*
601f584c 8271 if (operands[3] == const0_rtx)
8272 {
8273 if (GET_CODE (operands[1]) == LT)
8274 return \"mov\\t%0, %2, lsr #31\";
8275
8276 if (GET_CODE (operands[1]) == GE)
8277 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 8278
601f584c 8279 if (GET_CODE (operands[1]) == EQ)
8280 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8281 }
e2348bcb 8282
8fa3ba89 8283 if (GET_CODE (operands[1]) == NE)
8284 {
8285 if (which_alternative == 1)
8286 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8287 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8288 }
8289 if (which_alternative == 1)
8290 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8291 else
8292 output_asm_insn (\"cmp\\t%2, %3\", operands);
8293 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8294 "
8295 [(set_attr "conds" "clob")
8296 (set_attr "length" "12")]
8297)
9c08d1fa 8298
f7fbdd4a 8299(define_insn "*cond_move"
9c08d1fa 8300 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8301 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8302 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8303 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8304 (const_int 0)])
8305 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8306 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8307 "TARGET_ARM"
9c08d1fa 8308 "*
8fa3ba89 8309 if (GET_CODE (operands[3]) == NE)
8310 {
8311 if (which_alternative != 1)
8312 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8313 if (which_alternative != 0)
8314 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8315 return \"\";
8316 }
8317 if (which_alternative != 0)
8318 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8319 if (which_alternative != 1)
8320 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8321 return \"\";
8322 "
8323 [(set_attr "conds" "use")
8324 (set_attr "length" "4,4,8")]
8325)
9c08d1fa 8326
f7fbdd4a 8327(define_insn "*cond_arith"
9c08d1fa 8328 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8329 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8330 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8331 [(match_operand:SI 2 "s_register_operand" "r,r")
8332 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8333 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8334 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8335 "TARGET_ARM"
9c08d1fa 8336 "*
8fa3ba89 8337 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8338 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8339
8fa3ba89 8340 output_asm_insn (\"cmp\\t%2, %3\", operands);
8341 if (GET_CODE (operands[5]) == AND)
8342 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8343 else if (GET_CODE (operands[5]) == MINUS)
8344 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8345 else if (which_alternative != 0)
8346 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8347 return \"%i5%d4\\t%0, %1, #1\";
8348 "
8349 [(set_attr "conds" "clob")
8350 (set_attr "length" "12")]
8351)
9c08d1fa 8352
f7fbdd4a 8353(define_insn "*cond_sub"
9c08d1fa 8354 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8355 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8356 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8357 [(match_operand:SI 2 "s_register_operand" "r,r")
8358 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8359 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8360 "TARGET_ARM"
9c08d1fa 8361 "*
8fa3ba89 8362 output_asm_insn (\"cmp\\t%2, %3\", operands);
8363 if (which_alternative != 0)
8364 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8365 return \"sub%d4\\t%0, %1, #1\";
8366 "
8367 [(set_attr "conds" "clob")
8368 (set_attr "length" "8,12")]
8369)
9c08d1fa 8370
aea4c774 8371(define_insn "*cmp_ite0"
cffb2a26 8372 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8373 (compare
8374 (if_then_else:SI
8fa3ba89 8375 (match_operator 4 "arm_comparison_operator"
aea4c774 8376 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8377 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8378 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8379 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8380 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8381 (const_int 0))
8382 (const_int 0)))]
cffb2a26 8383 "TARGET_ARM"
9c08d1fa 8384 "*
aea4c774 8385 {
8fa3ba89 8386 static const char * const opcodes[4][2] =
8387 {
8388 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8389 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8390 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8391 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8392 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8393 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8394 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8395 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8396 };
8397 int swap =
8398 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8399
8400 return opcodes[which_alternative][swap];
8401 }"
8402 [(set_attr "conds" "set")
8403 (set_attr "length" "8")]
8404)
9c08d1fa 8405
aea4c774 8406(define_insn "*cmp_ite1"
cffb2a26 8407 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8408 (compare
8409 (if_then_else:SI
8fa3ba89 8410 (match_operator 4 "arm_comparison_operator"
aea4c774 8411 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8412 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8413 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8414 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8415 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8416 (const_int 1))
8417 (const_int 0)))]
cffb2a26 8418 "TARGET_ARM"
9c08d1fa 8419 "*
9c08d1fa 8420 {
215b30b3 8421 static const char * const opcodes[4][2] =
8422 {
8423 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8424 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8425 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8426 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8427 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8428 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8429 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8430 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8431 };
8432 int swap =
8433 comparison_dominates_p (GET_CODE (operands[5]),
8434 reverse_condition (GET_CODE (operands[4])));
8435
8436 return opcodes[which_alternative][swap];
8437 }"
8fa3ba89 8438 [(set_attr "conds" "set")
8439 (set_attr "length" "8")]
8440)
9c08d1fa 8441
f6c53574 8442(define_insn "*cmp_and"
8443 [(set (match_operand 6 "dominant_cc_register" "")
8444 (compare
8445 (and:SI
8446 (match_operator 4 "arm_comparison_operator"
8447 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8448 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8449 (match_operator:SI 5 "arm_comparison_operator"
8450 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8451 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8452 (const_int 0)))]
8453 "TARGET_ARM"
8454 "*
8455 {
35823b64 8456 static const char *const opcodes[4][2] =
f6c53574 8457 {
8458 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8459 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8460 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8461 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8462 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8463 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8464 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8465 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8466 };
8467 int swap =
8468 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8469
8470 return opcodes[which_alternative][swap];
8471 }"
8472 [(set_attr "conds" "set")
8473 (set_attr "predicable" "no")
8474 (set_attr "length" "8")]
8475)
8476
8477(define_insn "*cmp_ior"
8478 [(set (match_operand 6 "dominant_cc_register" "")
8479 (compare
8480 (ior:SI
8481 (match_operator 4 "arm_comparison_operator"
8482 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8483 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8484 (match_operator:SI 5 "arm_comparison_operator"
8485 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8486 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8487 (const_int 0)))]
8488 "TARGET_ARM"
8489 "*
8490{
35823b64 8491 static const char *const opcodes[4][2] =
f6c53574 8492 {
8493 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8494 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8495 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8496 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8497 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8498 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8499 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8500 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8501 };
8502 int swap =
8503 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8504
8505 return opcodes[which_alternative][swap];
8506}
8507"
8508 [(set_attr "conds" "set")
8509 (set_attr "length" "8")]
8510)
8511
3c5afce6 8512(define_insn_and_split "*ior_scc_scc"
8513 [(set (match_operand:SI 0 "s_register_operand" "=r")
8514 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8515 [(match_operand:SI 1 "s_register_operand" "r")
8516 (match_operand:SI 2 "arm_add_operand" "rIL")])
8517 (match_operator:SI 6 "arm_comparison_operator"
8518 [(match_operand:SI 4 "s_register_operand" "r")
8519 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8520 (clobber (reg:CC CC_REGNUM))]
8521 "TARGET_ARM
8522 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8523 != CCmode)"
8524 "#"
8525 "TARGET_ARM && reload_completed"
8526 [(set (match_dup 7)
8527 (compare
8528 (ior:SI
8529 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8530 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8531 (const_int 0)))
8532 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8533 "operands[7]
8534 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8535 DOM_CC_X_OR_Y),
601f584c 8536 CC_REGNUM);"
8537 [(set_attr "conds" "clob")
8538 (set_attr "length" "16")])
8539
8540; If the above pattern is followed by a CMP insn, then the compare is
8541; redundant, since we can rework the conditional instruction that follows.
8542(define_insn_and_split "*ior_scc_scc_cmp"
8543 [(set (match_operand 0 "dominant_cc_register" "")
8544 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8545 [(match_operand:SI 1 "s_register_operand" "r")
8546 (match_operand:SI 2 "arm_add_operand" "rIL")])
8547 (match_operator:SI 6 "arm_comparison_operator"
8548 [(match_operand:SI 4 "s_register_operand" "r")
8549 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8550 (const_int 0)))
8551 (set (match_operand:SI 7 "s_register_operand" "=r")
8552 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8553 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8554 "TARGET_ARM"
8555 "#"
8556 "TARGET_ARM && reload_completed"
8557 [(set (match_dup 0)
8558 (compare
8559 (ior:SI
8560 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8561 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8562 (const_int 0)))
8563 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8564 ""
8565 [(set_attr "conds" "set")
8566 (set_attr "length" "16")])
3c5afce6 8567
8568(define_insn_and_split "*and_scc_scc"
8569 [(set (match_operand:SI 0 "s_register_operand" "=r")
8570 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8571 [(match_operand:SI 1 "s_register_operand" "r")
8572 (match_operand:SI 2 "arm_add_operand" "rIL")])
8573 (match_operator:SI 6 "arm_comparison_operator"
8574 [(match_operand:SI 4 "s_register_operand" "r")
8575 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8576 (clobber (reg:CC CC_REGNUM))]
8577 "TARGET_ARM
8578 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8579 != CCmode)"
8580 "#"
601f584c 8581 "TARGET_ARM && reload_completed
8582 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8583 != CCmode)"
3c5afce6 8584 [(set (match_dup 7)
8585 (compare
8586 (and:SI
8587 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8588 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8589 (const_int 0)))
8590 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8591 "operands[7]
8592 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8593 DOM_CC_X_AND_Y),
601f584c 8594 CC_REGNUM);"
8595 [(set_attr "conds" "clob")
8596 (set_attr "length" "16")])
8597
8598; If the above pattern is followed by a CMP insn, then the compare is
8599; redundant, since we can rework the conditional instruction that follows.
8600(define_insn_and_split "*and_scc_scc_cmp"
8601 [(set (match_operand 0 "dominant_cc_register" "")
8602 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8603 [(match_operand:SI 1 "s_register_operand" "r")
8604 (match_operand:SI 2 "arm_add_operand" "rIL")])
8605 (match_operator:SI 6 "arm_comparison_operator"
8606 [(match_operand:SI 4 "s_register_operand" "r")
8607 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8608 (const_int 0)))
8609 (set (match_operand:SI 7 "s_register_operand" "=r")
8610 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8611 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8612 "TARGET_ARM"
8613 "#"
8614 "TARGET_ARM && reload_completed"
8615 [(set (match_dup 0)
8616 (compare
8617 (and:SI
8618 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8619 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8620 (const_int 0)))
8621 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8622 ""
8623 [(set_attr "conds" "set")
8624 (set_attr "length" "16")])
8625
8626;; If there is no dominance in the comparison, then we can still save an
8627;; instruction in the AND case, since we can know that the second compare
8628;; need only zero the value if false (if true, then the value is already
8629;; correct).
8630(define_insn_and_split "*and_scc_scc_nodom"
8631 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8632 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8633 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8634 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8635 (match_operator:SI 6 "arm_comparison_operator"
8636 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8637 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8638 (clobber (reg:CC CC_REGNUM))]
8639 "TARGET_ARM
8640 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8641 == CCmode)"
8642 "#"
8643 "TARGET_ARM && reload_completed"
8644 [(parallel [(set (match_dup 0)
8645 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8646 (clobber (reg:CC CC_REGNUM))])
8647 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8648 (set (match_dup 0)
8649 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8650 (match_dup 0)
8651 (const_int 0)))]
8652 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8653 operands[4], operands[5]),
8654 CC_REGNUM);
8655 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8656 operands[5]);"
8657 [(set_attr "conds" "clob")
8658 (set_attr "length" "20")])
3c5afce6 8659
3a0bdee0 8660(define_split
8661 [(set (reg:CC_NOOV CC_REGNUM)
8662 (compare:CC_NOOV (ior:SI
8663 (and:SI (match_operand:SI 0 "s_register_operand" "")
8664 (const_int 1))
8665 (match_operator:SI 1 "comparison_operator"
8666 [(match_operand:SI 2 "s_register_operand" "")
8667 (match_operand:SI 3 "arm_add_operand" "")]))
8668 (const_int 0)))
8669 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8670 "TARGET_ARM"
8671 [(set (match_dup 4)
8672 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8673 (match_dup 0)))
8674 (set (reg:CC_NOOV CC_REGNUM)
8675 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8676 (const_int 0)))]
8677 "")
8678
8679(define_split
8680 [(set (reg:CC_NOOV CC_REGNUM)
8681 (compare:CC_NOOV (ior:SI
8682 (match_operator:SI 1 "comparison_operator"
8683 [(match_operand:SI 2 "s_register_operand" "")
8684 (match_operand:SI 3 "arm_add_operand" "")])
8685 (and:SI (match_operand:SI 0 "s_register_operand" "")
8686 (const_int 1)))
8687 (const_int 0)))
8688 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8689 "TARGET_ARM"
8690 [(set (match_dup 4)
8691 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8692 (match_dup 0)))
8693 (set (reg:CC_NOOV CC_REGNUM)
8694 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8695 (const_int 0)))]
8696 "")
8697
f7fbdd4a 8698(define_insn "*negscc"
9c08d1fa 8699 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8700 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 8701 [(match_operand:SI 1 "s_register_operand" "r")
8702 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 8703 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8704 "TARGET_ARM"
9c08d1fa 8705 "*
f0e75574 8706 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
e2348bcb 8707 return \"mov\\t%0, %1, asr #31\";
8708
9c08d1fa 8709 if (GET_CODE (operands[3]) == NE)
e2348bcb 8710 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8711
9c08d1fa 8712 if (GET_CODE (operands[3]) == GT)
e2348bcb 8713 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8714
8715 output_asm_insn (\"cmp\\t%1, %2\", operands);
8716 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8717 return \"mvn%d3\\t%0, #0\";
215b30b3 8718 "
8fa3ba89 8719 [(set_attr "conds" "clob")
8720 (set_attr "length" "12")]
8721)
9c08d1fa 8722
8723(define_insn "movcond"
8724 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 8725 (if_then_else:SI
8fa3ba89 8726 (match_operator 5 "arm_comparison_operator"
5565501b 8727 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8728 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8729 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8730 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 8731 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8732 "TARGET_ARM"
9c08d1fa 8733 "*
8734 if (GET_CODE (operands[5]) == LT
8735 && (operands[4] == const0_rtx))
8736 {
5565501b 8737 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 8738 {
9c08d1fa 8739 if (operands[2] == const0_rtx)
e2348bcb 8740 return \"and\\t%0, %1, %3, asr #31\";
8741 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 8742 }
8743 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8744 {
9c08d1fa 8745 if (operands[1] == const0_rtx)
e2348bcb 8746 return \"bic\\t%0, %2, %3, asr #31\";
8747 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 8748 }
8749 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8750 are constants. */
9c08d1fa 8751 }
e2348bcb 8752
9c08d1fa 8753 if (GET_CODE (operands[5]) == GE
8754 && (operands[4] == const0_rtx))
8755 {
8756 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8757 {
9c08d1fa 8758 if (operands[2] == const0_rtx)
e2348bcb 8759 return \"bic\\t%0, %1, %3, asr #31\";
8760 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 8761 }
8762 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8763 {
9c08d1fa 8764 if (operands[1] == const0_rtx)
e2348bcb 8765 return \"and\\t%0, %2, %3, asr #31\";
8766 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 8767 }
8768 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8769 are constants. */
9c08d1fa 8770 }
8771 if (GET_CODE (operands[4]) == CONST_INT
8772 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 8773 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 8774 else
e2348bcb 8775 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 8776 if (which_alternative != 0)
e2348bcb 8777 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 8778 if (which_alternative != 1)
e2348bcb 8779 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 8780 return \"\";
215b30b3 8781 "
8fa3ba89 8782 [(set_attr "conds" "clob")
8783 (set_attr "length" "8,8,12")]
8784)
9c08d1fa 8785
8a18b90c 8786(define_insn "*ifcompare_plus_move"
8787 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8788 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8789 [(match_operand:SI 4 "s_register_operand" "r,r")
8790 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8791 (plus:SI
8792 (match_operand:SI 2 "s_register_operand" "r,r")
8793 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 8794 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8795 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8796 "TARGET_ARM"
8a18b90c 8797 "#"
8fa3ba89 8798 [(set_attr "conds" "clob")
8799 (set_attr "length" "8,12")]
8800)
8a18b90c 8801
8802(define_insn "*if_plus_move"
129a2fe4 8803 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8804 (if_then_else:SI
8fa3ba89 8805 (match_operator 4 "arm_comparison_operator"
8a18b90c 8806 [(match_operand 5 "cc_register" "") (const_int 0)])
8807 (plus:SI
129a2fe4 8808 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8809 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8810 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 8811 "TARGET_ARM"
8a18b90c 8812 "@
8813 add%d4\\t%0, %2, %3
8814 sub%d4\\t%0, %2, #%n3
8815 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 8816 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 8817 [(set_attr "conds" "use")
8818 (set_attr "length" "4,4,8,8")
8819 (set_attr "type" "*,*,*,*")]
8820)
8a18b90c 8821
8822(define_insn "*ifcompare_move_plus"
5565501b 8823 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8824 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8825 [(match_operand:SI 4 "s_register_operand" "r,r")
8826 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8827 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8828 (plus:SI
8829 (match_operand:SI 2 "s_register_operand" "r,r")
8830 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 8831 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8832 "TARGET_ARM"
8a18b90c 8833 "#"
8fa3ba89 8834 [(set_attr "conds" "clob")
8835 (set_attr "length" "8,12")]
8836)
8a18b90c 8837
8838(define_insn "*if_move_plus"
129a2fe4 8839 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8840 (if_then_else:SI
8fa3ba89 8841 (match_operator 4 "arm_comparison_operator"
8a18b90c 8842 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 8843 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 8844 (plus:SI
129a2fe4 8845 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8846 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 8847 "TARGET_ARM"
8a18b90c 8848 "@
8849 add%D4\\t%0, %2, %3
8850 sub%D4\\t%0, %2, #%n3
8851 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 8852 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 8853 [(set_attr "conds" "use")
8854 (set_attr "length" "4,4,8,8")
8855 (set_attr "type" "*,*,*,*")]
8856)
8a18b90c 8857
8858(define_insn "*ifcompare_arith_arith"
8859 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8860 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 8861 [(match_operand:SI 5 "s_register_operand" "r")
8862 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 8863 (match_operator:SI 8 "shiftable_operator"
8a18b90c 8864 [(match_operand:SI 1 "s_register_operand" "r")
8865 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 8866 (match_operator:SI 7 "shiftable_operator"
8a18b90c 8867 [(match_operand:SI 3 "s_register_operand" "r")
8868 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 8869 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8870 "TARGET_ARM"
8a18b90c 8871 "#"
8fa3ba89 8872 [(set_attr "conds" "clob")
8873 (set_attr "length" "12")]
8874)
9c08d1fa 8875
8a18b90c 8876(define_insn "*if_arith_arith"
8877 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8878 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 8879 [(match_operand 8 "cc_register" "") (const_int 0)])
8880 (match_operator:SI 6 "shiftable_operator"
8881 [(match_operand:SI 1 "s_register_operand" "r")
8882 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8883 (match_operator:SI 7 "shiftable_operator"
8884 [(match_operand:SI 3 "s_register_operand" "r")
8885 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 8886 "TARGET_ARM"
8a18b90c 8887 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 8888 [(set_attr "conds" "use")
8889 (set_attr "length" "8")]
8890)
8a18b90c 8891
f7fbdd4a 8892(define_insn "*ifcompare_arith_move"
9c08d1fa 8893 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8894 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8895 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 8896 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 8897 (match_operator:SI 7 "shiftable_operator"
8898 [(match_operand:SI 4 "s_register_operand" "r,r")
8899 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 8900 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8901 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8902 "TARGET_ARM"
9c08d1fa 8903 "*
9c08d1fa 8904 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8905 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 8906 everything is in registers then we can do this in two instructions. */
9c08d1fa 8907 if (operands[3] == const0_rtx
8908 && GET_CODE (operands[7]) != AND
8909 && GET_CODE (operands[5]) == REG
8910 && GET_CODE (operands[1]) == REG
8911 && REGNO (operands[1]) == REGNO (operands[4])
8912 && REGNO (operands[4]) != REGNO (operands[0]))
8913 {
8914 if (GET_CODE (operands[6]) == LT)
40dbec34 8915 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8916 else if (GET_CODE (operands[6]) == GE)
40dbec34 8917 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8918 }
8919 if (GET_CODE (operands[3]) == CONST_INT
8920 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 8921 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 8922 else
e2348bcb 8923 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 8924 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 8925 if (which_alternative != 0)
129a2fe4 8926 return \"mov%D6\\t%0, %1\";
9c08d1fa 8927 return \"\";
215b30b3 8928 "
8fa3ba89 8929 [(set_attr "conds" "clob")
8930 (set_attr "length" "8,12")]
8931)
9c08d1fa 8932
8a18b90c 8933(define_insn "*if_arith_move"
129a2fe4 8934 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8935 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 8936 [(match_operand 6 "cc_register" "") (const_int 0)])
8937 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8938 [(match_operand:SI 2 "s_register_operand" "r,r")
8939 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8940 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 8941 "TARGET_ARM"
8a18b90c 8942 "@
8943 %I5%d4\\t%0, %2, %3
129a2fe4 8944 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 8945 [(set_attr "conds" "use")
8946 (set_attr "length" "4,8")
8947 (set_attr "type" "*,*")]
8948)
8a18b90c 8949
f7fbdd4a 8950(define_insn "*ifcompare_move_arith"
9c08d1fa 8951 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8952 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8953 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 8954 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8955 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 8956 (match_operator:SI 7 "shiftable_operator"
8957 [(match_operand:SI 2 "s_register_operand" "r,r")
8958 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8959 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8960 "TARGET_ARM"
9c08d1fa 8961 "*
9c08d1fa 8962 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8963 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 8964 everything is in registers then we can do this in two instructions */
8965 if (operands[5] == const0_rtx
8966 && GET_CODE (operands[7]) != AND
8967 && GET_CODE (operands[3]) == REG
8968 && GET_CODE (operands[1]) == REG
8969 && REGNO (operands[1]) == REGNO (operands[2])
8970 && REGNO (operands[2]) != REGNO (operands[0]))
8971 {
8972 if (GET_CODE (operands[6]) == GE)
40dbec34 8973 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8974 else if (GET_CODE (operands[6]) == LT)
40dbec34 8975 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8976 }
40dbec34 8977
9c08d1fa 8978 if (GET_CODE (operands[5]) == CONST_INT
8979 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 8980 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 8981 else
e2348bcb 8982 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 8983
9c08d1fa 8984 if (which_alternative != 0)
129a2fe4 8985 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 8986 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 8987 "
8fa3ba89 8988 [(set_attr "conds" "clob")
8989 (set_attr "length" "8,12")]
8990)
9c08d1fa 8991
8a18b90c 8992(define_insn "*if_move_arith"
129a2fe4 8993 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 8994 (if_then_else:SI
8fa3ba89 8995 (match_operator 4 "arm_comparison_operator"
8a18b90c 8996 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 8997 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8998 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8999 [(match_operand:SI 2 "s_register_operand" "r,r")
9000 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9001 "TARGET_ARM"
8a18b90c 9002 "@
9003 %I5%D4\\t%0, %2, %3
129a2fe4 9004 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9005 [(set_attr "conds" "use")
9006 (set_attr "length" "4,8")
9007 (set_attr "type" "*,*")]
9008)
8a18b90c 9009
9010(define_insn "*ifcompare_move_not"
9c08d1fa 9011 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9012 (if_then_else:SI
8fa3ba89 9013 (match_operator 5 "arm_comparison_operator"
8a18b90c 9014 [(match_operand:SI 3 "s_register_operand" "r,r")
9015 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9016 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9017 (not:SI
9018 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9019 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9020 "TARGET_ARM"
8a18b90c 9021 "#"
8fa3ba89 9022 [(set_attr "conds" "clob")
9023 (set_attr "length" "8,12")]
9024)
9c08d1fa 9025
8a18b90c 9026(define_insn "*if_move_not"
9027 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9028 (if_then_else:SI
8fa3ba89 9029 (match_operator 4 "arm_comparison_operator"
8a18b90c 9030 [(match_operand 3 "cc_register" "") (const_int 0)])
9031 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9032 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9033 "TARGET_ARM"
8a18b90c 9034 "@
9035 mvn%D4\\t%0, %2
9036 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9037 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9038 [(set_attr "conds" "use")
9039 (set_attr "length" "4,8,8")]
9040)
8a18b90c 9041
9042(define_insn "*ifcompare_not_move"
9c08d1fa 9043 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9044 (if_then_else:SI
8fa3ba89 9045 (match_operator 5 "arm_comparison_operator"
8a18b90c 9046 [(match_operand:SI 3 "s_register_operand" "r,r")
9047 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9048 (not:SI
9049 (match_operand:SI 2 "s_register_operand" "r,r"))
9050 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9051 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9052 "TARGET_ARM"
8a18b90c 9053 "#"
8fa3ba89 9054 [(set_attr "conds" "clob")
9055 (set_attr "length" "8,12")]
9056)
9c08d1fa 9057
8a18b90c 9058(define_insn "*if_not_move"
9059 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9060 (if_then_else:SI
8fa3ba89 9061 (match_operator 4 "arm_comparison_operator"
8a18b90c 9062 [(match_operand 3 "cc_register" "") (const_int 0)])
9063 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9064 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9065 "TARGET_ARM"
8a18b90c 9066 "@
9067 mvn%d4\\t%0, %2
9068 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9069 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9070 [(set_attr "conds" "use")
9071 (set_attr "length" "4,8,8")]
9072)
8a18b90c 9073
9074(define_insn "*ifcompare_shift_move"
9c08d1fa 9075 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9076 (if_then_else:SI
8fa3ba89 9077 (match_operator 6 "arm_comparison_operator"
8a18b90c 9078 [(match_operand:SI 4 "s_register_operand" "r,r")
9079 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9080 (match_operator:SI 7 "shift_operator"
9081 [(match_operand:SI 2 "s_register_operand" "r,r")
9082 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9083 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9084 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9085 "TARGET_ARM"
9c08d1fa 9086 "#"
8fa3ba89 9087 [(set_attr "conds" "clob")
9088 (set_attr "length" "8,12")]
9089)
9c08d1fa 9090
8a18b90c 9091(define_insn "*if_shift_move"
9092 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9093 (if_then_else:SI
8fa3ba89 9094 (match_operator 5 "arm_comparison_operator"
8a18b90c 9095 [(match_operand 6 "cc_register" "") (const_int 0)])
9096 (match_operator:SI 4 "shift_operator"
9097 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9098 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9099 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9100 "TARGET_ARM"
5565501b 9101 "@
8a18b90c 9102 mov%d5\\t%0, %2%S4
9103 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9104 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9105 [(set_attr "conds" "use")
331beb1a 9106 (set_attr "shift" "2")
a2cd141b 9107 (set_attr "length" "4,8,8")
9108 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9109 (const_string "alu_shift")
9110 (const_string "alu_shift_reg")))]
8fa3ba89 9111)
5565501b 9112
8a18b90c 9113(define_insn "*ifcompare_move_shift"
9114 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9115 (if_then_else:SI
8fa3ba89 9116 (match_operator 6 "arm_comparison_operator"
8a18b90c 9117 [(match_operand:SI 4 "s_register_operand" "r,r")
9118 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9119 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9120 (match_operator:SI 7 "shift_operator"
8a18b90c 9121 [(match_operand:SI 2 "s_register_operand" "r,r")
9122 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9123 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9124 "TARGET_ARM"
8a18b90c 9125 "#"
8fa3ba89 9126 [(set_attr "conds" "clob")
9127 (set_attr "length" "8,12")]
9128)
5565501b 9129
8a18b90c 9130(define_insn "*if_move_shift"
9131 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9132 (if_then_else:SI
8fa3ba89 9133 (match_operator 5 "arm_comparison_operator"
8a18b90c 9134 [(match_operand 6 "cc_register" "") (const_int 0)])
9135 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9136 (match_operator:SI 4 "shift_operator"
9137 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9138 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9139 "TARGET_ARM"
5565501b 9140 "@
8a18b90c 9141 mov%D5\\t%0, %2%S4
9142 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9143 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9144 [(set_attr "conds" "use")
331beb1a 9145 (set_attr "shift" "2")
a2cd141b 9146 (set_attr "length" "4,8,8")
9147 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9148 (const_string "alu_shift")
9149 (const_string "alu_shift_reg")))]
8fa3ba89 9150)
9c08d1fa 9151
f7fbdd4a 9152(define_insn "*ifcompare_shift_shift"
8a18b90c 9153 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9154 (if_then_else:SI
8fa3ba89 9155 (match_operator 7 "arm_comparison_operator"
8a18b90c 9156 [(match_operand:SI 5 "s_register_operand" "r")
9157 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9158 (match_operator:SI 8 "shift_operator"
8a18b90c 9159 [(match_operand:SI 1 "s_register_operand" "r")
9160 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9161 (match_operator:SI 9 "shift_operator"
8a18b90c 9162 [(match_operand:SI 3 "s_register_operand" "r")
9163 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9164 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9165 "TARGET_ARM"
8a18b90c 9166 "#"
8fa3ba89 9167 [(set_attr "conds" "clob")
9168 (set_attr "length" "12")]
9169)
9c08d1fa 9170
8a18b90c 9171(define_insn "*if_shift_shift"
9172 [(set (match_operand:SI 0 "s_register_operand" "=r")
9173 (if_then_else:SI
8fa3ba89 9174 (match_operator 5 "arm_comparison_operator"
8a18b90c 9175 [(match_operand 8 "cc_register" "") (const_int 0)])
9176 (match_operator:SI 6 "shift_operator"
9177 [(match_operand:SI 1 "s_register_operand" "r")
9178 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9179 (match_operator:SI 7 "shift_operator"
9180 [(match_operand:SI 3 "s_register_operand" "r")
9181 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9182 "TARGET_ARM"
8a18b90c 9183 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9184 [(set_attr "conds" "use")
331beb1a 9185 (set_attr "shift" "1")
a2cd141b 9186 (set_attr "length" "8")
9187 (set (attr "type") (if_then_else
9188 (and (match_operand 2 "const_int_operand" "")
9189 (match_operand 4 "const_int_operand" ""))
9190 (const_string "alu_shift")
9191 (const_string "alu_shift_reg")))]
8fa3ba89 9192)
8a18b90c 9193
f7fbdd4a 9194(define_insn "*ifcompare_not_arith"
8a18b90c 9195 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9196 (if_then_else:SI
8fa3ba89 9197 (match_operator 6 "arm_comparison_operator"
8a18b90c 9198 [(match_operand:SI 4 "s_register_operand" "r")
9199 (match_operand:SI 5 "arm_add_operand" "rIL")])
9200 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9201 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9202 [(match_operand:SI 2 "s_register_operand" "r")
9203 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9204 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9205 "TARGET_ARM"
8a18b90c 9206 "#"
8fa3ba89 9207 [(set_attr "conds" "clob")
9208 (set_attr "length" "12")]
9209)
9c08d1fa 9210
8a18b90c 9211(define_insn "*if_not_arith"
9212 [(set (match_operand:SI 0 "s_register_operand" "=r")
9213 (if_then_else:SI
8fa3ba89 9214 (match_operator 5 "arm_comparison_operator"
8a18b90c 9215 [(match_operand 4 "cc_register" "") (const_int 0)])
9216 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9217 (match_operator:SI 6 "shiftable_operator"
9218 [(match_operand:SI 2 "s_register_operand" "r")
9219 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9220 "TARGET_ARM"
8a18b90c 9221 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9222 [(set_attr "conds" "use")
9223 (set_attr "length" "8")]
9224)
8a18b90c 9225
9226(define_insn "*ifcompare_arith_not"
9227 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9228 (if_then_else:SI
8fa3ba89 9229 (match_operator 6 "arm_comparison_operator"
8a18b90c 9230 [(match_operand:SI 4 "s_register_operand" "r")
9231 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9232 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9233 [(match_operand:SI 2 "s_register_operand" "r")
9234 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9235 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9236 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9237 "TARGET_ARM"
8a18b90c 9238 "#"
8fa3ba89 9239 [(set_attr "conds" "clob")
9240 (set_attr "length" "12")]
9241)
9c08d1fa 9242
8a18b90c 9243(define_insn "*if_arith_not"
9244 [(set (match_operand:SI 0 "s_register_operand" "=r")
9245 (if_then_else:SI
8fa3ba89 9246 (match_operator 5 "arm_comparison_operator"
8a18b90c 9247 [(match_operand 4 "cc_register" "") (const_int 0)])
9248 (match_operator:SI 6 "shiftable_operator"
9249 [(match_operand:SI 2 "s_register_operand" "r")
9250 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9251 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9252 "TARGET_ARM"
8a18b90c 9253 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9254 [(set_attr "conds" "use")
9255 (set_attr "length" "8")]
9256)
8a18b90c 9257
f7fbdd4a 9258(define_insn "*ifcompare_neg_move"
8a18b90c 9259 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9260 (if_then_else:SI
8fa3ba89 9261 (match_operator 5 "arm_comparison_operator"
8a18b90c 9262 [(match_operand:SI 3 "s_register_operand" "r,r")
9263 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9264 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9265 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9266 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9267 "TARGET_ARM"
8a18b90c 9268 "#"
8fa3ba89 9269 [(set_attr "conds" "clob")
9270 (set_attr "length" "8,12")]
9271)
8a18b90c 9272
9273(define_insn "*if_neg_move"
9274 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9275 (if_then_else:SI
8fa3ba89 9276 (match_operator 4 "arm_comparison_operator"
8a18b90c 9277 [(match_operand 3 "cc_register" "") (const_int 0)])
9278 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9279 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9280 "TARGET_ARM"
8a18b90c 9281 "@
9282 rsb%d4\\t%0, %2, #0
9283 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9284 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9285 [(set_attr "conds" "use")
9286 (set_attr "length" "4,8,8")]
9287)
9c08d1fa 9288
f7fbdd4a 9289(define_insn "*ifcompare_move_neg"
8a18b90c 9290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9291 (if_then_else:SI
8fa3ba89 9292 (match_operator 5 "arm_comparison_operator"
8a18b90c 9293 [(match_operand:SI 3 "s_register_operand" "r,r")
9294 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9295 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9296 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9297 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9298 "TARGET_ARM"
8a18b90c 9299 "#"
8fa3ba89 9300 [(set_attr "conds" "clob")
9301 (set_attr "length" "8,12")]
9302)
8a18b90c 9303
9304(define_insn "*if_move_neg"
9305 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9306 (if_then_else:SI
8fa3ba89 9307 (match_operator 4 "arm_comparison_operator"
8a18b90c 9308 [(match_operand 3 "cc_register" "") (const_int 0)])
9309 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9310 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9311 "TARGET_ARM"
8a18b90c 9312 "@
9313 rsb%D4\\t%0, %2, #0
9314 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9315 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9316 [(set_attr "conds" "use")
9317 (set_attr "length" "4,8,8")]
9318)
9c08d1fa 9319
f7fbdd4a 9320(define_insn "*arith_adjacentmem"
9c08d1fa 9321 [(set (match_operand:SI 0 "s_register_operand" "=r")
9322 (match_operator:SI 1 "shiftable_operator"
9323 [(match_operand:SI 2 "memory_operand" "m")
9324 (match_operand:SI 3 "memory_operand" "m")]))
9325 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9326 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9327 "*
215b30b3 9328 {
9329 rtx ldm[3];
9330 rtx arith[4];
94dee231 9331 rtx base_reg;
9332 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9333
215b30b3 9334 if (REGNO (operands[0]) > REGNO (operands[4]))
9335 {
9336 ldm[1] = operands[4];
9337 ldm[2] = operands[0];
9338 }
9339 else
9340 {
9341 ldm[1] = operands[0];
9342 ldm[2] = operands[4];
9343 }
94dee231 9344
9345 base_reg = XEXP (operands[2], 0);
9346
9347 if (!REG_P (base_reg))
9348 {
9349 val1 = INTVAL (XEXP (base_reg, 1));
9350 base_reg = XEXP (base_reg, 0);
9351 }
9352
9353 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9354 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9355
215b30b3 9356 arith[0] = operands[0];
9357 arith[3] = operands[1];
94dee231 9358
215b30b3 9359 if (val1 < val2)
9360 {
9361 arith[1] = ldm[1];
9362 arith[2] = ldm[2];
9363 }
9364 else
9365 {
9366 arith[1] = ldm[2];
9367 arith[2] = ldm[1];
9368 }
94dee231 9369
9370 ldm[0] = base_reg;
9371 if (val1 !=0 && val2 != 0)
215b30b3 9372 {
94dee231 9373 if (val1 == 4 || val2 == 4)
9374 /* Other val must be 8, since we know they are adjacent and neither
9375 is zero. */
9376 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
215b30b3 9377 else
94dee231 9378 {
9379 rtx ops[3];
9380
9381 ldm[0] = ops[0] = operands[4];
9382 ops[1] = base_reg;
9383 ops[2] = GEN_INT (val1);
9384 output_add_immediate (ops);
9385 if (val1 < val2)
9386 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9387 else
9388 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9389 }
215b30b3 9390 }
94dee231 9391 else if (val1 != 0)
215b30b3 9392 {
215b30b3 9393 if (val1 < val2)
9394 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9395 else
9396 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9397 }
9398 else
9399 {
215b30b3 9400 if (val1 < val2)
9401 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9402 else
9403 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9404 }
9405 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9406 return \"\";
9407 }"
9408 [(set_attr "length" "12")
9409 (set_attr "predicable" "yes")
a2cd141b 9410 (set_attr "type" "load1")]
215b30b3 9411)
9c08d1fa 9412
9413;; the arm can support extended pre-inc instructions
9414
9415;; In all these cases, we use operands 0 and 1 for the register being
9416;; incremented because those are the operands that local-alloc will
9417;; tie and these are the pair most likely to be tieable (and the ones
9418;; that will benefit the most).
9419
9420;; We reject the frame pointer if it occurs anywhere in these patterns since
9421;; elimination will cause too many headaches.
9422
f7fbdd4a 9423(define_insn "*strqi_preinc"
9c08d1fa 9424 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9425 (match_operand:SI 2 "index_operand" "rJ")))
9426 (match_operand:QI 3 "s_register_operand" "r"))
9427 (set (match_operand:SI 0 "s_register_operand" "=r")
9428 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9429 "TARGET_ARM
da45ccee 9430 && !arm_eliminable_register (operands[0])
9431 && !arm_eliminable_register (operands[1])
9432 && !arm_eliminable_register (operands[2])"
40dbec34 9433 "str%?b\\t%3, [%0, %2]!"
0d66636f 9434 [(set_attr "type" "store1")
9435 (set_attr "predicable" "yes")]
9436)
9c08d1fa 9437
f7fbdd4a 9438(define_insn "*strqi_predec"
9c08d1fa 9439 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9440 (match_operand:SI 2 "s_register_operand" "r")))
9441 (match_operand:QI 3 "s_register_operand" "r"))
9442 (set (match_operand:SI 0 "s_register_operand" "=r")
9443 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9444 "TARGET_ARM
da45ccee 9445 && !arm_eliminable_register (operands[0])
9446 && !arm_eliminable_register (operands[1])
9447 && !arm_eliminable_register (operands[2])"
40dbec34 9448 "str%?b\\t%3, [%0, -%2]!"
0d66636f 9449 [(set_attr "type" "store1")
9450 (set_attr "predicable" "yes")]
9451)
9c08d1fa 9452
f7fbdd4a 9453(define_insn "*loadqi_preinc"
9c08d1fa 9454 [(set (match_operand:QI 3 "s_register_operand" "=r")
9455 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9456 (match_operand:SI 2 "index_operand" "rJ"))))
9457 (set (match_operand:SI 0 "s_register_operand" "=r")
9458 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9459 "TARGET_ARM
da45ccee 9460 && !arm_eliminable_register (operands[0])
9461 && !arm_eliminable_register (operands[1])
9462 && !arm_eliminable_register (operands[2])"
40dbec34 9463 "ldr%?b\\t%3, [%0, %2]!"
a2cd141b 9464 [(set_attr "type" "load_byte")
0d66636f 9465 (set_attr "predicable" "yes")]
9466)
9c08d1fa 9467
f7fbdd4a 9468(define_insn "*loadqi_predec"
9c08d1fa 9469 [(set (match_operand:QI 3 "s_register_operand" "=r")
9470 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9471 (match_operand:SI 2 "s_register_operand" "r"))))
9472 (set (match_operand:SI 0 "s_register_operand" "=r")
9473 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9474 "TARGET_ARM
da45ccee 9475 && !arm_eliminable_register (operands[0])
9476 && !arm_eliminable_register (operands[1])
9477 && !arm_eliminable_register (operands[2])"
40dbec34 9478 "ldr%?b\\t%3, [%0, -%2]!"
a2cd141b 9479 [(set_attr "type" "load_byte")
0d66636f 9480 (set_attr "predicable" "yes")]
9481)
9c08d1fa 9482
f7fbdd4a 9483(define_insn "*loadqisi_preinc"
9c08d1fa 9484 [(set (match_operand:SI 3 "s_register_operand" "=r")
9485 (zero_extend:SI
9486 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9487 (match_operand:SI 2 "index_operand" "rJ")))))
9488 (set (match_operand:SI 0 "s_register_operand" "=r")
9489 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9490 "TARGET_ARM
da45ccee 9491 && !arm_eliminable_register (operands[0])
9492 && !arm_eliminable_register (operands[1])
9493 && !arm_eliminable_register (operands[2])"
40dbec34 9494 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
a2cd141b 9495 [(set_attr "type" "load_byte")
0d66636f 9496 (set_attr "predicable" "yes")]
9497)
9c08d1fa 9498
f7fbdd4a 9499(define_insn "*loadqisi_predec"
9c08d1fa 9500 [(set (match_operand:SI 3 "s_register_operand" "=r")
9501 (zero_extend:SI
9502 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9503 (match_operand:SI 2 "s_register_operand" "r")))))
9504 (set (match_operand:SI 0 "s_register_operand" "=r")
9505 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9506 "TARGET_ARM
da45ccee 9507 && !arm_eliminable_register (operands[0])
9508 && !arm_eliminable_register (operands[1])
9509 && !arm_eliminable_register (operands[2])"
40dbec34 9510 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
a2cd141b 9511 [(set_attr "type" "load_byte")
0d66636f 9512 (set_attr "predicable" "yes")]
9513)
9c08d1fa 9514
f7fbdd4a 9515(define_insn "*strsi_preinc"
9c08d1fa 9516 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9517 (match_operand:SI 2 "index_operand" "rJ")))
9518 (match_operand:SI 3 "s_register_operand" "r"))
9519 (set (match_operand:SI 0 "s_register_operand" "=r")
9520 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9521 "TARGET_ARM
da45ccee 9522 && !arm_eliminable_register (operands[0])
9523 && !arm_eliminable_register (operands[1])
9524 && !arm_eliminable_register (operands[2])"
40dbec34 9525 "str%?\\t%3, [%0, %2]!"
0d66636f 9526 [(set_attr "type" "store1")
9527 (set_attr "predicable" "yes")]
9528)
9c08d1fa 9529
cbd60e74 9530(define_insn "*strsi_predec"
9c08d1fa 9531 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9532 (match_operand:SI 2 "s_register_operand" "r")))
9533 (match_operand:SI 3 "s_register_operand" "r"))
9534 (set (match_operand:SI 0 "s_register_operand" "=r")
9535 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9536 "TARGET_ARM
da45ccee 9537 && !arm_eliminable_register (operands[0])
9538 && !arm_eliminable_register (operands[1])
9539 && !arm_eliminable_register (operands[2])"
40dbec34 9540 "str%?\\t%3, [%0, -%2]!"
0d66636f 9541 [(set_attr "type" "store1")
9542 (set_attr "predicable" "yes")]
9543)
9c08d1fa 9544
f7fbdd4a 9545(define_insn "*loadsi_preinc"
9c08d1fa 9546 [(set (match_operand:SI 3 "s_register_operand" "=r")
9547 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9548 (match_operand:SI 2 "index_operand" "rJ"))))
9549 (set (match_operand:SI 0 "s_register_operand" "=r")
9550 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9551 "TARGET_ARM
da45ccee 9552 && !arm_eliminable_register (operands[0])
9553 && !arm_eliminable_register (operands[1])
9554 && !arm_eliminable_register (operands[2])"
40dbec34 9555 "ldr%?\\t%3, [%0, %2]!"
a2cd141b 9556 [(set_attr "type" "load1")
0d66636f 9557 (set_attr "predicable" "yes")]
9558)
9c08d1fa 9559
f7fbdd4a 9560(define_insn "*loadsi_predec"
9c08d1fa 9561 [(set (match_operand:SI 3 "s_register_operand" "=r")
9562 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9563 (match_operand:SI 2 "s_register_operand" "r"))))
9564 (set (match_operand:SI 0 "s_register_operand" "=r")
9565 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9566 "TARGET_ARM
da45ccee 9567 && !arm_eliminable_register (operands[0])
9568 && !arm_eliminable_register (operands[1])
9569 && !arm_eliminable_register (operands[2])"
40dbec34 9570 "ldr%?\\t%3, [%0, -%2]!"
a2cd141b 9571 [(set_attr "type" "load1")
0d66636f 9572 (set_attr "predicable" "yes")]
9573)
9c08d1fa 9574
f7fbdd4a 9575(define_insn "*strqi_shiftpreinc"
9c08d1fa 9576 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9577 [(match_operand:SI 3 "s_register_operand" "r")
9578 (match_operand:SI 4 "const_shift_operand" "n")])
9579 (match_operand:SI 1 "s_register_operand" "0")))
9580 (match_operand:QI 5 "s_register_operand" "r"))
9581 (set (match_operand:SI 0 "s_register_operand" "=r")
9582 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9583 (match_dup 1)))]
cffb2a26 9584 "TARGET_ARM
da45ccee 9585 && !arm_eliminable_register (operands[0])
9586 && !arm_eliminable_register (operands[1])
9587 && !arm_eliminable_register (operands[3])"
87b22bf7 9588 "str%?b\\t%5, [%0, %3%S2]!"
0d66636f 9589 [(set_attr "type" "store1")
9590 (set_attr "predicable" "yes")]
9591)
9c08d1fa 9592
f7fbdd4a 9593(define_insn "*strqi_shiftpredec"
9c08d1fa 9594 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9595 (match_operator:SI 2 "shift_operator"
9596 [(match_operand:SI 3 "s_register_operand" "r")
9597 (match_operand:SI 4 "const_shift_operand" "n")])))
9598 (match_operand:QI 5 "s_register_operand" "r"))
9599 (set (match_operand:SI 0 "s_register_operand" "=r")
9600 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9601 (match_dup 4)])))]
cffb2a26 9602 "TARGET_ARM
da45ccee 9603 && !arm_eliminable_register (operands[0])
9604 && !arm_eliminable_register (operands[1])
9605 && !arm_eliminable_register (operands[3])"
87b22bf7 9606 "str%?b\\t%5, [%0, -%3%S2]!"
0d66636f 9607 [(set_attr "type" "store1")
9608 (set_attr "predicable" "yes")]
9609)
9c08d1fa 9610
f7fbdd4a 9611(define_insn "*loadqi_shiftpreinc"
9c08d1fa 9612 [(set (match_operand:QI 5 "s_register_operand" "=r")
9613 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9614 [(match_operand:SI 3 "s_register_operand" "r")
9615 (match_operand:SI 4 "const_shift_operand" "n")])
9616 (match_operand:SI 1 "s_register_operand" "0"))))
9617 (set (match_operand:SI 0 "s_register_operand" "=r")
9618 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9619 (match_dup 1)))]
cffb2a26 9620 "TARGET_ARM
da45ccee 9621 && !arm_eliminable_register (operands[0])
9622 && !arm_eliminable_register (operands[1])
9623 && !arm_eliminable_register (operands[3])"
87b22bf7 9624 "ldr%?b\\t%5, [%0, %3%S2]!"
a2cd141b 9625 [(set_attr "type" "load_byte")
0d66636f 9626 (set_attr "predicable" "yes")]
9627)
9c08d1fa 9628
f7fbdd4a 9629(define_insn "*loadqi_shiftpredec"
9c08d1fa 9630 [(set (match_operand:QI 5 "s_register_operand" "=r")
9631 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9632 (match_operator:SI 2 "shift_operator"
9633 [(match_operand:SI 3 "s_register_operand" "r")
9634 (match_operand:SI 4 "const_shift_operand" "n")]))))
9635 (set (match_operand:SI 0 "s_register_operand" "=r")
9636 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9637 (match_dup 4)])))]
cffb2a26 9638 "TARGET_ARM
da45ccee 9639 && !arm_eliminable_register (operands[0])
9640 && !arm_eliminable_register (operands[1])
9641 && !arm_eliminable_register (operands[3])"
87b22bf7 9642 "ldr%?b\\t%5, [%0, -%3%S2]!"
a2cd141b 9643 [(set_attr "type" "load_byte")
0d66636f 9644 (set_attr "predicable" "yes")]
9645)
9c08d1fa 9646
f7fbdd4a 9647(define_insn "*strsi_shiftpreinc"
9c08d1fa 9648 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9649 [(match_operand:SI 3 "s_register_operand" "r")
9650 (match_operand:SI 4 "const_shift_operand" "n")])
9651 (match_operand:SI 1 "s_register_operand" "0")))
9652 (match_operand:SI 5 "s_register_operand" "r"))
9653 (set (match_operand:SI 0 "s_register_operand" "=r")
9654 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9655 (match_dup 1)))]
cffb2a26 9656 "TARGET_ARM
da45ccee 9657 && !arm_eliminable_register (operands[0])
9658 && !arm_eliminable_register (operands[1])
9659 && !arm_eliminable_register (operands[3])"
87b22bf7 9660 "str%?\\t%5, [%0, %3%S2]!"
0d66636f 9661 [(set_attr "type" "store1")
9662 (set_attr "predicable" "yes")]
9663)
9c08d1fa 9664
f7fbdd4a 9665(define_insn "*strsi_shiftpredec"
9c08d1fa 9666 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9667 (match_operator:SI 2 "shift_operator"
9668 [(match_operand:SI 3 "s_register_operand" "r")
9669 (match_operand:SI 4 "const_shift_operand" "n")])))
9670 (match_operand:SI 5 "s_register_operand" "r"))
9671 (set (match_operand:SI 0 "s_register_operand" "=r")
9672 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9673 (match_dup 4)])))]
cffb2a26 9674 "TARGET_ARM
da45ccee 9675 && !arm_eliminable_register (operands[0])
9676 && !arm_eliminable_register (operands[1])
9677 && !arm_eliminable_register (operands[3])"
87b22bf7 9678 "str%?\\t%5, [%0, -%3%S2]!"
0d66636f 9679 [(set_attr "type" "store1")
9680 (set_attr "predicable" "yes")]
9681)
9c08d1fa 9682
cbd60e74 9683(define_insn "*loadsi_shiftpreinc"
9c08d1fa 9684 [(set (match_operand:SI 5 "s_register_operand" "=r")
9685 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9686 [(match_operand:SI 3 "s_register_operand" "r")
9687 (match_operand:SI 4 "const_shift_operand" "n")])
9688 (match_operand:SI 1 "s_register_operand" "0"))))
9689 (set (match_operand:SI 0 "s_register_operand" "=r")
9690 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9691 (match_dup 1)))]
cffb2a26 9692 "TARGET_ARM
da45ccee 9693 && !arm_eliminable_register (operands[0])
9694 && !arm_eliminable_register (operands[1])
9695 && !arm_eliminable_register (operands[3])"
87b22bf7 9696 "ldr%?\\t%5, [%0, %3%S2]!"
a2cd141b 9697 [(set_attr "type" "load1")
0d66636f 9698 (set_attr "predicable" "yes")]
9699)
9c08d1fa 9700
cbd60e74 9701(define_insn "*loadsi_shiftpredec"
9c08d1fa 9702 [(set (match_operand:SI 5 "s_register_operand" "=r")
9703 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9704 (match_operator:SI 2 "shift_operator"
9705 [(match_operand:SI 3 "s_register_operand" "r")
9706 (match_operand:SI 4 "const_shift_operand" "n")]))))
9707 (set (match_operand:SI 0 "s_register_operand" "=r")
9708 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9709 (match_dup 4)])))]
cffb2a26 9710 "TARGET_ARM
da45ccee 9711 && !arm_eliminable_register (operands[0])
9712 && !arm_eliminable_register (operands[1])
9713 && !arm_eliminable_register (operands[3])"
87b22bf7 9714 "ldr%?\\t%5, [%0, -%3%S2]!"
a2cd141b 9715 [(set_attr "type" "load1")
0d66636f 9716 (set_attr "predicable" "yes")])
9c08d1fa 9717
9c08d1fa 9718; It can also support extended post-inc expressions, but combine doesn't
9719; try these....
9720; It doesn't seem worth adding peepholes for anything but the most common
9721; cases since, unlike combine, the increment must immediately follow the load
9722; for this pattern to match.
fc40f3ac 9723; We must watch to see that the source/destination register isn't also the
9724; same as the base address register, and that if the index is a register,
9725; that it is not the same as the base address register. In such cases the
e3e08e7f 9726; instruction that we would generate would have UNPREDICTABLE behavior so
fc40f3ac 9727; we cannot use it.
9c08d1fa 9728
9729(define_peephole
9730 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9731 (match_operand:QI 2 "s_register_operand" "r"))
9732 (set (match_dup 0)
9733 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 9734 "TARGET_ARM
9735 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9736 && (GET_CODE (operands[1]) != REG
9737 || (REGNO (operands[1]) != REGNO (operands[0])))"
9738 "str%?b\\t%2, [%0], %1"
9739)
9c08d1fa 9740
9741(define_peephole
9742 [(set (match_operand:QI 0 "s_register_operand" "=r")
9743 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9744 (set (match_dup 1)
9745 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
fc40f3ac 9746 "TARGET_ARM
9747 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 9748 && (GET_CODE (operands[2]) != REG
9749 || REGNO(operands[0]) != REGNO (operands[2]))"
9750 "ldr%?b\\t%0, [%1], %2"
9751)
9c08d1fa 9752
9753(define_peephole
9754 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9755 (match_operand:SI 2 "s_register_operand" "r"))
9756 (set (match_dup 0)
9757 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 9758 "TARGET_ARM
9759 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9760 && (GET_CODE (operands[1]) != REG
9761 || (REGNO (operands[1]) != REGNO (operands[0])))"
9762 "str%?\\t%2, [%0], %1"
9763)
9c08d1fa 9764
9c08d1fa 9765(define_peephole
9766 [(set (match_operand:SI 0 "s_register_operand" "=r")
9767 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9768 (set (match_dup 1)
9769 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
cffb2a26 9770 "TARGET_ARM
fc40f3ac 9771 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 9772 && (GET_CODE (operands[2]) != REG
9773 || REGNO(operands[0]) != REGNO (operands[2]))"
9774 "ldr%?\\t%0, [%1], %2"
9775)
9c08d1fa 9776
c7597b5d 9777(define_peephole
9778 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9779 (match_operand:SI 1 "index_operand" "rJ")))
9780 (match_operand:QI 2 "s_register_operand" "r"))
9781 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
fc40f3ac 9782 "TARGET_ARM
9783 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9784 && (GET_CODE (operands[1]) != REG
9785 || (REGNO (operands[1]) != REGNO (operands[0])))"
9786 "str%?b\\t%2, [%0, %1]!"
9787)
c7597b5d 9788
9789(define_peephole
9790 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9791 [(match_operand:SI 0 "s_register_operand" "r")
87b22bf7 9792 (match_operand:SI 1 "const_int_operand" "n")])
c7597b5d 9793 (match_operand:SI 2 "s_register_operand" "+r")))
9794 (match_operand:QI 3 "s_register_operand" "r"))
9795 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9796 (match_dup 2)))]
fc40f3ac 9797 "TARGET_ARM
9798 && (REGNO (operands[3]) != REGNO (operands[2]))
9799 && (REGNO (operands[0]) != REGNO (operands[2]))"
215b30b3 9800 "str%?b\\t%3, [%2, %0%S4]!"
9801)
c7597b5d 9802
9c08d1fa 9803; This pattern is never tried by combine, so do it as a peephole
9804
a0f94409 9805(define_peephole2
372575c7 9806 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9807 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9808 (set (reg:CC CC_REGNUM)
aea4c774 9809 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9810 "TARGET_ARM"
a0f94409 9811 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9812 (set (match_dup 0) (match_dup 1))])]
9813 ""
0d66636f 9814)
9c08d1fa 9815
675d848d 9816; Peepholes to spot possible load- and store-multiples, if the ordering is
9817; reversed, check that the memory references aren't volatile.
9c08d1fa 9818
9819(define_peephole
9820 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9821 (match_operand:SI 4 "memory_operand" "m"))
9822 (set (match_operand:SI 1 "s_register_operand" "=r")
9823 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 9824 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9825 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 9826 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 9827 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 9828 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9829 "*
9830 return emit_ldm_seq (operands, 4);
215b30b3 9831 "
9832)
9c08d1fa 9833
9834(define_peephole
9835 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9836 (match_operand:SI 3 "memory_operand" "m"))
9837 (set (match_operand:SI 1 "s_register_operand" "=r")
9838 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 9839 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9840 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 9841 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9842 "*
9843 return emit_ldm_seq (operands, 3);
215b30b3 9844 "
9845)
9c08d1fa 9846
9847(define_peephole
9848 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9849 (match_operand:SI 2 "memory_operand" "m"))
9850 (set (match_operand:SI 1 "s_register_operand" "=r")
9851 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 9852 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9853 "*
9854 return emit_ldm_seq (operands, 2);
215b30b3 9855 "
9856)
9c08d1fa 9857
9858(define_peephole
aea4c774 9859 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 9860 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9861 (set (match_operand:SI 5 "memory_operand" "=m")
9862 (match_operand:SI 1 "s_register_operand" "r"))
9863 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 9864 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 9865 (set (match_operand:SI 7 "memory_operand" "=m")
9866 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 9867 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9868 "*
9869 return emit_stm_seq (operands, 4);
215b30b3 9870 "
9871)
9c08d1fa 9872
9873(define_peephole
aea4c774 9874 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 9875 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9876 (set (match_operand:SI 4 "memory_operand" "=m")
9877 (match_operand:SI 1 "s_register_operand" "r"))
9878 (set (match_operand:SI 5 "memory_operand" "=m")
9879 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 9880 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9881 "*
9882 return emit_stm_seq (operands, 3);
215b30b3 9883 "
9884)
9c08d1fa 9885
9886(define_peephole
aea4c774 9887 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 9888 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9889 (set (match_operand:SI 3 "memory_operand" "=m")
9890 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 9891 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9892 "*
9893 return emit_stm_seq (operands, 2);
215b30b3 9894 "
9895)
9c08d1fa 9896
9c08d1fa 9897(define_split
9898 [(set (match_operand:SI 0 "s_register_operand" "")
9899 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9900 (const_int 0))
8fa3ba89 9901 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9902 [(match_operand:SI 3 "s_register_operand" "")
9903 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9904 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9905 "TARGET_ARM"
9c08d1fa 9906 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9907 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9908 (match_dup 5)))]
215b30b3 9909 ""
9910)
9c08d1fa 9911
aea4c774 9912;; This split can be used because CC_Z mode implies that the following
9913;; branch will be an equality, or an unsigned inequality, so the sign
9914;; extension is not needed.
9c08d1fa 9915
aea4c774 9916(define_split
bd5b4116 9917 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9918 (compare:CC_Z
9919 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9920 (const_int 24))
aea4c774 9921 (match_operand 1 "const_int_operand" "")))
9922 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9923 "TARGET_ARM
9924 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9925 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9926 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9927 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9928 "
9c08d1fa 9929 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9930 "
9931)
9c08d1fa 9932
87b22bf7 9933(define_expand "prologue"
9934 [(clobber (const_int 0))]
cffb2a26 9935 "TARGET_EITHER"
9936 "if (TARGET_ARM)
9937 arm_expand_prologue ();
9938 else
9939 thumb_expand_prologue ();
87b22bf7 9940 DONE;
cffb2a26 9941 "
9942)
87b22bf7 9943
56d27660 9944(define_expand "epilogue"
4c44712e 9945 [(clobber (const_int 0))]
cffb2a26 9946 "TARGET_EITHER"
56d27660 9947 "
4c44712e 9948 if (current_function_calls_eh_return)
9949 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
cffb2a26 9950 if (TARGET_THUMB)
9951 thumb_expand_epilogue ();
9952 else if (USE_RETURN_INSN (FALSE))
56d27660 9953 {
9954 emit_jump_insn (gen_return ());
9955 DONE;
9956 }
cffb2a26 9957 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9958 gen_rtvec (1,
9959 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9960 VUNSPEC_EPILOGUE));
cffb2a26 9961 DONE;
9962 "
9963)
56d27660 9964
ef5651d0 9965;; Note - although unspec_volatile's USE all hard registers,
9966;; USEs are ignored after relaod has completed. Thus we need
9967;; to add an unspec of the link register to ensure that flow
9968;; does not think that it is unused by the sibcall branch that
9969;; will replace the standard function epilogue.
1c494086 9970(define_insn "sibcall_epilogue"
ef5651d0 9971 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9972 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
1c494086 9973 "TARGET_ARM"
9974 "*
ffc9d00c 9975 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9976 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9977 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9978 "
9979;; Length is absolute worst case
9980 [(set_attr "length" "44")
defc47cf 9981 (set_attr "type" "block")
9982 ;; We don't clobber the conditions, but the potential length of this
9983 ;; operation is sufficient to make conditionalizing the sequence
9984 ;; unlikely to be profitable.
9985 (set_attr "conds" "clob")]
1c494086 9986)
9987
cffb2a26 9988(define_insn "*epilogue_insns"
e1159bbe 9989 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9990 "TARGET_EITHER"
56d27660 9991 "*
cffb2a26 9992 if (TARGET_ARM)
ffc9d00c 9993 return arm_output_epilogue (NULL);
cffb2a26 9994 else /* TARGET_THUMB */
9995 return thumb_unexpanded_epilogue ();
9996 "
215b30b3 9997 ; Length is absolute worst case
cffb2a26 9998 [(set_attr "length" "44")
defc47cf 9999 (set_attr "type" "block")
10000 ;; We don't clobber the conditions, but the potential length of this
10001 ;; operation is sufficient to make conditionalizing the sequence
10002 ;; unlikely to be profitable.
10003 (set_attr "conds" "clob")]
cffb2a26 10004)
10005
10006(define_expand "eh_epilogue"
7db9af5d 10007 [(use (match_operand:SI 0 "register_operand" ""))
10008 (use (match_operand:SI 1 "register_operand" ""))
10009 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 10010 "TARGET_EITHER"
10011 "
215b30b3 10012 {
10013 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10014 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10015 {
10016 rtx ra = gen_rtx_REG (Pmode, 2);
10017
10018 emit_move_insn (ra, operands[2]);
10019 operands[2] = ra;
10020 }
5cf3595a 10021 /* This is a hack -- we may have crystalized the function type too
10022 early. */
10023 cfun->machine->func_type = 0;
215b30b3 10024 }"
10025)
56d27660 10026
9c08d1fa 10027;; This split is only used during output to reduce the number of patterns
10028;; that need assembler instructions adding to them. We allowed the setting
10029;; of the conditions to be implicit during rtl generation so that
10030;; the conditional compare patterns would work. However this conflicts to
8a18b90c 10031;; some extent with the conditional data operations, so we have to split them
9c08d1fa 10032;; up again here.
10033
10034(define_split
10035 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10036 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10037 [(match_operand 2 "" "") (match_operand 3 "" "")])
10038 (match_dup 0)
10039 (match_operand 4 "" "")))
bd5b4116 10040 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10041 "TARGET_ARM && reload_completed"
8fa3ba89 10042 [(set (match_dup 5) (match_dup 6))
10043 (cond_exec (match_dup 7)
10044 (set (match_dup 0) (match_dup 4)))]
10045 "
10046 {
10047 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10048 operands[2], operands[3]);
10049 enum rtx_code rc = GET_CODE (operands[1]);
10050
bd5b4116 10051 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10052 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10053 if (mode == CCFPmode || mode == CCFPEmode)
10054 rc = reverse_condition_maybe_unordered (rc);
10055 else
10056 rc = reverse_condition (rc);
10057
10058 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10059 }"
10060)
10061
10062(define_split
10063 [(set (match_operand:SI 0 "s_register_operand" "")
10064 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10065 [(match_operand 2 "" "") (match_operand 3 "" "")])
10066 (match_operand 4 "" "")
10067 (match_dup 0)))
bd5b4116 10068 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10069 "TARGET_ARM && reload_completed"
8fa3ba89 10070 [(set (match_dup 5) (match_dup 6))
10071 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10072 (set (match_dup 0) (match_dup 4)))]
10073 "
10074 {
10075 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10076 operands[2], operands[3]);
10077
bd5b4116 10078 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10079 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10080 }"
10081)
10082
10083(define_split
10084 [(set (match_operand:SI 0 "s_register_operand" "")
10085 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 10086 [(match_operand 2 "" "") (match_operand 3 "" "")])
10087 (match_operand 4 "" "")
10088 (match_operand 5 "" "")))
bd5b4116 10089 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10090 "TARGET_ARM && reload_completed"
8fa3ba89 10091 [(set (match_dup 6) (match_dup 7))
10092 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10093 (set (match_dup 0) (match_dup 4)))
10094 (cond_exec (match_dup 8)
10095 (set (match_dup 0) (match_dup 5)))]
10096 "
10097 {
10098 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10099 operands[2], operands[3]);
10100 enum rtx_code rc = GET_CODE (operands[1]);
10101
bd5b4116 10102 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 10103 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10104 if (mode == CCFPmode || mode == CCFPEmode)
10105 rc = reverse_condition_maybe_unordered (rc);
10106 else
10107 rc = reverse_condition (rc);
10108
10109 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10110 }"
10111)
10112
cffb2a26 10113(define_split
10114 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 10115 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 10116 [(match_operand:SI 2 "s_register_operand" "")
10117 (match_operand:SI 3 "arm_add_operand" "")])
10118 (match_operand:SI 4 "arm_rhs_operand" "")
10119 (not:SI
10120 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 10121 (clobber (reg:CC CC_REGNUM))]
ac8b093b 10122 "TARGET_ARM && reload_completed"
cffb2a26 10123 [(set (match_dup 6) (match_dup 7))
f6c53574 10124 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10125 (set (match_dup 0) (match_dup 4)))
10126 (cond_exec (match_dup 8)
10127 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 10128 "
215b30b3 10129 {
10130 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10131 operands[2], operands[3]);
f6c53574 10132 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 10133
bd5b4116 10134 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 10135 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 10136 if (mode == CCFPmode || mode == CCFPEmode)
10137 rc = reverse_condition_maybe_unordered (rc);
10138 else
10139 rc = reverse_condition (rc);
10140
10141 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 10142 }"
10143)
cffb2a26 10144
10145(define_insn "*cond_move_not"
10146 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 10147 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 10148 [(match_operand 3 "cc_register" "") (const_int 0)])
10149 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10150 (not:SI
10151 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10152 "TARGET_ARM"
10153 "@
10154 mvn%D4\\t%0, %2
10155 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 10156 [(set_attr "conds" "use")
10157 (set_attr "length" "4,8")]
10158)
cffb2a26 10159
9c08d1fa 10160;; The next two patterns occur when an AND operation is followed by a
10161;; scc insn sequence
10162
f7fbdd4a 10163(define_insn "*sign_extract_onebit"
9c08d1fa 10164 [(set (match_operand:SI 0 "s_register_operand" "=r")
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 (\"ands\\t%0, %1, %2\", operands);
10173 return \"mvnne\\t%0, #0\";
10174 "
10175 [(set_attr "conds" "clob")
10176 (set_attr "length" "8")]
10177)
9c08d1fa 10178
f7fbdd4a 10179(define_insn "*not_signextract_onebit"
9c08d1fa 10180 [(set (match_operand:SI 0 "s_register_operand" "=r")
10181 (not:SI
10182 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10183 (const_int 1)
ed750274 10184 (match_operand:SI 2 "const_int_operand" "n"))))
10185 (clobber (reg:CC CC_REGNUM))]
cffb2a26 10186 "TARGET_ARM"
9c08d1fa 10187 "*
0d66636f 10188 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10189 output_asm_insn (\"tst\\t%1, %2\", operands);
10190 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10191 return \"movne\\t%0, #0\";
10192 "
10193 [(set_attr "conds" "clob")
10194 (set_attr "length" "12")]
10195)
87b22bf7 10196
0d66636f 10197;; Push multiple registers to the stack. Registers are in parallel (use ...)
10198;; expressions. For simplicity, the first register is also in the unspec
10199;; part.
f7fbdd4a 10200(define_insn "*push_multi"
87b22bf7 10201 [(match_parallel 2 "multi_register_push"
10202 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10203 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10204 UNSPEC_PUSH_MULT))])]
cffb2a26 10205 "TARGET_ARM"
87b22bf7 10206 "*
215b30b3 10207 {
10208 int num_saves = XVECLEN (operands[2], 0);
ed593f11 10209
215b30b3 10210 /* For the StrongARM at least it is faster to
10211 use STR to store only a single register. */
6079f055 10212 if (num_saves == 1)
215b30b3 10213 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10214 else
10215 {
10216 int i;
10217 char pattern[100];
ed593f11 10218
215b30b3 10219 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10220
6079f055 10221 for (i = 1; i < num_saves; i++)
215b30b3 10222 {
10223 strcat (pattern, \", %|\");
10224 strcat (pattern,
10225 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10226 }
10227
10228 strcat (pattern, \"}\");
10229 output_asm_insn (pattern, operands);
10230 }
10231
10232 return \"\";
10233 }"
10234 [(set_attr "type" "store4")]
10235)
f7fbdd4a 10236
4c58c898 10237(define_insn "stack_tie"
10238 [(set (mem:BLK (scratch))
10239 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10240 (match_operand:SI 1 "s_register_operand" "r")]
10241 UNSPEC_PRLG_STK))]
10242 ""
10243 ""
10244 [(set_attr "length" "0")]
10245)
10246
3398e91d 10247;; Similarly for the floating point registers
7b1d2fc4 10248(define_insn "*push_fp_multi"
10249 [(match_parallel 2 "multi_register_push"
10250 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 10251 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10252 UNSPEC_PUSH_MULT))])]
a2cd141b 10253 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 10254 "*
215b30b3 10255 {
10256 char pattern[100];
7b1d2fc4 10257
215b30b3 10258 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10259 output_asm_insn (pattern, operands);
10260 return \"\";
10261 }"
10262 [(set_attr "type" "f_store")]
10263)
7b1d2fc4 10264
f7fbdd4a 10265;; Special patterns for dealing with the constant pool
10266
cffb2a26 10267(define_insn "align_4"
e1159bbe 10268 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 10269 "TARGET_EITHER"
f7fbdd4a 10270 "*
cffb2a26 10271 assemble_align (32);
f7fbdd4a 10272 return \"\";
cffb2a26 10273 "
10274)
f7fbdd4a 10275
755eb2b4 10276(define_insn "align_8"
10277 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 10278 "TARGET_EITHER"
755eb2b4 10279 "*
10280 assemble_align (64);
10281 return \"\";
10282 "
10283)
10284
cffb2a26 10285(define_insn "consttable_end"
e1159bbe 10286 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10287 "TARGET_EITHER"
f7fbdd4a 10288 "*
cffb2a26 10289 making_const_table = FALSE;
f7fbdd4a 10290 return \"\";
cffb2a26 10291 "
10292)
f7fbdd4a 10293
cffb2a26 10294(define_insn "consttable_1"
e1159bbe 10295 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
cffb2a26 10296 "TARGET_THUMB"
f7fbdd4a 10297 "*
cffb2a26 10298 making_const_table = TRUE;
09d688ff 10299 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10300 assemble_zeros (3);
f7fbdd4a 10301 return \"\";
cffb2a26 10302 "
10303 [(set_attr "length" "4")]
10304)
f7fbdd4a 10305
cffb2a26 10306(define_insn "consttable_2"
e1159bbe 10307 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
cffb2a26 10308 "TARGET_THUMB"
f7fbdd4a 10309 "*
cffb2a26 10310 making_const_table = TRUE;
09d688ff 10311 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10312 assemble_zeros (2);
f7fbdd4a 10313 return \"\";
cffb2a26 10314 "
10315 [(set_attr "length" "4")]
10316)
10317
10318(define_insn "consttable_4"
e1159bbe 10319 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10320 "TARGET_EITHER"
10321 "*
10322 {
10323 making_const_table = TRUE;
10324 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10325 {
10326 case MODE_FLOAT:
10327 {
badfe841 10328 REAL_VALUE_TYPE r;
10329 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10330 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10331 break;
10332 }
10333 default:
09d688ff 10334 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 10335 break;
10336 }
10337 return \"\";
10338 }"
10339 [(set_attr "length" "4")]
10340)
10341
10342(define_insn "consttable_8"
e1159bbe 10343 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10344 "TARGET_EITHER"
10345 "*
10346 {
10347 making_const_table = TRUE;
10348 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10349 {
10350 case MODE_FLOAT:
10351 {
badfe841 10352 REAL_VALUE_TYPE r;
10353 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10354 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10355 break;
10356 }
10357 default:
09d688ff 10358 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10359 break;
10360 }
10361 return \"\";
10362 }"
10363 [(set_attr "length" "8")]
10364)
10365
10366;; Miscellaneous Thumb patterns
10367
fd957ef3 10368(define_expand "tablejump"
7db9af5d 10369 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10370 (use (label_ref (match_operand 1 "" "")))])]
10371 "TARGET_THUMB"
10372 "
10373 if (flag_pic)
10374 {
10375 /* Hopefully, CSE will eliminate this copy. */
10376 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10377 rtx reg2 = gen_reg_rtx (SImode);
10378
10379 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10380 operands[0] = reg2;
10381 }
10382 "
10383)
10384
f1039640 10385;; NB never uses BX.
fd957ef3 10386(define_insn "*thumb_tablejump"
cffb2a26 10387 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10388 (use (label_ref (match_operand 1 "" "")))]
10389 "TARGET_THUMB"
fd957ef3 10390 "mov\\t%|pc, %0"
cffb2a26 10391 [(set_attr "length" "2")]
10392)
0d66636f 10393
331beb1a 10394;; V5 Instructions,
10395
8f4be2be 10396(define_insn "clzsi2"
10397 [(set (match_operand:SI 0 "s_register_operand" "=r")
10398 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
e1159bbe 10399 "TARGET_ARM && arm_arch5"
ee7cbe0e 10400 "clz%?\\t%0, %1"
10401 [(set_attr "predicable" "yes")])
331beb1a 10402
e1159bbe 10403(define_expand "ffssi2"
10404 [(set (match_operand:SI 0 "s_register_operand" "")
10405 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10406 "TARGET_ARM && arm_arch5"
10407 "
10408 {
10409 rtx t1, t2, t3;
10410
10411 t1 = gen_reg_rtx (SImode);
10412 t2 = gen_reg_rtx (SImode);
10413 t3 = gen_reg_rtx (SImode);
10414
10415 emit_insn (gen_negsi2 (t1, operands[1]));
10416 emit_insn (gen_andsi3 (t2, operands[1], t1));
8f4be2be 10417 emit_insn (gen_clzsi2 (t3, t2));
e1159bbe 10418 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10419 DONE;
10420 }"
10421)
10422
8f4be2be 10423(define_expand "ctzsi2"
10424 [(set (match_operand:SI 0 "s_register_operand" "")
10425 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10426 "TARGET_ARM && arm_arch5"
10427 "
10428 {
10429 rtx t1, t2, t3;
10430
10431 t1 = gen_reg_rtx (SImode);
10432 t2 = gen_reg_rtx (SImode);
10433 t3 = gen_reg_rtx (SImode);
10434
10435 emit_insn (gen_negsi2 (t1, operands[1]));
10436 emit_insn (gen_andsi3 (t2, operands[1], t1));
10437 emit_insn (gen_clzsi2 (t3, t2));
10438 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10439 DONE;
10440 }"
10441)
10442
e1159bbe 10443;; V5E instructions.
331beb1a 10444
10445(define_insn "prefetch"
f4e79814 10446 [(prefetch (match_operand:SI 0 "address_operand" "p")
10447 (match_operand:SI 1 "" "")
10448 (match_operand:SI 2 "" ""))]
e1159bbe 10449 "TARGET_ARM && arm_arch5e"
bcb7a8f6 10450 "pld\\t%a0")
331beb1a 10451
0d66636f 10452;; General predication pattern
10453
10454(define_cond_exec
10455 [(match_operator 0 "arm_comparison_operator"
10456 [(match_operand 1 "cc_register" "")
10457 (const_int 0)])]
10458 "TARGET_ARM"
10459 ""
10460)
10461
063a05c7 10462(define_insn "prologue_use"
10463 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10464 ""
10465 "%@ %0 needed for prologue"
10466)
7db9af5d 10467
4c44712e 10468
10469;; Patterns for exception handling
10470
10471(define_expand "eh_return"
10472 [(use (match_operand 0 "general_operand" ""))]
10473 "TARGET_EITHER"
10474 "
10475 {
10476 if (TARGET_ARM)
10477 emit_insn (gen_arm_eh_return (operands[0]));
10478 else
10479 emit_insn (gen_thumb_eh_return (operands[0]));
10480 DONE;
10481 }"
10482)
10483
10484;; We can't expand this before we know where the link register is stored.
10485(define_insn_and_split "arm_eh_return"
10486 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10487 VUNSPEC_EH_RETURN)
10488 (clobber (match_scratch:SI 1 "=&r"))]
10489 "TARGET_ARM"
10490 "#"
10491 "&& reload_completed"
10492 [(const_int 0)]
10493 "
10494 {
10495 arm_set_return_address (operands[0], operands[1]);
10496 DONE;
10497 }"
10498)
10499
10500(define_insn_and_split "thumb_eh_return"
10501 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10502 VUNSPEC_EH_RETURN)
10503 (clobber (match_scratch:SI 1 "=&l"))]
10504 "TARGET_THUMB"
10505 "#"
10506 "&& reload_completed"
10507 [(const_int 0)]
10508 "
10509 {
10510 thumb_set_return_address (operands[0], operands[1]);
10511 DONE;
10512 }"
10513)
10514
7db9af5d 10515;; Load the FPA co-processor patterns
10516(include "fpa.md")
10517;; Load the Maverick co-processor patterns
10518(include "cirrus.md")
755eb2b4 10519;; Load the Intel Wireless Multimedia Extension patterns
10520(include "iwmmxt.md")
a2cd141b 10521;; Load the VFP co-processor patterns
10522(include "vfp.md")
10523