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