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