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