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