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