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