]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
PR c++/9373
[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,
27da10cf 3;; 2001, 2002, 2003 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
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
38 (LAST_ARM_REGNUM 15)
39 ]
40)
41
9c08d1fa 42;; UNSPEC Usage:
8a18b90c 43;; Note: sin and cos are no-longer used.
e1159bbe 44
45(define_constants
46 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
47 ; operand 0 is the result,
48 ; operand 1 the parameter.
49 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
53 ; operand 0 is the first register,
54 ; subsequent registers are in parallel (use ...)
55 ; expressions.
56 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
57 ; usage, that is, we will add the pic_register
58 ; value to it before trying to dereference it.
59 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
60 ; being scheduled before the stack adjustment insn.
063a05c7 61 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
62 ; this unspec is used to prevent the deletion of
63 ; instructions setting registers for EH handling
64 ; and stack frame generation. Operand 0 is the
65 ; register to "use".
68121397 66 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
e1159bbe 67 ]
68)
69
215b30b3 70;; UNSPEC_VOLATILE Usage:
e1159bbe 71
72(define_constants
73 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
74 ; insn in the code.
75 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
76 ; instruction epilogue sequence that isn't expanded
77 ; into normal RTL. Used for both normal and sibcall
78 ; epilogues.
79 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
80 ; for inlined constants.
81 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
82 ; table.
83 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
84 ; an 8-bit object.
85 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
86 ; a 16-bit object.
87 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
88 ; a 32-bit object.
89 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
90 ; a 64-bit object.
e1159bbe 91 ]
92)
b11cae9e 93\f
e1159bbe 94;;---------------------------------------------------------------------------
9c08d1fa 95;; Attributes
96
215b30b3 97; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
98; generating ARM code. This is used to control the length of some insn
99; patterns that share the same RTL in both ARM and Thumb code.
1c494086 100(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 101
f7fbdd4a 102; PROG_MODE attribute is used to determine whether condition codes are
103; clobbered by a call insn: they are if in prog32 mode. This is controlled
104; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
105(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
9c08d1fa 106
215b30b3 107; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
108; scheduling decisions for the load unit and the multiplier.
9888ad6d 109(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
9c08d1fa 110
331beb1a 111;; Operand number of an input operand that is shifted. Zero if the
112;; given instruction does not shift one of its input operands.
113(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
114(define_attr "shift" "" (const_int 0))
115
3d91c5d6 116; Floating Point Unit. If we only have floating point emulation, then there
117; is no point in scheduling the floating point insns. (Well, for best
118; performance we should try and group them together).
f7fbdd4a 119(define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 120
094e994f 121; LENGTH of an instruction (in bytes)
122(define_attr "length" "" (const_int 4))
9c08d1fa 123
56d27660 124; POOL_RANGE is how far away from a constant pool entry that this insn
125; can be placed. If the distance is zero, then this insn will never
126; reference the pool.
cffb2a26 127; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
128; before its address.
56d27660 129(define_attr "pool_range" "" (const_int 0))
cffb2a26 130(define_attr "neg_pool_range" "" (const_int 0))
56d27660 131
215b30b3 132; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 133; If such an insn references the pool, then we have no way of knowing how,
134; so use the most conservative value for pool_range.
9c08d1fa 135(define_asm_attributes
4d7a8451 136 [(set_attr "conds" "clob")
137 (set_attr "length" "4")
138 (set_attr "pool_range" "250")])
9c08d1fa 139
140; TYPE attribute is used to detect floating point instructions which, if
141; running on a co-processor can run in parallel with other, basic instructions
142; If write-buffer scheduling is enabled then it can also be used in the
143; scheduling of writes.
144
145; Classification of each insn
146; normal any data instruction that doesn't hit memory or fp regs
f7fbdd4a 147; mult a multiply instruction
9c08d1fa 148; block blockage insn, this blocks all functional units
149; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 150; fdivd DFmode floating point division
151; fdivs SFmode floating point division
152; fmul Floating point multiply
153; ffmul Fast floating point multiply
154; farith Floating point arithmetic (4 cycle)
155; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 156; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 157; even on a machine with an fpa.
9c08d1fa 158; f_load a floating point load from memory
159; f_store a floating point store to memory
160; f_mem_r a transfer of a floating point register to a real reg via mem
161; r_mem_f the reverse of f_mem_r
162; f_2_r fast transfer float to arm (no memory needed)
163; r_2_f fast transfer arm to float
164; call a subroutine call
165; load any load from memory
166; store1 store 1 word to memory from arm registers
167; store2 store 2 words
168; store3 store 3 words
169; store4 store 4 words
2c6c7d8b 170; Additions for Cirrus Maverick co-processor:
171; mav_farith Floating point arithmetic (4 cycle)
172; mav_dmult Double multiplies (7 cycle)
9c08d1fa 173;
174(define_attr "type"
2c6c7d8b 175 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult"
9c08d1fa 176 (const_string "normal"))
177
9888ad6d 178; Load scheduling, set from the arm_ld_sched variable
457275b6 179; initialized by arm_override_options()
9888ad6d 180(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 181
f7fbdd4a 182; condition codes: this one is used by final_prescan_insn to speed up
183; conditionalizing instructions. It saves having to scan the rtl to see if
184; it uses or alters the condition codes.
215b30b3 185;
f7fbdd4a 186; USE means that the condition codes are used by the insn in the process of
215b30b3 187; outputting code, this means (at present) that we can't use the insn in
188; inlined branches
189;
f7fbdd4a 190; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 191; well defined manner.
192;
f7fbdd4a 193; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 194; they are altered at all
195;
8fa3ba89 196; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 197; instruction (UNEQ and LTGT). These cannot be predicated.
198;
f7fbdd4a 199; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 200; output of this insn
f7fbdd4a 201
202(define_attr "conds" "use,set,clob,jump_clob,nocond"
203 (if_then_else (eq_attr "type" "call")
204 (if_then_else (eq_attr "prog_mode" "prog32")
205 (const_string "clob") (const_string "nocond"))
206 (const_string "nocond")))
207
215b30b3 208; Predicable means that the insn can be conditionally executed based on
209; an automatically added predicate (additional patterns are generated by
210; gen...). We default to 'no' because no Thumb patterns match this rule
211; and not all ARM patterns do.
0d66636f 212(define_attr "predicable" "no,yes" (const_string "no"))
213
129a2fe4 214; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
215; have one. Later ones, such as StrongARM, have write-back caches, so don't
216; suffer blockages enough to warrent modelling this (and it can adversely
217; affect the schedule).
9888ad6d 218(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
129a2fe4 219
215b30b3 220; WRITE_CONFLICT implies that a read following an unrelated write is likely
221; to stall the processor. Used with model_wbuf above.
9c08d1fa 222(define_attr "write_conflict" "no,yes"
223 (if_then_else (eq_attr "type"
224 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
225 (const_string "yes")
226 (const_string "no")))
227
215b30b3 228; Classify the insns into those that take one cycle and those that take more
229; than one on the main cpu execution unit.
f7fbdd4a 230(define_attr "core_cycles" "single,multi"
231 (if_then_else (eq_attr "type"
232 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
233 (const_string "single")
234 (const_string "multi")))
235
cffb2a26 236;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 237;; distant label. Only applicable to Thumb code.
cffb2a26 238(define_attr "far_jump" "yes,no" (const_string "no"))
239
9c08d1fa 240;; (define_function_unit {name} {num-units} {n-users} {test}
241;; {ready-delay} {issue-delay} [{conflict-list}])
215b30b3 242
243;;--------------------------------------------------------------------
244;; Floating point unit (FPA)
245;;--------------------------------------------------------------------
3d91c5d6 246(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
247 (eq_attr "type" "fdivx")) 71 69)
248
249(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
250 (eq_attr "type" "fdivd")) 59 57)
251
252(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
253 (eq_attr "type" "fdivs")) 31 29)
254
255(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
256 (eq_attr "type" "fmul")) 9 7)
257
258(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
259 (eq_attr "type" "ffmul")) 6 4)
260
261(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
262 (eq_attr "type" "farith")) 4 2)
263
264(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
265 (eq_attr "type" "ffarith")) 2 2)
266
267(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
268 (eq_attr "type" "r_2_f")) 5 3)
269
270(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
271 (eq_attr "type" "f_2_r")) 1 2)
272
215b30b3 273; The fpa10 doesn't really have a memory read unit, but it can start to
274; speculatively execute the instruction in the pipeline, provided the data
275; is already loaded, so pretend reads have a delay of 2 (and that the
276; pipeline is infinite).
3d91c5d6 277
278(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
279 (eq_attr "type" "f_load")) 3 1)
9c08d1fa 280
129a2fe4 281;;--------------------------------------------------------------------
282;; Write buffer
283;;--------------------------------------------------------------------
215b30b3 284; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
285;
286; The write buffer on some of the arm6 processors is hard to model exactly.
287; There is room in the buffer for up to two addresses and up to eight words
288; of memory, but the two needn't be split evenly. When writing the two
289; addresses are fully pipelined. However, a read from memory that is not
290; currently in the cache will block until the writes have completed.
291; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
292; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
293; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
294; cycle to add as well.
295
129a2fe4 296(define_function_unit "write_buf" 1 2
297 (and (eq_attr "model_wbuf" "yes")
298 (eq_attr "type" "store1,r_mem_f")) 5 3)
299(define_function_unit "write_buf" 1 2
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "store2")) 7 4)
302(define_function_unit "write_buf" 1 2
303 (and (eq_attr "model_wbuf" "yes")
304 (eq_attr "type" "store3")) 9 5)
305(define_function_unit "write_buf" 1 2
306 (and (eq_attr "model_wbuf" "yes")
307 (eq_attr "type" "store4")) 11 6)
308
309;;--------------------------------------------------------------------
310;; Write blockage unit
311;;--------------------------------------------------------------------
215b30b3 312; The write_blockage unit models (partially), the fact that reads will stall
313; until the write buffer empties.
314; The f_mem_r and r_mem_f could also block, but they are to the stack,
315; so we don't model them here
129a2fe4 316(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
317 (eq_attr "type" "store1")) 5 5
9c08d1fa 318 [(eq_attr "write_conflict" "yes")])
129a2fe4 319(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
320 (eq_attr "type" "store2")) 7 7
9c08d1fa 321 [(eq_attr "write_conflict" "yes")])
129a2fe4 322(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
323 (eq_attr "type" "store3")) 9 9
9c08d1fa 324 [(eq_attr "write_conflict" "yes")])
129a2fe4 325(define_function_unit "write_blockage" 1 0
326 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
9c08d1fa 327 [(eq_attr "write_conflict" "yes")])
129a2fe4 328(define_function_unit "write_blockage" 1 0
329 (and (eq_attr "model_wbuf" "yes")
330 (eq_attr "write_conflict" "yes")) 1 1)
331
332;;--------------------------------------------------------------------
333;; Core unit
334;;--------------------------------------------------------------------
215b30b3 335; Everything must spend at least one cycle in the core unit
cffb2a26 336(define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
337
129a2fe4 338(define_function_unit "core" 1 0
339 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
849170fd 340
129a2fe4 341(define_function_unit "core" 1 0
342 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
849170fd 343
331beb1a 344;; We do not need to conditionalize the define_function_unit immediately
345;; above. This one will be ignored for anything other than xscale
346;; compiles and for xscale compiles it provides a larger delay
347;; and the scheduler will DTRT.
348;; FIXME: this test needs to be revamped to not depend on this feature
349;; of the scheduler.
350
351(define_function_unit "core" 1 0
352 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
353 (eq_attr "is_xscale" "yes"))
354 3 1)
355
129a2fe4 356(define_function_unit "core" 1 0
357 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
f7fbdd4a 358
129a2fe4 359(define_function_unit "core" 1 0
360 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
849170fd 361
129a2fe4 362(define_function_unit "core" 1 0
363 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
f7fbdd4a 364
129a2fe4 365(define_function_unit "core" 1 0
366 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
f7fbdd4a 367
129a2fe4 368(define_function_unit "core" 1 0
369 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
849170fd 370
129a2fe4 371(define_function_unit "core" 1 0
9888ad6d 372 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
f7fbdd4a 373
129a2fe4 374(define_function_unit "core" 1 0
9888ad6d 375 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
376 (eq_attr "type" "mult")) 4 4)
f7fbdd4a 377
129a2fe4 378(define_function_unit "core" 1 0
9888ad6d 379 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
380 (eq_attr "type" "mult")) 3 2)
f7fbdd4a 381
129a2fe4 382(define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
f7fbdd4a 383
129a2fe4 384(define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
849170fd 385
129a2fe4 386(define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
cffb2a26 387
388(define_function_unit "core" 1 0
389 (and (eq_attr "core_cycles" "multi")
390 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
9c08d1fa 391\f
7d57ec45 392(include "cirrus.md")
393
215b30b3 394;;---------------------------------------------------------------------------
e1159bbe 395;; Insn patterns
396;;
a0f94409 397;; Addition insns.
215b30b3 398
9c08d1fa 399;; Note: For DImode insns, there is normally no reason why operands should
400;; not be in the same register, what we don't want is for something being
401;; written to partially overlap something that is an input.
7d57ec45 402;; Cirrus 64bit additions should not be split because we have a native
403;; 64bit addition instructions.
9c08d1fa 404
cffb2a26 405(define_expand "adddi3"
406 [(parallel
215b30b3 407 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 408 (plus:DI (match_operand:DI 1 "s_register_operand" "")
409 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 410 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 411 "TARGET_EITHER"
412 "
7d57ec45 413 if (TARGET_CIRRUS)
414 {
415 if (!cirrus_fp_register (operands[0], DImode))
416 operands[0] = force_reg (DImode, operands[0]);
417 if (!cirrus_fp_register (operands[1], DImode))
418 operands[1] = force_reg (DImode, operands[1]);
419 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
420 DONE;
421 }
422
cffb2a26 423 if (TARGET_THUMB)
424 {
425 if (GET_CODE (operands[1]) != REG)
426 operands[1] = force_reg (SImode, operands[1]);
427 if (GET_CODE (operands[2]) != REG)
428 operands[2] = force_reg (SImode, operands[2]);
429 }
430 "
431)
432
433(define_insn "*thumb_adddi3"
434 [(set (match_operand:DI 0 "register_operand" "=l")
435 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 436 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 437 (clobber (reg:CC CC_REGNUM))
cffb2a26 438 ]
439 "TARGET_THUMB"
440 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
441 [(set_attr "length" "4")]
442)
443
a0f94409 444(define_insn_and_split "*arm_adddi3"
cffb2a26 445 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 446 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
447 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 448 (clobber (reg:CC CC_REGNUM))]
7d57ec45 449 "TARGET_ARM && !TARGET_CIRRUS"
33782ec7 450 "#"
a0f94409 451 "TARGET_ARM && reload_completed"
452 [(parallel [(set (reg:CC_C CC_REGNUM)
453 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
454 (match_dup 1)))
455 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
456 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
457 (plus:SI (match_dup 4) (match_dup 5))))]
458 "
459 {
460 operands[3] = gen_highpart (SImode, operands[0]);
461 operands[0] = gen_lowpart (SImode, operands[0]);
462 operands[4] = gen_highpart (SImode, operands[1]);
463 operands[1] = gen_lowpart (SImode, operands[1]);
464 operands[5] = gen_highpart (SImode, operands[2]);
465 operands[2] = gen_lowpart (SImode, operands[2]);
466 }"
cffb2a26 467 [(set_attr "conds" "clob")
468 (set_attr "length" "8")]
469)
9c08d1fa 470
a0f94409 471(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 472 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
473 (plus:DI (sign_extend:DI
97499065 474 (match_operand:SI 2 "s_register_operand" "r,r"))
475 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 476 (clobber (reg:CC CC_REGNUM))]
7d57ec45 477 "TARGET_ARM && !TARGET_CIRRUS"
33782ec7 478 "#"
a0f94409 479 "TARGET_ARM && reload_completed"
480 [(parallel [(set (reg:CC_C CC_REGNUM)
481 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
482 (match_dup 1)))
483 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
484 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
485 (plus:SI (ashiftrt:SI (match_dup 2)
486 (const_int 31))
487 (match_dup 4))))]
488 "
489 {
490 operands[3] = gen_highpart (SImode, operands[0]);
491 operands[0] = gen_lowpart (SImode, operands[0]);
492 operands[4] = gen_highpart (SImode, operands[1]);
493 operands[1] = gen_lowpart (SImode, operands[1]);
494 operands[2] = gen_lowpart (SImode, operands[2]);
495 }"
215b30b3 496 [(set_attr "conds" "clob")
497 (set_attr "length" "8")]
498)
9c08d1fa 499
a0f94409 500(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 501 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
502 (plus:DI (zero_extend:DI
97499065 503 (match_operand:SI 2 "s_register_operand" "r,r"))
504 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 505 (clobber (reg:CC CC_REGNUM))]
7d57ec45 506 "TARGET_ARM && !TARGET_CIRRUS"
33782ec7 507 "#"
a0f94409 508 "TARGET_ARM && reload_completed"
509 [(parallel [(set (reg:CC_C CC_REGNUM)
510 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
511 (match_dup 1)))
512 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
513 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
514 (plus:SI (match_dup 4) (const_int 0))))]
515 "
516 {
517 operands[3] = gen_highpart (SImode, operands[0]);
518 operands[0] = gen_lowpart (SImode, operands[0]);
519 operands[4] = gen_highpart (SImode, operands[1]);
520 operands[1] = gen_lowpart (SImode, operands[1]);
521 operands[2] = gen_lowpart (SImode, operands[2]);
522 }"
cffb2a26 523 [(set_attr "conds" "clob")
524 (set_attr "length" "8")]
525)
b11cae9e 526
87b22bf7 527(define_expand "addsi3"
cffb2a26 528 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 529 (plus:SI (match_operand:SI 1 "s_register_operand" "")
530 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 531 "TARGET_EITHER"
87b22bf7 532 "
cffb2a26 533 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 534 {
535 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
536 operands[1],
935d87ee 537 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
87b22bf7 538 DONE;
539 }
cffb2a26 540 "
541)
87b22bf7 542
a0f94409 543; If there is a scratch available, this will be faster than synthesising the
544; addition.
545(define_peephole2
546 [(match_scratch:SI 3 "r")
547 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 548 (plus:SI (match_operand:SI 1 "s_register_operand" "")
cffb2a26 549 (match_operand:SI 2 "const_int_operand" "")))]
550 "TARGET_ARM &&
a0f94409 551 !(const_ok_for_arm (INTVAL (operands[2]))
552 || const_ok_for_arm (-INTVAL (operands[2])))
553 && const_ok_for_arm (~INTVAL (operands[2]))"
554 [(set (match_dup 3) (match_dup 2))
555 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
556 ""
557)
87b22bf7 558
a0f94409 559(define_insn_and_split "*arm_addsi3"
cffb2a26 560 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0f94409 561 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
87b22bf7 562 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
cffb2a26 563 "TARGET_ARM"
5565501b 564 "@
565 add%?\\t%0, %1, %2
87b22bf7 566 sub%?\\t%0, %1, #%n2
567 #"
a0f94409 568 "TARGET_ARM &&
569 GET_CODE (operands[2]) == CONST_INT
570 && !(const_ok_for_arm (INTVAL (operands[2]))
571 || const_ok_for_arm (-INTVAL (operands[2])))"
572 [(clobber (const_int 0))]
573 "
574 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
575 operands[1], 0);
576 DONE;
577 "
0d66636f 578 [(set_attr "length" "4,4,16")
579 (set_attr "predicable" "yes")]
cffb2a26 580)
581
582;; Register group 'k' is a single register group containing only the stack
583;; register. Trying to reload it will always fail catastrophically,
584;; so never allow those alternatives to match if reloading is needed.
585
586(define_insn "*thumb_addsi3"
587 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
588 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
589 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
590 "TARGET_THUMB"
591 "*
0d66636f 592 static const char * const asms[] =
cffb2a26 593 {
594 \"add\\t%0, %0, %2\",
595 \"sub\\t%0, %0, #%n2\",
596 \"add\\t%0, %1, %2\",
597 \"add\\t%0, %0, %2\",
598 \"add\\t%0, %0, %2\",
599 \"add\\t%0, %1, %2\",
600 \"add\\t%0, %1, %2\"
601 };
602 if ((which_alternative == 2 || which_alternative == 6)
603 && GET_CODE (operands[2]) == CONST_INT
604 && INTVAL (operands[2]) < 0)
605 return \"sub\\t%0, %1, #%n2\";
606 return asms[which_alternative];
607 "
608 [(set_attr "length" "2")]
609)
610
611;; Reloading and elimination of the frame pointer can
612;; sometimes cause this optimization to be missed.
a0f94409 613(define_peephole2
a058e94a 614 [(set (match_operand:SI 0 "register_operand" "")
615 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 616 (set (match_dup 0)
a058e94a 617 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
cffb2a26 618 "TARGET_THUMB
619 && REGNO (operands[2]) == STACK_POINTER_REGNUM
620 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
621 && (INTVAL (operands[1]) & 3) == 0"
a0f94409 622 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
623 ""
cffb2a26 624)
b11cae9e 625
f7fbdd4a 626(define_insn "*addsi3_compare0"
bd5b4116 627 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 628 (compare:CC_NOOV
215b30b3 629 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
630 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 631 (const_int 0)))
632 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 633 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 634 "TARGET_ARM"
5565501b 635 "@
636 add%?s\\t%0, %1, %2
637 sub%?s\\t%0, %1, #%n2"
cffb2a26 638 [(set_attr "conds" "set")]
639)
9c08d1fa 640
aea4c774 641(define_insn "*addsi3_compare0_scratch"
bd5b4116 642 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 643 (compare:CC_NOOV
215b30b3 644 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
645 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 646 (const_int 0)))]
cffb2a26 647 "TARGET_ARM"
648 "@
649 cmn%?\\t%0, %1
650 cmp%?\\t%0, #%n1"
0d66636f 651 [(set_attr "conds" "set")]
652)
cffb2a26 653
654;; These patterns are the same ones as the two regular addsi3_compare0
655;; patterns, except we write them slightly different - the combiner
656;; tends to generate them this way.
657(define_insn "*addsi3_compare0_for_combiner"
bd5b4116 658 [(set (reg:CC CC_REGNUM)
cffb2a26 659 (compare:CC
660 (match_operand:SI 1 "s_register_operand" "r,r")
661 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
662 (set (match_operand:SI 0 "s_register_operand" "=r,r")
663 (plus:SI (match_dup 1) (match_dup 2)))]
664 "TARGET_ARM"
665 "@
666 add%?s\\t%0, %1, %2
667 sub%?s\\t%0, %1, #%n2"
668 [(set_attr "conds" "set")]
669)
670
671(define_insn "*addsi3_compare0_scratch_for_combiner"
bd5b4116 672 [(set (reg:CC CC_REGNUM)
cffb2a26 673 (compare:CC
674 (match_operand:SI 0 "s_register_operand" "r,r")
675 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
676 "TARGET_ARM"
aea4c774 677 "@
678 cmn%?\\t%0, %1
679 cmp%?\\t%0, #%n1"
0d66636f 680 [(set_attr "conds" "set")]
681)
aea4c774 682
ebcc79bc 683;; The next four insns work because they compare the result with one of
684;; the operands, and we know that the use of the condition code is
685;; either GEU or LTU, so we can use the carry flag from the addition
686;; instead of doing the compare a second time.
687(define_insn "*addsi3_compare_op1"
bd5b4116 688 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 689 (compare:CC_C
690 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
691 (match_operand:SI 2 "arm_add_operand" "rI,L"))
692 (match_dup 1)))
693 (set (match_operand:SI 0 "s_register_operand" "=r,r")
694 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 695 "TARGET_ARM"
ebcc79bc 696 "@
697 add%?s\\t%0, %1, %2
698 sub%?s\\t%0, %1, #%n2"
0d66636f 699 [(set_attr "conds" "set")]
700)
ebcc79bc 701
702(define_insn "*addsi3_compare_op2"
bd5b4116 703 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 704 (compare:CC_C
705 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
706 (match_operand:SI 2 "arm_add_operand" "rI,L"))
707 (match_dup 2)))
5565501b 708 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 709 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 710 "TARGET_ARM"
5565501b 711 "@
712 add%?s\\t%0, %1, %2
713 sub%?s\\t%0, %1, #%n2"
0d66636f 714 [(set_attr "conds" "set")]
715)
9c08d1fa 716
ebcc79bc 717(define_insn "*compare_addsi2_op0"
bd5b4116 718 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 719 (compare:CC_C
720 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
721 (match_operand:SI 1 "arm_add_operand" "rI,L"))
722 (match_dup 0)))]
cffb2a26 723 "TARGET_ARM"
ebcc79bc 724 "@
725 cmn%?\\t%0, %1
726 cmp%?\\t%0, #%n1"
0d66636f 727 [(set_attr "conds" "set")]
728)
ebcc79bc 729
730(define_insn "*compare_addsi2_op1"
bd5b4116 731 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 732 (compare:CC_C
733 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
734 (match_operand:SI 1 "arm_add_operand" "rI,L"))
735 (match_dup 1)))]
cffb2a26 736 "TARGET_ARM"
ebcc79bc 737 "@
738 cmn%?\\t%0, %1
739 cmp%?\\t%0, #%n1"
0d66636f 740 [(set_attr "conds" "set")]
741)
ebcc79bc 742
743(define_insn "*addsi3_carryin"
744 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 745 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 746 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
747 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
cffb2a26 748 "TARGET_ARM"
ebcc79bc 749 "adc%?\\t%0, %1, %2"
cffb2a26 750 [(set_attr "conds" "use")]
751)
ebcc79bc 752
33782ec7 753(define_insn "*addsi3_carryin_shift"
754 [(set (match_operand:SI 0 "s_register_operand" "")
bd5b4116 755 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 756 (plus:SI
757 (match_operator:SI 2 "shift_operator"
758 [(match_operand:SI 3 "s_register_operand" "")
759 (match_operand:SI 4 "reg_or_int_operand" "")])
760 (match_operand:SI 1 "s_register_operand" ""))))]
cffb2a26 761 "TARGET_ARM"
33782ec7 762 "adc%?\\t%0, %1, %3%S2"
763 [(set_attr "conds" "use")]
764)
765
ebcc79bc 766(define_insn "*addsi3_carryin_alt1"
767 [(set (match_operand:SI 0 "s_register_operand" "=r")
768 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
769 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 770 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
cffb2a26 771 "TARGET_ARM"
ebcc79bc 772 "adc%?\\t%0, %1, %2"
cffb2a26 773 [(set_attr "conds" "use")]
774)
ebcc79bc 775
776(define_insn "*addsi3_carryin_alt2"
777 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 778 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 779 (match_operand:SI 1 "s_register_operand" "r"))
780 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 781 "TARGET_ARM"
ebcc79bc 782 "adc%?\\t%0, %1, %2"
0d66636f 783 [(set_attr "conds" "use")]
784)
ebcc79bc 785
786(define_insn "*addsi3_carryin_alt3"
787 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 788 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 789 (match_operand:SI 2 "arm_rhs_operand" "rI"))
790 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 791 "TARGET_ARM"
ebcc79bc 792 "adc%?\\t%0, %1, %2"
cffb2a26 793 [(set_attr "conds" "use")]
794)
ebcc79bc 795
9c08d1fa 796(define_insn "incscc"
797 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 798 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 799 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 800 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 801 "TARGET_ARM"
5565501b 802 "@
803 add%d2\\t%0, %1, #1
804 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 805 [(set_attr "conds" "use")
215b30b3 806 (set_attr "length" "4,8")]
807)
9c08d1fa 808
604f3a0a 809(define_expand "addsf3"
810 [(set (match_operand:SF 0 "s_register_operand" "")
811 (plus:SF (match_operand:SF 1 "s_register_operand" "")
e8ff69a4 812 (match_operand:SF 2 "fpa_add_operand" "")))]
604f3a0a 813 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
814 "
815 if (TARGET_CIRRUS
816 && !cirrus_fp_register (operands[2], SFmode))
817 operands[2] = force_reg (SFmode, operands[2]);
818")
819
7d57ec45 820(define_insn "*arm_addsf3"
cffb2a26 821 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
a0f94409 822 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
e8ff69a4 823 (match_operand:SF 2 "fpa_add_operand" "fG,H")))]
cffb2a26 824 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 825 "@
826 adf%?s\\t%0, %1, %2
827 suf%?s\\t%0, %1, #%N2"
0d66636f 828 [(set_attr "type" "farith")
829 (set_attr "predicable" "yes")]
cffb2a26 830)
9c08d1fa 831
604f3a0a 832(define_expand "adddf3"
833 [(set (match_operand:DF 0 "s_register_operand" "")
834 (plus:DF (match_operand:DF 1 "s_register_operand" "")
e8ff69a4 835 (match_operand:DF 2 "fpa_add_operand" "")))]
604f3a0a 836 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
837 "
838 if (TARGET_CIRRUS
839 && !cirrus_fp_register (operands[2], DFmode))
840 operands[2] = force_reg (DFmode, operands[2]);
841")
842
7d57ec45 843(define_insn "*arm_adddf3"
cffb2a26 844 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
a0f94409 845 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
e8ff69a4 846 (match_operand:DF 2 "fpa_add_operand" "fG,H")))]
cffb2a26 847 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 848 "@
849 adf%?d\\t%0, %1, %2
850 suf%?d\\t%0, %1, #%N2"
0d66636f 851 [(set_attr "type" "farith")
852 (set_attr "predicable" "yes")]
cffb2a26 853)
9c08d1fa 854
cbd60e74 855(define_insn "*adddf_esfdf_df"
cffb2a26 856 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
9c08d1fa 857 (plus:DF (float_extend:DF
cffb2a26 858 (match_operand:SF 1 "s_register_operand" "f,f"))
e8ff69a4 859 (match_operand:DF 2 "fpa_add_operand" "fG,H")))]
cffb2a26 860 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 861 "@
862 adf%?d\\t%0, %1, %2
863 suf%?d\\t%0, %1, #%N2"
0d66636f 864 [(set_attr "type" "farith")
865 (set_attr "predicable" "yes")]
cffb2a26 866)
9c08d1fa 867
f7fbdd4a 868(define_insn "*adddf_df_esfdf"
cffb2a26 869 [(set (match_operand:DF 0 "s_register_operand" "=f")
870 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
9c08d1fa 871 (float_extend:DF
cffb2a26 872 (match_operand:SF 2 "s_register_operand" "f"))))]
873 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 874 "adf%?d\\t%0, %1, %2"
0d66636f 875 [(set_attr "type" "farith")
876 (set_attr "predicable" "yes")]
cffb2a26 877)
9c08d1fa 878
f7fbdd4a 879(define_insn "*adddf_esfdf_esfdf"
cffb2a26 880 [(set (match_operand:DF 0 "s_register_operand" "=f")
9c08d1fa 881 (plus:DF (float_extend:DF
882 (match_operand:SF 1 "s_register_operand" "f"))
883 (float_extend:DF
884 (match_operand:SF 2 "s_register_operand" "f"))))]
cffb2a26 885 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 886 "adf%?d\\t%0, %1, %2"
0d66636f 887 [(set_attr "type" "farith")
888 (set_attr "predicable" "yes")]
cffb2a26 889)
9c08d1fa 890
cffb2a26 891(define_expand "subdi3"
892 [(parallel
893 [(set (match_operand:DI 0 "s_register_operand" "")
894 (minus:DI (match_operand:DI 1 "s_register_operand" "")
895 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 896 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 897 "TARGET_EITHER"
898 "
7d57ec45 899 if (TARGET_CIRRUS
900 && TARGET_ARM
901 && cirrus_fp_register (operands[0], DImode)
902 && cirrus_fp_register (operands[1], DImode))
903 {
904 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
905 DONE;
906 }
907
cffb2a26 908 if (TARGET_THUMB)
909 {
910 if (GET_CODE (operands[1]) != REG)
911 operands[1] = force_reg (SImode, operands[1]);
912 if (GET_CODE (operands[2]) != REG)
913 operands[2] = force_reg (SImode, operands[2]);
914 }
915 "
916)
917
918(define_insn "*arm_subdi3"
919 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 920 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
921 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 922 (clobber (reg:CC CC_REGNUM))]
cffb2a26 923 "TARGET_ARM"
97499065 924 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 925 [(set_attr "conds" "clob")
926 (set_attr "length" "8")]
927)
928
929(define_insn "*thumb_subdi3"
930 [(set (match_operand:DI 0 "register_operand" "=l")
931 (minus:DI (match_operand:DI 1 "register_operand" "0")
932 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 933 (clobber (reg:CC CC_REGNUM))]
cffb2a26 934 "TARGET_THUMB"
935 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
936 [(set_attr "length" "4")]
937)
9c08d1fa 938
f7fbdd4a 939(define_insn "*subdi_di_zesidi"
cffb2a26 940 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
941 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 942 (zero_extend:DI
cffb2a26 943 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 944 (clobber (reg:CC CC_REGNUM))]
cffb2a26 945 "TARGET_ARM"
97499065 946 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 947 [(set_attr "conds" "clob")
948 (set_attr "length" "8")]
949)
9c08d1fa 950
f7fbdd4a 951(define_insn "*subdi_di_sesidi"
cffb2a26 952 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
953 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 954 (sign_extend:DI
cffb2a26 955 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 956 (clobber (reg:CC CC_REGNUM))]
cffb2a26 957 "TARGET_ARM"
97499065 958 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 959 [(set_attr "conds" "clob")
960 (set_attr "length" "8")]
961)
9c08d1fa 962
f7fbdd4a 963(define_insn "*subdi_zesidi_di"
cffb2a26 964 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 965 (minus:DI (zero_extend:DI
cffb2a26 966 (match_operand:SI 2 "s_register_operand" "r,r"))
967 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 968 (clobber (reg:CC CC_REGNUM))]
cffb2a26 969 "TARGET_ARM"
97499065 970 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 971 [(set_attr "conds" "clob")
972 (set_attr "length" "8")]
973)
9c08d1fa 974
f7fbdd4a 975(define_insn "*subdi_sesidi_di"
cffb2a26 976 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 977 (minus:DI (sign_extend:DI
cffb2a26 978 (match_operand:SI 2 "s_register_operand" "r,r"))
979 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 980 (clobber (reg:CC CC_REGNUM))]
cffb2a26 981 "TARGET_ARM"
97499065 982 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 983 [(set_attr "conds" "clob")
984 (set_attr "length" "8")]
985)
9c08d1fa 986
f7fbdd4a 987(define_insn "*subdi_zesidi_zesidi"
cffb2a26 988 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 989 (minus:DI (zero_extend:DI
cffb2a26 990 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 991 (zero_extend:DI
cffb2a26 992 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 993 (clobber (reg:CC CC_REGNUM))]
cffb2a26 994 "TARGET_ARM"
97499065 995 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
cffb2a26 996 [(set_attr "conds" "clob")
997 (set_attr "length" "8")]
998)
b11cae9e 999
87b22bf7 1000(define_expand "subsi3"
cffb2a26 1001 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1002 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1003 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 1004 "TARGET_EITHER"
87b22bf7 1005 "
1006 if (GET_CODE (operands[1]) == CONST_INT)
1007 {
cffb2a26 1008 if (TARGET_ARM)
1009 {
1010 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1011 operands[2],
935d87ee 1012 (no_new_pseudos ? 0
cffb2a26 1013 : preserve_subexpressions_p ()));
1014 DONE;
1015 }
1016 else /* TARGET_THUMB */
1017 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 1018 }
cffb2a26 1019 "
1020)
87b22bf7 1021
cffb2a26 1022(define_insn "*thumb_subsi3_insn"
1023 [(set (match_operand:SI 0 "register_operand" "=l")
1024 (minus:SI (match_operand:SI 1 "register_operand" "l")
1025 (match_operand:SI 2 "register_operand" "l")))]
1026 "TARGET_THUMB"
1027 "sub\\t%0, %1, %2"
1028 [(set_attr "length" "2")]
1029)
1030
a0f94409 1031(define_insn_and_split "*arm_subsi3_insn"
cffb2a26 1032 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 1033 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1034 (match_operand:SI 2 "s_register_operand" "r,r")))]
cffb2a26 1035 "TARGET_ARM"
e2348bcb 1036 "@
87b22bf7 1037 rsb%?\\t%0, %2, %1
1038 #"
a0f94409 1039 "TARGET_ARM
1040 && GET_CODE (operands[1]) == CONST_INT
1041 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 1042 [(clobber (const_int 0))]
1043 "
1044 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1045 operands[2], 0);
1046 DONE;
cffb2a26 1047 "
a0f94409 1048 [(set_attr "length" "4,16")
1049 (set_attr "predicable" "yes")]
1050)
1051
1052(define_peephole2
1053 [(match_scratch:SI 3 "r")
1054 (set (match_operand:SI 0 "s_register_operand" "")
1055 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1056 (match_operand:SI 2 "s_register_operand" "")))]
1057 "TARGET_ARM
1058 && !const_ok_for_arm (INTVAL (operands[1]))
1059 && const_ok_for_arm (~INTVAL (operands[1]))"
1060 [(set (match_dup 3) (match_dup 1))
1061 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1062 ""
cffb2a26 1063)
b11cae9e 1064
f7fbdd4a 1065(define_insn "*subsi3_compare0"
bd5b4116 1066 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1067 (compare:CC_NOOV
1068 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1069 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1070 (const_int 0)))
9c08d1fa 1071 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1072 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1073 "TARGET_ARM"
e2348bcb 1074 "@
40dbec34 1075 sub%?s\\t%0, %1, %2
1076 rsb%?s\\t%0, %2, %1"
cffb2a26 1077 [(set_attr "conds" "set")]
1078)
9c08d1fa 1079
1080(define_insn "decscc"
cffb2a26 1081 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1082 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1083 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1084 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1085 "TARGET_ARM"
e2348bcb 1086 "@
215b30b3 1087 sub%d2\\t%0, %1, #1
1088 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1089 [(set_attr "conds" "use")
1090 (set_attr "length" "*,8")]
1091)
9c08d1fa 1092
604f3a0a 1093(define_expand "subsf3"
1094 [(set (match_operand:SF 0 "s_register_operand" "")
e8ff69a4 1095 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1096 (match_operand:SF 2 "fpa_rhs_operand" "")))]
604f3a0a 1097 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1098 "
1099 if (TARGET_CIRRUS)
1100 {
1101 if (!cirrus_fp_register (operands[1], SFmode))
1102 operands[1] = force_reg (SFmode, operands[1]);
1103 if (!cirrus_fp_register (operands[2], SFmode))
1104 operands[2] = force_reg (SFmode, operands[2]);
1105 }
1106")
1107
7d57ec45 1108(define_insn "*arm_subsf3"
9c08d1fa 1109 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
e8ff69a4 1110 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "f,G")
1111 (match_operand:SF 2 "fpa_rhs_operand" "fG,f")))]
cffb2a26 1112 "TARGET_ARM && TARGET_HARD_FLOAT"
e2348bcb 1113 "@
40dbec34 1114 suf%?s\\t%0, %1, %2
1115 rsf%?s\\t%0, %2, %1"
cffb2a26 1116 [(set_attr "type" "farith")]
1117)
b11cae9e 1118
604f3a0a 1119(define_expand "subdf3"
1120 [(set (match_operand:DF 0 "s_register_operand" "")
e8ff69a4 1121 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1122 (match_operand:DF 2 "fpa_rhs_operand" "")))]
604f3a0a 1123 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1124 "
1125 if (TARGET_CIRRUS)
1126 {
1127 if (!cirrus_fp_register (operands[1], DFmode))
1128 operands[1] = force_reg (DFmode, operands[1]);
1129 if (!cirrus_fp_register (operands[2], DFmode))
1130 operands[2] = force_reg (DFmode, operands[2]);
1131 }
1132")
1133
7d57ec45 1134(define_insn "*arm_subdf3"
cffb2a26 1135 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
e8ff69a4 1136 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "f,G")
1137 (match_operand:DF 2 "fpa_rhs_operand" "fG,f")))]
cffb2a26 1138 "TARGET_ARM && TARGET_HARD_FLOAT"
e2348bcb 1139 "@
40dbec34 1140 suf%?d\\t%0, %1, %2
1141 rsf%?d\\t%0, %2, %1"
0d66636f 1142 [(set_attr "type" "farith")
1143 (set_attr "predicable" "yes")]
cffb2a26 1144)
9c08d1fa 1145
f7fbdd4a 1146(define_insn "*subdf_esfdf_df"
cffb2a26 1147 [(set (match_operand:DF 0 "s_register_operand" "=f")
9c08d1fa 1148 (minus:DF (float_extend:DF
cffb2a26 1149 (match_operand:SF 1 "s_register_operand" "f"))
e8ff69a4 1150 (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
cffb2a26 1151 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1152 "suf%?d\\t%0, %1, %2"
0d66636f 1153 [(set_attr "type" "farith")
1154 (set_attr "predicable" "yes")]
cffb2a26 1155)
9c08d1fa 1156
f7fbdd4a 1157(define_insn "*subdf_df_esfdf"
9c08d1fa 1158 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
e8ff69a4 1159 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "f,G")
9c08d1fa 1160 (float_extend:DF
1161 (match_operand:SF 2 "s_register_operand" "f,f"))))]
cffb2a26 1162 "TARGET_ARM && TARGET_HARD_FLOAT"
e2348bcb 1163 "@
40dbec34 1164 suf%?d\\t%0, %1, %2
1165 rsf%?d\\t%0, %2, %1"
0d66636f 1166 [(set_attr "type" "farith")
1167 (set_attr "predicable" "yes")]
cffb2a26 1168)
9c08d1fa 1169
f7fbdd4a 1170(define_insn "*subdf_esfdf_esfdf"
9c08d1fa 1171 [(set (match_operand:DF 0 "s_register_operand" "=f")
1172 (minus:DF (float_extend:DF
1173 (match_operand:SF 1 "s_register_operand" "f"))
1174 (float_extend:DF
1175 (match_operand:SF 2 "s_register_operand" "f"))))]
cffb2a26 1176 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1177 "suf%?d\\t%0, %1, %2"
0d66636f 1178 [(set_attr "type" "farith")
1179 (set_attr "predicable" "yes")]
cffb2a26 1180)
b11cae9e 1181\f
1182;; Multiplication insns
1183
cffb2a26 1184(define_expand "mulsi3"
1185 [(set (match_operand:SI 0 "s_register_operand" "")
1186 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1187 (match_operand:SI 1 "s_register_operand" "")))]
1188 "TARGET_EITHER"
1189 ""
1190)
1191
9c08d1fa 1192;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1193(define_insn "*arm_mulsi3"
1194 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1195 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1196 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
cffb2a26 1197 "TARGET_ARM"
f7fbdd4a 1198 "mul%?\\t%0, %2, %1"
0d66636f 1199 [(set_attr "type" "mult")
1200 (set_attr "predicable" "yes")]
cffb2a26 1201)
1202
215b30b3 1203; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1204; 1 and 2; are the same, because reload will make operand 0 match
1205; operand 1 without realizing that this conflicts with operand 2. We fix
1206; this by adding another alternative to match this case, and then `reload'
1207; it ourselves. This alternative must come first.
cffb2a26 1208(define_insn "*thumb_mulsi3"
1209 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1210 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1211 (match_operand:SI 2 "register_operand" "l,l,l")))]
1212 "TARGET_THUMB"
1213 "*
1214 if (which_alternative < 2)
1215 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1216 else
1217 return \"mul\\t%0, %0, %2\";
1218 "
1219 [(set_attr "length" "4,4,2")
1220 (set_attr "type" "mult")]
1221)
b11cae9e 1222
f7fbdd4a 1223(define_insn "*mulsi3_compare0"
bd5b4116 1224 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1225 (compare:CC_NOOV (mult:SI
1226 (match_operand:SI 2 "s_register_operand" "r,r")
1227 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1228 (const_int 0)))
1229 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230 (mult:SI (match_dup 2) (match_dup 1)))]
331beb1a 1231 "TARGET_ARM && !arm_is_xscale"
40dbec34 1232 "mul%?s\\t%0, %2, %1"
cffb2a26 1233 [(set_attr "conds" "set")
1234 (set_attr "type" "mult")]
1235)
9c08d1fa 1236
f7fbdd4a 1237(define_insn "*mulsi_compare0_scratch"
bd5b4116 1238 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1239 (compare:CC_NOOV (mult:SI
1240 (match_operand:SI 2 "s_register_operand" "r,r")
1241 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1242 (const_int 0)))
1243 (clobber (match_scratch:SI 0 "=&r,&r"))]
331beb1a 1244 "TARGET_ARM && !arm_is_xscale"
40dbec34 1245 "mul%?s\\t%0, %2, %1"
cffb2a26 1246 [(set_attr "conds" "set")
1247 (set_attr "type" "mult")]
1248)
9c08d1fa 1249
b11cae9e 1250;; Unnamed templates to match MLA instruction.
1251
f7fbdd4a 1252(define_insn "*mulsi3addsi"
9c08d1fa 1253 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1254 (plus:SI
9c08d1fa 1255 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1256 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1257 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
cffb2a26 1258 "TARGET_ARM"
f7fbdd4a 1259 "mla%?\\t%0, %2, %1, %3"
0d66636f 1260 [(set_attr "type" "mult")
1261 (set_attr "predicable" "yes")]
1262)
b11cae9e 1263
f7fbdd4a 1264(define_insn "*mulsi3addsi_compare0"
bd5b4116 1265 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1266 (compare:CC_NOOV
1267 (plus:SI (mult:SI
1268 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1269 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1270 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1271 (const_int 0)))
9c08d1fa 1272 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1273 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1274 (match_dup 3)))]
331beb1a 1275 "TARGET_ARM && !arm_is_xscale"
40dbec34 1276 "mla%?s\\t%0, %2, %1, %3"
0d66636f 1277 [(set_attr "conds" "set")
1278 (set_attr "type" "mult")]
1279)
9c08d1fa 1280
f7fbdd4a 1281(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1282 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1283 (compare:CC_NOOV
1284 (plus:SI (mult:SI
1285 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1286 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1287 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1288 (const_int 0)))
9c08d1fa 1289 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
331beb1a 1290 "TARGET_ARM && !arm_is_xscale"
40dbec34 1291 "mla%?s\\t%0, %2, %1, %3"
cffb2a26 1292 [(set_attr "conds" "set")
1293 (set_attr "type" "mult")]
1294)
f7fbdd4a 1295
82b85d08 1296;; Unnamed template to match long long multiply-accumlate (smlal)
1297
1298(define_insn "*mulsidi3adddi"
fe8dbf85 1299 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1300 (plus:DI
215b30b3 1301 (mult:DI
fe8dbf85 1302 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1303 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1304 (match_operand:DI 1 "s_register_operand" "0")))]
cffb2a26 1305 "TARGET_ARM && arm_fast_multiply"
fe8dbf85 1306 "smlal%?\\t%Q0, %R0, %3, %2"
0d66636f 1307 [(set_attr "type" "mult")
1308 (set_attr "predicable" "yes")]
1309)
82b85d08 1310
f7fbdd4a 1311(define_insn "mulsidi3"
1312 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1313 (mult:DI
1314 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1315 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
cffb2a26 1316 "TARGET_ARM && arm_fast_multiply"
97499065 1317 "smull%?\\t%Q0, %R0, %1, %2"
0d66636f 1318 [(set_attr "type" "mult")
1319 (set_attr "predicable" "yes")]
1320)
f7fbdd4a 1321
1322(define_insn "umulsidi3"
1323 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1324 (mult:DI
1325 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1326 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
cffb2a26 1327 "TARGET_ARM && arm_fast_multiply"
97499065 1328 "umull%?\\t%Q0, %R0, %1, %2"
0d66636f 1329 [(set_attr "type" "mult")
1330 (set_attr "predicable" "yes")]
1331)
b11cae9e 1332
82b85d08 1333;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1334
1335(define_insn "*umulsidi3adddi"
8ead09f9 1336 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1337 (plus:DI
215b30b3 1338 (mult:DI
fe8dbf85 1339 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1340 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1341 (match_operand:DI 1 "s_register_operand" "0")))]
cffb2a26 1342 "TARGET_ARM && arm_fast_multiply"
fe8dbf85 1343 "umlal%?\\t%Q0, %R0, %3, %2"
0d66636f 1344 [(set_attr "type" "mult")
1345 (set_attr "predicable" "yes")]
1346)
82b85d08 1347
f082f1c4 1348(define_insn "smulsi3_highpart"
1349 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1350 (truncate:SI
1351 (lshiftrt:DI
215b30b3 1352 (mult:DI
1353 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1354 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1355 (const_int 32))))
1356 (clobber (match_scratch:SI 3 "=&r,&r"))]
cffb2a26 1357 "TARGET_ARM && arm_fast_multiply"
f082f1c4 1358 "smull%?\\t%3, %0, %2, %1"
0d66636f 1359 [(set_attr "type" "mult")
1360 (set_attr "predicable" "yes")]
cffb2a26 1361)
f082f1c4 1362
1363(define_insn "umulsi3_highpart"
1364 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1365 (truncate:SI
1366 (lshiftrt:DI
215b30b3 1367 (mult:DI
1368 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1369 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1370 (const_int 32))))
1371 (clobber (match_scratch:SI 3 "=&r,&r"))]
cffb2a26 1372 "TARGET_ARM && arm_fast_multiply"
f082f1c4 1373 "umull%?\\t%3, %0, %2, %1"
0d66636f 1374 [(set_attr "type" "mult")
1375 (set_attr "predicable" "yes")]
cffb2a26 1376)
f082f1c4 1377
331beb1a 1378(define_insn "mulhisi3"
1379 [(set (match_operand:SI 0 "s_register_operand" "=r")
1380 (mult:SI (sign_extend:SI
1381 (match_operand:HI 1 "s_register_operand" "%r"))
1382 (sign_extend:SI
1383 (match_operand:HI 2 "s_register_operand" "r"))))]
fec538d9 1384 "TARGET_ARM && arm_arch5e"
61a2d04c 1385 "smulbb%?\\t%0, %1, %2"
fec538d9 1386 [(set_attr "type" "mult")
1387 (set_attr "predicable" "yes")]
1388)
1389
1390(define_insn "*mulhisi3tb"
1391 [(set (match_operand:SI 0 "s_register_operand" "=r")
1392 (mult:SI (ashiftrt:SI
1393 (match_operand:SI 1 "s_register_operand" "r")
1394 (const_int 16))
1395 (sign_extend:SI
1396 (match_operand:HI 2 "s_register_operand" "r"))))]
1397 "TARGET_ARM && arm_arch5e"
1398 "smultb%?\\t%0, %1, %2"
1399 [(set_attr "type" "mult")
1400 (set_attr "predicable" "yes")]
1401)
1402
1403(define_insn "*mulhisi3bt"
1404 [(set (match_operand:SI 0 "s_register_operand" "=r")
1405 (mult:SI (sign_extend:SI
1406 (match_operand:HI 1 "s_register_operand" "r"))
1407 (ashiftrt:SI
1408 (match_operand:SI 2 "s_register_operand" "r")
1409 (const_int 16))))]
1410 "TARGET_ARM && arm_arch5e"
1411 "smulbt%?\\t%0, %1, %2"
1412 [(set_attr "type" "mult")
1413 (set_attr "predicable" "yes")]
1414)
1415
1416(define_insn "*mulhisi3tt"
1417 [(set (match_operand:SI 0 "s_register_operand" "=r")
1418 (mult:SI (ashiftrt:SI
1419 (match_operand:SI 1 "s_register_operand" "r")
1420 (const_int 16))
1421 (ashiftrt:SI
1422 (match_operand:SI 2 "s_register_operand" "r")
1423 (const_int 16))))]
1424 "TARGET_ARM && arm_arch5e"
1425 "smultt%?\\t%0, %1, %2"
1426 [(set_attr "type" "mult")
1427 (set_attr "predicable" "yes")]
331beb1a 1428)
1429
1430(define_insn "*mulhisi3addsi"
1431 [(set (match_operand:SI 0 "s_register_operand" "=r")
1432 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1433 (mult:SI (sign_extend:SI
1434 (match_operand:HI 2 "s_register_operand" "%r"))
1435 (sign_extend:SI
1436 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1437 "TARGET_ARM && arm_arch5e"
61a2d04c 1438 "smlabb%?\\t%0, %2, %3, %1"
fec538d9 1439 [(set_attr "type" "mult")
1440 (set_attr "predicable" "yes")]
331beb1a 1441)
1442
1443(define_insn "*mulhidi3adddi"
1444 [(set (match_operand:DI 0 "s_register_operand" "=r")
1445 (plus:DI
1446 (match_operand:DI 1 "s_register_operand" "0")
1447 (mult:DI (sign_extend:DI
1448 (match_operand:HI 2 "s_register_operand" "%r"))
1449 (sign_extend:DI
1450 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1451 "TARGET_ARM && arm_arch5e"
331beb1a 1452 "smlalbb%?\\t%Q0, %R0, %2, %3"
fec538d9 1453 [(set_attr "type" "mult")
1454 (set_attr "predicable" "yes")])
331beb1a 1455
604f3a0a 1456(define_expand "mulsf3"
1457 [(set (match_operand:SF 0 "s_register_operand" "")
1458 (mult:SF (match_operand:SF 1 "s_register_operand" "")
e8ff69a4 1459 (match_operand:SF 2 "fpa_rhs_operand" "")))]
604f3a0a 1460 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1461 "
1462 if (TARGET_CIRRUS
1463 && !cirrus_fp_register (operands[2], SFmode))
1464 operands[2] = force_reg (SFmode, operands[2]);
1465")
1466
7d57ec45 1467(define_insn "*arm_mulsf3"
9c08d1fa 1468 [(set (match_operand:SF 0 "s_register_operand" "=f")
1469 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
e8ff69a4 1470 (match_operand:SF 2 "fpa_rhs_operand" "fG")))]
cffb2a26 1471 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1472 "fml%?s\\t%0, %1, %2"
0d66636f 1473 [(set_attr "type" "ffmul")
1474 (set_attr "predicable" "yes")]
1475)
b11cae9e 1476
604f3a0a 1477(define_expand "muldf3"
1478 [(set (match_operand:DF 0 "s_register_operand" "")
1479 (mult:DF (match_operand:DF 1 "s_register_operand" "")
e8ff69a4 1480 (match_operand:DF 2 "fpa_rhs_operand" "")))]
604f3a0a 1481 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1482 "
1483 if (TARGET_CIRRUS
1484 && !cirrus_fp_register (operands[2], DFmode))
1485 operands[2] = force_reg (DFmode, operands[2]);
1486")
1487
7d57ec45 1488(define_insn "*arm_muldf3"
9c08d1fa 1489 [(set (match_operand:DF 0 "s_register_operand" "=f")
1490 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
e8ff69a4 1491 (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
cffb2a26 1492 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1493 "muf%?d\\t%0, %1, %2"
0d66636f 1494 [(set_attr "type" "fmul")
1495 (set_attr "predicable" "yes")]
1496)
9c08d1fa 1497
f7fbdd4a 1498(define_insn "*muldf_esfdf_df"
9c08d1fa 1499 [(set (match_operand:DF 0 "s_register_operand" "=f")
1500 (mult:DF (float_extend:DF
1501 (match_operand:SF 1 "s_register_operand" "f"))
e8ff69a4 1502 (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
cffb2a26 1503 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1504 "muf%?d\\t%0, %1, %2"
0d66636f 1505 [(set_attr "type" "fmul")
1506 (set_attr "predicable" "yes")]
1507)
9c08d1fa 1508
f7fbdd4a 1509(define_insn "*muldf_df_esfdf"
9c08d1fa 1510 [(set (match_operand:DF 0 "s_register_operand" "=f")
1511 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1512 (float_extend:DF
1513 (match_operand:SF 2 "s_register_operand" "f"))))]
cffb2a26 1514 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1515 "muf%?d\\t%0, %1, %2"
0d66636f 1516 [(set_attr "type" "fmul")
1517 (set_attr "predicable" "yes")]
1518)
9c08d1fa 1519
f7fbdd4a 1520(define_insn "*muldf_esfdf_esfdf"
9c08d1fa 1521 [(set (match_operand:DF 0 "s_register_operand" "=f")
215b30b3 1522 (mult:DF
1523 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1524 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
cffb2a26 1525 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1526 "muf%?d\\t%0, %1, %2"
0d66636f 1527 [(set_attr "type" "fmul")
1528 (set_attr "predicable" "yes")]
1529)
b11cae9e 1530\f
1531;; Division insns
1532
1533(define_insn "divsf3"
9c08d1fa 1534 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
e8ff69a4 1535 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "f,G")
1536 (match_operand:SF 2 "fpa_rhs_operand" "fG,f")))]
cffb2a26 1537 "TARGET_ARM && TARGET_HARD_FLOAT"
e2348bcb 1538 "@
40dbec34 1539 fdv%?s\\t%0, %1, %2
1540 frd%?s\\t%0, %2, %1"
0d66636f 1541 [(set_attr "type" "fdivs")
1542 (set_attr "predicable" "yes")]
1543)
b11cae9e 1544
1545(define_insn "divdf3"
9c08d1fa 1546 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
e8ff69a4 1547 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "f,G")
1548 (match_operand:DF 2 "fpa_rhs_operand" "fG,f")))]
cffb2a26 1549 "TARGET_ARM && TARGET_HARD_FLOAT"
e2348bcb 1550 "@
40dbec34 1551 dvf%?d\\t%0, %1, %2
1552 rdf%?d\\t%0, %2, %1"
0d66636f 1553 [(set_attr "type" "fdivd")
1554 (set_attr "predicable" "yes")]
1555)
9c08d1fa 1556
f7fbdd4a 1557(define_insn "*divdf_esfdf_df"
9c08d1fa 1558 [(set (match_operand:DF 0 "s_register_operand" "=f")
1559 (div:DF (float_extend:DF
1560 (match_operand:SF 1 "s_register_operand" "f"))
e8ff69a4 1561 (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
cffb2a26 1562 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1563 "dvf%?d\\t%0, %1, %2"
0d66636f 1564 [(set_attr "type" "fdivd")
1565 (set_attr "predicable" "yes")]
1566)
9c08d1fa 1567
f7fbdd4a 1568(define_insn "*divdf_df_esfdf"
9c08d1fa 1569 [(set (match_operand:DF 0 "s_register_operand" "=f")
e8ff69a4 1570 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "fG")
9c08d1fa 1571 (float_extend:DF
1572 (match_operand:SF 2 "s_register_operand" "f"))))]
cffb2a26 1573 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1574 "rdf%?d\\t%0, %2, %1"
0d66636f 1575 [(set_attr "type" "fdivd")
1576 (set_attr "predicable" "yes")]
1577)
9c08d1fa 1578
f7fbdd4a 1579(define_insn "*divdf_esfdf_esfdf"
9c08d1fa 1580 [(set (match_operand:DF 0 "s_register_operand" "=f")
1581 (div:DF (float_extend:DF
1582 (match_operand:SF 1 "s_register_operand" "f"))
1583 (float_extend:DF
1584 (match_operand:SF 2 "s_register_operand" "f"))))]
cffb2a26 1585 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1586 "dvf%?d\\t%0, %1, %2"
0d66636f 1587 [(set_attr "type" "fdivd")
1588 (set_attr "predicable" "yes")]
1589)
b11cae9e 1590\f
1591;; Modulo insns
1592
1593(define_insn "modsf3"
9c08d1fa 1594 [(set (match_operand:SF 0 "s_register_operand" "=f")
1595 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
e8ff69a4 1596 (match_operand:SF 2 "fpa_rhs_operand" "fG")))]
cffb2a26 1597 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1598 "rmf%?s\\t%0, %1, %2"
0d66636f 1599 [(set_attr "type" "fdivs")
1600 (set_attr "predicable" "yes")]
1601)
b11cae9e 1602
1603(define_insn "moddf3"
9c08d1fa 1604 [(set (match_operand:DF 0 "s_register_operand" "=f")
1605 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
e8ff69a4 1606 (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
cffb2a26 1607 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1608 "rmf%?d\\t%0, %1, %2"
0d66636f 1609 [(set_attr "type" "fdivd")
1610 (set_attr "predicable" "yes")]
1611)
9c08d1fa 1612
f7fbdd4a 1613(define_insn "*moddf_esfdf_df"
9c08d1fa 1614 [(set (match_operand:DF 0 "s_register_operand" "=f")
1615 (mod:DF (float_extend:DF
1616 (match_operand:SF 1 "s_register_operand" "f"))
e8ff69a4 1617 (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
cffb2a26 1618 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1619 "rmf%?d\\t%0, %1, %2"
0d66636f 1620 [(set_attr "type" "fdivd")
1621 (set_attr "predicable" "yes")]
1622)
9c08d1fa 1623
f7fbdd4a 1624(define_insn "*moddf_df_esfdf"
9c08d1fa 1625 [(set (match_operand:DF 0 "s_register_operand" "=f")
1626 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1627 (float_extend:DF
1628 (match_operand:SF 2 "s_register_operand" "f"))))]
cffb2a26 1629 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1630 "rmf%?d\\t%0, %1, %2"
0d66636f 1631 [(set_attr "type" "fdivd")
1632 (set_attr "predicable" "yes")]
1633)
9c08d1fa 1634
f7fbdd4a 1635(define_insn "*moddf_esfdf_esfdf"
9c08d1fa 1636 [(set (match_operand:DF 0 "s_register_operand" "=f")
1637 (mod:DF (float_extend:DF
1638 (match_operand:SF 1 "s_register_operand" "f"))
1639 (float_extend:DF
1640 (match_operand:SF 2 "s_register_operand" "f"))))]
cffb2a26 1641 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 1642 "rmf%?d\\t%0, %1, %2"
0d66636f 1643 [(set_attr "type" "fdivd")
1644 (set_attr "predicable" "yes")]
1645)
b11cae9e 1646\f
1647;; Boolean and,ior,xor insns
1648
f6ebffac 1649;; Split up double word logical operations
1650
1651;; Split up simple DImode logical operations. Simply perform the logical
1652;; operation on the upper and lower halves of the registers.
1653(define_split
1654 [(set (match_operand:DI 0 "s_register_operand" "")
1655 (match_operator:DI 6 "logical_binary_operator"
1656 [(match_operand:DI 1 "s_register_operand" "")
1657 (match_operand:DI 2 "s_register_operand" "")]))]
cffb2a26 1658 "TARGET_ARM && reload_completed"
f6ebffac 1659 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1660 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1661 "
215b30b3 1662 {
1663 operands[3] = gen_highpart (SImode, operands[0]);
1664 operands[0] = gen_lowpart (SImode, operands[0]);
1665 operands[4] = gen_highpart (SImode, operands[1]);
1666 operands[1] = gen_lowpart (SImode, operands[1]);
1667 operands[5] = gen_highpart (SImode, operands[2]);
1668 operands[2] = gen_lowpart (SImode, operands[2]);
1669 }"
1670)
f6ebffac 1671
f6ebffac 1672(define_split
1673 [(set (match_operand:DI 0 "s_register_operand" "")
1674 (match_operator:DI 6 "logical_binary_operator"
1675 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1676 (match_operand:DI 1 "s_register_operand" "")]))]
cffb2a26 1677 "TARGET_ARM && reload_completed"
f6ebffac 1678 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1679 (set (match_dup 3) (match_op_dup:SI 6
1680 [(ashiftrt:SI (match_dup 2) (const_int 31))
1681 (match_dup 4)]))]
1682 "
215b30b3 1683 {
1684 operands[3] = gen_highpart (SImode, operands[0]);
1685 operands[0] = gen_lowpart (SImode, operands[0]);
1686 operands[4] = gen_highpart (SImode, operands[1]);
1687 operands[1] = gen_lowpart (SImode, operands[1]);
1688 operands[5] = gen_highpart (SImode, operands[2]);
1689 operands[2] = gen_lowpart (SImode, operands[2]);
1690 }"
1691)
f6ebffac 1692
f6ebffac 1693;; The zero extend of operand 2 means we can just copy the high part of
1694;; operand1 into operand0.
1695(define_split
1696 [(set (match_operand:DI 0 "s_register_operand" "")
1697 (ior:DI
1698 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1699 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1700 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1701 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1702 (set (match_dup 3) (match_dup 4))]
1703 "
215b30b3 1704 {
1705 operands[4] = gen_highpart (SImode, operands[1]);
1706 operands[3] = gen_highpart (SImode, operands[0]);
1707 operands[0] = gen_lowpart (SImode, operands[0]);
1708 operands[1] = gen_lowpart (SImode, operands[1]);
1709 }"
1710)
f6ebffac 1711
1712;; The zero extend of operand 2 means we can just copy the high part of
1713;; operand1 into operand0.
1714(define_split
1715 [(set (match_operand:DI 0 "s_register_operand" "")
1716 (xor:DI
1717 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1718 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1719 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1720 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1721 (set (match_dup 3) (match_dup 4))]
1722 "
215b30b3 1723 {
1724 operands[4] = gen_highpart (SImode, operands[1]);
1725 operands[3] = gen_highpart (SImode, operands[0]);
1726 operands[0] = gen_lowpart (SImode, operands[0]);
1727 operands[1] = gen_lowpart (SImode, operands[1]);
1728 }"
1729)
f6ebffac 1730
b11cae9e 1731(define_insn "anddi3"
cffb2a26 1732 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1733 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1734 (match_operand:DI 2 "s_register_operand" "r,r")))]
1735 "TARGET_ARM"
f6ebffac 1736 "#"
215b30b3 1737 [(set_attr "length" "8")]
1738)
b11cae9e 1739
a0f94409 1740(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1741 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1742 (and:DI (zero_extend:DI
1743 (match_operand:SI 2 "s_register_operand" "r,r"))
1744 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 1745 "TARGET_ARM"
f6ebffac 1746 "#"
a0f94409 1747 "TARGET_ARM && reload_completed"
1748 ; The zero extend of operand 2 clears the high word of the output
1749 ; operand.
1750 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1751 (set (match_dup 3) (const_int 0))]
1752 "
1753 {
1754 operands[3] = gen_highpart (SImode, operands[0]);
1755 operands[0] = gen_lowpart (SImode, operands[0]);
1756 operands[1] = gen_lowpart (SImode, operands[1]);
1757 }"
215b30b3 1758 [(set_attr "length" "8")]
1759)
b11cae9e 1760
f7fbdd4a 1761(define_insn "*anddi_sesdi_di"
cffb2a26 1762 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1763 (and:DI (sign_extend:DI
1764 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1765 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1766 "TARGET_ARM"
f6ebffac 1767 "#"
cffb2a26 1768 [(set_attr "length" "8")]
1769)
b11cae9e 1770
87b22bf7 1771(define_expand "andsi3"
cffb2a26 1772 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1773 (and:SI (match_operand:SI 1 "s_register_operand" "")
1774 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1775 "TARGET_EITHER"
87b22bf7 1776 "
cffb2a26 1777 if (TARGET_ARM)
87b22bf7 1778 {
cffb2a26 1779 if (GET_CODE (operands[2]) == CONST_INT)
1780 {
1781 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1782 operands[1],
935d87ee 1783 (no_new_pseudos
cffb2a26 1784 ? 0 : preserve_subexpressions_p ()));
1785 DONE;
1786 }
87b22bf7 1787 }
cffb2a26 1788 else /* TARGET_THUMB */
1789 {
1790 if (GET_CODE (operands[2]) != CONST_INT)
1791 operands[2] = force_reg (SImode, operands[2]);
1792 else
1793 {
1794 int i;
1795
215b30b3 1796 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1797 {
215b30b3 1798 operands[2] = force_reg (SImode,
1799 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1800
1801 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1802
1803 DONE;
1804 }
87b22bf7 1805
cffb2a26 1806 for (i = 9; i <= 31; i++)
1807 {
1808 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1809 {
1810 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1811 const0_rtx));
1812 DONE;
1813 }
215b30b3 1814 else if ((((HOST_WIDE_INT) 1) << i) - 1
1815 == ~INTVAL (operands[2]))
cffb2a26 1816 {
1817 rtx shift = GEN_INT (i);
1818 rtx reg = gen_reg_rtx (SImode);
1819
1820 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1821 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1822
1823 DONE;
1824 }
1825 }
1826
1827 operands[2] = force_reg (SImode, operands[2]);
1828 }
215b30b3 1829 }
1830 "
cffb2a26 1831)
1832
a0f94409 1833(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1834 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1835 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1836 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
cffb2a26 1837 "TARGET_ARM"
5565501b 1838 "@
1839 and%?\\t%0, %1, %2
87b22bf7 1840 bic%?\\t%0, %1, #%B2
1841 #"
a0f94409 1842 "TARGET_ARM
1843 && GET_CODE (operands[2]) == CONST_INT
1844 && !(const_ok_for_arm (INTVAL (operands[2]))
1845 || const_ok_for_arm (~INTVAL (operands[2])))"
1846 [(clobber (const_int 0))]
1847 "
1848 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1849 operands[1], 0);
1850 DONE;
1851 "
0d66636f 1852 [(set_attr "length" "4,4,16")
1853 (set_attr "predicable" "yes")]
cffb2a26 1854)
1855
1856(define_insn "*thumb_andsi3_insn"
1857 [(set (match_operand:SI 0 "register_operand" "=l")
1858 (and:SI (match_operand:SI 1 "register_operand" "%0")
1859 (match_operand:SI 2 "register_operand" "l")))]
1860 "TARGET_THUMB"
1861 "and\\t%0, %0, %2"
1862 [(set_attr "length" "2")]
1863)
87b22bf7 1864
f7fbdd4a 1865(define_insn "*andsi3_compare0"
bd5b4116 1866 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1867 (compare:CC_NOOV
1868 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1869 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1870 (const_int 0)))
cffb2a26 1871 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1872 (and:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1873 "TARGET_ARM"
5565501b 1874 "@
1875 and%?s\\t%0, %1, %2
1876 bic%?s\\t%0, %1, #%B2"
cffb2a26 1877 [(set_attr "conds" "set")]
1878)
9c08d1fa 1879
f7fbdd4a 1880(define_insn "*andsi3_compare0_scratch"
bd5b4116 1881 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1882 (compare:CC_NOOV
1883 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1884 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1885 (const_int 0)))
dd193d7c 1886 (clobber (match_scratch:SI 2 "=X,r"))]
cffb2a26 1887 "TARGET_ARM"
5565501b 1888 "@
1889 tst%?\\t%0, %1
dd193d7c 1890 bic%?s\\t%2, %0, #%B1"
0d66636f 1891 [(set_attr "conds" "set")]
1892)
9c08d1fa 1893
f7fbdd4a 1894(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 1895 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1896 (compare:CC_NOOV (zero_extract:SI
1897 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 1898 (match_operand 1 "const_int_operand" "n")
1899 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 1900 (const_int 0)))]
cffb2a26 1901 "TARGET_ARM
1902 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1903 && INTVAL (operands[1]) > 0
1904 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1905 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 1906 "*
5c49a439 1907 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1908 << INTVAL (operands[2]));
40dbec34 1909 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 1910 return \"\";
0d66636f 1911 "
1912 [(set_attr "conds" "set")]
1913)
9c08d1fa 1914
c4034607 1915(define_insn "*ne_zeroextractsi"
1916 [(set (match_operand:SI 0 "s_register_operand" "=r")
1917 (ne:SI (zero_extract:SI
1918 (match_operand:SI 1 "s_register_operand" "r")
1919 (match_operand:SI 2 "const_int_operand" "n")
1920 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 1921 (const_int 0)))
1922 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1923 "TARGET_ARM
1924 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1925 && INTVAL (operands[2]) > 0
1926 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1927 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
9c08d1fa 1928 "*
c4034607 1929 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1930 << INTVAL (operands[3]));
1931 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1932 return \"movne\\t%0, #1\";
0d66636f 1933 "
1934 [(set_attr "conds" "clob")
215b30b3 1935 (set_attr "length" "8")]
1936)
9c08d1fa 1937
a42059fd 1938;;; ??? This pattern is bogus. If operand3 has bits outside the range
1939;;; represented by the bitfield, then this will produce incorrect results.
1940;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 1941;;; which have a real bit-field insert instruction, the truncation happens
1942;;; in the bit-field insert instruction itself. Since arm does not have a
1943;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 1944;;; the value before we insert. This loses some of the advantage of having
1945;;; this insv pattern, so this pattern needs to be reevalutated.
1946
8a18b90c 1947(define_expand "insv"
1948 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1949 (match_operand:SI 1 "general_operand" "")
1950 (match_operand:SI 2 "general_operand" ""))
19335226 1951 (match_operand:SI 3 "reg_or_int_operand" ""))]
cffb2a26 1952 "TARGET_ARM"
8a18b90c 1953 "
215b30b3 1954 {
1955 int start_bit = INTVAL (operands[2]);
1956 int width = INTVAL (operands[1]);
1957 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1958 rtx target, subtarget;
1959
1960 target = operands[0];
1961 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1962 subreg as the final target. */
1963 if (GET_CODE (target) == SUBREG)
1964 {
1965 subtarget = gen_reg_rtx (SImode);
1966 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1967 < GET_MODE_SIZE (SImode))
1968 target = SUBREG_REG (target);
1969 }
1970 else
1971 subtarget = target;
8a18b90c 1972
215b30b3 1973 if (GET_CODE (operands[3]) == CONST_INT)
1974 {
1975 /* Since we are inserting a known constant, we may be able to
1976 reduce the number of bits that we have to clear so that
1977 the mask becomes simple. */
1978 /* ??? This code does not check to see if the new mask is actually
1979 simpler. It may not be. */
1980 rtx op1 = gen_reg_rtx (SImode);
1981 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1982 start of this pattern. */
1983 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1984 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1985
1986 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1987 emit_insn (gen_iorsi3 (subtarget, op1,
1988 GEN_INT (op3_value << start_bit)));
1989 }
1990 else if (start_bit == 0
1991 && !(const_ok_for_arm (mask)
1992 || const_ok_for_arm (~mask)))
1993 {
1994 /* A Trick, since we are setting the bottom bits in the word,
1995 we can shift operand[3] up, operand[0] down, OR them together
1996 and rotate the result back again. This takes 3 insns, and
1997 the third might be mergable into another op. */
1998 /* The shift up copes with the possibility that operand[3] is
1999 wider than the bitfield. */
2000 rtx op0 = gen_reg_rtx (SImode);
2001 rtx op1 = gen_reg_rtx (SImode);
2002
2003 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2004 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2005 emit_insn (gen_iorsi3 (op1, op1, op0));
2006 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2007 }
2008 else if ((width + start_bit == 32)
2009 && !(const_ok_for_arm (mask)
2010 || const_ok_for_arm (~mask)))
2011 {
2012 /* Similar trick, but slightly less efficient. */
8a18b90c 2013
215b30b3 2014 rtx op0 = gen_reg_rtx (SImode);
2015 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 2016
215b30b3 2017 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2018 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2019 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2020 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2021 }
2022 else
2023 {
2024 rtx op0 = GEN_INT (mask);
2025 rtx op1 = gen_reg_rtx (SImode);
2026 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 2027
215b30b3 2028 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2029 {
2030 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2031
215b30b3 2032 emit_insn (gen_movsi (tmp, op0));
2033 op0 = tmp;
2034 }
8a18b90c 2035
215b30b3 2036 /* Mask out any bits in operand[3] that are not needed. */
2037 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 2038
215b30b3 2039 if (GET_CODE (op0) == CONST_INT
2040 && (const_ok_for_arm (mask << start_bit)
2041 || const_ok_for_arm (~(mask << start_bit))))
2042 {
2043 op0 = GEN_INT (~(mask << start_bit));
2044 emit_insn (gen_andsi3 (op2, operands[0], op0));
2045 }
2046 else
2047 {
2048 if (GET_CODE (op0) == CONST_INT)
2049 {
2050 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 2051
215b30b3 2052 emit_insn (gen_movsi (tmp, op0));
2053 op0 = tmp;
2054 }
2055
2056 if (start_bit != 0)
2057 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 2058
215b30b3 2059 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2060 }
8a18b90c 2061
215b30b3 2062 if (start_bit != 0)
2063 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 2064
215b30b3 2065 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2066 }
f082f1c4 2067
215b30b3 2068 if (subtarget != target)
2069 {
2070 /* If TARGET is still a SUBREG, then it must be wider than a word,
2071 so we must be careful only to set the subword we were asked to. */
2072 if (GET_CODE (target) == SUBREG)
2073 emit_move_insn (target, subtarget);
2074 else
2075 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2076 }
8a18b90c 2077
215b30b3 2078 DONE;
2079 }"
2080)
8a18b90c 2081
215b30b3 2082; constants for op 2 will never be given to these patterns.
a0f94409 2083(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2084 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2085 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2086 (match_operand:DI 2 "s_register_operand" "0,r")))]
cffb2a26 2087 "TARGET_ARM"
f6ebffac 2088 "#"
a0f94409 2089 "TARGET_ARM && reload_completed"
2090 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2091 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2092 "
2093 {
2094 operands[3] = gen_highpart (SImode, operands[0]);
2095 operands[0] = gen_lowpart (SImode, operands[0]);
2096 operands[4] = gen_highpart (SImode, operands[1]);
2097 operands[1] = gen_lowpart (SImode, operands[1]);
2098 operands[5] = gen_highpart (SImode, operands[2]);
2099 operands[2] = gen_lowpart (SImode, operands[2]);
2100 }"
0d66636f 2101 [(set_attr "length" "8")
2102 (set_attr "predicable" "yes")]
2103)
9c08d1fa 2104
a0f94409 2105(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2106 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2107 (and:DI (not:DI (zero_extend:DI
2108 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2109 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2110 "TARGET_ARM"
e2348bcb 2111 "@
97499065 2112 bic%?\\t%Q0, %Q1, %2
f6ebffac 2113 #"
a0f94409 2114 ; (not (zero_extend ...)) allows us to just copy the high word from
2115 ; operand1 to operand0.
2116 "TARGET_ARM
2117 && reload_completed
2118 && operands[0] != operands[1]"
5a097f7d 2119 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2120 (set (match_dup 3) (match_dup 4))]
2121 "
2122 {
2123 operands[3] = gen_highpart (SImode, operands[0]);
2124 operands[0] = gen_lowpart (SImode, operands[0]);
2125 operands[4] = gen_highpart (SImode, operands[1]);
2126 operands[1] = gen_lowpart (SImode, operands[1]);
2127 }"
0d66636f 2128 [(set_attr "length" "4,8")
2129 (set_attr "predicable" "yes")]
2130)
9c08d1fa 2131
a0f94409 2132(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2133 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2134 (and:DI (not:DI (sign_extend:DI
2135 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2136 (match_operand:DI 1 "s_register_operand" "0,r")))]
cffb2a26 2137 "TARGET_ARM"
f6ebffac 2138 "#"
a0f94409 2139 "TARGET_ARM && reload_completed"
5a097f7d 2140 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2141 (set (match_dup 3) (and:SI (not:SI
2142 (ashiftrt:SI (match_dup 2) (const_int 31)))
2143 (match_dup 4)))]
2144 "
2145 {
2146 operands[3] = gen_highpart (SImode, operands[0]);
2147 operands[0] = gen_lowpart (SImode, operands[0]);
2148 operands[4] = gen_highpart (SImode, operands[1]);
2149 operands[1] = gen_lowpart (SImode, operands[1]);
2150 }"
0d66636f 2151 [(set_attr "length" "8")
2152 (set_attr "predicable" "yes")]
2153)
9c08d1fa 2154
8a18b90c 2155(define_insn "andsi_notsi_si"
9c08d1fa 2156 [(set (match_operand:SI 0 "s_register_operand" "=r")
2157 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2158 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2159 "TARGET_ARM"
0d66636f 2160 "bic%?\\t%0, %1, %2"
2161 [(set_attr "predicable" "yes")]
2162)
b11cae9e 2163
cffb2a26 2164(define_insn "bicsi3"
2165 [(set (match_operand:SI 0 "register_operand" "=l")
2166 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2167 (match_operand:SI 2 "register_operand" "0")))]
2168 "TARGET_THUMB"
2169 "bic\\t%0, %0, %1"
2170 [(set_attr "length" "2")]
2171)
2172
8a18b90c 2173(define_insn "andsi_not_shiftsi_si"
cffb2a26 2174 [(set (match_operand:SI 0 "s_register_operand" "=r")
2175 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2176 [(match_operand:SI 2 "s_register_operand" "r")
2177 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2178 (match_operand:SI 1 "s_register_operand" "r")))]
2179 "TARGET_ARM"
6c4c2133 2180 "bic%?\\t%0, %1, %2%S4"
344495ea 2181 [(set_attr "predicable" "yes")
331beb1a 2182 (set_attr "shift" "2")
344495ea 2183 ]
6c4c2133 2184)
8a18b90c 2185
f7fbdd4a 2186(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2187 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2188 (compare:CC_NOOV
2189 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2190 (match_operand:SI 1 "s_register_operand" "r"))
2191 (const_int 0)))
9c08d1fa 2192 (set (match_operand:SI 0 "s_register_operand" "=r")
2193 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
cffb2a26 2194 "TARGET_ARM"
40dbec34 2195 "bic%?s\\t%0, %1, %2"
0d66636f 2196 [(set_attr "conds" "set")]
2197)
9c08d1fa 2198
f7fbdd4a 2199(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2200 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2201 (compare:CC_NOOV
2202 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2203 (match_operand:SI 1 "s_register_operand" "r"))
2204 (const_int 0)))
9c08d1fa 2205 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2206 "TARGET_ARM"
40dbec34 2207 "bic%?s\\t%0, %1, %2"
0d66636f 2208 [(set_attr "conds" "set")]
2209)
9c08d1fa 2210
2211(define_insn "iordi3"
cffb2a26 2212 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2213 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2214 (match_operand:DI 2 "s_register_operand" "r,r")))]
2215 "TARGET_ARM"
f6ebffac 2216 "#"
0d66636f 2217 [(set_attr "length" "8")
2218 (set_attr "predicable" "yes")]
cffb2a26 2219)
9c08d1fa 2220
f7fbdd4a 2221(define_insn "*iordi_zesidi_di"
9c08d1fa 2222 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2223 (ior:DI (zero_extend:DI
2224 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2225 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2226 "TARGET_ARM"
e2348bcb 2227 "@
97499065 2228 orr%?\\t%Q0, %Q1, %2
f6ebffac 2229 #"
0d66636f 2230 [(set_attr "length" "4,8")
2231 (set_attr "predicable" "yes")]
cffb2a26 2232)
9c08d1fa 2233
f7fbdd4a 2234(define_insn "*iordi_sesidi_di"
9c08d1fa 2235 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2236 (ior:DI (sign_extend:DI
2237 (match_operand:SI 2 "s_register_operand" "r,r"))
2238 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2239 "TARGET_ARM"
f6ebffac 2240 "#"
0d66636f 2241 [(set_attr "length" "8")
2242 (set_attr "predicable" "yes")]
cffb2a26 2243)
9c08d1fa 2244
87b22bf7 2245(define_expand "iorsi3"
cffb2a26 2246 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2247 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2248 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2249 "TARGET_EITHER"
87b22bf7 2250 "
2251 if (GET_CODE (operands[2]) == CONST_INT)
2252 {
cffb2a26 2253 if (TARGET_ARM)
2254 {
2255 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2256 operands[1],
935d87ee 2257 (no_new_pseudos
cffb2a26 2258 ? 0 : preserve_subexpressions_p ()));
2259 DONE;
2260 }
2261 else /* TARGET_THUMB */
2262 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2263 }
cffb2a26 2264 "
2265)
87b22bf7 2266
a0f94409 2267(define_insn_and_split "*arm_iorsi3"
cffb2a26 2268 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2269 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2270 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
cffb2a26 2271 "TARGET_ARM"
87b22bf7 2272 "@
2273 orr%?\\t%0, %1, %2
2274 #"
a0f94409 2275 "TARGET_ARM
2276 && GET_CODE (operands[2]) == CONST_INT
2277 && !const_ok_for_arm (INTVAL (operands[2]))"
2278 [(clobber (const_int 0))]
2279 "
2280 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2281 operands[1], 0);
2282 DONE;
2283 "
0d66636f 2284 [(set_attr "length" "4,16")
2285 (set_attr "predicable" "yes")]
cffb2a26 2286)
2287
2288(define_insn "*thumb_iorsi3"
2289 [(set (match_operand:SI 0 "register_operand" "=l")
2290 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2291 (match_operand:SI 2 "register_operand" "l")))]
2292 "TARGET_THUMB"
2293 "orr\\t%0, %0, %2"
2294 [(set_attr "length" "2")]
2295)
9c08d1fa 2296
a0f94409 2297(define_peephole2
2298 [(match_scratch:SI 3 "r")
2299 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2300 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2301 (match_operand:SI 2 "const_int_operand" "")))]
a0f94409 2302 "TARGET_ARM
2303 && !const_ok_for_arm (INTVAL (operands[2]))
2304 && const_ok_for_arm (~INTVAL (operands[2]))"
2305 [(set (match_dup 3) (match_dup 2))
2306 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2307 ""
215b30b3 2308)
a0f94409 2309
f7fbdd4a 2310(define_insn "*iorsi3_compare0"
bd5b4116 2311 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2312 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2313 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2314 (const_int 0)))
2315 (set (match_operand:SI 0 "s_register_operand" "=r")
2316 (ior:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2317 "TARGET_ARM"
40dbec34 2318 "orr%?s\\t%0, %1, %2"
cffb2a26 2319 [(set_attr "conds" "set")]
2320)
9c08d1fa 2321
f7fbdd4a 2322(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2323 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2324 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2325 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2326 (const_int 0)))
2327 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2328 "TARGET_ARM"
40dbec34 2329 "orr%?s\\t%0, %1, %2"
0d66636f 2330 [(set_attr "conds" "set")]
2331)
9c08d1fa 2332
2333(define_insn "xordi3"
cffb2a26 2334 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2335 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2336 (match_operand:DI 2 "s_register_operand" "r,r")))]
2337 "TARGET_ARM"
f6ebffac 2338 "#"
0d66636f 2339 [(set_attr "length" "8")
2340 (set_attr "predicable" "yes")]
cffb2a26 2341)
9c08d1fa 2342
f7fbdd4a 2343(define_insn "*xordi_zesidi_di"
9c08d1fa 2344 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2345 (xor:DI (zero_extend:DI
2346 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2347 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2348 "TARGET_ARM"
e2348bcb 2349 "@
97499065 2350 eor%?\\t%Q0, %Q1, %2
f6ebffac 2351 #"
0d66636f 2352 [(set_attr "length" "4,8")
2353 (set_attr "predicable" "yes")]
cffb2a26 2354)
9c08d1fa 2355
f7fbdd4a 2356(define_insn "*xordi_sesidi_di"
9c08d1fa 2357 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2358 (xor:DI (sign_extend:DI
2359 (match_operand:SI 2 "s_register_operand" "r,r"))
2360 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2361 "TARGET_ARM"
f6ebffac 2362 "#"
0d66636f 2363 [(set_attr "length" "8")
2364 (set_attr "predicable" "yes")]
cffb2a26 2365)
9c08d1fa 2366
cffb2a26 2367(define_expand "xorsi3"
2368 [(set (match_operand:SI 0 "s_register_operand" "")
2369 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2370 (match_operand:SI 2 "arm_rhs_operand" "")))]
2371 "TARGET_EITHER"
2372 "if (TARGET_THUMB)
2373 if (GET_CODE (operands[2]) == CONST_INT)
2374 operands[2] = force_reg (SImode, operands[2]);
2375 "
2376)
2377
2378(define_insn "*arm_xorsi3"
2379 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2380 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2381 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 2382 "TARGET_ARM"
2383 "eor%?\\t%0, %1, %2"
0d66636f 2384 [(set_attr "predicable" "yes")]
cffb2a26 2385)
2386
2387(define_insn "*thumb_xorsi3"
2388 [(set (match_operand:SI 0 "register_operand" "=l")
2389 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2390 (match_operand:SI 2 "register_operand" "l")))]
2391 "TARGET_THUMB"
2392 "eor\\t%0, %0, %2"
2393 [(set_attr "length" "2")]
2394)
9c08d1fa 2395
f7fbdd4a 2396(define_insn "*xorsi3_compare0"
bd5b4116 2397 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2398 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2399 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2400 (const_int 0)))
2401 (set (match_operand:SI 0 "s_register_operand" "=r")
2402 (xor:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2403 "TARGET_ARM"
40dbec34 2404 "eor%?s\\t%0, %1, %2"
0d66636f 2405 [(set_attr "conds" "set")]
2406)
9c08d1fa 2407
f7fbdd4a 2408(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2409 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2410 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2411 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2412 (const_int 0)))]
cffb2a26 2413 "TARGET_ARM"
40dbec34 2414 "teq%?\\t%0, %1"
cffb2a26 2415 [(set_attr "conds" "set")]
2416)
9c08d1fa 2417
215b30b3 2418; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2419; (NOT D) we can sometimes merge the final NOT into one of the following
2420; insns.
9c08d1fa 2421
2422(define_split
a058e94a 2423 [(set (match_operand:SI 0 "s_register_operand" "")
2424 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2425 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2426 (match_operand:SI 3 "arm_rhs_operand" "")))
2427 (clobber (match_operand:SI 4 "s_register_operand" ""))]
cffb2a26 2428 "TARGET_ARM"
9c08d1fa 2429 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2430 (not:SI (match_dup 3))))
2431 (set (match_dup 0) (not:SI (match_dup 4)))]
2432 ""
2433)
2434
f7fbdd4a 2435(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2436 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2437 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2438 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2439 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
cffb2a26 2440 "TARGET_ARM"
40dbec34 2441 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2442 [(set_attr "length" "8")
2443 (set_attr "predicable" "yes")]
cffb2a26 2444)
9c08d1fa 2445
2446\f
2447
2448;; Minimum and maximum insns
2449
2450(define_insn "smaxsi3"
cffb2a26 2451 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2452 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2453 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2454 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2455 "TARGET_ARM"
e2348bcb 2456 "@
2457 cmp\\t%1, %2\;movlt\\t%0, %2
2458 cmp\\t%1, %2\;movge\\t%0, %1
2459 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2460 [(set_attr "conds" "clob")
2461 (set_attr "length" "8,8,12")]
2462)
9c08d1fa 2463
2464(define_insn "sminsi3"
2465 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2466 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2467 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2468 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2469 "TARGET_ARM"
e2348bcb 2470 "@
2471 cmp\\t%1, %2\;movge\\t%0, %2
2472 cmp\\t%1, %2\;movlt\\t%0, %1
2473 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 2474 [(set_attr "conds" "clob")
2475 (set_attr "length" "8,8,12")]
2476)
9c08d1fa 2477
2478(define_insn "umaxsi3"
2479 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2480 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2481 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2482 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2483 "TARGET_ARM"
e2348bcb 2484 "@
2485 cmp\\t%1, %2\;movcc\\t%0, %2
2486 cmp\\t%1, %2\;movcs\\t%0, %1
2487 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 2488 [(set_attr "conds" "clob")
2489 (set_attr "length" "8,8,12")]
2490)
9c08d1fa 2491
2492(define_insn "uminsi3"
2493 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2494 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2495 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2496 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2497 "TARGET_ARM"
e2348bcb 2498 "@
2499 cmp\\t%1, %2\;movcs\\t%0, %2
2500 cmp\\t%1, %2\;movcc\\t%0, %1
2501 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 2502 [(set_attr "conds" "clob")
2503 (set_attr "length" "8,8,12")]
2504)
9c08d1fa 2505
8a18b90c 2506(define_insn "*store_minmaxsi"
9c08d1fa 2507 [(set (match_operand:SI 0 "memory_operand" "=m")
2508 (match_operator:SI 3 "minmax_operator"
2509 [(match_operand:SI 1 "s_register_operand" "r")
2510 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 2511 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2512 "TARGET_ARM"
9c08d1fa 2513 "*
2514 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2515 operands[2]);
e2348bcb 2516 output_asm_insn (\"cmp\\t%1, %2\", operands);
2517 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2518 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2519 return \"\";
0d66636f 2520 "
2521 [(set_attr "conds" "clob")
2522 (set_attr "length" "12")
2523 (set_attr "type" "store1")]
2524)
9c08d1fa 2525
8a18b90c 2526; Reject the frame pointer in operand[1], since reloading this after
2527; it has been eliminated can cause carnage.
f7fbdd4a 2528(define_insn "*minmax_arithsi"
9c08d1fa 2529 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2530 (match_operator:SI 4 "shiftable_operator"
2531 [(match_operator:SI 5 "minmax_operator"
2532 [(match_operand:SI 2 "s_register_operand" "r,r")
2533 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2534 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 2535 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2536 "TARGET_ARM
2537 && (GET_CODE (operands[1]) != REG
2538 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2539 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
9c08d1fa 2540 "*
0d66636f 2541 {
2542 enum rtx_code code = GET_CODE (operands[4]);
2543
2544 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2545 operands[3]);
2546 output_asm_insn (\"cmp\\t%2, %3\", operands);
2547 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2548 if (which_alternative != 0 || operands[3] != const0_rtx
2549 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2550 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2551 return \"\";
215b30b3 2552 }"
0d66636f 2553 [(set_attr "conds" "clob")
2554 (set_attr "length" "12")]
2555)
9c08d1fa 2556
b11cae9e 2557\f
2558;; Shift and rotation insns
2559
87b22bf7 2560(define_expand "ashlsi3"
cffb2a26 2561 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2562 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2563 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2564 "TARGET_EITHER"
87b22bf7 2565 "
2566 if (GET_CODE (operands[2]) == CONST_INT
2567 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2568 {
2569 emit_insn (gen_movsi (operands[0], const0_rtx));
2570 DONE;
2571 }
cffb2a26 2572 "
2573)
2574
2575(define_insn "*thumb_ashlsi3"
2576 [(set (match_operand:SI 0 "register_operand" "=l,l")
2577 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2578 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2579 "TARGET_THUMB"
2580 "lsl\\t%0, %1, %2"
2581 [(set_attr "length" "2")]
2582)
b11cae9e 2583
87b22bf7 2584(define_expand "ashrsi3"
cffb2a26 2585 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2586 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2587 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2588 "TARGET_EITHER"
87b22bf7 2589 "
2590 if (GET_CODE (operands[2]) == CONST_INT
2591 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2592 operands[2] = GEN_INT (31);
cffb2a26 2593 "
2594)
2595
2596(define_insn "*thumb_ashrsi3"
2597 [(set (match_operand:SI 0 "register_operand" "=l,l")
2598 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2599 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2600 "TARGET_THUMB"
2601 "asr\\t%0, %1, %2"
2602 [(set_attr "length" "2")]
2603)
b11cae9e 2604
87b22bf7 2605(define_expand "lshrsi3"
cffb2a26 2606 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2607 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2608 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2609 "TARGET_EITHER"
87b22bf7 2610 "
2611 if (GET_CODE (operands[2]) == CONST_INT
2612 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2613 {
2614 emit_insn (gen_movsi (operands[0], const0_rtx));
2615 DONE;
2616 }
cffb2a26 2617 "
2618)
2619
2620(define_insn "*thumb_lshrsi3"
2621 [(set (match_operand:SI 0 "register_operand" "=l,l")
2622 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2623 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2624 "TARGET_THUMB"
2625 "lsr\\t%0, %1, %2"
2626 [(set_attr "length" "2")]
2627)
b11cae9e 2628
87b22bf7 2629(define_expand "rotlsi3"
cffb2a26 2630 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2631 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2632 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2633 "TARGET_ARM"
87b22bf7 2634 "
2635 if (GET_CODE (operands[2]) == CONST_INT)
2636 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2637 else
b11cae9e 2638 {
87b22bf7 2639 rtx reg = gen_reg_rtx (SImode);
2640 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2641 operands[2] = reg;
b11cae9e 2642 }
cffb2a26 2643 "
2644)
9c08d1fa 2645
87b22bf7 2646(define_expand "rotrsi3"
cffb2a26 2647 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2648 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2649 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2650 "TARGET_EITHER"
87b22bf7 2651 "
cffb2a26 2652 if (TARGET_ARM)
2653 {
2654 if (GET_CODE (operands[2]) == CONST_INT
2655 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2656 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2657 }
2658 else /* TARGET_THUMB */
2659 {
2660 if (GET_CODE (operands [2]) == CONST_INT)
2661 operands [2] = force_reg (SImode, operands[2]);
2662 }
2663 "
2664)
87b22bf7 2665
cffb2a26 2666(define_insn "*thumb_rotrsi3"
2667 [(set (match_operand:SI 0 "register_operand" "=l")
2668 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2669 (match_operand:SI 2 "register_operand" "l")))]
2670 "TARGET_THUMB"
2671 "ror\\t%0, %0, %2"
2672 [(set_attr "length" "2")]
2673)
2674
7d57ec45 2675(define_expand "ashldi3"
2676 [(set (match_operand:DI 0 "s_register_operand" "")
2677 (ashift:DI (match_operand:DI 1 "general_operand" "")
2678 (match_operand:SI 2 "general_operand" "")))]
2679 "TARGET_ARM && (TARGET_CIRRUS)"
2680 "
2681 if (! s_register_operand (operands[1], DImode))
2682 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2683 if (! s_register_operand (operands[2], SImode))
2684 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2685 "
2686)
2687
cffb2a26 2688(define_insn "*arm_shiftsi3"
2689 [(set (match_operand:SI 0 "s_register_operand" "=r")
2690 (match_operator:SI 3 "shift_operator"
2691 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 2692 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
cffb2a26 2693 "TARGET_ARM"
6c4c2133 2694 "mov%?\\t%0, %1%S3"
344495ea 2695 [(set_attr "predicable" "yes")
331beb1a 2696 (set_attr "shift" "1")
344495ea 2697 ]
6c4c2133 2698)
87b22bf7 2699
f7fbdd4a 2700(define_insn "*shiftsi3_compare0"
bd5b4116 2701 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2702 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2703 [(match_operand:SI 1 "s_register_operand" "r")
2704 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2705 (const_int 0)))
2706 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2707 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
cffb2a26 2708 "TARGET_ARM"
87b22bf7 2709 "mov%?s\\t%0, %1%S3"
344495ea 2710 [(set_attr "conds" "set")
331beb1a 2711 (set_attr "shift" "1")
344495ea 2712 ]
0d66636f 2713)
9c08d1fa 2714
f7fbdd4a 2715(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 2716 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2717 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2718 [(match_operand:SI 1 "s_register_operand" "r")
2719 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2720 (const_int 0)))
2721 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2722 "TARGET_ARM"
87b22bf7 2723 "mov%?s\\t%0, %1%S3"
344495ea 2724 [(set_attr "conds" "set")
331beb1a 2725 (set_attr "shift" "1")
344495ea 2726 ]
0d66636f 2727)
9c08d1fa 2728
f7fbdd4a 2729(define_insn "*notsi_shiftsi"
9c08d1fa 2730 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2731 (not:SI (match_operator:SI 3 "shift_operator"
2732 [(match_operand:SI 1 "s_register_operand" "r")
2733 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 2734 "TARGET_ARM"
6c4c2133 2735 "mvn%?\\t%0, %1%S3"
344495ea 2736 [(set_attr "predicable" "yes")
331beb1a 2737 (set_attr "shift" "1")
344495ea 2738 ]
0d66636f 2739)
9c08d1fa 2740
f7fbdd4a 2741(define_insn "*notsi_shiftsi_compare0"
bd5b4116 2742 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2743 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2744 [(match_operand:SI 1 "s_register_operand" "r")
2745 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2746 (const_int 0)))
2747 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2748 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 2749 "TARGET_ARM"
87b22bf7 2750 "mvn%?s\\t%0, %1%S3"
344495ea 2751 [(set_attr "conds" "set")
331beb1a 2752 (set_attr "shift" "1")
344495ea 2753 ]
0d66636f 2754)
9c08d1fa 2755
f7fbdd4a 2756(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 2757 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2758 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2759 [(match_operand:SI 1 "s_register_operand" "r")
2760 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2761 (const_int 0)))
2762 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2763 "TARGET_ARM"
87b22bf7 2764 "mvn%?s\\t%0, %1%S3"
344495ea 2765 [(set_attr "conds" "set")
331beb1a 2766 (set_attr "shift" "1")
2767 ]
0d66636f 2768)
9c08d1fa 2769
cffb2a26 2770;; We don't really have extzv, but defining this using shifts helps
2771;; to reduce register pressure later on.
2772
2773(define_expand "extzv"
2774 [(set (match_dup 4)
2775 (ashift:SI (match_operand:SI 1 "register_operand" "")
2776 (match_operand:SI 2 "const_int_operand" "")))
2777 (set (match_operand:SI 0 "register_operand" "")
2778 (lshiftrt:SI (match_dup 4)
215b30b3 2779 (match_operand:SI 3 "const_int_operand" "")))]
cffb2a26 2780 "TARGET_THUMB"
2781 "
2782 {
2783 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2784 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2785
2786 operands[3] = GEN_INT (rshift);
2787
2788 if (lshift == 0)
2789 {
2790 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2791 DONE;
2792 }
2793
2794 operands[2] = GEN_INT (lshift);
2795 operands[4] = gen_reg_rtx (SImode);
215b30b3 2796 }"
cffb2a26 2797)
2798
b11cae9e 2799\f
2800;; Unary arithmetic insns
2801
cffb2a26 2802(define_expand "negdi2"
2803 [(parallel
2804 [(set (match_operand:DI 0 "s_register_operand" "")
2805 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 2806 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 2807 "TARGET_EITHER"
2808 "
2809 if (TARGET_THUMB)
2810 {
2811 if (GET_CODE (operands[1]) != REG)
2812 operands[1] = force_reg (SImode, operands[1]);
2813 }
215b30b3 2814 "
cffb2a26 2815)
2816
2817;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2818;; The second alternative is to allow the common case of a *full* overlap.
2819(define_insn "*arm_negdi2"
2820 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2821 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 2822 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2823 "TARGET_ARM"
97499065 2824 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 2825 [(set_attr "conds" "clob")
2826 (set_attr "length" "8")]
2827)
b11cae9e 2828
cffb2a26 2829(define_insn "*thumb_negdi2"
2830 [(set (match_operand:DI 0 "register_operand" "=&l")
2831 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 2832 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2833 "TARGET_THUMB"
2834 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2835 [(set_attr "length" "6")]
2836)
2837
2838(define_expand "negsi2"
2839 [(set (match_operand:SI 0 "s_register_operand" "")
2840 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2841 "TARGET_EITHER"
b11cae9e 2842 ""
cffb2a26 2843)
2844
2845(define_insn "*arm_negsi2"
2846 [(set (match_operand:SI 0 "s_register_operand" "=r")
2847 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2848 "TARGET_ARM"
2849 "rsb%?\\t%0, %1, #0"
0d66636f 2850 [(set_attr "predicable" "yes")]
cffb2a26 2851)
2852
2853(define_insn "*thumb_negsi2"
2854 [(set (match_operand:SI 0 "register_operand" "=l")
2855 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2856 "TARGET_THUMB"
2857 "neg\\t%0, %1"
2858 [(set_attr "length" "2")]
2859)
b11cae9e 2860
604f3a0a 2861(define_expand "negsf2"
2862 [(set (match_operand:SF 0 "s_register_operand" "")
2863 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2864 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2865 ""
2866)
2867
2868(define_expand "negdf2"
2869 [(set (match_operand:DF 0 "s_register_operand" "")
2870 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2871 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2872 "")
2873
7d57ec45 2874(define_insn "*arm_negsf2"
722f9800 2875 [(set (match_operand:SF 0 "s_register_operand" "=f")
9c08d1fa 2876 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
cffb2a26 2877 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 2878 "mnf%?s\\t%0, %1"
0d66636f 2879 [(set_attr "type" "ffarith")
2880 (set_attr "predicable" "yes")]
cffb2a26 2881)
b11cae9e 2882
7d57ec45 2883(define_insn "*arm_negdf2"
722f9800 2884 [(set (match_operand:DF 0 "s_register_operand" "=f")
9c08d1fa 2885 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
cffb2a26 2886 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 2887 "mnf%?d\\t%0, %1"
0d66636f 2888 [(set_attr "type" "ffarith")
2889 (set_attr "predicable" "yes")]
2890)
9c08d1fa 2891
f7fbdd4a 2892(define_insn "*negdf_esfdf"
9c08d1fa 2893 [(set (match_operand:DF 0 "s_register_operand" "=f")
2894 (neg:DF (float_extend:DF
2895 (match_operand:SF 1 "s_register_operand" "f"))))]
cffb2a26 2896 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 2897 "mnf%?d\\t%0, %1"
0d66636f 2898 [(set_attr "type" "ffarith")
2899 (set_attr "predicable" "yes")]
2900)
9c08d1fa 2901
9c08d1fa 2902;; abssi2 doesn't really clobber the condition codes if a different register
2903;; is being set. To keep things simple, assume during rtl manipulations that
2904;; it does, but tell the final scan operator the truth. Similarly for
2905;; (neg (abs...))
2906
604f3a0a 2907(define_expand "abssi2"
2908 [(parallel
2909 [(set (match_operand:SI 0 "s_register_operand" "")
2910 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2911 (clobber (reg:CC CC_REGNUM))])]
2912 "TARGET_ARM"
2913 "")
2914
7d57ec45 2915(define_insn "*arm_abssi2"
722f9800 2916 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 2917 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 2918 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2919 "TARGET_ARM"
e2348bcb 2920 "@
2921 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 2922 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 2923 [(set_attr "conds" "clob,*")
331beb1a 2924 (set_attr "shift" "1")
0d66636f 2925 ;; predicable can't be set based on the variant, so left as no
cffb2a26 2926 (set_attr "length" "8")]
2927)
9c08d1fa 2928
f7fbdd4a 2929(define_insn "*neg_abssi2"
9c08d1fa 2930 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2931 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 2932 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2933 "TARGET_ARM"
e2348bcb 2934 "@
2935 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 2936 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 2937 [(set_attr "conds" "clob,*")
331beb1a 2938 (set_attr "shift" "1")
0d66636f 2939 ;; predicable can't be set based on the variant, so left as no
cffb2a26 2940 (set_attr "length" "8")]
2941)
b11cae9e 2942
604f3a0a 2943(define_expand "abssf2"
2944 [(set (match_operand:SF 0 "s_register_operand" "")
2945 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2946 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2947 "")
2948
7d57ec45 2949(define_insn "*arm_abssf2"
722f9800 2950 [(set (match_operand:SF 0 "s_register_operand" "=f")
9c08d1fa 2951 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
cffb2a26 2952 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 2953 "abs%?s\\t%0, %1"
0d66636f 2954 [(set_attr "type" "ffarith")
2955 (set_attr "predicable" "yes")]
2956)
b11cae9e 2957
604f3a0a 2958(define_expand "absdf2"
2959 [(set (match_operand:DF 0 "s_register_operand" "")
2960 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2961 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2962 "")
2963
7d57ec45 2964(define_insn "*arm_absdf2"
722f9800 2965 [(set (match_operand:DF 0 "s_register_operand" "=f")
9c08d1fa 2966 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
cffb2a26 2967 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 2968 "abs%?d\\t%0, %1"
0d66636f 2969 [(set_attr "type" "ffarith")
2970 (set_attr "predicable" "yes")]
2971)
9c08d1fa 2972
f7fbdd4a 2973(define_insn "*absdf_esfdf"
9c08d1fa 2974 [(set (match_operand:DF 0 "s_register_operand" "=f")
2975 (abs:DF (float_extend:DF
2976 (match_operand:SF 1 "s_register_operand" "f"))))]
cffb2a26 2977 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 2978 "abs%?d\\t%0, %1"
0d66636f 2979 [(set_attr "type" "ffarith")
2980 (set_attr "predicable" "yes")]
2981)
9c08d1fa 2982
b11cae9e 2983(define_insn "sqrtsf2"
9c08d1fa 2984 [(set (match_operand:SF 0 "s_register_operand" "=f")
2985 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
cffb2a26 2986 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 2987 "sqt%?s\\t%0, %1"
0d66636f 2988 [(set_attr "type" "float_em")
2989 (set_attr "predicable" "yes")]
2990)
b11cae9e 2991
2992(define_insn "sqrtdf2"
9c08d1fa 2993 [(set (match_operand:DF 0 "s_register_operand" "=f")
2994 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
cffb2a26 2995 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 2996 "sqt%?d\\t%0, %1"
0d66636f 2997 [(set_attr "type" "float_em")
2998 (set_attr "predicable" "yes")]
2999)
9c08d1fa 3000
f7fbdd4a 3001(define_insn "*sqrtdf_esfdf"
9c08d1fa 3002 [(set (match_operand:DF 0 "s_register_operand" "=f")
3003 (sqrt:DF (float_extend:DF
3004 (match_operand:SF 1 "s_register_operand" "f"))))]
cffb2a26 3005 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 3006 "sqt%?d\\t%0, %1"
0d66636f 3007 [(set_attr "type" "float_em")
3008 (set_attr "predicable" "yes")]
3009)
9c08d1fa 3010
a0f94409 3011(define_insn_and_split "one_cmpldi2"
9c08d1fa 3012 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3013 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 3014 "TARGET_ARM"
f6ebffac 3015 "#"
a0f94409 3016 "TARGET_ARM && reload_completed"
3017 [(set (match_dup 0) (not:SI (match_dup 1)))
3018 (set (match_dup 2) (not:SI (match_dup 3)))]
3019 "
3020 {
3021 operands[2] = gen_highpart (SImode, operands[0]);
3022 operands[0] = gen_lowpart (SImode, operands[0]);
3023 operands[3] = gen_highpart (SImode, operands[1]);
3024 operands[1] = gen_lowpart (SImode, operands[1]);
3025 }"
0d66636f 3026 [(set_attr "length" "8")
3027 (set_attr "predicable" "yes")]
cffb2a26 3028)
b11cae9e 3029
cffb2a26 3030(define_expand "one_cmplsi2"
3031 [(set (match_operand:SI 0 "s_register_operand" "")
3032 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3033 "TARGET_EITHER"
b11cae9e 3034 ""
cffb2a26 3035)
3036
3037(define_insn "*arm_one_cmplsi2"
3038 [(set (match_operand:SI 0 "s_register_operand" "=r")
3039 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3040 "TARGET_ARM"
3041 "mvn%?\\t%0, %1"
0d66636f 3042 [(set_attr "predicable" "yes")]
cffb2a26 3043)
3044
3045(define_insn "*thumb_one_cmplsi2"
3046 [(set (match_operand:SI 0 "register_operand" "=l")
3047 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3048 "TARGET_THUMB"
3049 "mvn\\t%0, %1"
3050 [(set_attr "length" "2")]
3051)
9c08d1fa 3052
f7fbdd4a 3053(define_insn "*notsi_compare0"
bd5b4116 3054 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3055 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3056 (const_int 0)))
3057 (set (match_operand:SI 0 "s_register_operand" "=r")
3058 (not:SI (match_dup 1)))]
cffb2a26 3059 "TARGET_ARM"
40dbec34 3060 "mvn%?s\\t%0, %1"
cffb2a26 3061 [(set_attr "conds" "set")]
3062)
9c08d1fa 3063
f7fbdd4a 3064(define_insn "*notsi_compare0_scratch"
bd5b4116 3065 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3066 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3067 (const_int 0)))
3068 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3069 "TARGET_ARM"
40dbec34 3070 "mvn%?s\\t%0, %1"
cffb2a26 3071 [(set_attr "conds" "set")]
3072)
b11cae9e 3073\f
3074;; Fixed <--> Floating conversion insns
3075
604f3a0a 3076(define_expand "floatsisf2"
3077 [(set (match_operand:SF 0 "s_register_operand" "")
3078 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3079 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3080 "
3081 if (TARGET_CIRRUS)
3082 {
3083 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3084 DONE;
3085 }
3086")
3087
7d57ec45 3088(define_insn "*arm_floatsisf2"
722f9800 3089 [(set (match_operand:SF 0 "s_register_operand" "=f")
9c08d1fa 3090 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3091 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 3092 "flt%?s\\t%0, %1"
0d66636f 3093 [(set_attr "type" "r_2_f")
3094 (set_attr "predicable" "yes")]
3095)
b11cae9e 3096
604f3a0a 3097(define_expand "floatsidf2"
3098 [(set (match_operand:DF 0 "s_register_operand" "")
3099 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3100 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3101 "
3102 if (TARGET_CIRRUS)
3103 {
3104 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3105 DONE;
3106 }
3107")
3108
7d57ec45 3109(define_insn "*arm_floatsidf2"
722f9800 3110 [(set (match_operand:DF 0 "s_register_operand" "=f")
9c08d1fa 3111 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3112 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 3113 "flt%?d\\t%0, %1"
0d66636f 3114 [(set_attr "type" "r_2_f")
3115 (set_attr "predicable" "yes")]
3116)
9c08d1fa 3117
604f3a0a 3118(define_expand "fix_truncsfsi2"
3119 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3120 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
604f3a0a 3121 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3122 "
3123 if (TARGET_CIRRUS)
3124 {
3125 if (!cirrus_fp_register (operands[0], SImode))
3126 operands[0] = force_reg (SImode, operands[0]);
3127 if (!cirrus_fp_register (operands[1], SFmode))
3128 operands[1] = force_reg (SFmode, operands[0]);
3129 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3130 DONE;
3131 }
3132")
3133
7d57ec45 3134(define_insn "*arm_fix_truncsfsi2"
722f9800 3135 [(set (match_operand:SI 0 "s_register_operand" "=r")
a33d5c9c 3136 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "f"))))]
cffb2a26 3137 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 3138 "fix%?z\\t%0, %1"
0d66636f 3139 [(set_attr "type" "f_2_r")
3140 (set_attr "predicable" "yes")]
3141)
9c08d1fa 3142
604f3a0a 3143(define_expand "fix_truncdfsi2"
3144 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3145 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
604f3a0a 3146 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3147 "
3148 if (TARGET_CIRRUS)
3149 {
3150 if (!cirrus_fp_register (operands[1], DFmode))
3151 operands[1] = force_reg (DFmode, operands[0]);
3152 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3153 DONE;
3154 }
3155")
3156
7d57ec45 3157(define_insn "*arm_fix_truncdfsi2"
722f9800 3158 [(set (match_operand:SI 0 "s_register_operand" "=r")
a33d5c9c 3159 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "f"))))]
cffb2a26 3160 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 3161 "fix%?z\\t%0, %1"
0d66636f 3162 [(set_attr "type" "f_2_r")
3163 (set_attr "predicable" "yes")]
3164)
9c08d1fa 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" "")))]
3172 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3173 ""
3174)
3175
7d57ec45 3176(define_insn "*arm_truncdfsf2"
9c08d1fa 3177 [(set (match_operand:SF 0 "s_register_operand" "=f")
c8f69309 3178 (float_truncate:SF
9c08d1fa 3179 (match_operand:DF 1 "s_register_operand" "f")))]
cffb2a26 3180 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 3181 "mvf%?s\\t%0, %1"
0d66636f 3182 [(set_attr "type" "ffarith")
3183 (set_attr "predicable" "yes")]
3184)
b11cae9e 3185\f
9c08d1fa 3186;; Zero and sign extension instructions.
b11cae9e 3187
9c08d1fa 3188(define_insn "zero_extendsidi2"
3189 [(set (match_operand:DI 0 "s_register_operand" "=r")
3190 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3191 "TARGET_ARM"
9c08d1fa 3192 "*
0d66636f 3193 if (REGNO (operands[1])
3194 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3195 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3196 return \"mov%?\\t%R0, #0\";
3197 "
3198 [(set_attr "length" "8")
3199 (set_attr "predicable" "yes")]
3200)
9c08d1fa 3201
3202(define_insn "zero_extendqidi2"
cffb2a26 3203 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3204 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3205 "TARGET_ARM"
e2348bcb 3206 "@
97499065 3207 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3208 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3209 [(set_attr "length" "8")
0d66636f 3210 (set_attr "predicable" "yes")
cffb2a26 3211 (set_attr "type" "*,load")
3212 (set_attr "pool_range" "*,4092")
3213 (set_attr "neg_pool_range" "*,4084")]
3214)
9c08d1fa 3215
3216(define_insn "extendsidi2"
3217 [(set (match_operand:DI 0 "s_register_operand" "=r")
3218 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3219 "TARGET_ARM"
9c08d1fa 3220 "*
0d66636f 3221 if (REGNO (operands[1])
3222 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3223 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3224 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3225 "
3226 [(set_attr "length" "8")
331beb1a 3227 (set_attr "shift" "1")
0d66636f 3228 (set_attr "predicable" "yes")]
3229)
9c08d1fa 3230
3231(define_expand "zero_extendhisi2"
cffb2a26 3232 [(set (match_dup 2)
0d66636f 3233 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3234 (const_int 16)))
9c08d1fa 3235 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3236 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3237 "TARGET_EITHER"
9c08d1fa 3238 "
cffb2a26 3239 {
3240 if (TARGET_ARM)
3241 {
3242 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3243 {
3244 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3245 here because the insn below will generate an LDRH instruction
3246 rather than an LDR instruction, so we cannot get an unaligned
3247 word access. */
3248 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
215b30b3 3249 gen_rtx_ZERO_EXTEND (SImode,
3250 operands[1])));
cffb2a26 3251 DONE;
3252 }
3253 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3254 {
3255 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3256 DONE;
3257 }
215b30b3 3258 if (!s_register_operand (operands[1], HImode))
cffb2a26 3259 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3260 operands[1] = gen_lowpart (SImode, operands[1]);
3261 operands[2] = gen_reg_rtx (SImode);
3262 }
3263 else /* TARGET_THUMB */
3264 {
3265 if (GET_CODE (operands[1]) == MEM)
3266 {
3267 rtx tmp;
3268
3269 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3270 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3271 emit_insn (tmp);
3272 }
3273 else
3274 {
3275 rtx ops[3];
3276
215b30b3 3277 if (!s_register_operand (operands[1], HImode))
cffb2a26 3278 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3279 operands[1] = gen_lowpart (SImode, operands[1]);
3280 operands[2] = gen_reg_rtx (SImode);
3281
3282 ops[0] = operands[2];
3283 ops[1] = operands[1];
3284 ops[2] = GEN_INT (16);
3285
0d66636f 3286 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3287 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3288
3289 ops[0] = operands[0];
3290 ops[1] = operands[2];
3291 ops[2] = GEN_INT (16);
3292
0d66636f 3293 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3294 gen_rtx_LSHIFTRT (SImode, ops[1],
3295 ops[2])));
cffb2a26 3296 }
3297 DONE;
3298 }
3299 }"
3300)
3301
3302(define_insn "*thumb_zero_extendhisi2"
3303 [(set (match_operand:SI 0 "register_operand" "=l")
3304 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3305 "TARGET_THUMB"
3306 "*
3307 rtx mem = XEXP (operands[1], 0);
3308
3309 if (GET_CODE (mem) == CONST)
3310 mem = XEXP (mem, 0);
3311
3312 if (GET_CODE (mem) == LABEL_REF)
3313 return \"ldr\\t%0, %1\";
3314
3315 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3316 {
cffb2a26 3317 rtx a = XEXP (mem, 0);
3318 rtx b = XEXP (mem, 1);
3319
3320 /* This can happen due to bugs in reload. */
3321 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3322 {
3323 rtx ops[2];
3324 ops[0] = operands[0];
3325 ops[1] = a;
3326
3327 output_asm_insn (\"mov %0, %1\", ops);
3328
3329 XEXP (mem, 0) = operands[0];
3330 }
3331
3332 else if ( GET_CODE (a) == LABEL_REF
3333 && GET_CODE (b) == CONST_INT)
3334 return \"ldr\\t%0, %1\";
25f7a26e 3335 }
cffb2a26 3336
3337 return \"ldrh\\t%0, %1\";
3338 "
3339 [(set_attr "length" "4")
3340 (set_attr "type" "load")
3341 (set_attr "pool_range" "60")]
3342)
9c08d1fa 3343
cffb2a26 3344(define_insn "*arm_zero_extendhisi2"
3345 [(set (match_operand:SI 0 "s_register_operand" "=r")
3346 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3347 "TARGET_ARM && arm_arch4"
f7fbdd4a 3348 "ldr%?h\\t%0, %1"
cffb2a26 3349 [(set_attr "type" "load")
0d66636f 3350 (set_attr "predicable" "yes")
cffb2a26 3351 (set_attr "pool_range" "256")
3352 (set_attr "neg_pool_range" "244")]
3353)
f7fbdd4a 3354
206ee9a2 3355(define_split
3356 [(set (match_operand:SI 0 "s_register_operand" "")
3357 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3358 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3359 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3360 [(set (match_dup 2) (match_dup 1))
3361 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3362 "
cffb2a26 3363 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3364 FAIL;
215b30b3 3365 "
3366)
206ee9a2 3367
3368(define_split
3369 [(set (match_operand:SI 0 "s_register_operand" "")
3370 (match_operator:SI 3 "shiftable_operator"
3371 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3372 (match_operand:SI 4 "s_register_operand" "")]))
3373 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3374 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3375 [(set (match_dup 2) (match_dup 1))
3376 (set (match_dup 0)
3377 (match_op_dup 3
3378 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3379 "
cffb2a26 3380 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3381 FAIL;
215b30b3 3382 "
3383)
206ee9a2 3384
87b22bf7 3385(define_expand "zero_extendqisi2"
cffb2a26 3386 [(set (match_operand:SI 0 "s_register_operand" "")
3387 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3388 "TARGET_EITHER"
87b22bf7 3389 "
3390 if (GET_CODE (operands[1]) != MEM)
3391 {
cffb2a26 3392 if (TARGET_ARM)
3393 {
215b30b3 3394 emit_insn (gen_andsi3 (operands[0],
3395 gen_lowpart (SImode, operands[1]),
cffb2a26 3396 GEN_INT (255)));
3397 }
3398 else /* TARGET_THUMB */
3399 {
3400 rtx temp = gen_reg_rtx (SImode);
3401 rtx ops[3];
3402
3403 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3404 operands[1] = gen_lowpart (SImode, operands[1]);
3405
3406 ops[0] = temp;
3407 ops[1] = operands[1];
3408 ops[2] = GEN_INT (24);
3409
215b30b3 3410 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3411 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3412
3413 ops[0] = operands[0];
3414 ops[1] = temp;
3415 ops[2] = GEN_INT (24);
3416
215b30b3 3417 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3418 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3419 }
87b22bf7 3420 DONE;
3421 }
215b30b3 3422 "
3423)
9c08d1fa 3424
cffb2a26 3425(define_insn "*thumb_zero_extendqisi2"
3426 [(set (match_operand:SI 0 "register_operand" "=l")
3427 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3428 "TARGET_THUMB"
3429 "ldrb\\t%0, %1"
3430 [(set_attr "length" "2")
3431 (set_attr "type" "load")
3432 (set_attr "pool_range" "32")]
3433)
3434
3435(define_insn "*arm_zero_extendqisi2"
3436 [(set (match_operand:SI 0 "s_register_operand" "=r")
3437 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3438 "TARGET_ARM"
87b22bf7 3439 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
cffb2a26 3440 [(set_attr "type" "load")
0d66636f 3441 (set_attr "predicable" "yes")
cffb2a26 3442 (set_attr "pool_range" "4096")
3443 (set_attr "neg_pool_range" "4084")]
3444)
87b22bf7 3445
3446(define_split
3447 [(set (match_operand:SI 0 "s_register_operand" "")
3448 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3449 (clobber (match_operand:SI 2 "s_register_operand" ""))]
9e8503e6 3450 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 3451 [(set (match_dup 2) (match_dup 1))
3452 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 3453 ""
3454)
9c08d1fa 3455
f7fbdd4a 3456(define_insn "*compareqi_eq0"
bd5b4116 3457 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 3458 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 3459 (const_int 0)))]
cffb2a26 3460 "TARGET_ARM"
87b22bf7 3461 "tst\\t%0, #255"
cffb2a26 3462 [(set_attr "conds" "set")]
3463)
b11cae9e 3464
b11cae9e 3465(define_expand "extendhisi2"
c8f69309 3466 [(set (match_dup 2)
25f7a26e 3467 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 3468 (const_int 16)))
9c08d1fa 3469 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3470 (ashiftrt:SI (match_dup 2)
3471 (const_int 16)))]
cffb2a26 3472 "TARGET_EITHER"
b11cae9e 3473 "
cffb2a26 3474 {
3475 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3476 {
3477 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3478 here because the insn below will generate an LDRH instruction
3479 rather than an LDR instruction, so we cannot get an unaligned
3480 word access. */
3481 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3482 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3483 DONE;
3484 }
7bd8ccc9 3485
cffb2a26 3486 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3487 {
3488 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3489 DONE;
3490 }
215b30b3 3491 if (!s_register_operand (operands[1], HImode))
cffb2a26 3492 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3493 operands[1] = gen_lowpart (SImode, operands[1]);
3494 operands[2] = gen_reg_rtx (SImode);
3495
3496 if (TARGET_THUMB)
3497 {
3498 rtx ops[3];
3499
3500 ops[0] = operands[2];
3501 ops[1] = operands[1];
3502 ops[2] = GEN_INT (16);
3503
0d66636f 3504 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3505 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3506
3507 ops[0] = operands[0];
3508 ops[1] = operands[2];
3509 ops[2] = GEN_INT (16);
3510
0d66636f 3511 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3512 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3513
3514 DONE;
3515 }
3516 }"
3517)
3518
3519(define_insn "*thumb_extendhisi2_insn"
3520 [(set (match_operand:SI 0 "register_operand" "=l")
3521 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3522 (clobber (match_scratch:SI 2 "=&l"))]
3523 "TARGET_THUMB"
3524 "*
3525 {
3526 rtx ops[4];
3527 rtx mem = XEXP (operands[1], 0);
3528
3529 /* This code used to try to use 'V', and fix the address only if it was
3530 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3531 range of QImode offsets, and offsettable_address_p does a QImode
3532 address check. */
3533
3534 if (GET_CODE (mem) == CONST)
3535 mem = XEXP (mem, 0);
3536
3537 if (GET_CODE (mem) == LABEL_REF)
3538 return \"ldr\\t%0, %1\";
3539
3540 if (GET_CODE (mem) == PLUS)
3541 {
3542 rtx a = XEXP (mem, 0);
3543 rtx b = XEXP (mem, 1);
3544
3545 if (GET_CODE (a) == LABEL_REF
3546 && GET_CODE (b) == CONST_INT)
3547 return \"ldr\\t%0, %1\";
3548
3549 if (GET_CODE (b) == REG)
3550 return \"ldrsh\\t%0, %1\";
3551
3552 ops[1] = a;
3553 ops[2] = b;
3554 }
3555 else
3556 {
3557 ops[1] = mem;
3558 ops[2] = const0_rtx;
3559 }
3560
3561 if (GET_CODE (ops[1]) != REG)
3562 {
3563 debug_rtx (ops[1]);
3564 abort ();
3565 }
3566
3567 ops[0] = operands[0];
3568 ops[3] = operands[2];
3569 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3570 return \"\";
3571 }"
3572 [(set_attr "length" "4")
3573 (set_attr "type" "load")
3574 (set_attr "pool_range" "1020")]
3575)
25f7a26e 3576
3577(define_expand "extendhisi2_mem"
eab14235 3578 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 3579 (set (match_dup 3)
eab14235 3580 (zero_extend:SI (match_dup 7)))
25f7a26e 3581 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3582 (set (match_operand:SI 0 "" "")
3583 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 3584 "TARGET_ARM"
25f7a26e 3585 "
215b30b3 3586 {
3587 rtx mem1, mem2;
3588 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3589
3590 mem1 = gen_rtx_MEM (QImode, addr);
3591 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3592 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3593 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3594 operands[0] = gen_lowpart (SImode, operands[0]);
3595 operands[1] = mem1;
3596 operands[2] = gen_reg_rtx (SImode);
3597 operands[3] = gen_reg_rtx (SImode);
3598 operands[6] = gen_reg_rtx (SImode);
3599 operands[7] = mem2;
25f7a26e 3600
215b30b3 3601 if (BYTES_BIG_ENDIAN)
3602 {
3603 operands[4] = operands[2];
3604 operands[5] = operands[3];
3605 }
3606 else
3607 {
3608 operands[4] = operands[3];
3609 operands[5] = operands[2];
3610 }
3611 }"
3612)
b11cae9e 3613
cffb2a26 3614(define_insn "*arm_extendhisi_insn"
3615 [(set (match_operand:SI 0 "s_register_operand" "=r")
3616 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3617 "TARGET_ARM && arm_arch4"
f7fbdd4a 3618 "ldr%?sh\\t%0, %1"
cffb2a26 3619 [(set_attr "type" "load")
0d66636f 3620 (set_attr "predicable" "yes")
cffb2a26 3621 (set_attr "pool_range" "256")
3622 (set_attr "neg_pool_range" "244")]
3623)
f7fbdd4a 3624
206ee9a2 3625(define_split
cffb2a26 3626 [(set (match_operand:SI 0 "s_register_operand" "")
206ee9a2 3627 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
cffb2a26 3628 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3629 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3630 [(set (match_dup 2) (match_dup 1))
3631 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3632 "
cffb2a26 3633 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3634 FAIL;
cffb2a26 3635 "
3636)
206ee9a2 3637
3638(define_split
cffb2a26 3639 [(set (match_operand:SI 0 "s_register_operand" "")
3640 (match_operator:SI 3 "shiftable_operator"
206ee9a2 3641 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
cffb2a26 3642 (match_operand:SI 4 "s_register_operand" "")]))
3643 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3644 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3645 [(set (match_dup 2) (match_dup 1))
3646 (set (match_dup 0)
3647 (match_op_dup 3
3648 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
cffb2a26 3649 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3650 FAIL;
206ee9a2 3651 "
cffb2a26 3652)
206ee9a2 3653
c8f69309 3654(define_expand "extendqihi2"
3655 [(set (match_dup 2)
f7fbdd4a 3656 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 3657 (const_int 24)))
9c08d1fa 3658 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 3659 (ashiftrt:SI (match_dup 2)
3660 (const_int 24)))]
cffb2a26 3661 "TARGET_ARM"
c8f69309 3662 "
215b30b3 3663 {
3664 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3665 {
3666 emit_insn (gen_rtx_SET (VOIDmode,
3667 operands[0],
3668 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3669 DONE;
3670 }
3671 if (!s_register_operand (operands[1], QImode))
3672 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3673 operands[0] = gen_lowpart (SImode, operands[0]);
3674 operands[1] = gen_lowpart (SImode, operands[1]);
3675 operands[2] = gen_reg_rtx (SImode);
3676 }"
3677)
f7fbdd4a 3678
3fc2009e 3679; Rather than restricting all byte accesses to memory addresses that ldrsb
3680; can handle, we fix up the ones that ldrsb can't grok with a split.
f7fbdd4a 3681(define_insn "*extendqihi_insn"
cffb2a26 3682 [(set (match_operand:HI 0 "s_register_operand" "=r")
3683 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3684 "TARGET_ARM && arm_arch4"
3fc2009e 3685 "*
3686 /* If the address is invalid, this will split the instruction into two. */
cffb2a26 3687 if (bad_signed_byte_operand (operands[1], VOIDmode))
3fc2009e 3688 return \"#\";
3689 return \"ldr%?sb\\t%0, %1\";
cffb2a26 3690 "
3691 [(set_attr "type" "load")
0d66636f 3692 (set_attr "predicable" "yes")
cffb2a26 3693 (set_attr "length" "8")
3694 (set_attr "pool_range" "256")
3695 (set_attr "neg_pool_range" "244")]
3696)
3fc2009e 3697
3698(define_split
3699 [(set (match_operand:HI 0 "s_register_operand" "")
3700 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
cffb2a26 3701 "TARGET_ARM && arm_arch4 && reload_completed"
3fc2009e 3702 [(set (match_dup 3) (match_dup 1))
3703 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3704 "
3705 {
3706 HOST_WIDE_INT offset;
3707
76676c8e 3708 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3709 operands[2] = gen_rtx_MEM (QImode, operands[3]);
e4600bc3 3710 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3fc2009e 3711 operands[1] = XEXP (operands[1], 0);
3712 if (GET_CODE (operands[1]) == PLUS
3713 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
215b30b3 3714 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3715 || const_ok_for_arm (-offset)))
3fc2009e 3716 {
3717 HOST_WIDE_INT low = (offset > 0
3718 ? (offset & 0xff) : -((-offset) & 0xff));
3719 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3720 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3721 }
dbf7d203 3722 /* Ensure the sum is in correct canonical form */
3723 else if (GET_CODE (operands[1]) == PLUS
3724 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
215b30b3 3725 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
76676c8e 3726 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
9888ad6d 3727 XEXP (operands[1], 1),
3728 XEXP (operands[1], 0));
215b30b3 3729 }"
3730)
b11cae9e 3731
3732(define_expand "extendqisi2"
c8f69309 3733 [(set (match_dup 2)
3fc2009e 3734 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 3735 (const_int 24)))
9c08d1fa 3736 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3737 (ashiftrt:SI (match_dup 2)
3738 (const_int 24)))]
cffb2a26 3739 "TARGET_EITHER"
b11cae9e 3740 "
cffb2a26 3741 {
3742 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3743 {
3744 emit_insn (gen_rtx_SET (VOIDmode,
3745 operands[0],
3746 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3747 DONE;
3748 }
215b30b3 3749 if (!s_register_operand (operands[1], QImode))
cffb2a26 3750 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3751 operands[1] = gen_lowpart (SImode, operands[1]);
3752 operands[2] = gen_reg_rtx (SImode);
3753
3754 if (TARGET_THUMB)
3755 {
3756 rtx ops[3];
3757
3758 ops[0] = operands[2];
3759 ops[1] = operands[1];
3760 ops[2] = GEN_INT (24);
3761
215b30b3 3762 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3763 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3764
3765 ops[0] = operands[0];
3766 ops[1] = operands[2];
3767 ops[2] = GEN_INT (24);
3768
215b30b3 3769 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3770 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3771
3772 DONE;
3773 }
3774 }"
3775)
f7fbdd4a 3776
3fc2009e 3777; Rather than restricting all byte accesses to memory addresses that ldrsb
3778; can handle, we fix up the ones that ldrsb can't grok with a split.
cffb2a26 3779(define_insn "*arm_extendqisi_insn"
3780 [(set (match_operand:SI 0 "s_register_operand" "=r")
3781 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3782 "TARGET_ARM && arm_arch4"
3fc2009e 3783 "*
3784 /* If the address is invalid, this will split the instruction into two. */
cffb2a26 3785 if (bad_signed_byte_operand (operands[1], VOIDmode))
3fc2009e 3786 return \"#\";
3787 return \"ldr%?sb\\t%0, %1\";
cffb2a26 3788 "
3789 [(set_attr "type" "load")
0d66636f 3790 (set_attr "predicable" "yes")
cffb2a26 3791 (set_attr "length" "8")
3792 (set_attr "pool_range" "256")
3793 (set_attr "neg_pool_range" "244")]
3794)
3fc2009e 3795
3796(define_split
3797 [(set (match_operand:SI 0 "s_register_operand" "")
3798 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
cffb2a26 3799 "TARGET_ARM && arm_arch4 && reload_completed"
3fc2009e 3800 [(set (match_dup 0) (match_dup 1))
3801 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3802 "
3803 {
3804 HOST_WIDE_INT offset;
3805
76676c8e 3806 operands[2] = gen_rtx_MEM (QImode, operands[0]);
e4600bc3 3807 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3fc2009e 3808 operands[1] = XEXP (operands[1], 0);
3809 if (GET_CODE (operands[1]) == PLUS
3810 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
215b30b3 3811 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3812 || const_ok_for_arm (-offset)))
3fc2009e 3813 {
3814 HOST_WIDE_INT low = (offset > 0
3815 ? (offset & 0xff) : -((-offset) & 0xff));
3816 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3817 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3818 }
dbf7d203 3819 /* Ensure the sum is in correct canonical form */
3820 else if (GET_CODE (operands[1]) == PLUS
3821 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
215b30b3 3822 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
76676c8e 3823 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
9888ad6d 3824 XEXP (operands[1], 1),
3825 XEXP (operands[1], 0));
215b30b3 3826 }"
3827)
b11cae9e 3828
cffb2a26 3829(define_insn "*thumb_extendqisi2_insn"
3830 [(set (match_operand:SI 0 "register_operand" "=l,l")
3831 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3832 "TARGET_THUMB"
3833 "*
3834 {
3835 rtx ops[3];
3836 rtx mem = XEXP (operands[1], 0);
3837
3838 if (GET_CODE (mem) == CONST)
3839 mem = XEXP (mem, 0);
3840
3841 if (GET_CODE (mem) == LABEL_REF)
3842 return \"ldr\\t%0, %1\";
3843
3844 if (GET_CODE (mem) == PLUS
3845 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3846 return \"ldr\\t%0, %1\";
3847
3848 if (which_alternative == 0)
3849 return \"ldrsb\\t%0, %1\";
3850
3851 ops[0] = operands[0];
3852
3853 if (GET_CODE (mem) == PLUS)
3854 {
3855 rtx a = XEXP (mem, 0);
3856 rtx b = XEXP (mem, 1);
3857
3858 ops[1] = a;
3859 ops[2] = b;
3860
3861 if (GET_CODE (a) == REG)
3862 {
3863 if (GET_CODE (b) == REG)
3864 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3865 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 3866 {
3867 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3868 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3869 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3870 }
cffb2a26 3871 else
3872 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3873 }
3874 else if (GET_CODE (b) != REG)
3875 abort ();
3876 else
3877 {
3878 if (REGNO (b) == REGNO (ops[0]))
215b30b3 3879 {
3880 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3881 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3882 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3883 }
cffb2a26 3884 else
3885 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3886 }
3887 }
3888 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3889 {
215b30b3 3890 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3891 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3892 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 3893 }
3894 else
3895 {
3896 ops[1] = mem;
3897 ops[2] = const0_rtx;
3898
3899 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3900 }
3901 return \"\";
3902 }"
3903 [(set_attr "length" "2,6")
3904 (set_attr "type" "load,load")
3905 (set_attr "pool_range" "32,32")]
3906)
3907
caedf871 3908(define_expand "extendsfdf2"
3909 [(set (match_operand:DF 0 "s_register_operand" "")
3910 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3911 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3912 ""
3913)
3914
7d57ec45 3915(define_insn "*arm_extendsfdf2"
cffb2a26 3916 [(set (match_operand:DF 0 "s_register_operand" "=f")
3917 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3918 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 3919 "mvf%?d\\t%0, %1"
0d66636f 3920 [(set_attr "type" "ffarith")
3921 (set_attr "predicable" "yes")]
3922)
b11cae9e 3923\f
3924;; Move insns (including loads and stores)
3925
3926;; XXX Just some ideas about movti.
9c08d1fa 3927;; I don't think these are a good idea on the arm, there just aren't enough
3928;; registers
b11cae9e 3929;;(define_expand "loadti"
9c08d1fa 3930;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 3931;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3932;; "" "")
3933
3934;;(define_expand "storeti"
3935;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 3936;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 3937;; "" "")
3938
3939;;(define_expand "movti"
3940;; [(set (match_operand:TI 0 "general_operand" "")
3941;; (match_operand:TI 1 "general_operand" ""))]
3942;; ""
3943;; "
3944;;{
3945;; rtx insn;
3946;;
3947;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3948;; operands[1] = copy_to_reg (operands[1]);
3949;; if (GET_CODE (operands[0]) == MEM)
3950;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3951;; else if (GET_CODE (operands[1]) == MEM)
3952;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3953;; else
3954;; FAIL;
3955;;
3956;; emit_insn (insn);
3957;; DONE;
3958;;}")
3959
a2f10574 3960;; Recognize garbage generated above.
b11cae9e 3961
3962;;(define_insn ""
3963;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3964;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3965;; ""
3966;; "*
3967;; {
3968;; register mem = (which_alternative < 3);
0d66636f 3969;; register const char *template;
b11cae9e 3970;;
3971;; operands[mem] = XEXP (operands[mem], 0);
3972;; switch (which_alternative)
3973;; {
3974;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3975;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3976;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3977;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3978;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3979;; case 5: template = \"stmia\\t%0, %M1\"; break;
3980;; }
e2348bcb 3981;; output_asm_insn (template, operands);
3982;; return \"\";
b11cae9e 3983;; }")
3984
cffb2a26 3985(define_expand "movdi"
3986 [(set (match_operand:DI 0 "general_operand" "")
3987 (match_operand:DI 1 "general_operand" ""))]
3988 "TARGET_EITHER"
3989 "
3990 if (TARGET_THUMB)
3991 {
215b30b3 3992 if (!no_new_pseudos)
cffb2a26 3993 {
3994 if (GET_CODE (operands[0]) != REG)
3995 operands[1] = force_reg (DImode, operands[1]);
3996 }
3997 }
3998 "
3999)
b11cae9e 4000
cffb2a26 4001(define_insn "*arm_movdi"
215b30b3 4002 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
4003 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
7d57ec45 4004 "TARGET_ARM && !TARGET_CIRRUS"
b11cae9e 4005 "*
4006 return (output_move_double (operands));
cffb2a26 4007 "
4008 [(set_attr "length" "8")
4009 (set_attr "type" "*,load,store2")
4010 (set_attr "pool_range" "*,1020,*")
dd080cc9 4011 (set_attr "neg_pool_range" "*,1008,*")]
cffb2a26 4012)
4013
4014;;; ??? This should have alternatives for constants.
4015;;; ??? This was originally identical to the movdf_insn pattern.
4016;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4017;;; thumb_reorg with a memory reference.
4018(define_insn "*thumb_movdi_insn"
215b30b3 4019 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4020 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
cffb2a26 4021 "TARGET_THUMB
7d57ec45 4022 && !TARGET_CIRRUS
cffb2a26 4023 && ( register_operand (operands[0], DImode)
4024 || register_operand (operands[1], DImode))"
4025 "*
4026 {
4027 switch (which_alternative)
4028 {
4029 default:
4030 case 0:
4031 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4032 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4033 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4034 case 1:
4035 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4036 case 2:
4037 operands[1] = GEN_INT (- INTVAL (operands[1]));
4038 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4039 case 3:
4040 return \"ldmia\\t%1, {%0, %H0}\";
4041 case 4:
4042 return \"stmia\\t%0, {%1, %H1}\";
4043 case 5:
4044 return thumb_load_double_from_address (operands);
4045 case 6:
215b30b3 4046 operands[2] = gen_rtx (MEM, SImode,
4047 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4048 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4049 return \"\";
4050 case 7:
4051 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4052 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4053 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4054 }
4055 }"
4056 [(set_attr "length" "4,4,6,2,2,6,4,4")
4057 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4058 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4059)
b11cae9e 4060
9c08d1fa 4061(define_expand "movsi"
4062 [(set (match_operand:SI 0 "general_operand" "")
4063 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4064 "TARGET_EITHER"
9c08d1fa 4065 "
cffb2a26 4066 if (TARGET_ARM)
9c08d1fa 4067 {
cffb2a26 4068 /* Everything except mem = const or mem = mem can be done easily */
4069 if (GET_CODE (operands[0]) == MEM)
4070 operands[1] = force_reg (SImode, operands[1]);
4071 if (GET_CODE (operands[1]) == CONST_INT
4072 && !(const_ok_for_arm (INTVAL (operands[1]))
4073 || const_ok_for_arm (~INTVAL (operands[1]))))
4074 {
4075 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4076 NULL_RTX,
935d87ee 4077 (no_new_pseudos ? 0
cffb2a26 4078 : preserve_subexpressions_p ()));
4079 DONE;
4080 }
4081 }
4082 else /* TARGET_THUMB.... */
4083 {
215b30b3 4084 if (!no_new_pseudos)
cffb2a26 4085 {
4086 if (GET_CODE (operands[0]) != REG)
4087 operands[1] = force_reg (SImode, operands[1]);
4088 }
9c08d1fa 4089 }
af1b847e 4090
bbe777ea 4091 if (flag_pic
4092 && (CONSTANT_P (operands[1])
4093 || symbol_mentioned_p (operands[1])
4094 || label_mentioned_p (operands[1])))
849170fd 4095 operands[1] = legitimize_pic_address (operands[1], SImode,
935d87ee 4096 (no_new_pseudos ? operands[0] : 0));
215b30b3 4097 "
4098)
9c08d1fa 4099
cffb2a26 4100(define_insn "*arm_movsi_insn"
215b30b3 4101 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4102 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
cffb2a26 4103 "TARGET_ARM
4104 && ( register_operand (operands[0], SImode)
4105 || register_operand (operands[1], SImode))"
f7fbdd4a 4106 "@
4107 mov%?\\t%0, %1
4108 mvn%?\\t%0, #%B1
4109 ldr%?\\t%0, %1
4110 str%?\\t%1, %0"
cffb2a26 4111 [(set_attr "type" "*,*,load,store1")
0d66636f 4112 (set_attr "predicable" "yes")
cffb2a26 4113 (set_attr "pool_range" "*,*,4096,*")
4114 (set_attr "neg_pool_range" "*,*,4084,*")]
4115)
87b22bf7 4116
4117(define_split
4118 [(set (match_operand:SI 0 "s_register_operand" "")
4119 (match_operand:SI 1 "const_int_operand" ""))]
cffb2a26 4120 "TARGET_ARM
215b30b3 4121 && (!(const_ok_for_arm (INTVAL (operands[1]))
4122 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4123 [(clobber (const_int 0))]
4124 "
4125 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4126 NULL_RTX, 0);
4127 DONE;
215b30b3 4128 "
4129)
9c08d1fa 4130
cffb2a26 4131(define_insn "*thumb_movsi_insn"
215b30b3 4132 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4133 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
cffb2a26 4134 "TARGET_THUMB
4135 && ( register_operand (operands[0], SImode)
4136 || register_operand (operands[1], SImode))"
4137 "@
4138 mov %0, %1
4139 mov %0, %1
4140 #
4141 #
4142 ldmia\\t%1, {%0}
4143 stmia\\t%0, {%1}
4144 ldr\\t%0, %1
4145 str\\t%1, %0
4146 mov\\t%0, %1"
4147 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4148 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4149 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4150)
4151
4152(define_split
4153 [(set (match_operand:SI 0 "register_operand" "")
4154 (match_operand:SI 1 "const_int_operand" ""))]
4155 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4156 [(set (match_dup 0) (match_dup 1))
4157 (set (match_dup 0) (neg:SI (match_dup 0)))]
4158 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4159)
4160
4161(define_split
4162 [(set (match_operand:SI 0 "register_operand" "")
4163 (match_operand:SI 1 "const_int_operand" ""))]
4164 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4165 [(set (match_dup 0) (match_dup 1))
4166 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4167 "
4168 {
4169 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4170 unsigned HOST_WIDE_INT mask = 0xff;
4171 int i;
4172
4173 for (i = 0; i < 25; i++)
4174 if ((val & (mask << i)) == val)
4175 break;
4176
f5b3169c 4177 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4178 if (i == 0)
4179 FAIL;
4180
4181 operands[1] = GEN_INT (val >> i);
4182 operands[2] = GEN_INT (i);
4183 }"
4184)
4185
67336bcf 4186;; When generating pic, we need to load the symbol offset into a register.
4187;; So that the optimizer does not confuse this with a normal symbol load
4188;; we use an unspec. The offset will be loaded from a constant pool entry,
4189;; since that is the only type of relocation we can use.
4190
4191;; The rather odd constraints on the following are to force reload to leave
4192;; the insn alone, and to force the minipool generation pass to then move
4193;; the GOT symbol to memory.
849170fd 4194
8c4d8060 4195(define_insn "pic_load_addr_arm"
849170fd 4196 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4197 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4198 "TARGET_ARM && flag_pic"
67336bcf 4199 "ldr%?\\t%0, %1"
cffb2a26 4200 [(set_attr "type" "load")
8c4d8060 4201 (set (attr "pool_range") (const_int 4096))
4202 (set (attr "neg_pool_range") (const_int 4084))]
4203)
4204
4205(define_insn "pic_load_addr_thumb"
4206 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4207 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4208 "TARGET_THUMB && flag_pic"
4209 "ldr\\t%0, %1"
4210 [(set_attr "type" "load")
4211 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4212)
849170fd 4213
4214;; This variant is used for AOF assembly, since it needs to mention the
4215;; pic register in the rtl.
4216(define_expand "pic_load_addr_based"
4217 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4218 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
cffb2a26 4219 "TARGET_ARM && flag_pic"
4220 "operands[2] = pic_offset_table_rtx;"
4221)
849170fd 4222
4223(define_insn "*pic_load_addr_based_insn"
4224 [(set (match_operand:SI 0 "s_register_operand" "=r")
4225 (unspec:SI [(match_operand 1 "" "")
e1159bbe 4226 (match_operand 2 "s_register_operand" "r")]
4227 UNSPEC_PIC_SYM))]
cffb2a26 4228 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
849170fd 4229 "*
4230#ifdef AOF_ASSEMBLER
4231 operands[1] = aof_pic_entry (operands[1]);
4232#endif
4233 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4234 return \"\";
cffb2a26 4235 "
4236 [(set_attr "type" "load")
4237 (set (attr "pool_range")
4238 (if_then_else (eq_attr "is_thumb" "yes")
4239 (const_int 1024)
4240 (const_int 4096)))
4241 (set (attr "neg_pool_range")
4242 (if_then_else (eq_attr "is_thumb" "yes")
4243 (const_int 0)
4244 (const_int 4084)))]
4245)
4246
4247(define_insn "pic_add_dot_plus_four"
4248 [(set (match_operand:SI 0 "register_operand" "+r")
4249 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4250 (use (label_ref (match_operand 1 "" "")))]
4251 "TARGET_THUMB && flag_pic"
4252 "*
805e22b2 4253 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
cffb2a26 4254 CODE_LABEL_NUMBER (operands[1]));
4255 return \"add\\t%0, %|pc\";
4256 "
4257 [(set_attr "length" "2")]
4258)
849170fd 4259
4260(define_insn "pic_add_dot_plus_eight"
6c4c2133 4261 [(set (match_operand:SI 0 "register_operand" "+r")
c4034607 4262 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4263 (use (label_ref (match_operand 1 "" "")))]
cffb2a26 4264 "TARGET_ARM && flag_pic"
c4034607 4265 "*
805e22b2 4266 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
0d66636f 4267 CODE_LABEL_NUMBER (operands[1]));
4268 return \"add%?\\t%0, %|pc, %0\";
cffb2a26 4269 "
0d66636f 4270 [(set_attr "predicable" "yes")]
cffb2a26 4271)
849170fd 4272
95373f08 4273(define_expand "builtin_setjmp_receiver"
4274 [(label_ref (match_operand 0 "" ""))]
4275 "flag_pic"
4276 "
4277{
4278 arm_finalize_pic (0);
4279 DONE;
4280}")
4281
9c08d1fa 4282;; If copying one reg to another we can set the condition codes according to
4283;; its value. Such a move is common after a return from subroutine and the
4284;; result is being tested against zero.
4285
f7fbdd4a 4286(define_insn "*movsi_compare0"
bd5b4116 4287 [(set (reg:CC CC_REGNUM)
cffb2a26 4288 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4289 (const_int 0)))
4290 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4291 (match_dup 1))]
4292 "TARGET_ARM"
e2348bcb 4293 "@
40dbec34 4294 cmp%?\\t%0, #0
4295 sub%?s\\t%0, %1, #0"
cffb2a26 4296 [(set_attr "conds" "set")]
4297)
b11cae9e 4298
b11cae9e 4299;; Subroutine to store a half word from a register into memory.
4300;; Operand 0 is the source register (HImode)
c8f69309 4301;; Operand 1 is the destination address in a register (SImode)
b11cae9e 4302
9c08d1fa 4303;; In both this routine and the next, we must be careful not to spill
01cc3b75 4304;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 4305;; can generate unrecognizable rtl.
4306
b11cae9e 4307(define_expand "storehi"
c8f69309 4308 [;; store the low byte
f082f1c4 4309 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 4310 ;; extract the high byte
c8f69309 4311 (set (match_dup 2)
4312 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 4313 ;; store the high byte
f082f1c4 4314 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
cffb2a26 4315 "TARGET_ARM"
b11cae9e 4316 "
215b30b3 4317 {
537ffcfc 4318 rtx op1 = operands[1];
4319 rtx addr = XEXP (op1, 0);
215b30b3 4320 enum rtx_code code = GET_CODE (addr);
4321
4322 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4323 || code == MINUS)
537ffcfc 4324 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 4325
537ffcfc 4326 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4327 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4328 operands[3] = gen_lowpart (QImode, operands[0]);
4329 operands[0] = gen_lowpart (SImode, operands[0]);
4330 operands[2] = gen_reg_rtx (SImode);
4331 }"
4332)
b11cae9e 4333
c7597b5d 4334(define_expand "storehi_bigend"
f082f1c4 4335 [(set (match_dup 4) (match_dup 3))
c7597b5d 4336 (set (match_dup 2)
4337 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
9e8503e6 4338 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
cffb2a26 4339 "TARGET_ARM"
b11cae9e 4340 "
215b30b3 4341 {
537ffcfc 4342 rtx op1 = operands[1];
4343 rtx addr = XEXP (op1, 0);
215b30b3 4344 enum rtx_code code = GET_CODE (addr);
4345
4346 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4347 || code == MINUS)
537ffcfc 4348 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 4349
537ffcfc 4350 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4351 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4352 operands[3] = gen_lowpart (QImode, operands[0]);
4353 operands[0] = gen_lowpart (SImode, operands[0]);
4354 operands[2] = gen_reg_rtx (SImode);
4355 }"
4356)
c7597b5d 4357
4358;; Subroutine to store a half word integer constant into memory.
4359(define_expand "storeinthi"
f082f1c4 4360 [(set (match_operand 0 "" "")
c7597b5d 4361 (subreg:QI (match_operand 1 "" "") 0))
9e8503e6 4362 (set (match_dup 3) (match_dup 2))]
cffb2a26 4363 "TARGET_ARM"
c7597b5d 4364 "
215b30b3 4365 {
4366 HOST_WIDE_INT value = INTVAL (operands[1]);
4367 rtx addr = XEXP (operands[0], 0);
537ffcfc 4368 rtx op0 = operands[0];
215b30b3 4369 enum rtx_code code = GET_CODE (addr);
c7597b5d 4370
215b30b3 4371 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4372 || code == MINUS)
537ffcfc 4373 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 4374
215b30b3 4375 operands[1] = gen_reg_rtx (SImode);
4376 if (BYTES_BIG_ENDIAN)
4377 {
4378 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4379 if ((value & 255) == ((value >> 8) & 255))
4380 operands[2] = operands[1];
4381 else
4382 {
4383 operands[2] = gen_reg_rtx (SImode);
4384 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4385 }
4386 }
4387 else
4388 {
4389 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4390 if ((value & 255) == ((value >> 8) & 255))
4391 operands[2] = operands[1];
4392 else
4393 {
4394 operands[2] = gen_reg_rtx (SImode);
4395 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4396 }
4397 }
c7597b5d 4398
537ffcfc 4399 operands[3] = adjust_address (op0, QImode, 1);
e513d163 4400 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 4401 operands[2] = gen_lowpart (QImode, operands[2]);
215b30b3 4402 }"
4403)
b11cae9e 4404
f7fbdd4a 4405(define_expand "storehi_single_op"
4406 [(set (match_operand:HI 0 "memory_operand" "")
4407 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4408 "TARGET_ARM && arm_arch4"
f7fbdd4a 4409 "
215b30b3 4410 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 4411 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 4412 "
4413)
f7fbdd4a 4414
b11cae9e 4415(define_expand "movhi"
4416 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 4417 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4418 "TARGET_EITHER"
b11cae9e 4419 "
cffb2a26 4420 if (TARGET_ARM)
b11cae9e 4421 {
215b30b3 4422 if (!no_new_pseudos)
cffb2a26 4423 {
4424 if (GET_CODE (operands[0]) == MEM)
b11cae9e 4425 {
cffb2a26 4426 if (arm_arch4)
4427 {
4428 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4429 DONE;
4430 }
4431 if (GET_CODE (operands[1]) == CONST_INT)
4432 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 4433 else
cffb2a26 4434 {
4435 if (GET_CODE (operands[1]) == MEM)
4436 operands[1] = force_reg (HImode, operands[1]);
4437 if (BYTES_BIG_ENDIAN)
4438 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4439 else
4440 emit_insn (gen_storehi (operands[1], operands[0]));
4441 }
4442 DONE;
b11cae9e 4443 }
cffb2a26 4444 /* Sign extend a constant, and keep it in an SImode reg. */
4445 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 4446 {
cffb2a26 4447 rtx reg = gen_reg_rtx (SImode);
4448 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4449
4450 /* If the constant is already valid, leave it alone. */
215b30b3 4451 if (!const_ok_for_arm (val))
cffb2a26 4452 {
4453 /* If setting all the top bits will make the constant
4454 loadable in a single instruction, then set them.
4455 Otherwise, sign extend the number. */
4456
215b30b3 4457 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 4458 val |= ~0xffff;
4459 else if (val & 0x8000)
4460 val |= ~0xffff;
4461 }
4462
4463 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 4464 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 4465 }
0045890a 4466 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4467 && GET_CODE (operands[1]) == MEM)
4468 {
4469 rtx reg = gen_reg_rtx (SImode);
4470
4471 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4472 operands[1] = gen_lowpart (HImode, reg);
4473 }
215b30b3 4474 else if (!arm_arch4)
f7fbdd4a 4475 {
cffb2a26 4476 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4477 for v4 and up architectures because LDRH instructions will
4478 be used to access the HI values, and these cannot generate
4479 unaligned word access faults in the MMU. */
4480 if (GET_CODE (operands[1]) == MEM)
4481 {
4482 if (TARGET_MMU_TRAPS)
206ee9a2 4483 {
cffb2a26 4484 rtx base;
4485 rtx offset = const0_rtx;
206ee9a2 4486 rtx reg = gen_reg_rtx (SImode);
cffb2a26 4487
4488 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4489 || (GET_CODE (base) == PLUS
215b30b3 4490 && (GET_CODE (offset = XEXP (base, 1))
4491 == CONST_INT)
cffb2a26 4492 && ((INTVAL(offset) & 1) != 1)
4493 && GET_CODE (base = XEXP (base, 0)) == REG))
8a126e61 4494 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
cffb2a26 4495 {
4496 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4497 rtx new;
4498
4499 new = gen_rtx_MEM (SImode,
4500 plus_constant (base, new_offset));
e4600bc3 4501 MEM_COPY_ATTRIBUTES (new, operands[1]);
cffb2a26 4502 emit_insn (gen_movsi (reg, new));
4503 if (((INTVAL (offset) & 2) != 0)
4504 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4505 {
4506 rtx reg2 = gen_reg_rtx (SImode);
4507
215b30b3 4508 emit_insn (gen_lshrsi3 (reg2, reg,
4509 GEN_INT (16)));
cffb2a26 4510 reg = reg2;
4511 }
4512 }
4513 else
4514 emit_insn (gen_movhi_bytes (reg, operands[1]));
206ee9a2 4515
4516 operands[1] = gen_lowpart (HImode, reg);
4517 }
cffb2a26 4518 else if (BYTES_BIG_ENDIAN)
206ee9a2 4519 {
cffb2a26 4520 rtx base;
4521 rtx offset = const0_rtx;
4522
4523 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4524 || (GET_CODE (base) == PLUS
215b30b3 4525 && (GET_CODE (offset = XEXP (base, 1))
4526 == CONST_INT)
cffb2a26 4527 && GET_CODE (base = XEXP (base, 0)) == REG))
8a126e61 4528 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
cffb2a26 4529 {
4530 rtx reg = gen_reg_rtx (SImode);
4531 rtx new;
4532
4533 if ((INTVAL (offset) & 2) == 2)
4534 {
4535 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4536 new = gen_rtx_MEM (SImode,
215b30b3 4537 plus_constant (base,
4538 new_offset));
cffb2a26 4539 MEM_COPY_ATTRIBUTES (new, operands[1]);
cffb2a26 4540 emit_insn (gen_movsi (reg, new));
4541 }
4542 else
4543 {
215b30b3 4544 new = gen_rtx_MEM (SImode,
4545 XEXP (operands[1], 0));
cffb2a26 4546 MEM_COPY_ATTRIBUTES (new, operands[1]);
cffb2a26 4547 emit_insn (gen_rotated_loadsi (reg, new));
4548 }
4549
4550 operands[1] = gen_lowpart (HImode, reg);
4551 }
4552 else
4553 {
215b30b3 4554 emit_insn (gen_movhi_bigend (operands[0],
4555 operands[1]));
cffb2a26 4556 DONE;
4557 }
206ee9a2 4558 }
cffb2a26 4559 }
4560 }
4561 }
4562 /* Handle loading a large integer during reload */
4563 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4564 && !const_ok_for_arm (INTVAL (operands[1]))
4565 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 4566 {
4567 /* Writing a constant to memory needs a scratch, which should
4568 be handled with SECONDARY_RELOADs. */
4569 if (GET_CODE (operands[0]) != REG)
4570 abort ();
4571
4572 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4573 emit_insn (gen_movsi (operands[0], operands[1]));
4574 DONE;
4575 }
4576 }
4577 else /* TARGET_THUMB */
4578 {
215b30b3 4579 if (!no_new_pseudos)
cffb2a26 4580 {
4581 if (GET_CODE (operands[0]) != REG)
4582 operands[1] = force_reg (HImode, operands[1]);
4583
4584 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4585 happen if we are passed a SP (never OK for HImode/QImode) or
4586 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4587 HImode/QImode) relative address. */
cffb2a26 4588 /* ??? This should perhaps be fixed elsewhere, for instance, in
4589 fixup_stack_1, by checking for other kinds of invalid addresses,
4590 e.g. a bare reference to a virtual register. This may confuse the
4591 alpha though, which must handle this case differently. */
4592 if (GET_CODE (operands[0]) == MEM
215b30b3 4593 && !memory_address_p (GET_MODE (operands[0]),
4594 XEXP (operands[0], 0)))
537ffcfc 4595 operands[0]
4596 = replace_equiv_address (operands[0],
4597 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 4598
4599 if (GET_CODE (operands[1]) == MEM
215b30b3 4600 && !memory_address_p (GET_MODE (operands[1]),
4601 XEXP (operands[1], 0)))
537ffcfc 4602 operands[1]
4603 = replace_equiv_address (operands[1],
4604 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 4605 }
4606 /* Handle loading a large integer during reload */
4607 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4608 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
cffb2a26 4609 {
4610 /* Writing a constant to memory needs a scratch, which should
4611 be handled with SECONDARY_RELOADs. */
4612 if (GET_CODE (operands[0]) != REG)
4613 abort ();
4614
4615 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4616 emit_insn (gen_movsi (operands[0], operands[1]));
4617 DONE;
4618 }
b11cae9e 4619 }
cffb2a26 4620 "
4621)
4622
4623(define_insn "*thumb_movhi_insn"
215b30b3 4624 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
cffb2a26 4625 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4626 "TARGET_THUMB
4627 && ( register_operand (operands[0], HImode)
4628 || register_operand (operands[1], HImode))"
4629 "*
4630 switch (which_alternative)
d79300ac 4631 {
cffb2a26 4632 case 0: return \"add %0, %1, #0\";
4633 case 2: return \"strh %1, %0\";
4634 case 3: return \"mov %0, %1\";
4635 case 4: return \"mov %0, %1\";
4636 case 5: return \"mov %0, %1\";
4637 default: abort ();
4638 case 1:
4639 /* The stack pointer can end up being taken as an index register.
4640 Catch this case here and deal with it. */
4641 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4642 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4643 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4644 {
4645 rtx ops[2];
4646 ops[0] = operands[0];
4647 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4648
4649 output_asm_insn (\"mov %0, %1\", ops);
4650
4651 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4652
4653 }
4654 return \"ldrh %0, %1\";
4655 }"
4656 [(set_attr "length" "2,4,2,2,2,2")
4657 (set_attr "type" "*,load,store1,*,*,*")
4658 (set_attr "pool_range" "*,64,*,*,*,*")]
4659)
d79300ac 4660
b11cae9e 4661
206ee9a2 4662(define_insn "rotated_loadsi"
cffb2a26 4663 [(set (match_operand:SI 0 "s_register_operand" "=r")
206ee9a2 4664 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4665 (const_int 16)))]
215b30b3 4666 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
206ee9a2 4667 "*
215b30b3 4668 {
4669 rtx ops[2];
206ee9a2 4670
215b30b3 4671 ops[0] = operands[0];
4672 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4673 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4674 return \"\";
cffb2a26 4675 }"
0d66636f 4676 [(set_attr "type" "load")
4677 (set_attr "predicable" "yes")]
cffb2a26 4678)
206ee9a2 4679
25f7a26e 4680(define_expand "movhi_bytes"
eab14235 4681 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4682 (set (match_dup 3)
eab14235 4683 (zero_extend:SI (match_dup 6)))
25f7a26e 4684 (set (match_operand:SI 0 "" "")
4685 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 4686 "TARGET_ARM"
25f7a26e 4687 "
215b30b3 4688 {
4689 rtx mem1, mem2;
4690 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4691
4692 mem1 = gen_rtx_MEM (QImode, addr);
4693 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4694 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4695 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4696 operands[0] = gen_lowpart (SImode, operands[0]);
4697 operands[1] = mem1;
4698 operands[2] = gen_reg_rtx (SImode);
4699 operands[3] = gen_reg_rtx (SImode);
4700 operands[6] = mem2;
25f7a26e 4701
215b30b3 4702 if (BYTES_BIG_ENDIAN)
4703 {
4704 operands[4] = operands[2];
4705 operands[5] = operands[3];
4706 }
4707 else
4708 {
4709 operands[4] = operands[3];
4710 operands[5] = operands[2];
4711 }
4712 }"
4713)
25f7a26e 4714
c7597b5d 4715(define_expand "movhi_bigend"
4716 [(set (match_dup 2)
4717 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4718 (const_int 16)))
4719 (set (match_dup 3)
4720 (ashiftrt:SI (match_dup 2) (const_int 16)))
4721 (set (match_operand:HI 0 "s_register_operand" "")
4722 (subreg:HI (match_dup 3) 0))]
cffb2a26 4723 "TARGET_ARM"
c7597b5d 4724 "
4725 operands[2] = gen_reg_rtx (SImode);
4726 operands[3] = gen_reg_rtx (SImode);
215b30b3 4727 "
4728)
b11cae9e 4729
a2f10574 4730;; Pattern to recognize insn generated default case above
f7fbdd4a 4731(define_insn "*movhi_insn_arch4"
cffb2a26 4732 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 4733 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 4734 "TARGET_ARM
4735 && arm_arch4
f7fbdd4a 4736 && (GET_CODE (operands[1]) != CONST_INT
4737 || const_ok_for_arm (INTVAL (operands[1]))
4738 || const_ok_for_arm (~INTVAL (operands[1])))"
4739 "@
4740 mov%?\\t%0, %1\\t%@ movhi
4741 mvn%?\\t%0, #%B1\\t%@ movhi
cffb2a26 4742 str%?h\\t%1, %0\\t%@ movhi
4743 ldr%?h\\t%0, %1\\t%@ movhi"
4744 [(set_attr "type" "*,*,store1,load")
0d66636f 4745 (set_attr "predicable" "yes")
cffb2a26 4746 (set_attr "pool_range" "*,*,*,256")
4747 (set_attr "neg_pool_range" "*,*,*,244")]
4748)
f7fbdd4a 4749
4750(define_insn "*movhi_insn_littleend"
129a2fe4 4751 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
c7597b5d 4752 (match_operand:HI 1 "general_operand" "rI,K,m"))]
cffb2a26 4753 "TARGET_ARM
215b30b3 4754 && !arm_arch4
4755 && !BYTES_BIG_ENDIAN
4756 && !TARGET_MMU_TRAPS
c7597b5d 4757 && (GET_CODE (operands[1]) != CONST_INT
4758 || const_ok_for_arm (INTVAL (operands[1]))
4759 || const_ok_for_arm (~INTVAL (operands[1])))"
5565501b 4760 "@
4761 mov%?\\t%0, %1\\t%@ movhi
4762 mvn%?\\t%0, #%B1\\t%@ movhi
c7597b5d 4763 ldr%?\\t%0, %1\\t%@ movhi"
cffb2a26 4764 [(set_attr "type" "*,*,load")
0d66636f 4765 (set_attr "predicable" "yes")
cffb2a26 4766 (set_attr "pool_range" "4096")
4767 (set_attr "neg_pool_range" "4084")]
4768)
c7597b5d 4769
f7fbdd4a 4770(define_insn "*movhi_insn_bigend"
c7597b5d 4771 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
cffb2a26 4772 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4773 "TARGET_ARM
215b30b3 4774 && !arm_arch4
f7fbdd4a 4775 && BYTES_BIG_ENDIAN
215b30b3 4776 && !TARGET_MMU_TRAPS
c7597b5d 4777 && (GET_CODE (operands[1]) != CONST_INT
4778 || const_ok_for_arm (INTVAL (operands[1]))
4779 || const_ok_for_arm (~INTVAL (operands[1])))"
4780 "@
4781 mov%?\\t%0, %1\\t%@ movhi
4782 mvn%?\\t%0, #%B1\\t%@ movhi
4783 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
cffb2a26 4784 [(set_attr "type" "*,*,load")
0d66636f 4785 (set_attr "predicable" "yes")
cffb2a26 4786 (set_attr "length" "4,4,8")
4787 (set_attr "pool_range" "*,*,4092")
4788 (set_attr "neg_pool_range" "*,*,4084")]
4789)
c7597b5d 4790
f7fbdd4a 4791(define_insn "*loadhi_si_bigend"
cffb2a26 4792 [(set (match_operand:SI 0 "s_register_operand" "=r")
4793 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
c7597b5d 4794 (const_int 16)))]
cffb2a26 4795 "TARGET_ARM
4796 && BYTES_BIG_ENDIAN
215b30b3 4797 && !TARGET_MMU_TRAPS"
c7597b5d 4798 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
cffb2a26 4799 [(set_attr "type" "load")
0d66636f 4800 (set_attr "predicable" "yes")
cffb2a26 4801 (set_attr "pool_range" "4096")
4802 (set_attr "neg_pool_range" "4084")]
4803)
9c08d1fa 4804
f7fbdd4a 4805(define_insn "*movhi_bytes"
25f7a26e 4806 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4807 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
cffb2a26 4808 "TARGET_ARM && TARGET_MMU_TRAPS"
25f7a26e 4809 "@
4810 mov%?\\t%0, %1\\t%@ movhi
0d66636f 4811 mvn%?\\t%0, #%B1\\t%@ movhi"
4812 [(set_attr "predicable" "yes")]
4813)
25f7a26e 4814
cffb2a26 4815(define_insn "thumb_movhi_clobber"
4816 [(set (match_operand:HI 0 "memory_operand" "=m")
4817 (match_operand:HI 1 "register_operand" "l"))
4818 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4819 "TARGET_THUMB"
344495ea 4820 "*
4821 abort ();"
cffb2a26 4822)
4823
bc5c7e08 4824;; We use a DImode scratch because we may occasionally need an additional
4825;; temporary if the address isn't offsettable -- push_reload doesn't seem
4826;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 4827(define_expand "reload_outhi"
cffb2a26 4828 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 4829 (match_operand:HI 1 "s_register_operand" "r")
4830 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 4831 "TARGET_EITHER"
4832 "if (TARGET_ARM)
4833 arm_reload_out_hi (operands);
4834 else
4835 thumb_reload_out_hi (operands);
d3373b54 4836 DONE;
cffb2a26 4837 "
4838)
d3373b54 4839
25f7a26e 4840(define_expand "reload_inhi"
4841 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 4842 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 4843 (match_operand:DI 2 "s_register_operand" "=&r")])]
cffb2a26 4844 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
25f7a26e 4845 "
cffb2a26 4846 if (TARGET_ARM)
4847 arm_reload_in_hi (operands);
4848 else
4849 thumb_reload_out_hi (operands);
25f7a26e 4850 DONE;
4851")
4852
9c08d1fa 4853(define_expand "movqi"
4854 [(set (match_operand:QI 0 "general_operand" "")
4855 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 4856 "TARGET_EITHER"
9c08d1fa 4857 "
cffb2a26 4858 if (TARGET_ARM)
9c08d1fa 4859 {
cffb2a26 4860 /* Everything except mem = const or mem = mem can be done easily */
c7597b5d 4861
935d87ee 4862 if (!no_new_pseudos)
cffb2a26 4863 {
4864 if (GET_CODE (operands[1]) == CONST_INT)
4865 {
4866 rtx reg = gen_reg_rtx (SImode);
4867
4868 emit_insn (gen_movsi (reg, operands[1]));
9e8503e6 4869 operands[1] = gen_lowpart (QImode, reg);
cffb2a26 4870 }
0045890a 4871 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4872 {
4873 rtx reg = gen_reg_rtx (SImode);
4874
4875 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4876 operands[1] = gen_lowpart (QImode, reg);
4877 }
4878 if (GET_CODE (operands[0]) == MEM)
4879 operands[1] = force_reg (QImode, operands[1]);
4880 }
b11cae9e 4881 }
cffb2a26 4882 else /* TARGET_THUMB */
4883 {
215b30b3 4884 if (!no_new_pseudos)
cffb2a26 4885 {
4886 if (GET_CODE (operands[0]) != REG)
4887 operands[1] = force_reg (QImode, operands[1]);
4888
4889 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4890 happen if we are passed a SP (never OK for HImode/QImode) or
4891 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4892 HImode/QImode) relative address. */
cffb2a26 4893 /* ??? This should perhaps be fixed elsewhere, for instance, in
4894 fixup_stack_1, by checking for other kinds of invalid addresses,
4895 e.g. a bare reference to a virtual register. This may confuse the
4896 alpha though, which must handle this case differently. */
4897 if (GET_CODE (operands[0]) == MEM
215b30b3 4898 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 4899 XEXP (operands[0], 0)))
537ffcfc 4900 operands[0]
4901 = replace_equiv_address (operands[0],
4902 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 4903 if (GET_CODE (operands[1]) == MEM
4904 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 4905 XEXP (operands[1], 0)))
537ffcfc 4906 operands[1]
4907 = replace_equiv_address (operands[1],
4908 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 4909 }
4910 /* Handle loading a large integer during reload */
4911 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4912 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
cffb2a26 4913 {
4914 /* Writing a constant to memory needs a scratch, which should
4915 be handled with SECONDARY_RELOADs. */
4916 if (GET_CODE (operands[0]) != REG)
4917 abort ();
4918
9e8503e6 4919 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 4920 emit_insn (gen_movsi (operands[0], operands[1]));
4921 DONE;
4922 }
4923 }
4924 "
4925)
b11cae9e 4926
9c08d1fa 4927
cffb2a26 4928(define_insn "*arm_movqi_insn"
4929 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 4930 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
cffb2a26 4931 "TARGET_ARM
4932 && ( register_operand (operands[0], QImode)
4933 || register_operand (operands[1], QImode))"
5565501b 4934 "@
4935 mov%?\\t%0, %1
4936 mvn%?\\t%0, #%B1
4937 ldr%?b\\t%0, %1
4938 str%?b\\t%1, %0"
0d66636f 4939 [(set_attr "type" "*,*,load,store1")
4940 (set_attr "predicable" "yes")]
cffb2a26 4941)
4942
4943(define_insn "*thumb_movqi_insn"
4944 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 4945 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
cffb2a26 4946 "TARGET_THUMB
4947 && ( register_operand (operands[0], QImode)
4948 || register_operand (operands[1], QImode))"
4949 "@
4950 add\\t%0, %1, #0
4951 ldrb\\t%0, %1
4952 strb\\t%1, %0
4953 mov\\t%0, %1
4954 mov\\t%0, %1
4955 mov\\t%0, %1"
4956 [(set_attr "length" "2")
4957 (set_attr "type" "*,load,store1,*,*,*")
4958 (set_attr "pool_range" "*,32,*,*,*,*")]
4959)
b11cae9e 4960
87b22bf7 4961(define_expand "movsf"
4962 [(set (match_operand:SF 0 "general_operand" "")
4963 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 4964 "TARGET_EITHER"
87b22bf7 4965 "
cffb2a26 4966 if (TARGET_ARM)
4967 {
4968 if (GET_CODE (operands[0]) == MEM)
4969 operands[1] = force_reg (SFmode, operands[1]);
4970 }
4971 else /* TARGET_THUMB */
4972 {
215b30b3 4973 if (!no_new_pseudos)
cffb2a26 4974 {
4975 if (GET_CODE (operands[0]) != REG)
4976 operands[1] = force_reg (SFmode, operands[1]);
4977 }
4978 }
4979 "
4980)
4981
4982(define_split
4983 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4984 (match_operand:SF 1 "immediate_operand" ""))]
4985 "TARGET_ARM
215b30b3 4986 && !TARGET_HARD_FLOAT
cffb2a26 4987 && reload_completed
4988 && GET_CODE (operands[1]) == CONST_DOUBLE"
4989 [(set (match_dup 2) (match_dup 3))]
4990 "
4991 operands[2] = gen_lowpart (SImode, operands[0]);
4992 operands[3] = gen_lowpart (SImode, operands[1]);
4993 if (operands[2] == 0 || operands[3] == 0)
4994 FAIL;
215b30b3 4995 "
4996)
87b22bf7 4997
cffb2a26 4998(define_insn "*arm_movsf_hard_insn"
215b30b3 4999 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
5000 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
cffb2a26 5001 "TARGET_ARM
5002 && TARGET_HARD_FLOAT
215b30b3 5003 && (GET_CODE (operands[0]) != MEM
5004 || register_operand (operands[1], SFmode))"
5565501b 5005 "@
5006 mvf%?s\\t%0, %1
5007 mnf%?s\\t%0, #%N1
5008 ldf%?s\\t%0, %1
5009 stf%?s\\t%1, %0
899850b0 5010 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
5011 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
5565501b 5012 mov%?\\t%0, %1
5013 ldr%?\\t%0, %1\\t%@ float
5014 str%?\\t%1, %0\\t%@ float"
cffb2a26 5015 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
0d66636f 5016 (set_attr "predicable" "yes")
cffb2a26 5017 (set_attr "type"
56d27660 5018 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
cffb2a26 5019 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
5020 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
5021)
9c08d1fa 5022
9a1112d7 5023;; Exactly the same as above, except that all `f' cases are deleted.
5024;; This is necessary to prevent reload from ever trying to use a `f' reg
5025;; when -msoft-float.
5026
cffb2a26 5027(define_insn "*arm_movsf_soft_insn"
5028 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5029 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5030 "TARGET_ARM
7d57ec45 5031 && !TARGET_CIRRUS
cffb2a26 5032 && TARGET_SOFT_FLOAT
215b30b3 5033 && (GET_CODE (operands[0]) != MEM
5034 || register_operand (operands[1], SFmode))"
9a1112d7 5035 "@
5036 mov%?\\t%0, %1
5037 ldr%?\\t%0, %1\\t%@ float
5038 str%?\\t%1, %0\\t%@ float"
cffb2a26 5039 [(set_attr "length" "4,4,4")
0d66636f 5040 (set_attr "predicable" "yes")
cffb2a26 5041 (set_attr "type" "*,load,store1")
5042 (set_attr "pool_range" "*,4096,*")
5043 (set_attr "neg_pool_range" "*,4084,*")]
5044)
5045
5046;;; ??? This should have alternatives for constants.
5047(define_insn "*thumb_movsf_insn"
215b30b3 5048 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5049 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
cffb2a26 5050 "TARGET_THUMB
5051 && ( register_operand (operands[0], SFmode)
5052 || register_operand (operands[1], SFmode))"
5053 "@
5054 add\\t%0, %1, #0
5055 ldmia\\t%1, {%0}
5056 stmia\\t%0, {%1}
5057 ldr\\t%0, %1
5058 str\\t%1, %0
5059 mov\\t%0, %1
5060 mov\\t%0, %1"
5061 [(set_attr "length" "2")
5062 (set_attr "type" "*,load,store1,load,store1,*,*")
5063 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5064)
9a1112d7 5065
9c08d1fa 5066(define_expand "movdf"
87b22bf7 5067 [(set (match_operand:DF 0 "general_operand" "")
5068 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5069 "TARGET_EITHER"
9c08d1fa 5070 "
cffb2a26 5071 if (TARGET_ARM)
5072 {
5073 if (GET_CODE (operands[0]) == MEM)
5074 operands[1] = force_reg (DFmode, operands[1]);
5075 }
5076 else /* TARGET_THUMB */
5077 {
215b30b3 5078 if (!no_new_pseudos)
cffb2a26 5079 {
5080 if (GET_CODE (operands[0]) != REG)
5081 operands[1] = force_reg (DFmode, operands[1]);
5082 }
5083 }
5084 "
5085)
b11cae9e 5086
9c08d1fa 5087;; Reloading a df mode value stored in integer regs to memory can require a
5088;; scratch reg.
5089(define_expand "reload_outdf"
cffb2a26 5090 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5091 (match_operand:DF 1 "s_register_operand" "r")
5092 (match_operand:SI 2 "s_register_operand" "=&r")]
cffb2a26 5093 "TARGET_ARM"
87b22bf7 5094 "
215b30b3 5095 {
5096 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5097
215b30b3 5098 if (code == REG)
5099 operands[2] = XEXP (operands[0], 0);
5100 else if (code == POST_INC || code == PRE_DEC)
5101 {
5102 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5103 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5104 emit_insn (gen_movdi (operands[0], operands[1]));
5105 DONE;
5106 }
5107 else if (code == PRE_INC)
5108 {
5109 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5110
215b30b3 5111 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5112 operands[2] = reg;
5113 }
5114 else if (code == POST_DEC)
5115 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5116 else
5117 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5118 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5119
215b30b3 5120 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5121 operands[1]));
f7fbdd4a 5122
215b30b3 5123 if (code == POST_DEC)
5124 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5125
5126 DONE;
5127 }"
5128)
9c08d1fa 5129
f7fbdd4a 5130(define_insn "*movdf_hard_insn"
215b30b3 5131 [(set (match_operand:DF 0 "nonimmediate_operand"
5132 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5133 (match_operand:DF 1 "general_operand"
5134 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
cffb2a26 5135 "TARGET_ARM
5136 && TARGET_HARD_FLOAT
f7fbdd4a 5137 && (GET_CODE (operands[0]) != MEM
5138 || register_operand (operands[1], DFmode))"
9c08d1fa 5139 "*
cffb2a26 5140 {
9c08d1fa 5141 switch (which_alternative)
5142 {
82ec49ae 5143 default:
97499065 5144 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5145 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
f7fbdd4a 5146 case 2: case 3: case 4: return output_move_double (operands);
5147 case 5: return \"mvf%?d\\t%0, %1\";
5148 case 6: return \"mnf%?d\\t%0, #%N1\";
5149 case 7: return \"ldf%?d\\t%0, %1\";
5150 case 8: return \"stf%?d\\t%1, %0\";
e8ff69a4 5151 case 9: return output_mov_double_fpa_from_arm (operands);
5152 case 10: return output_mov_double_arm_from_fpa (operands);
9c08d1fa 5153 }
cffb2a26 5154 }
5155 "
5156 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
0d66636f 5157 (set_attr "predicable" "yes")
cffb2a26 5158 (set_attr "type"
0d66636f 5159 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
dd080cc9 5160 (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5161 (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
cffb2a26 5162)
9c08d1fa 5163
39b5e676 5164;; Software floating point version. This is essentially the same as movdi.
5165;; Do not use `f' as a constraint to prevent reload from ever trying to use
5166;; an `f' reg.
9a1112d7 5167
5168(define_insn "*movdf_soft_insn"
cffb2a26 5169 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
f7fbdd4a 5170 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
344495ea 5171 "TARGET_ARM && TARGET_SOFT_FLOAT
7d57ec45 5172 && !TARGET_CIRRUS
344495ea 5173 "
39b5e676 5174 "* return output_move_double (operands);"
cffb2a26 5175 [(set_attr "length" "8,8,8")
5176 (set_attr "type" "*,load,store2")
dd080cc9 5177 (set_attr "pool_range" "1020")
5178 (set_attr "neg_pool_range" "1008")]
cffb2a26 5179)
5180
5181;;; ??? This should have alternatives for constants.
5182;;; ??? This was originally identical to the movdi_insn pattern.
5183;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5184;;; thumb_reorg with a memory reference.
5185(define_insn "*thumb_movdf_insn"
215b30b3 5186 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5187 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
cffb2a26 5188 "TARGET_THUMB
5189 && ( register_operand (operands[0], DFmode)
5190 || register_operand (operands[1], DFmode))"
5191 "*
5192 switch (which_alternative)
5193 {
5194 default:
5195 case 0:
5196 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5197 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5198 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5199 case 1:
5200 return \"ldmia\\t%1, {%0, %H0}\";
5201 case 2:
5202 return \"stmia\\t%0, {%1, %H1}\";
5203 case 3:
5204 return thumb_load_double_from_address (operands);
5205 case 4:
215b30b3 5206 operands[2] = gen_rtx (MEM, SImode,
5207 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5208 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5209 return \"\";
5210 case 5:
5211 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5212 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5213 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5214 }
5215 "
5216 [(set_attr "length" "4,2,2,6,4,4")
5217 (set_attr "type" "*,load,store2,load,store2,*")
5218 (set_attr "pool_range" "*,*,*,1020,*,*")]
5219)
5220
9a1112d7 5221
27da10cf 5222;; Saving and restoring the floating point registers in the prologue should
5223;; be done in XFmode, even though we don't support that for anything else
5224;; (Well, strictly it's 'internal representation', but that's effectively
5225;; XFmode).
87b22bf7 5226
f7fbdd4a 5227(define_insn "*movxf_hard_insn"
cffb2a26 5228 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
9c08d1fa 5229 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
27da10cf 5230 "TARGET_ARM && TARGET_HARD_FLOAT && reload_completed"
b11cae9e 5231 "*
5232 switch (which_alternative)
5233 {
82ec49ae 5234 default:
40dbec34 5235 case 0: return \"mvf%?e\\t%0, %1\";
5565501b 5236 case 1: return \"mnf%?e\\t%0, #%N1\";
40dbec34 5237 case 2: return \"ldf%?e\\t%0, %1\";
5238 case 3: return \"stf%?e\\t%1, %0\";
e8ff69a4 5239 case 4: return output_mov_long_double_fpa_from_arm (operands);
5240 case 5: return output_mov_long_double_arm_from_fpa (operands);
9c08d1fa 5241 case 6: return output_mov_long_double_arm_from_arm (operands);
b11cae9e 5242 }
cffb2a26 5243 "
5244 [(set_attr "length" "4,4,4,4,8,8,12")
0d66636f 5245 (set_attr "predicable" "yes")
cffb2a26 5246 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5247 (set_attr "pool_range" "*,*,1024,*,*,*,*")
dd080cc9 5248 (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
cffb2a26 5249)
b11cae9e 5250\f
b11cae9e 5251
9c08d1fa 5252;; load- and store-multiple insns
5253;; The arm can load/store any set of registers, provided that they are in
5254;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5255
9c08d1fa 5256(define_expand "load_multiple"
5257 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5258 (match_operand:SI 1 "" ""))
5259 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5260 "TARGET_ARM"
9c08d1fa 5261 "
bd5b4116 5262 /* Support only fixed point registers. */
9c08d1fa 5263 if (GET_CODE (operands[2]) != CONST_INT
5264 || INTVAL (operands[2]) > 14
5265 || INTVAL (operands[2]) < 2
5266 || GET_CODE (operands[1]) != MEM
5267 || GET_CODE (operands[0]) != REG
bd5b4116 5268 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5269 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5270 FAIL;
5271
5272 operands[3]
f082f1c4 5273 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5274 force_reg (SImode, XEXP (operands[1], 0)),
5275 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
e4600bc3 5276 MEM_IN_STRUCT_P(operands[1]),
5277 MEM_SCALAR_P (operands[1]));
215b30b3 5278 "
5279)
b11cae9e 5280
9c08d1fa 5281;; Load multiple with write-back
5282
2162064c 5283(define_insn "*ldmsi_postinc4"
9c08d1fa 5284 [(match_parallel 0 "load_multiple_operation"
13e9316a 5285 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5286 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5287 (const_int 16)))
5288 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5289 (mem:SI (match_dup 2)))
a0a72ac3 5290 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5291 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5292 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5293 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5294 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5295 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5296 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5297 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5298 [(set_attr "type" "load")
5299 (set_attr "predicable" "yes")]
5300)
b11cae9e 5301
2162064c 5302(define_insn "*ldmsi_postinc3"
5303 [(match_parallel 0 "load_multiple_operation"
13e9316a 5304 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5305 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5306 (const_int 12)))
5307 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5308 (mem:SI (match_dup 2)))
5309 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5310 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5311 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5312 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5313 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5314 "ldm%?ia\\t%1!, {%3, %4, %5}"
5315 [(set_attr "type" "load")
5316 (set_attr "predicable" "yes")]
5317)
b11cae9e 5318
2162064c 5319(define_insn "*ldmsi_postinc2"
5320 [(match_parallel 0 "load_multiple_operation"
13e9316a 5321 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5322 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5323 (const_int 8)))
5324 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5325 (mem:SI (match_dup 2)))
5326 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5327 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5328 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5329 "ldm%?ia\\t%1!, {%3, %4}"
0d66636f 5330 [(set_attr "type" "load")
5331 (set_attr "predicable" "yes")]
5332)
b11cae9e 5333
9c08d1fa 5334;; Ordinary load multiple
b11cae9e 5335
2162064c 5336(define_insn "*ldmsi4"
9c08d1fa 5337 [(match_parallel 0 "load_multiple_operation"
2162064c 5338 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5339 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5340 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5341 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5342 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5343 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5344 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5345 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5346 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5347 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5348 [(set_attr "type" "load")
5349 (set_attr "predicable" "yes")]
5350)
9c08d1fa 5351
2162064c 5352(define_insn "*ldmsi3"
5353 [(match_parallel 0 "load_multiple_operation"
5354 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5355 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5356 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5357 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5358 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5359 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5360 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5361 "ldm%?ia\\t%1, {%2, %3, %4}"
5362 [(set_attr "type" "load")
5363 (set_attr "predicable" "yes")]
5364)
9c08d1fa 5365
2162064c 5366(define_insn "*ldmsi2"
5367 [(match_parallel 0 "load_multiple_operation"
5368 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5369 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5370 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5371 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5372 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5373 "ldm%?ia\\t%1, {%2, %3}"
0d66636f 5374 [(set_attr "type" "load")
5375 (set_attr "predicable" "yes")]
5376)
9c08d1fa 5377
5378(define_expand "store_multiple"
5379 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5380 (match_operand:SI 1 "" ""))
5381 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5382 "TARGET_ARM"
9c08d1fa 5383 "
5384 /* Support only fixed point registers */
5385 if (GET_CODE (operands[2]) != CONST_INT
5386 || INTVAL (operands[2]) > 14
5387 || INTVAL (operands[2]) < 2
5388 || GET_CODE (operands[1]) != REG
5389 || GET_CODE (operands[0]) != MEM
bd5b4116 5390 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5391 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5392 FAIL;
5393
5394 operands[3]
f082f1c4 5395 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5396 force_reg (SImode, XEXP (operands[0], 0)),
5397 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
e4600bc3 5398 MEM_IN_STRUCT_P(operands[0]),
5399 MEM_SCALAR_P (operands[0]));
215b30b3 5400 "
5401)
b11cae9e 5402
9c08d1fa 5403;; Store multiple with write-back
5404
2162064c 5405(define_insn "*stmsi_postinc4"
9c08d1fa 5406 [(match_parallel 0 "store_multiple_operation"
13e9316a 5407 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5408 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5409 (const_int 16)))
a0a72ac3 5410 (set (mem:SI (match_dup 2))
2162064c 5411 (match_operand:SI 3 "arm_hard_register_operand" ""))
5412 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5413 (match_operand:SI 4 "arm_hard_register_operand" ""))
5414 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5415 (match_operand:SI 5 "arm_hard_register_operand" ""))
5416 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5417 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5418 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5419 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5420 [(set_attr "predicable" "yes")
5421 (set_attr "type" "store4")]
5422)
b11cae9e 5423
2162064c 5424(define_insn "*stmsi_postinc3"
5425 [(match_parallel 0 "store_multiple_operation"
13e9316a 5426 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5427 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5428 (const_int 12)))
5429 (set (mem:SI (match_dup 2))
5430 (match_operand:SI 3 "arm_hard_register_operand" ""))
5431 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5432 (match_operand:SI 4 "arm_hard_register_operand" ""))
5433 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5434 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5435 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5436 "stm%?ia\\t%1!, {%3, %4, %5}"
5437 [(set_attr "predicable" "yes")
5438 (set_attr "type" "store3")]
5439)
9c08d1fa 5440
2162064c 5441(define_insn "*stmsi_postinc2"
5442 [(match_parallel 0 "store_multiple_operation"
13e9316a 5443 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5444 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5445 (const_int 8)))
5446 (set (mem:SI (match_dup 2))
5447 (match_operand:SI 3 "arm_hard_register_operand" ""))
5448 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5449 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5450 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5451 "stm%?ia\\t%1!, {%3, %4}"
0d66636f 5452 [(set_attr "predicable" "yes")
2162064c 5453 (set_attr "type" "store2")]
cffb2a26 5454)
9c08d1fa 5455
5456;; Ordinary store multiple
5457
2162064c 5458(define_insn "*stmsi4"
9c08d1fa 5459 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 5460 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 5461 (match_operand:SI 2 "arm_hard_register_operand" ""))
5462 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5463 (match_operand:SI 3 "arm_hard_register_operand" ""))
5464 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5465 (match_operand:SI 4 "arm_hard_register_operand" ""))
5466 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5467 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5468 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5469 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5470 [(set_attr "predicable" "yes")
5471 (set_attr "type" "store4")]
5472)
9c08d1fa 5473
2162064c 5474(define_insn "*stmsi3"
5475 [(match_parallel 0 "store_multiple_operation"
5476 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5477 (match_operand:SI 2 "arm_hard_register_operand" ""))
5478 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5479 (match_operand:SI 3 "arm_hard_register_operand" ""))
5480 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5481 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5482 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5483 "stm%?ia\\t%1, {%2, %3, %4}"
5484 [(set_attr "predicable" "yes")
5485 (set_attr "type" "store3")]
5486)
9c08d1fa 5487
2162064c 5488(define_insn "*stmsi2"
5489 [(match_parallel 0 "store_multiple_operation"
5490 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5491 (match_operand:SI 2 "arm_hard_register_operand" ""))
5492 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5493 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5494 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5495 "stm%?ia\\t%1, {%2, %3}"
0d66636f 5496 [(set_attr "predicable" "yes")
2162064c 5497 (set_attr "type" "store2")]
cffb2a26 5498)
9c08d1fa 5499
5500;; Move a block of memory if it is word aligned and MORE than 2 words long.
5501;; We could let this apply for blocks of less than this, but it clobbers so
5502;; many registers that there is then probably a better way.
5503
34191dd1 5504(define_expand "movstrqi"
5505 [(match_operand:BLK 0 "general_operand" "")
5506 (match_operand:BLK 1 "general_operand" "")
5507 (match_operand:SI 2 "const_int_operand" "")
5508 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 5509 "TARGET_EITHER"
9c08d1fa 5510 "
cffb2a26 5511 if (TARGET_ARM)
5512 {
5513 if (arm_gen_movstrqi (operands))
5514 DONE;
5515 FAIL;
5516 }
5517 else /* TARGET_THUMB */
5518 {
5519 if ( INTVAL (operands[3]) != 4
5520 || INTVAL (operands[2]) > 48)
5521 FAIL;
5522
5523 thumb_expand_movstrqi (operands);
5524 DONE;
5525 }
5526 "
5527)
5528
2162064c 5529;; Thumb block-move insns
cffb2a26 5530
5531(define_insn "movmem12b"
960f3acf 5532 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5533 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5534 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5535 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5536 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5537 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5538 (set (match_operand:SI 0 "register_operand" "=l")
5539 (plus:SI (match_dup 2) (const_int 12)))
5540 (set (match_operand:SI 1 "register_operand" "=l")
5541 (plus:SI (match_dup 3) (const_int 12)))
5542 (clobber (match_scratch:SI 4 "=&l"))
5543 (clobber (match_scratch:SI 5 "=&l"))
5544 (clobber (match_scratch:SI 6 "=&l"))]
cffb2a26 5545 "TARGET_THUMB"
5546 "* return thumb_output_move_mem_multiple (3, operands);"
5547 [(set_attr "length" "4")
215b30b3 5548 ; This isn't entirely accurate... It loads as well, but in terms of
5549 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5550 (set_attr "type" "store3")]
5551)
5552
5553(define_insn "movmem8b"
960f3acf 5554 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5555 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5556 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5557 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5558 (set (match_operand:SI 0 "register_operand" "=l")
5559 (plus:SI (match_dup 2) (const_int 8)))
5560 (set (match_operand:SI 1 "register_operand" "=l")
5561 (plus:SI (match_dup 3) (const_int 8)))
5562 (clobber (match_scratch:SI 4 "=&l"))
5563 (clobber (match_scratch:SI 5 "=&l"))]
cffb2a26 5564 "TARGET_THUMB"
5565 "* return thumb_output_move_mem_multiple (2, operands);"
5566 [(set_attr "length" "4")
215b30b3 5567 ; This isn't entirely accurate... It loads as well, but in terms of
5568 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5569 (set_attr "type" "store2")]
5570)
5571
9c08d1fa 5572\f
b11cae9e 5573
341940e8 5574;; Compare & branch insns
5575;; The range calcualations are based as follows:
5576;; For forward branches, the address calculation returns the address of
5577;; the next instruction. This is 2 beyond the branch instruction.
5578;; For backward branches, the address calculation returns the address of
5579;; the first instruction in this pattern (cmp). This is 2 before the branch
5580;; instruction for the shortest sequence, and 4 before the branch instruction
5581;; if we have to jump around an unconditional branch.
5582;; To the basic branch range the PC offset must be added (this is +4).
5583;; So for forward branches we have
5584;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5585;; And for backward branches we have
5586;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5587;;
5588;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5589;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 5590
5591(define_insn "cbranchsi4"
5592 [(set (pc)
5593 (if_then_else
8fa3ba89 5594 (match_operator 0 "arm_comparison_operator"
cffb2a26 5595 [(match_operand:SI 1 "register_operand" "l,r")
5596 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5597 (label_ref (match_operand 3 "" ""))
5598 (pc)))]
5599 "TARGET_THUMB"
5600 "*
5601 output_asm_insn (\"cmp\\t%1, %2\", operands);
5602 switch (get_attr_length (insn))
5603 {
5604 case 4: return \"b%d0\\t%l3\";
5605 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5606 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5607 }
5608 "
5609 [(set (attr "far_jump")
5610 (if_then_else
5611 (eq_attr "length" "8")
5612 (const_string "yes")
5613 (const_string "no")))
5614 (set (attr "length")
5615 (if_then_else
5616 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5617 (le (minus (match_dup 3) (pc)) (const_int 256)))
5618 (const_int 4)
5619 (if_then_else
5620 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 5621 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5622 (const_int 6)
5623 (const_int 8))))]
5624)
5625
5626(define_insn "*negated_cbranchsi4"
5627 [(set (pc)
5628 (if_then_else
215b30b3 5629 (match_operator 0 "arm_comparison_operator"
5630 [(match_operand:SI 1 "register_operand" "l")
5631 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5632 (label_ref (match_operand 3 "" ""))
5633 (pc)))]
cffb2a26 5634 "TARGET_THUMB"
5635 "*
5636 output_asm_insn (\"cmn\\t%1, %2\", operands);
5637 switch (get_attr_length (insn))
5638 {
5639 case 4: return \"b%d0\\t%l3\";
5640 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5641 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5642 }
5643 "
5644 [(set (attr "far_jump")
5645 (if_then_else
5646 (eq_attr "length" "8")
5647 (const_string "yes")
5648 (const_string "no")))
5649 (set (attr "length")
5650 (if_then_else
5651 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 5652 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 5653 (const_int 4)
5654 (if_then_else
341940e8 5655 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5656 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5657 (const_int 6)
5658 (const_int 8))))]
5659)
5660
5661
9c08d1fa 5662;; Comparison and test insns
5663
5664(define_expand "cmpsi"
aea4c774 5665 [(match_operand:SI 0 "s_register_operand" "")
5666 (match_operand:SI 1 "arm_add_operand" "")]
cffb2a26 5667 "TARGET_ARM"
5668 "{
5669 arm_compare_op0 = operands[0];
5670 arm_compare_op1 = operands[1];
5671 DONE;
5672 }"
5673)
b11cae9e 5674
9c08d1fa 5675(define_expand "cmpsf"
aea4c774 5676 [(match_operand:SF 0 "s_register_operand" "")
e8ff69a4 5677 (match_operand:SF 1 "fpa_rhs_operand" "")]
7d57ec45 5678 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
9c08d1fa 5679 "
7d57ec45 5680 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5681 operands[1] = force_reg (SFmode, operands[1]);
5682
9c08d1fa 5683 arm_compare_op0 = operands[0];
5684 arm_compare_op1 = operands[1];
9c08d1fa 5685 DONE;
215b30b3 5686 "
5687)
b11cae9e 5688
9c08d1fa 5689(define_expand "cmpdf"
aea4c774 5690 [(match_operand:DF 0 "s_register_operand" "")
e8ff69a4 5691 (match_operand:DF 1 "fpa_rhs_operand" "")]
7d57ec45 5692 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
9c08d1fa 5693 "
7d57ec45 5694 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5695 operands[1] = force_reg (DFmode, operands[1]);
5696
9c08d1fa 5697 arm_compare_op0 = operands[0];
5698 arm_compare_op1 = operands[1];
9c08d1fa 5699 DONE;
215b30b3 5700 "
5701)
b11cae9e 5702
cffb2a26 5703(define_insn "*arm_cmpsi_insn"
bd5b4116 5704 [(set (reg:CC CC_REGNUM)
aea4c774 5705 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 5706 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5707 "TARGET_ARM"
5565501b 5708 "@
aea4c774 5709 cmp%?\\t%0, %1
5710 cmn%?\\t%0, #%n1"
cffb2a26 5711 [(set_attr "conds" "set")]
5712)
b11cae9e 5713
aea4c774 5714(define_insn "*cmpsi_shiftsi"
bd5b4116 5715 [(set (reg:CC CC_REGNUM)
cffb2a26 5716 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5717 (match_operator:SI 3 "shift_operator"
aea4c774 5718 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 5719 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5720 "TARGET_ARM"
aea4c774 5721 "cmp%?\\t%0, %1%S3"
344495ea 5722 [(set_attr "conds" "set")
331beb1a 5723 (set_attr "shift" "1")
344495ea 5724 ]
0d66636f 5725)
b11cae9e 5726
aea4c774 5727(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 5728 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 5729 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5730 [(match_operand:SI 1 "s_register_operand" "r")
5731 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5732 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 5733 "TARGET_ARM"
aea4c774 5734 "cmp%?\\t%0, %1%S3"
344495ea 5735 [(set_attr "conds" "set")
331beb1a 5736 (set_attr "shift" "1")
344495ea 5737 ]
0d66636f 5738)
b11cae9e 5739
f7fbdd4a 5740(define_insn "*cmpsi_neg_shiftsi"
bd5b4116 5741 [(set (reg:CC CC_REGNUM)
aea4c774 5742 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5743 (neg:SI (match_operator:SI 3 "shift_operator"
5744 [(match_operand:SI 1 "s_register_operand" "r")
5745 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
cffb2a26 5746 "TARGET_ARM"
aea4c774 5747 "cmn%?\\t%0, %1%S3"
344495ea 5748 [(set_attr "conds" "set")
331beb1a 5749 (set_attr "shift" "1")
344495ea 5750 ]
0d66636f 5751)
b11cae9e 5752
f7fbdd4a 5753(define_insn "*cmpsf_insn"
bd5b4116 5754 [(set (reg:CCFP CC_REGNUM)
9c08d1fa 5755 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
e8ff69a4 5756 (match_operand:SF 1 "fpa_add_operand" "fG,H")))]
cffb2a26 5757 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 5758 "@
5759 cmf%?\\t%0, %1
5760 cnf%?\\t%0, #%N1"
0d66636f 5761 [(set_attr "conds" "set")
5762 (set_attr "type" "f_2_r")]
5763)
b11cae9e 5764
f7fbdd4a 5765(define_insn "*cmpdf_insn"
bd5b4116 5766 [(set (reg:CCFP CC_REGNUM)
9c08d1fa 5767 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
e8ff69a4 5768 (match_operand:DF 1 "fpa_add_operand" "fG,H")))]
cffb2a26 5769 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 5770 "@
5771 cmf%?\\t%0, %1
5772 cnf%?\\t%0, #%N1"
0d66636f 5773 [(set_attr "conds" "set")
5774 (set_attr "type" "f_2_r")]
5775)
b11cae9e 5776
f7fbdd4a 5777(define_insn "*cmpesfdf_df"
bd5b4116 5778 [(set (reg:CCFP CC_REGNUM)
9c08d1fa 5779 (compare:CCFP (float_extend:DF
5780 (match_operand:SF 0 "s_register_operand" "f,f"))
e8ff69a4 5781 (match_operand:DF 1 "fpa_add_operand" "fG,H")))]
cffb2a26 5782 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 5783 "@
5784 cmf%?\\t%0, %1
5785 cnf%?\\t%0, #%N1"
0d66636f 5786 [(set_attr "conds" "set")
5787 (set_attr "type" "f_2_r")]
5788)
b11cae9e 5789
f7fbdd4a 5790(define_insn "*cmpdf_esfdf"
bd5b4116 5791 [(set (reg:CCFP CC_REGNUM)
9c08d1fa 5792 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5793 (float_extend:DF
5794 (match_operand:SF 1 "s_register_operand" "f"))))]
cffb2a26 5795 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 5796 "cmf%?\\t%0, %1"
0d66636f 5797 [(set_attr "conds" "set")
5798 (set_attr "type" "f_2_r")]
5799)
b11cae9e 5800
7d57ec45 5801;; Cirrus SF compare instruction
5802(define_insn "*cirrus_cmpsf"
5803 [(set (reg:CCFP CC_REGNUM)
5804 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5805 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5806 "TARGET_ARM && TARGET_CIRRUS"
5807 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 5808 [(set_attr "type" "mav_farith")
7d57ec45 5809 (set_attr "cirrus" "compare")]
5810)
5811
5812;; Cirrus DF compare instruction
5813(define_insn "*cirrus_cmpdf"
5814 [(set (reg:CCFP CC_REGNUM)
5815 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5816 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5817 "TARGET_ARM && TARGET_CIRRUS"
5818 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 5819 [(set_attr "type" "mav_farith")
7d57ec45 5820 (set_attr "cirrus" "compare")]
5821)
5822
5823;; Cirrus DI compare instruction
5824(define_expand "cmpdi"
5825 [(match_operand:DI 0 "cirrus_fp_register" "")
5826 (match_operand:DI 1 "cirrus_fp_register" "")]
5827 "TARGET_ARM && TARGET_CIRRUS"
5828 "{
5829 arm_compare_op0 = operands[0];
5830 arm_compare_op1 = operands[1];
5831 DONE;
5832 }")
5833
5834(define_insn "*cirrus_cmpdi"
5835 [(set (reg:CC CC_REGNUM)
5836 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5837 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5838 "TARGET_ARM && TARGET_CIRRUS"
5839 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 5840 [(set_attr "type" "mav_farith")
7d57ec45 5841 (set_attr "cirrus" "compare")]
5842)
5843
f7fbdd4a 5844(define_insn "*cmpsf_trap"
bd5b4116 5845 [(set (reg:CCFPE CC_REGNUM)
9c08d1fa 5846 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
e8ff69a4 5847 (match_operand:SF 1 "fpa_add_operand" "fG,H")))]
cffb2a26 5848 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 5849 "@
4d61e570 5850 cmf%?e\\t%0, %1
5851 cnf%?e\\t%0, #%N1"
0d66636f 5852 [(set_attr "conds" "set")
5853 (set_attr "type" "f_2_r")]
5854)
b11cae9e 5855
f7fbdd4a 5856(define_insn "*cmpdf_trap"
bd5b4116 5857 [(set (reg:CCFPE CC_REGNUM)
9c08d1fa 5858 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
e8ff69a4 5859 (match_operand:DF 1 "fpa_add_operand" "fG,H")))]
cffb2a26 5860 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 5861 "@
5862 cmf%?e\\t%0, %1
5863 cnf%?e\\t%0, #%N1"
0d66636f 5864 [(set_attr "conds" "set")
5865 (set_attr "type" "f_2_r")]
5866)
9c08d1fa 5867
f7fbdd4a 5868(define_insn "*cmp_esfdf_df_trap"
bd5b4116 5869 [(set (reg:CCFPE CC_REGNUM)
9c08d1fa 5870 (compare:CCFPE (float_extend:DF
5871 (match_operand:SF 0 "s_register_operand" "f,f"))
e8ff69a4 5872 (match_operand:DF 1 "fpa_add_operand" "fG,H")))]
cffb2a26 5873 "TARGET_ARM && TARGET_HARD_FLOAT"
5565501b 5874 "@
5875 cmf%?e\\t%0, %1
5876 cnf%?e\\t%0, #%N1"
0d66636f 5877 [(set_attr "conds" "set")
5878 (set_attr "type" "f_2_r")]
5879)
b11cae9e 5880
f7fbdd4a 5881(define_insn "*cmp_df_esfdf_trap"
bd5b4116 5882 [(set (reg:CCFPE CC_REGNUM)
9c08d1fa 5883 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5884 (float_extend:DF
5885 (match_operand:SF 1 "s_register_operand" "f"))))]
cffb2a26 5886 "TARGET_ARM && TARGET_HARD_FLOAT"
40dbec34 5887 "cmf%?e\\t%0, %1"
0d66636f 5888 [(set_attr "conds" "set")
5889 (set_attr "type" "f_2_r")]
5890)
b11cae9e 5891
9c08d1fa 5892; This insn allows redundant compares to be removed by cse, nothing should
5893; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5894; is deleted later on. The match_dup will match the mode here, so that
5895; mode changes of the condition codes aren't lost by this even though we don't
5896; specify what they are.
5897
8a18b90c 5898(define_insn "*deleted_compare"
9c08d1fa 5899 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
cffb2a26 5900 "TARGET_ARM"
40dbec34 5901 "\\t%@ deleted compare"
cffb2a26 5902 [(set_attr "conds" "set")
5903 (set_attr "length" "0")]
5904)
9c08d1fa 5905
5906\f
5907;; Conditional branch insns
5908
5909(define_expand "beq"
5910 [(set (pc)
5911 (if_then_else (eq (match_dup 1) (const_int 0))
5912 (label_ref (match_operand 0 "" ""))
5913 (pc)))]
cffb2a26 5914 "TARGET_ARM"
5915 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5916)
5c951228 5917
9c08d1fa 5918(define_expand "bne"
5919 [(set (pc)
5920 (if_then_else (ne (match_dup 1) (const_int 0))
5921 (label_ref (match_operand 0 "" ""))
5922 (pc)))]
cffb2a26 5923 "TARGET_ARM"
5924 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5925)
5c951228 5926
9c08d1fa 5927(define_expand "bgt"
5928 [(set (pc)
5929 (if_then_else (gt (match_dup 1) (const_int 0))
5930 (label_ref (match_operand 0 "" ""))
5931 (pc)))]
cffb2a26 5932 "TARGET_ARM"
5933 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5934)
5c951228 5935
9c08d1fa 5936(define_expand "ble"
5937 [(set (pc)
5938 (if_then_else (le (match_dup 1) (const_int 0))
5939 (label_ref (match_operand 0 "" ""))
5940 (pc)))]
cffb2a26 5941 "TARGET_ARM"
5942 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5943)
5c951228 5944
9c08d1fa 5945(define_expand "bge"
5946 [(set (pc)
5947 (if_then_else (ge (match_dup 1) (const_int 0))
5948 (label_ref (match_operand 0 "" ""))
5949 (pc)))]
cffb2a26 5950 "TARGET_ARM"
5951 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5952)
5c951228 5953
9c08d1fa 5954(define_expand "blt"
5955 [(set (pc)
5956 (if_then_else (lt (match_dup 1) (const_int 0))
5957 (label_ref (match_operand 0 "" ""))
5958 (pc)))]
cffb2a26 5959 "TARGET_ARM"
5960 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5961)
5c951228 5962
9c08d1fa 5963(define_expand "bgtu"
5964 [(set (pc)
5965 (if_then_else (gtu (match_dup 1) (const_int 0))
5966 (label_ref (match_operand 0 "" ""))
5967 (pc)))]
cffb2a26 5968 "TARGET_ARM"
5969 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5970)
5c951228 5971
9c08d1fa 5972(define_expand "bleu"
b11cae9e 5973 [(set (pc)
9c08d1fa 5974 (if_then_else (leu (match_dup 1) (const_int 0))
5975 (label_ref (match_operand 0 "" ""))
5976 (pc)))]
cffb2a26 5977 "TARGET_ARM"
5978 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5979)
b11cae9e 5980
9c08d1fa 5981(define_expand "bgeu"
b11cae9e 5982 [(set (pc)
9c08d1fa 5983 (if_then_else (geu (match_dup 1) (const_int 0))
5984 (label_ref (match_operand 0 "" ""))
5985 (pc)))]
cffb2a26 5986 "TARGET_ARM"
5987 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5988)
b11cae9e 5989
9c08d1fa 5990(define_expand "bltu"
5991 [(set (pc)
5992 (if_then_else (ltu (match_dup 1) (const_int 0))
5993 (label_ref (match_operand 0 "" ""))
5994 (pc)))]
cffb2a26 5995 "TARGET_ARM"
5996 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5997)
b11cae9e 5998
8fa3ba89 5999(define_expand "bunordered"
6000 [(set (pc)
6001 (if_then_else (unordered (match_dup 1) (const_int 0))
6002 (label_ref (match_operand 0 "" ""))
6003 (pc)))]
6004 "TARGET_ARM && TARGET_HARD_FLOAT"
6005 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6006 arm_compare_op1);"
6007)
6008
6009(define_expand "bordered"
6010 [(set (pc)
6011 (if_then_else (ordered (match_dup 1) (const_int 0))
6012 (label_ref (match_operand 0 "" ""))
6013 (pc)))]
6014 "TARGET_ARM && TARGET_HARD_FLOAT"
6015 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6016 arm_compare_op1);"
6017)
6018
6019(define_expand "bungt"
6020 [(set (pc)
6021 (if_then_else (ungt (match_dup 1) (const_int 0))
6022 (label_ref (match_operand 0 "" ""))
6023 (pc)))]
6024 "TARGET_ARM && TARGET_HARD_FLOAT"
6025 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6026)
6027
6028(define_expand "bunlt"
6029 [(set (pc)
6030 (if_then_else (unlt (match_dup 1) (const_int 0))
6031 (label_ref (match_operand 0 "" ""))
6032 (pc)))]
6033 "TARGET_ARM && TARGET_HARD_FLOAT"
6034 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6035)
6036
6037(define_expand "bunge"
6038 [(set (pc)
6039 (if_then_else (unge (match_dup 1) (const_int 0))
6040 (label_ref (match_operand 0 "" ""))
6041 (pc)))]
6042 "TARGET_ARM && TARGET_HARD_FLOAT"
6043 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6044)
6045
6046(define_expand "bunle"
6047 [(set (pc)
6048 (if_then_else (unle (match_dup 1) (const_int 0))
6049 (label_ref (match_operand 0 "" ""))
6050 (pc)))]
6051 "TARGET_ARM && TARGET_HARD_FLOAT"
6052 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6053)
6054
6055;; The following two patterns need two branch instructions, since there is
6056;; no single instruction that will handle all cases.
6057(define_expand "buneq"
6058 [(set (pc)
6059 (if_then_else (uneq (match_dup 1) (const_int 0))
6060 (label_ref (match_operand 0 "" ""))
6061 (pc)))]
6062 "TARGET_ARM && TARGET_HARD_FLOAT"
6063 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6064)
6065
6066(define_expand "bltgt"
6067 [(set (pc)
6068 (if_then_else (ltgt (match_dup 1) (const_int 0))
6069 (label_ref (match_operand 0 "" ""))
6070 (pc)))]
6071 "TARGET_ARM && TARGET_HARD_FLOAT"
6072 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6073)
6074
6075;;
6076;; Patterns to match conditional branch insns.
6077;;
6078
6079; Special pattern to match UNEQ.
6080(define_insn "*arm_buneq"
6081 [(set (pc)
6082 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6083 (label_ref (match_operand 0 "" ""))
6084 (pc)))]
6085 "TARGET_ARM && TARGET_HARD_FLOAT"
6086 "*
6087 if (arm_ccfsm_state != 0)
6088 abort ();
6089
278b301d 6090 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 6091 "
6092 [(set_attr "conds" "jump_clob")
6093 (set_attr "length" "8")]
6094)
6095
6096; Special pattern to match LTGT.
6097(define_insn "*arm_bltgt"
6098 [(set (pc)
6099 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6100 (label_ref (match_operand 0 "" ""))
6101 (pc)))]
6102 "TARGET_ARM && TARGET_HARD_FLOAT"
6103 "*
6104 if (arm_ccfsm_state != 0)
6105 abort ();
6106
278b301d 6107 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 6108 "
6109 [(set_attr "conds" "jump_clob")
6110 (set_attr "length" "8")]
6111)
9c08d1fa 6112
cffb2a26 6113(define_insn "*arm_cond_branch"
9c08d1fa 6114 [(set (pc)
8fa3ba89 6115 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6116 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6117 (label_ref (match_operand 0 "" ""))
6118 (pc)))]
cffb2a26 6119 "TARGET_ARM"
d75350ce 6120 "*
9c08d1fa 6121 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6122 {
6123 arm_ccfsm_state += 2;
6124 return \"\";
6125 }
e2348bcb 6126 return \"b%d1\\t%l0\";
cffb2a26 6127 "
6128 [(set_attr "conds" "use")]
6129)
d75350ce 6130
8fa3ba89 6131; Special pattern to match reversed UNEQ.
6132(define_insn "*arm_buneq_reversed"
6133 [(set (pc)
6134 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6135 (pc)
6136 (label_ref (match_operand 0 "" ""))))]
6137 "TARGET_ARM && TARGET_HARD_FLOAT"
6138 "*
6139 if (arm_ccfsm_state != 0)
6140 abort ();
6141
278b301d 6142 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 6143 "
6144 [(set_attr "conds" "jump_clob")
6145 (set_attr "length" "8")]
6146)
6147
6148; Special pattern to match reversed LTGT.
6149(define_insn "*arm_bltgt_reversed"
6150 [(set (pc)
6151 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6152 (pc)
6153 (label_ref (match_operand 0 "" ""))))]
6154 "TARGET_ARM && TARGET_HARD_FLOAT"
6155 "*
6156 if (arm_ccfsm_state != 0)
6157 abort ();
6158
278b301d 6159 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 6160 "
6161 [(set_attr "conds" "jump_clob")
6162 (set_attr "length" "8")]
6163)
6164
cffb2a26 6165(define_insn "*arm_cond_branch_reversed"
9c08d1fa 6166 [(set (pc)
8fa3ba89 6167 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6168 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6169 (pc)
6170 (label_ref (match_operand 0 "" ""))))]
cffb2a26 6171 "TARGET_ARM"
d75350ce 6172 "*
9c08d1fa 6173 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6174 {
6175 arm_ccfsm_state += 2;
6176 return \"\";
6177 }
e2348bcb 6178 return \"b%D1\\t%l0\";
cffb2a26 6179 "
6180 [(set_attr "conds" "use")]
6181)
6182
b11cae9e 6183\f
9c08d1fa 6184
6185; scc insns
6186
6187(define_expand "seq"
6188 [(set (match_operand:SI 0 "s_register_operand" "=r")
6189 (eq:SI (match_dup 1) (const_int 0)))]
cffb2a26 6190 "TARGET_ARM"
6191 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6192)
9c08d1fa 6193
6194(define_expand "sne"
6195 [(set (match_operand:SI 0 "s_register_operand" "=r")
6196 (ne:SI (match_dup 1) (const_int 0)))]
cffb2a26 6197 "TARGET_ARM"
6198 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6199)
9c08d1fa 6200
6201(define_expand "sgt"
6202 [(set (match_operand:SI 0 "s_register_operand" "=r")
6203 (gt:SI (match_dup 1) (const_int 0)))]
cffb2a26 6204 "TARGET_ARM"
6205 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6206)
9c08d1fa 6207
6208(define_expand "sle"
6209 [(set (match_operand:SI 0 "s_register_operand" "=r")
6210 (le:SI (match_dup 1) (const_int 0)))]
cffb2a26 6211 "TARGET_ARM"
6212 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6213)
9c08d1fa 6214
6215(define_expand "sge"
6216 [(set (match_operand:SI 0 "s_register_operand" "=r")
6217 (ge:SI (match_dup 1) (const_int 0)))]
cffb2a26 6218 "TARGET_ARM"
6219 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6220)
9c08d1fa 6221
6222(define_expand "slt"
6223 [(set (match_operand:SI 0 "s_register_operand" "=r")
6224 (lt:SI (match_dup 1) (const_int 0)))]
cffb2a26 6225 "TARGET_ARM"
6226 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6227)
9c08d1fa 6228
6229(define_expand "sgtu"
6230 [(set (match_operand:SI 0 "s_register_operand" "=r")
6231 (gtu:SI (match_dup 1) (const_int 0)))]
cffb2a26 6232 "TARGET_ARM"
6233 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6234)
9c08d1fa 6235
6236(define_expand "sleu"
6237 [(set (match_operand:SI 0 "s_register_operand" "=r")
6238 (leu:SI (match_dup 1) (const_int 0)))]
cffb2a26 6239 "TARGET_ARM"
6240 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6241)
9c08d1fa 6242
6243(define_expand "sgeu"
6244 [(set (match_operand:SI 0 "s_register_operand" "=r")
6245 (geu:SI (match_dup 1) (const_int 0)))]
cffb2a26 6246 "TARGET_ARM"
6247 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6248)
9c08d1fa 6249
6250(define_expand "sltu"
6251 [(set (match_operand:SI 0 "s_register_operand" "=r")
6252 (ltu:SI (match_dup 1) (const_int 0)))]
cffb2a26 6253 "TARGET_ARM"
6254 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6255)
9c08d1fa 6256
8fa3ba89 6257(define_expand "sunordered"
6258 [(set (match_operand:SI 0 "s_register_operand" "=r")
6259 (unordered:SI (match_dup 1) (const_int 0)))]
6260 "TARGET_ARM && TARGET_HARD_FLOAT"
6261 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6262 arm_compare_op1);"
6263)
6264
6265(define_expand "sordered"
6266 [(set (match_operand:SI 0 "s_register_operand" "=r")
6267 (ordered:SI (match_dup 1) (const_int 0)))]
6268 "TARGET_ARM && TARGET_HARD_FLOAT"
6269 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6270 arm_compare_op1);"
6271)
6272
6273(define_expand "sungt"
6274 [(set (match_operand:SI 0 "s_register_operand" "=r")
6275 (ungt:SI (match_dup 1) (const_int 0)))]
6276 "TARGET_ARM && TARGET_HARD_FLOAT"
6277 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6278 arm_compare_op1);"
6279)
6280
6281(define_expand "sunge"
6282 [(set (match_operand:SI 0 "s_register_operand" "=r")
6283 (unge:SI (match_dup 1) (const_int 0)))]
6284 "TARGET_ARM && TARGET_HARD_FLOAT"
6285 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6286 arm_compare_op1);"
6287)
6288
6289(define_expand "sunlt"
6290 [(set (match_operand:SI 0 "s_register_operand" "=r")
6291 (unlt:SI (match_dup 1) (const_int 0)))]
6292 "TARGET_ARM && TARGET_HARD_FLOAT"
6293 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6294 arm_compare_op1);"
6295)
6296
6297(define_expand "sunle"
6298 [(set (match_operand:SI 0 "s_register_operand" "=r")
6299 (unle:SI (match_dup 1) (const_int 0)))]
6300 "TARGET_ARM && TARGET_HARD_FLOAT"
6301 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6302 arm_compare_op1);"
6303)
6304
6305;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6306;;; simple ARM instructions.
6307;
6308; (define_expand "suneq"
6309; [(set (match_operand:SI 0 "s_register_operand" "=r")
6310; (uneq:SI (match_dup 1) (const_int 0)))]
6311; "TARGET_ARM && TARGET_HARD_FLOAT"
6312; "abort ();"
6313; )
6314;
6315; (define_expand "sltgt"
6316; [(set (match_operand:SI 0 "s_register_operand" "=r")
6317; (ltgt:SI (match_dup 1) (const_int 0)))]
6318; "TARGET_ARM && TARGET_HARD_FLOAT"
6319; "abort ();"
6320; )
6321
f7fbdd4a 6322(define_insn "*mov_scc"
9c08d1fa 6323 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 6324 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 6325 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 6326 "TARGET_ARM"
4d61e570 6327 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 6328 [(set_attr "conds" "use")
6329 (set_attr "length" "8")]
6330)
9c08d1fa 6331
f7fbdd4a 6332(define_insn "*mov_negscc"
9c08d1fa 6333 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 6334 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 6335 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 6336 "TARGET_ARM"
4d61e570 6337 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 6338 [(set_attr "conds" "use")
6339 (set_attr "length" "8")]
6340)
9c08d1fa 6341
f7fbdd4a 6342(define_insn "*mov_notscc"
9c08d1fa 6343 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 6344 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 6345 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 6346 "TARGET_ARM"
4d61e570 6347 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 6348 [(set_attr "conds" "use")
6349 (set_attr "length" "8")]
6350)
9c08d1fa 6351
6352\f
39b5e676 6353;; Conditional move insns
6354
6355(define_expand "movsicc"
8a18b90c 6356 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 6357 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 6358 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 6359 (match_operand:SI 3 "arm_not_operand" "")))]
cffb2a26 6360 "TARGET_ARM"
39b5e676 6361 "
215b30b3 6362 {
6363 enum rtx_code code = GET_CODE (operands[1]);
278b301d 6364 rtx ccreg;
6365
6366 if (code == UNEQ || code == LTGT)
6367 FAIL;
39b5e676 6368
278b301d 6369 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
215b30b3 6370 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6371 }"
6372)
39b5e676 6373
6374(define_expand "movsfcc"
8a18b90c 6375 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 6376 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 6377 (match_operand:SF 2 "s_register_operand" "")
6378 (match_operand:SF 3 "nonmemory_operand" "")))]
cffb2a26 6379 "TARGET_ARM"
39b5e676 6380 "
215b30b3 6381 {
6382 enum rtx_code code = GET_CODE (operands[1]);
6383 rtx ccreg;
f082f1c4 6384
278b301d 6385 if (code == UNEQ || code == LTGT)
6386 FAIL;
6387
215b30b3 6388 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6389 Otherwise, ensure it is a valid FP add operand */
6390 if ((!TARGET_HARD_FLOAT)
e8ff69a4 6391 || (!fpa_add_operand (operands[3], SFmode)))
215b30b3 6392 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 6393
215b30b3 6394 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6395 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6396 }"
6397)
39b5e676 6398
6399(define_expand "movdfcc"
8a18b90c 6400 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 6401 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 6402 (match_operand:DF 2 "s_register_operand" "")
e8ff69a4 6403 (match_operand:DF 3 "fpa_add_operand" "")))]
cffb2a26 6404 "TARGET_ARM && TARGET_HARD_FLOAT"
39b5e676 6405 "
215b30b3 6406 {
6407 enum rtx_code code = GET_CODE (operands[1]);
278b301d 6408 rtx ccreg;
39b5e676 6409
278b301d 6410 if (code == UNEQ || code == LTGT)
6411 FAIL;
6412
6413 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
215b30b3 6414 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6415 }"
6416)
39b5e676 6417
6418(define_insn "*movsicc_insn"
f082f1c4 6419 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 6420 (if_then_else:SI
8fa3ba89 6421 (match_operator 3 "arm_comparison_operator"
8a18b90c 6422 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 6423 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6424 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 6425 "TARGET_ARM"
39b5e676 6426 "@
8a18b90c 6427 mov%D3\\t%0, %2
6428 mvn%D3\\t%0, #%B2
f082f1c4 6429 mov%d3\\t%0, %1
6430 mvn%d3\\t%0, #%B1
8a18b90c 6431 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6432 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6433 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6434 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 6435 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 6436 (set_attr "conds" "use")]
6437)
39b5e676 6438
6439(define_insn "*movsfcc_hard_insn"
f082f1c4 6440 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6441 (if_then_else:SF
8fa3ba89 6442 (match_operator 3 "arm_comparison_operator"
f082f1c4 6443 [(match_operand 4 "cc_register" "") (const_int 0)])
e8ff69a4 6444 (match_operand:SF 1 "fpa_add_operand" "0,0,fG,H,fG,fG,H,H")
6445 (match_operand:SF 2 "fpa_add_operand" "fG,H,0,0,fG,H,fG,H")))]
cffb2a26 6446 "TARGET_ARM && TARGET_HARD_FLOAT"
8a18b90c 6447 "@
6448 mvf%D3s\\t%0, %2
f082f1c4 6449 mnf%D3s\\t%0, #%N2
6450 mvf%d3s\\t%0, %1
6451 mnf%d3s\\t%0, #%N1
6452 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6453 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6454 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6455 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6456 [(set_attr "length" "4,4,4,4,8,8,8,8")
6457 (set_attr "type" "ffarith")
215b30b3 6458 (set_attr "conds" "use")]
6459)
39b5e676 6460
6461(define_insn "*movsfcc_soft_insn"
f082f1c4 6462 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 6463 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 6464 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 6465 (match_operand:SF 1 "s_register_operand" "0,r")
6466 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 6467 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 6468 "@
6469 mov%D3\\t%0, %2
6470 mov%d3\\t%0, %1"
8fa3ba89 6471 [(set_attr "conds" "use")]
6472)
39b5e676 6473
6474(define_insn "*movdfcc_insn"
f082f1c4 6475 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6476 (if_then_else:DF
8fa3ba89 6477 (match_operator 3 "arm_comparison_operator"
f082f1c4 6478 [(match_operand 4 "cc_register" "") (const_int 0)])
e8ff69a4 6479 (match_operand:DF 1 "fpa_add_operand" "0,0,fG,H,fG,fG,H,H")
6480 (match_operand:DF 2 "fpa_add_operand" "fG,H,0,0,fG,H,fG,H")))]
cffb2a26 6481 "TARGET_ARM && TARGET_HARD_FLOAT"
8a18b90c 6482 "@
6483 mvf%D3d\\t%0, %2
f082f1c4 6484 mnf%D3d\\t%0, #%N2
6485 mvf%d3d\\t%0, %1
6486 mnf%d3d\\t%0, #%N1
6487 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6488 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6489 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6490 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6491 [(set_attr "length" "4,4,4,4,8,8,8,8")
6492 (set_attr "type" "ffarith")
215b30b3 6493 (set_attr "conds" "use")]
6494)
6495
39b5e676 6496\f
9c08d1fa 6497;; Jump and linkage insns
6498
cffb2a26 6499(define_expand "jump"
9c08d1fa 6500 [(set (pc)
6501 (label_ref (match_operand 0 "" "")))]
cffb2a26 6502 "TARGET_EITHER"
9c08d1fa 6503 ""
cffb2a26 6504)
6505
6506(define_insn "*arm_jump"
6507 [(set (pc)
6508 (label_ref (match_operand 0 "" "")))]
6509 "TARGET_ARM"
9c08d1fa 6510 "*
0d66636f 6511 {
6512 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6513 {
6514 arm_ccfsm_state += 2;
6515 return \"\";
6516 }
6517 return \"b%?\\t%l0\";
6518 }
6519 "
6520 [(set_attr "predicable" "yes")]
6521)
9c08d1fa 6522
cffb2a26 6523(define_insn "*thumb_jump"
6524 [(set (pc)
6525 (label_ref (match_operand 0 "" "")))]
6526 "TARGET_THUMB"
6527 "*
6528 if (get_attr_length (insn) == 2)
6529 return \"b\\t%l0\";
6530 return \"bl\\t%l0\\t%@ far jump\";
6531 "
6532 [(set (attr "far_jump")
6533 (if_then_else
6534 (eq_attr "length" "4")
6535 (const_string "yes")
6536 (const_string "no")))
6537 (set (attr "length")
6538 (if_then_else
6539 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6540 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6541 (const_int 2)
6542 (const_int 4)))]
6543)
6544
d3373b54 6545(define_expand "call"
6546 [(parallel [(call (match_operand 0 "memory_operand" "")
6547 (match_operand 1 "general_operand" ""))
cffb2a26 6548 (use (match_operand 2 "" ""))
bd5b4116 6549 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 6550 "TARGET_EITHER"
6c4c2133 6551 "
6552 {
78fe751b 6553 rtx callee;
bbe777ea 6554
bbe777ea 6555 /* In an untyped call, we can get NULL for operand 2. */
6556 if (operands[2] == NULL_RTX)
6557 operands[2] = const0_rtx;
6558
78fe751b 6559 /* This is to decide if we should generate indirect calls by loading the
6560 32 bit address of the callee into a register before performing the
6561 branch and link. operand[2] encodes the long_call/short_call
6562 attribute of the function being called. This attribute is set whenever
6563 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6564 is used, and the short_call attribute can also be set if function is
6565 declared as static or if it has already been defined in the current
6566 compilation unit. See arm.c and arm.h for info about this. The third
6567 parameter to arm_is_longcall_p is used to tell it which pattern
6568 invoked it. */
6569 callee = XEXP (operands[0], 0);
6570
bbe777ea 6571 if (GET_CODE (callee) != REG
6572 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6573 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6c4c2133 6574 }"
6575)
d3373b54 6576
f7fbdd4a 6577(define_insn "*call_reg"
d3373b54 6578 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 6579 (match_operand 1 "" ""))
6580 (use (match_operand 2 "" ""))
bd5b4116 6581 (clobber (reg:SI LR_REGNUM))]
cffb2a26 6582 "TARGET_ARM"
9c08d1fa 6583 "*
5565501b 6584 return output_call (operands);
cffb2a26 6585 "
6586 ;; length is worst case, normally it is only two
6587 [(set_attr "length" "12")
6588 (set_attr "type" "call")]
6589)
9c08d1fa 6590
f7fbdd4a 6591(define_insn "*call_mem"
6c4c2133 6592 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
cffb2a26 6593 (match_operand 1 "" ""))
6594 (use (match_operand 2 "" ""))
bd5b4116 6595 (clobber (reg:SI LR_REGNUM))]
cffb2a26 6596 "TARGET_ARM"
9c08d1fa 6597 "*
5565501b 6598 return output_call_mem (operands);
cffb2a26 6599 "
6600 [(set_attr "length" "12")
6601 (set_attr "type" "call")]
6602)
6603
6604(define_insn "*call_indirect"
6605 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6606 (match_operand 1 "" ""))
6607 (use (match_operand 2 "" ""))
bd5b4116 6608 (clobber (reg:SI LR_REGNUM))]
cffb2a26 6609 "TARGET_THUMB"
6610 "*
6611 {
6612 if (TARGET_CALLER_INTERWORKING)
6613 return \"bl\\t%__interwork_call_via_%0\";
6614 else
6615 return \"bl\\t%__call_via_%0\";
6616 }"
6617 [(set_attr "type" "call")]
6618)
6619
6620(define_insn "*call_value_indirect"
6621 [(set (match_operand 0 "" "=l")
6622 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6623 (match_operand 2 "" "")))
6624 (use (match_operand 3 "" ""))
bd5b4116 6625 (clobber (reg:SI LR_REGNUM))]
cffb2a26 6626 "TARGET_THUMB"
6627 "*
6628 {
6629 if (TARGET_CALLER_INTERWORKING)
6630 return \"bl\\t%__interwork_call_via_%1\";
6631 else
6632 return \"bl\\t%__call_via_%1\";
6633 }"
6634 [(set_attr "type" "call")]
6635)
9c08d1fa 6636
d3373b54 6637(define_expand "call_value"
e0698af7 6638 [(parallel [(set (match_operand 0 "" "")
6639 (call (match_operand 1 "memory_operand" "")
6640 (match_operand 2 "general_operand" "")))
cffb2a26 6641 (use (match_operand 3 "" ""))
bd5b4116 6642 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 6643 "TARGET_EITHER"
6c4c2133 6644 "
6645 {
bbe777ea 6646 rtx callee = XEXP (operands[1], 0);
6647
6648 /* In an untyped call, we can get NULL for operand 2. */
6649 if (operands[3] == 0)
6650 operands[3] = const0_rtx;
6651
6652 /* See the comment in define_expand \"call\". */
6653 if (GET_CODE (callee) != REG
6654 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
78fe751b 6655 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6c4c2133 6656 }"
6657)
d3373b54 6658
f7fbdd4a 6659(define_insn "*call_value_reg"
7d57ec45 6660 [(set (match_operand 0 "" "=r,f,v")
6661 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
cffb2a26 6662 (match_operand 2 "" "")))
bbe777ea 6663 (use (match_operand 3 "" ""))
bd5b4116 6664 (clobber (reg:SI LR_REGNUM))]
cffb2a26 6665 "TARGET_ARM"
9c08d1fa 6666 "*
215b30b3 6667 return output_call (&operands[1]);
cffb2a26 6668 "
6669 [(set_attr "length" "12")
6670 (set_attr "type" "call")]
6671)
9c08d1fa 6672
f7fbdd4a 6673(define_insn "*call_value_mem"
7d57ec45 6674 [(set (match_operand 0 "" "=r,f,v")
6675 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
cffb2a26 6676 (match_operand 2 "" "")))
bbe777ea 6677 (use (match_operand 3 "" ""))
bd5b4116 6678 (clobber (reg:SI LR_REGNUM))]
215b30b3 6679 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 6680 "*
215b30b3 6681 return output_call_mem (&operands[1]);
cffb2a26 6682 "
6683 [(set_attr "length" "12")
6684 (set_attr "type" "call")]
6685)
9c08d1fa 6686
6687;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6688;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6689
f7fbdd4a 6690(define_insn "*call_symbol"
6691 [(call (mem:SI (match_operand:SI 0 "" "X"))
cffb2a26 6692 (match_operand 1 "" ""))
bbe777ea 6693 (use (match_operand 2 "" ""))
bd5b4116 6694 (clobber (reg:SI LR_REGNUM))]
cffb2a26 6695 "TARGET_ARM
6696 && (GET_CODE (operands[0]) == SYMBOL_REF)
215b30b3 6697 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6ebaa29d 6698 "*
6699 {
55c1e470 6700 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 6701 }"
cffb2a26 6702 [(set_attr "type" "call")]
6703)
9c08d1fa 6704
f7fbdd4a 6705(define_insn "*call_value_symbol"
7d57ec45 6706 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6707 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
dd6d7504 6708 (match_operand:SI 2 "" "")))
bbe777ea 6709 (use (match_operand 3 "" ""))
bd5b4116 6710 (clobber (reg:SI LR_REGNUM))]
cffb2a26 6711 "TARGET_ARM
6712 && (GET_CODE (operands[1]) == SYMBOL_REF)
215b30b3 6713 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6ebaa29d 6714 "*
6715 {
55c1e470 6716 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 6717 }"
cffb2a26 6718 [(set_attr "type" "call")]
6719)
6720
6721(define_insn "*call_insn"
6722 [(call (mem:SI (match_operand:SI 0 "" "X"))
6723 (match_operand:SI 1 "" ""))
6724 (use (match_operand 2 "" ""))
bd5b4116 6725 (clobber (reg:SI LR_REGNUM))]
1c494086 6726 "TARGET_THUMB
1675c6e9 6727 && GET_CODE (operands[0]) == SYMBOL_REF
6728 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
cffb2a26 6729 "bl\\t%a0"
6730 [(set_attr "length" "4")
6731 (set_attr "type" "call")]
6732)
6733
6734(define_insn "*call_value_insn"
6735 [(set (match_operand 0 "register_operand" "=l")
6736 (call (mem:SI (match_operand 1 "" "X"))
6737 (match_operand 2 "" "")))
6738 (use (match_operand 3 "" ""))
bd5b4116 6739 (clobber (reg:SI LR_REGNUM))]
1c494086 6740 "TARGET_THUMB
1675c6e9 6741 && GET_CODE (operands[1]) == SYMBOL_REF
6742 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
cffb2a26 6743 "bl\\t%a1"
6744 [(set_attr "length" "4")
6745 (set_attr "type" "call")]
6746)
9c08d1fa 6747
1c494086 6748;; We may also be able to do sibcalls for Thumb, but it's much harder...
6749(define_expand "sibcall"
6750 [(parallel [(call (match_operand 0 "memory_operand" "")
6751 (match_operand 1 "general_operand" ""))
2ba80634 6752 (return)
6753 (use (match_operand 2 "" ""))])]
1c494086 6754 "TARGET_ARM"
6755 "
6756 {
6757 if (operands[2] == NULL_RTX)
6758 operands[2] = const0_rtx;
1c494086 6759 }"
6760)
6761
6762(define_expand "sibcall_value"
6763 [(parallel [(set (match_operand 0 "register_operand" "")
6764 (call (match_operand 1 "memory_operand" "")
6765 (match_operand 2 "general_operand" "")))
2ba80634 6766 (return)
6767 (use (match_operand 3 "" ""))])]
1c494086 6768 "TARGET_ARM"
6769 "
6770 {
6771 if (operands[3] == NULL_RTX)
6772 operands[3] = const0_rtx;
1c494086 6773 }"
6774)
6775
6776(define_insn "*sibcall_insn"
6777 [(call (mem:SI (match_operand:SI 0 "" "X"))
6778 (match_operand 1 "" ""))
2ba80634 6779 (return)
6780 (use (match_operand 2 "" ""))]
1c494086 6781 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6782 "*
6783 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6784 "
6785 [(set_attr "type" "call")]
6786)
6787
6788(define_insn "*sibcall_value_insn"
7d57ec45 6789 [(set (match_operand 0 "s_register_operand" "=r,f,v")
6790 (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
1c494086 6791 (match_operand 2 "" "")))
2ba80634 6792 (return)
6793 (use (match_operand 3 "" ""))]
1c494086 6794 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6795 "*
6796 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6797 "
6798 [(set_attr "type" "call")]
6799)
6800
9c08d1fa 6801;; Often the return insn will be the same as loading from memory, so set attr
6802(define_insn "return"
6803 [(return)]
cffb2a26 6804 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 6805 "*
9c08d1fa 6806 {
cffb2a26 6807 if (arm_ccfsm_state == 2)
6808 {
6809 arm_ccfsm_state += 2;
6810 return \"\";
6811 }
5db468b7 6812 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 6813 }"
0d66636f 6814 [(set_attr "type" "load")
6815 (set_attr "predicable" "yes")]
cffb2a26 6816)
9c08d1fa 6817
f7fbdd4a 6818(define_insn "*cond_return"
9c08d1fa 6819 [(set (pc)
8fa3ba89 6820 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 6821 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 6822 (return)
6823 (pc)))]
cffb2a26 6824 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 6825 "*
8fa3ba89 6826 {
6827 if (arm_ccfsm_state == 2)
6828 {
6829 arm_ccfsm_state += 2;
6830 return \"\";
6831 }
6832 return output_return_instruction (operands[0], TRUE, FALSE);
6833 }"
6834 [(set_attr "conds" "use")
6835 (set_attr "type" "load")]
6836)
9c08d1fa 6837
f7fbdd4a 6838(define_insn "*cond_return_inverted"
9c08d1fa 6839 [(set (pc)
8fa3ba89 6840 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 6841 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 6842 (pc)
6843 (return)))]
cffb2a26 6844 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 6845 "*
8fa3ba89 6846 {
6847 if (arm_ccfsm_state == 2)
6848 {
6849 arm_ccfsm_state += 2;
6850 return \"\";
6851 }
6852 return output_return_instruction (operands[0], TRUE, TRUE);
6853 }"
6854 [(set_attr "conds" "use")
6855 (set_attr "type" "load")]
6856)
9c08d1fa 6857
68121397 6858;; Generate a sequence of instructions to determine if the processor is
6859;; in 26-bit or 32-bit mode, and return the appropriate return address
6860;; mask.
6861
6862(define_expand "return_addr_mask"
6863 [(set (match_dup 1)
6864 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6865 (const_int 0)))
6866 (set (match_operand:SI 0 "s_register_operand" "")
6867 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6868 (const_int -1)
6869 (const_int 67108860)))] ; 0x03fffffc
6870 "TARGET_ARM"
6871 "
62eddbd4 6872 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 6873 ")
6874
6875(define_insn "*check_arch2"
6876 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6877 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6878 (const_int 0)))]
6879 "TARGET_ARM"
6880 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6881 [(set_attr "length" "8")
6882 (set_attr "conds" "set")]
6883)
6884
9c08d1fa 6885;; Call subroutine returning any type.
6886
6887(define_expand "untyped_call"
6888 [(parallel [(call (match_operand 0 "" "")
6889 (const_int 0))
6890 (match_operand 1 "" "")
6891 (match_operand 2 "" "")])]
cffb2a26 6892 "TARGET_ARM"
9c08d1fa 6893 "
215b30b3 6894 {
6895 int i;
9c08d1fa 6896
215b30b3 6897 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
9c08d1fa 6898
215b30b3 6899 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6900 {
6901 rtx set = XVECEXP (operands[2], 0, i);
9c08d1fa 6902
215b30b3 6903 emit_move_insn (SET_DEST (set), SET_SRC (set));
6904 }
9c08d1fa 6905
215b30b3 6906 /* The optimizer does not know that the call sets the function value
6907 registers we stored in the result block. We avoid problems by
6908 claiming that all hard registers are used and clobbered at this
6909 point. */
6910 emit_insn (gen_blockage ());
6911
6912 DONE;
6913 }"
6914)
9c08d1fa 6915
6916;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6917;; all of memory. This blocks insns from being moved across this point.
6918
6919(define_insn "blockage"
e1159bbe 6920 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 6921 "TARGET_EITHER"
9c08d1fa 6922 ""
cffb2a26 6923 [(set_attr "length" "0")
6924 (set_attr "type" "block")]
6925)
9c08d1fa 6926
f7fbdd4a 6927(define_expand "casesi"
6928 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 6929 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6930 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 6931 (match_operand:SI 3 "" "") ; table label
6932 (match_operand:SI 4 "" "")] ; Out of range label
cffb2a26 6933 "TARGET_ARM"
f7fbdd4a 6934 "
215b30b3 6935 {
6936 rtx reg;
6937 if (operands[1] != const0_rtx)
6938 {
6939 reg = gen_reg_rtx (SImode);
f7fbdd4a 6940
215b30b3 6941 emit_insn (gen_addsi3 (reg, operands[0],
6942 GEN_INT (-INTVAL (operands[1]))));
6943 operands[0] = reg;
6944 }
9c08d1fa 6945
215b30b3 6946 if (!const_ok_for_arm (INTVAL (operands[2])))
6947 operands[2] = force_reg (SImode, operands[2]);
6948
6949 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6950 operands[4]));
6951 DONE;
6952 }"
6953)
f7fbdd4a 6954
f082f1c4 6955;; The USE in this pattern is needed to tell flow analysis that this is
6956;; a CASESI insn. It has no other purpose.
f7fbdd4a 6957(define_insn "casesi_internal"
f082f1c4 6958 [(parallel [(set (pc)
6959 (if_then_else
6960 (leu (match_operand:SI 0 "s_register_operand" "r")
6961 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6962 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6963 (label_ref (match_operand 2 "" ""))))
6964 (label_ref (match_operand 3 "" ""))))
bd5b4116 6965 (clobber (reg:CC CC_REGNUM))
f082f1c4 6966 (use (label_ref (match_dup 2)))])]
cffb2a26 6967 "TARGET_ARM"
f7fbdd4a 6968 "*
0d66636f 6969 if (flag_pic)
6970 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6971 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6972 "
6973 [(set_attr "conds" "clob")
6974 (set_attr "length" "12")]
6975)
9c08d1fa 6976
cffb2a26 6977(define_expand "indirect_jump"
9c08d1fa 6978 [(set (pc)
cffb2a26 6979 (match_operand:SI 0 "s_register_operand" ""))]
6980 "TARGET_EITHER"
9c08d1fa 6981 ""
cffb2a26 6982)
6983
6984(define_insn "*arm_indirect_jump"
6985 [(set (pc)
6986 (match_operand:SI 0 "s_register_operand" "r"))]
6987 "TARGET_ARM"
6988 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 6989 [(set_attr "predicable" "yes")]
cffb2a26 6990)
9c08d1fa 6991
cffb2a26 6992;; Although not supported by the define_expand above,
6993;; cse/combine may generate this form.
f7fbdd4a 6994(define_insn "*load_indirect_jump"
9c08d1fa 6995 [(set (pc)
6996 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 6997 "TARGET_ARM"
6998 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
0d66636f 6999 [(set_attr "type" "load")
61a2d04c 7000 (set_attr "pool_range" "4096")
7001 (set_attr "neg_pool_range" "4084")
0d66636f 7002 (set_attr "predicable" "yes")]
cffb2a26 7003)
7004
7005(define_insn "*thumb_indirect_jump"
7006 [(set (pc)
7007 (match_operand:SI 0 "register_operand" "l*r"))]
7008 "TARGET_THUMB"
7009 "mov\\tpc, %0"
7010 [(set_attr "conds" "clob")
7011 (set_attr "length" "2")]
7012)
7013
9c08d1fa 7014\f
7015;; Misc insns
7016
7017(define_insn "nop"
7018 [(const_int 0)]
cffb2a26 7019 "TARGET_EITHER"
7020 "*
7021 if (TARGET_ARM)
7022 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7023 return \"mov\\tr8, r8\";
7024 "
7025 [(set (attr "length")
7026 (if_then_else (eq_attr "is_thumb" "yes")
7027 (const_int 2)
7028 (const_int 4)))]
7029)
7030
9c08d1fa 7031\f
7032;; Patterns to allow combination of arithmetic, cond code and shifts
7033
f7fbdd4a 7034(define_insn "*arith_shiftsi"
9c08d1fa 7035 [(set (match_operand:SI 0 "s_register_operand" "=r")
7036 (match_operator:SI 1 "shiftable_operator"
7037 [(match_operator:SI 3 "shift_operator"
7038 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 7039 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 7040 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 7041 "TARGET_ARM"
6c4c2133 7042 "%i1%?\\t%0, %2, %4%S3"
344495ea 7043 [(set_attr "predicable" "yes")
331beb1a 7044 (set_attr "shift" "4")
344495ea 7045 ]
6c4c2133 7046)
9c08d1fa 7047
f7fbdd4a 7048(define_insn "*arith_shiftsi_compare0"
bd5b4116 7049 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 7050 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7051 [(match_operator:SI 3 "shift_operator"
7052 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 7053 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 7054 (match_operand:SI 2 "s_register_operand" "r")])
7055 (const_int 0)))
7056 (set (match_operand:SI 0 "s_register_operand" "=r")
7057 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7058 (match_dup 2)]))]
cffb2a26 7059 "TARGET_ARM"
87b22bf7 7060 "%i1%?s\\t%0, %2, %4%S3"
344495ea 7061 [(set_attr "conds" "set")
331beb1a 7062 (set_attr "shift" "4")
344495ea 7063 ]
0d66636f 7064)
9c08d1fa 7065
f7fbdd4a 7066(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 7067 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 7068 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7069 [(match_operator:SI 3 "shift_operator"
7070 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 7071 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 7072 (match_operand:SI 2 "s_register_operand" "r")])
7073 (const_int 0)))
7074 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 7075 "TARGET_ARM"
87b22bf7 7076 "%i1%?s\\t%0, %2, %4%S3"
344495ea 7077 [(set_attr "conds" "set")
331beb1a 7078 (set_attr "shift" "4")
344495ea 7079 ]
0d66636f 7080)
9c08d1fa 7081
f7fbdd4a 7082(define_insn "*sub_shiftsi"
9c08d1fa 7083 [(set (match_operand:SI 0 "s_register_operand" "=r")
7084 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7085 (match_operator:SI 2 "shift_operator"
7086 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 7087 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 7088 "TARGET_ARM"
6c4c2133 7089 "sub%?\\t%0, %1, %3%S2"
344495ea 7090 [(set_attr "predicable" "yes")
331beb1a 7091 (set_attr "shift" "3")
344495ea 7092 ]
6c4c2133 7093)
9c08d1fa 7094
f7fbdd4a 7095(define_insn "*sub_shiftsi_compare0"
bd5b4116 7096 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 7097 (compare:CC_NOOV
7098 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7099 (match_operator:SI 2 "shift_operator"
7100 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 7101 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 7102 (const_int 0)))
9c08d1fa 7103 (set (match_operand:SI 0 "s_register_operand" "=r")
7104 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7105 (match_dup 4)])))]
cffb2a26 7106 "TARGET_ARM"
87b22bf7 7107 "sub%?s\\t%0, %1, %3%S2"
344495ea 7108 [(set_attr "conds" "set")
331beb1a 7109 (set_attr "shift" "3")
344495ea 7110 ]
0d66636f 7111)
9c08d1fa 7112
f7fbdd4a 7113(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 7114 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 7115 (compare:CC_NOOV
7116 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7117 (match_operator:SI 2 "shift_operator"
7118 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 7119 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 7120 (const_int 0)))
9c08d1fa 7121 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 7122 "TARGET_ARM"
87b22bf7 7123 "sub%?s\\t%0, %1, %3%S2"
344495ea 7124 [(set_attr "conds" "set")
331beb1a 7125 (set_attr "shift" "3")
344495ea 7126 ]
0d66636f 7127)
9c08d1fa 7128
9c08d1fa 7129\f
7130
f7fbdd4a 7131(define_insn "*and_scc"
9c08d1fa 7132 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7133 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 7134 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 7135 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 7136 "TARGET_ARM"
e2348bcb 7137 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 7138 [(set_attr "conds" "use")
7139 (set_attr "length" "8")]
7140)
9c08d1fa 7141
f7fbdd4a 7142(define_insn "*ior_scc"
9c08d1fa 7143 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7144 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 7145 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 7146 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 7147 "TARGET_ARM"
e2348bcb 7148 "@
899850b0 7149 orr%d2\\t%0, %1, #1
7150 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 7151 [(set_attr "conds" "use")
7152 (set_attr "length" "4,8")]
7153)
9c08d1fa 7154
f7fbdd4a 7155(define_insn "*compare_scc"
5565501b 7156 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7157 (match_operator:SI 1 "arm_comparison_operator"
5565501b 7158 [(match_operand:SI 2 "s_register_operand" "r,r")
7159 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 7160 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7161 "TARGET_ARM"
9c08d1fa 7162 "*
8fa3ba89 7163 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7164 return \"mov\\t%0, %2, lsr #31\";
e2348bcb 7165
8fa3ba89 7166 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7167 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 7168
8fa3ba89 7169 if (GET_CODE (operands[1]) == NE)
7170 {
7171 if (which_alternative == 1)
7172 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7173 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7174 }
7175 if (which_alternative == 1)
7176 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7177 else
7178 output_asm_insn (\"cmp\\t%2, %3\", operands);
7179 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7180 "
7181 [(set_attr "conds" "clob")
7182 (set_attr "length" "12")]
7183)
9c08d1fa 7184
f7fbdd4a 7185(define_insn "*cond_move"
9c08d1fa 7186 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 7187 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 7188 [(match_operator 4 "arm_comparison_operator"
8a18b90c 7189 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 7190 (const_int 0)])
7191 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7192 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 7193 "TARGET_ARM"
9c08d1fa 7194 "*
8fa3ba89 7195 if (GET_CODE (operands[3]) == NE)
7196 {
7197 if (which_alternative != 1)
7198 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7199 if (which_alternative != 0)
7200 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7201 return \"\";
7202 }
7203 if (which_alternative != 0)
7204 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7205 if (which_alternative != 1)
7206 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7207 return \"\";
7208 "
7209 [(set_attr "conds" "use")
7210 (set_attr "length" "4,4,8")]
7211)
9c08d1fa 7212
f7fbdd4a 7213(define_insn "*cond_arith"
9c08d1fa 7214 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7215 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 7216 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 7217 [(match_operand:SI 2 "s_register_operand" "r,r")
7218 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7219 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 7220 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7221 "TARGET_ARM"
9c08d1fa 7222 "*
8fa3ba89 7223 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7224 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 7225
8fa3ba89 7226 output_asm_insn (\"cmp\\t%2, %3\", operands);
7227 if (GET_CODE (operands[5]) == AND)
7228 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7229 else if (GET_CODE (operands[5]) == MINUS)
7230 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7231 else if (which_alternative != 0)
7232 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7233 return \"%i5%d4\\t%0, %1, #1\";
7234 "
7235 [(set_attr "conds" "clob")
7236 (set_attr "length" "12")]
7237)
9c08d1fa 7238
f7fbdd4a 7239(define_insn "*cond_sub"
9c08d1fa 7240 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7241 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 7242 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 7243 [(match_operand:SI 2 "s_register_operand" "r,r")
7244 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 7245 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7246 "TARGET_ARM"
9c08d1fa 7247 "*
8fa3ba89 7248 output_asm_insn (\"cmp\\t%2, %3\", operands);
7249 if (which_alternative != 0)
7250 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7251 return \"sub%d4\\t%0, %1, #1\";
7252 "
7253 [(set_attr "conds" "clob")
7254 (set_attr "length" "8,12")]
7255)
9c08d1fa 7256
aea4c774 7257(define_insn "*cmp_ite0"
cffb2a26 7258 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 7259 (compare
7260 (if_then_else:SI
8fa3ba89 7261 (match_operator 4 "arm_comparison_operator"
aea4c774 7262 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7263 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 7264 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 7265 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7266 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7267 (const_int 0))
7268 (const_int 0)))]
cffb2a26 7269 "TARGET_ARM"
9c08d1fa 7270 "*
aea4c774 7271 {
8fa3ba89 7272 static const char * const opcodes[4][2] =
7273 {
7274 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7275 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7276 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7277 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7278 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7279 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7280 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7281 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7282 };
7283 int swap =
7284 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7285
7286 return opcodes[which_alternative][swap];
7287 }"
7288 [(set_attr "conds" "set")
7289 (set_attr "length" "8")]
7290)
9c08d1fa 7291
aea4c774 7292(define_insn "*cmp_ite1"
cffb2a26 7293 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 7294 (compare
7295 (if_then_else:SI
8fa3ba89 7296 (match_operator 4 "arm_comparison_operator"
aea4c774 7297 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 7298 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 7299 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 7300 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 7301 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 7302 (const_int 1))
7303 (const_int 0)))]
cffb2a26 7304 "TARGET_ARM"
9c08d1fa 7305 "*
9c08d1fa 7306 {
215b30b3 7307 static const char * const opcodes[4][2] =
7308 {
7309 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7310 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7311 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7312 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7313 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7314 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7315 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7316 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7317 };
7318 int swap =
7319 comparison_dominates_p (GET_CODE (operands[5]),
7320 reverse_condition (GET_CODE (operands[4])));
7321
7322 return opcodes[which_alternative][swap];
7323 }"
8fa3ba89 7324 [(set_attr "conds" "set")
7325 (set_attr "length" "8")]
7326)
9c08d1fa 7327
f6c53574 7328(define_insn "*cmp_and"
7329 [(set (match_operand 6 "dominant_cc_register" "")
7330 (compare
7331 (and:SI
7332 (match_operator 4 "arm_comparison_operator"
7333 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7334 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7335 (match_operator:SI 5 "arm_comparison_operator"
7336 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7337 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7338 (const_int 0)))]
7339 "TARGET_ARM"
7340 "*
7341 {
35823b64 7342 static const char *const opcodes[4][2] =
f6c53574 7343 {
7344 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7345 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7346 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7347 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7348 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7349 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7350 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7351 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7352 };
7353 int swap =
7354 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7355
7356 return opcodes[which_alternative][swap];
7357 }"
7358 [(set_attr "conds" "set")
7359 (set_attr "predicable" "no")
7360 (set_attr "length" "8")]
7361)
7362
7363(define_insn "*cmp_ior"
7364 [(set (match_operand 6 "dominant_cc_register" "")
7365 (compare
7366 (ior:SI
7367 (match_operator 4 "arm_comparison_operator"
7368 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7369 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7370 (match_operator:SI 5 "arm_comparison_operator"
7371 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7372 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7373 (const_int 0)))]
7374 "TARGET_ARM"
7375 "*
7376{
35823b64 7377 static const char *const opcodes[4][2] =
f6c53574 7378 {
7379 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7380 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7381 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7382 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7383 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7384 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7385 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7386 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7387 };
7388 int swap =
7389 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7390
7391 return opcodes[which_alternative][swap];
7392}
7393"
7394 [(set_attr "conds" "set")
7395 (set_attr "length" "8")]
7396)
7397
f7fbdd4a 7398(define_insn "*negscc"
9c08d1fa 7399 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7400 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 7401 [(match_operand:SI 1 "s_register_operand" "r")
7402 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 7403 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7404 "TARGET_ARM"
9c08d1fa 7405 "*
f0e75574 7406 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
e2348bcb 7407 return \"mov\\t%0, %1, asr #31\";
7408
9c08d1fa 7409 if (GET_CODE (operands[3]) == NE)
e2348bcb 7410 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7411
9c08d1fa 7412 if (GET_CODE (operands[3]) == GT)
e2348bcb 7413 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7414
7415 output_asm_insn (\"cmp\\t%1, %2\", operands);
7416 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7417 return \"mvn%d3\\t%0, #0\";
215b30b3 7418 "
8fa3ba89 7419 [(set_attr "conds" "clob")
7420 (set_attr "length" "12")]
7421)
9c08d1fa 7422
7423(define_insn "movcond"
7424 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 7425 (if_then_else:SI
8fa3ba89 7426 (match_operator 5 "arm_comparison_operator"
5565501b 7427 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7428 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7429 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7430 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 7431 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7432 "TARGET_ARM"
9c08d1fa 7433 "*
7434 if (GET_CODE (operands[5]) == LT
7435 && (operands[4] == const0_rtx))
7436 {
5565501b 7437 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 7438 {
9c08d1fa 7439 if (operands[2] == const0_rtx)
e2348bcb 7440 return \"and\\t%0, %1, %3, asr #31\";
7441 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 7442 }
7443 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7444 {
9c08d1fa 7445 if (operands[1] == const0_rtx)
e2348bcb 7446 return \"bic\\t%0, %2, %3, asr #31\";
7447 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 7448 }
7449 /* The only case that falls through to here is when both ops 1 & 2
7450 are constants */
7451 }
e2348bcb 7452
9c08d1fa 7453 if (GET_CODE (operands[5]) == GE
7454 && (operands[4] == const0_rtx))
7455 {
7456 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7457 {
9c08d1fa 7458 if (operands[2] == const0_rtx)
e2348bcb 7459 return \"bic\\t%0, %1, %3, asr #31\";
7460 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 7461 }
7462 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7463 {
9c08d1fa 7464 if (operands[1] == const0_rtx)
e2348bcb 7465 return \"and\\t%0, %2, %3, asr #31\";
7466 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 7467 }
7468 /* The only case that falls through to here is when both ops 1 & 2
7469 are constants */
7470 }
7471 if (GET_CODE (operands[4]) == CONST_INT
7472 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 7473 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 7474 else
e2348bcb 7475 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 7476 if (which_alternative != 0)
e2348bcb 7477 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 7478 if (which_alternative != 1)
e2348bcb 7479 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 7480 return \"\";
215b30b3 7481 "
8fa3ba89 7482 [(set_attr "conds" "clob")
7483 (set_attr "length" "8,8,12")]
7484)
9c08d1fa 7485
8a18b90c 7486(define_insn "*ifcompare_plus_move"
7487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7488 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 7489 [(match_operand:SI 4 "s_register_operand" "r,r")
7490 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7491 (plus:SI
7492 (match_operand:SI 2 "s_register_operand" "r,r")
7493 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 7494 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 7495 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7496 "TARGET_ARM"
8a18b90c 7497 "#"
8fa3ba89 7498 [(set_attr "conds" "clob")
7499 (set_attr "length" "8,12")]
7500)
8a18b90c 7501
7502(define_insn "*if_plus_move"
129a2fe4 7503 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 7504 (if_then_else:SI
8fa3ba89 7505 (match_operator 4 "arm_comparison_operator"
8a18b90c 7506 [(match_operand 5 "cc_register" "") (const_int 0)])
7507 (plus:SI
129a2fe4 7508 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7509 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7510 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 7511 "TARGET_ARM"
8a18b90c 7512 "@
7513 add%d4\\t%0, %2, %3
7514 sub%d4\\t%0, %2, #%n3
7515 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 7516 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 7517 [(set_attr "conds" "use")
7518 (set_attr "length" "4,4,8,8")
7519 (set_attr "type" "*,*,*,*")]
7520)
8a18b90c 7521
7522(define_insn "*ifcompare_move_plus"
5565501b 7523 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7524 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 7525 [(match_operand:SI 4 "s_register_operand" "r,r")
7526 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 7527 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 7528 (plus:SI
7529 (match_operand:SI 2 "s_register_operand" "r,r")
7530 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 7531 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7532 "TARGET_ARM"
8a18b90c 7533 "#"
8fa3ba89 7534 [(set_attr "conds" "clob")
7535 (set_attr "length" "8,12")]
7536)
8a18b90c 7537
7538(define_insn "*if_move_plus"
129a2fe4 7539 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 7540 (if_then_else:SI
8fa3ba89 7541 (match_operator 4 "arm_comparison_operator"
8a18b90c 7542 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 7543 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 7544 (plus:SI
129a2fe4 7545 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7546 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 7547 "TARGET_ARM"
8a18b90c 7548 "@
7549 add%D4\\t%0, %2, %3
7550 sub%D4\\t%0, %2, #%n3
7551 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 7552 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 7553 [(set_attr "conds" "use")
7554 (set_attr "length" "4,4,8,8")
7555 (set_attr "type" "*,*,*,*")]
7556)
8a18b90c 7557
7558(define_insn "*ifcompare_arith_arith"
7559 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7560 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 7561 [(match_operand:SI 5 "s_register_operand" "r")
7562 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 7563 (match_operator:SI 8 "shiftable_operator"
8a18b90c 7564 [(match_operand:SI 1 "s_register_operand" "r")
7565 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 7566 (match_operator:SI 7 "shiftable_operator"
8a18b90c 7567 [(match_operand:SI 3 "s_register_operand" "r")
7568 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 7569 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7570 "TARGET_ARM"
8a18b90c 7571 "#"
8fa3ba89 7572 [(set_attr "conds" "clob")
7573 (set_attr "length" "12")]
7574)
9c08d1fa 7575
8a18b90c 7576(define_insn "*if_arith_arith"
7577 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7578 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 7579 [(match_operand 8 "cc_register" "") (const_int 0)])
7580 (match_operator:SI 6 "shiftable_operator"
7581 [(match_operand:SI 1 "s_register_operand" "r")
7582 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7583 (match_operator:SI 7 "shiftable_operator"
7584 [(match_operand:SI 3 "s_register_operand" "r")
7585 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 7586 "TARGET_ARM"
8a18b90c 7587 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 7588 [(set_attr "conds" "use")
7589 (set_attr "length" "8")]
7590)
8a18b90c 7591
f7fbdd4a 7592(define_insn "*ifcompare_arith_move"
9c08d1fa 7593 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7594 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 7595 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 7596 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 7597 (match_operator:SI 7 "shiftable_operator"
7598 [(match_operand:SI 4 "s_register_operand" "r,r")
7599 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 7600 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 7601 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7602 "TARGET_ARM"
9c08d1fa 7603 "*
9c08d1fa 7604 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 7605 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 7606 everything is in registers then we can do this in two instructions */
7607 if (operands[3] == const0_rtx
7608 && GET_CODE (operands[7]) != AND
7609 && GET_CODE (operands[5]) == REG
7610 && GET_CODE (operands[1]) == REG
7611 && REGNO (operands[1]) == REGNO (operands[4])
7612 && REGNO (operands[4]) != REGNO (operands[0]))
7613 {
7614 if (GET_CODE (operands[6]) == LT)
40dbec34 7615 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 7616 else if (GET_CODE (operands[6]) == GE)
40dbec34 7617 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 7618 }
7619 if (GET_CODE (operands[3]) == CONST_INT
7620 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 7621 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 7622 else
e2348bcb 7623 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 7624 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 7625 if (which_alternative != 0)
129a2fe4 7626 return \"mov%D6\\t%0, %1\";
9c08d1fa 7627 return \"\";
215b30b3 7628 "
8fa3ba89 7629 [(set_attr "conds" "clob")
7630 (set_attr "length" "8,12")]
7631)
9c08d1fa 7632
8a18b90c 7633(define_insn "*if_arith_move"
129a2fe4 7634 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7635 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 7636 [(match_operand 6 "cc_register" "") (const_int 0)])
7637 (match_operator:SI 5 "shiftable_operator"
129a2fe4 7638 [(match_operand:SI 2 "s_register_operand" "r,r")
7639 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7640 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 7641 "TARGET_ARM"
8a18b90c 7642 "@
7643 %I5%d4\\t%0, %2, %3
129a2fe4 7644 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 7645 [(set_attr "conds" "use")
7646 (set_attr "length" "4,8")
7647 (set_attr "type" "*,*")]
7648)
8a18b90c 7649
f7fbdd4a 7650(define_insn "*ifcompare_move_arith"
9c08d1fa 7651 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7652 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 7653 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 7654 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 7655 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 7656 (match_operator:SI 7 "shiftable_operator"
7657 [(match_operand:SI 2 "s_register_operand" "r,r")
7658 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 7659 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7660 "TARGET_ARM"
9c08d1fa 7661 "*
9c08d1fa 7662 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 7663 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 7664 everything is in registers then we can do this in two instructions */
7665 if (operands[5] == const0_rtx
7666 && GET_CODE (operands[7]) != AND
7667 && GET_CODE (operands[3]) == REG
7668 && GET_CODE (operands[1]) == REG
7669 && REGNO (operands[1]) == REGNO (operands[2])
7670 && REGNO (operands[2]) != REGNO (operands[0]))
7671 {
7672 if (GET_CODE (operands[6]) == GE)
40dbec34 7673 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 7674 else if (GET_CODE (operands[6]) == LT)
40dbec34 7675 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 7676 }
40dbec34 7677
9c08d1fa 7678 if (GET_CODE (operands[5]) == CONST_INT
7679 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 7680 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 7681 else
e2348bcb 7682 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 7683
9c08d1fa 7684 if (which_alternative != 0)
129a2fe4 7685 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 7686 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 7687 "
8fa3ba89 7688 [(set_attr "conds" "clob")
7689 (set_attr "length" "8,12")]
7690)
9c08d1fa 7691
8a18b90c 7692(define_insn "*if_move_arith"
129a2fe4 7693 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 7694 (if_then_else:SI
8fa3ba89 7695 (match_operator 4 "arm_comparison_operator"
8a18b90c 7696 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 7697 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 7698 (match_operator:SI 5 "shiftable_operator"
129a2fe4 7699 [(match_operand:SI 2 "s_register_operand" "r,r")
7700 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 7701 "TARGET_ARM"
8a18b90c 7702 "@
7703 %I5%D4\\t%0, %2, %3
129a2fe4 7704 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 7705 [(set_attr "conds" "use")
7706 (set_attr "length" "4,8")
7707 (set_attr "type" "*,*")]
7708)
8a18b90c 7709
7710(define_insn "*ifcompare_move_not"
9c08d1fa 7711 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 7712 (if_then_else:SI
8fa3ba89 7713 (match_operator 5 "arm_comparison_operator"
8a18b90c 7714 [(match_operand:SI 3 "s_register_operand" "r,r")
7715 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7716 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7717 (not:SI
7718 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 7719 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7720 "TARGET_ARM"
8a18b90c 7721 "#"
8fa3ba89 7722 [(set_attr "conds" "clob")
7723 (set_attr "length" "8,12")]
7724)
9c08d1fa 7725
8a18b90c 7726(define_insn "*if_move_not"
7727 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7728 (if_then_else:SI
8fa3ba89 7729 (match_operator 4 "arm_comparison_operator"
8a18b90c 7730 [(match_operand 3 "cc_register" "") (const_int 0)])
7731 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7732 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 7733 "TARGET_ARM"
8a18b90c 7734 "@
7735 mvn%D4\\t%0, %2
7736 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7737 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 7738 [(set_attr "conds" "use")
7739 (set_attr "length" "4,8,8")]
7740)
8a18b90c 7741
7742(define_insn "*ifcompare_not_move"
9c08d1fa 7743 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 7744 (if_then_else:SI
8fa3ba89 7745 (match_operator 5 "arm_comparison_operator"
8a18b90c 7746 [(match_operand:SI 3 "s_register_operand" "r,r")
7747 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7748 (not:SI
7749 (match_operand:SI 2 "s_register_operand" "r,r"))
7750 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 7751 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7752 "TARGET_ARM"
8a18b90c 7753 "#"
8fa3ba89 7754 [(set_attr "conds" "clob")
7755 (set_attr "length" "8,12")]
7756)
9c08d1fa 7757
8a18b90c 7758(define_insn "*if_not_move"
7759 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7760 (if_then_else:SI
8fa3ba89 7761 (match_operator 4 "arm_comparison_operator"
8a18b90c 7762 [(match_operand 3 "cc_register" "") (const_int 0)])
7763 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7764 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 7765 "TARGET_ARM"
8a18b90c 7766 "@
7767 mvn%d4\\t%0, %2
7768 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7769 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 7770 [(set_attr "conds" "use")
7771 (set_attr "length" "4,8,8")]
7772)
8a18b90c 7773
7774(define_insn "*ifcompare_shift_move"
9c08d1fa 7775 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 7776 (if_then_else:SI
8fa3ba89 7777 (match_operator 6 "arm_comparison_operator"
8a18b90c 7778 [(match_operand:SI 4 "s_register_operand" "r,r")
7779 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7780 (match_operator:SI 7 "shift_operator"
7781 [(match_operand:SI 2 "s_register_operand" "r,r")
7782 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7783 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 7784 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7785 "TARGET_ARM"
9c08d1fa 7786 "#"
8fa3ba89 7787 [(set_attr "conds" "clob")
7788 (set_attr "length" "8,12")]
7789)
9c08d1fa 7790
8a18b90c 7791(define_insn "*if_shift_move"
7792 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7793 (if_then_else:SI
8fa3ba89 7794 (match_operator 5 "arm_comparison_operator"
8a18b90c 7795 [(match_operand 6 "cc_register" "") (const_int 0)])
7796 (match_operator:SI 4 "shift_operator"
7797 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7798 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7799 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 7800 "TARGET_ARM"
5565501b 7801 "@
8a18b90c 7802 mov%d5\\t%0, %2%S4
7803 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7804 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 7805 [(set_attr "conds" "use")
331beb1a 7806 (set_attr "shift" "2")
8fa3ba89 7807 (set_attr "length" "4,8,8")]
7808)
5565501b 7809
8a18b90c 7810(define_insn "*ifcompare_move_shift"
7811 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 7812 (if_then_else:SI
8fa3ba89 7813 (match_operator 6 "arm_comparison_operator"
8a18b90c 7814 [(match_operand:SI 4 "s_register_operand" "r,r")
7815 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7816 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 7817 (match_operator:SI 7 "shift_operator"
8a18b90c 7818 [(match_operand:SI 2 "s_register_operand" "r,r")
7819 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 7820 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7821 "TARGET_ARM"
8a18b90c 7822 "#"
8fa3ba89 7823 [(set_attr "conds" "clob")
7824 (set_attr "length" "8,12")]
7825)
5565501b 7826
8a18b90c 7827(define_insn "*if_move_shift"
7828 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 7829 (if_then_else:SI
8fa3ba89 7830 (match_operator 5 "arm_comparison_operator"
8a18b90c 7831 [(match_operand 6 "cc_register" "") (const_int 0)])
7832 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7833 (match_operator:SI 4 "shift_operator"
7834 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7835 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 7836 "TARGET_ARM"
5565501b 7837 "@
8a18b90c 7838 mov%D5\\t%0, %2%S4
7839 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7840 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 7841 [(set_attr "conds" "use")
331beb1a 7842 (set_attr "shift" "2")
8fa3ba89 7843 (set_attr "length" "4,8,8")]
7844)
9c08d1fa 7845
f7fbdd4a 7846(define_insn "*ifcompare_shift_shift"
8a18b90c 7847 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 7848 (if_then_else:SI
8fa3ba89 7849 (match_operator 7 "arm_comparison_operator"
8a18b90c 7850 [(match_operand:SI 5 "s_register_operand" "r")
7851 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 7852 (match_operator:SI 8 "shift_operator"
8a18b90c 7853 [(match_operand:SI 1 "s_register_operand" "r")
7854 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 7855 (match_operator:SI 9 "shift_operator"
8a18b90c 7856 [(match_operand:SI 3 "s_register_operand" "r")
7857 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 7858 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7859 "TARGET_ARM"
8a18b90c 7860 "#"
8fa3ba89 7861 [(set_attr "conds" "clob")
7862 (set_attr "length" "12")]
7863)
9c08d1fa 7864
8a18b90c 7865(define_insn "*if_shift_shift"
7866 [(set (match_operand:SI 0 "s_register_operand" "=r")
7867 (if_then_else:SI
8fa3ba89 7868 (match_operator 5 "arm_comparison_operator"
8a18b90c 7869 [(match_operand 8 "cc_register" "") (const_int 0)])
7870 (match_operator:SI 6 "shift_operator"
7871 [(match_operand:SI 1 "s_register_operand" "r")
7872 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7873 (match_operator:SI 7 "shift_operator"
7874 [(match_operand:SI 3 "s_register_operand" "r")
7875 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 7876 "TARGET_ARM"
8a18b90c 7877 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 7878 [(set_attr "conds" "use")
331beb1a 7879 (set_attr "shift" "1")
8fa3ba89 7880 (set_attr "length" "8")]
7881)
8a18b90c 7882
f7fbdd4a 7883(define_insn "*ifcompare_not_arith"
8a18b90c 7884 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 7885 (if_then_else:SI
8fa3ba89 7886 (match_operator 6 "arm_comparison_operator"
8a18b90c 7887 [(match_operand:SI 4 "s_register_operand" "r")
7888 (match_operand:SI 5 "arm_add_operand" "rIL")])
7889 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 7890 (match_operator:SI 7 "shiftable_operator"
8a18b90c 7891 [(match_operand:SI 2 "s_register_operand" "r")
7892 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 7893 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7894 "TARGET_ARM"
8a18b90c 7895 "#"
8fa3ba89 7896 [(set_attr "conds" "clob")
7897 (set_attr "length" "12")]
7898)
9c08d1fa 7899
8a18b90c 7900(define_insn "*if_not_arith"
7901 [(set (match_operand:SI 0 "s_register_operand" "=r")
7902 (if_then_else:SI
8fa3ba89 7903 (match_operator 5 "arm_comparison_operator"
8a18b90c 7904 [(match_operand 4 "cc_register" "") (const_int 0)])
7905 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7906 (match_operator:SI 6 "shiftable_operator"
7907 [(match_operand:SI 2 "s_register_operand" "r")
7908 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 7909 "TARGET_ARM"
8a18b90c 7910 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 7911 [(set_attr "conds" "use")
7912 (set_attr "length" "8")]
7913)
8a18b90c 7914
7915(define_insn "*ifcompare_arith_not"
7916 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 7917 (if_then_else:SI
8fa3ba89 7918 (match_operator 6 "arm_comparison_operator"
8a18b90c 7919 [(match_operand:SI 4 "s_register_operand" "r")
7920 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 7921 (match_operator:SI 7 "shiftable_operator"
8a18b90c 7922 [(match_operand:SI 2 "s_register_operand" "r")
7923 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7924 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 7925 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7926 "TARGET_ARM"
8a18b90c 7927 "#"
8fa3ba89 7928 [(set_attr "conds" "clob")
7929 (set_attr "length" "12")]
7930)
9c08d1fa 7931
8a18b90c 7932(define_insn "*if_arith_not"
7933 [(set (match_operand:SI 0 "s_register_operand" "=r")
7934 (if_then_else:SI
8fa3ba89 7935 (match_operator 5 "arm_comparison_operator"
8a18b90c 7936 [(match_operand 4 "cc_register" "") (const_int 0)])
7937 (match_operator:SI 6 "shiftable_operator"
7938 [(match_operand:SI 2 "s_register_operand" "r")
7939 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7940 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 7941 "TARGET_ARM"
8a18b90c 7942 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 7943 [(set_attr "conds" "use")
7944 (set_attr "length" "8")]
7945)
8a18b90c 7946
f7fbdd4a 7947(define_insn "*ifcompare_neg_move"
8a18b90c 7948 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 7949 (if_then_else:SI
8fa3ba89 7950 (match_operator 5 "arm_comparison_operator"
8a18b90c 7951 [(match_operand:SI 3 "s_register_operand" "r,r")
7952 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7953 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7954 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 7955 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7956 "TARGET_ARM"
8a18b90c 7957 "#"
8fa3ba89 7958 [(set_attr "conds" "clob")
7959 (set_attr "length" "8,12")]
7960)
8a18b90c 7961
7962(define_insn "*if_neg_move"
7963 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7964 (if_then_else:SI
8fa3ba89 7965 (match_operator 4 "arm_comparison_operator"
8a18b90c 7966 [(match_operand 3 "cc_register" "") (const_int 0)])
7967 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7968 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 7969 "TARGET_ARM"
8a18b90c 7970 "@
7971 rsb%d4\\t%0, %2, #0
7972 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7973 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 7974 [(set_attr "conds" "use")
7975 (set_attr "length" "4,8,8")]
7976)
9c08d1fa 7977
f7fbdd4a 7978(define_insn "*ifcompare_move_neg"
8a18b90c 7979 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 7980 (if_then_else:SI
8fa3ba89 7981 (match_operator 5 "arm_comparison_operator"
8a18b90c 7982 [(match_operand:SI 3 "s_register_operand" "r,r")
7983 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7984 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7985 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 7986 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7987 "TARGET_ARM"
8a18b90c 7988 "#"
8fa3ba89 7989 [(set_attr "conds" "clob")
7990 (set_attr "length" "8,12")]
7991)
8a18b90c 7992
7993(define_insn "*if_move_neg"
7994 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7995 (if_then_else:SI
8fa3ba89 7996 (match_operator 4 "arm_comparison_operator"
8a18b90c 7997 [(match_operand 3 "cc_register" "") (const_int 0)])
7998 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7999 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 8000 "TARGET_ARM"
8a18b90c 8001 "@
8002 rsb%D4\\t%0, %2, #0
8003 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8004 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 8005 [(set_attr "conds" "use")
8006 (set_attr "length" "4,8,8")]
8007)
9c08d1fa 8008
f7fbdd4a 8009(define_insn "*arith_adjacentmem"
9c08d1fa 8010 [(set (match_operand:SI 0 "s_register_operand" "=r")
8011 (match_operator:SI 1 "shiftable_operator"
8012 [(match_operand:SI 2 "memory_operand" "m")
8013 (match_operand:SI 3 "memory_operand" "m")]))
8014 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 8015 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 8016 "*
215b30b3 8017 {
8018 rtx ldm[3];
8019 rtx arith[4];
8020 int val1 = 0, val2 = 0;
9c08d1fa 8021
215b30b3 8022 if (REGNO (operands[0]) > REGNO (operands[4]))
8023 {
8024 ldm[1] = operands[4];
8025 ldm[2] = operands[0];
8026 }
8027 else
8028 {
8029 ldm[1] = operands[0];
8030 ldm[2] = operands[4];
8031 }
8032 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8033 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8034 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8035 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8036 arith[0] = operands[0];
8037 arith[3] = operands[1];
8038 if (val1 < val2)
8039 {
8040 arith[1] = ldm[1];
8041 arith[2] = ldm[2];
8042 }
8043 else
8044 {
8045 arith[1] = ldm[2];
8046 arith[2] = ldm[1];
8047 }
8048 if (val1 && val2)
8049 {
8050 rtx ops[3];
8051 ldm[0] = ops[0] = operands[4];
8052 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8053 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8054 output_add_immediate (ops);
8055 if (val1 < val2)
8056 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8057 else
8058 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8059 }
8060 else if (val1)
8061 {
8062 ldm[0] = XEXP (operands[3], 0);
8063 if (val1 < val2)
8064 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8065 else
8066 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8067 }
8068 else
8069 {
8070 ldm[0] = XEXP (operands[2], 0);
8071 if (val1 < val2)
8072 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8073 else
8074 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8075 }
8076 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8077 return \"\";
8078 }"
8079 [(set_attr "length" "12")
8080 (set_attr "predicable" "yes")
8081 (set_attr "type" "load")]
8082)
9c08d1fa 8083
8084;; the arm can support extended pre-inc instructions
8085
8086;; In all these cases, we use operands 0 and 1 for the register being
8087;; incremented because those are the operands that local-alloc will
8088;; tie and these are the pair most likely to be tieable (and the ones
8089;; that will benefit the most).
8090
8091;; We reject the frame pointer if it occurs anywhere in these patterns since
8092;; elimination will cause too many headaches.
8093
f7fbdd4a 8094(define_insn "*strqi_preinc"
9c08d1fa 8095 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8096 (match_operand:SI 2 "index_operand" "rJ")))
8097 (match_operand:QI 3 "s_register_operand" "r"))
8098 (set (match_operand:SI 0 "s_register_operand" "=r")
8099 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8100 "TARGET_ARM
8101 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8102 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8103 && (GET_CODE (operands[2]) != REG
8104 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8105 "str%?b\\t%3, [%0, %2]!"
0d66636f 8106 [(set_attr "type" "store1")
8107 (set_attr "predicable" "yes")]
8108)
9c08d1fa 8109
f7fbdd4a 8110(define_insn "*strqi_predec"
9c08d1fa 8111 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8112 (match_operand:SI 2 "s_register_operand" "r")))
8113 (match_operand:QI 3 "s_register_operand" "r"))
8114 (set (match_operand:SI 0 "s_register_operand" "=r")
8115 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8116 "TARGET_ARM
8117 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8118 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8119 && (GET_CODE (operands[2]) != REG
8120 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8121 "str%?b\\t%3, [%0, -%2]!"
0d66636f 8122 [(set_attr "type" "store1")
8123 (set_attr "predicable" "yes")]
8124)
9c08d1fa 8125
f7fbdd4a 8126(define_insn "*loadqi_preinc"
9c08d1fa 8127 [(set (match_operand:QI 3 "s_register_operand" "=r")
8128 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8129 (match_operand:SI 2 "index_operand" "rJ"))))
8130 (set (match_operand:SI 0 "s_register_operand" "=r")
8131 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8132 "TARGET_ARM
8133 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8134 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8135 && (GET_CODE (operands[2]) != REG
8136 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8137 "ldr%?b\\t%3, [%0, %2]!"
0d66636f 8138 [(set_attr "type" "load")
8139 (set_attr "predicable" "yes")]
8140)
9c08d1fa 8141
f7fbdd4a 8142(define_insn "*loadqi_predec"
9c08d1fa 8143 [(set (match_operand:QI 3 "s_register_operand" "=r")
8144 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8145 (match_operand:SI 2 "s_register_operand" "r"))))
8146 (set (match_operand:SI 0 "s_register_operand" "=r")
8147 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8148 "TARGET_ARM
8149 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8150 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8151 && (GET_CODE (operands[2]) != REG
8152 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8153 "ldr%?b\\t%3, [%0, -%2]!"
0d66636f 8154 [(set_attr "type" "load")
8155 (set_attr "predicable" "yes")]
8156)
9c08d1fa 8157
f7fbdd4a 8158(define_insn "*loadqisi_preinc"
9c08d1fa 8159 [(set (match_operand:SI 3 "s_register_operand" "=r")
8160 (zero_extend:SI
8161 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8162 (match_operand:SI 2 "index_operand" "rJ")))))
8163 (set (match_operand:SI 0 "s_register_operand" "=r")
8164 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8165 "TARGET_ARM
8166 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8167 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8168 && (GET_CODE (operands[2]) != REG
8169 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8170 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
0d66636f 8171 [(set_attr "type" "load")
8172 (set_attr "predicable" "yes")]
8173)
9c08d1fa 8174
f7fbdd4a 8175(define_insn "*loadqisi_predec"
9c08d1fa 8176 [(set (match_operand:SI 3 "s_register_operand" "=r")
8177 (zero_extend:SI
8178 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8179 (match_operand:SI 2 "s_register_operand" "r")))))
8180 (set (match_operand:SI 0 "s_register_operand" "=r")
8181 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8182 "TARGET_ARM
8183 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8184 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8185 && (GET_CODE (operands[2]) != REG
8186 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8187 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
0d66636f 8188 [(set_attr "type" "load")
8189 (set_attr "predicable" "yes")]
8190)
9c08d1fa 8191
f7fbdd4a 8192(define_insn "*strsi_preinc"
9c08d1fa 8193 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8194 (match_operand:SI 2 "index_operand" "rJ")))
8195 (match_operand:SI 3 "s_register_operand" "r"))
8196 (set (match_operand:SI 0 "s_register_operand" "=r")
8197 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8198 "TARGET_ARM
8199 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8200 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8201 && (GET_CODE (operands[2]) != REG
8202 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8203 "str%?\\t%3, [%0, %2]!"
0d66636f 8204 [(set_attr "type" "store1")
8205 (set_attr "predicable" "yes")]
8206)
9c08d1fa 8207
cbd60e74 8208(define_insn "*strsi_predec"
9c08d1fa 8209 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8210 (match_operand:SI 2 "s_register_operand" "r")))
8211 (match_operand:SI 3 "s_register_operand" "r"))
8212 (set (match_operand:SI 0 "s_register_operand" "=r")
8213 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8214 "TARGET_ARM
8215 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8216 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8217 && (GET_CODE (operands[2]) != REG
8218 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8219 "str%?\\t%3, [%0, -%2]!"
0d66636f 8220 [(set_attr "type" "store1")
8221 (set_attr "predicable" "yes")]
8222)
9c08d1fa 8223
f7fbdd4a 8224(define_insn "*loadsi_preinc"
9c08d1fa 8225 [(set (match_operand:SI 3 "s_register_operand" "=r")
8226 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8227 (match_operand:SI 2 "index_operand" "rJ"))))
8228 (set (match_operand:SI 0 "s_register_operand" "=r")
8229 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8230 "TARGET_ARM
8231 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8232 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8233 && (GET_CODE (operands[2]) != REG
8234 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8235 "ldr%?\\t%3, [%0, %2]!"
0d66636f 8236 [(set_attr "type" "load")
8237 (set_attr "predicable" "yes")]
8238)
9c08d1fa 8239
f7fbdd4a 8240(define_insn "*loadsi_predec"
9c08d1fa 8241 [(set (match_operand:SI 3 "s_register_operand" "=r")
8242 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8243 (match_operand:SI 2 "s_register_operand" "r"))))
8244 (set (match_operand:SI 0 "s_register_operand" "=r")
8245 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8246 "TARGET_ARM
8247 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8248 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8249 && (GET_CODE (operands[2]) != REG
8250 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8251 "ldr%?\\t%3, [%0, -%2]!"
0d66636f 8252 [(set_attr "type" "load")
8253 (set_attr "predicable" "yes")]
8254)
9c08d1fa 8255
f7fbdd4a 8256(define_insn "*loadhi_preinc"
9c08d1fa 8257 [(set (match_operand:HI 3 "s_register_operand" "=r")
8258 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8259 (match_operand:SI 2 "index_operand" "rJ"))))
8260 (set (match_operand:SI 0 "s_register_operand" "=r")
8261 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8262 "TARGET_ARM
215b30b3 8263 && !BYTES_BIG_ENDIAN
8264 && !TARGET_MMU_TRAPS
0a666055 8265 && !arm_arch4
c7597b5d 8266 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8267 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8268 && (GET_CODE (operands[2]) != REG
8269 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8270 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
0d66636f 8271 [(set_attr "type" "load")
8272 (set_attr "predicable" "yes")]
8273)
9c08d1fa 8274
f7fbdd4a 8275(define_insn "*loadhi_predec"
9c08d1fa 8276 [(set (match_operand:HI 3 "s_register_operand" "=r")
8277 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8278 (match_operand:SI 2 "s_register_operand" "r"))))
8279 (set (match_operand:SI 0 "s_register_operand" "=r")
8280 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 8281 "TARGET_ARM
215b30b3 8282 && !BYTES_BIG_ENDIAN
8283 && !TARGET_MMU_TRAPS
0a666055 8284 && !arm_arch4
c7597b5d 8285 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8286 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8287 && (GET_CODE (operands[2]) != REG
8288 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 8289 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
0d66636f 8290 [(set_attr "type" "load")
8291 (set_attr "predicable" "yes")]
8292)
9c08d1fa 8293
f7fbdd4a 8294(define_insn "*strqi_shiftpreinc"
9c08d1fa 8295 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8296 [(match_operand:SI 3 "s_register_operand" "r")
8297 (match_operand:SI 4 "const_shift_operand" "n")])
8298 (match_operand:SI 1 "s_register_operand" "0")))
8299 (match_operand:QI 5 "s_register_operand" "r"))
8300 (set (match_operand:SI 0 "s_register_operand" "=r")
8301 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8302 (match_dup 1)))]
cffb2a26 8303 "TARGET_ARM
8304 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8305 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8306 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8307 "str%?b\\t%5, [%0, %3%S2]!"
0d66636f 8308 [(set_attr "type" "store1")
8309 (set_attr "predicable" "yes")]
8310)
9c08d1fa 8311
f7fbdd4a 8312(define_insn "*strqi_shiftpredec"
9c08d1fa 8313 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8314 (match_operator:SI 2 "shift_operator"
8315 [(match_operand:SI 3 "s_register_operand" "r")
8316 (match_operand:SI 4 "const_shift_operand" "n")])))
8317 (match_operand:QI 5 "s_register_operand" "r"))
8318 (set (match_operand:SI 0 "s_register_operand" "=r")
8319 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8320 (match_dup 4)])))]
cffb2a26 8321 "TARGET_ARM
8322 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8323 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8324 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8325 "str%?b\\t%5, [%0, -%3%S2]!"
0d66636f 8326 [(set_attr "type" "store1")
8327 (set_attr "predicable" "yes")]
8328)
9c08d1fa 8329
f7fbdd4a 8330(define_insn "*loadqi_shiftpreinc"
9c08d1fa 8331 [(set (match_operand:QI 5 "s_register_operand" "=r")
8332 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8333 [(match_operand:SI 3 "s_register_operand" "r")
8334 (match_operand:SI 4 "const_shift_operand" "n")])
8335 (match_operand:SI 1 "s_register_operand" "0"))))
8336 (set (match_operand:SI 0 "s_register_operand" "=r")
8337 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8338 (match_dup 1)))]
cffb2a26 8339 "TARGET_ARM
8340 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8341 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8342 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8343 "ldr%?b\\t%5, [%0, %3%S2]!"
0d66636f 8344 [(set_attr "type" "load")
8345 (set_attr "predicable" "yes")]
8346)
9c08d1fa 8347
f7fbdd4a 8348(define_insn "*loadqi_shiftpredec"
9c08d1fa 8349 [(set (match_operand:QI 5 "s_register_operand" "=r")
8350 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8351 (match_operator:SI 2 "shift_operator"
8352 [(match_operand:SI 3 "s_register_operand" "r")
8353 (match_operand:SI 4 "const_shift_operand" "n")]))))
8354 (set (match_operand:SI 0 "s_register_operand" "=r")
8355 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8356 (match_dup 4)])))]
cffb2a26 8357 "TARGET_ARM
8358 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8359 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8360 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8361 "ldr%?b\\t%5, [%0, -%3%S2]!"
0d66636f 8362 [(set_attr "type" "load")
8363 (set_attr "predicable" "yes")]
8364)
9c08d1fa 8365
f7fbdd4a 8366(define_insn "*strsi_shiftpreinc"
9c08d1fa 8367 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8368 [(match_operand:SI 3 "s_register_operand" "r")
8369 (match_operand:SI 4 "const_shift_operand" "n")])
8370 (match_operand:SI 1 "s_register_operand" "0")))
8371 (match_operand:SI 5 "s_register_operand" "r"))
8372 (set (match_operand:SI 0 "s_register_operand" "=r")
8373 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8374 (match_dup 1)))]
cffb2a26 8375 "TARGET_ARM
8376 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8377 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8378 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8379 "str%?\\t%5, [%0, %3%S2]!"
0d66636f 8380 [(set_attr "type" "store1")
8381 (set_attr "predicable" "yes")]
8382)
9c08d1fa 8383
f7fbdd4a 8384(define_insn "*strsi_shiftpredec"
9c08d1fa 8385 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8386 (match_operator:SI 2 "shift_operator"
8387 [(match_operand:SI 3 "s_register_operand" "r")
8388 (match_operand:SI 4 "const_shift_operand" "n")])))
8389 (match_operand:SI 5 "s_register_operand" "r"))
8390 (set (match_operand:SI 0 "s_register_operand" "=r")
8391 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8392 (match_dup 4)])))]
cffb2a26 8393 "TARGET_ARM
8394 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8395 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8396 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8397 "str%?\\t%5, [%0, -%3%S2]!"
0d66636f 8398 [(set_attr "type" "store1")
8399 (set_attr "predicable" "yes")]
8400)
9c08d1fa 8401
cbd60e74 8402(define_insn "*loadsi_shiftpreinc"
9c08d1fa 8403 [(set (match_operand:SI 5 "s_register_operand" "=r")
8404 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8405 [(match_operand:SI 3 "s_register_operand" "r")
8406 (match_operand:SI 4 "const_shift_operand" "n")])
8407 (match_operand:SI 1 "s_register_operand" "0"))))
8408 (set (match_operand:SI 0 "s_register_operand" "=r")
8409 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8410 (match_dup 1)))]
cffb2a26 8411 "TARGET_ARM
8412 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8413 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8414 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8415 "ldr%?\\t%5, [%0, %3%S2]!"
0d66636f 8416 [(set_attr "type" "load")
8417 (set_attr "predicable" "yes")]
8418)
9c08d1fa 8419
cbd60e74 8420(define_insn "*loadsi_shiftpredec"
9c08d1fa 8421 [(set (match_operand:SI 5 "s_register_operand" "=r")
8422 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8423 (match_operator:SI 2 "shift_operator"
8424 [(match_operand:SI 3 "s_register_operand" "r")
8425 (match_operand:SI 4 "const_shift_operand" "n")]))))
8426 (set (match_operand:SI 0 "s_register_operand" "=r")
8427 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8428 (match_dup 4)])))]
cffb2a26 8429 "TARGET_ARM
8430 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8431 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8432 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8433 "ldr%?\\t%5, [%0, -%3%S2]!"
0d66636f 8434 [(set_attr "type" "load")
8435 (set_attr "predicable" "yes")])
9c08d1fa 8436
f7fbdd4a 8437(define_insn "*loadhi_shiftpreinc"
9c08d1fa 8438 [(set (match_operand:HI 5 "s_register_operand" "=r")
8439 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8440 [(match_operand:SI 3 "s_register_operand" "r")
8441 (match_operand:SI 4 "const_shift_operand" "n")])
8442 (match_operand:SI 1 "s_register_operand" "0"))))
8443 (set (match_operand:SI 0 "s_register_operand" "=r")
8444 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8445 (match_dup 1)))]
cffb2a26 8446 "TARGET_ARM
215b30b3 8447 && !BYTES_BIG_ENDIAN
8448 && !TARGET_MMU_TRAPS
0a666055 8449 && !arm_arch4
c7597b5d 8450 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8451 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8452 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8453 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
0d66636f 8454 [(set_attr "type" "load")
8455 (set_attr "predicable" "yes")]
8456)
9c08d1fa 8457
f7fbdd4a 8458(define_insn "*loadhi_shiftpredec"
9c08d1fa 8459 [(set (match_operand:HI 5 "s_register_operand" "=r")
8460 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8461 (match_operator:SI 2 "shift_operator"
8462 [(match_operand:SI 3 "s_register_operand" "r")
8463 (match_operand:SI 4 "const_shift_operand" "n")]))))
8464 (set (match_operand:SI 0 "s_register_operand" "=r")
8465 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8466 (match_dup 4)])))]
cffb2a26 8467 "TARGET_ARM
215b30b3 8468 && !BYTES_BIG_ENDIAN
8469 && !TARGET_MMU_TRAPS
0a666055 8470 && !arm_arch4
c7597b5d 8471 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 8472 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8473 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 8474 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
0d66636f 8475 [(set_attr "type" "load")
8476 (set_attr "predicable" "yes")]
8477)
9c08d1fa 8478
8479; It can also support extended post-inc expressions, but combine doesn't
8480; try these....
8481; It doesn't seem worth adding peepholes for anything but the most common
8482; cases since, unlike combine, the increment must immediately follow the load
8483; for this pattern to match.
fc40f3ac 8484; We must watch to see that the source/destination register isn't also the
8485; same as the base address register, and that if the index is a register,
8486; that it is not the same as the base address register. In such cases the
e3e08e7f 8487; instruction that we would generate would have UNPREDICTABLE behavior so
fc40f3ac 8488; we cannot use it.
9c08d1fa 8489
8490(define_peephole
8491 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8492 (match_operand:QI 2 "s_register_operand" "r"))
8493 (set (match_dup 0)
8494 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 8495 "TARGET_ARM
8496 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 8497 && (GET_CODE (operands[1]) != REG
8498 || (REGNO (operands[1]) != REGNO (operands[0])))"
8499 "str%?b\\t%2, [%0], %1"
8500)
9c08d1fa 8501
8502(define_peephole
8503 [(set (match_operand:QI 0 "s_register_operand" "=r")
8504 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8505 (set (match_dup 1)
8506 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
fc40f3ac 8507 "TARGET_ARM
8508 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 8509 && (GET_CODE (operands[2]) != REG
8510 || REGNO(operands[0]) != REGNO (operands[2]))"
8511 "ldr%?b\\t%0, [%1], %2"
8512)
9c08d1fa 8513
8514(define_peephole
8515 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8516 (match_operand:SI 2 "s_register_operand" "r"))
8517 (set (match_dup 0)
8518 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 8519 "TARGET_ARM
8520 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 8521 && (GET_CODE (operands[1]) != REG
8522 || (REGNO (operands[1]) != REGNO (operands[0])))"
8523 "str%?\\t%2, [%0], %1"
8524)
9c08d1fa 8525
8526(define_peephole
8527 [(set (match_operand:HI 0 "s_register_operand" "=r")
8528 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8529 (set (match_dup 1)
8530 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
cffb2a26 8531 "TARGET_ARM
215b30b3 8532 && !BYTES_BIG_ENDIAN
8533 && !TARGET_MMU_TRAPS
0a666055 8534 && !arm_arch4
fc40f3ac 8535 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 8536 && (GET_CODE (operands[2]) != REG
8537 || REGNO(operands[0]) != REGNO (operands[2]))"
8538 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8539)
9c08d1fa 8540
8541(define_peephole
8542 [(set (match_operand:SI 0 "s_register_operand" "=r")
8543 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8544 (set (match_dup 1)
8545 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
cffb2a26 8546 "TARGET_ARM
fc40f3ac 8547 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 8548 && (GET_CODE (operands[2]) != REG
8549 || REGNO(operands[0]) != REGNO (operands[2]))"
8550 "ldr%?\\t%0, [%1], %2"
8551)
9c08d1fa 8552
c7597b5d 8553(define_peephole
8554 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8555 (match_operand:SI 1 "index_operand" "rJ")))
8556 (match_operand:QI 2 "s_register_operand" "r"))
8557 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
fc40f3ac 8558 "TARGET_ARM
8559 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 8560 && (GET_CODE (operands[1]) != REG
8561 || (REGNO (operands[1]) != REGNO (operands[0])))"
8562 "str%?b\\t%2, [%0, %1]!"
8563)
c7597b5d 8564
8565(define_peephole
8566 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8567 [(match_operand:SI 0 "s_register_operand" "r")
87b22bf7 8568 (match_operand:SI 1 "const_int_operand" "n")])
c7597b5d 8569 (match_operand:SI 2 "s_register_operand" "+r")))
8570 (match_operand:QI 3 "s_register_operand" "r"))
8571 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8572 (match_dup 2)))]
fc40f3ac 8573 "TARGET_ARM
8574 && (REGNO (operands[3]) != REGNO (operands[2]))
8575 && (REGNO (operands[0]) != REGNO (operands[2]))"
215b30b3 8576 "str%?b\\t%3, [%2, %0%S4]!"
8577)
c7597b5d 8578
9c08d1fa 8579; This pattern is never tried by combine, so do it as a peephole
8580
a0f94409 8581(define_peephole2
8582 [(set (match_operand:SI 0 "s_register_operand" "")
8583 (match_operand:SI 1 "s_register_operand" ""))
bd5b4116 8584 (set (reg:CC CC_REGNUM)
aea4c774 8585 (compare:CC (match_dup 1) (const_int 0)))]
722f9800 8586 "TARGET_ARM
7d57ec45 8587 && (!TARGET_CIRRUS
8588 || (!cirrus_fp_register (operands[0], SImode)
8589 && !cirrus_fp_register (operands[1], SImode)))
722f9800 8590 "
a0f94409 8591 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8592 (set (match_dup 0) (match_dup 1))])]
8593 ""
0d66636f 8594)
9c08d1fa 8595
675d848d 8596; Peepholes to spot possible load- and store-multiples, if the ordering is
8597; reversed, check that the memory references aren't volatile.
9c08d1fa 8598
8599(define_peephole
8600 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 8601 (match_operand:SI 4 "memory_operand" "m"))
8602 (set (match_operand:SI 1 "s_register_operand" "=r")
8603 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 8604 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 8605 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 8606 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 8607 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 8608 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 8609 "*
8610 return emit_ldm_seq (operands, 4);
215b30b3 8611 "
8612)
9c08d1fa 8613
8614(define_peephole
8615 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 8616 (match_operand:SI 3 "memory_operand" "m"))
8617 (set (match_operand:SI 1 "s_register_operand" "=r")
8618 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 8619 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 8620 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 8621 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 8622 "*
8623 return emit_ldm_seq (operands, 3);
215b30b3 8624 "
8625)
9c08d1fa 8626
8627(define_peephole
8628 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 8629 (match_operand:SI 2 "memory_operand" "m"))
8630 (set (match_operand:SI 1 "s_register_operand" "=r")
8631 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 8632 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 8633 "*
8634 return emit_ldm_seq (operands, 2);
215b30b3 8635 "
8636)
9c08d1fa 8637
8638(define_peephole
aea4c774 8639 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 8640 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 8641 (set (match_operand:SI 5 "memory_operand" "=m")
8642 (match_operand:SI 1 "s_register_operand" "r"))
8643 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 8644 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 8645 (set (match_operand:SI 7 "memory_operand" "=m")
8646 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 8647 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 8648 "*
8649 return emit_stm_seq (operands, 4);
215b30b3 8650 "
8651)
9c08d1fa 8652
8653(define_peephole
aea4c774 8654 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 8655 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 8656 (set (match_operand:SI 4 "memory_operand" "=m")
8657 (match_operand:SI 1 "s_register_operand" "r"))
8658 (set (match_operand:SI 5 "memory_operand" "=m")
8659 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 8660 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 8661 "*
8662 return emit_stm_seq (operands, 3);
215b30b3 8663 "
8664)
9c08d1fa 8665
8666(define_peephole
aea4c774 8667 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 8668 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 8669 (set (match_operand:SI 3 "memory_operand" "=m")
8670 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 8671 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 8672 "*
8673 return emit_stm_seq (operands, 2);
215b30b3 8674 "
8675)
9c08d1fa 8676
9c08d1fa 8677(define_split
8678 [(set (match_operand:SI 0 "s_register_operand" "")
8679 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8680 (const_int 0))
8fa3ba89 8681 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 8682 [(match_operand:SI 3 "s_register_operand" "")
8683 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8684 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 8685 "TARGET_ARM"
9c08d1fa 8686 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8687 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8688 (match_dup 5)))]
215b30b3 8689 ""
8690)
9c08d1fa 8691
aea4c774 8692;; This split can be used because CC_Z mode implies that the following
8693;; branch will be an equality, or an unsigned inequality, so the sign
8694;; extension is not needed.
9c08d1fa 8695
aea4c774 8696(define_split
bd5b4116 8697 [(set (reg:CC_Z CC_REGNUM)
aea4c774 8698 (compare:CC_Z
8699 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 8700 (const_int 24))
aea4c774 8701 (match_operand 1 "const_int_operand" "")))
8702 (clobber (match_scratch:SI 2 ""))]
cffb2a26 8703 "TARGET_ARM
8704 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8705 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 8706 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 8707 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 8708 "
9c08d1fa 8709 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 8710 "
8711)
9c08d1fa 8712
87b22bf7 8713(define_expand "prologue"
8714 [(clobber (const_int 0))]
cffb2a26 8715 "TARGET_EITHER"
8716 "if (TARGET_ARM)
8717 arm_expand_prologue ();
8718 else
8719 thumb_expand_prologue ();
87b22bf7 8720 DONE;
cffb2a26 8721 "
8722)
87b22bf7 8723
56d27660 8724(define_expand "epilogue"
e1159bbe 8725 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 8726 "TARGET_EITHER"
56d27660 8727 "
cffb2a26 8728 if (TARGET_THUMB)
8729 thumb_expand_epilogue ();
8730 else if (USE_RETURN_INSN (FALSE))
56d27660 8731 {
8732 emit_jump_insn (gen_return ());
8733 DONE;
8734 }
cffb2a26 8735 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8736 gen_rtvec (1,
8737 gen_rtx_RETURN (VOIDmode)),
e1159bbe 8738 VUNSPEC_EPILOGUE));
cffb2a26 8739 DONE;
8740 "
8741)
56d27660 8742
ef5651d0 8743;; Note - although unspec_volatile's USE all hard registers,
8744;; USEs are ignored after relaod has completed. Thus we need
8745;; to add an unspec of the link register to ensure that flow
8746;; does not think that it is unused by the sibcall branch that
8747;; will replace the standard function epilogue.
1c494086 8748(define_insn "sibcall_epilogue"
ef5651d0 8749 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8750 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
1c494086 8751 "TARGET_ARM"
8752 "*
1c494086 8753 if (USE_RETURN_INSN (FALSE))
5db468b7 8754 return output_return_instruction (const_true_rtx, FALSE, FALSE);
1c494086 8755 return arm_output_epilogue (FALSE);
8756 "
8757;; Length is absolute worst case
8758 [(set_attr "length" "44")
defc47cf 8759 (set_attr "type" "block")
8760 ;; We don't clobber the conditions, but the potential length of this
8761 ;; operation is sufficient to make conditionalizing the sequence
8762 ;; unlikely to be profitable.
8763 (set_attr "conds" "clob")]
1c494086 8764)
8765
cffb2a26 8766(define_insn "*epilogue_insns"
e1159bbe 8767 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 8768 "TARGET_EITHER"
56d27660 8769 "*
cffb2a26 8770 if (TARGET_ARM)
1c494086 8771 return arm_output_epilogue (TRUE);
cffb2a26 8772 else /* TARGET_THUMB */
8773 return thumb_unexpanded_epilogue ();
8774 "
215b30b3 8775 ; Length is absolute worst case
cffb2a26 8776 [(set_attr "length" "44")
defc47cf 8777 (set_attr "type" "block")
8778 ;; We don't clobber the conditions, but the potential length of this
8779 ;; operation is sufficient to make conditionalizing the sequence
8780 ;; unlikely to be profitable.
8781 (set_attr "conds" "clob")]
cffb2a26 8782)
8783
8784(define_expand "eh_epilogue"
8785 [(use (match_operand:SI 0 "register_operand" "r"))
8786 (use (match_operand:SI 1 "register_operand" "r"))
8787 (use (match_operand:SI 2 "register_operand" "r"))]
8788 "TARGET_EITHER"
8789 "
215b30b3 8790 {
8791 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8792 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8793 {
8794 rtx ra = gen_rtx_REG (Pmode, 2);
8795
8796 emit_move_insn (ra, operands[2]);
8797 operands[2] = ra;
8798 }
5cf3595a 8799 /* This is a hack -- we may have crystalized the function type too
8800 early. */
8801 cfun->machine->func_type = 0;
215b30b3 8802 }"
8803)
56d27660 8804
9c08d1fa 8805;; This split is only used during output to reduce the number of patterns
8806;; that need assembler instructions adding to them. We allowed the setting
8807;; of the conditions to be implicit during rtl generation so that
8808;; the conditional compare patterns would work. However this conflicts to
8a18b90c 8809;; some extent with the conditional data operations, so we have to split them
9c08d1fa 8810;; up again here.
8811
8812(define_split
8813 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8814 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8815 [(match_operand 2 "" "") (match_operand 3 "" "")])
8816 (match_dup 0)
8817 (match_operand 4 "" "")))
bd5b4116 8818 (clobber (reg:CC CC_REGNUM))]
0d66636f 8819 "TARGET_ARM && reload_completed"
8fa3ba89 8820 [(set (match_dup 5) (match_dup 6))
8821 (cond_exec (match_dup 7)
8822 (set (match_dup 0) (match_dup 4)))]
8823 "
8824 {
8825 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8826 operands[2], operands[3]);
8827 enum rtx_code rc = GET_CODE (operands[1]);
8828
bd5b4116 8829 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 8830 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8831 if (mode == CCFPmode || mode == CCFPEmode)
8832 rc = reverse_condition_maybe_unordered (rc);
8833 else
8834 rc = reverse_condition (rc);
8835
8836 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8837 }"
8838)
8839
8840(define_split
8841 [(set (match_operand:SI 0 "s_register_operand" "")
8842 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8843 [(match_operand 2 "" "") (match_operand 3 "" "")])
8844 (match_operand 4 "" "")
8845 (match_dup 0)))
bd5b4116 8846 (clobber (reg:CC CC_REGNUM))]
0d66636f 8847 "TARGET_ARM && reload_completed"
8fa3ba89 8848 [(set (match_dup 5) (match_dup 6))
8849 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8850 (set (match_dup 0) (match_dup 4)))]
8851 "
8852 {
8853 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8854 operands[2], operands[3]);
8855
bd5b4116 8856 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 8857 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8858 }"
8859)
8860
8861(define_split
8862 [(set (match_operand:SI 0 "s_register_operand" "")
8863 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 8864 [(match_operand 2 "" "") (match_operand 3 "" "")])
8865 (match_operand 4 "" "")
8866 (match_operand 5 "" "")))
bd5b4116 8867 (clobber (reg:CC CC_REGNUM))]
0d66636f 8868 "TARGET_ARM && reload_completed"
8fa3ba89 8869 [(set (match_dup 6) (match_dup 7))
8870 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8871 (set (match_dup 0) (match_dup 4)))
8872 (cond_exec (match_dup 8)
8873 (set (match_dup 0) (match_dup 5)))]
8874 "
8875 {
8876 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8877 operands[2], operands[3]);
8878 enum rtx_code rc = GET_CODE (operands[1]);
8879
bd5b4116 8880 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 8881 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8882 if (mode == CCFPmode || mode == CCFPEmode)
8883 rc = reverse_condition_maybe_unordered (rc);
8884 else
8885 rc = reverse_condition (rc);
8886
8887 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8888 }"
8889)
8890
cffb2a26 8891(define_split
8892 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 8893 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 8894 [(match_operand:SI 2 "s_register_operand" "")
8895 (match_operand:SI 3 "arm_add_operand" "")])
8896 (match_operand:SI 4 "arm_rhs_operand" "")
8897 (not:SI
8898 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 8899 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8900 "TARGET_ARM && reload_completed"
8901 [(set (match_dup 6) (match_dup 7))
f6c53574 8902 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8903 (set (match_dup 0) (match_dup 4)))
8904 (cond_exec (match_dup 8)
8905 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 8906 "
215b30b3 8907 {
8908 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8909 operands[2], operands[3]);
f6c53574 8910 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 8911
bd5b4116 8912 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
215b30b3 8913 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
f6c53574 8914 if (mode == CCFPmode || mode == CCFPEmode)
8915 rc = reverse_condition_maybe_unordered (rc);
8916 else
8917 rc = reverse_condition (rc);
8918
8919 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 8920 }"
8921)
cffb2a26 8922
8923(define_insn "*cond_move_not"
8924 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8925 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 8926 [(match_operand 3 "cc_register" "") (const_int 0)])
8927 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8928 (not:SI
8929 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8930 "TARGET_ARM"
8931 "@
8932 mvn%D4\\t%0, %2
8933 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 8934 [(set_attr "conds" "use")
8935 (set_attr "length" "4,8")]
8936)
cffb2a26 8937
9c08d1fa 8938;; The next two patterns occur when an AND operation is followed by a
8939;; scc insn sequence
8940
f7fbdd4a 8941(define_insn "*sign_extract_onebit"
9c08d1fa 8942 [(set (match_operand:SI 0 "s_register_operand" "=r")
8943 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8944 (const_int 1)
ed750274 8945 (match_operand:SI 2 "const_int_operand" "n")))
8946 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8947 "TARGET_ARM"
9c08d1fa 8948 "*
0d66636f 8949 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8950 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8951 return \"mvnne\\t%0, #0\";
8952 "
8953 [(set_attr "conds" "clob")
8954 (set_attr "length" "8")]
8955)
9c08d1fa 8956
f7fbdd4a 8957(define_insn "*not_signextract_onebit"
9c08d1fa 8958 [(set (match_operand:SI 0 "s_register_operand" "=r")
8959 (not:SI
8960 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8961 (const_int 1)
ed750274 8962 (match_operand:SI 2 "const_int_operand" "n"))))
8963 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8964 "TARGET_ARM"
9c08d1fa 8965 "*
0d66636f 8966 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8967 output_asm_insn (\"tst\\t%1, %2\", operands);
8968 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8969 return \"movne\\t%0, #0\";
8970 "
8971 [(set_attr "conds" "clob")
8972 (set_attr "length" "12")]
8973)
87b22bf7 8974
0d66636f 8975;; Push multiple registers to the stack. Registers are in parallel (use ...)
8976;; expressions. For simplicity, the first register is also in the unspec
8977;; part.
f7fbdd4a 8978(define_insn "*push_multi"
87b22bf7 8979 [(match_parallel 2 "multi_register_push"
8980 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 8981 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8982 UNSPEC_PUSH_MULT))])]
cffb2a26 8983 "TARGET_ARM"
87b22bf7 8984 "*
215b30b3 8985 {
8986 int num_saves = XVECLEN (operands[2], 0);
ed593f11 8987
215b30b3 8988 /* For the StrongARM at least it is faster to
8989 use STR to store only a single register. */
6079f055 8990 if (num_saves == 1)
215b30b3 8991 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8992 else
8993 {
8994 int i;
8995 char pattern[100];
ed593f11 8996
215b30b3 8997 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8998
6079f055 8999 for (i = 1; i < num_saves; i++)
215b30b3 9000 {
9001 strcat (pattern, \", %|\");
9002 strcat (pattern,
9003 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9004 }
9005
9006 strcat (pattern, \"}\");
9007 output_asm_insn (pattern, operands);
9008 }
9009
9010 return \"\";
9011 }"
9012 [(set_attr "type" "store4")]
9013)
f7fbdd4a 9014
4c58c898 9015(define_insn "stack_tie"
9016 [(set (mem:BLK (scratch))
9017 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9018 (match_operand:SI 1 "s_register_operand" "r")]
9019 UNSPEC_PRLG_STK))]
9020 ""
9021 ""
9022 [(set_attr "length" "0")]
9023)
9024
3398e91d 9025;; Similarly for the floating point registers
7b1d2fc4 9026(define_insn "*push_fp_multi"
9027 [(match_parallel 2 "multi_register_push"
9028 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 9029 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9030 UNSPEC_PUSH_MULT))])]
cffb2a26 9031 "TARGET_ARM"
7b1d2fc4 9032 "*
215b30b3 9033 {
9034 char pattern[100];
7b1d2fc4 9035
215b30b3 9036 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9037 output_asm_insn (pattern, operands);
9038 return \"\";
9039 }"
9040 [(set_attr "type" "f_store")]
9041)
7b1d2fc4 9042
f7fbdd4a 9043;; Special patterns for dealing with the constant pool
9044
cffb2a26 9045(define_insn "align_4"
e1159bbe 9046 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 9047 "TARGET_EITHER"
f7fbdd4a 9048 "*
cffb2a26 9049 assemble_align (32);
f7fbdd4a 9050 return \"\";
cffb2a26 9051 "
9052)
f7fbdd4a 9053
cffb2a26 9054(define_insn "consttable_end"
e1159bbe 9055 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 9056 "TARGET_EITHER"
f7fbdd4a 9057 "*
cffb2a26 9058 making_const_table = FALSE;
f7fbdd4a 9059 return \"\";
cffb2a26 9060 "
9061)
f7fbdd4a 9062
cffb2a26 9063(define_insn "consttable_1"
e1159bbe 9064 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
cffb2a26 9065 "TARGET_THUMB"
f7fbdd4a 9066 "*
cffb2a26 9067 making_const_table = TRUE;
09d688ff 9068 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 9069 assemble_zeros (3);
f7fbdd4a 9070 return \"\";
cffb2a26 9071 "
9072 [(set_attr "length" "4")]
9073)
f7fbdd4a 9074
cffb2a26 9075(define_insn "consttable_2"
e1159bbe 9076 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
cffb2a26 9077 "TARGET_THUMB"
f7fbdd4a 9078 "*
cffb2a26 9079 making_const_table = TRUE;
09d688ff 9080 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 9081 assemble_zeros (2);
f7fbdd4a 9082 return \"\";
cffb2a26 9083 "
9084 [(set_attr "length" "4")]
9085)
9086
9087(define_insn "consttable_4"
e1159bbe 9088 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 9089 "TARGET_EITHER"
9090 "*
9091 {
9092 making_const_table = TRUE;
9093 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9094 {
9095 case MODE_FLOAT:
9096 {
badfe841 9097 REAL_VALUE_TYPE r;
9098 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9099 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 9100 break;
9101 }
9102 default:
09d688ff 9103 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 9104 break;
9105 }
9106 return \"\";
9107 }"
9108 [(set_attr "length" "4")]
9109)
9110
9111(define_insn "consttable_8"
e1159bbe 9112 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 9113 "TARGET_EITHER"
9114 "*
9115 {
9116 making_const_table = TRUE;
9117 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9118 {
9119 case MODE_FLOAT:
9120 {
badfe841 9121 REAL_VALUE_TYPE r;
9122 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9123 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 9124 break;
9125 }
9126 default:
09d688ff 9127 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 9128 break;
9129 }
9130 return \"\";
9131 }"
9132 [(set_attr "length" "8")]
9133)
9134
9135;; Miscellaneous Thumb patterns
9136
fd957ef3 9137(define_expand "tablejump"
9138 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9139 (use (label_ref (match_operand 1 "" "")))])]
9140 "TARGET_THUMB"
9141 "
9142 if (flag_pic)
9143 {
9144 /* Hopefully, CSE will eliminate this copy. */
9145 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9146 rtx reg2 = gen_reg_rtx (SImode);
9147
9148 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9149 operands[0] = reg2;
9150 }
9151 "
9152)
9153
9154(define_insn "*thumb_tablejump"
cffb2a26 9155 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9156 (use (label_ref (match_operand 1 "" "")))]
9157 "TARGET_THUMB"
fd957ef3 9158 "mov\\t%|pc, %0"
cffb2a26 9159 [(set_attr "length" "2")]
9160)
0d66636f 9161
331beb1a 9162;; V5 Instructions,
9163
8f4be2be 9164(define_insn "clzsi2"
9165 [(set (match_operand:SI 0 "s_register_operand" "=r")
9166 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
e1159bbe 9167 "TARGET_ARM && arm_arch5"
61a2d04c 9168 "clz\\t%0, %1")
331beb1a 9169
e1159bbe 9170(define_expand "ffssi2"
9171 [(set (match_operand:SI 0 "s_register_operand" "")
9172 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9173 "TARGET_ARM && arm_arch5"
9174 "
9175 {
9176 rtx t1, t2, t3;
9177
9178 t1 = gen_reg_rtx (SImode);
9179 t2 = gen_reg_rtx (SImode);
9180 t3 = gen_reg_rtx (SImode);
9181
9182 emit_insn (gen_negsi2 (t1, operands[1]));
9183 emit_insn (gen_andsi3 (t2, operands[1], t1));
8f4be2be 9184 emit_insn (gen_clzsi2 (t3, t2));
e1159bbe 9185 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9186 DONE;
9187 }"
9188)
9189
8f4be2be 9190(define_expand "ctzsi2"
9191 [(set (match_operand:SI 0 "s_register_operand" "")
9192 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
9193 "TARGET_ARM && arm_arch5"
9194 "
9195 {
9196 rtx t1, t2, t3;
9197
9198 t1 = gen_reg_rtx (SImode);
9199 t2 = gen_reg_rtx (SImode);
9200 t3 = gen_reg_rtx (SImode);
9201
9202 emit_insn (gen_negsi2 (t1, operands[1]));
9203 emit_insn (gen_andsi3 (t2, operands[1], t1));
9204 emit_insn (gen_clzsi2 (t3, t2));
9205 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
9206 DONE;
9207 }"
9208)
9209
e1159bbe 9210;; V5E instructions.
331beb1a 9211
9212(define_insn "prefetch"
f4e79814 9213 [(prefetch (match_operand:SI 0 "address_operand" "p")
9214 (match_operand:SI 1 "" "")
9215 (match_operand:SI 2 "" ""))]
e1159bbe 9216 "TARGET_ARM && arm_arch5e"
bcb7a8f6 9217 "pld\\t%a0")
331beb1a 9218
0d66636f 9219;; General predication pattern
9220
9221(define_cond_exec
9222 [(match_operator 0 "arm_comparison_operator"
9223 [(match_operand 1 "cc_register" "")
9224 (const_int 0)])]
9225 "TARGET_ARM"
9226 ""
9227)
9228
063a05c7 9229(define_insn "prologue_use"
9230 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9231 ""
9232 "%@ %0 needed for prologue"
9233)