]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2004-06-25 Paolo Carlini <pcarlini@suse.de>
[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,
a941568e 3;; 2001, 2002, 2003 2004 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
215b30b3 131; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
132; scheduling decisions for the load unit and the multiplier.
9888ad6d 133(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
9c08d1fa 134
5ecb8da7 135; IS_XSCALE is set to 'yes' when compiling for XScale.
136(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
137
331beb1a 138;; Operand number of an input operand that is shifted. Zero if the
139;; given instruction does not shift one of its input operands.
331beb1a 140(define_attr "shift" "" (const_int 0))
141
3d91c5d6 142; Floating Point Unit. If we only have floating point emulation, then there
143; is no point in scheduling the floating point insns. (Well, for best
144; performance we should try and group them together).
a2cd141b 145(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 146 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 147
094e994f 148; LENGTH of an instruction (in bytes)
149(define_attr "length" "" (const_int 4))
9c08d1fa 150
56d27660 151; POOL_RANGE is how far away from a constant pool entry that this insn
152; can be placed. If the distance is zero, then this insn will never
153; reference the pool.
cffb2a26 154; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
155; before its address.
56d27660 156(define_attr "pool_range" "" (const_int 0))
cffb2a26 157(define_attr "neg_pool_range" "" (const_int 0))
56d27660 158
215b30b3 159; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 160; If such an insn references the pool, then we have no way of knowing how,
161; so use the most conservative value for pool_range.
9c08d1fa 162(define_asm_attributes
4d7a8451 163 [(set_attr "conds" "clob")
164 (set_attr "length" "4")
165 (set_attr "pool_range" "250")])
9c08d1fa 166
a2cd141b 167;; The instruction used to implement a particular pattern. This
168;; information is used by pipeline descriptions to provide accurate
169;; scheduling information.
170
171(define_attr "insn"
172 "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
173 (const_string "other"))
174
9c08d1fa 175; TYPE attribute is used to detect floating point instructions which, if
176; running on a co-processor can run in parallel with other, basic instructions
177; If write-buffer scheduling is enabled then it can also be used in the
178; scheduling of writes.
179
180; Classification of each insn
a2cd141b 181; alu any alu instruction that doesn't hit memory or fp
182; regs or have a shifted source operand
183; alu_shift any data instruction that doesn't hit memory or fp
184; regs, but has a source operand shifted by a constant
185; alu_shift_reg any data instruction that doesn't hit memory or fp
186; regs, but has a source operand shifted by a register value
f7fbdd4a 187; mult a multiply instruction
9c08d1fa 188; block blockage insn, this blocks all functional units
189; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 190; fdivd DFmode floating point division
191; fdivs SFmode floating point division
192; fmul Floating point multiply
193; ffmul Fast floating point multiply
194; farith Floating point arithmetic (4 cycle)
195; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 196; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 197; even on a machine with an fpa.
9c08d1fa 198; f_load a floating point load from memory
199; f_store a floating point store to memory
200; f_mem_r a transfer of a floating point register to a real reg via mem
201; r_mem_f the reverse of f_mem_r
202; f_2_r fast transfer float to arm (no memory needed)
203; r_2_f fast transfer arm to float
a2cd141b 204; branch a branch
9c08d1fa 205; call a subroutine call
a2cd141b 206; load_byte load byte(s) from memory to arm registers
207; load1 load 1 word from memory to arm registers
208; load2 load 2 words from memory to arm registers
209; load3 load 3 words from memory to arm registers
210; load4 load 4 words from memory to arm registers
211; store store 1 word to memory from arm registers
9c08d1fa 212; store2 store 2 words
213; store3 store 3 words
a2cd141b 214; store4 store 4 (or more) words
2c6c7d8b 215; Additions for Cirrus Maverick co-processor:
216; mav_farith Floating point arithmetic (4 cycle)
217; mav_dmult Double multiplies (7 cycle)
9c08d1fa 218;
219(define_attr "type"
a2cd141b 220 "alu,alu_shift,alu_shift_reg,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,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
221 (if_then_else
222 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
223 (const_string "mult")
224 (const_string "alu")))
9c08d1fa 225
9888ad6d 226; Load scheduling, set from the arm_ld_sched variable
457275b6 227; initialized by arm_override_options()
9888ad6d 228(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 229
f7fbdd4a 230; condition codes: this one is used by final_prescan_insn to speed up
231; conditionalizing instructions. It saves having to scan the rtl to see if
232; it uses or alters the condition codes.
215b30b3 233;
f7fbdd4a 234; USE means that the condition codes are used by the insn in the process of
215b30b3 235; outputting code, this means (at present) that we can't use the insn in
236; inlined branches
237;
f7fbdd4a 238; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 239; well defined manner.
240;
f7fbdd4a 241; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 242; they are altered at all
243;
8fa3ba89 244; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 245; instruction (UNEQ and LTGT). These cannot be predicated.
246;
f7fbdd4a 247; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 248; output of this insn
f7fbdd4a 249
250(define_attr "conds" "use,set,clob,jump_clob,nocond"
251 (if_then_else (eq_attr "type" "call")
c1a66faf 252 (const_string "clob")
f7fbdd4a 253 (const_string "nocond")))
254
215b30b3 255; Predicable means that the insn can be conditionally executed based on
256; an automatically added predicate (additional patterns are generated by
257; gen...). We default to 'no' because no Thumb patterns match this rule
258; and not all ARM patterns do.
0d66636f 259(define_attr "predicable" "no,yes" (const_string "no"))
260
129a2fe4 261; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
262; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 263; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 264; affect the schedule).
9888ad6d 265(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
129a2fe4 266
215b30b3 267; WRITE_CONFLICT implies that a read following an unrelated write is likely
268; to stall the processor. Used with model_wbuf above.
9c08d1fa 269(define_attr "write_conflict" "no,yes"
270 (if_then_else (eq_attr "type"
a2cd141b 271 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 272 (const_string "yes")
273 (const_string "no")))
274
215b30b3 275; Classify the insns into those that take one cycle and those that take more
276; than one on the main cpu execution unit.
f7fbdd4a 277(define_attr "core_cycles" "single,multi"
278 (if_then_else (eq_attr "type"
a2cd141b 279 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 280 (const_string "single")
281 (const_string "multi")))
282
cffb2a26 283;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 284;; distant label. Only applicable to Thumb code.
cffb2a26 285(define_attr "far_jump" "yes,no" (const_string "no"))
286
a2cd141b 287;;---------------------------------------------------------------------------
288;; Pipeline descriptions
215b30b3 289
a2cd141b 290;; Processor type. This attribute must exactly match the table in
291;; arm-cores.def.
292(define_attr "tune"
293 "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7m,arm7d,arm7dm,arm7di,arm7dmi,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7tdmi,arm710t,arm720t,arm740t,arm8,arm810,arm9,arm920,arm920t,arm940t,arm9tdmi,arm9e,ep9312,strongarm,strongarm110,strongarm1100,strongarm1110,arm10tdmi,arm1020t,arm926ejs,arm1026ejs,xscale,iwmmxt,arm1136js,arm1136jfs"
294 (const (symbol_ref "arm_tune")))
331beb1a 295
a2cd141b 296;; True if the generic scheduling description should be used.
297
298(define_attr "generic_sched" "yes,no"
299 (if_then_else
300 (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs")
301 (const_string "no")
302 (const_string "yes")))
303
304(include "arm-generic.md")
305(include "arm926ejs.md")
306(include "arm1026ejs.md")
307(include "arm1136jfs.md")
3586df96 308
9c08d1fa 309\f
215b30b3 310;;---------------------------------------------------------------------------
e1159bbe 311;; Insn patterns
312;;
a0f94409 313;; Addition insns.
215b30b3 314
9c08d1fa 315;; Note: For DImode insns, there is normally no reason why operands should
316;; not be in the same register, what we don't want is for something being
317;; written to partially overlap something that is an input.
7d57ec45 318;; Cirrus 64bit additions should not be split because we have a native
319;; 64bit addition instructions.
9c08d1fa 320
cffb2a26 321(define_expand "adddi3"
322 [(parallel
215b30b3 323 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 324 (plus:DI (match_operand:DI 1 "s_register_operand" "")
325 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 326 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 327 "TARGET_EITHER"
328 "
a2cd141b 329 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 330 {
331 if (!cirrus_fp_register (operands[0], DImode))
332 operands[0] = force_reg (DImode, operands[0]);
333 if (!cirrus_fp_register (operands[1], DImode))
334 operands[1] = force_reg (DImode, operands[1]);
335 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
336 DONE;
337 }
338
cffb2a26 339 if (TARGET_THUMB)
340 {
341 if (GET_CODE (operands[1]) != REG)
342 operands[1] = force_reg (SImode, operands[1]);
343 if (GET_CODE (operands[2]) != REG)
344 operands[2] = force_reg (SImode, operands[2]);
345 }
346 "
347)
348
349(define_insn "*thumb_adddi3"
350 [(set (match_operand:DI 0 "register_operand" "=l")
351 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 352 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 353 (clobber (reg:CC CC_REGNUM))
cffb2a26 354 ]
355 "TARGET_THUMB"
356 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
357 [(set_attr "length" "4")]
358)
359
a0f94409 360(define_insn_and_split "*arm_adddi3"
cffb2a26 361 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 362 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
363 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 364 (clobber (reg:CC CC_REGNUM))]
a2cd141b 365 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 366 "#"
a0f94409 367 "TARGET_ARM && reload_completed"
368 [(parallel [(set (reg:CC_C CC_REGNUM)
369 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
370 (match_dup 1)))
371 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
372 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
373 (plus:SI (match_dup 4) (match_dup 5))))]
374 "
375 {
376 operands[3] = gen_highpart (SImode, operands[0]);
377 operands[0] = gen_lowpart (SImode, operands[0]);
378 operands[4] = gen_highpart (SImode, operands[1]);
379 operands[1] = gen_lowpart (SImode, operands[1]);
380 operands[5] = gen_highpart (SImode, operands[2]);
381 operands[2] = gen_lowpart (SImode, operands[2]);
382 }"
cffb2a26 383 [(set_attr "conds" "clob")
384 (set_attr "length" "8")]
385)
9c08d1fa 386
a0f94409 387(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 388 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
389 (plus:DI (sign_extend:DI
97499065 390 (match_operand:SI 2 "s_register_operand" "r,r"))
391 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 392 (clobber (reg:CC CC_REGNUM))]
a2cd141b 393 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 394 "#"
a0f94409 395 "TARGET_ARM && reload_completed"
396 [(parallel [(set (reg:CC_C CC_REGNUM)
397 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398 (match_dup 1)))
399 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401 (plus:SI (ashiftrt:SI (match_dup 2)
402 (const_int 31))
403 (match_dup 4))))]
404 "
405 {
406 operands[3] = gen_highpart (SImode, operands[0]);
407 operands[0] = gen_lowpart (SImode, operands[0]);
408 operands[4] = gen_highpart (SImode, operands[1]);
409 operands[1] = gen_lowpart (SImode, operands[1]);
410 operands[2] = gen_lowpart (SImode, operands[2]);
411 }"
215b30b3 412 [(set_attr "conds" "clob")
413 (set_attr "length" "8")]
414)
9c08d1fa 415
a0f94409 416(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 417 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
418 (plus:DI (zero_extend:DI
97499065 419 (match_operand:SI 2 "s_register_operand" "r,r"))
420 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 421 (clobber (reg:CC CC_REGNUM))]
a2cd141b 422 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 423 "#"
a0f94409 424 "TARGET_ARM && reload_completed"
425 [(parallel [(set (reg:CC_C CC_REGNUM)
426 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
427 (match_dup 1)))
428 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
429 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
430 (plus:SI (match_dup 4) (const_int 0))))]
431 "
432 {
433 operands[3] = gen_highpart (SImode, operands[0]);
434 operands[0] = gen_lowpart (SImode, operands[0]);
435 operands[4] = gen_highpart (SImode, operands[1]);
436 operands[1] = gen_lowpart (SImode, operands[1]);
437 operands[2] = gen_lowpart (SImode, operands[2]);
438 }"
cffb2a26 439 [(set_attr "conds" "clob")
440 (set_attr "length" "8")]
441)
b11cae9e 442
87b22bf7 443(define_expand "addsi3"
cffb2a26 444 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 445 (plus:SI (match_operand:SI 1 "s_register_operand" "")
446 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 447 "TARGET_EITHER"
87b22bf7 448 "
cffb2a26 449 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 450 {
96f57e36 451 arm_split_constant (PLUS, SImode, NULL_RTX,
452 INTVAL (operands[2]), operands[0], operands[1],
935d87ee 453 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
87b22bf7 454 DONE;
455 }
cffb2a26 456 "
457)
87b22bf7 458
5bd751ff 459; If there is a scratch available, this will be faster than synthesizing the
a0f94409 460; addition.
461(define_peephole2
462 [(match_scratch:SI 3 "r")
372575c7 463 (set (match_operand:SI 0 "arm_general_register_operand" "")
464 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 465 (match_operand:SI 2 "const_int_operand" "")))]
466 "TARGET_ARM &&
a0f94409 467 !(const_ok_for_arm (INTVAL (operands[2]))
468 || const_ok_for_arm (-INTVAL (operands[2])))
469 && const_ok_for_arm (~INTVAL (operands[2]))"
470 [(set (match_dup 3) (match_dup 2))
471 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
472 ""
473)
87b22bf7 474
a0f94409 475(define_insn_and_split "*arm_addsi3"
cffb2a26 476 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0f94409 477 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
87b22bf7 478 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
cffb2a26 479 "TARGET_ARM"
5565501b 480 "@
481 add%?\\t%0, %1, %2
87b22bf7 482 sub%?\\t%0, %1, #%n2
483 #"
a0f94409 484 "TARGET_ARM &&
485 GET_CODE (operands[2]) == CONST_INT
486 && !(const_ok_for_arm (INTVAL (operands[2]))
487 || const_ok_for_arm (-INTVAL (operands[2])))"
488 [(clobber (const_int 0))]
489 "
96f57e36 490 arm_split_constant (PLUS, SImode, curr_insn,
491 INTVAL (operands[2]), operands[0],
a0f94409 492 operands[1], 0);
493 DONE;
494 "
0d66636f 495 [(set_attr "length" "4,4,16")
496 (set_attr "predicable" "yes")]
cffb2a26 497)
498
499;; Register group 'k' is a single register group containing only the stack
500;; register. Trying to reload it will always fail catastrophically,
501;; so never allow those alternatives to match if reloading is needed.
502
503(define_insn "*thumb_addsi3"
504 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
505 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
506 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
507 "TARGET_THUMB"
508 "*
0d66636f 509 static const char * const asms[] =
cffb2a26 510 {
511 \"add\\t%0, %0, %2\",
512 \"sub\\t%0, %0, #%n2\",
513 \"add\\t%0, %1, %2\",
514 \"add\\t%0, %0, %2\",
515 \"add\\t%0, %0, %2\",
516 \"add\\t%0, %1, %2\",
517 \"add\\t%0, %1, %2\"
518 };
519 if ((which_alternative == 2 || which_alternative == 6)
520 && GET_CODE (operands[2]) == CONST_INT
521 && INTVAL (operands[2]) < 0)
522 return \"sub\\t%0, %1, #%n2\";
523 return asms[which_alternative];
524 "
525 [(set_attr "length" "2")]
526)
527
528;; Reloading and elimination of the frame pointer can
529;; sometimes cause this optimization to be missed.
a0f94409 530(define_peephole2
372575c7 531 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 532 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 533 (set (match_dup 0)
372575c7 534 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
cffb2a26 535 "TARGET_THUMB
cffb2a26 536 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
537 && (INTVAL (operands[1]) & 3) == 0"
372575c7 538 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 539 ""
cffb2a26 540)
b11cae9e 541
f7fbdd4a 542(define_insn "*addsi3_compare0"
bd5b4116 543 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 544 (compare:CC_NOOV
215b30b3 545 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
546 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 547 (const_int 0)))
548 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 549 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 550 "TARGET_ARM"
5565501b 551 "@
552 add%?s\\t%0, %1, %2
553 sub%?s\\t%0, %1, #%n2"
cffb2a26 554 [(set_attr "conds" "set")]
555)
9c08d1fa 556
aea4c774 557(define_insn "*addsi3_compare0_scratch"
bd5b4116 558 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 559 (compare:CC_NOOV
215b30b3 560 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
561 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 562 (const_int 0)))]
cffb2a26 563 "TARGET_ARM"
564 "@
565 cmn%?\\t%0, %1
566 cmp%?\\t%0, #%n1"
0d66636f 567 [(set_attr "conds" "set")]
568)
cffb2a26 569
570;; These patterns are the same ones as the two regular addsi3_compare0
571;; patterns, except we write them slightly different - the combiner
572;; tends to generate them this way.
573(define_insn "*addsi3_compare0_for_combiner"
bd5b4116 574 [(set (reg:CC CC_REGNUM)
cffb2a26 575 (compare:CC
576 (match_operand:SI 1 "s_register_operand" "r,r")
577 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
578 (set (match_operand:SI 0 "s_register_operand" "=r,r")
579 (plus:SI (match_dup 1) (match_dup 2)))]
580 "TARGET_ARM"
581 "@
582 add%?s\\t%0, %1, %2
583 sub%?s\\t%0, %1, #%n2"
584 [(set_attr "conds" "set")]
585)
586
587(define_insn "*addsi3_compare0_scratch_for_combiner"
bd5b4116 588 [(set (reg:CC CC_REGNUM)
cffb2a26 589 (compare:CC
590 (match_operand:SI 0 "s_register_operand" "r,r")
591 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
592 "TARGET_ARM"
aea4c774 593 "@
594 cmn%?\\t%0, %1
595 cmp%?\\t%0, #%n1"
0d66636f 596 [(set_attr "conds" "set")]
597)
aea4c774 598
203c488f 599;; This is the canonicalization of addsi3_compare0_for_combiner when the
600;; addend is a constant.
601(define_insn "*cmpsi2_addneg"
602 [(set (reg:CC CC_REGNUM)
603 (compare:CC
604 (match_operand:SI 1 "s_register_operand" "r,r")
605 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
606 (set (match_operand:SI 0 "s_register_operand" "=r,r")
607 (plus:SI (match_dup 1)
608 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
609 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
610 "@
611 sub%?s\\t%0, %1, %2
612 add%?s\\t%0, %1, #%n2"
613 [(set_attr "conds" "set")]
614)
615
616;; Convert the sequence
617;; sub rd, rn, #1
618;; cmn rd, #1 (equivalent to cmp rd, #-1)
619;; bne dest
620;; into
621;; subs rd, rn, #1
622;; bcs dest ((unsigned)rn >= 1)
623;; similarly for the beq variant using bcc.
624;; This is a common looping idiom (while (n--))
625(define_peephole2
372575c7 626 [(set (match_operand:SI 0 "arm_general_register_operand" "")
627 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 628 (const_int -1)))
629 (set (match_operand 2 "cc_register" "")
630 (compare (match_dup 0) (const_int -1)))
631 (set (pc)
632 (if_then_else (match_operator 3 "equality_operator"
633 [(match_dup 2) (const_int 0)])
634 (match_operand 4 "" "")
635 (match_operand 5 "" "")))]
636 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
637 [(parallel[
638 (set (match_dup 2)
639 (compare:CC
640 (match_dup 1) (const_int 1)))
641 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
642 (set (pc)
643 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
644 (match_dup 4)
645 (match_dup 5)))]
646 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
647 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
648 ? GEU : LTU),
649 VOIDmode,
650 operands[2], const0_rtx);"
651)
652
ebcc79bc 653;; The next four insns work because they compare the result with one of
654;; the operands, and we know that the use of the condition code is
655;; either GEU or LTU, so we can use the carry flag from the addition
656;; instead of doing the compare a second time.
657(define_insn "*addsi3_compare_op1"
bd5b4116 658 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 659 (compare:CC_C
660 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
661 (match_operand:SI 2 "arm_add_operand" "rI,L"))
662 (match_dup 1)))
663 (set (match_operand:SI 0 "s_register_operand" "=r,r")
664 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 665 "TARGET_ARM"
ebcc79bc 666 "@
667 add%?s\\t%0, %1, %2
668 sub%?s\\t%0, %1, #%n2"
0d66636f 669 [(set_attr "conds" "set")]
670)
ebcc79bc 671
672(define_insn "*addsi3_compare_op2"
bd5b4116 673 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 674 (compare:CC_C
675 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_add_operand" "rI,L"))
677 (match_dup 2)))
5565501b 678 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 679 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 680 "TARGET_ARM"
5565501b 681 "@
682 add%?s\\t%0, %1, %2
683 sub%?s\\t%0, %1, #%n2"
0d66636f 684 [(set_attr "conds" "set")]
685)
9c08d1fa 686
ebcc79bc 687(define_insn "*compare_addsi2_op0"
bd5b4116 688 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 689 (compare:CC_C
690 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
691 (match_operand:SI 1 "arm_add_operand" "rI,L"))
692 (match_dup 0)))]
cffb2a26 693 "TARGET_ARM"
ebcc79bc 694 "@
695 cmn%?\\t%0, %1
696 cmp%?\\t%0, #%n1"
0d66636f 697 [(set_attr "conds" "set")]
698)
ebcc79bc 699
700(define_insn "*compare_addsi2_op1"
bd5b4116 701 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 702 (compare:CC_C
703 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
704 (match_operand:SI 1 "arm_add_operand" "rI,L"))
705 (match_dup 1)))]
cffb2a26 706 "TARGET_ARM"
ebcc79bc 707 "@
708 cmn%?\\t%0, %1
709 cmp%?\\t%0, #%n1"
0d66636f 710 [(set_attr "conds" "set")]
711)
ebcc79bc 712
713(define_insn "*addsi3_carryin"
714 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 715 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 716 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
717 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
cffb2a26 718 "TARGET_ARM"
ebcc79bc 719 "adc%?\\t%0, %1, %2"
cffb2a26 720 [(set_attr "conds" "use")]
721)
ebcc79bc 722
33782ec7 723(define_insn "*addsi3_carryin_shift"
7b63a8dd 724 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 725 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 726 (plus:SI
727 (match_operator:SI 2 "shift_operator"
7b63a8dd 728 [(match_operand:SI 3 "s_register_operand" "r")
729 (match_operand:SI 4 "reg_or_int_operand" "rM")])
730 (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 731 "TARGET_ARM"
33782ec7 732 "adc%?\\t%0, %1, %3%S2"
a2cd141b 733 [(set_attr "conds" "use")
734 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
735 (const_string "alu_shift")
736 (const_string "alu_shift_reg")))]
33782ec7 737)
738
ebcc79bc 739(define_insn "*addsi3_carryin_alt1"
740 [(set (match_operand:SI 0 "s_register_operand" "=r")
741 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
742 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 743 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
cffb2a26 744 "TARGET_ARM"
ebcc79bc 745 "adc%?\\t%0, %1, %2"
cffb2a26 746 [(set_attr "conds" "use")]
747)
ebcc79bc 748
749(define_insn "*addsi3_carryin_alt2"
750 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 751 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 752 (match_operand:SI 1 "s_register_operand" "r"))
753 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 754 "TARGET_ARM"
ebcc79bc 755 "adc%?\\t%0, %1, %2"
0d66636f 756 [(set_attr "conds" "use")]
757)
ebcc79bc 758
759(define_insn "*addsi3_carryin_alt3"
760 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 761 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 762 (match_operand:SI 2 "arm_rhs_operand" "rI"))
763 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 764 "TARGET_ARM"
ebcc79bc 765 "adc%?\\t%0, %1, %2"
cffb2a26 766 [(set_attr "conds" "use")]
767)
ebcc79bc 768
9c08d1fa 769(define_insn "incscc"
770 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 771 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 772 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 773 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 774 "TARGET_ARM"
5565501b 775 "@
776 add%d2\\t%0, %1, #1
777 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 778 [(set_attr "conds" "use")
215b30b3 779 (set_attr "length" "4,8")]
780)
9c08d1fa 781
d795fb69 782; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
783(define_split
784 [(set (match_operand:SI 0 "s_register_operand" "")
785 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
786 (match_operand:SI 2 "s_register_operand" ""))
787 (const_int -1)))
788 (clobber (match_operand:SI 3 "s_register_operand" ""))]
789 "TARGET_ARM"
790 [(set (match_dup 3) (match_dup 1))
791 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
792 "
793 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
794")
795
604f3a0a 796(define_expand "addsf3"
797 [(set (match_operand:SF 0 "s_register_operand" "")
798 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 799 (match_operand:SF 2 "arm_float_add_operand" "")))]
800 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 801 "
a2cd141b 802 if (TARGET_MAVERICK
604f3a0a 803 && !cirrus_fp_register (operands[2], SFmode))
804 operands[2] = force_reg (SFmode, operands[2]);
805")
806
604f3a0a 807(define_expand "adddf3"
808 [(set (match_operand:DF 0 "s_register_operand" "")
809 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 810 (match_operand:DF 2 "arm_float_add_operand" "")))]
811 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 812 "
a2cd141b 813 if (TARGET_MAVERICK
604f3a0a 814 && !cirrus_fp_register (operands[2], DFmode))
815 operands[2] = force_reg (DFmode, operands[2]);
816")
817
cffb2a26 818(define_expand "subdi3"
819 [(parallel
820 [(set (match_operand:DI 0 "s_register_operand" "")
821 (minus:DI (match_operand:DI 1 "s_register_operand" "")
822 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 823 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 824 "TARGET_EITHER"
825 "
a2cd141b 826 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
7d57ec45 827 && TARGET_ARM
828 && cirrus_fp_register (operands[0], DImode)
829 && cirrus_fp_register (operands[1], DImode))
830 {
831 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
832 DONE;
833 }
834
cffb2a26 835 if (TARGET_THUMB)
836 {
837 if (GET_CODE (operands[1]) != REG)
838 operands[1] = force_reg (SImode, operands[1]);
839 if (GET_CODE (operands[2]) != REG)
840 operands[2] = force_reg (SImode, operands[2]);
841 }
842 "
843)
844
845(define_insn "*arm_subdi3"
846 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 847 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
848 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 849 (clobber (reg:CC CC_REGNUM))]
cffb2a26 850 "TARGET_ARM"
97499065 851 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 852 [(set_attr "conds" "clob")
853 (set_attr "length" "8")]
854)
855
856(define_insn "*thumb_subdi3"
857 [(set (match_operand:DI 0 "register_operand" "=l")
858 (minus:DI (match_operand:DI 1 "register_operand" "0")
859 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 860 (clobber (reg:CC CC_REGNUM))]
cffb2a26 861 "TARGET_THUMB"
862 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
863 [(set_attr "length" "4")]
864)
9c08d1fa 865
f7fbdd4a 866(define_insn "*subdi_di_zesidi"
cffb2a26 867 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
868 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
9c08d1fa 869 (zero_extend:DI
cffb2a26 870 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 871 (clobber (reg:CC CC_REGNUM))]
cffb2a26 872 "TARGET_ARM"
97499065 873 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
cffb2a26 874 [(set_attr "conds" "clob")
875 (set_attr "length" "8")]
876)
9c08d1fa 877
f7fbdd4a 878(define_insn "*subdi_di_sesidi"
cffb2a26 879 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
880 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 881 (sign_extend:DI
cffb2a26 882 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 883 (clobber (reg:CC CC_REGNUM))]
cffb2a26 884 "TARGET_ARM"
97499065 885 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
888)
9c08d1fa 889
f7fbdd4a 890(define_insn "*subdi_zesidi_di"
cffb2a26 891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 892 (minus:DI (zero_extend:DI
cffb2a26 893 (match_operand:SI 2 "s_register_operand" "r,r"))
894 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 895 (clobber (reg:CC CC_REGNUM))]
cffb2a26 896 "TARGET_ARM"
97499065 897 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
cffb2a26 898 [(set_attr "conds" "clob")
899 (set_attr "length" "8")]
900)
9c08d1fa 901
f7fbdd4a 902(define_insn "*subdi_sesidi_di"
cffb2a26 903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 904 (minus:DI (sign_extend:DI
cffb2a26 905 (match_operand:SI 2 "s_register_operand" "r,r"))
906 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 907 (clobber (reg:CC CC_REGNUM))]
cffb2a26 908 "TARGET_ARM"
97499065 909 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
912)
9c08d1fa 913
f7fbdd4a 914(define_insn "*subdi_zesidi_zesidi"
cffb2a26 915 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 916 (minus:DI (zero_extend:DI
cffb2a26 917 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 918 (zero_extend:DI
cffb2a26 919 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 920 (clobber (reg:CC CC_REGNUM))]
cffb2a26 921 "TARGET_ARM"
97499065 922 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
cffb2a26 923 [(set_attr "conds" "clob")
924 (set_attr "length" "8")]
925)
b11cae9e 926
87b22bf7 927(define_expand "subsi3"
cffb2a26 928 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 929 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
930 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 931 "TARGET_EITHER"
87b22bf7 932 "
933 if (GET_CODE (operands[1]) == CONST_INT)
934 {
cffb2a26 935 if (TARGET_ARM)
936 {
96f57e36 937 arm_split_constant (MINUS, SImode, NULL_RTX,
938 INTVAL (operands[1]), operands[0],
cffb2a26 939 operands[2],
935d87ee 940 (no_new_pseudos ? 0
cffb2a26 941 : preserve_subexpressions_p ()));
942 DONE;
943 }
944 else /* TARGET_THUMB */
945 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 946 }
cffb2a26 947 "
948)
87b22bf7 949
cffb2a26 950(define_insn "*thumb_subsi3_insn"
951 [(set (match_operand:SI 0 "register_operand" "=l")
952 (minus:SI (match_operand:SI 1 "register_operand" "l")
953 (match_operand:SI 2 "register_operand" "l")))]
954 "TARGET_THUMB"
955 "sub\\t%0, %1, %2"
956 [(set_attr "length" "2")]
957)
958
a0f94409 959(define_insn_and_split "*arm_subsi3_insn"
cffb2a26 960 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 961 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
962 (match_operand:SI 2 "s_register_operand" "r,r")))]
cffb2a26 963 "TARGET_ARM"
e2348bcb 964 "@
87b22bf7 965 rsb%?\\t%0, %2, %1
966 #"
a0f94409 967 "TARGET_ARM
968 && GET_CODE (operands[1]) == CONST_INT
969 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 970 [(clobber (const_int 0))]
971 "
96f57e36 972 arm_split_constant (MINUS, SImode, curr_insn,
973 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 974 DONE;
cffb2a26 975 "
a0f94409 976 [(set_attr "length" "4,16")
977 (set_attr "predicable" "yes")]
978)
979
980(define_peephole2
981 [(match_scratch:SI 3 "r")
372575c7 982 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 983 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 984 (match_operand:SI 2 "arm_general_register_operand" "")))]
a0f94409 985 "TARGET_ARM
986 && !const_ok_for_arm (INTVAL (operands[1]))
987 && const_ok_for_arm (~INTVAL (operands[1]))"
988 [(set (match_dup 3) (match_dup 1))
989 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
990 ""
cffb2a26 991)
b11cae9e 992
f7fbdd4a 993(define_insn "*subsi3_compare0"
bd5b4116 994 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 995 (compare:CC_NOOV
996 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
997 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
998 (const_int 0)))
9c08d1fa 999 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1000 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1001 "TARGET_ARM"
e2348bcb 1002 "@
40dbec34 1003 sub%?s\\t%0, %1, %2
1004 rsb%?s\\t%0, %2, %1"
cffb2a26 1005 [(set_attr "conds" "set")]
1006)
9c08d1fa 1007
1008(define_insn "decscc"
cffb2a26 1009 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1010 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1011 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1012 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1013 "TARGET_ARM"
e2348bcb 1014 "@
215b30b3 1015 sub%d2\\t%0, %1, #1
1016 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1017 [(set_attr "conds" "use")
1018 (set_attr "length" "*,8")]
1019)
9c08d1fa 1020
604f3a0a 1021(define_expand "subsf3"
1022 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1023 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1024 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1025 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1026 "
a2cd141b 1027 if (TARGET_MAVERICK)
604f3a0a 1028 {
1029 if (!cirrus_fp_register (operands[1], SFmode))
1030 operands[1] = force_reg (SFmode, operands[1]);
1031 if (!cirrus_fp_register (operands[2], SFmode))
1032 operands[2] = force_reg (SFmode, operands[2]);
1033 }
1034")
1035
604f3a0a 1036(define_expand "subdf3"
1037 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1038 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1039 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1040 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1041 "
a2cd141b 1042 if (TARGET_MAVERICK)
604f3a0a 1043 {
1044 if (!cirrus_fp_register (operands[1], DFmode))
1045 operands[1] = force_reg (DFmode, operands[1]);
1046 if (!cirrus_fp_register (operands[2], DFmode))
1047 operands[2] = force_reg (DFmode, operands[2]);
1048 }
1049")
1050
b11cae9e 1051\f
1052;; Multiplication insns
1053
cffb2a26 1054(define_expand "mulsi3"
1055 [(set (match_operand:SI 0 "s_register_operand" "")
1056 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1057 (match_operand:SI 1 "s_register_operand" "")))]
1058 "TARGET_EITHER"
1059 ""
1060)
1061
9c08d1fa 1062;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1063(define_insn "*arm_mulsi3"
1064 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1065 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1066 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
cffb2a26 1067 "TARGET_ARM"
f7fbdd4a 1068 "mul%?\\t%0, %2, %1"
a2cd141b 1069 [(set_attr "insn" "mul")
0d66636f 1070 (set_attr "predicable" "yes")]
cffb2a26 1071)
1072
215b30b3 1073; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1074; 1 and 2; are the same, because reload will make operand 0 match
1075; operand 1 without realizing that this conflicts with operand 2. We fix
1076; this by adding another alternative to match this case, and then `reload'
1077; it ourselves. This alternative must come first.
cffb2a26 1078(define_insn "*thumb_mulsi3"
1079 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1080 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1081 (match_operand:SI 2 "register_operand" "l,l,l")))]
1082 "TARGET_THUMB"
1083 "*
1084 if (which_alternative < 2)
1085 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1086 else
1087 return \"mul\\t%0, %0, %2\";
1088 "
1089 [(set_attr "length" "4,4,2")
a2cd141b 1090 (set_attr "insn" "mul")]
cffb2a26 1091)
b11cae9e 1092
f7fbdd4a 1093(define_insn "*mulsi3_compare0"
bd5b4116 1094 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1095 (compare:CC_NOOV (mult:SI
1096 (match_operand:SI 2 "s_register_operand" "r,r")
1097 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1098 (const_int 0)))
1099 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1100 (mult:SI (match_dup 2) (match_dup 1)))]
f8e17552 1101 "TARGET_ARM && !arm_arch_xscale"
40dbec34 1102 "mul%?s\\t%0, %2, %1"
cffb2a26 1103 [(set_attr "conds" "set")
a2cd141b 1104 (set_attr "insn" "muls")]
cffb2a26 1105)
9c08d1fa 1106
f7fbdd4a 1107(define_insn "*mulsi_compare0_scratch"
bd5b4116 1108 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1109 (compare:CC_NOOV (mult:SI
1110 (match_operand:SI 2 "s_register_operand" "r,r")
1111 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1112 (const_int 0)))
1113 (clobber (match_scratch:SI 0 "=&r,&r"))]
f8e17552 1114 "TARGET_ARM && !arm_arch_xscale"
40dbec34 1115 "mul%?s\\t%0, %2, %1"
cffb2a26 1116 [(set_attr "conds" "set")
a2cd141b 1117 (set_attr "insn" "muls")]
cffb2a26 1118)
9c08d1fa 1119
b11cae9e 1120;; Unnamed templates to match MLA instruction.
1121
f7fbdd4a 1122(define_insn "*mulsi3addsi"
9c08d1fa 1123 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1124 (plus:SI
9c08d1fa 1125 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1126 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1127 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
cffb2a26 1128 "TARGET_ARM"
f7fbdd4a 1129 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1130 [(set_attr "insn" "mla")
0d66636f 1131 (set_attr "predicable" "yes")]
1132)
b11cae9e 1133
f7fbdd4a 1134(define_insn "*mulsi3addsi_compare0"
bd5b4116 1135 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1136 (compare:CC_NOOV
1137 (plus:SI (mult:SI
1138 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1139 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1140 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1141 (const_int 0)))
9c08d1fa 1142 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1143 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1144 (match_dup 3)))]
f8e17552 1145 "TARGET_ARM && !arm_arch_xscale"
40dbec34 1146 "mla%?s\\t%0, %2, %1, %3"
0d66636f 1147 [(set_attr "conds" "set")
a2cd141b 1148 (set_attr "insn" "mlas")]
0d66636f 1149)
9c08d1fa 1150
f7fbdd4a 1151(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1152 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1153 (compare:CC_NOOV
1154 (plus:SI (mult:SI
1155 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1156 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1157 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1158 (const_int 0)))
9c08d1fa 1159 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
f8e17552 1160 "TARGET_ARM && !arm_arch_xscale"
40dbec34 1161 "mla%?s\\t%0, %2, %1, %3"
cffb2a26 1162 [(set_attr "conds" "set")
a2cd141b 1163 (set_attr "insn" "mlas")]
cffb2a26 1164)
f7fbdd4a 1165
efee20da 1166;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1167
1168(define_insn "*mulsidi3adddi"
fe8dbf85 1169 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1170 (plus:DI
215b30b3 1171 (mult:DI
fe8dbf85 1172 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1173 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1174 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1175 "TARGET_ARM && arm_arch3m"
fe8dbf85 1176 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1177 [(set_attr "insn" "smlal")
0d66636f 1178 (set_attr "predicable" "yes")]
1179)
82b85d08 1180
f7fbdd4a 1181(define_insn "mulsidi3"
1182 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1183 (mult:DI
1184 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1185 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1186 "TARGET_ARM && arm_arch3m"
97499065 1187 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1188 [(set_attr "insn" "smull")
0d66636f 1189 (set_attr "predicable" "yes")]
1190)
f7fbdd4a 1191
1192(define_insn "umulsidi3"
1193 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1194 (mult:DI
1195 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1196 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1197 "TARGET_ARM && arm_arch3m"
97499065 1198 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1199 [(set_attr "insn" "umull")
0d66636f 1200 (set_attr "predicable" "yes")]
1201)
b11cae9e 1202
efee20da 1203;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1204
1205(define_insn "*umulsidi3adddi"
8ead09f9 1206 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1207 (plus:DI
215b30b3 1208 (mult:DI
fe8dbf85 1209 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1210 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1211 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1212 "TARGET_ARM && arm_arch3m"
fe8dbf85 1213 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1214 [(set_attr "insn" "umlal")
0d66636f 1215 (set_attr "predicable" "yes")]
1216)
82b85d08 1217
f082f1c4 1218(define_insn "smulsi3_highpart"
1219 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1220 (truncate:SI
1221 (lshiftrt:DI
215b30b3 1222 (mult:DI
1223 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1224 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1225 (const_int 32))))
1226 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1227 "TARGET_ARM && arm_arch3m"
f082f1c4 1228 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1229 [(set_attr "insn" "smull")
0d66636f 1230 (set_attr "predicable" "yes")]
cffb2a26 1231)
f082f1c4 1232
1233(define_insn "umulsi3_highpart"
1234 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1235 (truncate:SI
1236 (lshiftrt:DI
215b30b3 1237 (mult:DI
1238 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1239 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1240 (const_int 32))))
1241 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1242 "TARGET_ARM && arm_arch3m"
f082f1c4 1243 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1244 [(set_attr "insn" "umull")
0d66636f 1245 (set_attr "predicable" "yes")]
cffb2a26 1246)
f082f1c4 1247
331beb1a 1248(define_insn "mulhisi3"
1249 [(set (match_operand:SI 0 "s_register_operand" "=r")
1250 (mult:SI (sign_extend:SI
1251 (match_operand:HI 1 "s_register_operand" "%r"))
1252 (sign_extend:SI
1253 (match_operand:HI 2 "s_register_operand" "r"))))]
fec538d9 1254 "TARGET_ARM && arm_arch5e"
61a2d04c 1255 "smulbb%?\\t%0, %1, %2"
a2cd141b 1256 [(set_attr "insn" "smulxy")
fec538d9 1257 (set_attr "predicable" "yes")]
1258)
1259
1260(define_insn "*mulhisi3tb"
1261 [(set (match_operand:SI 0 "s_register_operand" "=r")
1262 (mult:SI (ashiftrt:SI
1263 (match_operand:SI 1 "s_register_operand" "r")
1264 (const_int 16))
1265 (sign_extend:SI
1266 (match_operand:HI 2 "s_register_operand" "r"))))]
1267 "TARGET_ARM && arm_arch5e"
1268 "smultb%?\\t%0, %1, %2"
a2cd141b 1269 [(set_attr "insn" "smulxy")
fec538d9 1270 (set_attr "predicable" "yes")]
1271)
1272
1273(define_insn "*mulhisi3bt"
1274 [(set (match_operand:SI 0 "s_register_operand" "=r")
1275 (mult:SI (sign_extend:SI
1276 (match_operand:HI 1 "s_register_operand" "r"))
1277 (ashiftrt:SI
1278 (match_operand:SI 2 "s_register_operand" "r")
1279 (const_int 16))))]
1280 "TARGET_ARM && arm_arch5e"
1281 "smulbt%?\\t%0, %1, %2"
a2cd141b 1282 [(set_attr "insn" "smulxy")
fec538d9 1283 (set_attr "predicable" "yes")]
1284)
1285
1286(define_insn "*mulhisi3tt"
1287 [(set (match_operand:SI 0 "s_register_operand" "=r")
1288 (mult:SI (ashiftrt:SI
1289 (match_operand:SI 1 "s_register_operand" "r")
1290 (const_int 16))
1291 (ashiftrt:SI
1292 (match_operand:SI 2 "s_register_operand" "r")
1293 (const_int 16))))]
1294 "TARGET_ARM && arm_arch5e"
1295 "smultt%?\\t%0, %1, %2"
a2cd141b 1296 [(set_attr "insn" "smulxy")
fec538d9 1297 (set_attr "predicable" "yes")]
331beb1a 1298)
1299
1300(define_insn "*mulhisi3addsi"
1301 [(set (match_operand:SI 0 "s_register_operand" "=r")
1302 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1303 (mult:SI (sign_extend:SI
1304 (match_operand:HI 2 "s_register_operand" "%r"))
1305 (sign_extend:SI
1306 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1307 "TARGET_ARM && arm_arch5e"
61a2d04c 1308 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1309 [(set_attr "insn" "smlaxy")
fec538d9 1310 (set_attr "predicable" "yes")]
331beb1a 1311)
1312
1313(define_insn "*mulhidi3adddi"
1314 [(set (match_operand:DI 0 "s_register_operand" "=r")
1315 (plus:DI
1316 (match_operand:DI 1 "s_register_operand" "0")
1317 (mult:DI (sign_extend:DI
1318 (match_operand:HI 2 "s_register_operand" "%r"))
1319 (sign_extend:DI
1320 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1321 "TARGET_ARM && arm_arch5e"
331beb1a 1322 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1323 [(set_attr "insn" "smlalxy")
fec538d9 1324 (set_attr "predicable" "yes")])
331beb1a 1325
604f3a0a 1326(define_expand "mulsf3"
1327 [(set (match_operand:SF 0 "s_register_operand" "")
1328 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1329 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1330 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1331 "
a2cd141b 1332 if (TARGET_MAVERICK
604f3a0a 1333 && !cirrus_fp_register (operands[2], SFmode))
1334 operands[2] = force_reg (SFmode, operands[2]);
1335")
1336
604f3a0a 1337(define_expand "muldf3"
1338 [(set (match_operand:DF 0 "s_register_operand" "")
1339 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1340 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1341 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1342 "
a2cd141b 1343 if (TARGET_MAVERICK
604f3a0a 1344 && !cirrus_fp_register (operands[2], DFmode))
1345 operands[2] = force_reg (DFmode, operands[2]);
1346")
b11cae9e 1347\f
1348;; Division insns
1349
7db9af5d 1350(define_expand "divsf3"
1351 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1352 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1353 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1354 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1355 "")
9c08d1fa 1356
7db9af5d 1357(define_expand "divdf3"
1358 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1359 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1360 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1361 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1362 "")
b11cae9e 1363\f
1364;; Modulo insns
1365
7db9af5d 1366(define_expand "modsf3"
1367 [(set (match_operand:SF 0 "s_register_operand" "")
1368 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1369 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1370 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1371 "")
9c08d1fa 1372
7db9af5d 1373(define_expand "moddf3"
1374 [(set (match_operand:DF 0 "s_register_operand" "")
1375 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1376 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1377 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1378 "")
b11cae9e 1379\f
1380;; Boolean and,ior,xor insns
1381
f6ebffac 1382;; Split up double word logical operations
1383
1384;; Split up simple DImode logical operations. Simply perform the logical
1385;; operation on the upper and lower halves of the registers.
1386(define_split
1387 [(set (match_operand:DI 0 "s_register_operand" "")
1388 (match_operator:DI 6 "logical_binary_operator"
1389 [(match_operand:DI 1 "s_register_operand" "")
1390 (match_operand:DI 2 "s_register_operand" "")]))]
755eb2b4 1391 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1392 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1393 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1394 "
215b30b3 1395 {
1396 operands[3] = gen_highpart (SImode, operands[0]);
1397 operands[0] = gen_lowpart (SImode, operands[0]);
1398 operands[4] = gen_highpart (SImode, operands[1]);
1399 operands[1] = gen_lowpart (SImode, operands[1]);
1400 operands[5] = gen_highpart (SImode, operands[2]);
1401 operands[2] = gen_lowpart (SImode, operands[2]);
1402 }"
1403)
f6ebffac 1404
f6ebffac 1405(define_split
1406 [(set (match_operand:DI 0 "s_register_operand" "")
1407 (match_operator:DI 6 "logical_binary_operator"
1408 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1409 (match_operand:DI 1 "s_register_operand" "")]))]
cffb2a26 1410 "TARGET_ARM && reload_completed"
f6ebffac 1411 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1412 (set (match_dup 3) (match_op_dup:SI 6
1413 [(ashiftrt:SI (match_dup 2) (const_int 31))
1414 (match_dup 4)]))]
1415 "
215b30b3 1416 {
1417 operands[3] = gen_highpart (SImode, operands[0]);
1418 operands[0] = gen_lowpart (SImode, operands[0]);
1419 operands[4] = gen_highpart (SImode, operands[1]);
1420 operands[1] = gen_lowpart (SImode, operands[1]);
1421 operands[5] = gen_highpart (SImode, operands[2]);
1422 operands[2] = gen_lowpart (SImode, operands[2]);
1423 }"
1424)
f6ebffac 1425
f6ebffac 1426;; The zero extend of operand 2 means we can just copy the high part of
1427;; operand1 into operand0.
1428(define_split
1429 [(set (match_operand:DI 0 "s_register_operand" "")
1430 (ior:DI
1431 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1432 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1433 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1434 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1435 (set (match_dup 3) (match_dup 4))]
1436 "
215b30b3 1437 {
1438 operands[4] = gen_highpart (SImode, operands[1]);
1439 operands[3] = gen_highpart (SImode, operands[0]);
1440 operands[0] = gen_lowpart (SImode, operands[0]);
1441 operands[1] = gen_lowpart (SImode, operands[1]);
1442 }"
1443)
f6ebffac 1444
1445;; The zero extend of operand 2 means we can just copy the high part of
1446;; operand1 into operand0.
1447(define_split
1448 [(set (match_operand:DI 0 "s_register_operand" "")
1449 (xor:DI
1450 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1451 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1452 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1453 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1454 (set (match_dup 3) (match_dup 4))]
1455 "
215b30b3 1456 {
1457 operands[4] = gen_highpart (SImode, operands[1]);
1458 operands[3] = gen_highpart (SImode, operands[0]);
1459 operands[0] = gen_lowpart (SImode, operands[0]);
1460 operands[1] = gen_lowpart (SImode, operands[1]);
1461 }"
1462)
f6ebffac 1463
b11cae9e 1464(define_insn "anddi3"
cffb2a26 1465 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1466 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1467 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 1468 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 1469 "#"
215b30b3 1470 [(set_attr "length" "8")]
1471)
b11cae9e 1472
a0f94409 1473(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1474 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1475 (and:DI (zero_extend:DI
1476 (match_operand:SI 2 "s_register_operand" "r,r"))
1477 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 1478 "TARGET_ARM"
f6ebffac 1479 "#"
a0f94409 1480 "TARGET_ARM && reload_completed"
1481 ; The zero extend of operand 2 clears the high word of the output
1482 ; operand.
1483 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1484 (set (match_dup 3) (const_int 0))]
1485 "
1486 {
1487 operands[3] = gen_highpart (SImode, operands[0]);
1488 operands[0] = gen_lowpart (SImode, operands[0]);
1489 operands[1] = gen_lowpart (SImode, operands[1]);
1490 }"
215b30b3 1491 [(set_attr "length" "8")]
1492)
b11cae9e 1493
f7fbdd4a 1494(define_insn "*anddi_sesdi_di"
cffb2a26 1495 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1496 (and:DI (sign_extend:DI
1497 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1498 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1499 "TARGET_ARM"
f6ebffac 1500 "#"
cffb2a26 1501 [(set_attr "length" "8")]
1502)
b11cae9e 1503
87b22bf7 1504(define_expand "andsi3"
cffb2a26 1505 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1506 (and:SI (match_operand:SI 1 "s_register_operand" "")
1507 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1508 "TARGET_EITHER"
87b22bf7 1509 "
cffb2a26 1510 if (TARGET_ARM)
87b22bf7 1511 {
cffb2a26 1512 if (GET_CODE (operands[2]) == CONST_INT)
1513 {
96f57e36 1514 arm_split_constant (AND, SImode, NULL_RTX,
1515 INTVAL (operands[2]), operands[0],
cffb2a26 1516 operands[1],
935d87ee 1517 (no_new_pseudos
cffb2a26 1518 ? 0 : preserve_subexpressions_p ()));
1519 DONE;
1520 }
87b22bf7 1521 }
cffb2a26 1522 else /* TARGET_THUMB */
1523 {
1524 if (GET_CODE (operands[2]) != CONST_INT)
1525 operands[2] = force_reg (SImode, operands[2]);
1526 else
1527 {
1528 int i;
1529
215b30b3 1530 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1531 {
215b30b3 1532 operands[2] = force_reg (SImode,
1533 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1534
1535 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1536
1537 DONE;
1538 }
87b22bf7 1539
cffb2a26 1540 for (i = 9; i <= 31; i++)
1541 {
1542 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1543 {
1544 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1545 const0_rtx));
1546 DONE;
1547 }
215b30b3 1548 else if ((((HOST_WIDE_INT) 1) << i) - 1
1549 == ~INTVAL (operands[2]))
cffb2a26 1550 {
1551 rtx shift = GEN_INT (i);
1552 rtx reg = gen_reg_rtx (SImode);
1553
1554 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1555 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1556
1557 DONE;
1558 }
1559 }
1560
1561 operands[2] = force_reg (SImode, operands[2]);
1562 }
215b30b3 1563 }
1564 "
cffb2a26 1565)
1566
a0f94409 1567(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1568 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1569 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1570 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
cffb2a26 1571 "TARGET_ARM"
5565501b 1572 "@
1573 and%?\\t%0, %1, %2
87b22bf7 1574 bic%?\\t%0, %1, #%B2
1575 #"
a0f94409 1576 "TARGET_ARM
1577 && GET_CODE (operands[2]) == CONST_INT
1578 && !(const_ok_for_arm (INTVAL (operands[2]))
1579 || const_ok_for_arm (~INTVAL (operands[2])))"
1580 [(clobber (const_int 0))]
1581 "
96f57e36 1582 arm_split_constant (AND, SImode, curr_insn,
1583 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1584 DONE;
1585 "
0d66636f 1586 [(set_attr "length" "4,4,16")
1587 (set_attr "predicable" "yes")]
cffb2a26 1588)
1589
1590(define_insn "*thumb_andsi3_insn"
1591 [(set (match_operand:SI 0 "register_operand" "=l")
1592 (and:SI (match_operand:SI 1 "register_operand" "%0")
1593 (match_operand:SI 2 "register_operand" "l")))]
1594 "TARGET_THUMB"
1595 "and\\t%0, %0, %2"
1596 [(set_attr "length" "2")]
1597)
87b22bf7 1598
f7fbdd4a 1599(define_insn "*andsi3_compare0"
bd5b4116 1600 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1601 (compare:CC_NOOV
1602 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1603 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1604 (const_int 0)))
cffb2a26 1605 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1606 (and:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1607 "TARGET_ARM"
5565501b 1608 "@
1609 and%?s\\t%0, %1, %2
1610 bic%?s\\t%0, %1, #%B2"
cffb2a26 1611 [(set_attr "conds" "set")]
1612)
9c08d1fa 1613
f7fbdd4a 1614(define_insn "*andsi3_compare0_scratch"
bd5b4116 1615 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1616 (compare:CC_NOOV
1617 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1618 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1619 (const_int 0)))
dd193d7c 1620 (clobber (match_scratch:SI 2 "=X,r"))]
cffb2a26 1621 "TARGET_ARM"
5565501b 1622 "@
1623 tst%?\\t%0, %1
dd193d7c 1624 bic%?s\\t%2, %0, #%B1"
0d66636f 1625 [(set_attr "conds" "set")]
1626)
9c08d1fa 1627
f7fbdd4a 1628(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 1629 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1630 (compare:CC_NOOV (zero_extract:SI
1631 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 1632 (match_operand 1 "const_int_operand" "n")
1633 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 1634 (const_int 0)))]
cffb2a26 1635 "TARGET_ARM
1636 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1637 && INTVAL (operands[1]) > 0
1638 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1639 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 1640 "*
5c49a439 1641 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1642 << INTVAL (operands[2]));
40dbec34 1643 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 1644 return \"\";
0d66636f 1645 "
1646 [(set_attr "conds" "set")]
1647)
9c08d1fa 1648
f4462328 1649(define_insn_and_split "*ne_zeroextractsi"
c4034607 1650 [(set (match_operand:SI 0 "s_register_operand" "=r")
1651 (ne:SI (zero_extract:SI
1652 (match_operand:SI 1 "s_register_operand" "r")
1653 (match_operand:SI 2 "const_int_operand" "n")
1654 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 1655 (const_int 0)))
1656 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1657 "TARGET_ARM
1658 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1659 && INTVAL (operands[2]) > 0
1660 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1661 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 1662 "#"
1663 "TARGET_ARM
1664 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665 && INTVAL (operands[2]) > 0
1666 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1668 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1669 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1670 (const_int 0)))
1671 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1672 (set (match_dup 0)
1673 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1674 (match_dup 0) (const_int 1)))]
1675 "
1676 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1677 << INTVAL (operands[3]));
1678 "
1679 [(set_attr "conds" "clob")
1680 (set_attr "length" "8")]
1681)
1682
1683(define_insn_and_split "*ne_zeroextractsi_shifted"
1684 [(set (match_operand:SI 0 "s_register_operand" "=r")
1685 (ne:SI (zero_extract:SI
1686 (match_operand:SI 1 "s_register_operand" "r")
1687 (match_operand:SI 2 "const_int_operand" "n")
1688 (const_int 0))
1689 (const_int 0)))
1690 (clobber (reg:CC CC_REGNUM))]
1691 "TARGET_ARM"
1692 "#"
1693 "TARGET_ARM"
1694 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1695 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1696 (const_int 0)))
1697 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1698 (set (match_dup 0)
1699 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1700 (match_dup 0) (const_int 1)))]
1701 "
1702 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1703 "
1704 [(set_attr "conds" "clob")
1705 (set_attr "length" "8")]
1706)
1707
1708(define_insn_and_split "*ite_ne_zeroextractsi"
1709 [(set (match_operand:SI 0 "s_register_operand" "=r")
1710 (if_then_else:SI (ne (zero_extract:SI
1711 (match_operand:SI 1 "s_register_operand" "r")
1712 (match_operand:SI 2 "const_int_operand" "n")
1713 (match_operand:SI 3 "const_int_operand" "n"))
1714 (const_int 0))
1715 (match_operand:SI 4 "arm_not_operand" "rIK")
1716 (const_int 0)))
1717 (clobber (reg:CC CC_REGNUM))]
1718 "TARGET_ARM
1719 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1720 && INTVAL (operands[2]) > 0
1721 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1722 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1723 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1724 "#"
1725 "TARGET_ARM
1726 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1727 && INTVAL (operands[2]) > 0
1728 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1729 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1730 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1731 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1732 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1733 (const_int 0)))
1734 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1735 (set (match_dup 0)
1736 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1737 (match_dup 0) (match_dup 4)))]
1738 "
c4034607 1739 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 1740 << INTVAL (operands[3]));
1741 "
1742 [(set_attr "conds" "clob")
1743 (set_attr "length" "8")]
1744)
1745
1746(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1747 [(set (match_operand:SI 0 "s_register_operand" "=r")
1748 (if_then_else:SI (ne (zero_extract:SI
1749 (match_operand:SI 1 "s_register_operand" "r")
1750 (match_operand:SI 2 "const_int_operand" "n")
1751 (const_int 0))
1752 (const_int 0))
1753 (match_operand:SI 3 "arm_not_operand" "rIK")
1754 (const_int 0)))
1755 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 1756 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1757 "#"
f8d7bf2f 1758 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1759 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1760 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1761 (const_int 0)))
1762 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1763 (set (match_dup 0)
1764 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1765 (match_dup 0) (match_dup 3)))]
1766 "
1767 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 1768 "
1769 [(set_attr "conds" "clob")
215b30b3 1770 (set_attr "length" "8")]
1771)
9c08d1fa 1772
58d6528b 1773(define_split
1774 [(set (match_operand:SI 0 "s_register_operand" "")
1775 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1776 (match_operand:SI 2 "const_int_operand" "")
1777 (match_operand:SI 3 "const_int_operand" "")))
1778 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1779 "TARGET_THUMB"
1780 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1781 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1782 "{
1783 HOST_WIDE_INT temp = INTVAL (operands[2]);
1784
1785 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1786 operands[3] = GEN_INT (32 - temp);
1787 }"
1788)
1789
d7863cfe 1790(define_split
1791 [(set (match_operand:SI 0 "s_register_operand" "")
1792 (match_operator:SI 1 "shiftable_operator"
1793 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1794 (match_operand:SI 3 "const_int_operand" "")
1795 (match_operand:SI 4 "const_int_operand" ""))
1796 (match_operand:SI 5 "s_register_operand" "")]))
1797 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1798 "TARGET_ARM"
1799 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1800 (set (match_dup 0)
1801 (match_op_dup 1
1802 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1803 (match_dup 5)]))]
1804 "{
1805 HOST_WIDE_INT temp = INTVAL (operands[3]);
1806
1807 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1808 operands[4] = GEN_INT (32 - temp);
1809 }"
1810)
1811
58d6528b 1812(define_split
1813 [(set (match_operand:SI 0 "s_register_operand" "")
1814 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1815 (match_operand:SI 2 "const_int_operand" "")
1816 (match_operand:SI 3 "const_int_operand" "")))]
1817 "TARGET_THUMB"
1818 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1819 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1820 "{
1821 HOST_WIDE_INT temp = INTVAL (operands[2]);
1822
1823 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1824 operands[3] = GEN_INT (32 - temp);
1825 }"
1826)
1827
d7863cfe 1828(define_split
1829 [(set (match_operand:SI 0 "s_register_operand" "")
1830 (match_operator:SI 1 "shiftable_operator"
1831 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1832 (match_operand:SI 3 "const_int_operand" "")
1833 (match_operand:SI 4 "const_int_operand" ""))
1834 (match_operand:SI 5 "s_register_operand" "")]))
1835 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1836 "TARGET_ARM"
1837 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1838 (set (match_dup 0)
1839 (match_op_dup 1
1840 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1841 (match_dup 5)]))]
1842 "{
1843 HOST_WIDE_INT temp = INTVAL (operands[3]);
1844
1845 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1846 operands[4] = GEN_INT (32 - temp);
1847 }"
1848)
1849
a42059fd 1850;;; ??? This pattern is bogus. If operand3 has bits outside the range
1851;;; represented by the bitfield, then this will produce incorrect results.
1852;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 1853;;; which have a real bit-field insert instruction, the truncation happens
1854;;; in the bit-field insert instruction itself. Since arm does not have a
1855;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 1856;;; the value before we insert. This loses some of the advantage of having
1857;;; this insv pattern, so this pattern needs to be reevalutated.
1858
8a18b90c 1859(define_expand "insv"
1860 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1861 (match_operand:SI 1 "general_operand" "")
1862 (match_operand:SI 2 "general_operand" ""))
19335226 1863 (match_operand:SI 3 "reg_or_int_operand" ""))]
cffb2a26 1864 "TARGET_ARM"
8a18b90c 1865 "
215b30b3 1866 {
1867 int start_bit = INTVAL (operands[2]);
1868 int width = INTVAL (operands[1]);
1869 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1870 rtx target, subtarget;
1871
1872 target = operands[0];
1873 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1874 subreg as the final target. */
1875 if (GET_CODE (target) == SUBREG)
1876 {
1877 subtarget = gen_reg_rtx (SImode);
1878 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1879 < GET_MODE_SIZE (SImode))
1880 target = SUBREG_REG (target);
1881 }
1882 else
1883 subtarget = target;
8a18b90c 1884
215b30b3 1885 if (GET_CODE (operands[3]) == CONST_INT)
1886 {
1887 /* Since we are inserting a known constant, we may be able to
1888 reduce the number of bits that we have to clear so that
1889 the mask becomes simple. */
1890 /* ??? This code does not check to see if the new mask is actually
1891 simpler. It may not be. */
1892 rtx op1 = gen_reg_rtx (SImode);
1893 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1894 start of this pattern. */
1895 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1896 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1897
1898 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1899 emit_insn (gen_iorsi3 (subtarget, op1,
1900 GEN_INT (op3_value << start_bit)));
1901 }
1902 else if (start_bit == 0
1903 && !(const_ok_for_arm (mask)
1904 || const_ok_for_arm (~mask)))
1905 {
1906 /* A Trick, since we are setting the bottom bits in the word,
1907 we can shift operand[3] up, operand[0] down, OR them together
1908 and rotate the result back again. This takes 3 insns, and
5910bb95 1909 the third might be mergeable into another op. */
215b30b3 1910 /* The shift up copes with the possibility that operand[3] is
1911 wider than the bitfield. */
1912 rtx op0 = gen_reg_rtx (SImode);
1913 rtx op1 = gen_reg_rtx (SImode);
1914
1915 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1916 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1917 emit_insn (gen_iorsi3 (op1, op1, op0));
1918 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1919 }
1920 else if ((width + start_bit == 32)
1921 && !(const_ok_for_arm (mask)
1922 || const_ok_for_arm (~mask)))
1923 {
1924 /* Similar trick, but slightly less efficient. */
8a18b90c 1925
215b30b3 1926 rtx op0 = gen_reg_rtx (SImode);
1927 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 1928
215b30b3 1929 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1930 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1931 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1932 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1933 }
1934 else
1935 {
1936 rtx op0 = GEN_INT (mask);
1937 rtx op1 = gen_reg_rtx (SImode);
1938 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 1939
215b30b3 1940 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1941 {
1942 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1943
215b30b3 1944 emit_insn (gen_movsi (tmp, op0));
1945 op0 = tmp;
1946 }
8a18b90c 1947
215b30b3 1948 /* Mask out any bits in operand[3] that are not needed. */
1949 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 1950
215b30b3 1951 if (GET_CODE (op0) == CONST_INT
1952 && (const_ok_for_arm (mask << start_bit)
1953 || const_ok_for_arm (~(mask << start_bit))))
1954 {
1955 op0 = GEN_INT (~(mask << start_bit));
1956 emit_insn (gen_andsi3 (op2, operands[0], op0));
1957 }
1958 else
1959 {
1960 if (GET_CODE (op0) == CONST_INT)
1961 {
1962 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1963
215b30b3 1964 emit_insn (gen_movsi (tmp, op0));
1965 op0 = tmp;
1966 }
1967
1968 if (start_bit != 0)
1969 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 1970
215b30b3 1971 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1972 }
8a18b90c 1973
215b30b3 1974 if (start_bit != 0)
1975 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 1976
215b30b3 1977 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1978 }
f082f1c4 1979
215b30b3 1980 if (subtarget != target)
1981 {
1982 /* If TARGET is still a SUBREG, then it must be wider than a word,
1983 so we must be careful only to set the subword we were asked to. */
1984 if (GET_CODE (target) == SUBREG)
1985 emit_move_insn (target, subtarget);
1986 else
1987 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1988 }
8a18b90c 1989
215b30b3 1990 DONE;
1991 }"
1992)
8a18b90c 1993
215b30b3 1994; constants for op 2 will never be given to these patterns.
a0f94409 1995(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 1996 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 1997 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1998 (match_operand:DI 2 "s_register_operand" "0,r")))]
cffb2a26 1999 "TARGET_ARM"
f6ebffac 2000 "#"
755eb2b4 2001 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2002 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2003 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2004 "
2005 {
2006 operands[3] = gen_highpart (SImode, operands[0]);
2007 operands[0] = gen_lowpart (SImode, operands[0]);
2008 operands[4] = gen_highpart (SImode, operands[1]);
2009 operands[1] = gen_lowpart (SImode, operands[1]);
2010 operands[5] = gen_highpart (SImode, operands[2]);
2011 operands[2] = gen_lowpart (SImode, operands[2]);
2012 }"
0d66636f 2013 [(set_attr "length" "8")
2014 (set_attr "predicable" "yes")]
2015)
9c08d1fa 2016
a0f94409 2017(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2018 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2019 (and:DI (not:DI (zero_extend:DI
2020 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2021 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2022 "TARGET_ARM"
e2348bcb 2023 "@
97499065 2024 bic%?\\t%Q0, %Q1, %2
f6ebffac 2025 #"
a0f94409 2026 ; (not (zero_extend ...)) allows us to just copy the high word from
2027 ; operand1 to operand0.
2028 "TARGET_ARM
2029 && reload_completed
2030 && operands[0] != operands[1]"
5a097f7d 2031 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2032 (set (match_dup 3) (match_dup 4))]
2033 "
2034 {
2035 operands[3] = gen_highpart (SImode, operands[0]);
2036 operands[0] = gen_lowpart (SImode, operands[0]);
2037 operands[4] = gen_highpart (SImode, operands[1]);
2038 operands[1] = gen_lowpart (SImode, operands[1]);
2039 }"
0d66636f 2040 [(set_attr "length" "4,8")
2041 (set_attr "predicable" "yes")]
2042)
9c08d1fa 2043
a0f94409 2044(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2045 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2046 (and:DI (not:DI (sign_extend:DI
2047 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2048 (match_operand:DI 1 "s_register_operand" "0,r")))]
cffb2a26 2049 "TARGET_ARM"
f6ebffac 2050 "#"
a0f94409 2051 "TARGET_ARM && reload_completed"
5a097f7d 2052 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2053 (set (match_dup 3) (and:SI (not:SI
2054 (ashiftrt:SI (match_dup 2) (const_int 31)))
2055 (match_dup 4)))]
2056 "
2057 {
2058 operands[3] = gen_highpart (SImode, operands[0]);
2059 operands[0] = gen_lowpart (SImode, operands[0]);
2060 operands[4] = gen_highpart (SImode, operands[1]);
2061 operands[1] = gen_lowpart (SImode, operands[1]);
2062 }"
0d66636f 2063 [(set_attr "length" "8")
2064 (set_attr "predicable" "yes")]
2065)
9c08d1fa 2066
8a18b90c 2067(define_insn "andsi_notsi_si"
9c08d1fa 2068 [(set (match_operand:SI 0 "s_register_operand" "=r")
2069 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2070 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2071 "TARGET_ARM"
0d66636f 2072 "bic%?\\t%0, %1, %2"
2073 [(set_attr "predicable" "yes")]
2074)
b11cae9e 2075
cffb2a26 2076(define_insn "bicsi3"
2077 [(set (match_operand:SI 0 "register_operand" "=l")
2078 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2079 (match_operand:SI 2 "register_operand" "0")))]
2080 "TARGET_THUMB"
2081 "bic\\t%0, %0, %1"
2082 [(set_attr "length" "2")]
2083)
2084
8a18b90c 2085(define_insn "andsi_not_shiftsi_si"
a2cd141b 2086 [(set (match_operand:SI 0 "s_register_operand" "=r")
2087 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2088 [(match_operand:SI 2 "s_register_operand" "r")
2089 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2090 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2091 "TARGET_ARM"
6c4c2133 2092 "bic%?\\t%0, %1, %2%S4"
344495ea 2093 [(set_attr "predicable" "yes")
331beb1a 2094 (set_attr "shift" "2")
a2cd141b 2095 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2096 (const_string "alu_shift")
2097 (const_string "alu_shift_reg")))]
6c4c2133 2098)
8a18b90c 2099
f7fbdd4a 2100(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2101 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2102 (compare:CC_NOOV
2103 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2104 (match_operand:SI 1 "s_register_operand" "r"))
2105 (const_int 0)))
9c08d1fa 2106 (set (match_operand:SI 0 "s_register_operand" "=r")
2107 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
cffb2a26 2108 "TARGET_ARM"
40dbec34 2109 "bic%?s\\t%0, %1, %2"
0d66636f 2110 [(set_attr "conds" "set")]
2111)
9c08d1fa 2112
f7fbdd4a 2113(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2114 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2115 (compare:CC_NOOV
2116 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2117 (match_operand:SI 1 "s_register_operand" "r"))
2118 (const_int 0)))
9c08d1fa 2119 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2120 "TARGET_ARM"
40dbec34 2121 "bic%?s\\t%0, %1, %2"
0d66636f 2122 [(set_attr "conds" "set")]
2123)
9c08d1fa 2124
2125(define_insn "iordi3"
cffb2a26 2126 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2127 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2128 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2129 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 2130 "#"
0d66636f 2131 [(set_attr "length" "8")
2132 (set_attr "predicable" "yes")]
cffb2a26 2133)
9c08d1fa 2134
f7fbdd4a 2135(define_insn "*iordi_zesidi_di"
9c08d1fa 2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137 (ior:DI (zero_extend:DI
2138 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2139 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2140 "TARGET_ARM"
e2348bcb 2141 "@
97499065 2142 orr%?\\t%Q0, %Q1, %2
f6ebffac 2143 #"
0d66636f 2144 [(set_attr "length" "4,8")
2145 (set_attr "predicable" "yes")]
cffb2a26 2146)
9c08d1fa 2147
f7fbdd4a 2148(define_insn "*iordi_sesidi_di"
9c08d1fa 2149 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2150 (ior:DI (sign_extend:DI
2151 (match_operand:SI 2 "s_register_operand" "r,r"))
2152 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2153 "TARGET_ARM"
f6ebffac 2154 "#"
0d66636f 2155 [(set_attr "length" "8")
2156 (set_attr "predicable" "yes")]
cffb2a26 2157)
9c08d1fa 2158
87b22bf7 2159(define_expand "iorsi3"
cffb2a26 2160 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2161 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2162 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2163 "TARGET_EITHER"
87b22bf7 2164 "
2165 if (GET_CODE (operands[2]) == CONST_INT)
2166 {
cffb2a26 2167 if (TARGET_ARM)
2168 {
96f57e36 2169 arm_split_constant (IOR, SImode, NULL_RTX,
2170 INTVAL (operands[2]), operands[0], operands[1],
935d87ee 2171 (no_new_pseudos
cffb2a26 2172 ? 0 : preserve_subexpressions_p ()));
2173 DONE;
2174 }
2175 else /* TARGET_THUMB */
2176 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2177 }
cffb2a26 2178 "
2179)
87b22bf7 2180
a0f94409 2181(define_insn_and_split "*arm_iorsi3"
cffb2a26 2182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2183 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
cffb2a26 2185 "TARGET_ARM"
87b22bf7 2186 "@
2187 orr%?\\t%0, %1, %2
2188 #"
a0f94409 2189 "TARGET_ARM
2190 && GET_CODE (operands[2]) == CONST_INT
2191 && !const_ok_for_arm (INTVAL (operands[2]))"
2192 [(clobber (const_int 0))]
2193 "
96f57e36 2194 arm_split_constant (IOR, SImode, curr_insn,
2195 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2196 DONE;
2197 "
0d66636f 2198 [(set_attr "length" "4,16")
2199 (set_attr "predicable" "yes")]
cffb2a26 2200)
2201
2202(define_insn "*thumb_iorsi3"
2203 [(set (match_operand:SI 0 "register_operand" "=l")
2204 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2205 (match_operand:SI 2 "register_operand" "l")))]
2206 "TARGET_THUMB"
2207 "orr\\t%0, %0, %2"
2208 [(set_attr "length" "2")]
2209)
9c08d1fa 2210
a0f94409 2211(define_peephole2
2212 [(match_scratch:SI 3 "r")
372575c7 2213 (set (match_operand:SI 0 "arm_general_register_operand" "")
2214 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2215 (match_operand:SI 2 "const_int_operand" "")))]
a0f94409 2216 "TARGET_ARM
2217 && !const_ok_for_arm (INTVAL (operands[2]))
2218 && const_ok_for_arm (~INTVAL (operands[2]))"
2219 [(set (match_dup 3) (match_dup 2))
2220 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2221 ""
215b30b3 2222)
a0f94409 2223
f7fbdd4a 2224(define_insn "*iorsi3_compare0"
bd5b4116 2225 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2226 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2228 (const_int 0)))
2229 (set (match_operand:SI 0 "s_register_operand" "=r")
2230 (ior:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2231 "TARGET_ARM"
40dbec34 2232 "orr%?s\\t%0, %1, %2"
cffb2a26 2233 [(set_attr "conds" "set")]
2234)
9c08d1fa 2235
f7fbdd4a 2236(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2237 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2238 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2240 (const_int 0)))
2241 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2242 "TARGET_ARM"
40dbec34 2243 "orr%?s\\t%0, %1, %2"
0d66636f 2244 [(set_attr "conds" "set")]
2245)
9c08d1fa 2246
2247(define_insn "xordi3"
cffb2a26 2248 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2249 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2250 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2251 "TARGET_ARM && !TARGET_IWMMXT"
f6ebffac 2252 "#"
0d66636f 2253 [(set_attr "length" "8")
2254 (set_attr "predicable" "yes")]
cffb2a26 2255)
9c08d1fa 2256
f7fbdd4a 2257(define_insn "*xordi_zesidi_di"
9c08d1fa 2258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259 (xor:DI (zero_extend:DI
2260 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2261 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2262 "TARGET_ARM"
e2348bcb 2263 "@
97499065 2264 eor%?\\t%Q0, %Q1, %2
f6ebffac 2265 #"
0d66636f 2266 [(set_attr "length" "4,8")
2267 (set_attr "predicable" "yes")]
cffb2a26 2268)
9c08d1fa 2269
f7fbdd4a 2270(define_insn "*xordi_sesidi_di"
9c08d1fa 2271 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272 (xor:DI (sign_extend:DI
2273 (match_operand:SI 2 "s_register_operand" "r,r"))
2274 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2275 "TARGET_ARM"
f6ebffac 2276 "#"
0d66636f 2277 [(set_attr "length" "8")
2278 (set_attr "predicable" "yes")]
cffb2a26 2279)
9c08d1fa 2280
cffb2a26 2281(define_expand "xorsi3"
2282 [(set (match_operand:SI 0 "s_register_operand" "")
2283 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2284 (match_operand:SI 2 "arm_rhs_operand" "")))]
2285 "TARGET_EITHER"
2286 "if (TARGET_THUMB)
2287 if (GET_CODE (operands[2]) == CONST_INT)
2288 operands[2] = force_reg (SImode, operands[2]);
2289 "
2290)
2291
2292(define_insn "*arm_xorsi3"
2293 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2294 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 2296 "TARGET_ARM"
2297 "eor%?\\t%0, %1, %2"
0d66636f 2298 [(set_attr "predicable" "yes")]
cffb2a26 2299)
2300
2301(define_insn "*thumb_xorsi3"
2302 [(set (match_operand:SI 0 "register_operand" "=l")
2303 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2304 (match_operand:SI 2 "register_operand" "l")))]
2305 "TARGET_THUMB"
2306 "eor\\t%0, %0, %2"
2307 [(set_attr "length" "2")]
2308)
9c08d1fa 2309
f7fbdd4a 2310(define_insn "*xorsi3_compare0"
bd5b4116 2311 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2312 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2314 (const_int 0)))
2315 (set (match_operand:SI 0 "s_register_operand" "=r")
2316 (xor:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2317 "TARGET_ARM"
40dbec34 2318 "eor%?s\\t%0, %1, %2"
0d66636f 2319 [(set_attr "conds" "set")]
2320)
9c08d1fa 2321
f7fbdd4a 2322(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2323 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2324 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2326 (const_int 0)))]
cffb2a26 2327 "TARGET_ARM"
40dbec34 2328 "teq%?\\t%0, %1"
cffb2a26 2329 [(set_attr "conds" "set")]
2330)
9c08d1fa 2331
215b30b3 2332; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2333; (NOT D) we can sometimes merge the final NOT into one of the following
2334; insns.
9c08d1fa 2335
2336(define_split
a058e94a 2337 [(set (match_operand:SI 0 "s_register_operand" "")
2338 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2339 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2340 (match_operand:SI 3 "arm_rhs_operand" "")))
2341 (clobber (match_operand:SI 4 "s_register_operand" ""))]
cffb2a26 2342 "TARGET_ARM"
9c08d1fa 2343 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344 (not:SI (match_dup 3))))
2345 (set (match_dup 0) (not:SI (match_dup 4)))]
2346 ""
2347)
2348
f7fbdd4a 2349(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2350 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
cffb2a26 2354 "TARGET_ARM"
40dbec34 2355 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2356 [(set_attr "length" "8")
2357 (set_attr "predicable" "yes")]
cffb2a26 2358)
9c08d1fa 2359
d7863cfe 2360(define_split
2361 [(set (match_operand:SI 0 "s_register_operand" "")
2362 (match_operator:SI 1 "logical_binary_operator"
2363 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2364 (match_operand:SI 3 "const_int_operand" "")
2365 (match_operand:SI 4 "const_int_operand" ""))
2366 (match_operator:SI 9 "logical_binary_operator"
2367 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2368 (match_operand:SI 6 "const_int_operand" ""))
2369 (match_operand:SI 7 "s_register_operand" "")])]))
2370 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2371 "TARGET_ARM
2372 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2373 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2374 [(set (match_dup 8)
2375 (match_op_dup 1
2376 [(ashift:SI (match_dup 2) (match_dup 4))
2377 (match_dup 5)]))
2378 (set (match_dup 0)
2379 (match_op_dup 1
2380 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2381 (match_dup 7)]))]
2382 "
2383 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2384")
2385
2386(define_split
2387 [(set (match_operand:SI 0 "s_register_operand" "")
2388 (match_operator:SI 1 "logical_binary_operator"
2389 [(match_operator:SI 9 "logical_binary_operator"
2390 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2391 (match_operand:SI 6 "const_int_operand" ""))
2392 (match_operand:SI 7 "s_register_operand" "")])
2393 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2394 (match_operand:SI 3 "const_int_operand" "")
2395 (match_operand:SI 4 "const_int_operand" ""))]))
2396 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2397 "TARGET_ARM
2398 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2399 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2400 [(set (match_dup 8)
2401 (match_op_dup 1
2402 [(ashift:SI (match_dup 2) (match_dup 4))
2403 (match_dup 5)]))
2404 (set (match_dup 0)
2405 (match_op_dup 1
2406 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2407 (match_dup 7)]))]
2408 "
2409 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2410")
2411
2412(define_split
2413 [(set (match_operand:SI 0 "s_register_operand" "")
2414 (match_operator:SI 1 "logical_binary_operator"
2415 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2416 (match_operand:SI 3 "const_int_operand" "")
2417 (match_operand:SI 4 "const_int_operand" ""))
2418 (match_operator:SI 9 "logical_binary_operator"
2419 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2420 (match_operand:SI 6 "const_int_operand" ""))
2421 (match_operand:SI 7 "s_register_operand" "")])]))
2422 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2423 "TARGET_ARM
2424 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2425 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2426 [(set (match_dup 8)
2427 (match_op_dup 1
2428 [(ashift:SI (match_dup 2) (match_dup 4))
2429 (match_dup 5)]))
2430 (set (match_dup 0)
2431 (match_op_dup 1
2432 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2433 (match_dup 7)]))]
2434 "
2435 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2436")
2437
2438(define_split
2439 [(set (match_operand:SI 0 "s_register_operand" "")
2440 (match_operator:SI 1 "logical_binary_operator"
2441 [(match_operator:SI 9 "logical_binary_operator"
2442 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2443 (match_operand:SI 6 "const_int_operand" ""))
2444 (match_operand:SI 7 "s_register_operand" "")])
2445 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2446 (match_operand:SI 3 "const_int_operand" "")
2447 (match_operand:SI 4 "const_int_operand" ""))]))
2448 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2449 "TARGET_ARM
2450 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2451 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2452 [(set (match_dup 8)
2453 (match_op_dup 1
2454 [(ashift:SI (match_dup 2) (match_dup 4))
2455 (match_dup 5)]))
2456 (set (match_dup 0)
2457 (match_op_dup 1
2458 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2459 (match_dup 7)]))]
2460 "
2461 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2462")
9c08d1fa 2463\f
2464
2465;; Minimum and maximum insns
2466
2467(define_insn "smaxsi3"
cffb2a26 2468 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2469 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2470 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2471 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2472 "TARGET_ARM"
e2348bcb 2473 "@
2474 cmp\\t%1, %2\;movlt\\t%0, %2
2475 cmp\\t%1, %2\;movge\\t%0, %1
2476 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2477 [(set_attr "conds" "clob")
2478 (set_attr "length" "8,8,12")]
2479)
9c08d1fa 2480
2481(define_insn "sminsi3"
2482 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2483 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2484 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2485 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2486 "TARGET_ARM"
e2348bcb 2487 "@
2488 cmp\\t%1, %2\;movge\\t%0, %2
2489 cmp\\t%1, %2\;movlt\\t%0, %1
2490 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 2491 [(set_attr "conds" "clob")
2492 (set_attr "length" "8,8,12")]
2493)
9c08d1fa 2494
2495(define_insn "umaxsi3"
2496 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2497 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2498 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2499 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2500 "TARGET_ARM"
e2348bcb 2501 "@
2502 cmp\\t%1, %2\;movcc\\t%0, %2
2503 cmp\\t%1, %2\;movcs\\t%0, %1
2504 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 2505 [(set_attr "conds" "clob")
2506 (set_attr "length" "8,8,12")]
2507)
9c08d1fa 2508
2509(define_insn "uminsi3"
2510 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2511 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2512 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2513 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2514 "TARGET_ARM"
e2348bcb 2515 "@
2516 cmp\\t%1, %2\;movcs\\t%0, %2
2517 cmp\\t%1, %2\;movcc\\t%0, %1
2518 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 2519 [(set_attr "conds" "clob")
2520 (set_attr "length" "8,8,12")]
2521)
9c08d1fa 2522
8a18b90c 2523(define_insn "*store_minmaxsi"
9c08d1fa 2524 [(set (match_operand:SI 0 "memory_operand" "=m")
2525 (match_operator:SI 3 "minmax_operator"
2526 [(match_operand:SI 1 "s_register_operand" "r")
2527 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 2528 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2529 "TARGET_ARM"
9c08d1fa 2530 "*
dc55b8a9 2531 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2532 operands[1], operands[2]);
e2348bcb 2533 output_asm_insn (\"cmp\\t%1, %2\", operands);
2534 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2535 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2536 return \"\";
0d66636f 2537 "
2538 [(set_attr "conds" "clob")
2539 (set_attr "length" "12")
2540 (set_attr "type" "store1")]
2541)
9c08d1fa 2542
8a18b90c 2543; Reject the frame pointer in operand[1], since reloading this after
2544; it has been eliminated can cause carnage.
f7fbdd4a 2545(define_insn "*minmax_arithsi"
9c08d1fa 2546 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2547 (match_operator:SI 4 "shiftable_operator"
2548 [(match_operator:SI 5 "minmax_operator"
2549 [(match_operand:SI 2 "s_register_operand" "r,r")
2550 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2551 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 2552 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2553 "TARGET_ARM
2554 && (GET_CODE (operands[1]) != REG
2555 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2556 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
9c08d1fa 2557 "*
0d66636f 2558 {
2559 enum rtx_code code = GET_CODE (operands[4]);
2560
dc55b8a9 2561 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2562 operands[2], operands[3]);
0d66636f 2563 output_asm_insn (\"cmp\\t%2, %3\", operands);
2564 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2565 if (which_alternative != 0 || operands[3] != const0_rtx
2566 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2567 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2568 return \"\";
215b30b3 2569 }"
0d66636f 2570 [(set_attr "conds" "clob")
2571 (set_attr "length" "12")]
2572)
9c08d1fa 2573
b11cae9e 2574\f
2575;; Shift and rotation insns
2576
a2cd141b 2577(define_expand "ashldi3"
2578 [(set (match_operand:DI 0 "s_register_operand" "")
2579 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2580 (match_operand:SI 2 "reg_or_int_operand" "")))]
2581 "TARGET_ARM"
2582 "
2583 if (GET_CODE (operands[2]) == CONST_INT)
2584 {
2585 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2586 {
2587 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2588 DONE;
2589 }
2590 /* Ideally we shouldn't fail here if we could know that operands[1]
2591 ends up already living in an iwmmxt register. Otherwise it's
2592 cheaper to have the alternate code being generated than moving
1d60d981 2593 values to iwmmxt regs and back. */
a2cd141b 2594 FAIL;
2595 }
2596 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2597 FAIL;
2598 "
2599)
2600
2601(define_insn "arm_ashldi3_1bit"
2602 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2603 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2604 (const_int 1)))
2605 (clobber (reg:CC CC_REGNUM))]
2606 "TARGET_ARM"
2607 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2608 [(set_attr "conds" "clob")
2609 (set_attr "length" "8")]
2610)
2611
87b22bf7 2612(define_expand "ashlsi3"
cffb2a26 2613 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2614 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2615 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2616 "TARGET_EITHER"
87b22bf7 2617 "
2618 if (GET_CODE (operands[2]) == CONST_INT
2619 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2620 {
2621 emit_insn (gen_movsi (operands[0], const0_rtx));
2622 DONE;
2623 }
cffb2a26 2624 "
2625)
2626
2627(define_insn "*thumb_ashlsi3"
2628 [(set (match_operand:SI 0 "register_operand" "=l,l")
2629 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2630 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2631 "TARGET_THUMB"
2632 "lsl\\t%0, %1, %2"
2633 [(set_attr "length" "2")]
2634)
b11cae9e 2635
a2cd141b 2636(define_expand "ashrdi3"
2637 [(set (match_operand:DI 0 "s_register_operand" "")
2638 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2639 (match_operand:SI 2 "reg_or_int_operand" "")))]
2640 "TARGET_ARM"
2641 "
2642 if (GET_CODE (operands[2]) == CONST_INT)
2643 {
2644 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2645 {
2646 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2647 DONE;
2648 }
2649 /* Ideally we shouldn't fail here if we could know that operands[1]
2650 ends up already living in an iwmmxt register. Otherwise it's
2651 cheaper to have the alternate code being generated than moving
1d60d981 2652 values to iwmmxt regs and back. */
a2cd141b 2653 FAIL;
2654 }
2655 else if (!TARGET_REALLY_IWMMXT)
2656 FAIL;
2657 "
2658)
2659
2660(define_insn "arm_ashrdi3_1bit"
2661 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2662 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2663 (const_int 1)))
2664 (clobber (reg:CC CC_REGNUM))]
2665 "TARGET_ARM"
2666 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2667 [(set_attr "conds" "clob")
2668 (set_attr "length" "8")]
2669)
2670
87b22bf7 2671(define_expand "ashrsi3"
cffb2a26 2672 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2673 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2674 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2675 "TARGET_EITHER"
87b22bf7 2676 "
2677 if (GET_CODE (operands[2]) == CONST_INT
2678 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2679 operands[2] = GEN_INT (31);
cffb2a26 2680 "
2681)
2682
2683(define_insn "*thumb_ashrsi3"
2684 [(set (match_operand:SI 0 "register_operand" "=l,l")
2685 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2686 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2687 "TARGET_THUMB"
2688 "asr\\t%0, %1, %2"
2689 [(set_attr "length" "2")]
2690)
b11cae9e 2691
a2cd141b 2692(define_expand "lshrdi3"
2693 [(set (match_operand:DI 0 "s_register_operand" "")
2694 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2695 (match_operand:SI 2 "reg_or_int_operand" "")))]
2696 "TARGET_ARM"
2697 "
2698 if (GET_CODE (operands[2]) == CONST_INT)
2699 {
2700 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2701 {
2702 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2703 DONE;
2704 }
2705 /* Ideally we shouldn't fail here if we could know that operands[1]
2706 ends up already living in an iwmmxt register. Otherwise it's
2707 cheaper to have the alternate code being generated than moving
1d60d981 2708 values to iwmmxt regs and back. */
a2cd141b 2709 FAIL;
2710 }
2711 else if (!TARGET_REALLY_IWMMXT)
2712 FAIL;
2713 "
2714)
2715
2716(define_insn "arm_lshrdi3_1bit"
2717 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2718 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2719 (const_int 1)))
2720 (clobber (reg:CC CC_REGNUM))]
2721 "TARGET_ARM"
2722 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2723 [(set_attr "conds" "clob")
2724 (set_attr "length" "8")]
2725)
2726
87b22bf7 2727(define_expand "lshrsi3"
cffb2a26 2728 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2729 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2730 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2731 "TARGET_EITHER"
87b22bf7 2732 "
2733 if (GET_CODE (operands[2]) == CONST_INT
2734 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2735 {
2736 emit_insn (gen_movsi (operands[0], const0_rtx));
2737 DONE;
2738 }
cffb2a26 2739 "
2740)
2741
2742(define_insn "*thumb_lshrsi3"
2743 [(set (match_operand:SI 0 "register_operand" "=l,l")
2744 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2745 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2746 "TARGET_THUMB"
2747 "lsr\\t%0, %1, %2"
2748 [(set_attr "length" "2")]
2749)
b11cae9e 2750
87b22bf7 2751(define_expand "rotlsi3"
cffb2a26 2752 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2753 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2754 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2755 "TARGET_ARM"
87b22bf7 2756 "
2757 if (GET_CODE (operands[2]) == CONST_INT)
2758 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2759 else
b11cae9e 2760 {
87b22bf7 2761 rtx reg = gen_reg_rtx (SImode);
2762 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2763 operands[2] = reg;
b11cae9e 2764 }
cffb2a26 2765 "
2766)
9c08d1fa 2767
87b22bf7 2768(define_expand "rotrsi3"
cffb2a26 2769 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2770 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2771 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2772 "TARGET_EITHER"
87b22bf7 2773 "
cffb2a26 2774 if (TARGET_ARM)
2775 {
2776 if (GET_CODE (operands[2]) == CONST_INT
2777 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2778 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2779 }
2780 else /* TARGET_THUMB */
2781 {
2782 if (GET_CODE (operands [2]) == CONST_INT)
2783 operands [2] = force_reg (SImode, operands[2]);
2784 }
2785 "
2786)
87b22bf7 2787
cffb2a26 2788(define_insn "*thumb_rotrsi3"
2789 [(set (match_operand:SI 0 "register_operand" "=l")
2790 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2791 (match_operand:SI 2 "register_operand" "l")))]
2792 "TARGET_THUMB"
2793 "ror\\t%0, %0, %2"
2794 [(set_attr "length" "2")]
2795)
2796
2797(define_insn "*arm_shiftsi3"
2798 [(set (match_operand:SI 0 "s_register_operand" "=r")
2799 (match_operator:SI 3 "shift_operator"
2800 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 2801 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
cffb2a26 2802 "TARGET_ARM"
6c4c2133 2803 "mov%?\\t%0, %1%S3"
344495ea 2804 [(set_attr "predicable" "yes")
331beb1a 2805 (set_attr "shift" "1")
a2cd141b 2806 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2807 (const_string "alu_shift")
2808 (const_string "alu_shift_reg")))]
6c4c2133 2809)
87b22bf7 2810
f7fbdd4a 2811(define_insn "*shiftsi3_compare0"
bd5b4116 2812 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2813 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2814 [(match_operand:SI 1 "s_register_operand" "r")
2815 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2816 (const_int 0)))
2817 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2818 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
cffb2a26 2819 "TARGET_ARM"
87b22bf7 2820 "mov%?s\\t%0, %1%S3"
344495ea 2821 [(set_attr "conds" "set")
331beb1a 2822 (set_attr "shift" "1")
a2cd141b 2823 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2824 (const_string "alu_shift")
2825 (const_string "alu_shift_reg")))]
0d66636f 2826)
9c08d1fa 2827
f7fbdd4a 2828(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 2829 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2830 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2831 [(match_operand:SI 1 "s_register_operand" "r")
2832 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2833 (const_int 0)))
2834 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2835 "TARGET_ARM"
87b22bf7 2836 "mov%?s\\t%0, %1%S3"
344495ea 2837 [(set_attr "conds" "set")
a2cd141b 2838 (set_attr "shift" "1")]
0d66636f 2839)
9c08d1fa 2840
f7fbdd4a 2841(define_insn "*notsi_shiftsi"
9c08d1fa 2842 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2843 (not:SI (match_operator:SI 3 "shift_operator"
2844 [(match_operand:SI 1 "s_register_operand" "r")
2845 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 2846 "TARGET_ARM"
6c4c2133 2847 "mvn%?\\t%0, %1%S3"
344495ea 2848 [(set_attr "predicable" "yes")
331beb1a 2849 (set_attr "shift" "1")
a2cd141b 2850 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2851 (const_string "alu_shift")
2852 (const_string "alu_shift_reg")))]
0d66636f 2853)
9c08d1fa 2854
f7fbdd4a 2855(define_insn "*notsi_shiftsi_compare0"
bd5b4116 2856 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2857 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2858 [(match_operand:SI 1 "s_register_operand" "r")
2859 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2860 (const_int 0)))
2861 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2862 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 2863 "TARGET_ARM"
87b22bf7 2864 "mvn%?s\\t%0, %1%S3"
344495ea 2865 [(set_attr "conds" "set")
331beb1a 2866 (set_attr "shift" "1")
a2cd141b 2867 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2868 (const_string "alu_shift")
2869 (const_string "alu_shift_reg")))]
0d66636f 2870)
9c08d1fa 2871
f7fbdd4a 2872(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 2873 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2874 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2875 [(match_operand:SI 1 "s_register_operand" "r")
2876 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2877 (const_int 0)))
2878 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2879 "TARGET_ARM"
87b22bf7 2880 "mvn%?s\\t%0, %1%S3"
344495ea 2881 [(set_attr "conds" "set")
331beb1a 2882 (set_attr "shift" "1")
a2cd141b 2883 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2884 (const_string "alu_shift")
2885 (const_string "alu_shift_reg")))]
0d66636f 2886)
9c08d1fa 2887
cffb2a26 2888;; We don't really have extzv, but defining this using shifts helps
2889;; to reduce register pressure later on.
2890
2891(define_expand "extzv"
2892 [(set (match_dup 4)
2893 (ashift:SI (match_operand:SI 1 "register_operand" "")
2894 (match_operand:SI 2 "const_int_operand" "")))
2895 (set (match_operand:SI 0 "register_operand" "")
2896 (lshiftrt:SI (match_dup 4)
215b30b3 2897 (match_operand:SI 3 "const_int_operand" "")))]
cffb2a26 2898 "TARGET_THUMB"
2899 "
2900 {
2901 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2902 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2903
2904 operands[3] = GEN_INT (rshift);
2905
2906 if (lshift == 0)
2907 {
2908 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2909 DONE;
2910 }
2911
2912 operands[2] = GEN_INT (lshift);
2913 operands[4] = gen_reg_rtx (SImode);
215b30b3 2914 }"
cffb2a26 2915)
2916
b11cae9e 2917\f
2918;; Unary arithmetic insns
2919
cffb2a26 2920(define_expand "negdi2"
2921 [(parallel
2922 [(set (match_operand:DI 0 "s_register_operand" "")
2923 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 2924 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 2925 "TARGET_EITHER"
2926 "
2927 if (TARGET_THUMB)
2928 {
2929 if (GET_CODE (operands[1]) != REG)
2930 operands[1] = force_reg (SImode, operands[1]);
2931 }
215b30b3 2932 "
cffb2a26 2933)
2934
2935;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2936;; The second alternative is to allow the common case of a *full* overlap.
2937(define_insn "*arm_negdi2"
2938 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2939 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 2940 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2941 "TARGET_ARM"
97499065 2942 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 2943 [(set_attr "conds" "clob")
2944 (set_attr "length" "8")]
2945)
b11cae9e 2946
cffb2a26 2947(define_insn "*thumb_negdi2"
2948 [(set (match_operand:DI 0 "register_operand" "=&l")
2949 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 2950 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2951 "TARGET_THUMB"
2952 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2953 [(set_attr "length" "6")]
2954)
2955
2956(define_expand "negsi2"
2957 [(set (match_operand:SI 0 "s_register_operand" "")
2958 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2959 "TARGET_EITHER"
b11cae9e 2960 ""
cffb2a26 2961)
2962
2963(define_insn "*arm_negsi2"
2964 [(set (match_operand:SI 0 "s_register_operand" "=r")
2965 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2966 "TARGET_ARM"
2967 "rsb%?\\t%0, %1, #0"
0d66636f 2968 [(set_attr "predicable" "yes")]
cffb2a26 2969)
2970
2971(define_insn "*thumb_negsi2"
2972 [(set (match_operand:SI 0 "register_operand" "=l")
2973 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2974 "TARGET_THUMB"
2975 "neg\\t%0, %1"
2976 [(set_attr "length" "2")]
2977)
b11cae9e 2978
604f3a0a 2979(define_expand "negsf2"
2980 [(set (match_operand:SF 0 "s_register_operand" "")
2981 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 2982 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
604f3a0a 2983 ""
2984)
2985
2986(define_expand "negdf2"
2987 [(set (match_operand:DF 0 "s_register_operand" "")
2988 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 2989 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
604f3a0a 2990 "")
2991
9c08d1fa 2992;; abssi2 doesn't really clobber the condition codes if a different register
2993;; is being set. To keep things simple, assume during rtl manipulations that
2994;; it does, but tell the final scan operator the truth. Similarly for
2995;; (neg (abs...))
2996
604f3a0a 2997(define_expand "abssi2"
2998 [(parallel
2999 [(set (match_operand:SI 0 "s_register_operand" "")
3000 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3001 (clobber (reg:CC CC_REGNUM))])]
3002 "TARGET_ARM"
3003 "")
3004
7d57ec45 3005(define_insn "*arm_abssi2"
722f9800 3006 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3007 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3008 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3009 "TARGET_ARM"
e2348bcb 3010 "@
3011 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3012 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3013 [(set_attr "conds" "clob,*")
331beb1a 3014 (set_attr "shift" "1")
0d66636f 3015 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3016 (set_attr "length" "8")]
3017)
9c08d1fa 3018
f7fbdd4a 3019(define_insn "*neg_abssi2"
9c08d1fa 3020 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3021 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3022 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3023 "TARGET_ARM"
e2348bcb 3024 "@
3025 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3026 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3027 [(set_attr "conds" "clob,*")
331beb1a 3028 (set_attr "shift" "1")
0d66636f 3029 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3030 (set_attr "length" "8")]
3031)
b11cae9e 3032
604f3a0a 3033(define_expand "abssf2"
3034 [(set (match_operand:SF 0 "s_register_operand" "")
3035 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3036 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3037 "")
3038
604f3a0a 3039(define_expand "absdf2"
3040 [(set (match_operand:DF 0 "s_register_operand" "")
3041 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3042 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3043 "")
3044
7db9af5d 3045(define_expand "sqrtsf2"
3046 [(set (match_operand:SF 0 "s_register_operand" "")
3047 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3048 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3049 "")
9c08d1fa 3050
7db9af5d 3051(define_expand "sqrtdf2"
3052 [(set (match_operand:DF 0 "s_register_operand" "")
3053 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3054 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3055 "")
9c08d1fa 3056
a0f94409 3057(define_insn_and_split "one_cmpldi2"
9c08d1fa 3058 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3059 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 3060 "TARGET_ARM"
f6ebffac 3061 "#"
a0f94409 3062 "TARGET_ARM && reload_completed"
3063 [(set (match_dup 0) (not:SI (match_dup 1)))
3064 (set (match_dup 2) (not:SI (match_dup 3)))]
3065 "
3066 {
3067 operands[2] = gen_highpart (SImode, operands[0]);
3068 operands[0] = gen_lowpart (SImode, operands[0]);
3069 operands[3] = gen_highpart (SImode, operands[1]);
3070 operands[1] = gen_lowpart (SImode, operands[1]);
3071 }"
0d66636f 3072 [(set_attr "length" "8")
3073 (set_attr "predicable" "yes")]
cffb2a26 3074)
b11cae9e 3075
cffb2a26 3076(define_expand "one_cmplsi2"
3077 [(set (match_operand:SI 0 "s_register_operand" "")
3078 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3079 "TARGET_EITHER"
b11cae9e 3080 ""
cffb2a26 3081)
3082
3083(define_insn "*arm_one_cmplsi2"
3084 [(set (match_operand:SI 0 "s_register_operand" "=r")
3085 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3086 "TARGET_ARM"
3087 "mvn%?\\t%0, %1"
0d66636f 3088 [(set_attr "predicable" "yes")]
cffb2a26 3089)
3090
3091(define_insn "*thumb_one_cmplsi2"
3092 [(set (match_operand:SI 0 "register_operand" "=l")
3093 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3094 "TARGET_THUMB"
3095 "mvn\\t%0, %1"
3096 [(set_attr "length" "2")]
3097)
9c08d1fa 3098
f7fbdd4a 3099(define_insn "*notsi_compare0"
bd5b4116 3100 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3101 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3102 (const_int 0)))
3103 (set (match_operand:SI 0 "s_register_operand" "=r")
3104 (not:SI (match_dup 1)))]
cffb2a26 3105 "TARGET_ARM"
40dbec34 3106 "mvn%?s\\t%0, %1"
cffb2a26 3107 [(set_attr "conds" "set")]
3108)
9c08d1fa 3109
f7fbdd4a 3110(define_insn "*notsi_compare0_scratch"
bd5b4116 3111 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3112 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3113 (const_int 0)))
3114 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3115 "TARGET_ARM"
40dbec34 3116 "mvn%?s\\t%0, %1"
cffb2a26 3117 [(set_attr "conds" "set")]
3118)
b11cae9e 3119\f
3120;; Fixed <--> Floating conversion insns
3121
604f3a0a 3122(define_expand "floatsisf2"
3123 [(set (match_operand:SF 0 "s_register_operand" "")
3124 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3125 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3126 "
a2cd141b 3127 if (TARGET_MAVERICK)
604f3a0a 3128 {
3129 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3130 DONE;
3131 }
3132")
3133
604f3a0a 3134(define_expand "floatsidf2"
3135 [(set (match_operand:DF 0 "s_register_operand" "")
3136 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3137 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3138 "
a2cd141b 3139 if (TARGET_MAVERICK)
604f3a0a 3140 {
3141 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3142 DONE;
3143 }
3144")
3145
604f3a0a 3146(define_expand "fix_truncsfsi2"
3147 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3148 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
a2cd141b 3149 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3150 "
a2cd141b 3151 if (TARGET_MAVERICK)
604f3a0a 3152 {
3153 if (!cirrus_fp_register (operands[0], SImode))
3154 operands[0] = force_reg (SImode, operands[0]);
3155 if (!cirrus_fp_register (operands[1], SFmode))
3156 operands[1] = force_reg (SFmode, operands[0]);
3157 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3158 DONE;
3159 }
3160")
3161
604f3a0a 3162(define_expand "fix_truncdfsi2"
3163 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3164 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a2cd141b 3165 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3166 "
a2cd141b 3167 if (TARGET_MAVERICK)
604f3a0a 3168 {
3169 if (!cirrus_fp_register (operands[1], DFmode))
3170 operands[1] = force_reg (DFmode, operands[0]);
3171 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3172 DONE;
3173 }
3174")
3175
f544c6d2 3176;; Truncation insns
b11cae9e 3177
604f3a0a 3178(define_expand "truncdfsf2"
3179 [(set (match_operand:SF 0 "s_register_operand" "")
3180 (float_truncate:SF
3181 (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3182 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3183 ""
3184)
b11cae9e 3185\f
9c08d1fa 3186;; Zero and sign extension instructions.
b11cae9e 3187
9c08d1fa 3188(define_insn "zero_extendsidi2"
3189 [(set (match_operand:DI 0 "s_register_operand" "=r")
3190 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3191 "TARGET_ARM"
9c08d1fa 3192 "*
0d66636f 3193 if (REGNO (operands[1])
3194 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3195 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3196 return \"mov%?\\t%R0, #0\";
3197 "
3198 [(set_attr "length" "8")
3199 (set_attr "predicable" "yes")]
3200)
9c08d1fa 3201
3202(define_insn "zero_extendqidi2"
cffb2a26 3203 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3204 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3205 "TARGET_ARM"
e2348bcb 3206 "@
97499065 3207 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3208 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3209 [(set_attr "length" "8")
0d66636f 3210 (set_attr "predicable" "yes")
a2cd141b 3211 (set_attr "type" "*,load_byte")
cffb2a26 3212 (set_attr "pool_range" "*,4092")
3213 (set_attr "neg_pool_range" "*,4084")]
3214)
9c08d1fa 3215
3216(define_insn "extendsidi2"
3217 [(set (match_operand:DI 0 "s_register_operand" "=r")
3218 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3219 "TARGET_ARM"
9c08d1fa 3220 "*
0d66636f 3221 if (REGNO (operands[1])
3222 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3223 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3224 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3225 "
3226 [(set_attr "length" "8")
331beb1a 3227 (set_attr "shift" "1")
0d66636f 3228 (set_attr "predicable" "yes")]
3229)
9c08d1fa 3230
3231(define_expand "zero_extendhisi2"
cffb2a26 3232 [(set (match_dup 2)
0d66636f 3233 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3234 (const_int 16)))
9c08d1fa 3235 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3236 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3237 "TARGET_EITHER"
9c08d1fa 3238 "
cffb2a26 3239 {
a2cd141b 3240 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3241 {
a2cd141b 3242 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3243 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3244 DONE;
cffb2a26 3245 }
cffb2a26 3246
c1a66faf 3247 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3248 {
3249 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3250 DONE;
3251 }
cffb2a26 3252
a2cd141b 3253 if (!s_register_operand (operands[1], HImode))
3254 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3255
a2cd141b 3256 if (arm_arch6)
3257 {
3258 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3259 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3260 DONE;
cffb2a26 3261 }
a2cd141b 3262
3263 operands[1] = gen_lowpart (SImode, operands[1]);
3264 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3265 }"
3266)
3267
3268(define_insn "*thumb_zero_extendhisi2"
a2cd141b 3269 [(set (match_operand:SI 0 "register_operand" "=l")
3270 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3271 "TARGET_THUMB && !arm_arch6"
cffb2a26 3272 "*
3273 rtx mem = XEXP (operands[1], 0);
3274
3275 if (GET_CODE (mem) == CONST)
3276 mem = XEXP (mem, 0);
3277
3278 if (GET_CODE (mem) == LABEL_REF)
3279 return \"ldr\\t%0, %1\";
3280
3281 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3282 {
cffb2a26 3283 rtx a = XEXP (mem, 0);
3284 rtx b = XEXP (mem, 1);
3285
3286 /* This can happen due to bugs in reload. */
3287 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3288 {
3289 rtx ops[2];
3290 ops[0] = operands[0];
3291 ops[1] = a;
3292
3293 output_asm_insn (\"mov %0, %1\", ops);
3294
3295 XEXP (mem, 0) = operands[0];
3296 }
3297
3298 else if ( GET_CODE (a) == LABEL_REF
3299 && GET_CODE (b) == CONST_INT)
3300 return \"ldr\\t%0, %1\";
25f7a26e 3301 }
cffb2a26 3302
3303 return \"ldrh\\t%0, %1\";
3304 "
3305 [(set_attr "length" "4")
a2cd141b 3306 (set_attr "type" "load_byte")
cffb2a26 3307 (set_attr "pool_range" "60")]
3308)
9c08d1fa 3309
a2cd141b 3310(define_insn "*thumb_zero_extendhisi2_v6"
3311 [(set (match_operand:SI 0 "register_operand" "=l,l")
3312 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3313 "TARGET_THUMB && arm_arch6"
3314 "*
3315 rtx mem;
3316
3317 if (which_alternative == 0)
3318 return \"uxth\\t%0, %1\";
3319
3320 mem = XEXP (operands[1], 0);
3321
3322 if (GET_CODE (mem) == CONST)
3323 mem = XEXP (mem, 0);
3324
3325 if (GET_CODE (mem) == LABEL_REF)
3326 return \"ldr\\t%0, %1\";
3327
3328 if (GET_CODE (mem) == PLUS)
3329 {
3330 rtx a = XEXP (mem, 0);
3331 rtx b = XEXP (mem, 1);
3332
3333 /* This can happen due to bugs in reload. */
3334 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3335 {
3336 rtx ops[2];
3337 ops[0] = operands[0];
3338 ops[1] = a;
3339
3340 output_asm_insn (\"mov %0, %1\", ops);
3341
3342 XEXP (mem, 0) = operands[0];
3343 }
3344
3345 else if ( GET_CODE (a) == LABEL_REF
3346 && GET_CODE (b) == CONST_INT)
3347 return \"ldr\\t%0, %1\";
3348 }
3349
3350 return \"ldrh\\t%0, %1\";
3351 "
3352 [(set_attr "length" "2,4")
3353 (set_attr "type" "alu_shift,load_byte")
3354 (set_attr "pool_range" "*,60")]
3355)
3356
cffb2a26 3357(define_insn "*arm_zero_extendhisi2"
a2cd141b 3358 [(set (match_operand:SI 0 "s_register_operand" "=r")
3359 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3360 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3361 "ldr%?h\\t%0, %1"
a2cd141b 3362 [(set_attr "type" "load_byte")
0d66636f 3363 (set_attr "predicable" "yes")
cffb2a26 3364 (set_attr "pool_range" "256")
3365 (set_attr "neg_pool_range" "244")]
3366)
f7fbdd4a 3367
a2cd141b 3368(define_insn "*arm_zero_extendhisi2_v6"
3369 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3370 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3371 "TARGET_ARM && arm_arch6"
3372 "@
3373 uxth%?\\t%0, %1
3374 ldr%?h\\t%0, %1"
3375 [(set_attr "type" "alu_shift,load_byte")
3376 (set_attr "predicable" "yes")
3377 (set_attr "pool_range" "*,256")
3378 (set_attr "neg_pool_range" "*,244")]
3379)
3380
3381(define_insn "*arm_zero_extendhisi2addsi"
3382 [(set (match_operand:SI 0 "s_register_operand" "=r")
3383 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3384 (match_operand:SI 2 "s_register_operand" "r")))]
3385 "TARGET_ARM && arm_arch6"
3386 "uxtah%?\\t%0, %2, %1"
3387 [(set_attr "type" "alu_shift")
3388 (set_attr "predicable" "yes")]
3389)
3390
206ee9a2 3391(define_split
3392 [(set (match_operand:SI 0 "s_register_operand" "")
3393 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3394 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3395 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3396 [(set (match_dup 2) (match_dup 1))
3397 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3398 "
cffb2a26 3399 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3400 FAIL;
215b30b3 3401 "
3402)
206ee9a2 3403
3404(define_split
3405 [(set (match_operand:SI 0 "s_register_operand" "")
3406 (match_operator:SI 3 "shiftable_operator"
3407 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3408 (match_operand:SI 4 "s_register_operand" "")]))
3409 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3410 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3411 [(set (match_dup 2) (match_dup 1))
3412 (set (match_dup 0)
3413 (match_op_dup 3
3414 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3415 "
cffb2a26 3416 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3417 FAIL;
215b30b3 3418 "
3419)
206ee9a2 3420
87b22bf7 3421(define_expand "zero_extendqisi2"
cffb2a26 3422 [(set (match_operand:SI 0 "s_register_operand" "")
3423 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3424 "TARGET_EITHER"
87b22bf7 3425 "
a2cd141b 3426 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 3427 {
cffb2a26 3428 if (TARGET_ARM)
3429 {
215b30b3 3430 emit_insn (gen_andsi3 (operands[0],
3431 gen_lowpart (SImode, operands[1]),
cffb2a26 3432 GEN_INT (255)));
3433 }
3434 else /* TARGET_THUMB */
3435 {
3436 rtx temp = gen_reg_rtx (SImode);
3437 rtx ops[3];
3438
3439 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3440 operands[1] = gen_lowpart (SImode, operands[1]);
3441
3442 ops[0] = temp;
3443 ops[1] = operands[1];
3444 ops[2] = GEN_INT (24);
3445
215b30b3 3446 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3447 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3448
3449 ops[0] = operands[0];
3450 ops[1] = temp;
3451 ops[2] = GEN_INT (24);
3452
215b30b3 3453 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3454 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3455 }
87b22bf7 3456 DONE;
3457 }
215b30b3 3458 "
3459)
9c08d1fa 3460
cffb2a26 3461(define_insn "*thumb_zero_extendqisi2"
a2cd141b 3462 [(set (match_operand:SI 0 "register_operand" "=l")
3463 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3464 "TARGET_THUMB && !arm_arch6"
cffb2a26 3465 "ldrb\\t%0, %1"
3466 [(set_attr "length" "2")
a2cd141b 3467 (set_attr "type" "load_byte")
cffb2a26 3468 (set_attr "pool_range" "32")]
3469)
3470
a2cd141b 3471(define_insn "*thumb_zero_extendqisi2_v6"
3472 [(set (match_operand:SI 0 "register_operand" "=l,l")
3473 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3474 "TARGET_THUMB && arm_arch6"
3475 "@
3476 uxtb\\t%0, %1
3477 ldrb\\t%0, %1"
3478 [(set_attr "length" "2,2")
3479 (set_attr "type" "alu_shift,load_byte")
3480 (set_attr "pool_range" "*,32")]
3481)
3482
cffb2a26 3483(define_insn "*arm_zero_extendqisi2"
a2cd141b 3484 [(set (match_operand:SI 0 "s_register_operand" "=r")
3485 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3486 "TARGET_ARM && !arm_arch6"
87b22bf7 3487 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3488 [(set_attr "type" "load_byte")
0d66636f 3489 (set_attr "predicable" "yes")
cffb2a26 3490 (set_attr "pool_range" "4096")
3491 (set_attr "neg_pool_range" "4084")]
3492)
87b22bf7 3493
a2cd141b 3494(define_insn "*arm_zero_extendqisi2_v6"
3495 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3496 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3497 "TARGET_ARM && arm_arch6"
3498 "@
3499 uxtb%?\\t%0, %1
3500 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3501 [(set_attr "type" "alu_shift,load_byte")
3502 (set_attr "predicable" "yes")
3503 (set_attr "pool_range" "*,4096")
3504 (set_attr "neg_pool_range" "*,4084")]
3505)
3506
3507(define_insn "*arm_zero_extendqisi2addsi"
3508 [(set (match_operand:SI 0 "s_register_operand" "=r")
3509 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3510 (match_operand:SI 2 "s_register_operand" "r")))]
3511 "TARGET_ARM && arm_arch6"
3512 "uxtab%?\\t%0, %2, %1"
3513 [(set_attr "predicable" "yes")
3514 (set_attr "type" "alu_shift")]
3515)
3516
87b22bf7 3517(define_split
3518 [(set (match_operand:SI 0 "s_register_operand" "")
3519 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3520 (clobber (match_operand:SI 2 "s_register_operand" ""))]
9e8503e6 3521 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 3522 [(set (match_dup 2) (match_dup 1))
3523 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 3524 ""
3525)
9c08d1fa 3526
f7fbdd4a 3527(define_insn "*compareqi_eq0"
bd5b4116 3528 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 3529 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 3530 (const_int 0)))]
cffb2a26 3531 "TARGET_ARM"
87b22bf7 3532 "tst\\t%0, #255"
cffb2a26 3533 [(set_attr "conds" "set")]
3534)
b11cae9e 3535
b11cae9e 3536(define_expand "extendhisi2"
c8f69309 3537 [(set (match_dup 2)
25f7a26e 3538 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 3539 (const_int 16)))
9c08d1fa 3540 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3541 (ashiftrt:SI (match_dup 2)
3542 (const_int 16)))]
cffb2a26 3543 "TARGET_EITHER"
b11cae9e 3544 "
cffb2a26 3545 {
a2cd141b 3546 if (GET_CODE (operands[1]) == MEM)
cffb2a26 3547 {
a2cd141b 3548 if (TARGET_THUMB)
3549 {
3550 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3551 DONE;
3552 }
3553 else if (arm_arch4)
3554 {
a2cd141b 3555 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3556 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3557 DONE;
3558 }
cffb2a26 3559 }
7bd8ccc9 3560
c1a66faf 3561 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 3562 {
3563 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3564 DONE;
3565 }
a2cd141b 3566
215b30b3 3567 if (!s_register_operand (operands[1], HImode))
cffb2a26 3568 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3569
a2cd141b 3570 if (arm_arch6)
cffb2a26 3571 {
a2cd141b 3572 if (TARGET_THUMB)
3573 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3574 else
3575 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3576 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3577
cffb2a26 3578 DONE;
3579 }
a2cd141b 3580
3581 operands[1] = gen_lowpart (SImode, operands[1]);
3582 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3583 }"
3584)
3585
a2cd141b 3586(define_insn "thumb_extendhisi2"
3587 [(set (match_operand:SI 0 "register_operand" "=l")
3588 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3589 (clobber (match_scratch:SI 2 "=&l"))]
3590 "TARGET_THUMB && !arm_arch6"
cffb2a26 3591 "*
3592 {
3593 rtx ops[4];
3594 rtx mem = XEXP (operands[1], 0);
3595
3596 /* This code used to try to use 'V', and fix the address only if it was
3597 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3598 range of QImode offsets, and offsettable_address_p does a QImode
3599 address check. */
3600
3601 if (GET_CODE (mem) == CONST)
3602 mem = XEXP (mem, 0);
3603
3604 if (GET_CODE (mem) == LABEL_REF)
3605 return \"ldr\\t%0, %1\";
3606
3607 if (GET_CODE (mem) == PLUS)
3608 {
3609 rtx a = XEXP (mem, 0);
3610 rtx b = XEXP (mem, 1);
3611
3612 if (GET_CODE (a) == LABEL_REF
3613 && GET_CODE (b) == CONST_INT)
3614 return \"ldr\\t%0, %1\";
3615
3616 if (GET_CODE (b) == REG)
3617 return \"ldrsh\\t%0, %1\";
3618
3619 ops[1] = a;
3620 ops[2] = b;
3621 }
3622 else
3623 {
3624 ops[1] = mem;
3625 ops[2] = const0_rtx;
3626 }
3627
3628 if (GET_CODE (ops[1]) != REG)
3629 {
3630 debug_rtx (ops[1]);
3631 abort ();
3632 }
3633
3634 ops[0] = operands[0];
3635 ops[3] = operands[2];
3636 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3637 return \"\";
3638 }"
3639 [(set_attr "length" "4")
a2cd141b 3640 (set_attr "type" "load_byte")
cffb2a26 3641 (set_attr "pool_range" "1020")]
3642)
25f7a26e 3643
a2cd141b 3644;; We used to have an early-clobber on the scratch register here.
3645;; However, there's a bug somewhere in reload which means that this
3646;; can be partially ignored during spill allocation if the memory
3647;; address also needs reloading; this causes an abort later on when
3648;; we try to verify the operands. Fortunately, we don't really need
3649;; the early-clobber: we can always use operand 0 if operand 2
3650;; overlaps the address.
3651(define_insn "*thumb_extendhisi2_insn_v6"
3652 [(set (match_operand:SI 0 "register_operand" "=l,l")
3653 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3654 (clobber (match_scratch:SI 2 "=X,l"))]
3655 "TARGET_THUMB && arm_arch6"
3656 "*
3657 {
3658 rtx ops[4];
3659 rtx mem;
3660
3661 if (which_alternative == 0)
3662 return \"sxth\\t%0, %1\";
3663
3664 mem = XEXP (operands[1], 0);
3665
3666 /* This code used to try to use 'V', and fix the address only if it was
3667 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3668 range of QImode offsets, and offsettable_address_p does a QImode
3669 address check. */
3670
3671 if (GET_CODE (mem) == CONST)
3672 mem = XEXP (mem, 0);
3673
3674 if (GET_CODE (mem) == LABEL_REF)
3675 return \"ldr\\t%0, %1\";
3676
3677 if (GET_CODE (mem) == PLUS)
3678 {
3679 rtx a = XEXP (mem, 0);
3680 rtx b = XEXP (mem, 1);
3681
3682 if (GET_CODE (a) == LABEL_REF
3683 && GET_CODE (b) == CONST_INT)
3684 return \"ldr\\t%0, %1\";
3685
3686 if (GET_CODE (b) == REG)
3687 return \"ldrsh\\t%0, %1\";
3688
3689 ops[1] = a;
3690 ops[2] = b;
3691 }
3692 else
3693 {
3694 ops[1] = mem;
3695 ops[2] = const0_rtx;
3696 }
3697
3698 if (GET_CODE (ops[1]) != REG)
3699 {
3700 debug_rtx (ops[1]);
3701 abort ();
3702 }
3703
3704 ops[0] = operands[0];
3705 if (reg_mentioned_p (operands[2], ops[1]))
3706 ops[3] = ops[0];
3707 else
3708 ops[3] = operands[2];
3709 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3710 return \"\";
3711 }"
3712 [(set_attr "length" "2,4")
3713 (set_attr "type" "alu_shift,load_byte")
3714 (set_attr "pool_range" "*,1020")]
3715)
3716
25f7a26e 3717(define_expand "extendhisi2_mem"
eab14235 3718 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 3719 (set (match_dup 3)
eab14235 3720 (zero_extend:SI (match_dup 7)))
25f7a26e 3721 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3722 (set (match_operand:SI 0 "" "")
3723 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 3724 "TARGET_ARM"
25f7a26e 3725 "
215b30b3 3726 {
3727 rtx mem1, mem2;
3728 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3729
3730 mem1 = gen_rtx_MEM (QImode, addr);
3731 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3732 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3733 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3734 operands[0] = gen_lowpart (SImode, operands[0]);
3735 operands[1] = mem1;
3736 operands[2] = gen_reg_rtx (SImode);
3737 operands[3] = gen_reg_rtx (SImode);
3738 operands[6] = gen_reg_rtx (SImode);
3739 operands[7] = mem2;
25f7a26e 3740
215b30b3 3741 if (BYTES_BIG_ENDIAN)
3742 {
3743 operands[4] = operands[2];
3744 operands[5] = operands[3];
3745 }
3746 else
3747 {
3748 operands[4] = operands[3];
3749 operands[5] = operands[2];
3750 }
3751 }"
3752)
b11cae9e 3753
a2cd141b 3754(define_insn "*arm_extendhisi2"
3755 [(set (match_operand:SI 0 "s_register_operand" "=r")
3756 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3757 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3758 "ldr%?sh\\t%0, %1"
a2cd141b 3759 [(set_attr "type" "load_byte")
0d66636f 3760 (set_attr "predicable" "yes")
cffb2a26 3761 (set_attr "pool_range" "256")
3762 (set_attr "neg_pool_range" "244")]
3763)
f7fbdd4a 3764
a2cd141b 3765(define_insn "*arm_extendhisi2_v6"
3766 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3767 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3768 "TARGET_ARM && arm_arch6"
3769 "@
3770 sxth%?\\t%0, %1
3771 ldr%?sh\\t%0, %1"
3772 [(set_attr "type" "alu_shift,load_byte")
3773 (set_attr "predicable" "yes")
3774 (set_attr "pool_range" "*,256")
3775 (set_attr "neg_pool_range" "*,244")]
3776)
3777
3778(define_insn "*arm_extendhisi2addsi"
3779 [(set (match_operand:SI 0 "s_register_operand" "=r")
3780 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3781 (match_operand:SI 2 "s_register_operand" "r")))]
3782 "TARGET_ARM && arm_arch6"
3783 "sxtah%?\\t%0, %2, %1"
3784)
3785
206ee9a2 3786(define_split
cffb2a26 3787 [(set (match_operand:SI 0 "s_register_operand" "")
206ee9a2 3788 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
cffb2a26 3789 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3790 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3791 [(set (match_dup 2) (match_dup 1))
3792 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3793 "
cffb2a26 3794 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
206ee9a2 3795 FAIL;
cffb2a26 3796 "
3797)
206ee9a2 3798
3799(define_split
cffb2a26 3800 [(set (match_operand:SI 0 "s_register_operand" "")
3801 (match_operator:SI 3 "shiftable_operator"
206ee9a2 3802 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
cffb2a26 3803 (match_operand:SI 4 "s_register_operand" "")]))
3804 (clobber (match_operand:SI 2 "s_register_operand" ""))]
215b30b3 3805 "TARGET_ARM && (!arm_arch4)"
206ee9a2 3806 [(set (match_dup 2) (match_dup 1))
3807 (set (match_dup 0)
3808 (match_op_dup 3
3809 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
cffb2a26 3810 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3811 FAIL;
206ee9a2 3812 "
cffb2a26 3813)
206ee9a2 3814
c8f69309 3815(define_expand "extendqihi2"
3816 [(set (match_dup 2)
f7fbdd4a 3817 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 3818 (const_int 24)))
9c08d1fa 3819 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 3820 (ashiftrt:SI (match_dup 2)
3821 (const_int 24)))]
cffb2a26 3822 "TARGET_ARM"
c8f69309 3823 "
215b30b3 3824 {
3825 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3826 {
3827 emit_insn (gen_rtx_SET (VOIDmode,
3828 operands[0],
3829 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3830 DONE;
3831 }
3832 if (!s_register_operand (operands[1], QImode))
3833 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3834 operands[0] = gen_lowpart (SImode, operands[0]);
3835 operands[1] = gen_lowpart (SImode, operands[1]);
3836 operands[2] = gen_reg_rtx (SImode);
3837 }"
3838)
f7fbdd4a 3839
3840(define_insn "*extendqihi_insn"
b4e8a300 3841 [(set (match_operand:HI 0 "s_register_operand" "=r")
3842 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
cffb2a26 3843 "TARGET_ARM && arm_arch4"
b4e8a300 3844 "ldr%?sb\\t%0, %1"
a2cd141b 3845 [(set_attr "type" "load_byte")
0d66636f 3846 (set_attr "predicable" "yes")
cffb2a26 3847 (set_attr "pool_range" "256")
3848 (set_attr "neg_pool_range" "244")]
3849)
3fc2009e 3850
b11cae9e 3851(define_expand "extendqisi2"
c8f69309 3852 [(set (match_dup 2)
3fc2009e 3853 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 3854 (const_int 24)))
9c08d1fa 3855 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3856 (ashiftrt:SI (match_dup 2)
3857 (const_int 24)))]
cffb2a26 3858 "TARGET_EITHER"
b11cae9e 3859 "
cffb2a26 3860 {
a2cd141b 3861 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3862 {
a2cd141b 3863 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 3864 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3865 DONE;
3866 }
a2cd141b 3867
215b30b3 3868 if (!s_register_operand (operands[1], QImode))
cffb2a26 3869 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 3870
a2cd141b 3871 if (arm_arch6)
3872 {
3873 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3874 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3875 DONE;
cffb2a26 3876 }
a2cd141b 3877
3878 operands[1] = gen_lowpart (SImode, operands[1]);
3879 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3880 }"
3881)
f7fbdd4a 3882
a2cd141b 3883(define_insn "*arm_extendqisi"
3884 [(set (match_operand:SI 0 "s_register_operand" "=r")
b4e8a300 3885 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
a2cd141b 3886 "TARGET_ARM && arm_arch4 && !arm_arch6"
b4e8a300 3887 "ldr%?sb\\t%0, %1"
a2cd141b 3888 [(set_attr "type" "load_byte")
0d66636f 3889 (set_attr "predicable" "yes")
cffb2a26 3890 (set_attr "pool_range" "256")
3891 (set_attr "neg_pool_range" "244")]
3892)
3fc2009e 3893
a2cd141b 3894(define_insn "*arm_extendqisi_v6"
3895 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
b4e8a300 3896 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
a2cd141b 3897 "TARGET_ARM && arm_arch6"
b4e8a300 3898 "@
3899 sxtb%?\\t%0, %1
3900 ldr%?sb\\t%0, %1"
a2cd141b 3901 [(set_attr "type" "alu_shift,load_byte")
3902 (set_attr "predicable" "yes")
a2cd141b 3903 (set_attr "pool_range" "*,256")
3904 (set_attr "neg_pool_range" "*,244")]
3905)
3906
3907(define_insn "*arm_extendqisi2addsi"
3908 [(set (match_operand:SI 0 "s_register_operand" "=r")
3909 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3910 (match_operand:SI 2 "s_register_operand" "r")))]
3911 "TARGET_ARM && arm_arch6"
3912 "sxtab%?\\t%0, %2, %1"
3913 [(set_attr "type" "alu_shift")
3914 (set_attr "predicable" "yes")]
3915)
3916
a2cd141b 3917(define_insn "*thumb_extendqisi2"
3918 [(set (match_operand:SI 0 "register_operand" "=l,l")
3919 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3920 "TARGET_THUMB && !arm_arch6"
cffb2a26 3921 "*
3922 {
3923 rtx ops[3];
3924 rtx mem = XEXP (operands[1], 0);
3925
3926 if (GET_CODE (mem) == CONST)
3927 mem = XEXP (mem, 0);
3928
3929 if (GET_CODE (mem) == LABEL_REF)
3930 return \"ldr\\t%0, %1\";
3931
3932 if (GET_CODE (mem) == PLUS
3933 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3934 return \"ldr\\t%0, %1\";
3935
3936 if (which_alternative == 0)
3937 return \"ldrsb\\t%0, %1\";
3938
3939 ops[0] = operands[0];
3940
3941 if (GET_CODE (mem) == PLUS)
3942 {
3943 rtx a = XEXP (mem, 0);
3944 rtx b = XEXP (mem, 1);
3945
3946 ops[1] = a;
3947 ops[2] = b;
3948
3949 if (GET_CODE (a) == REG)
3950 {
3951 if (GET_CODE (b) == REG)
3952 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3953 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 3954 {
3955 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3956 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3957 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3958 }
cffb2a26 3959 else
3960 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3961 }
3962 else if (GET_CODE (b) != REG)
3963 abort ();
3964 else
3965 {
3966 if (REGNO (b) == REGNO (ops[0]))
215b30b3 3967 {
3968 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3969 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3970 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3971 }
cffb2a26 3972 else
3973 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3974 }
3975 }
3976 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3977 {
215b30b3 3978 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3979 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3980 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 3981 }
3982 else
3983 {
3984 ops[1] = mem;
3985 ops[2] = const0_rtx;
3986
3987 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3988 }
3989 return \"\";
3990 }"
3991 [(set_attr "length" "2,6")
a2cd141b 3992 (set_attr "type" "load_byte,load_byte")
cffb2a26 3993 (set_attr "pool_range" "32,32")]
3994)
3995
a2cd141b 3996(define_insn "*thumb_extendqisi2_v6"
3997 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3998 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3999 "TARGET_THUMB && arm_arch6"
4000 "*
4001 {
4002 rtx ops[3];
4003 rtx mem;
4004
4005 if (which_alternative == 0)
4006 return \"sxtb\\t%0, %1\";
4007
4008 mem = XEXP (operands[1], 0);
4009
4010 if (GET_CODE (mem) == CONST)
4011 mem = XEXP (mem, 0);
4012
4013 if (GET_CODE (mem) == LABEL_REF)
4014 return \"ldr\\t%0, %1\";
4015
4016 if (GET_CODE (mem) == PLUS
4017 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4018 return \"ldr\\t%0, %1\";
4019
4020 if (which_alternative == 0)
4021 return \"ldrsb\\t%0, %1\";
4022
4023 ops[0] = operands[0];
4024
4025 if (GET_CODE (mem) == PLUS)
4026 {
4027 rtx a = XEXP (mem, 0);
4028 rtx b = XEXP (mem, 1);
4029
4030 ops[1] = a;
4031 ops[2] = b;
4032
4033 if (GET_CODE (a) == REG)
4034 {
4035 if (GET_CODE (b) == REG)
4036 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4037 else if (REGNO (a) == REGNO (ops[0]))
4038 {
4039 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4040 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4041 }
4042 else
4043 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4044 }
4045 else if (GET_CODE (b) != REG)
4046 abort ();
4047 else
4048 {
4049 if (REGNO (b) == REGNO (ops[0]))
4050 {
4051 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4052 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4053 }
4054 else
4055 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4056 }
4057 }
4058 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4059 {
4060 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4061 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4062 }
4063 else
4064 {
4065 ops[1] = mem;
4066 ops[2] = const0_rtx;
4067
4068 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4069 }
4070 return \"\";
4071 }"
4072 [(set_attr "length" "2,2,4")
4073 (set_attr "type" "alu_shift,load_byte,load_byte")
4074 (set_attr "pool_range" "*,32,32")]
4075)
4076
caedf871 4077(define_expand "extendsfdf2"
4078 [(set (match_operand:DF 0 "s_register_operand" "")
4079 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 4080 "TARGET_ARM && TARGET_HARD_FLOAT"
caedf871 4081 ""
4082)
b11cae9e 4083\f
4084;; Move insns (including loads and stores)
4085
4086;; XXX Just some ideas about movti.
9c08d1fa 4087;; I don't think these are a good idea on the arm, there just aren't enough
4088;; registers
b11cae9e 4089;;(define_expand "loadti"
9c08d1fa 4090;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4091;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4092;; "" "")
4093
4094;;(define_expand "storeti"
4095;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4096;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4097;; "" "")
4098
4099;;(define_expand "movti"
4100;; [(set (match_operand:TI 0 "general_operand" "")
4101;; (match_operand:TI 1 "general_operand" ""))]
4102;; ""
4103;; "
4104;;{
4105;; rtx insn;
4106;;
4107;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4108;; operands[1] = copy_to_reg (operands[1]);
4109;; if (GET_CODE (operands[0]) == MEM)
4110;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4111;; else if (GET_CODE (operands[1]) == MEM)
4112;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4113;; else
4114;; FAIL;
4115;;
4116;; emit_insn (insn);
4117;; DONE;
4118;;}")
4119
a2f10574 4120;; Recognize garbage generated above.
b11cae9e 4121
4122;;(define_insn ""
4123;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4124;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4125;; ""
4126;; "*
4127;; {
4128;; register mem = (which_alternative < 3);
0d66636f 4129;; register const char *template;
b11cae9e 4130;;
4131;; operands[mem] = XEXP (operands[mem], 0);
4132;; switch (which_alternative)
4133;; {
4134;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4135;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4136;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4137;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4138;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4139;; case 5: template = \"stmia\\t%0, %M1\"; break;
4140;; }
e2348bcb 4141;; output_asm_insn (template, operands);
4142;; return \"\";
b11cae9e 4143;; }")
4144
cffb2a26 4145(define_expand "movdi"
4146 [(set (match_operand:DI 0 "general_operand" "")
4147 (match_operand:DI 1 "general_operand" ""))]
4148 "TARGET_EITHER"
4149 "
4150 if (TARGET_THUMB)
4151 {
215b30b3 4152 if (!no_new_pseudos)
cffb2a26 4153 {
4154 if (GET_CODE (operands[0]) != REG)
4155 operands[1] = force_reg (DImode, operands[1]);
4156 }
4157 }
4158 "
4159)
b11cae9e 4160
cffb2a26 4161(define_insn "*arm_movdi"
a8a3b539 4162 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
215b30b3 4163 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
a2cd141b 4164 "TARGET_ARM
4165 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4166 && !TARGET_IWMMXT"
b11cae9e 4167 "*
4168 return (output_move_double (operands));
cffb2a26 4169 "
4170 [(set_attr "length" "8")
a2cd141b 4171 (set_attr "type" "*,load2,store2")
cffb2a26 4172 (set_attr "pool_range" "*,1020,*")
dd080cc9 4173 (set_attr "neg_pool_range" "*,1008,*")]
cffb2a26 4174)
4175
a8a3b539 4176;; We can't actually do base+index doubleword loads if the index and
4177;; destination overlap. Split here so that we at least have chance to
4178;; schedule.
4179(define_split
4180 [(set (match_operand:DI 0 "s_register_operand" "")
4181 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4182 (match_operand:SI 2 "s_register_operand" ""))))]
4183 "TARGET_LDRD
4184 && reg_overlap_mentioned_p (operands[0], operands[1])
4185 && reg_overlap_mentioned_p (operands[0], operands[2])"
4186 [(set (match_dup 4)
4187 (plus:SI (match_dup 1)
4188 (match_dup 2)))
4189 (set (match_dup 0)
4190 (mem:DI (match_dup 4)))]
4191 "
4192 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4193 "
4194)
4195
cffb2a26 4196;;; ??? This should have alternatives for constants.
4197;;; ??? This was originally identical to the movdf_insn pattern.
4198;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4199;;; thumb_reorg with a memory reference.
4200(define_insn "*thumb_movdi_insn"
215b30b3 4201 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4202 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
cffb2a26 4203 "TARGET_THUMB
a2cd141b 4204 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4205 && ( register_operand (operands[0], DImode)
4206 || register_operand (operands[1], DImode))"
4207 "*
4208 {
4209 switch (which_alternative)
4210 {
4211 default:
4212 case 0:
4213 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4214 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4215 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4216 case 1:
4217 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4218 case 2:
4219 operands[1] = GEN_INT (- INTVAL (operands[1]));
4220 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4221 case 3:
4222 return \"ldmia\\t%1, {%0, %H0}\";
4223 case 4:
4224 return \"stmia\\t%0, {%1, %H1}\";
4225 case 5:
4226 return thumb_load_double_from_address (operands);
4227 case 6:
1a83b3ff 4228 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4229 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4230 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4231 return \"\";
4232 case 7:
4233 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4234 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4235 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4236 }
4237 }"
4238 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4239 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4240 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4241)
b11cae9e 4242
9c08d1fa 4243(define_expand "movsi"
4244 [(set (match_operand:SI 0 "general_operand" "")
4245 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4246 "TARGET_EITHER"
9c08d1fa 4247 "
cffb2a26 4248 if (TARGET_ARM)
9c08d1fa 4249 {
674a8f0b 4250 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4251 if (GET_CODE (operands[0]) == MEM)
4252 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4253 if (arm_general_register_operand (operands[0], SImode)
4254 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4255 && !(const_ok_for_arm (INTVAL (operands[1]))
4256 || const_ok_for_arm (~INTVAL (operands[1]))))
4257 {
96f57e36 4258 arm_split_constant (SET, SImode, NULL_RTX,
4259 INTVAL (operands[1]), operands[0], NULL_RTX,
935d87ee 4260 (no_new_pseudos ? 0
cffb2a26 4261 : preserve_subexpressions_p ()));
4262 DONE;
4263 }
4264 }
674a8f0b 4265 else /* TARGET_THUMB.... */
cffb2a26 4266 {
215b30b3 4267 if (!no_new_pseudos)
cffb2a26 4268 {
4269 if (GET_CODE (operands[0]) != REG)
4270 operands[1] = force_reg (SImode, operands[1]);
4271 }
9c08d1fa 4272 }
af1b847e 4273
bbe777ea 4274 if (flag_pic
4275 && (CONSTANT_P (operands[1])
4276 || symbol_mentioned_p (operands[1])
4277 || label_mentioned_p (operands[1])))
849170fd 4278 operands[1] = legitimize_pic_address (operands[1], SImode,
935d87ee 4279 (no_new_pseudos ? operands[0] : 0));
215b30b3 4280 "
4281)
9c08d1fa 4282
cffb2a26 4283(define_insn "*arm_movsi_insn"
215b30b3 4284 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4285 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
755eb2b4 4286 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 4287 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 4288 && ( register_operand (operands[0], SImode)
4289 || register_operand (operands[1], SImode))"
f7fbdd4a 4290 "@
4291 mov%?\\t%0, %1
4292 mvn%?\\t%0, #%B1
4293 ldr%?\\t%0, %1
4294 str%?\\t%1, %0"
a2cd141b 4295 [(set_attr "type" "*,*,load1,store1")
0d66636f 4296 (set_attr "predicable" "yes")
cffb2a26 4297 (set_attr "pool_range" "*,*,4096,*")
4298 (set_attr "neg_pool_range" "*,*,4084,*")]
4299)
87b22bf7 4300
4301(define_split
a2cd141b 4302 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 4303 (match_operand:SI 1 "const_int_operand" ""))]
cffb2a26 4304 "TARGET_ARM
215b30b3 4305 && (!(const_ok_for_arm (INTVAL (operands[1]))
4306 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4307 [(clobber (const_int 0))]
4308 "
96f57e36 4309 arm_split_constant (SET, SImode, NULL_RTX,
4310 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 4311 DONE;
215b30b3 4312 "
4313)
9c08d1fa 4314
cffb2a26 4315(define_insn "*thumb_movsi_insn"
215b30b3 4316 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4317 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
cffb2a26 4318 "TARGET_THUMB
4319 && ( register_operand (operands[0], SImode)
4320 || register_operand (operands[1], SImode))"
4321 "@
4322 mov %0, %1
4323 mov %0, %1
4324 #
4325 #
4326 ldmia\\t%1, {%0}
4327 stmia\\t%0, {%1}
4328 ldr\\t%0, %1
4329 str\\t%1, %0
4330 mov\\t%0, %1"
4331 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 4332 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 4333 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4334)
4335
4336(define_split
4337 [(set (match_operand:SI 0 "register_operand" "")
4338 (match_operand:SI 1 "const_int_operand" ""))]
4339 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4340 [(set (match_dup 0) (match_dup 1))
4341 (set (match_dup 0) (neg:SI (match_dup 0)))]
4342 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4343)
4344
4345(define_split
4346 [(set (match_operand:SI 0 "register_operand" "")
4347 (match_operand:SI 1 "const_int_operand" ""))]
4348 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4349 [(set (match_dup 0) (match_dup 1))
4350 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4351 "
4352 {
4353 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4354 unsigned HOST_WIDE_INT mask = 0xff;
4355 int i;
4356
4357 for (i = 0; i < 25; i++)
4358 if ((val & (mask << i)) == val)
4359 break;
4360
f5b3169c 4361 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4362 if (i == 0)
4363 FAIL;
4364
4365 operands[1] = GEN_INT (val >> i);
4366 operands[2] = GEN_INT (i);
4367 }"
4368)
4369
67336bcf 4370;; When generating pic, we need to load the symbol offset into a register.
4371;; So that the optimizer does not confuse this with a normal symbol load
4372;; we use an unspec. The offset will be loaded from a constant pool entry,
4373;; since that is the only type of relocation we can use.
4374
4375;; The rather odd constraints on the following are to force reload to leave
4376;; the insn alone, and to force the minipool generation pass to then move
4377;; the GOT symbol to memory.
849170fd 4378
8c4d8060 4379(define_insn "pic_load_addr_arm"
849170fd 4380 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4381 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4382 "TARGET_ARM && flag_pic"
67336bcf 4383 "ldr%?\\t%0, %1"
a2cd141b 4384 [(set_attr "type" "load1")
8c4d8060 4385 (set (attr "pool_range") (const_int 4096))
4386 (set (attr "neg_pool_range") (const_int 4084))]
4387)
4388
4389(define_insn "pic_load_addr_thumb"
4390 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4391 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4392 "TARGET_THUMB && flag_pic"
4393 "ldr\\t%0, %1"
a2cd141b 4394 [(set_attr "type" "load1")
8c4d8060 4395 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4396)
849170fd 4397
4398;; This variant is used for AOF assembly, since it needs to mention the
4399;; pic register in the rtl.
4400(define_expand "pic_load_addr_based"
7db9af5d 4401 [(set (match_operand:SI 0 "s_register_operand" "")
e1159bbe 4402 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
cffb2a26 4403 "TARGET_ARM && flag_pic"
4404 "operands[2] = pic_offset_table_rtx;"
4405)
849170fd 4406
4407(define_insn "*pic_load_addr_based_insn"
4408 [(set (match_operand:SI 0 "s_register_operand" "=r")
4409 (unspec:SI [(match_operand 1 "" "")
e1159bbe 4410 (match_operand 2 "s_register_operand" "r")]
4411 UNSPEC_PIC_SYM))]
cffb2a26 4412 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
849170fd 4413 "*
4414#ifdef AOF_ASSEMBLER
4415 operands[1] = aof_pic_entry (operands[1]);
4416#endif
4417 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4418 return \"\";
cffb2a26 4419 "
a2cd141b 4420 [(set_attr "type" "load1")
cffb2a26 4421 (set (attr "pool_range")
4422 (if_then_else (eq_attr "is_thumb" "yes")
4423 (const_int 1024)
4424 (const_int 4096)))
4425 (set (attr "neg_pool_range")
4426 (if_then_else (eq_attr "is_thumb" "yes")
4427 (const_int 0)
4428 (const_int 4084)))]
4429)
4430
4431(define_insn "pic_add_dot_plus_four"
4432 [(set (match_operand:SI 0 "register_operand" "+r")
2c96dc5a 4433 (unspec:SI [(plus:SI (match_dup 0)
4434 (const (plus:SI (pc) (const_int 4))))]
4435 UNSPEC_PIC_BASE))
cffb2a26 4436 (use (label_ref (match_operand 1 "" "")))]
4437 "TARGET_THUMB && flag_pic"
4438 "*
805e22b2 4439 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
cffb2a26 4440 CODE_LABEL_NUMBER (operands[1]));
4441 return \"add\\t%0, %|pc\";
4442 "
4443 [(set_attr "length" "2")]
4444)
849170fd 4445
4446(define_insn "pic_add_dot_plus_eight"
6c4c2133 4447 [(set (match_operand:SI 0 "register_operand" "+r")
2c96dc5a 4448 (unspec:SI [(plus:SI (match_dup 0)
4449 (const (plus:SI (pc) (const_int 8))))]
4450 UNSPEC_PIC_BASE))
c4034607 4451 (use (label_ref (match_operand 1 "" "")))]
cffb2a26 4452 "TARGET_ARM && flag_pic"
c4034607 4453 "*
805e22b2 4454 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
0d66636f 4455 CODE_LABEL_NUMBER (operands[1]));
4456 return \"add%?\\t%0, %|pc, %0\";
cffb2a26 4457 "
0d66636f 4458 [(set_attr "predicable" "yes")]
cffb2a26 4459)
849170fd 4460
95373f08 4461(define_expand "builtin_setjmp_receiver"
4462 [(label_ref (match_operand 0 "" ""))]
4463 "flag_pic"
4464 "
4465{
4466 arm_finalize_pic (0);
4467 DONE;
4468}")
4469
9c08d1fa 4470;; If copying one reg to another we can set the condition codes according to
4471;; its value. Such a move is common after a return from subroutine and the
4472;; result is being tested against zero.
4473
f7fbdd4a 4474(define_insn "*movsi_compare0"
bd5b4116 4475 [(set (reg:CC CC_REGNUM)
cffb2a26 4476 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4477 (const_int 0)))
4478 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4479 (match_dup 1))]
4480 "TARGET_ARM"
e2348bcb 4481 "@
40dbec34 4482 cmp%?\\t%0, #0
4483 sub%?s\\t%0, %1, #0"
cffb2a26 4484 [(set_attr "conds" "set")]
4485)
b11cae9e 4486
b11cae9e 4487;; Subroutine to store a half word from a register into memory.
4488;; Operand 0 is the source register (HImode)
c8f69309 4489;; Operand 1 is the destination address in a register (SImode)
b11cae9e 4490
9c08d1fa 4491;; In both this routine and the next, we must be careful not to spill
01cc3b75 4492;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 4493;; can generate unrecognizable rtl.
4494
b11cae9e 4495(define_expand "storehi"
c8f69309 4496 [;; store the low byte
f082f1c4 4497 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 4498 ;; extract the high byte
c8f69309 4499 (set (match_dup 2)
4500 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 4501 ;; store the high byte
787f8210 4502 (set (match_dup 4) (match_dup 5))]
cffb2a26 4503 "TARGET_ARM"
b11cae9e 4504 "
215b30b3 4505 {
537ffcfc 4506 rtx op1 = operands[1];
4507 rtx addr = XEXP (op1, 0);
215b30b3 4508 enum rtx_code code = GET_CODE (addr);
4509
4510 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4511 || code == MINUS)
537ffcfc 4512 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 4513
537ffcfc 4514 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4515 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4516 operands[3] = gen_lowpart (QImode, operands[0]);
4517 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 4518 operands[2] = gen_reg_rtx (SImode);
4519 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4520 }"
4521)
b11cae9e 4522
c7597b5d 4523(define_expand "storehi_bigend"
f082f1c4 4524 [(set (match_dup 4) (match_dup 3))
c7597b5d 4525 (set (match_dup 2)
4526 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 4527 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 4528 "TARGET_ARM"
b11cae9e 4529 "
215b30b3 4530 {
537ffcfc 4531 rtx op1 = operands[1];
4532 rtx addr = XEXP (op1, 0);
215b30b3 4533 enum rtx_code code = GET_CODE (addr);
4534
4535 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4536 || code == MINUS)
537ffcfc 4537 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 4538
537ffcfc 4539 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4540 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4541 operands[3] = gen_lowpart (QImode, operands[0]);
4542 operands[0] = gen_lowpart (SImode, operands[0]);
4543 operands[2] = gen_reg_rtx (SImode);
787f8210 4544 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4545 }"
4546)
c7597b5d 4547
4548;; Subroutine to store a half word integer constant into memory.
4549(define_expand "storeinthi"
f082f1c4 4550 [(set (match_operand 0 "" "")
787f8210 4551 (match_operand 1 "" ""))
9e8503e6 4552 (set (match_dup 3) (match_dup 2))]
cffb2a26 4553 "TARGET_ARM"
c7597b5d 4554 "
215b30b3 4555 {
4556 HOST_WIDE_INT value = INTVAL (operands[1]);
4557 rtx addr = XEXP (operands[0], 0);
537ffcfc 4558 rtx op0 = operands[0];
215b30b3 4559 enum rtx_code code = GET_CODE (addr);
c7597b5d 4560
215b30b3 4561 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4562 || code == MINUS)
537ffcfc 4563 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 4564
215b30b3 4565 operands[1] = gen_reg_rtx (SImode);
4566 if (BYTES_BIG_ENDIAN)
4567 {
4568 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4569 if ((value & 255) == ((value >> 8) & 255))
4570 operands[2] = operands[1];
4571 else
4572 {
4573 operands[2] = gen_reg_rtx (SImode);
4574 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4575 }
4576 }
4577 else
4578 {
4579 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4580 if ((value & 255) == ((value >> 8) & 255))
4581 operands[2] = operands[1];
4582 else
4583 {
4584 operands[2] = gen_reg_rtx (SImode);
4585 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4586 }
4587 }
c7597b5d 4588
537ffcfc 4589 operands[3] = adjust_address (op0, QImode, 1);
e513d163 4590 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 4591 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 4592 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 4593 }"
4594)
b11cae9e 4595
f7fbdd4a 4596(define_expand "storehi_single_op"
4597 [(set (match_operand:HI 0 "memory_operand" "")
4598 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4599 "TARGET_ARM && arm_arch4"
f7fbdd4a 4600 "
215b30b3 4601 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 4602 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 4603 "
4604)
f7fbdd4a 4605
b11cae9e 4606(define_expand "movhi"
4607 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 4608 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4609 "TARGET_EITHER"
b11cae9e 4610 "
cffb2a26 4611 if (TARGET_ARM)
b11cae9e 4612 {
215b30b3 4613 if (!no_new_pseudos)
cffb2a26 4614 {
4615 if (GET_CODE (operands[0]) == MEM)
b11cae9e 4616 {
cffb2a26 4617 if (arm_arch4)
4618 {
4619 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4620 DONE;
4621 }
4622 if (GET_CODE (operands[1]) == CONST_INT)
4623 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 4624 else
cffb2a26 4625 {
4626 if (GET_CODE (operands[1]) == MEM)
4627 operands[1] = force_reg (HImode, operands[1]);
4628 if (BYTES_BIG_ENDIAN)
4629 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4630 else
4631 emit_insn (gen_storehi (operands[1], operands[0]));
4632 }
4633 DONE;
b11cae9e 4634 }
cffb2a26 4635 /* Sign extend a constant, and keep it in an SImode reg. */
4636 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 4637 {
cffb2a26 4638 rtx reg = gen_reg_rtx (SImode);
4639 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4640
4641 /* If the constant is already valid, leave it alone. */
215b30b3 4642 if (!const_ok_for_arm (val))
cffb2a26 4643 {
4644 /* If setting all the top bits will make the constant
4645 loadable in a single instruction, then set them.
4646 Otherwise, sign extend the number. */
4647
215b30b3 4648 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 4649 val |= ~0xffff;
4650 else if (val & 0x8000)
4651 val |= ~0xffff;
4652 }
4653
4654 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 4655 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 4656 }
0045890a 4657 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4658 && GET_CODE (operands[1]) == MEM)
4659 {
4660 rtx reg = gen_reg_rtx (SImode);
4661
4662 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4663 operands[1] = gen_lowpart (HImode, reg);
4664 }
215b30b3 4665 else if (!arm_arch4)
f7fbdd4a 4666 {
cffb2a26 4667 if (GET_CODE (operands[1]) == MEM)
4668 {
c1a66faf 4669 rtx base;
4670 rtx offset = const0_rtx;
4671 rtx reg = gen_reg_rtx (SImode);
4672
4673 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4674 || (GET_CODE (base) == PLUS
4675 && (GET_CODE (offset = XEXP (base, 1))
4676 == CONST_INT)
4677 && ((INTVAL(offset) & 1) != 1)
4678 && GET_CODE (base = XEXP (base, 0)) == REG))
4679 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 4680 {
c1a66faf 4681 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4682 rtx new;
4683
4684 new = gen_rtx_MEM (SImode,
4685 plus_constant (base, new_offset));
4686 MEM_COPY_ATTRIBUTES (new, operands[1]);
4687 emit_insn (gen_movsi (reg, new));
4688 if (((INTVAL (offset) & 2) != 0)
4689 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4690 {
4691 rtx reg2 = gen_reg_rtx (SImode);
4692
4693 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4694 reg = reg2;
4695 }
206ee9a2 4696 }
c1a66faf 4697 else
4698 emit_insn (gen_movhi_bytes (reg, operands[1]));
4699
4700 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 4701 }
4702 }
4703 }
674a8f0b 4704 /* Handle loading a large integer during reload. */
cffb2a26 4705 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4706 && !const_ok_for_arm (INTVAL (operands[1]))
4707 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 4708 {
4709 /* Writing a constant to memory needs a scratch, which should
4710 be handled with SECONDARY_RELOADs. */
4711 if (GET_CODE (operands[0]) != REG)
4712 abort ();
4713
4714 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4715 emit_insn (gen_movsi (operands[0], operands[1]));
4716 DONE;
4717 }
4718 }
4719 else /* TARGET_THUMB */
4720 {
215b30b3 4721 if (!no_new_pseudos)
cffb2a26 4722 {
4723 if (GET_CODE (operands[0]) != REG)
4724 operands[1] = force_reg (HImode, operands[1]);
4725
4726 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4727 happen if we are passed a SP (never OK for HImode/QImode) or
4728 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4729 HImode/QImode) relative address. */
cffb2a26 4730 /* ??? This should perhaps be fixed elsewhere, for instance, in
4731 fixup_stack_1, by checking for other kinds of invalid addresses,
4732 e.g. a bare reference to a virtual register. This may confuse the
4733 alpha though, which must handle this case differently. */
4734 if (GET_CODE (operands[0]) == MEM
215b30b3 4735 && !memory_address_p (GET_MODE (operands[0]),
4736 XEXP (operands[0], 0)))
537ffcfc 4737 operands[0]
4738 = replace_equiv_address (operands[0],
4739 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 4740
4741 if (GET_CODE (operands[1]) == MEM
215b30b3 4742 && !memory_address_p (GET_MODE (operands[1]),
4743 XEXP (operands[1], 0)))
537ffcfc 4744 operands[1]
4745 = replace_equiv_address (operands[1],
4746 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 4747 }
674a8f0b 4748 /* Handle loading a large integer during reload. */
cffb2a26 4749 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4750 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
cffb2a26 4751 {
4752 /* Writing a constant to memory needs a scratch, which should
4753 be handled with SECONDARY_RELOADs. */
4754 if (GET_CODE (operands[0]) != REG)
4755 abort ();
4756
1a83b3ff 4757 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 4758 emit_insn (gen_movsi (operands[0], operands[1]));
4759 DONE;
4760 }
b11cae9e 4761 }
cffb2a26 4762 "
4763)
4764
4765(define_insn "*thumb_movhi_insn"
a941568e 4766 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4767 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
cffb2a26 4768 "TARGET_THUMB
4769 && ( register_operand (operands[0], HImode)
4770 || register_operand (operands[1], HImode))"
4771 "*
4772 switch (which_alternative)
d79300ac 4773 {
cffb2a26 4774 case 0: return \"add %0, %1, #0\";
4775 case 2: return \"strh %1, %0\";
4776 case 3: return \"mov %0, %1\";
4777 case 4: return \"mov %0, %1\";
4778 case 5: return \"mov %0, %1\";
4779 default: abort ();
4780 case 1:
4781 /* The stack pointer can end up being taken as an index register.
4782 Catch this case here and deal with it. */
4783 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4784 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4785 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4786 {
4787 rtx ops[2];
4788 ops[0] = operands[0];
4789 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4790
4791 output_asm_insn (\"mov %0, %1\", ops);
4792
4793 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4794
4795 }
4796 return \"ldrh %0, %1\";
4797 }"
4798 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 4799 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 4800)
d79300ac 4801
b11cae9e 4802
25f7a26e 4803(define_expand "movhi_bytes"
eab14235 4804 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4805 (set (match_dup 3)
eab14235 4806 (zero_extend:SI (match_dup 6)))
25f7a26e 4807 (set (match_operand:SI 0 "" "")
4808 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 4809 "TARGET_ARM"
25f7a26e 4810 "
215b30b3 4811 {
4812 rtx mem1, mem2;
4813 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4814
4815 mem1 = gen_rtx_MEM (QImode, addr);
4816 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4817 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4818 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4819 operands[0] = gen_lowpart (SImode, operands[0]);
4820 operands[1] = mem1;
4821 operands[2] = gen_reg_rtx (SImode);
4822 operands[3] = gen_reg_rtx (SImode);
4823 operands[6] = mem2;
25f7a26e 4824
215b30b3 4825 if (BYTES_BIG_ENDIAN)
4826 {
4827 operands[4] = operands[2];
4828 operands[5] = operands[3];
4829 }
4830 else
4831 {
4832 operands[4] = operands[3];
4833 operands[5] = operands[2];
4834 }
4835 }"
4836)
25f7a26e 4837
c7597b5d 4838(define_expand "movhi_bigend"
4839 [(set (match_dup 2)
4840 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4841 (const_int 16)))
4842 (set (match_dup 3)
4843 (ashiftrt:SI (match_dup 2) (const_int 16)))
4844 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 4845 (match_dup 4))]
cffb2a26 4846 "TARGET_ARM"
c7597b5d 4847 "
4848 operands[2] = gen_reg_rtx (SImode);
4849 operands[3] = gen_reg_rtx (SImode);
787f8210 4850 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 4851 "
4852)
b11cae9e 4853
a2f10574 4854;; Pattern to recognize insn generated default case above
f7fbdd4a 4855(define_insn "*movhi_insn_arch4"
cffb2a26 4856 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 4857 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 4858 "TARGET_ARM
4859 && arm_arch4
f7fbdd4a 4860 && (GET_CODE (operands[1]) != CONST_INT
4861 || const_ok_for_arm (INTVAL (operands[1]))
4862 || const_ok_for_arm (~INTVAL (operands[1])))"
4863 "@
4864 mov%?\\t%0, %1\\t%@ movhi
4865 mvn%?\\t%0, #%B1\\t%@ movhi
cffb2a26 4866 str%?h\\t%1, %0\\t%@ movhi
4867 ldr%?h\\t%0, %1\\t%@ movhi"
a2cd141b 4868 [(set_attr "type" "*,*,store1,load1")
0d66636f 4869 (set_attr "predicable" "yes")
cffb2a26 4870 (set_attr "pool_range" "*,*,*,256")
4871 (set_attr "neg_pool_range" "*,*,*,244")]
4872)
f7fbdd4a 4873
f7fbdd4a 4874(define_insn "*movhi_bytes"
25f7a26e 4875 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4876 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 4877 "TARGET_ARM"
25f7a26e 4878 "@
4879 mov%?\\t%0, %1\\t%@ movhi
0d66636f 4880 mvn%?\\t%0, #%B1\\t%@ movhi"
4881 [(set_attr "predicable" "yes")]
4882)
25f7a26e 4883
cffb2a26 4884(define_insn "thumb_movhi_clobber"
4885 [(set (match_operand:HI 0 "memory_operand" "=m")
4886 (match_operand:HI 1 "register_operand" "l"))
4887 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4888 "TARGET_THUMB"
344495ea 4889 "*
4890 abort ();"
cffb2a26 4891)
4892
bc5c7e08 4893;; We use a DImode scratch because we may occasionally need an additional
4894;; temporary if the address isn't offsettable -- push_reload doesn't seem
4895;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 4896(define_expand "reload_outhi"
cffb2a26 4897 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 4898 (match_operand:HI 1 "s_register_operand" "r")
4899 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 4900 "TARGET_EITHER"
4901 "if (TARGET_ARM)
4902 arm_reload_out_hi (operands);
4903 else
4904 thumb_reload_out_hi (operands);
d3373b54 4905 DONE;
cffb2a26 4906 "
4907)
d3373b54 4908
25f7a26e 4909(define_expand "reload_inhi"
4910 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 4911 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 4912 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 4913 "TARGET_EITHER"
25f7a26e 4914 "
cffb2a26 4915 if (TARGET_ARM)
4916 arm_reload_in_hi (operands);
4917 else
4918 thumb_reload_out_hi (operands);
25f7a26e 4919 DONE;
4920")
4921
9c08d1fa 4922(define_expand "movqi"
4923 [(set (match_operand:QI 0 "general_operand" "")
4924 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 4925 "TARGET_EITHER"
9c08d1fa 4926 "
cffb2a26 4927 if (TARGET_ARM)
9c08d1fa 4928 {
cffb2a26 4929 /* Everything except mem = const or mem = mem can be done easily */
c7597b5d 4930
935d87ee 4931 if (!no_new_pseudos)
cffb2a26 4932 {
4933 if (GET_CODE (operands[1]) == CONST_INT)
4934 {
4935 rtx reg = gen_reg_rtx (SImode);
4936
4937 emit_insn (gen_movsi (reg, operands[1]));
9e8503e6 4938 operands[1] = gen_lowpart (QImode, reg);
cffb2a26 4939 }
0045890a 4940 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4941 {
4942 rtx reg = gen_reg_rtx (SImode);
4943
4944 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4945 operands[1] = gen_lowpart (QImode, reg);
4946 }
4947 if (GET_CODE (operands[0]) == MEM)
4948 operands[1] = force_reg (QImode, operands[1]);
4949 }
b11cae9e 4950 }
cffb2a26 4951 else /* TARGET_THUMB */
4952 {
215b30b3 4953 if (!no_new_pseudos)
cffb2a26 4954 {
4955 if (GET_CODE (operands[0]) != REG)
4956 operands[1] = force_reg (QImode, operands[1]);
4957
4958 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4959 happen if we are passed a SP (never OK for HImode/QImode) or
4960 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4961 HImode/QImode) relative address. */
cffb2a26 4962 /* ??? This should perhaps be fixed elsewhere, for instance, in
4963 fixup_stack_1, by checking for other kinds of invalid addresses,
4964 e.g. a bare reference to a virtual register. This may confuse the
4965 alpha though, which must handle this case differently. */
4966 if (GET_CODE (operands[0]) == MEM
215b30b3 4967 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 4968 XEXP (operands[0], 0)))
537ffcfc 4969 operands[0]
4970 = replace_equiv_address (operands[0],
4971 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 4972 if (GET_CODE (operands[1]) == MEM
4973 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 4974 XEXP (operands[1], 0)))
537ffcfc 4975 operands[1]
4976 = replace_equiv_address (operands[1],
4977 copy_to_reg (XEXP (operands[1], 0)));
cffb2a26 4978 }
674a8f0b 4979 /* Handle loading a large integer during reload. */
cffb2a26 4980 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4981 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
cffb2a26 4982 {
4983 /* Writing a constant to memory needs a scratch, which should
4984 be handled with SECONDARY_RELOADs. */
4985 if (GET_CODE (operands[0]) != REG)
4986 abort ();
4987
9e8503e6 4988 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 4989 emit_insn (gen_movsi (operands[0], operands[1]));
4990 DONE;
4991 }
4992 }
4993 "
4994)
b11cae9e 4995
9c08d1fa 4996
cffb2a26 4997(define_insn "*arm_movqi_insn"
4998 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 4999 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
cffb2a26 5000 "TARGET_ARM
5001 && ( register_operand (operands[0], QImode)
5002 || register_operand (operands[1], QImode))"
5565501b 5003 "@
5004 mov%?\\t%0, %1
5005 mvn%?\\t%0, #%B1
5006 ldr%?b\\t%0, %1
5007 str%?b\\t%1, %0"
a2cd141b 5008 [(set_attr "type" "*,*,load1,store1")
0d66636f 5009 (set_attr "predicable" "yes")]
cffb2a26 5010)
5011
5012(define_insn "*thumb_movqi_insn"
5013 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5014 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
cffb2a26 5015 "TARGET_THUMB
5016 && ( register_operand (operands[0], QImode)
5017 || register_operand (operands[1], QImode))"
5018 "@
5019 add\\t%0, %1, #0
5020 ldrb\\t%0, %1
5021 strb\\t%1, %0
5022 mov\\t%0, %1
5023 mov\\t%0, %1
5024 mov\\t%0, %1"
5025 [(set_attr "length" "2")
a2cd141b 5026 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5027 (set_attr "pool_range" "*,32,*,*,*,*")]
5028)
b11cae9e 5029
87b22bf7 5030(define_expand "movsf"
5031 [(set (match_operand:SF 0 "general_operand" "")
5032 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5033 "TARGET_EITHER"
87b22bf7 5034 "
cffb2a26 5035 if (TARGET_ARM)
5036 {
5037 if (GET_CODE (operands[0]) == MEM)
5038 operands[1] = force_reg (SFmode, operands[1]);
5039 }
5040 else /* TARGET_THUMB */
5041 {
215b30b3 5042 if (!no_new_pseudos)
cffb2a26 5043 {
5044 if (GET_CODE (operands[0]) != REG)
5045 operands[1] = force_reg (SFmode, operands[1]);
5046 }
5047 }
5048 "
5049)
5050
5051(define_split
5052 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5053 (match_operand:SF 1 "immediate_operand" ""))]
5054 "TARGET_ARM
a2cd141b 5055 && !(TARGET_HARD_FLOAT && TARGET_FPA)
cffb2a26 5056 && reload_completed
5057 && GET_CODE (operands[1]) == CONST_DOUBLE"
5058 [(set (match_dup 2) (match_dup 3))]
5059 "
5060 operands[2] = gen_lowpart (SImode, operands[0]);
5061 operands[3] = gen_lowpart (SImode, operands[1]);
5062 if (operands[2] == 0 || operands[3] == 0)
5063 FAIL;
215b30b3 5064 "
5065)
87b22bf7 5066
cffb2a26 5067(define_insn "*arm_movsf_soft_insn"
5068 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5069 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5070 "TARGET_ARM
5071 && TARGET_SOFT_FLOAT
215b30b3 5072 && (GET_CODE (operands[0]) != MEM
5073 || register_operand (operands[1], SFmode))"
9a1112d7 5074 "@
5075 mov%?\\t%0, %1
5076 ldr%?\\t%0, %1\\t%@ float
5077 str%?\\t%1, %0\\t%@ float"
cffb2a26 5078 [(set_attr "length" "4,4,4")
0d66636f 5079 (set_attr "predicable" "yes")
a2cd141b 5080 (set_attr "type" "*,load1,store1")
cffb2a26 5081 (set_attr "pool_range" "*,4096,*")
5082 (set_attr "neg_pool_range" "*,4084,*")]
5083)
5084
5085;;; ??? This should have alternatives for constants.
5086(define_insn "*thumb_movsf_insn"
215b30b3 5087 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5088 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
cffb2a26 5089 "TARGET_THUMB
5090 && ( register_operand (operands[0], SFmode)
5091 || register_operand (operands[1], SFmode))"
5092 "@
5093 add\\t%0, %1, #0
5094 ldmia\\t%1, {%0}
5095 stmia\\t%0, {%1}
5096 ldr\\t%0, %1
5097 str\\t%1, %0
5098 mov\\t%0, %1
5099 mov\\t%0, %1"
5100 [(set_attr "length" "2")
a2cd141b 5101 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5102 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5103)
9a1112d7 5104
9c08d1fa 5105(define_expand "movdf"
87b22bf7 5106 [(set (match_operand:DF 0 "general_operand" "")
5107 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5108 "TARGET_EITHER"
9c08d1fa 5109 "
cffb2a26 5110 if (TARGET_ARM)
5111 {
5112 if (GET_CODE (operands[0]) == MEM)
5113 operands[1] = force_reg (DFmode, operands[1]);
5114 }
5115 else /* TARGET_THUMB */
5116 {
215b30b3 5117 if (!no_new_pseudos)
cffb2a26 5118 {
5119 if (GET_CODE (operands[0]) != REG)
5120 operands[1] = force_reg (DFmode, operands[1]);
5121 }
5122 }
5123 "
5124)
b11cae9e 5125
9c08d1fa 5126;; Reloading a df mode value stored in integer regs to memory can require a
5127;; scratch reg.
5128(define_expand "reload_outdf"
cffb2a26 5129 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5130 (match_operand:DF 1 "s_register_operand" "r")
5131 (match_operand:SI 2 "s_register_operand" "=&r")]
cffb2a26 5132 "TARGET_ARM"
87b22bf7 5133 "
215b30b3 5134 {
5135 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5136
215b30b3 5137 if (code == REG)
5138 operands[2] = XEXP (operands[0], 0);
5139 else if (code == POST_INC || code == PRE_DEC)
5140 {
5141 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5142 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5143 emit_insn (gen_movdi (operands[0], operands[1]));
5144 DONE;
5145 }
5146 else if (code == PRE_INC)
5147 {
5148 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5149
215b30b3 5150 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5151 operands[2] = reg;
5152 }
5153 else if (code == POST_DEC)
5154 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5155 else
5156 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5157 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5158
215b30b3 5159 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5160 operands[1]));
f7fbdd4a 5161
215b30b3 5162 if (code == POST_DEC)
5163 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5164
5165 DONE;
5166 }"
5167)
9c08d1fa 5168
9a1112d7 5169(define_insn "*movdf_soft_insn"
cffb2a26 5170 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
f7fbdd4a 5171 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
344495ea 5172 "TARGET_ARM && TARGET_SOFT_FLOAT
5173 "
39b5e676 5174 "* return output_move_double (operands);"
cffb2a26 5175 [(set_attr "length" "8,8,8")
a2cd141b 5176 (set_attr "type" "*,load2,store2")
dd080cc9 5177 (set_attr "pool_range" "1020")
5178 (set_attr "neg_pool_range" "1008")]
cffb2a26 5179)
5180
5181;;; ??? This should have alternatives for constants.
5182;;; ??? This was originally identical to the movdi_insn pattern.
5183;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5184;;; thumb_reorg with a memory reference.
5185(define_insn "*thumb_movdf_insn"
215b30b3 5186 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5187 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
cffb2a26 5188 "TARGET_THUMB
5189 && ( register_operand (operands[0], DFmode)
5190 || register_operand (operands[1], DFmode))"
5191 "*
5192 switch (which_alternative)
5193 {
5194 default:
5195 case 0:
5196 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5197 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5198 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5199 case 1:
5200 return \"ldmia\\t%1, {%0, %H0}\";
5201 case 2:
5202 return \"stmia\\t%0, {%1, %H1}\";
5203 case 3:
5204 return thumb_load_double_from_address (operands);
5205 case 4:
1a83b3ff 5206 operands[2] = gen_rtx_MEM (SImode,
5207 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5208 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5209 return \"\";
5210 case 5:
5211 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5212 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5213 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5214 }
5215 "
5216 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 5217 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 5218 (set_attr "pool_range" "*,*,*,1020,*,*")]
5219)
755eb2b4 5220
5221;; Vector Moves
5222(define_expand "movv2si"
5223 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5224 (match_operand:V2SI 1 "general_operand" ""))]
5225 "TARGET_REALLY_IWMMXT"
5226{
5227})
5228
5229(define_expand "movv4hi"
5230 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5231 (match_operand:V4HI 1 "general_operand" ""))]
5232 "TARGET_REALLY_IWMMXT"
5233{
5234})
5235
5236(define_expand "movv8qi"
5237 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5238 (match_operand:V8QI 1 "general_operand" ""))]
5239 "TARGET_REALLY_IWMMXT"
5240{
5241})
b11cae9e 5242\f
b11cae9e 5243
9c08d1fa 5244;; load- and store-multiple insns
5245;; The arm can load/store any set of registers, provided that they are in
5246;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5247
9c08d1fa 5248(define_expand "load_multiple"
5249 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5250 (match_operand:SI 1 "" ""))
5251 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5252 "TARGET_ARM"
9c08d1fa 5253 "
bd5b4116 5254 /* Support only fixed point registers. */
9c08d1fa 5255 if (GET_CODE (operands[2]) != CONST_INT
5256 || INTVAL (operands[2]) > 14
5257 || INTVAL (operands[2]) < 2
5258 || GET_CODE (operands[1]) != MEM
5259 || GET_CODE (operands[0]) != REG
bd5b4116 5260 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5261 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5262 FAIL;
5263
5264 operands[3]
f082f1c4 5265 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5266 force_reg (SImode, XEXP (operands[1], 0)),
5267 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
e4600bc3 5268 MEM_IN_STRUCT_P(operands[1]),
5269 MEM_SCALAR_P (operands[1]));
215b30b3 5270 "
5271)
b11cae9e 5272
9c08d1fa 5273;; Load multiple with write-back
5274
2162064c 5275(define_insn "*ldmsi_postinc4"
9c08d1fa 5276 [(match_parallel 0 "load_multiple_operation"
13e9316a 5277 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5278 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5279 (const_int 16)))
5280 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5281 (mem:SI (match_dup 2)))
a0a72ac3 5282 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5283 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5284 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5285 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5286 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5287 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5288 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5289 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
a2cd141b 5290 [(set_attr "type" "load4")
2162064c 5291 (set_attr "predicable" "yes")]
5292)
b11cae9e 5293
2162064c 5294(define_insn "*ldmsi_postinc3"
5295 [(match_parallel 0 "load_multiple_operation"
13e9316a 5296 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5297 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5298 (const_int 12)))
5299 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5300 (mem:SI (match_dup 2)))
5301 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5302 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5303 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5304 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5305 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5306 "ldm%?ia\\t%1!, {%3, %4, %5}"
a2cd141b 5307 [(set_attr "type" "load3")
2162064c 5308 (set_attr "predicable" "yes")]
5309)
b11cae9e 5310
2162064c 5311(define_insn "*ldmsi_postinc2"
5312 [(match_parallel 0 "load_multiple_operation"
13e9316a 5313 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5314 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5315 (const_int 8)))
5316 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5317 (mem:SI (match_dup 2)))
5318 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5319 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5320 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5321 "ldm%?ia\\t%1!, {%3, %4}"
a2cd141b 5322 [(set_attr "type" "load2")
0d66636f 5323 (set_attr "predicable" "yes")]
5324)
b11cae9e 5325
9c08d1fa 5326;; Ordinary load multiple
b11cae9e 5327
2162064c 5328(define_insn "*ldmsi4"
9c08d1fa 5329 [(match_parallel 0 "load_multiple_operation"
2162064c 5330 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5331 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5332 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5333 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5334 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5335 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5336 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5337 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5338 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5339 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
a2cd141b 5340 [(set_attr "type" "load4")
2162064c 5341 (set_attr "predicable" "yes")]
5342)
9c08d1fa 5343
2162064c 5344(define_insn "*ldmsi3"
5345 [(match_parallel 0 "load_multiple_operation"
5346 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5347 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5348 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5349 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5350 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5351 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5352 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5353 "ldm%?ia\\t%1, {%2, %3, %4}"
a2cd141b 5354 [(set_attr "type" "load3")
2162064c 5355 (set_attr "predicable" "yes")]
5356)
9c08d1fa 5357
2162064c 5358(define_insn "*ldmsi2"
5359 [(match_parallel 0 "load_multiple_operation"
5360 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5361 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5362 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5363 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5364 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5365 "ldm%?ia\\t%1, {%2, %3}"
a2cd141b 5366 [(set_attr "type" "load2")
0d66636f 5367 (set_attr "predicable" "yes")]
5368)
9c08d1fa 5369
5370(define_expand "store_multiple"
5371 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5372 (match_operand:SI 1 "" ""))
5373 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5374 "TARGET_ARM"
9c08d1fa 5375 "
674a8f0b 5376 /* Support only fixed point registers. */
9c08d1fa 5377 if (GET_CODE (operands[2]) != CONST_INT
5378 || INTVAL (operands[2]) > 14
5379 || INTVAL (operands[2]) < 2
5380 || GET_CODE (operands[1]) != REG
5381 || GET_CODE (operands[0]) != MEM
bd5b4116 5382 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5383 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5384 FAIL;
5385
5386 operands[3]
f082f1c4 5387 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5388 force_reg (SImode, XEXP (operands[0], 0)),
5389 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
e4600bc3 5390 MEM_IN_STRUCT_P(operands[0]),
5391 MEM_SCALAR_P (operands[0]));
215b30b3 5392 "
5393)
b11cae9e 5394
9c08d1fa 5395;; Store multiple with write-back
5396
2162064c 5397(define_insn "*stmsi_postinc4"
9c08d1fa 5398 [(match_parallel 0 "store_multiple_operation"
13e9316a 5399 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5400 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5401 (const_int 16)))
a0a72ac3 5402 (set (mem:SI (match_dup 2))
2162064c 5403 (match_operand:SI 3 "arm_hard_register_operand" ""))
5404 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5405 (match_operand:SI 4 "arm_hard_register_operand" ""))
5406 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5407 (match_operand:SI 5 "arm_hard_register_operand" ""))
5408 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5409 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5410 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5411 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5412 [(set_attr "predicable" "yes")
5413 (set_attr "type" "store4")]
5414)
b11cae9e 5415
2162064c 5416(define_insn "*stmsi_postinc3"
5417 [(match_parallel 0 "store_multiple_operation"
13e9316a 5418 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5419 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5420 (const_int 12)))
5421 (set (mem:SI (match_dup 2))
5422 (match_operand:SI 3 "arm_hard_register_operand" ""))
5423 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5424 (match_operand:SI 4 "arm_hard_register_operand" ""))
5425 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5426 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5427 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5428 "stm%?ia\\t%1!, {%3, %4, %5}"
5429 [(set_attr "predicable" "yes")
5430 (set_attr "type" "store3")]
5431)
9c08d1fa 5432
2162064c 5433(define_insn "*stmsi_postinc2"
5434 [(match_parallel 0 "store_multiple_operation"
13e9316a 5435 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5436 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5437 (const_int 8)))
5438 (set (mem:SI (match_dup 2))
5439 (match_operand:SI 3 "arm_hard_register_operand" ""))
5440 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5441 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5442 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5443 "stm%?ia\\t%1!, {%3, %4}"
0d66636f 5444 [(set_attr "predicable" "yes")
2162064c 5445 (set_attr "type" "store2")]
cffb2a26 5446)
9c08d1fa 5447
5448;; Ordinary store multiple
5449
2162064c 5450(define_insn "*stmsi4"
9c08d1fa 5451 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 5452 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 5453 (match_operand:SI 2 "arm_hard_register_operand" ""))
5454 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5455 (match_operand:SI 3 "arm_hard_register_operand" ""))
5456 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5457 (match_operand:SI 4 "arm_hard_register_operand" ""))
5458 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5459 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5460 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5461 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5462 [(set_attr "predicable" "yes")
5463 (set_attr "type" "store4")]
5464)
9c08d1fa 5465
2162064c 5466(define_insn "*stmsi3"
5467 [(match_parallel 0 "store_multiple_operation"
5468 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5469 (match_operand:SI 2 "arm_hard_register_operand" ""))
5470 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5471 (match_operand:SI 3 "arm_hard_register_operand" ""))
5472 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5473 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5474 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5475 "stm%?ia\\t%1, {%2, %3, %4}"
5476 [(set_attr "predicable" "yes")
5477 (set_attr "type" "store3")]
5478)
9c08d1fa 5479
2162064c 5480(define_insn "*stmsi2"
5481 [(match_parallel 0 "store_multiple_operation"
5482 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5483 (match_operand:SI 2 "arm_hard_register_operand" ""))
5484 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5485 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5486 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5487 "stm%?ia\\t%1, {%2, %3}"
0d66636f 5488 [(set_attr "predicable" "yes")
2162064c 5489 (set_attr "type" "store2")]
cffb2a26 5490)
9c08d1fa 5491
5492;; Move a block of memory if it is word aligned and MORE than 2 words long.
5493;; We could let this apply for blocks of less than this, but it clobbers so
5494;; many registers that there is then probably a better way.
5495
34191dd1 5496(define_expand "movstrqi"
5497 [(match_operand:BLK 0 "general_operand" "")
5498 (match_operand:BLK 1 "general_operand" "")
5499 (match_operand:SI 2 "const_int_operand" "")
5500 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 5501 "TARGET_EITHER"
9c08d1fa 5502 "
cffb2a26 5503 if (TARGET_ARM)
5504 {
5505 if (arm_gen_movstrqi (operands))
5506 DONE;
5507 FAIL;
5508 }
5509 else /* TARGET_THUMB */
5510 {
5511 if ( INTVAL (operands[3]) != 4
5512 || INTVAL (operands[2]) > 48)
5513 FAIL;
5514
5515 thumb_expand_movstrqi (operands);
5516 DONE;
5517 }
5518 "
5519)
5520
2162064c 5521;; Thumb block-move insns
cffb2a26 5522
5523(define_insn "movmem12b"
960f3acf 5524 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5525 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5526 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5527 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5528 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5529 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5530 (set (match_operand:SI 0 "register_operand" "=l")
5531 (plus:SI (match_dup 2) (const_int 12)))
5532 (set (match_operand:SI 1 "register_operand" "=l")
5533 (plus:SI (match_dup 3) (const_int 12)))
5534 (clobber (match_scratch:SI 4 "=&l"))
5535 (clobber (match_scratch:SI 5 "=&l"))
5536 (clobber (match_scratch:SI 6 "=&l"))]
cffb2a26 5537 "TARGET_THUMB"
5538 "* return thumb_output_move_mem_multiple (3, operands);"
5539 [(set_attr "length" "4")
215b30b3 5540 ; This isn't entirely accurate... It loads as well, but in terms of
5541 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5542 (set_attr "type" "store3")]
5543)
5544
5545(define_insn "movmem8b"
960f3acf 5546 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5547 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5548 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5549 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5550 (set (match_operand:SI 0 "register_operand" "=l")
5551 (plus:SI (match_dup 2) (const_int 8)))
5552 (set (match_operand:SI 1 "register_operand" "=l")
5553 (plus:SI (match_dup 3) (const_int 8)))
5554 (clobber (match_scratch:SI 4 "=&l"))
5555 (clobber (match_scratch:SI 5 "=&l"))]
cffb2a26 5556 "TARGET_THUMB"
5557 "* return thumb_output_move_mem_multiple (2, operands);"
5558 [(set_attr "length" "4")
215b30b3 5559 ; This isn't entirely accurate... It loads as well, but in terms of
5560 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5561 (set_attr "type" "store2")]
5562)
5563
9c08d1fa 5564\f
b11cae9e 5565
341940e8 5566;; Compare & branch insns
8d232dc7 5567;; The range calculations are based as follows:
341940e8 5568;; For forward branches, the address calculation returns the address of
5569;; the next instruction. This is 2 beyond the branch instruction.
5570;; For backward branches, the address calculation returns the address of
5571;; the first instruction in this pattern (cmp). This is 2 before the branch
5572;; instruction for the shortest sequence, and 4 before the branch instruction
5573;; if we have to jump around an unconditional branch.
5574;; To the basic branch range the PC offset must be added (this is +4).
5575;; So for forward branches we have
5576;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5577;; And for backward branches we have
5578;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5579;;
5580;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5581;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 5582
aeac46d4 5583(define_expand "cbranchsi4"
5584 [(set (pc) (if_then_else
5585 (match_operator 0 "arm_comparison_operator"
5586 [(match_operand:SI 1 "s_register_operand" "")
5587 (match_operand:SI 2 "nonmemory_operand" "")])
5588 (label_ref (match_operand 3 "" ""))
5589 (pc)))]
5590 "TARGET_THUMB"
5591 "
5592 if (thumb_cmpneg_operand (operands[2], SImode))
5593 {
5594 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5595 operands[3], operands[0]));
5596 DONE;
5597 }
5598 if (!thumb_cmp_operand (operands[2], SImode))
5599 operands[2] = force_reg (SImode, operands[2]);
5600 ")
5601
5602(define_insn "*cbranchsi4_insn"
5603 [(set (pc) (if_then_else
5604 (match_operator 0 "arm_comparison_operator"
5605 [(match_operand:SI 1 "s_register_operand" "l,*h")
5606 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5607 (label_ref (match_operand 3 "" ""))
5608 (pc)))]
cffb2a26 5609 "TARGET_THUMB"
5610 "*
5611 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 5612
cffb2a26 5613 switch (get_attr_length (insn))
5614 {
5615 case 4: return \"b%d0\\t%l3\";
5616 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5617 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5618 }
5619 "
5620 [(set (attr "far_jump")
5621 (if_then_else
5622 (eq_attr "length" "8")
5623 (const_string "yes")
5624 (const_string "no")))
5625 (set (attr "length")
5626 (if_then_else
5627 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5628 (le (minus (match_dup 3) (pc)) (const_int 256)))
5629 (const_int 4)
5630 (if_then_else
5631 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 5632 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5633 (const_int 6)
5634 (const_int 8))))]
5635)
5636
aeac46d4 5637(define_insn "cbranchsi4_scratch"
5638 [(set (pc) (if_then_else
5639 (match_operator 4 "arm_comparison_operator"
5640 [(match_operand:SI 1 "s_register_operand" "l,0")
5641 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5642 (label_ref (match_operand 3 "" ""))
5643 (pc)))
5644 (clobber (match_scratch:SI 0 "=l,l"))]
5645 "TARGET_THUMB"
5646 "*
5647 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5648
5649 switch (get_attr_length (insn))
5650 {
5651 case 4: return \"b%d4\\t%l3\";
5652 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5653 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5654 }
5655 "
5656 [(set (attr "far_jump")
5657 (if_then_else
5658 (eq_attr "length" "8")
5659 (const_string "yes")
5660 (const_string "no")))
5661 (set (attr "length")
5662 (if_then_else
5663 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5664 (le (minus (match_dup 3) (pc)) (const_int 256)))
5665 (const_int 4)
5666 (if_then_else
5667 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5668 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5669 (const_int 6)
5670 (const_int 8))))]
5671)
5672(define_insn "*movsi_cbranchsi4"
5673 [(set (pc)
5674 (if_then_else
5675 (match_operator 3 "arm_comparison_operator"
5676 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5677 (const_int 0)])
5678 (label_ref (match_operand 2 "" ""))
5679 (pc)))
5680 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5681 (match_dup 1))]
5682 "TARGET_THUMB"
5683 "*{
5684 if (which_alternative == 0)
5685 output_asm_insn (\"cmp\t%0, #0\", operands);
5686 else if (which_alternative == 1)
5687 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5688 else
5689 {
5690 output_asm_insn (\"cmp\t%1, #0\", operands);
5691 if (which_alternative == 2)
5692 output_asm_insn (\"mov\t%0, %1\", operands);
5693 else
5694 output_asm_insn (\"str\t%1, %0\", operands);
5695 }
5696 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5697 {
5698 case 4: return \"b%d3\\t%l2\";
5699 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5700 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5701 }
5702 }"
5703 [(set (attr "far_jump")
5704 (if_then_else
5705 (ior (and (gt (symbol_ref ("which_alternative"))
5706 (const_int 1))
5707 (eq_attr "length" "8"))
5708 (eq_attr "length" "10"))
5709 (const_string "yes")
5710 (const_string "no")))
5711 (set (attr "length")
5712 (if_then_else
5713 (le (symbol_ref ("which_alternative"))
5714 (const_int 1))
5715 (if_then_else
5716 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5717 (le (minus (match_dup 2) (pc)) (const_int 256)))
5718 (const_int 4)
5719 (if_then_else
5720 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5721 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5722 (const_int 6)
5723 (const_int 8)))
5724 (if_then_else
5725 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5726 (le (minus (match_dup 2) (pc)) (const_int 256)))
5727 (const_int 6)
5728 (if_then_else
5729 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5730 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5731 (const_int 8)
5732 (const_int 10)))))]
5733)
5734
cffb2a26 5735(define_insn "*negated_cbranchsi4"
5736 [(set (pc)
5737 (if_then_else
aeac46d4 5738 (match_operator 0 "arm_comparison_operator"
5739 [(match_operand:SI 1 "s_register_operand" "l")
5740 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5741 (label_ref (match_operand 3 "" ""))
215b30b3 5742 (pc)))]
cffb2a26 5743 "TARGET_THUMB"
5744 "*
5745 output_asm_insn (\"cmn\\t%1, %2\", operands);
5746 switch (get_attr_length (insn))
5747 {
5748 case 4: return \"b%d0\\t%l3\";
5749 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5750 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5751 }
5752 "
5753 [(set (attr "far_jump")
5754 (if_then_else
5755 (eq_attr "length" "8")
5756 (const_string "yes")
5757 (const_string "no")))
5758 (set (attr "length")
5759 (if_then_else
5760 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 5761 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 5762 (const_int 4)
5763 (if_then_else
341940e8 5764 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5765 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5766 (const_int 6)
5767 (const_int 8))))]
5768)
5769
58d6528b 5770(define_insn "*tbit_cbranch"
5771 [(set (pc)
5772 (if_then_else
5773 (match_operator 0 "equality_operator"
5774 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5775 (const_int 1)
5776 (match_operand:SI 2 "const_int_operand" "i"))
5777 (const_int 0)])
5778 (label_ref (match_operand 3 "" ""))
5779 (pc)))
5780 (clobber (match_scratch:SI 4 "=l"))]
5781 "TARGET_THUMB"
5782 "*
5783 {
5784 rtx op[3];
5785 op[0] = operands[4];
5786 op[1] = operands[1];
5787 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5788
5789 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5790 switch (get_attr_length (insn))
5791 {
5792 case 4: return \"b%d0\\t%l3\";
5793 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5794 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5795 }
5796 }"
5797 [(set (attr "far_jump")
5798 (if_then_else
5799 (eq_attr "length" "8")
5800 (const_string "yes")
5801 (const_string "no")))
5802 (set (attr "length")
5803 (if_then_else
5804 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5805 (le (minus (match_dup 3) (pc)) (const_int 256)))
5806 (const_int 4)
5807 (if_then_else
5808 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5809 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5810 (const_int 6)
5811 (const_int 8))))]
5812)
5813
aeac46d4 5814(define_insn "*tstsi3_cbranch"
58d6528b 5815 [(set (pc)
5816 (if_then_else
aeac46d4 5817 (match_operator 3 "equality_operator"
5818 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5819 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 5820 (const_int 0)])
aeac46d4 5821 (label_ref (match_operand 2 "" ""))
5822 (pc)))]
58d6528b 5823 "TARGET_THUMB"
5824 "*
5825 {
aeac46d4 5826 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 5827 switch (get_attr_length (insn))
5828 {
aeac46d4 5829 case 4: return \"b%d3\\t%l2\";
5830 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5831 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 5832 }
5833 }"
5834 [(set (attr "far_jump")
5835 (if_then_else
5836 (eq_attr "length" "8")
5837 (const_string "yes")
5838 (const_string "no")))
5839 (set (attr "length")
5840 (if_then_else
aeac46d4 5841 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5842 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 5843 (const_int 4)
5844 (if_then_else
aeac46d4 5845 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5846 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 5847 (const_int 6)
5848 (const_int 8))))]
5849)
5850
5851(define_insn "*andsi3_cbranch"
5852 [(set (pc)
5853 (if_then_else
5854 (match_operator 5 "equality_operator"
5855 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5856 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5857 (const_int 0)])
5858 (label_ref (match_operand 4 "" ""))
5859 (pc)))
aeac46d4 5860 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 5861 (and:SI (match_dup 2) (match_dup 3)))
5862 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5863 "TARGET_THUMB"
5864 "*
5865 {
5866 if (which_alternative == 0)
5867 output_asm_insn (\"and\\t%0, %3\", operands);
5868 else if (which_alternative == 1)
5869 {
5870 output_asm_insn (\"and\\t%1, %3\", operands);
5871 output_asm_insn (\"mov\\t%0, %1\", operands);
5872 }
5873 else
5874 {
5875 output_asm_insn (\"and\\t%1, %3\", operands);
5876 output_asm_insn (\"str\\t%1, %0\", operands);
5877 }
5878
5879 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5880 {
5881 case 4: return \"b%d5\\t%l4\";
5882 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5883 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5884 }
5885 }"
5886 [(set (attr "far_jump")
5887 (if_then_else
5888 (ior (and (eq (symbol_ref ("which_alternative"))
5889 (const_int 0))
5890 (eq_attr "length" "8"))
5891 (eq_attr "length" "10"))
5892 (const_string "yes")
5893 (const_string "no")))
5894 (set (attr "length")
5895 (if_then_else
5896 (eq (symbol_ref ("which_alternative"))
5897 (const_int 0))
5898 (if_then_else
5899 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5900 (le (minus (match_dup 4) (pc)) (const_int 256)))
5901 (const_int 4)
5902 (if_then_else
5903 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5904 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5905 (const_int 6)
5906 (const_int 8)))
5907 (if_then_else
5908 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5909 (le (minus (match_dup 4) (pc)) (const_int 256)))
5910 (const_int 6)
5911 (if_then_else
5912 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5913 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5914 (const_int 8)
5915 (const_int 10)))))]
5916)
5917
5918(define_insn "*orrsi3_cbranch_scratch"
5919 [(set (pc)
5920 (if_then_else
5921 (match_operator 4 "equality_operator"
5922 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5923 (match_operand:SI 2 "s_register_operand" "l"))
5924 (const_int 0)])
5925 (label_ref (match_operand 3 "" ""))
5926 (pc)))
5927 (clobber (match_scratch:SI 0 "=l"))]
5928 "TARGET_THUMB"
5929 "*
5930 {
5931 output_asm_insn (\"orr\\t%0, %2\", operands);
5932 switch (get_attr_length (insn))
5933 {
5934 case 4: return \"b%d4\\t%l3\";
5935 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5936 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5937 }
5938 }"
5939 [(set (attr "far_jump")
5940 (if_then_else
5941 (eq_attr "length" "8")
5942 (const_string "yes")
5943 (const_string "no")))
5944 (set (attr "length")
5945 (if_then_else
5946 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5947 (le (minus (match_dup 3) (pc)) (const_int 256)))
5948 (const_int 4)
5949 (if_then_else
5950 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5951 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5952 (const_int 6)
5953 (const_int 8))))]
5954)
5955
5956(define_insn "*orrsi3_cbranch"
5957 [(set (pc)
5958 (if_then_else
5959 (match_operator 5 "equality_operator"
5960 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5961 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5962 (const_int 0)])
5963 (label_ref (match_operand 4 "" ""))
5964 (pc)))
aeac46d4 5965 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 5966 (ior:SI (match_dup 2) (match_dup 3)))
5967 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5968 "TARGET_THUMB"
5969 "*
5970 {
5971 if (which_alternative == 0)
5972 output_asm_insn (\"orr\\t%0, %3\", operands);
5973 else if (which_alternative == 1)
5974 {
5975 output_asm_insn (\"orr\\t%1, %3\", operands);
5976 output_asm_insn (\"mov\\t%0, %1\", operands);
5977 }
5978 else
5979 {
5980 output_asm_insn (\"orr\\t%1, %3\", operands);
5981 output_asm_insn (\"str\\t%1, %0\", operands);
5982 }
5983
5984 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5985 {
5986 case 4: return \"b%d5\\t%l4\";
5987 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5988 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5989 }
5990 }"
5991 [(set (attr "far_jump")
5992 (if_then_else
5993 (ior (and (eq (symbol_ref ("which_alternative"))
5994 (const_int 0))
5995 (eq_attr "length" "8"))
5996 (eq_attr "length" "10"))
5997 (const_string "yes")
5998 (const_string "no")))
5999 (set (attr "length")
6000 (if_then_else
6001 (eq (symbol_ref ("which_alternative"))
6002 (const_int 0))
6003 (if_then_else
6004 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6005 (le (minus (match_dup 4) (pc)) (const_int 256)))
6006 (const_int 4)
6007 (if_then_else
6008 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6009 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6010 (const_int 6)
6011 (const_int 8)))
6012 (if_then_else
6013 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6014 (le (minus (match_dup 4) (pc)) (const_int 256)))
6015 (const_int 6)
6016 (if_then_else
6017 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6018 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6019 (const_int 8)
6020 (const_int 10)))))]
6021)
6022
6023(define_insn "*xorsi3_cbranch_scratch"
6024 [(set (pc)
6025 (if_then_else
6026 (match_operator 4 "equality_operator"
6027 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6028 (match_operand:SI 2 "s_register_operand" "l"))
6029 (const_int 0)])
6030 (label_ref (match_operand 3 "" ""))
6031 (pc)))
6032 (clobber (match_scratch:SI 0 "=l"))]
6033 "TARGET_THUMB"
6034 "*
6035 {
6036 output_asm_insn (\"eor\\t%0, %2\", operands);
6037 switch (get_attr_length (insn))
6038 {
6039 case 4: return \"b%d4\\t%l3\";
6040 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6041 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6042 }
6043 }"
6044 [(set (attr "far_jump")
6045 (if_then_else
6046 (eq_attr "length" "8")
6047 (const_string "yes")
6048 (const_string "no")))
6049 (set (attr "length")
6050 (if_then_else
6051 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6052 (le (minus (match_dup 3) (pc)) (const_int 256)))
6053 (const_int 4)
6054 (if_then_else
6055 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6056 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6057 (const_int 6)
6058 (const_int 8))))]
6059)
6060
6061(define_insn "*xorsi3_cbranch"
6062 [(set (pc)
6063 (if_then_else
6064 (match_operator 5 "equality_operator"
6065 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6066 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6067 (const_int 0)])
6068 (label_ref (match_operand 4 "" ""))
6069 (pc)))
aeac46d4 6070 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6071 (xor:SI (match_dup 2) (match_dup 3)))
6072 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6073 "TARGET_THUMB"
6074 "*
6075 {
6076 if (which_alternative == 0)
6077 output_asm_insn (\"eor\\t%0, %3\", operands);
6078 else if (which_alternative == 1)
6079 {
6080 output_asm_insn (\"eor\\t%1, %3\", operands);
6081 output_asm_insn (\"mov\\t%0, %1\", operands);
6082 }
6083 else
6084 {
6085 output_asm_insn (\"eor\\t%1, %3\", operands);
6086 output_asm_insn (\"str\\t%1, %0\", operands);
6087 }
6088
6089 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6090 {
6091 case 4: return \"b%d5\\t%l4\";
6092 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6093 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6094 }
6095 }"
6096 [(set (attr "far_jump")
6097 (if_then_else
6098 (ior (and (eq (symbol_ref ("which_alternative"))
6099 (const_int 0))
6100 (eq_attr "length" "8"))
6101 (eq_attr "length" "10"))
6102 (const_string "yes")
6103 (const_string "no")))
6104 (set (attr "length")
6105 (if_then_else
6106 (eq (symbol_ref ("which_alternative"))
6107 (const_int 0))
6108 (if_then_else
6109 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6110 (le (minus (match_dup 4) (pc)) (const_int 256)))
6111 (const_int 4)
6112 (if_then_else
6113 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6114 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6115 (const_int 6)
6116 (const_int 8)))
6117 (if_then_else
6118 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6119 (le (minus (match_dup 4) (pc)) (const_int 256)))
6120 (const_int 6)
6121 (if_then_else
6122 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6123 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6124 (const_int 8)
6125 (const_int 10)))))]
6126)
6127
aeac46d4 6128(define_insn "*bicsi3_cbranch_scratch"
6129 [(set (pc)
6130 (if_then_else
6131 (match_operator 4 "equality_operator"
6132 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6133 (match_operand:SI 1 "s_register_operand" "0"))
6134 (const_int 0)])
6135 (label_ref (match_operand 3 "" ""))
6136 (pc)))
6137 (clobber (match_scratch:SI 0 "=l"))]
6138 "TARGET_THUMB"
6139 "*
6140 {
6141 output_asm_insn (\"bic\\t%0, %2\", operands);
6142 switch (get_attr_length (insn))
6143 {
6144 case 4: return \"b%d4\\t%l3\";
6145 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6146 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6147 }
6148 }"
6149 [(set (attr "far_jump")
6150 (if_then_else
6151 (eq_attr "length" "8")
6152 (const_string "yes")
6153 (const_string "no")))
6154 (set (attr "length")
6155 (if_then_else
6156 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6157 (le (minus (match_dup 3) (pc)) (const_int 256)))
6158 (const_int 4)
6159 (if_then_else
6160 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6161 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6162 (const_int 6)
6163 (const_int 8))))]
6164)
6165
6166(define_insn "*bicsi3_cbranch"
6167 [(set (pc)
6168 (if_then_else
6169 (match_operator 5 "equality_operator"
01145ae6 6170 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6171 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 6172 (const_int 0)])
6173 (label_ref (match_operand 4 "" ""))
6174 (pc)))
01145ae6 6175 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 6176 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 6177 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
aeac46d4 6178 "TARGET_THUMB"
6179 "*
6180 {
6181 if (which_alternative == 0)
6182 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 6183 else if (which_alternative <= 2)
aeac46d4 6184 {
6185 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 6186 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6187 conditions again, since we're only testing for equality. */
aeac46d4 6188 output_asm_insn (\"mov\\t%0, %1\", operands);
6189 }
6190 else
6191 {
6192 output_asm_insn (\"bic\\t%1, %3\", operands);
6193 output_asm_insn (\"str\\t%1, %0\", operands);
6194 }
6195
6196 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6197 {
6198 case 4: return \"b%d5\\t%l4\";
6199 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6200 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6201 }
6202 }"
6203 [(set (attr "far_jump")
6204 (if_then_else
6205 (ior (and (eq (symbol_ref ("which_alternative"))
6206 (const_int 0))
6207 (eq_attr "length" "8"))
6208 (eq_attr "length" "10"))
6209 (const_string "yes")
6210 (const_string "no")))
6211 (set (attr "length")
6212 (if_then_else
6213 (eq (symbol_ref ("which_alternative"))
6214 (const_int 0))
6215 (if_then_else
6216 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6217 (le (minus (match_dup 4) (pc)) (const_int 256)))
6218 (const_int 4)
6219 (if_then_else
6220 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6221 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6222 (const_int 6)
6223 (const_int 8)))
6224 (if_then_else
6225 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6226 (le (minus (match_dup 4) (pc)) (const_int 256)))
6227 (const_int 6)
6228 (if_then_else
6229 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6230 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6231 (const_int 8)
6232 (const_int 10)))))]
6233)
6234
203c488f 6235(define_insn "*cbranchne_decr1"
6236 [(set (pc)
6237 (if_then_else (match_operator 3 "equality_operator"
6238 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6239 (const_int 0)])
6240 (label_ref (match_operand 4 "" ""))
6241 (pc)))
aeac46d4 6242 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6243 (plus:SI (match_dup 2) (const_int -1)))
6244 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6245 "TARGET_THUMB"
6246 "*
6247 {
6248 rtx cond[2];
6249 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6250 ? GEU : LTU),
58d6528b 6251 VOIDmode, operands[2], const1_rtx);
203c488f 6252 cond[1] = operands[4];
6253
6254 if (which_alternative == 0)
6255 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6256 else if (which_alternative == 1)
6257 {
6258 /* We must provide an alternative for a hi reg because reload
6259 cannot handle output reloads on a jump instruction, but we
6260 can't subtract into that. Fortunately a mov from lo to hi
6261 does not clobber the condition codes. */
6262 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6263 output_asm_insn (\"mov\\t%0, %1\", operands);
6264 }
6265 else
6266 {
6267 /* Similarly, but the target is memory. */
6268 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6269 output_asm_insn (\"str\\t%1, %0\", operands);
6270 }
6271
6272 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6273 {
6274 case 4:
8aea555f 6275 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6276 return \"\";
6277 case 6:
8aea555f 6278 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6279 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6280 default:
8aea555f 6281 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6282 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6283 }
6284 }
6285 "
6286 [(set (attr "far_jump")
6287 (if_then_else
6288 (ior (and (eq (symbol_ref ("which_alternative"))
6289 (const_int 0))
6290 (eq_attr "length" "8"))
6291 (eq_attr "length" "10"))
6292 (const_string "yes")
6293 (const_string "no")))
6294 (set_attr_alternative "length"
6295 [
6296 ;; Alternative 0
6297 (if_then_else
6298 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6299 (le (minus (match_dup 4) (pc)) (const_int 256)))
6300 (const_int 4)
6301 (if_then_else
6302 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6303 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6304 (const_int 6)
6305 (const_int 8)))
6306 ;; Alternative 1
6307 (if_then_else
6308 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6309 (le (minus (match_dup 4) (pc)) (const_int 256)))
6310 (const_int 6)
6311 (if_then_else
6312 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6313 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6314 (const_int 8)
6315 (const_int 10)))
6316 ;; Alternative 2
6317 (if_then_else
6318 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6319 (le (minus (match_dup 4) (pc)) (const_int 256)))
6320 (const_int 6)
6321 (if_then_else
6322 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6323 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6324 (const_int 8)
6325 (const_int 10)))
6326 ;; Alternative 3
6327 (if_then_else
6328 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6329 (le (minus (match_dup 4) (pc)) (const_int 256)))
6330 (const_int 6)
6331 (if_then_else
6332 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6333 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6334 (const_int 8)
6335 (const_int 10)))])]
6336)
cffb2a26 6337
58d6528b 6338(define_insn "*addsi3_cbranch"
6339 [(set (pc)
6340 (if_then_else
6341 (match_operator 4 "comparison_operator"
6342 [(plus:SI
6343 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6344 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6345 (const_int 0)])
6346 (label_ref (match_operand 5 "" ""))
6347 (pc)))
aeac46d4 6348 (set
6349 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6350 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 6351 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6352 "TARGET_THUMB
6353 && (GET_CODE (operands[4]) == EQ
6354 || GET_CODE (operands[4]) == NE
6355 || GET_CODE (operands[4]) == GE
6356 || GET_CODE (operands[4]) == LT)"
6357 "*
6358 {
6359 rtx cond[3];
6360
6361
6362 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6363 cond[1] = operands[2];
6364 cond[2] = operands[3];
6365
6366 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6367 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6368 else
6369 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6370
6371 if (which_alternative >= 3
6372 && which_alternative < 4)
6373 output_asm_insn (\"mov\\t%0, %1\", operands);
6374 else if (which_alternative >= 4)
6375 output_asm_insn (\"str\\t%1, %0\", operands);
6376
6377 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6378 {
6379 case 4:
6380 return \"b%d4\\t%l5\";
6381 case 6:
6382 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6383 default:
6384 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6385 }
6386 }
6387 "
6388 [(set (attr "far_jump")
6389 (if_then_else
6390 (ior (and (lt (symbol_ref ("which_alternative"))
6391 (const_int 3))
6392 (eq_attr "length" "8"))
6393 (eq_attr "length" "10"))
6394 (const_string "yes")
6395 (const_string "no")))
6396 (set (attr "length")
6397 (if_then_else
6398 (lt (symbol_ref ("which_alternative"))
6399 (const_int 3))
6400 (if_then_else
6401 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6402 (le (minus (match_dup 5) (pc)) (const_int 256)))
6403 (const_int 4)
6404 (if_then_else
6405 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6406 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6407 (const_int 6)
6408 (const_int 8)))
6409 (if_then_else
6410 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6411 (le (minus (match_dup 5) (pc)) (const_int 256)))
6412 (const_int 6)
6413 (if_then_else
6414 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6415 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6416 (const_int 8)
6417 (const_int 10)))))]
6418)
6419
6420(define_insn "*addsi3_cbranch_scratch"
6421 [(set (pc)
6422 (if_then_else
6423 (match_operator 3 "comparison_operator"
6424 [(plus:SI
6425 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6426 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6427 (const_int 0)])
6428 (label_ref (match_operand 4 "" ""))
6429 (pc)))
6430 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6431 "TARGET_THUMB
6432 && (GET_CODE (operands[3]) == EQ
6433 || GET_CODE (operands[3]) == NE
6434 || GET_CODE (operands[3]) == GE
6435 || GET_CODE (operands[3]) == LT)"
6436 "*
6437 {
6438 switch (which_alternative)
6439 {
6440 case 0:
6441 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6442 break;
6443 case 1:
6444 output_asm_insn (\"cmn\t%1, %2\", operands);
6445 break;
6446 case 3:
6447 output_asm_insn (\"add\t%0, %1, %2\", operands);
6448 break;
6449 case 4:
6450 output_asm_insn (\"add\t%0, %0, %2\", operands);
6451 break;
6452 }
6453
6454 switch (get_attr_length (insn))
6455 {
6456 case 4:
6457 return \"b%d3\\t%l4\";
6458 case 6:
6459 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6460 default:
6461 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6462 }
6463 }
6464 "
6465 [(set (attr "far_jump")
6466 (if_then_else
6467 (eq_attr "length" "8")
6468 (const_string "yes")
6469 (const_string "no")))
6470 (set (attr "length")
6471 (if_then_else
6472 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6473 (le (minus (match_dup 4) (pc)) (const_int 256)))
6474 (const_int 4)
6475 (if_then_else
6476 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6477 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6478 (const_int 6)
6479 (const_int 8))))]
6480)
6481
6482(define_insn "*subsi3_cbranch"
6483 [(set (pc)
6484 (if_then_else
6485 (match_operator 4 "comparison_operator"
6486 [(minus:SI
6487 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6488 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6489 (const_int 0)])
6490 (label_ref (match_operand 5 "" ""))
6491 (pc)))
aeac46d4 6492 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6493 (minus:SI (match_dup 2) (match_dup 3)))
6494 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6495 "TARGET_THUMB
6496 && (GET_CODE (operands[4]) == EQ
6497 || GET_CODE (operands[4]) == NE
6498 || GET_CODE (operands[4]) == GE
6499 || GET_CODE (operands[4]) == LT)"
6500 "*
6501 {
6502 if (which_alternative == 0)
6503 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6504 else if (which_alternative == 1)
6505 {
6506 /* We must provide an alternative for a hi reg because reload
6507 cannot handle output reloads on a jump instruction, but we
6508 can't subtract into that. Fortunately a mov from lo to hi
6509 does not clobber the condition codes. */
6510 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6511 output_asm_insn (\"mov\\t%0, %1\", operands);
6512 }
6513 else
6514 {
6515 /* Similarly, but the target is memory. */
6516 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6517 output_asm_insn (\"str\\t%1, %0\", operands);
6518 }
6519
6520 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6521 {
6522 case 4:
6523 return \"b%d4\\t%l5\";
6524 case 6:
6525 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6526 default:
6527 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6528 }
6529 }
6530 "
6531 [(set (attr "far_jump")
6532 (if_then_else
6533 (ior (and (eq (symbol_ref ("which_alternative"))
6534 (const_int 0))
6535 (eq_attr "length" "8"))
6536 (eq_attr "length" "10"))
6537 (const_string "yes")
6538 (const_string "no")))
6539 (set (attr "length")
6540 (if_then_else
6541 (eq (symbol_ref ("which_alternative"))
6542 (const_int 0))
6543 (if_then_else
6544 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6545 (le (minus (match_dup 5) (pc)) (const_int 256)))
6546 (const_int 4)
6547 (if_then_else
6548 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6549 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6550 (const_int 6)
6551 (const_int 8)))
6552 (if_then_else
6553 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6554 (le (minus (match_dup 5) (pc)) (const_int 256)))
6555 (const_int 6)
6556 (if_then_else
6557 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6558 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6559 (const_int 8)
6560 (const_int 10)))))]
6561)
6562
6563(define_insn "*subsi3_cbranch_scratch"
6564 [(set (pc)
6565 (if_then_else
6566 (match_operator 0 "arm_comparison_operator"
6567 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6568 (match_operand:SI 2 "nonmemory_operand" "l"))
6569 (const_int 0)])
6570 (label_ref (match_operand 3 "" ""))
6571 (pc)))]
6572 "TARGET_THUMB
6573 && (GET_CODE (operands[0]) == EQ
6574 || GET_CODE (operands[0]) == NE
6575 || GET_CODE (operands[0]) == GE
6576 || GET_CODE (operands[0]) == LT)"
6577 "*
6578 output_asm_insn (\"cmp\\t%1, %2\", operands);
6579 switch (get_attr_length (insn))
6580 {
6581 case 4: return \"b%d0\\t%l3\";
6582 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6583 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6584 }
6585 "
6586 [(set (attr "far_jump")
6587 (if_then_else
6588 (eq_attr "length" "8")
6589 (const_string "yes")
6590 (const_string "no")))
6591 (set (attr "length")
6592 (if_then_else
6593 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6594 (le (minus (match_dup 3) (pc)) (const_int 256)))
6595 (const_int 4)
6596 (if_then_else
6597 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6598 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6599 (const_int 6)
6600 (const_int 8))))]
6601)
6602
9c08d1fa 6603;; Comparison and test insns
6604
6605(define_expand "cmpsi"
aea4c774 6606 [(match_operand:SI 0 "s_register_operand" "")
6607 (match_operand:SI 1 "arm_add_operand" "")]
cffb2a26 6608 "TARGET_ARM"
6609 "{
6610 arm_compare_op0 = operands[0];
6611 arm_compare_op1 = operands[1];
6612 DONE;
6613 }"
6614)
b11cae9e 6615
9c08d1fa 6616(define_expand "cmpsf"
aea4c774 6617 [(match_operand:SF 0 "s_register_operand" "")
a2cd141b 6618 (match_operand:SF 1 "arm_float_compare_operand" "")]
6619 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6620 "
9c08d1fa 6621 arm_compare_op0 = operands[0];
6622 arm_compare_op1 = operands[1];
9c08d1fa 6623 DONE;
215b30b3 6624 "
6625)
b11cae9e 6626
9c08d1fa 6627(define_expand "cmpdf"
aea4c774 6628 [(match_operand:DF 0 "s_register_operand" "")
a2cd141b 6629 (match_operand:DF 1 "arm_float_compare_operand" "")]
6630 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6631 "
9c08d1fa 6632 arm_compare_op0 = operands[0];
6633 arm_compare_op1 = operands[1];
9c08d1fa 6634 DONE;
215b30b3 6635 "
6636)
b11cae9e 6637
cffb2a26 6638(define_insn "*arm_cmpsi_insn"
bd5b4116 6639 [(set (reg:CC CC_REGNUM)
aea4c774 6640 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 6641 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6642 "TARGET_ARM"
5565501b 6643 "@
aea4c774 6644 cmp%?\\t%0, %1
6645 cmn%?\\t%0, #%n1"
cffb2a26 6646 [(set_attr "conds" "set")]
6647)
b11cae9e 6648
aea4c774 6649(define_insn "*cmpsi_shiftsi"
bd5b4116 6650 [(set (reg:CC CC_REGNUM)
cffb2a26 6651 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6652 (match_operator:SI 3 "shift_operator"
aea4c774 6653 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 6654 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6655 "TARGET_ARM"
aea4c774 6656 "cmp%?\\t%0, %1%S3"
344495ea 6657 [(set_attr "conds" "set")
331beb1a 6658 (set_attr "shift" "1")
a2cd141b 6659 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6660 (const_string "alu_shift")
6661 (const_string "alu_shift_reg")))]
0d66636f 6662)
b11cae9e 6663
aea4c774 6664(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6665 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6666 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6667 [(match_operand:SI 1 "s_register_operand" "r")
6668 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6669 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6670 "TARGET_ARM"
aea4c774 6671 "cmp%?\\t%0, %1%S3"
344495ea 6672 [(set_attr "conds" "set")
331beb1a 6673 (set_attr "shift" "1")
a2cd141b 6674 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6675 (const_string "alu_shift")
6676 (const_string "alu_shift_reg")))]
0d66636f 6677)
b11cae9e 6678
f7fbdd4a 6679(define_insn "*cmpsi_neg_shiftsi"
bd5b4116 6680 [(set (reg:CC CC_REGNUM)
aea4c774 6681 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6682 (neg:SI (match_operator:SI 3 "shift_operator"
6683 [(match_operand:SI 1 "s_register_operand" "r")
6684 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
cffb2a26 6685 "TARGET_ARM"
aea4c774 6686 "cmn%?\\t%0, %1%S3"
344495ea 6687 [(set_attr "conds" "set")
331beb1a 6688 (set_attr "shift" "1")
a2cd141b 6689 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6690 (const_string "alu_shift")
6691 (const_string "alu_shift_reg")))]
0d66636f 6692)
b11cae9e 6693
7d57ec45 6694;; Cirrus SF compare instruction
6695(define_insn "*cirrus_cmpsf"
6696 [(set (reg:CCFP CC_REGNUM)
6697 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6698 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 6699 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6700 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 6701 [(set_attr "type" "mav_farith")
7d57ec45 6702 (set_attr "cirrus" "compare")]
6703)
6704
6705;; Cirrus DF compare instruction
6706(define_insn "*cirrus_cmpdf"
6707 [(set (reg:CCFP CC_REGNUM)
6708 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6709 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 6710 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6711 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 6712 [(set_attr "type" "mav_farith")
7d57ec45 6713 (set_attr "cirrus" "compare")]
6714)
6715
6716;; Cirrus DI compare instruction
6717(define_expand "cmpdi"
6718 [(match_operand:DI 0 "cirrus_fp_register" "")
6719 (match_operand:DI 1 "cirrus_fp_register" "")]
a2cd141b 6720 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6721 "{
6722 arm_compare_op0 = operands[0];
6723 arm_compare_op1 = operands[1];
6724 DONE;
6725 }")
6726
6727(define_insn "*cirrus_cmpdi"
6728 [(set (reg:CC CC_REGNUM)
6729 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6730 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 6731 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6732 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 6733 [(set_attr "type" "mav_farith")
7d57ec45 6734 (set_attr "cirrus" "compare")]
6735)
6736
9c08d1fa 6737; This insn allows redundant compares to be removed by cse, nothing should
6738; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6739; is deleted later on. The match_dup will match the mode here, so that
6740; mode changes of the condition codes aren't lost by this even though we don't
6741; specify what they are.
6742
8a18b90c 6743(define_insn "*deleted_compare"
9c08d1fa 6744 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
cffb2a26 6745 "TARGET_ARM"
40dbec34 6746 "\\t%@ deleted compare"
cffb2a26 6747 [(set_attr "conds" "set")
6748 (set_attr "length" "0")]
6749)
9c08d1fa 6750
6751\f
6752;; Conditional branch insns
6753
6754(define_expand "beq"
6755 [(set (pc)
6756 (if_then_else (eq (match_dup 1) (const_int 0))
6757 (label_ref (match_operand 0 "" ""))
6758 (pc)))]
cffb2a26 6759 "TARGET_ARM"
6760 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6761)
5c951228 6762
9c08d1fa 6763(define_expand "bne"
6764 [(set (pc)
6765 (if_then_else (ne (match_dup 1) (const_int 0))
6766 (label_ref (match_operand 0 "" ""))
6767 (pc)))]
cffb2a26 6768 "TARGET_ARM"
6769 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6770)
5c951228 6771
9c08d1fa 6772(define_expand "bgt"
6773 [(set (pc)
6774 (if_then_else (gt (match_dup 1) (const_int 0))
6775 (label_ref (match_operand 0 "" ""))
6776 (pc)))]
cffb2a26 6777 "TARGET_ARM"
6778 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6779)
5c951228 6780
9c08d1fa 6781(define_expand "ble"
6782 [(set (pc)
6783 (if_then_else (le (match_dup 1) (const_int 0))
6784 (label_ref (match_operand 0 "" ""))
6785 (pc)))]
cffb2a26 6786 "TARGET_ARM"
6787 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6788)
5c951228 6789
9c08d1fa 6790(define_expand "bge"
6791 [(set (pc)
6792 (if_then_else (ge (match_dup 1) (const_int 0))
6793 (label_ref (match_operand 0 "" ""))
6794 (pc)))]
cffb2a26 6795 "TARGET_ARM"
6796 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6797)
5c951228 6798
9c08d1fa 6799(define_expand "blt"
6800 [(set (pc)
6801 (if_then_else (lt (match_dup 1) (const_int 0))
6802 (label_ref (match_operand 0 "" ""))
6803 (pc)))]
cffb2a26 6804 "TARGET_ARM"
6805 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6806)
5c951228 6807
9c08d1fa 6808(define_expand "bgtu"
6809 [(set (pc)
6810 (if_then_else (gtu (match_dup 1) (const_int 0))
6811 (label_ref (match_operand 0 "" ""))
6812 (pc)))]
cffb2a26 6813 "TARGET_ARM"
6814 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6815)
5c951228 6816
9c08d1fa 6817(define_expand "bleu"
b11cae9e 6818 [(set (pc)
9c08d1fa 6819 (if_then_else (leu (match_dup 1) (const_int 0))
6820 (label_ref (match_operand 0 "" ""))
6821 (pc)))]
cffb2a26 6822 "TARGET_ARM"
6823 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6824)
b11cae9e 6825
9c08d1fa 6826(define_expand "bgeu"
b11cae9e 6827 [(set (pc)
9c08d1fa 6828 (if_then_else (geu (match_dup 1) (const_int 0))
6829 (label_ref (match_operand 0 "" ""))
6830 (pc)))]
cffb2a26 6831 "TARGET_ARM"
6832 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6833)
b11cae9e 6834
9c08d1fa 6835(define_expand "bltu"
6836 [(set (pc)
6837 (if_then_else (ltu (match_dup 1) (const_int 0))
6838 (label_ref (match_operand 0 "" ""))
6839 (pc)))]
cffb2a26 6840 "TARGET_ARM"
6841 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6842)
b11cae9e 6843
8fa3ba89 6844(define_expand "bunordered"
6845 [(set (pc)
6846 (if_then_else (unordered (match_dup 1) (const_int 0))
6847 (label_ref (match_operand 0 "" ""))
6848 (pc)))]
a2cd141b 6849 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6850 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6851 arm_compare_op1);"
6852)
6853
6854(define_expand "bordered"
6855 [(set (pc)
6856 (if_then_else (ordered (match_dup 1) (const_int 0))
6857 (label_ref (match_operand 0 "" ""))
6858 (pc)))]
a2cd141b 6859 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6860 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6861 arm_compare_op1);"
6862)
6863
6864(define_expand "bungt"
6865 [(set (pc)
6866 (if_then_else (ungt (match_dup 1) (const_int 0))
6867 (label_ref (match_operand 0 "" ""))
6868 (pc)))]
a2cd141b 6869 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6870 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6871)
6872
6873(define_expand "bunlt"
6874 [(set (pc)
6875 (if_then_else (unlt (match_dup 1) (const_int 0))
6876 (label_ref (match_operand 0 "" ""))
6877 (pc)))]
a2cd141b 6878 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6879 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6880)
6881
6882(define_expand "bunge"
6883 [(set (pc)
6884 (if_then_else (unge (match_dup 1) (const_int 0))
6885 (label_ref (match_operand 0 "" ""))
6886 (pc)))]
a2cd141b 6887 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6888 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6889)
6890
6891(define_expand "bunle"
6892 [(set (pc)
6893 (if_then_else (unle (match_dup 1) (const_int 0))
6894 (label_ref (match_operand 0 "" ""))
6895 (pc)))]
a2cd141b 6896 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6897 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6898)
6899
6900;; The following two patterns need two branch instructions, since there is
6901;; no single instruction that will handle all cases.
6902(define_expand "buneq"
6903 [(set (pc)
6904 (if_then_else (uneq (match_dup 1) (const_int 0))
6905 (label_ref (match_operand 0 "" ""))
6906 (pc)))]
a2cd141b 6907 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6908 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6909)
6910
6911(define_expand "bltgt"
6912 [(set (pc)
6913 (if_then_else (ltgt (match_dup 1) (const_int 0))
6914 (label_ref (match_operand 0 "" ""))
6915 (pc)))]
a2cd141b 6916 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6917 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6918)
6919
6920;;
6921;; Patterns to match conditional branch insns.
6922;;
6923
6924; Special pattern to match UNEQ.
6925(define_insn "*arm_buneq"
6926 [(set (pc)
6927 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6928 (label_ref (match_operand 0 "" ""))
6929 (pc)))]
a2cd141b 6930 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6931 "*
6932 if (arm_ccfsm_state != 0)
6933 abort ();
6934
278b301d 6935 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 6936 "
6937 [(set_attr "conds" "jump_clob")
6938 (set_attr "length" "8")]
6939)
6940
6941; Special pattern to match LTGT.
6942(define_insn "*arm_bltgt"
6943 [(set (pc)
6944 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6945 (label_ref (match_operand 0 "" ""))
6946 (pc)))]
a2cd141b 6947 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6948 "*
6949 if (arm_ccfsm_state != 0)
6950 abort ();
6951
278b301d 6952 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 6953 "
6954 [(set_attr "conds" "jump_clob")
6955 (set_attr "length" "8")]
6956)
9c08d1fa 6957
cffb2a26 6958(define_insn "*arm_cond_branch"
9c08d1fa 6959 [(set (pc)
8fa3ba89 6960 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 6961 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 6962 (label_ref (match_operand 0 "" ""))
6963 (pc)))]
cffb2a26 6964 "TARGET_ARM"
d75350ce 6965 "*
9c08d1fa 6966 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 6967 {
6968 arm_ccfsm_state += 2;
6969 return \"\";
6970 }
e2348bcb 6971 return \"b%d1\\t%l0\";
cffb2a26 6972 "
a2cd141b 6973 [(set_attr "conds" "use")
6974 (set_attr "type" "branch")]
cffb2a26 6975)
d75350ce 6976
8fa3ba89 6977; Special pattern to match reversed UNEQ.
6978(define_insn "*arm_buneq_reversed"
6979 [(set (pc)
6980 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6981 (pc)
6982 (label_ref (match_operand 0 "" ""))))]
a2cd141b 6983 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 6984 "*
6985 if (arm_ccfsm_state != 0)
6986 abort ();
6987
278b301d 6988 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 6989 "
6990 [(set_attr "conds" "jump_clob")
6991 (set_attr "length" "8")]
6992)
6993
6994; Special pattern to match reversed LTGT.
6995(define_insn "*arm_bltgt_reversed"
6996 [(set (pc)
6997 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6998 (pc)
6999 (label_ref (match_operand 0 "" ""))))]
a2cd141b 7000 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7001 "*
7002 if (arm_ccfsm_state != 0)
7003 abort ();
7004
278b301d 7005 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7006 "
7007 [(set_attr "conds" "jump_clob")
7008 (set_attr "length" "8")]
7009)
7010
cffb2a26 7011(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7012 [(set (pc)
8fa3ba89 7013 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7014 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7015 (pc)
7016 (label_ref (match_operand 0 "" ""))))]
cffb2a26 7017 "TARGET_ARM"
d75350ce 7018 "*
9c08d1fa 7019 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7020 {
7021 arm_ccfsm_state += 2;
7022 return \"\";
7023 }
e2348bcb 7024 return \"b%D1\\t%l0\";
cffb2a26 7025 "
a2cd141b 7026 [(set_attr "conds" "use")
7027 (set_attr "type" "branch")]
cffb2a26 7028)
7029
b11cae9e 7030\f
9c08d1fa 7031
7032; scc insns
7033
7034(define_expand "seq"
7db9af5d 7035 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7036 (eq:SI (match_dup 1) (const_int 0)))]
cffb2a26 7037 "TARGET_ARM"
7038 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7039)
9c08d1fa 7040
7041(define_expand "sne"
7db9af5d 7042 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7043 (ne:SI (match_dup 1) (const_int 0)))]
cffb2a26 7044 "TARGET_ARM"
7045 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7046)
9c08d1fa 7047
7048(define_expand "sgt"
7db9af5d 7049 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7050 (gt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7051 "TARGET_ARM"
7052 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7053)
9c08d1fa 7054
7055(define_expand "sle"
7db9af5d 7056 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7057 (le:SI (match_dup 1) (const_int 0)))]
cffb2a26 7058 "TARGET_ARM"
7059 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7060)
9c08d1fa 7061
7062(define_expand "sge"
7db9af5d 7063 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7064 (ge:SI (match_dup 1) (const_int 0)))]
cffb2a26 7065 "TARGET_ARM"
7066 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7067)
9c08d1fa 7068
7069(define_expand "slt"
7db9af5d 7070 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7071 (lt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7072 "TARGET_ARM"
7073 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7074)
9c08d1fa 7075
7076(define_expand "sgtu"
7db9af5d 7077 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7078 (gtu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7079 "TARGET_ARM"
7080 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7081)
9c08d1fa 7082
7083(define_expand "sleu"
7db9af5d 7084 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7085 (leu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7086 "TARGET_ARM"
7087 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7088)
9c08d1fa 7089
7090(define_expand "sgeu"
7db9af5d 7091 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7092 (geu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7093 "TARGET_ARM"
7094 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7095)
9c08d1fa 7096
7097(define_expand "sltu"
7db9af5d 7098 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7099 (ltu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7100 "TARGET_ARM"
7101 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7102)
9c08d1fa 7103
8fa3ba89 7104(define_expand "sunordered"
7db9af5d 7105 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7106 (unordered:SI (match_dup 1) (const_int 0)))]
a2cd141b 7107 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7108 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7109 arm_compare_op1);"
7110)
7111
7112(define_expand "sordered"
7db9af5d 7113 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7114 (ordered:SI (match_dup 1) (const_int 0)))]
a2cd141b 7115 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7116 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7117 arm_compare_op1);"
7118)
7119
7120(define_expand "sungt"
7db9af5d 7121 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7122 (ungt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7123 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7124 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7125 arm_compare_op1);"
7126)
7127
7128(define_expand "sunge"
7db9af5d 7129 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7130 (unge:SI (match_dup 1) (const_int 0)))]
a2cd141b 7131 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7132 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7133 arm_compare_op1);"
7134)
7135
7136(define_expand "sunlt"
7db9af5d 7137 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7138 (unlt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7139 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7140 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7141 arm_compare_op1);"
7142)
7143
7144(define_expand "sunle"
7db9af5d 7145 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7146 (unle:SI (match_dup 1) (const_int 0)))]
a2cd141b 7147 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7148 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7149 arm_compare_op1);"
7150)
7151
7152;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7153;;; simple ARM instructions.
7154;
7155; (define_expand "suneq"
7db9af5d 7156; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7157; (uneq:SI (match_dup 1) (const_int 0)))]
a2cd141b 7158; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7159; "abort ();"
7160; )
7161;
7162; (define_expand "sltgt"
7db9af5d 7163; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7164; (ltgt:SI (match_dup 1) (const_int 0)))]
a2cd141b 7165; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
8fa3ba89 7166; "abort ();"
7167; )
7168
f7fbdd4a 7169(define_insn "*mov_scc"
9c08d1fa 7170 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7171 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7172 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7173 "TARGET_ARM"
4d61e570 7174 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7175 [(set_attr "conds" "use")
7176 (set_attr "length" "8")]
7177)
9c08d1fa 7178
f7fbdd4a 7179(define_insn "*mov_negscc"
9c08d1fa 7180 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7181 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7182 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7183 "TARGET_ARM"
4d61e570 7184 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7185 [(set_attr "conds" "use")
7186 (set_attr "length" "8")]
7187)
9c08d1fa 7188
f7fbdd4a 7189(define_insn "*mov_notscc"
9c08d1fa 7190 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7191 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7192 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7193 "TARGET_ARM"
4d61e570 7194 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7195 [(set_attr "conds" "use")
7196 (set_attr "length" "8")]
7197)
9c08d1fa 7198
7199\f
39b5e676 7200;; Conditional move insns
7201
7202(define_expand "movsicc"
8a18b90c 7203 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7204 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7205 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7206 (match_operand:SI 3 "arm_not_operand" "")))]
cffb2a26 7207 "TARGET_ARM"
39b5e676 7208 "
215b30b3 7209 {
7210 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7211 rtx ccreg;
7212
7213 if (code == UNEQ || code == LTGT)
7214 FAIL;
39b5e676 7215
278b301d 7216 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7217 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7218 }"
7219)
39b5e676 7220
7221(define_expand "movsfcc"
8a18b90c 7222 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7223 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7224 (match_operand:SF 2 "s_register_operand" "")
7225 (match_operand:SF 3 "nonmemory_operand" "")))]
cffb2a26 7226 "TARGET_ARM"
39b5e676 7227 "
215b30b3 7228 {
7229 enum rtx_code code = GET_CODE (operands[1]);
7230 rtx ccreg;
f082f1c4 7231
278b301d 7232 if (code == UNEQ || code == LTGT)
7233 FAIL;
7234
215b30b3 7235 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7236 Otherwise, ensure it is a valid FP add operand */
7237 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7238 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7239 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7240
215b30b3 7241 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7242 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7243 }"
7244)
39b5e676 7245
7246(define_expand "movdfcc"
8a18b90c 7247 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7248 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7249 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7250 (match_operand:DF 3 "arm_float_add_operand" "")))]
7251 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 7252 "
215b30b3 7253 {
7254 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7255 rtx ccreg;
39b5e676 7256
278b301d 7257 if (code == UNEQ || code == LTGT)
7258 FAIL;
7259
7260 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7261 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7262 }"
7263)
39b5e676 7264
7265(define_insn "*movsicc_insn"
f082f1c4 7266 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7267 (if_then_else:SI
8fa3ba89 7268 (match_operator 3 "arm_comparison_operator"
8a18b90c 7269 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7270 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7271 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7272 "TARGET_ARM"
39b5e676 7273 "@
8a18b90c 7274 mov%D3\\t%0, %2
7275 mvn%D3\\t%0, #%B2
f082f1c4 7276 mov%d3\\t%0, %1
7277 mvn%d3\\t%0, #%B1
8a18b90c 7278 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7279 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7280 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7281 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7282 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 7283 (set_attr "conds" "use")]
7284)
39b5e676 7285
39b5e676 7286(define_insn "*movsfcc_soft_insn"
f082f1c4 7287 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7288 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7289 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7290 (match_operand:SF 1 "s_register_operand" "0,r")
7291 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7292 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7293 "@
7294 mov%D3\\t%0, %2
7295 mov%d3\\t%0, %1"
8fa3ba89 7296 [(set_attr "conds" "use")]
7297)
39b5e676 7298
39b5e676 7299\f
9c08d1fa 7300;; Jump and linkage insns
7301
cffb2a26 7302(define_expand "jump"
9c08d1fa 7303 [(set (pc)
7304 (label_ref (match_operand 0 "" "")))]
cffb2a26 7305 "TARGET_EITHER"
9c08d1fa 7306 ""
cffb2a26 7307)
7308
7309(define_insn "*arm_jump"
7310 [(set (pc)
7311 (label_ref (match_operand 0 "" "")))]
7312 "TARGET_ARM"
9c08d1fa 7313 "*
0d66636f 7314 {
7315 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7316 {
7317 arm_ccfsm_state += 2;
7318 return \"\";
7319 }
7320 return \"b%?\\t%l0\";
7321 }
7322 "
7323 [(set_attr "predicable" "yes")]
7324)
9c08d1fa 7325
cffb2a26 7326(define_insn "*thumb_jump"
7327 [(set (pc)
7328 (label_ref (match_operand 0 "" "")))]
7329 "TARGET_THUMB"
7330 "*
7331 if (get_attr_length (insn) == 2)
7332 return \"b\\t%l0\";
7333 return \"bl\\t%l0\\t%@ far jump\";
7334 "
7335 [(set (attr "far_jump")
7336 (if_then_else
7337 (eq_attr "length" "4")
7338 (const_string "yes")
7339 (const_string "no")))
7340 (set (attr "length")
7341 (if_then_else
911ed8af 7342 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7343 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7344 (const_int 2)
7345 (const_int 4)))]
7346)
7347
d3373b54 7348(define_expand "call"
7349 [(parallel [(call (match_operand 0 "memory_operand" "")
7350 (match_operand 1 "general_operand" ""))
cffb2a26 7351 (use (match_operand 2 "" ""))
bd5b4116 7352 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7353 "TARGET_EITHER"
6c4c2133 7354 "
7355 {
78fe751b 7356 rtx callee;
bbe777ea 7357
bbe777ea 7358 /* In an untyped call, we can get NULL for operand 2. */
7359 if (operands[2] == NULL_RTX)
7360 operands[2] = const0_rtx;
7361
78fe751b 7362 /* This is to decide if we should generate indirect calls by loading the
7363 32 bit address of the callee into a register before performing the
7364 branch and link. operand[2] encodes the long_call/short_call
7365 attribute of the function being called. This attribute is set whenever
7366 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7367 is used, and the short_call attribute can also be set if function is
7368 declared as static or if it has already been defined in the current
7369 compilation unit. See arm.c and arm.h for info about this. The third
7370 parameter to arm_is_longcall_p is used to tell it which pattern
7371 invoked it. */
7372 callee = XEXP (operands[0], 0);
7373
bbe777ea 7374 if (GET_CODE (callee) != REG
7375 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7376 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6c4c2133 7377 }"
7378)
d3373b54 7379
f7fbdd4a 7380(define_insn "*call_reg"
d3373b54 7381 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7382 (match_operand 1 "" ""))
7383 (use (match_operand 2 "" ""))
bd5b4116 7384 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7385 "TARGET_ARM"
9c08d1fa 7386 "*
5565501b 7387 return output_call (operands);
cffb2a26 7388 "
7389 ;; length is worst case, normally it is only two
7390 [(set_attr "length" "12")
7391 (set_attr "type" "call")]
7392)
9c08d1fa 7393
f7fbdd4a 7394(define_insn "*call_mem"
6c4c2133 7395 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
cffb2a26 7396 (match_operand 1 "" ""))
7397 (use (match_operand 2 "" ""))
bd5b4116 7398 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7399 "TARGET_ARM"
9c08d1fa 7400 "*
5565501b 7401 return output_call_mem (operands);
cffb2a26 7402 "
7403 [(set_attr "length" "12")
7404 (set_attr "type" "call")]
7405)
7406
7407(define_insn "*call_indirect"
7408 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7409 (match_operand 1 "" ""))
7410 (use (match_operand 2 "" ""))
bd5b4116 7411 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7412 "TARGET_THUMB"
7413 "*
7414 {
7415 if (TARGET_CALLER_INTERWORKING)
7416 return \"bl\\t%__interwork_call_via_%0\";
7417 else
7418 return \"bl\\t%__call_via_%0\";
7419 }"
7420 [(set_attr "type" "call")]
7421)
7422
7423(define_insn "*call_value_indirect"
27ed6835 7424 [(set (match_operand 0 "" "")
cffb2a26 7425 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7426 (match_operand 2 "" "")))
7427 (use (match_operand 3 "" ""))
bd5b4116 7428 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7429 "TARGET_THUMB"
7430 "*
7431 {
7432 if (TARGET_CALLER_INTERWORKING)
7433 return \"bl\\t%__interwork_call_via_%1\";
7434 else
7435 return \"bl\\t%__call_via_%1\";
7436 }"
7437 [(set_attr "type" "call")]
7438)
9c08d1fa 7439
d3373b54 7440(define_expand "call_value"
e0698af7 7441 [(parallel [(set (match_operand 0 "" "")
7442 (call (match_operand 1 "memory_operand" "")
7443 (match_operand 2 "general_operand" "")))
cffb2a26 7444 (use (match_operand 3 "" ""))
bd5b4116 7445 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7446 "TARGET_EITHER"
6c4c2133 7447 "
7448 {
bbe777ea 7449 rtx callee = XEXP (operands[1], 0);
7450
7451 /* In an untyped call, we can get NULL for operand 2. */
7452 if (operands[3] == 0)
7453 operands[3] = const0_rtx;
7454
7455 /* See the comment in define_expand \"call\". */
7456 if (GET_CODE (callee) != REG
7457 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
78fe751b 7458 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6c4c2133 7459 }"
7460)
d3373b54 7461
f7fbdd4a 7462(define_insn "*call_value_reg"
27ed6835 7463 [(set (match_operand 0 "" "")
755eb2b4 7464 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7465 (match_operand 2 "" "")))
bbe777ea 7466 (use (match_operand 3 "" ""))
bd5b4116 7467 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7468 "TARGET_ARM"
9c08d1fa 7469 "*
215b30b3 7470 return output_call (&operands[1]);
cffb2a26 7471 "
7472 [(set_attr "length" "12")
7473 (set_attr "type" "call")]
7474)
9c08d1fa 7475
f7fbdd4a 7476(define_insn "*call_value_mem"
27ed6835 7477 [(set (match_operand 0 "" "")
755eb2b4 7478 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
cffb2a26 7479 (match_operand 2 "" "")))
bbe777ea 7480 (use (match_operand 3 "" ""))
bd5b4116 7481 (clobber (reg:SI LR_REGNUM))]
215b30b3 7482 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7483 "*
215b30b3 7484 return output_call_mem (&operands[1]);
cffb2a26 7485 "
7486 [(set_attr "length" "12")
7487 (set_attr "type" "call")]
7488)
9c08d1fa 7489
7490;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7491;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7492
f7fbdd4a 7493(define_insn "*call_symbol"
27ed6835 7494 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7495 (match_operand 1 "" ""))
bbe777ea 7496 (use (match_operand 2 "" ""))
bd5b4116 7497 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7498 "TARGET_ARM
7499 && (GET_CODE (operands[0]) == SYMBOL_REF)
215b30b3 7500 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6ebaa29d 7501 "*
7502 {
55c1e470 7503 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7504 }"
cffb2a26 7505 [(set_attr "type" "call")]
7506)
9c08d1fa 7507
f7fbdd4a 7508(define_insn "*call_value_symbol"
27ed6835 7509 [(set (match_operand 0 "s_register_operand" "")
7510 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7511 (match_operand:SI 2 "" "")))
bbe777ea 7512 (use (match_operand 3 "" ""))
bd5b4116 7513 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7514 "TARGET_ARM
7515 && (GET_CODE (operands[1]) == SYMBOL_REF)
215b30b3 7516 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6ebaa29d 7517 "*
7518 {
55c1e470 7519 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7520 }"
cffb2a26 7521 [(set_attr "type" "call")]
7522)
7523
7524(define_insn "*call_insn"
27ed6835 7525 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7526 (match_operand:SI 1 "" ""))
7527 (use (match_operand 2 "" ""))
bd5b4116 7528 (clobber (reg:SI LR_REGNUM))]
1c494086 7529 "TARGET_THUMB
1675c6e9 7530 && GET_CODE (operands[0]) == SYMBOL_REF
7531 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
cffb2a26 7532 "bl\\t%a0"
7533 [(set_attr "length" "4")
7534 (set_attr "type" "call")]
7535)
7536
7537(define_insn "*call_value_insn"
27ed6835 7538 [(set (match_operand 0 "register_operand" "")
7539 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 7540 (match_operand 2 "" "")))
7541 (use (match_operand 3 "" ""))
bd5b4116 7542 (clobber (reg:SI LR_REGNUM))]
1c494086 7543 "TARGET_THUMB
1675c6e9 7544 && GET_CODE (operands[1]) == SYMBOL_REF
7545 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
cffb2a26 7546 "bl\\t%a1"
7547 [(set_attr "length" "4")
7548 (set_attr "type" "call")]
7549)
9c08d1fa 7550
1c494086 7551;; We may also be able to do sibcalls for Thumb, but it's much harder...
7552(define_expand "sibcall"
7553 [(parallel [(call (match_operand 0 "memory_operand" "")
7554 (match_operand 1 "general_operand" ""))
2ba80634 7555 (return)
7556 (use (match_operand 2 "" ""))])]
1c494086 7557 "TARGET_ARM"
7558 "
7559 {
7560 if (operands[2] == NULL_RTX)
7561 operands[2] = const0_rtx;
1c494086 7562 }"
7563)
7564
7565(define_expand "sibcall_value"
7566 [(parallel [(set (match_operand 0 "register_operand" "")
7567 (call (match_operand 1 "memory_operand" "")
7568 (match_operand 2 "general_operand" "")))
2ba80634 7569 (return)
7570 (use (match_operand 3 "" ""))])]
1c494086 7571 "TARGET_ARM"
7572 "
7573 {
7574 if (operands[3] == NULL_RTX)
7575 operands[3] = const0_rtx;
1c494086 7576 }"
7577)
7578
7579(define_insn "*sibcall_insn"
7580 [(call (mem:SI (match_operand:SI 0 "" "X"))
7581 (match_operand 1 "" ""))
2ba80634 7582 (return)
7583 (use (match_operand 2 "" ""))]
1c494086 7584 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7585 "*
7586 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7587 "
7588 [(set_attr "type" "call")]
7589)
7590
7591(define_insn "*sibcall_value_insn"
27ed6835 7592 [(set (match_operand 0 "s_register_operand" "")
755eb2b4 7593 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 7594 (match_operand 2 "" "")))
2ba80634 7595 (return)
7596 (use (match_operand 3 "" ""))]
1c494086 7597 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7598 "*
7599 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7600 "
7601 [(set_attr "type" "call")]
7602)
7603
9c08d1fa 7604;; Often the return insn will be the same as loading from memory, so set attr
7605(define_insn "return"
7606 [(return)]
cffb2a26 7607 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7608 "*
9c08d1fa 7609 {
cffb2a26 7610 if (arm_ccfsm_state == 2)
7611 {
7612 arm_ccfsm_state += 2;
7613 return \"\";
7614 }
5db468b7 7615 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 7616 }"
a2cd141b 7617 [(set_attr "type" "load1")
755eb2b4 7618 (set_attr "length" "12")
0d66636f 7619 (set_attr "predicable" "yes")]
cffb2a26 7620)
9c08d1fa 7621
f7fbdd4a 7622(define_insn "*cond_return"
9c08d1fa 7623 [(set (pc)
8fa3ba89 7624 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7625 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7626 (return)
7627 (pc)))]
cffb2a26 7628 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7629 "*
8fa3ba89 7630 {
7631 if (arm_ccfsm_state == 2)
7632 {
7633 arm_ccfsm_state += 2;
7634 return \"\";
7635 }
7636 return output_return_instruction (operands[0], TRUE, FALSE);
7637 }"
7638 [(set_attr "conds" "use")
755eb2b4 7639 (set_attr "length" "12")
a2cd141b 7640 (set_attr "type" "load1")]
8fa3ba89 7641)
9c08d1fa 7642
f7fbdd4a 7643(define_insn "*cond_return_inverted"
9c08d1fa 7644 [(set (pc)
8fa3ba89 7645 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7646 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7647 (pc)
7648 (return)))]
cffb2a26 7649 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7650 "*
8fa3ba89 7651 {
7652 if (arm_ccfsm_state == 2)
7653 {
7654 arm_ccfsm_state += 2;
7655 return \"\";
7656 }
7657 return output_return_instruction (operands[0], TRUE, TRUE);
7658 }"
7659 [(set_attr "conds" "use")
a2cd141b 7660 (set_attr "type" "load1")]
8fa3ba89 7661)
9c08d1fa 7662
68121397 7663;; Generate a sequence of instructions to determine if the processor is
7664;; in 26-bit or 32-bit mode, and return the appropriate return address
7665;; mask.
7666
7667(define_expand "return_addr_mask"
7668 [(set (match_dup 1)
7669 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7670 (const_int 0)))
7671 (set (match_operand:SI 0 "s_register_operand" "")
7672 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7673 (const_int -1)
7674 (const_int 67108860)))] ; 0x03fffffc
7675 "TARGET_ARM"
7676 "
62eddbd4 7677 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7678 ")
7679
7680(define_insn "*check_arch2"
7681 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7682 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7683 (const_int 0)))]
7684 "TARGET_ARM"
7685 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7686 [(set_attr "length" "8")
7687 (set_attr "conds" "set")]
7688)
7689
9c08d1fa 7690;; Call subroutine returning any type.
7691
7692(define_expand "untyped_call"
7693 [(parallel [(call (match_operand 0 "" "")
7694 (const_int 0))
7695 (match_operand 1 "" "")
7696 (match_operand 2 "" "")])]
cffb2a26 7697 "TARGET_ARM"
9c08d1fa 7698 "
215b30b3 7699 {
7700 int i;
9c08d1fa 7701
215b30b3 7702 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
9c08d1fa 7703
215b30b3 7704 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7705 {
7706 rtx set = XVECEXP (operands[2], 0, i);
9c08d1fa 7707
215b30b3 7708 emit_move_insn (SET_DEST (set), SET_SRC (set));
7709 }
9c08d1fa 7710
215b30b3 7711 /* The optimizer does not know that the call sets the function value
7712 registers we stored in the result block. We avoid problems by
7713 claiming that all hard registers are used and clobbered at this
7714 point. */
7715 emit_insn (gen_blockage ());
7716
7717 DONE;
7718 }"
7719)
9c08d1fa 7720
7721;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7722;; all of memory. This blocks insns from being moved across this point.
7723
7724(define_insn "blockage"
e1159bbe 7725 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 7726 "TARGET_EITHER"
9c08d1fa 7727 ""
cffb2a26 7728 [(set_attr "length" "0")
7729 (set_attr "type" "block")]
7730)
9c08d1fa 7731
f7fbdd4a 7732(define_expand "casesi"
7733 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 7734 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7735 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 7736 (match_operand:SI 3 "" "") ; table label
7737 (match_operand:SI 4 "" "")] ; Out of range label
cffb2a26 7738 "TARGET_ARM"
f7fbdd4a 7739 "
215b30b3 7740 {
7741 rtx reg;
7742 if (operands[1] != const0_rtx)
7743 {
7744 reg = gen_reg_rtx (SImode);
f7fbdd4a 7745
215b30b3 7746 emit_insn (gen_addsi3 (reg, operands[0],
7747 GEN_INT (-INTVAL (operands[1]))));
7748 operands[0] = reg;
7749 }
9c08d1fa 7750
215b30b3 7751 if (!const_ok_for_arm (INTVAL (operands[2])))
7752 operands[2] = force_reg (SImode, operands[2]);
7753
7754 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7755 operands[4]));
7756 DONE;
7757 }"
7758)
f7fbdd4a 7759
f082f1c4 7760;; The USE in this pattern is needed to tell flow analysis that this is
7761;; a CASESI insn. It has no other purpose.
f7fbdd4a 7762(define_insn "casesi_internal"
f082f1c4 7763 [(parallel [(set (pc)
7764 (if_then_else
7765 (leu (match_operand:SI 0 "s_register_operand" "r")
7766 (match_operand:SI 1 "arm_rhs_operand" "rI"))
7767 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7768 (label_ref (match_operand 2 "" ""))))
7769 (label_ref (match_operand 3 "" ""))))
bd5b4116 7770 (clobber (reg:CC CC_REGNUM))
f082f1c4 7771 (use (label_ref (match_dup 2)))])]
cffb2a26 7772 "TARGET_ARM"
f7fbdd4a 7773 "*
0d66636f 7774 if (flag_pic)
7775 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7776 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7777 "
7778 [(set_attr "conds" "clob")
7779 (set_attr "length" "12")]
7780)
9c08d1fa 7781
cffb2a26 7782(define_expand "indirect_jump"
9c08d1fa 7783 [(set (pc)
cffb2a26 7784 (match_operand:SI 0 "s_register_operand" ""))]
7785 "TARGET_EITHER"
9c08d1fa 7786 ""
cffb2a26 7787)
7788
7789(define_insn "*arm_indirect_jump"
7790 [(set (pc)
7791 (match_operand:SI 0 "s_register_operand" "r"))]
7792 "TARGET_ARM"
7793 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 7794 [(set_attr "predicable" "yes")]
cffb2a26 7795)
9c08d1fa 7796
cffb2a26 7797;; Although not supported by the define_expand above,
7798;; cse/combine may generate this form.
f7fbdd4a 7799(define_insn "*load_indirect_jump"
9c08d1fa 7800 [(set (pc)
7801 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 7802 "TARGET_ARM"
7803 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 7804 [(set_attr "type" "load1")
61a2d04c 7805 (set_attr "pool_range" "4096")
7806 (set_attr "neg_pool_range" "4084")
0d66636f 7807 (set_attr "predicable" "yes")]
cffb2a26 7808)
7809
7810(define_insn "*thumb_indirect_jump"
7811 [(set (pc)
7812 (match_operand:SI 0 "register_operand" "l*r"))]
7813 "TARGET_THUMB"
7814 "mov\\tpc, %0"
7815 [(set_attr "conds" "clob")
7816 (set_attr "length" "2")]
7817)
7818
9c08d1fa 7819\f
7820;; Misc insns
7821
7822(define_insn "nop"
7823 [(const_int 0)]
cffb2a26 7824 "TARGET_EITHER"
7825 "*
7826 if (TARGET_ARM)
7827 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7828 return \"mov\\tr8, r8\";
7829 "
7830 [(set (attr "length")
7831 (if_then_else (eq_attr "is_thumb" "yes")
7832 (const_int 2)
7833 (const_int 4)))]
7834)
7835
9c08d1fa 7836\f
7837;; Patterns to allow combination of arithmetic, cond code and shifts
7838
f7fbdd4a 7839(define_insn "*arith_shiftsi"
9c08d1fa 7840 [(set (match_operand:SI 0 "s_register_operand" "=r")
7841 (match_operator:SI 1 "shiftable_operator"
7842 [(match_operator:SI 3 "shift_operator"
7843 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 7844 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 7845 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 7846 "TARGET_ARM"
6c4c2133 7847 "%i1%?\\t%0, %2, %4%S3"
344495ea 7848 [(set_attr "predicable" "yes")
331beb1a 7849 (set_attr "shift" "4")
a2cd141b 7850 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7851 (const_string "alu_shift")
7852 (const_string "alu_shift_reg")))]
6c4c2133 7853)
9c08d1fa 7854
d7863cfe 7855(define_split
7856 [(set (match_operand:SI 0 "s_register_operand" "")
7857 (match_operator:SI 1 "shiftable_operator"
7858 [(match_operator:SI 2 "shiftable_operator"
7859 [(match_operator:SI 3 "shift_operator"
7860 [(match_operand:SI 4 "s_register_operand" "")
7861 (match_operand:SI 5 "reg_or_int_operand" "")])
7862 (match_operand:SI 6 "s_register_operand" "")])
7863 (match_operand:SI 7 "arm_rhs_operand" "")]))
7864 (clobber (match_operand:SI 8 "s_register_operand" ""))]
7865 "TARGET_ARM"
7866 [(set (match_dup 8)
7867 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7868 (match_dup 6)]))
7869 (set (match_dup 0)
7870 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7871 "")
7872
f7fbdd4a 7873(define_insn "*arith_shiftsi_compare0"
bd5b4116 7874 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 7875 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7876 [(match_operator:SI 3 "shift_operator"
7877 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 7878 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 7879 (match_operand:SI 2 "s_register_operand" "r")])
7880 (const_int 0)))
7881 (set (match_operand:SI 0 "s_register_operand" "=r")
7882 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7883 (match_dup 2)]))]
cffb2a26 7884 "TARGET_ARM"
87b22bf7 7885 "%i1%?s\\t%0, %2, %4%S3"
344495ea 7886 [(set_attr "conds" "set")
331beb1a 7887 (set_attr "shift" "4")
a2cd141b 7888 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7889 (const_string "alu_shift")
7890 (const_string "alu_shift_reg")))]
0d66636f 7891)
9c08d1fa 7892
f7fbdd4a 7893(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 7894 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 7895 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7896 [(match_operator:SI 3 "shift_operator"
7897 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 7898 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 7899 (match_operand:SI 2 "s_register_operand" "r")])
7900 (const_int 0)))
7901 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 7902 "TARGET_ARM"
87b22bf7 7903 "%i1%?s\\t%0, %2, %4%S3"
344495ea 7904 [(set_attr "conds" "set")
331beb1a 7905 (set_attr "shift" "4")
a2cd141b 7906 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7907 (const_string "alu_shift")
7908 (const_string "alu_shift_reg")))]
0d66636f 7909)
9c08d1fa 7910
f7fbdd4a 7911(define_insn "*sub_shiftsi"
9c08d1fa 7912 [(set (match_operand:SI 0 "s_register_operand" "=r")
7913 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7914 (match_operator:SI 2 "shift_operator"
7915 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 7916 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 7917 "TARGET_ARM"
6c4c2133 7918 "sub%?\\t%0, %1, %3%S2"
344495ea 7919 [(set_attr "predicable" "yes")
331beb1a 7920 (set_attr "shift" "3")
a2cd141b 7921 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7922 (const_string "alu_shift")
7923 (const_string "alu_shift_reg")))]
6c4c2133 7924)
9c08d1fa 7925
f7fbdd4a 7926(define_insn "*sub_shiftsi_compare0"
bd5b4116 7927 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 7928 (compare:CC_NOOV
7929 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7930 (match_operator:SI 2 "shift_operator"
7931 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 7932 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 7933 (const_int 0)))
9c08d1fa 7934 (set (match_operand:SI 0 "s_register_operand" "=r")
7935 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7936 (match_dup 4)])))]
cffb2a26 7937 "TARGET_ARM"
87b22bf7 7938 "sub%?s\\t%0, %1, %3%S2"
344495ea 7939 [(set_attr "conds" "set")
a2cd141b 7940 (set_attr "shift" "3")
7941 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7942 (const_string "alu_shift")
7943 (const_string "alu_shift_reg")))]
0d66636f 7944)
9c08d1fa 7945
f7fbdd4a 7946(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 7947 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 7948 (compare:CC_NOOV
7949 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7950 (match_operator:SI 2 "shift_operator"
7951 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 7952 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 7953 (const_int 0)))
9c08d1fa 7954 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 7955 "TARGET_ARM"
87b22bf7 7956 "sub%?s\\t%0, %1, %3%S2"
344495ea 7957 [(set_attr "conds" "set")
a2cd141b 7958 (set_attr "shift" "3")
7959 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7960 (const_string "alu_shift")
7961 (const_string "alu_shift_reg")))]
0d66636f 7962)
9c08d1fa 7963
9c08d1fa 7964\f
7965
f7fbdd4a 7966(define_insn "*and_scc"
9c08d1fa 7967 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7968 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 7969 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 7970 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 7971 "TARGET_ARM"
e2348bcb 7972 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 7973 [(set_attr "conds" "use")
7974 (set_attr "length" "8")]
7975)
9c08d1fa 7976
f7fbdd4a 7977(define_insn "*ior_scc"
9c08d1fa 7978 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7979 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 7980 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 7981 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 7982 "TARGET_ARM"
e2348bcb 7983 "@
899850b0 7984 orr%d2\\t%0, %1, #1
7985 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 7986 [(set_attr "conds" "use")
7987 (set_attr "length" "4,8")]
7988)
9c08d1fa 7989
f7fbdd4a 7990(define_insn "*compare_scc"
5565501b 7991 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 7992 (match_operator:SI 1 "arm_comparison_operator"
5565501b 7993 [(match_operand:SI 2 "s_register_operand" "r,r")
7994 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 7995 (clobber (reg:CC CC_REGNUM))]
cffb2a26 7996 "TARGET_ARM"
9c08d1fa 7997 "*
601f584c 7998 if (operands[3] == const0_rtx)
7999 {
8000 if (GET_CODE (operands[1]) == LT)
8001 return \"mov\\t%0, %2, lsr #31\";
8002
8003 if (GET_CODE (operands[1]) == GE)
8004 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 8005
601f584c 8006 if (GET_CODE (operands[1]) == EQ)
8007 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8008 }
e2348bcb 8009
8fa3ba89 8010 if (GET_CODE (operands[1]) == NE)
8011 {
8012 if (which_alternative == 1)
8013 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8014 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8015 }
8016 if (which_alternative == 1)
8017 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8018 else
8019 output_asm_insn (\"cmp\\t%2, %3\", operands);
8020 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8021 "
8022 [(set_attr "conds" "clob")
8023 (set_attr "length" "12")]
8024)
9c08d1fa 8025
f7fbdd4a 8026(define_insn "*cond_move"
9c08d1fa 8027 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8028 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8029 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8030 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8031 (const_int 0)])
8032 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8033 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8034 "TARGET_ARM"
9c08d1fa 8035 "*
8fa3ba89 8036 if (GET_CODE (operands[3]) == NE)
8037 {
8038 if (which_alternative != 1)
8039 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8040 if (which_alternative != 0)
8041 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8042 return \"\";
8043 }
8044 if (which_alternative != 0)
8045 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8046 if (which_alternative != 1)
8047 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8048 return \"\";
8049 "
8050 [(set_attr "conds" "use")
8051 (set_attr "length" "4,4,8")]
8052)
9c08d1fa 8053
f7fbdd4a 8054(define_insn "*cond_arith"
9c08d1fa 8055 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8056 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8057 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8058 [(match_operand:SI 2 "s_register_operand" "r,r")
8059 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8060 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8061 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8062 "TARGET_ARM"
9c08d1fa 8063 "*
8fa3ba89 8064 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8065 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8066
8fa3ba89 8067 output_asm_insn (\"cmp\\t%2, %3\", operands);
8068 if (GET_CODE (operands[5]) == AND)
8069 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8070 else if (GET_CODE (operands[5]) == MINUS)
8071 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8072 else if (which_alternative != 0)
8073 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8074 return \"%i5%d4\\t%0, %1, #1\";
8075 "
8076 [(set_attr "conds" "clob")
8077 (set_attr "length" "12")]
8078)
9c08d1fa 8079
f7fbdd4a 8080(define_insn "*cond_sub"
9c08d1fa 8081 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8082 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8083 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8084 [(match_operand:SI 2 "s_register_operand" "r,r")
8085 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8086 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8087 "TARGET_ARM"
9c08d1fa 8088 "*
8fa3ba89 8089 output_asm_insn (\"cmp\\t%2, %3\", operands);
8090 if (which_alternative != 0)
8091 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8092 return \"sub%d4\\t%0, %1, #1\";
8093 "
8094 [(set_attr "conds" "clob")
8095 (set_attr "length" "8,12")]
8096)
9c08d1fa 8097
aea4c774 8098(define_insn "*cmp_ite0"
cffb2a26 8099 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8100 (compare
8101 (if_then_else:SI
8fa3ba89 8102 (match_operator 4 "arm_comparison_operator"
aea4c774 8103 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8104 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8105 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8106 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8107 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8108 (const_int 0))
8109 (const_int 0)))]
cffb2a26 8110 "TARGET_ARM"
9c08d1fa 8111 "*
aea4c774 8112 {
8fa3ba89 8113 static const char * const opcodes[4][2] =
8114 {
8115 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8116 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8117 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8118 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8119 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8120 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8121 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8122 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8123 };
8124 int swap =
8125 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8126
8127 return opcodes[which_alternative][swap];
8128 }"
8129 [(set_attr "conds" "set")
8130 (set_attr "length" "8")]
8131)
9c08d1fa 8132
aea4c774 8133(define_insn "*cmp_ite1"
cffb2a26 8134 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8135 (compare
8136 (if_then_else:SI
8fa3ba89 8137 (match_operator 4 "arm_comparison_operator"
aea4c774 8138 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8139 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8140 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8141 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8142 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8143 (const_int 1))
8144 (const_int 0)))]
cffb2a26 8145 "TARGET_ARM"
9c08d1fa 8146 "*
9c08d1fa 8147 {
215b30b3 8148 static const char * const opcodes[4][2] =
8149 {
8150 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8151 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8152 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8153 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8154 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8155 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8156 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8157 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8158 };
8159 int swap =
8160 comparison_dominates_p (GET_CODE (operands[5]),
8161 reverse_condition (GET_CODE (operands[4])));
8162
8163 return opcodes[which_alternative][swap];
8164 }"
8fa3ba89 8165 [(set_attr "conds" "set")
8166 (set_attr "length" "8")]
8167)
9c08d1fa 8168
f6c53574 8169(define_insn "*cmp_and"
8170 [(set (match_operand 6 "dominant_cc_register" "")
8171 (compare
8172 (and:SI
8173 (match_operator 4 "arm_comparison_operator"
8174 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8175 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8176 (match_operator:SI 5 "arm_comparison_operator"
8177 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8178 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8179 (const_int 0)))]
8180 "TARGET_ARM"
8181 "*
8182 {
35823b64 8183 static const char *const opcodes[4][2] =
f6c53574 8184 {
8185 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8186 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8187 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8188 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8189 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8190 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8191 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8192 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8193 };
8194 int swap =
8195 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8196
8197 return opcodes[which_alternative][swap];
8198 }"
8199 [(set_attr "conds" "set")
8200 (set_attr "predicable" "no")
8201 (set_attr "length" "8")]
8202)
8203
8204(define_insn "*cmp_ior"
8205 [(set (match_operand 6 "dominant_cc_register" "")
8206 (compare
8207 (ior:SI
8208 (match_operator 4 "arm_comparison_operator"
8209 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8210 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8211 (match_operator:SI 5 "arm_comparison_operator"
8212 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8213 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8214 (const_int 0)))]
8215 "TARGET_ARM"
8216 "*
8217{
35823b64 8218 static const char *const opcodes[4][2] =
f6c53574 8219 {
8220 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8221 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8222 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8223 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8224 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8225 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8226 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8227 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8228 };
8229 int swap =
8230 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8231
8232 return opcodes[which_alternative][swap];
8233}
8234"
8235 [(set_attr "conds" "set")
8236 (set_attr "length" "8")]
8237)
8238
3c5afce6 8239(define_insn_and_split "*ior_scc_scc"
8240 [(set (match_operand:SI 0 "s_register_operand" "=r")
8241 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8242 [(match_operand:SI 1 "s_register_operand" "r")
8243 (match_operand:SI 2 "arm_add_operand" "rIL")])
8244 (match_operator:SI 6 "arm_comparison_operator"
8245 [(match_operand:SI 4 "s_register_operand" "r")
8246 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8247 (clobber (reg:CC CC_REGNUM))]
8248 "TARGET_ARM
8249 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8250 != CCmode)"
8251 "#"
8252 "TARGET_ARM && reload_completed"
8253 [(set (match_dup 7)
8254 (compare
8255 (ior:SI
8256 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8257 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8258 (const_int 0)))
8259 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8260 "operands[7]
8261 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8262 DOM_CC_X_OR_Y),
601f584c 8263 CC_REGNUM);"
8264 [(set_attr "conds" "clob")
8265 (set_attr "length" "16")])
8266
8267; If the above pattern is followed by a CMP insn, then the compare is
8268; redundant, since we can rework the conditional instruction that follows.
8269(define_insn_and_split "*ior_scc_scc_cmp"
8270 [(set (match_operand 0 "dominant_cc_register" "")
8271 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8272 [(match_operand:SI 1 "s_register_operand" "r")
8273 (match_operand:SI 2 "arm_add_operand" "rIL")])
8274 (match_operator:SI 6 "arm_comparison_operator"
8275 [(match_operand:SI 4 "s_register_operand" "r")
8276 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8277 (const_int 0)))
8278 (set (match_operand:SI 7 "s_register_operand" "=r")
8279 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8280 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8281 "TARGET_ARM"
8282 "#"
8283 "TARGET_ARM && reload_completed"
8284 [(set (match_dup 0)
8285 (compare
8286 (ior:SI
8287 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8288 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8289 (const_int 0)))
8290 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8291 ""
8292 [(set_attr "conds" "set")
8293 (set_attr "length" "16")])
3c5afce6 8294
8295(define_insn_and_split "*and_scc_scc"
8296 [(set (match_operand:SI 0 "s_register_operand" "=r")
8297 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8298 [(match_operand:SI 1 "s_register_operand" "r")
8299 (match_operand:SI 2 "arm_add_operand" "rIL")])
8300 (match_operator:SI 6 "arm_comparison_operator"
8301 [(match_operand:SI 4 "s_register_operand" "r")
8302 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8303 (clobber (reg:CC CC_REGNUM))]
8304 "TARGET_ARM
8305 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8306 != CCmode)"
8307 "#"
601f584c 8308 "TARGET_ARM && reload_completed
8309 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8310 != CCmode)"
3c5afce6 8311 [(set (match_dup 7)
8312 (compare
8313 (and:SI
8314 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8315 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8316 (const_int 0)))
8317 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8318 "operands[7]
8319 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8320 DOM_CC_X_AND_Y),
601f584c 8321 CC_REGNUM);"
8322 [(set_attr "conds" "clob")
8323 (set_attr "length" "16")])
8324
8325; If the above pattern is followed by a CMP insn, then the compare is
8326; redundant, since we can rework the conditional instruction that follows.
8327(define_insn_and_split "*and_scc_scc_cmp"
8328 [(set (match_operand 0 "dominant_cc_register" "")
8329 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8330 [(match_operand:SI 1 "s_register_operand" "r")
8331 (match_operand:SI 2 "arm_add_operand" "rIL")])
8332 (match_operator:SI 6 "arm_comparison_operator"
8333 [(match_operand:SI 4 "s_register_operand" "r")
8334 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8335 (const_int 0)))
8336 (set (match_operand:SI 7 "s_register_operand" "=r")
8337 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8338 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8339 "TARGET_ARM"
8340 "#"
8341 "TARGET_ARM && reload_completed"
8342 [(set (match_dup 0)
8343 (compare
8344 (and:SI
8345 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8346 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8347 (const_int 0)))
8348 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8349 ""
8350 [(set_attr "conds" "set")
8351 (set_attr "length" "16")])
8352
8353;; If there is no dominance in the comparison, then we can still save an
8354;; instruction in the AND case, since we can know that the second compare
8355;; need only zero the value if false (if true, then the value is already
8356;; correct).
8357(define_insn_and_split "*and_scc_scc_nodom"
8358 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8359 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8360 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8361 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8362 (match_operator:SI 6 "arm_comparison_operator"
8363 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8364 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8365 (clobber (reg:CC CC_REGNUM))]
8366 "TARGET_ARM
8367 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8368 == CCmode)"
8369 "#"
8370 "TARGET_ARM && reload_completed"
8371 [(parallel [(set (match_dup 0)
8372 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8373 (clobber (reg:CC CC_REGNUM))])
8374 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8375 (set (match_dup 0)
8376 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8377 (match_dup 0)
8378 (const_int 0)))]
8379 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8380 operands[4], operands[5]),
8381 CC_REGNUM);
8382 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8383 operands[5]);"
8384 [(set_attr "conds" "clob")
8385 (set_attr "length" "20")])
3c5afce6 8386
3a0bdee0 8387(define_split
8388 [(set (reg:CC_NOOV CC_REGNUM)
8389 (compare:CC_NOOV (ior:SI
8390 (and:SI (match_operand:SI 0 "s_register_operand" "")
8391 (const_int 1))
8392 (match_operator:SI 1 "comparison_operator"
8393 [(match_operand:SI 2 "s_register_operand" "")
8394 (match_operand:SI 3 "arm_add_operand" "")]))
8395 (const_int 0)))
8396 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8397 "TARGET_ARM"
8398 [(set (match_dup 4)
8399 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8400 (match_dup 0)))
8401 (set (reg:CC_NOOV CC_REGNUM)
8402 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8403 (const_int 0)))]
8404 "")
8405
8406(define_split
8407 [(set (reg:CC_NOOV CC_REGNUM)
8408 (compare:CC_NOOV (ior:SI
8409 (match_operator:SI 1 "comparison_operator"
8410 [(match_operand:SI 2 "s_register_operand" "")
8411 (match_operand:SI 3 "arm_add_operand" "")])
8412 (and:SI (match_operand:SI 0 "s_register_operand" "")
8413 (const_int 1)))
8414 (const_int 0)))
8415 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8416 "TARGET_ARM"
8417 [(set (match_dup 4)
8418 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8419 (match_dup 0)))
8420 (set (reg:CC_NOOV CC_REGNUM)
8421 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8422 (const_int 0)))]
8423 "")
8424
f7fbdd4a 8425(define_insn "*negscc"
9c08d1fa 8426 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8427 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 8428 [(match_operand:SI 1 "s_register_operand" "r")
8429 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 8430 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8431 "TARGET_ARM"
9c08d1fa 8432 "*
f0e75574 8433 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
e2348bcb 8434 return \"mov\\t%0, %1, asr #31\";
8435
9c08d1fa 8436 if (GET_CODE (operands[3]) == NE)
e2348bcb 8437 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8438
9c08d1fa 8439 if (GET_CODE (operands[3]) == GT)
e2348bcb 8440 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8441
8442 output_asm_insn (\"cmp\\t%1, %2\", operands);
8443 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8444 return \"mvn%d3\\t%0, #0\";
215b30b3 8445 "
8fa3ba89 8446 [(set_attr "conds" "clob")
8447 (set_attr "length" "12")]
8448)
9c08d1fa 8449
8450(define_insn "movcond"
8451 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 8452 (if_then_else:SI
8fa3ba89 8453 (match_operator 5 "arm_comparison_operator"
5565501b 8454 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8455 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8456 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8457 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 8458 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8459 "TARGET_ARM"
9c08d1fa 8460 "*
8461 if (GET_CODE (operands[5]) == LT
8462 && (operands[4] == const0_rtx))
8463 {
5565501b 8464 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 8465 {
9c08d1fa 8466 if (operands[2] == const0_rtx)
e2348bcb 8467 return \"and\\t%0, %1, %3, asr #31\";
8468 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 8469 }
8470 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8471 {
9c08d1fa 8472 if (operands[1] == const0_rtx)
e2348bcb 8473 return \"bic\\t%0, %2, %3, asr #31\";
8474 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 8475 }
8476 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8477 are constants. */
9c08d1fa 8478 }
e2348bcb 8479
9c08d1fa 8480 if (GET_CODE (operands[5]) == GE
8481 && (operands[4] == const0_rtx))
8482 {
8483 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8484 {
9c08d1fa 8485 if (operands[2] == const0_rtx)
e2348bcb 8486 return \"bic\\t%0, %1, %3, asr #31\";
8487 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 8488 }
8489 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8490 {
9c08d1fa 8491 if (operands[1] == const0_rtx)
e2348bcb 8492 return \"and\\t%0, %2, %3, asr #31\";
8493 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 8494 }
8495 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8496 are constants. */
9c08d1fa 8497 }
8498 if (GET_CODE (operands[4]) == CONST_INT
8499 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 8500 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 8501 else
e2348bcb 8502 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 8503 if (which_alternative != 0)
e2348bcb 8504 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 8505 if (which_alternative != 1)
e2348bcb 8506 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 8507 return \"\";
215b30b3 8508 "
8fa3ba89 8509 [(set_attr "conds" "clob")
8510 (set_attr "length" "8,8,12")]
8511)
9c08d1fa 8512
8a18b90c 8513(define_insn "*ifcompare_plus_move"
8514 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8515 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8516 [(match_operand:SI 4 "s_register_operand" "r,r")
8517 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8518 (plus:SI
8519 (match_operand:SI 2 "s_register_operand" "r,r")
8520 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 8521 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8522 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8523 "TARGET_ARM"
8a18b90c 8524 "#"
8fa3ba89 8525 [(set_attr "conds" "clob")
8526 (set_attr "length" "8,12")]
8527)
8a18b90c 8528
8529(define_insn "*if_plus_move"
129a2fe4 8530 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8531 (if_then_else:SI
8fa3ba89 8532 (match_operator 4 "arm_comparison_operator"
8a18b90c 8533 [(match_operand 5 "cc_register" "") (const_int 0)])
8534 (plus:SI
129a2fe4 8535 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8536 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8537 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 8538 "TARGET_ARM"
8a18b90c 8539 "@
8540 add%d4\\t%0, %2, %3
8541 sub%d4\\t%0, %2, #%n3
8542 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 8543 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 8544 [(set_attr "conds" "use")
8545 (set_attr "length" "4,4,8,8")
8546 (set_attr "type" "*,*,*,*")]
8547)
8a18b90c 8548
8549(define_insn "*ifcompare_move_plus"
5565501b 8550 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8551 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8552 [(match_operand:SI 4 "s_register_operand" "r,r")
8553 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8554 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8555 (plus:SI
8556 (match_operand:SI 2 "s_register_operand" "r,r")
8557 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 8558 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8559 "TARGET_ARM"
8a18b90c 8560 "#"
8fa3ba89 8561 [(set_attr "conds" "clob")
8562 (set_attr "length" "8,12")]
8563)
8a18b90c 8564
8565(define_insn "*if_move_plus"
129a2fe4 8566 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8567 (if_then_else:SI
8fa3ba89 8568 (match_operator 4 "arm_comparison_operator"
8a18b90c 8569 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 8570 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 8571 (plus:SI
129a2fe4 8572 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8573 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 8574 "TARGET_ARM"
8a18b90c 8575 "@
8576 add%D4\\t%0, %2, %3
8577 sub%D4\\t%0, %2, #%n3
8578 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 8579 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 8580 [(set_attr "conds" "use")
8581 (set_attr "length" "4,4,8,8")
8582 (set_attr "type" "*,*,*,*")]
8583)
8a18b90c 8584
8585(define_insn "*ifcompare_arith_arith"
8586 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8587 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 8588 [(match_operand:SI 5 "s_register_operand" "r")
8589 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 8590 (match_operator:SI 8 "shiftable_operator"
8a18b90c 8591 [(match_operand:SI 1 "s_register_operand" "r")
8592 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 8593 (match_operator:SI 7 "shiftable_operator"
8a18b90c 8594 [(match_operand:SI 3 "s_register_operand" "r")
8595 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 8596 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8597 "TARGET_ARM"
8a18b90c 8598 "#"
8fa3ba89 8599 [(set_attr "conds" "clob")
8600 (set_attr "length" "12")]
8601)
9c08d1fa 8602
8a18b90c 8603(define_insn "*if_arith_arith"
8604 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8605 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 8606 [(match_operand 8 "cc_register" "") (const_int 0)])
8607 (match_operator:SI 6 "shiftable_operator"
8608 [(match_operand:SI 1 "s_register_operand" "r")
8609 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8610 (match_operator:SI 7 "shiftable_operator"
8611 [(match_operand:SI 3 "s_register_operand" "r")
8612 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 8613 "TARGET_ARM"
8a18b90c 8614 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 8615 [(set_attr "conds" "use")
8616 (set_attr "length" "8")]
8617)
8a18b90c 8618
f7fbdd4a 8619(define_insn "*ifcompare_arith_move"
9c08d1fa 8620 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8621 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8622 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 8623 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 8624 (match_operator:SI 7 "shiftable_operator"
8625 [(match_operand:SI 4 "s_register_operand" "r,r")
8626 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 8627 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8628 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8629 "TARGET_ARM"
9c08d1fa 8630 "*
9c08d1fa 8631 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8632 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 8633 everything is in registers then we can do this in two instructions. */
9c08d1fa 8634 if (operands[3] == const0_rtx
8635 && GET_CODE (operands[7]) != AND
8636 && GET_CODE (operands[5]) == REG
8637 && GET_CODE (operands[1]) == REG
8638 && REGNO (operands[1]) == REGNO (operands[4])
8639 && REGNO (operands[4]) != REGNO (operands[0]))
8640 {
8641 if (GET_CODE (operands[6]) == LT)
40dbec34 8642 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8643 else if (GET_CODE (operands[6]) == GE)
40dbec34 8644 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8645 }
8646 if (GET_CODE (operands[3]) == CONST_INT
8647 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 8648 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 8649 else
e2348bcb 8650 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 8651 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 8652 if (which_alternative != 0)
129a2fe4 8653 return \"mov%D6\\t%0, %1\";
9c08d1fa 8654 return \"\";
215b30b3 8655 "
8fa3ba89 8656 [(set_attr "conds" "clob")
8657 (set_attr "length" "8,12")]
8658)
9c08d1fa 8659
8a18b90c 8660(define_insn "*if_arith_move"
129a2fe4 8661 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8662 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 8663 [(match_operand 6 "cc_register" "") (const_int 0)])
8664 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8665 [(match_operand:SI 2 "s_register_operand" "r,r")
8666 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8667 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 8668 "TARGET_ARM"
8a18b90c 8669 "@
8670 %I5%d4\\t%0, %2, %3
129a2fe4 8671 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 8672 [(set_attr "conds" "use")
8673 (set_attr "length" "4,8")
8674 (set_attr "type" "*,*")]
8675)
8a18b90c 8676
f7fbdd4a 8677(define_insn "*ifcompare_move_arith"
9c08d1fa 8678 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8679 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8680 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 8681 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8682 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 8683 (match_operator:SI 7 "shiftable_operator"
8684 [(match_operand:SI 2 "s_register_operand" "r,r")
8685 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8686 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8687 "TARGET_ARM"
9c08d1fa 8688 "*
9c08d1fa 8689 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8690 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 8691 everything is in registers then we can do this in two instructions */
8692 if (operands[5] == const0_rtx
8693 && GET_CODE (operands[7]) != AND
8694 && GET_CODE (operands[3]) == REG
8695 && GET_CODE (operands[1]) == REG
8696 && REGNO (operands[1]) == REGNO (operands[2])
8697 && REGNO (operands[2]) != REGNO (operands[0]))
8698 {
8699 if (GET_CODE (operands[6]) == GE)
40dbec34 8700 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8701 else if (GET_CODE (operands[6]) == LT)
40dbec34 8702 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 8703 }
40dbec34 8704
9c08d1fa 8705 if (GET_CODE (operands[5]) == CONST_INT
8706 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 8707 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 8708 else
e2348bcb 8709 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 8710
9c08d1fa 8711 if (which_alternative != 0)
129a2fe4 8712 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 8713 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 8714 "
8fa3ba89 8715 [(set_attr "conds" "clob")
8716 (set_attr "length" "8,12")]
8717)
9c08d1fa 8718
8a18b90c 8719(define_insn "*if_move_arith"
129a2fe4 8720 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 8721 (if_then_else:SI
8fa3ba89 8722 (match_operator 4 "arm_comparison_operator"
8a18b90c 8723 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 8724 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8725 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8726 [(match_operand:SI 2 "s_register_operand" "r,r")
8727 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 8728 "TARGET_ARM"
8a18b90c 8729 "@
8730 %I5%D4\\t%0, %2, %3
129a2fe4 8731 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 8732 [(set_attr "conds" "use")
8733 (set_attr "length" "4,8")
8734 (set_attr "type" "*,*")]
8735)
8a18b90c 8736
8737(define_insn "*ifcompare_move_not"
9c08d1fa 8738 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 8739 (if_then_else:SI
8fa3ba89 8740 (match_operator 5 "arm_comparison_operator"
8a18b90c 8741 [(match_operand:SI 3 "s_register_operand" "r,r")
8742 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8743 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8744 (not:SI
8745 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 8746 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8747 "TARGET_ARM"
8a18b90c 8748 "#"
8fa3ba89 8749 [(set_attr "conds" "clob")
8750 (set_attr "length" "8,12")]
8751)
9c08d1fa 8752
8a18b90c 8753(define_insn "*if_move_not"
8754 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8755 (if_then_else:SI
8fa3ba89 8756 (match_operator 4 "arm_comparison_operator"
8a18b90c 8757 [(match_operand 3 "cc_register" "") (const_int 0)])
8758 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8759 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 8760 "TARGET_ARM"
8a18b90c 8761 "@
8762 mvn%D4\\t%0, %2
8763 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8764 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 8765 [(set_attr "conds" "use")
8766 (set_attr "length" "4,8,8")]
8767)
8a18b90c 8768
8769(define_insn "*ifcompare_not_move"
9c08d1fa 8770 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 8771 (if_then_else:SI
8fa3ba89 8772 (match_operator 5 "arm_comparison_operator"
8a18b90c 8773 [(match_operand:SI 3 "s_register_operand" "r,r")
8774 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8775 (not:SI
8776 (match_operand:SI 2 "s_register_operand" "r,r"))
8777 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 8778 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8779 "TARGET_ARM"
8a18b90c 8780 "#"
8fa3ba89 8781 [(set_attr "conds" "clob")
8782 (set_attr "length" "8,12")]
8783)
9c08d1fa 8784
8a18b90c 8785(define_insn "*if_not_move"
8786 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8787 (if_then_else:SI
8fa3ba89 8788 (match_operator 4 "arm_comparison_operator"
8a18b90c 8789 [(match_operand 3 "cc_register" "") (const_int 0)])
8790 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8791 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 8792 "TARGET_ARM"
8a18b90c 8793 "@
8794 mvn%d4\\t%0, %2
8795 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8796 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 8797 [(set_attr "conds" "use")
8798 (set_attr "length" "4,8,8")]
8799)
8a18b90c 8800
8801(define_insn "*ifcompare_shift_move"
9c08d1fa 8802 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 8803 (if_then_else:SI
8fa3ba89 8804 (match_operator 6 "arm_comparison_operator"
8a18b90c 8805 [(match_operand:SI 4 "s_register_operand" "r,r")
8806 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8807 (match_operator:SI 7 "shift_operator"
8808 [(match_operand:SI 2 "s_register_operand" "r,r")
8809 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8810 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 8811 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8812 "TARGET_ARM"
9c08d1fa 8813 "#"
8fa3ba89 8814 [(set_attr "conds" "clob")
8815 (set_attr "length" "8,12")]
8816)
9c08d1fa 8817
8a18b90c 8818(define_insn "*if_shift_move"
8819 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8820 (if_then_else:SI
8fa3ba89 8821 (match_operator 5 "arm_comparison_operator"
8a18b90c 8822 [(match_operand 6 "cc_register" "") (const_int 0)])
8823 (match_operator:SI 4 "shift_operator"
8824 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8825 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8826 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 8827 "TARGET_ARM"
5565501b 8828 "@
8a18b90c 8829 mov%d5\\t%0, %2%S4
8830 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8831 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 8832 [(set_attr "conds" "use")
331beb1a 8833 (set_attr "shift" "2")
a2cd141b 8834 (set_attr "length" "4,8,8")
8835 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8836 (const_string "alu_shift")
8837 (const_string "alu_shift_reg")))]
8fa3ba89 8838)
5565501b 8839
8a18b90c 8840(define_insn "*ifcompare_move_shift"
8841 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 8842 (if_then_else:SI
8fa3ba89 8843 (match_operator 6 "arm_comparison_operator"
8a18b90c 8844 [(match_operand:SI 4 "s_register_operand" "r,r")
8845 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8846 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 8847 (match_operator:SI 7 "shift_operator"
8a18b90c 8848 [(match_operand:SI 2 "s_register_operand" "r,r")
8849 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 8850 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8851 "TARGET_ARM"
8a18b90c 8852 "#"
8fa3ba89 8853 [(set_attr "conds" "clob")
8854 (set_attr "length" "8,12")]
8855)
5565501b 8856
8a18b90c 8857(define_insn "*if_move_shift"
8858 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 8859 (if_then_else:SI
8fa3ba89 8860 (match_operator 5 "arm_comparison_operator"
8a18b90c 8861 [(match_operand 6 "cc_register" "") (const_int 0)])
8862 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8863 (match_operator:SI 4 "shift_operator"
8864 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8865 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 8866 "TARGET_ARM"
5565501b 8867 "@
8a18b90c 8868 mov%D5\\t%0, %2%S4
8869 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8870 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 8871 [(set_attr "conds" "use")
331beb1a 8872 (set_attr "shift" "2")
a2cd141b 8873 (set_attr "length" "4,8,8")
8874 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8875 (const_string "alu_shift")
8876 (const_string "alu_shift_reg")))]
8fa3ba89 8877)
9c08d1fa 8878
f7fbdd4a 8879(define_insn "*ifcompare_shift_shift"
8a18b90c 8880 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 8881 (if_then_else:SI
8fa3ba89 8882 (match_operator 7 "arm_comparison_operator"
8a18b90c 8883 [(match_operand:SI 5 "s_register_operand" "r")
8884 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 8885 (match_operator:SI 8 "shift_operator"
8a18b90c 8886 [(match_operand:SI 1 "s_register_operand" "r")
8887 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 8888 (match_operator:SI 9 "shift_operator"
8a18b90c 8889 [(match_operand:SI 3 "s_register_operand" "r")
8890 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 8891 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8892 "TARGET_ARM"
8a18b90c 8893 "#"
8fa3ba89 8894 [(set_attr "conds" "clob")
8895 (set_attr "length" "12")]
8896)
9c08d1fa 8897
8a18b90c 8898(define_insn "*if_shift_shift"
8899 [(set (match_operand:SI 0 "s_register_operand" "=r")
8900 (if_then_else:SI
8fa3ba89 8901 (match_operator 5 "arm_comparison_operator"
8a18b90c 8902 [(match_operand 8 "cc_register" "") (const_int 0)])
8903 (match_operator:SI 6 "shift_operator"
8904 [(match_operand:SI 1 "s_register_operand" "r")
8905 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8906 (match_operator:SI 7 "shift_operator"
8907 [(match_operand:SI 3 "s_register_operand" "r")
8908 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 8909 "TARGET_ARM"
8a18b90c 8910 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 8911 [(set_attr "conds" "use")
331beb1a 8912 (set_attr "shift" "1")
a2cd141b 8913 (set_attr "length" "8")
8914 (set (attr "type") (if_then_else
8915 (and (match_operand 2 "const_int_operand" "")
8916 (match_operand 4 "const_int_operand" ""))
8917 (const_string "alu_shift")
8918 (const_string "alu_shift_reg")))]
8fa3ba89 8919)
8a18b90c 8920
f7fbdd4a 8921(define_insn "*ifcompare_not_arith"
8a18b90c 8922 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 8923 (if_then_else:SI
8fa3ba89 8924 (match_operator 6 "arm_comparison_operator"
8a18b90c 8925 [(match_operand:SI 4 "s_register_operand" "r")
8926 (match_operand:SI 5 "arm_add_operand" "rIL")])
8927 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 8928 (match_operator:SI 7 "shiftable_operator"
8a18b90c 8929 [(match_operand:SI 2 "s_register_operand" "r")
8930 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 8931 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8932 "TARGET_ARM"
8a18b90c 8933 "#"
8fa3ba89 8934 [(set_attr "conds" "clob")
8935 (set_attr "length" "12")]
8936)
9c08d1fa 8937
8a18b90c 8938(define_insn "*if_not_arith"
8939 [(set (match_operand:SI 0 "s_register_operand" "=r")
8940 (if_then_else:SI
8fa3ba89 8941 (match_operator 5 "arm_comparison_operator"
8a18b90c 8942 [(match_operand 4 "cc_register" "") (const_int 0)])
8943 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8944 (match_operator:SI 6 "shiftable_operator"
8945 [(match_operand:SI 2 "s_register_operand" "r")
8946 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 8947 "TARGET_ARM"
8a18b90c 8948 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 8949 [(set_attr "conds" "use")
8950 (set_attr "length" "8")]
8951)
8a18b90c 8952
8953(define_insn "*ifcompare_arith_not"
8954 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 8955 (if_then_else:SI
8fa3ba89 8956 (match_operator 6 "arm_comparison_operator"
8a18b90c 8957 [(match_operand:SI 4 "s_register_operand" "r")
8958 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 8959 (match_operator:SI 7 "shiftable_operator"
8a18b90c 8960 [(match_operand:SI 2 "s_register_operand" "r")
8961 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8962 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 8963 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8964 "TARGET_ARM"
8a18b90c 8965 "#"
8fa3ba89 8966 [(set_attr "conds" "clob")
8967 (set_attr "length" "12")]
8968)
9c08d1fa 8969
8a18b90c 8970(define_insn "*if_arith_not"
8971 [(set (match_operand:SI 0 "s_register_operand" "=r")
8972 (if_then_else:SI
8fa3ba89 8973 (match_operator 5 "arm_comparison_operator"
8a18b90c 8974 [(match_operand 4 "cc_register" "") (const_int 0)])
8975 (match_operator:SI 6 "shiftable_operator"
8976 [(match_operand:SI 2 "s_register_operand" "r")
8977 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8978 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 8979 "TARGET_ARM"
8a18b90c 8980 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 8981 [(set_attr "conds" "use")
8982 (set_attr "length" "8")]
8983)
8a18b90c 8984
f7fbdd4a 8985(define_insn "*ifcompare_neg_move"
8a18b90c 8986 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 8987 (if_then_else:SI
8fa3ba89 8988 (match_operator 5 "arm_comparison_operator"
8a18b90c 8989 [(match_operand:SI 3 "s_register_operand" "r,r")
8990 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8991 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8992 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 8993 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8994 "TARGET_ARM"
8a18b90c 8995 "#"
8fa3ba89 8996 [(set_attr "conds" "clob")
8997 (set_attr "length" "8,12")]
8998)
8a18b90c 8999
9000(define_insn "*if_neg_move"
9001 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9002 (if_then_else:SI
8fa3ba89 9003 (match_operator 4 "arm_comparison_operator"
8a18b90c 9004 [(match_operand 3 "cc_register" "") (const_int 0)])
9005 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9006 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9007 "TARGET_ARM"
8a18b90c 9008 "@
9009 rsb%d4\\t%0, %2, #0
9010 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9011 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9012 [(set_attr "conds" "use")
9013 (set_attr "length" "4,8,8")]
9014)
9c08d1fa 9015
f7fbdd4a 9016(define_insn "*ifcompare_move_neg"
8a18b90c 9017 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9018 (if_then_else:SI
8fa3ba89 9019 (match_operator 5 "arm_comparison_operator"
8a18b90c 9020 [(match_operand:SI 3 "s_register_operand" "r,r")
9021 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9022 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9023 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9024 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9025 "TARGET_ARM"
8a18b90c 9026 "#"
8fa3ba89 9027 [(set_attr "conds" "clob")
9028 (set_attr "length" "8,12")]
9029)
8a18b90c 9030
9031(define_insn "*if_move_neg"
9032 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9033 (if_then_else:SI
8fa3ba89 9034 (match_operator 4 "arm_comparison_operator"
8a18b90c 9035 [(match_operand 3 "cc_register" "") (const_int 0)])
9036 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9037 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9038 "TARGET_ARM"
8a18b90c 9039 "@
9040 rsb%D4\\t%0, %2, #0
9041 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9042 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9043 [(set_attr "conds" "use")
9044 (set_attr "length" "4,8,8")]
9045)
9c08d1fa 9046
f7fbdd4a 9047(define_insn "*arith_adjacentmem"
9c08d1fa 9048 [(set (match_operand:SI 0 "s_register_operand" "=r")
9049 (match_operator:SI 1 "shiftable_operator"
9050 [(match_operand:SI 2 "memory_operand" "m")
9051 (match_operand:SI 3 "memory_operand" "m")]))
9052 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9053 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9054 "*
215b30b3 9055 {
9056 rtx ldm[3];
9057 rtx arith[4];
9058 int val1 = 0, val2 = 0;
9c08d1fa 9059
215b30b3 9060 if (REGNO (operands[0]) > REGNO (operands[4]))
9061 {
9062 ldm[1] = operands[4];
9063 ldm[2] = operands[0];
9064 }
9065 else
9066 {
9067 ldm[1] = operands[0];
9068 ldm[2] = operands[4];
9069 }
9070 if (GET_CODE (XEXP (operands[2], 0)) != REG)
9071 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9072 if (GET_CODE (XEXP (operands[3], 0)) != REG)
9073 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9074 arith[0] = operands[0];
9075 arith[3] = operands[1];
9076 if (val1 < val2)
9077 {
9078 arith[1] = ldm[1];
9079 arith[2] = ldm[2];
9080 }
9081 else
9082 {
9083 arith[1] = ldm[2];
9084 arith[2] = ldm[1];
9085 }
9086 if (val1 && val2)
9087 {
9088 rtx ops[3];
9089 ldm[0] = ops[0] = operands[4];
9090 ops[1] = XEXP (XEXP (operands[2], 0), 0);
9091 ops[2] = XEXP (XEXP (operands[2], 0), 1);
9092 output_add_immediate (ops);
9093 if (val1 < val2)
9094 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9095 else
9096 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9097 }
9098 else if (val1)
9099 {
9100 ldm[0] = XEXP (operands[3], 0);
9101 if (val1 < val2)
9102 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9103 else
9104 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9105 }
9106 else
9107 {
9108 ldm[0] = XEXP (operands[2], 0);
9109 if (val1 < val2)
9110 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9111 else
9112 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9113 }
9114 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9115 return \"\";
9116 }"
9117 [(set_attr "length" "12")
9118 (set_attr "predicable" "yes")
a2cd141b 9119 (set_attr "type" "load1")]
215b30b3 9120)
9c08d1fa 9121
9122;; the arm can support extended pre-inc instructions
9123
9124;; In all these cases, we use operands 0 and 1 for the register being
9125;; incremented because those are the operands that local-alloc will
9126;; tie and these are the pair most likely to be tieable (and the ones
9127;; that will benefit the most).
9128
9129;; We reject the frame pointer if it occurs anywhere in these patterns since
9130;; elimination will cause too many headaches.
9131
f7fbdd4a 9132(define_insn "*strqi_preinc"
9c08d1fa 9133 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9134 (match_operand:SI 2 "index_operand" "rJ")))
9135 (match_operand:QI 3 "s_register_operand" "r"))
9136 (set (match_operand:SI 0 "s_register_operand" "=r")
9137 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9138 "TARGET_ARM
9139 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9140 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9141 && (GET_CODE (operands[2]) != REG
9142 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9143 "str%?b\\t%3, [%0, %2]!"
0d66636f 9144 [(set_attr "type" "store1")
9145 (set_attr "predicable" "yes")]
9146)
9c08d1fa 9147
f7fbdd4a 9148(define_insn "*strqi_predec"
9c08d1fa 9149 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9150 (match_operand:SI 2 "s_register_operand" "r")))
9151 (match_operand:QI 3 "s_register_operand" "r"))
9152 (set (match_operand:SI 0 "s_register_operand" "=r")
9153 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9154 "TARGET_ARM
9155 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9156 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9157 && (GET_CODE (operands[2]) != REG
9158 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9159 "str%?b\\t%3, [%0, -%2]!"
0d66636f 9160 [(set_attr "type" "store1")
9161 (set_attr "predicable" "yes")]
9162)
9c08d1fa 9163
f7fbdd4a 9164(define_insn "*loadqi_preinc"
9c08d1fa 9165 [(set (match_operand:QI 3 "s_register_operand" "=r")
9166 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9167 (match_operand:SI 2 "index_operand" "rJ"))))
9168 (set (match_operand:SI 0 "s_register_operand" "=r")
9169 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9170 "TARGET_ARM
9171 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9172 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9173 && (GET_CODE (operands[2]) != REG
9174 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9175 "ldr%?b\\t%3, [%0, %2]!"
a2cd141b 9176 [(set_attr "type" "load_byte")
0d66636f 9177 (set_attr "predicable" "yes")]
9178)
9c08d1fa 9179
f7fbdd4a 9180(define_insn "*loadqi_predec"
9c08d1fa 9181 [(set (match_operand:QI 3 "s_register_operand" "=r")
9182 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9183 (match_operand:SI 2 "s_register_operand" "r"))))
9184 (set (match_operand:SI 0 "s_register_operand" "=r")
9185 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9186 "TARGET_ARM
9187 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9188 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9189 && (GET_CODE (operands[2]) != REG
9190 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9191 "ldr%?b\\t%3, [%0, -%2]!"
a2cd141b 9192 [(set_attr "type" "load_byte")
0d66636f 9193 (set_attr "predicable" "yes")]
9194)
9c08d1fa 9195
f7fbdd4a 9196(define_insn "*loadqisi_preinc"
9c08d1fa 9197 [(set (match_operand:SI 3 "s_register_operand" "=r")
9198 (zero_extend:SI
9199 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9200 (match_operand:SI 2 "index_operand" "rJ")))))
9201 (set (match_operand:SI 0 "s_register_operand" "=r")
9202 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9203 "TARGET_ARM
9204 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9205 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9206 && (GET_CODE (operands[2]) != REG
9207 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9208 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
a2cd141b 9209 [(set_attr "type" "load_byte")
0d66636f 9210 (set_attr "predicable" "yes")]
9211)
9c08d1fa 9212
f7fbdd4a 9213(define_insn "*loadqisi_predec"
9c08d1fa 9214 [(set (match_operand:SI 3 "s_register_operand" "=r")
9215 (zero_extend:SI
9216 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9217 (match_operand:SI 2 "s_register_operand" "r")))))
9218 (set (match_operand:SI 0 "s_register_operand" "=r")
9219 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9220 "TARGET_ARM
9221 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9222 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9223 && (GET_CODE (operands[2]) != REG
9224 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9225 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
a2cd141b 9226 [(set_attr "type" "load_byte")
0d66636f 9227 (set_attr "predicable" "yes")]
9228)
9c08d1fa 9229
f7fbdd4a 9230(define_insn "*strsi_preinc"
9c08d1fa 9231 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9232 (match_operand:SI 2 "index_operand" "rJ")))
9233 (match_operand:SI 3 "s_register_operand" "r"))
9234 (set (match_operand:SI 0 "s_register_operand" "=r")
9235 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9236 "TARGET_ARM
9237 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9238 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9239 && (GET_CODE (operands[2]) != REG
9240 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9241 "str%?\\t%3, [%0, %2]!"
0d66636f 9242 [(set_attr "type" "store1")
9243 (set_attr "predicable" "yes")]
9244)
9c08d1fa 9245
cbd60e74 9246(define_insn "*strsi_predec"
9c08d1fa 9247 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9248 (match_operand:SI 2 "s_register_operand" "r")))
9249 (match_operand:SI 3 "s_register_operand" "r"))
9250 (set (match_operand:SI 0 "s_register_operand" "=r")
9251 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9252 "TARGET_ARM
9253 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9254 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9255 && (GET_CODE (operands[2]) != REG
9256 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9257 "str%?\\t%3, [%0, -%2]!"
0d66636f 9258 [(set_attr "type" "store1")
9259 (set_attr "predicable" "yes")]
9260)
9c08d1fa 9261
f7fbdd4a 9262(define_insn "*loadsi_preinc"
9c08d1fa 9263 [(set (match_operand:SI 3 "s_register_operand" "=r")
9264 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9265 (match_operand:SI 2 "index_operand" "rJ"))))
9266 (set (match_operand:SI 0 "s_register_operand" "=r")
9267 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9268 "TARGET_ARM
9269 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9270 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9271 && (GET_CODE (operands[2]) != REG
9272 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9273 "ldr%?\\t%3, [%0, %2]!"
a2cd141b 9274 [(set_attr "type" "load1")
0d66636f 9275 (set_attr "predicable" "yes")]
9276)
9c08d1fa 9277
f7fbdd4a 9278(define_insn "*loadsi_predec"
9c08d1fa 9279 [(set (match_operand:SI 3 "s_register_operand" "=r")
9280 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9281 (match_operand:SI 2 "s_register_operand" "r"))))
9282 (set (match_operand:SI 0 "s_register_operand" "=r")
9283 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 9284 "TARGET_ARM
9285 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9286 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9287 && (GET_CODE (operands[2]) != REG
9288 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
40dbec34 9289 "ldr%?\\t%3, [%0, -%2]!"
a2cd141b 9290 [(set_attr "type" "load1")
0d66636f 9291 (set_attr "predicable" "yes")]
9292)
9c08d1fa 9293
f7fbdd4a 9294(define_insn "*strqi_shiftpreinc"
9c08d1fa 9295 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9296 [(match_operand:SI 3 "s_register_operand" "r")
9297 (match_operand:SI 4 "const_shift_operand" "n")])
9298 (match_operand:SI 1 "s_register_operand" "0")))
9299 (match_operand:QI 5 "s_register_operand" "r"))
9300 (set (match_operand:SI 0 "s_register_operand" "=r")
9301 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9302 (match_dup 1)))]
cffb2a26 9303 "TARGET_ARM
9304 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9305 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9306 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 9307 "str%?b\\t%5, [%0, %3%S2]!"
0d66636f 9308 [(set_attr "type" "store1")
9309 (set_attr "predicable" "yes")]
9310)
9c08d1fa 9311
f7fbdd4a 9312(define_insn "*strqi_shiftpredec"
9c08d1fa 9313 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9314 (match_operator:SI 2 "shift_operator"
9315 [(match_operand:SI 3 "s_register_operand" "r")
9316 (match_operand:SI 4 "const_shift_operand" "n")])))
9317 (match_operand:QI 5 "s_register_operand" "r"))
9318 (set (match_operand:SI 0 "s_register_operand" "=r")
9319 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9320 (match_dup 4)])))]
cffb2a26 9321 "TARGET_ARM
9322 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9323 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9324 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 9325 "str%?b\\t%5, [%0, -%3%S2]!"
0d66636f 9326 [(set_attr "type" "store1")
9327 (set_attr "predicable" "yes")]
9328)
9c08d1fa 9329
f7fbdd4a 9330(define_insn "*loadqi_shiftpreinc"
9c08d1fa 9331 [(set (match_operand:QI 5 "s_register_operand" "=r")
9332 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9333 [(match_operand:SI 3 "s_register_operand" "r")
9334 (match_operand:SI 4 "const_shift_operand" "n")])
9335 (match_operand:SI 1 "s_register_operand" "0"))))
9336 (set (match_operand:SI 0 "s_register_operand" "=r")
9337 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9338 (match_dup 1)))]
cffb2a26 9339 "TARGET_ARM
9340 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9341 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9342 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 9343 "ldr%?b\\t%5, [%0, %3%S2]!"
a2cd141b 9344 [(set_attr "type" "load_byte")
0d66636f 9345 (set_attr "predicable" "yes")]
9346)
9c08d1fa 9347
f7fbdd4a 9348(define_insn "*loadqi_shiftpredec"
9c08d1fa 9349 [(set (match_operand:QI 5 "s_register_operand" "=r")
9350 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9351 (match_operator:SI 2 "shift_operator"
9352 [(match_operand:SI 3 "s_register_operand" "r")
9353 (match_operand:SI 4 "const_shift_operand" "n")]))))
9354 (set (match_operand:SI 0 "s_register_operand" "=r")
9355 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9356 (match_dup 4)])))]
cffb2a26 9357 "TARGET_ARM
9358 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9359 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9360 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 9361 "ldr%?b\\t%5, [%0, -%3%S2]!"
a2cd141b 9362 [(set_attr "type" "load_byte")
0d66636f 9363 (set_attr "predicable" "yes")]
9364)
9c08d1fa 9365
f7fbdd4a 9366(define_insn "*strsi_shiftpreinc"
9c08d1fa 9367 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9368 [(match_operand:SI 3 "s_register_operand" "r")
9369 (match_operand:SI 4 "const_shift_operand" "n")])
9370 (match_operand:SI 1 "s_register_operand" "0")))
9371 (match_operand:SI 5 "s_register_operand" "r"))
9372 (set (match_operand:SI 0 "s_register_operand" "=r")
9373 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9374 (match_dup 1)))]
cffb2a26 9375 "TARGET_ARM
9376 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9377 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9378 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 9379 "str%?\\t%5, [%0, %3%S2]!"
0d66636f 9380 [(set_attr "type" "store1")
9381 (set_attr "predicable" "yes")]
9382)
9c08d1fa 9383
f7fbdd4a 9384(define_insn "*strsi_shiftpredec"
9c08d1fa 9385 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9386 (match_operator:SI 2 "shift_operator"
9387 [(match_operand:SI 3 "s_register_operand" "r")
9388 (match_operand:SI 4 "const_shift_operand" "n")])))
9389 (match_operand:SI 5 "s_register_operand" "r"))
9390 (set (match_operand:SI 0 "s_register_operand" "=r")
9391 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9392 (match_dup 4)])))]
cffb2a26 9393 "TARGET_ARM
9394 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9395 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9396 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 9397 "str%?\\t%5, [%0, -%3%S2]!"
0d66636f 9398 [(set_attr "type" "store1")
9399 (set_attr "predicable" "yes")]
9400)
9c08d1fa 9401
cbd60e74 9402(define_insn "*loadsi_shiftpreinc"
9c08d1fa 9403 [(set (match_operand:SI 5 "s_register_operand" "=r")
9404 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9405 [(match_operand:SI 3 "s_register_operand" "r")
9406 (match_operand:SI 4 "const_shift_operand" "n")])
9407 (match_operand:SI 1 "s_register_operand" "0"))))
9408 (set (match_operand:SI 0 "s_register_operand" "=r")
9409 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9410 (match_dup 1)))]
cffb2a26 9411 "TARGET_ARM
9412 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9413 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9414 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 9415 "ldr%?\\t%5, [%0, %3%S2]!"
a2cd141b 9416 [(set_attr "type" "load1")
0d66636f 9417 (set_attr "predicable" "yes")]
9418)
9c08d1fa 9419
cbd60e74 9420(define_insn "*loadsi_shiftpredec"
9c08d1fa 9421 [(set (match_operand:SI 5 "s_register_operand" "=r")
9422 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9423 (match_operator:SI 2 "shift_operator"
9424 [(match_operand:SI 3 "s_register_operand" "r")
9425 (match_operand:SI 4 "const_shift_operand" "n")]))))
9426 (set (match_operand:SI 0 "s_register_operand" "=r")
9427 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9428 (match_dup 4)])))]
cffb2a26 9429 "TARGET_ARM
9430 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9c08d1fa 9431 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9432 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
87b22bf7 9433 "ldr%?\\t%5, [%0, -%3%S2]!"
a2cd141b 9434 [(set_attr "type" "load1")
0d66636f 9435 (set_attr "predicable" "yes")])
9c08d1fa 9436
9c08d1fa 9437; It can also support extended post-inc expressions, but combine doesn't
9438; try these....
9439; It doesn't seem worth adding peepholes for anything but the most common
9440; cases since, unlike combine, the increment must immediately follow the load
9441; for this pattern to match.
fc40f3ac 9442; We must watch to see that the source/destination register isn't also the
9443; same as the base address register, and that if the index is a register,
9444; that it is not the same as the base address register. In such cases the
e3e08e7f 9445; instruction that we would generate would have UNPREDICTABLE behavior so
fc40f3ac 9446; we cannot use it.
9c08d1fa 9447
9448(define_peephole
9449 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9450 (match_operand:QI 2 "s_register_operand" "r"))
9451 (set (match_dup 0)
9452 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 9453 "TARGET_ARM
9454 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9455 && (GET_CODE (operands[1]) != REG
9456 || (REGNO (operands[1]) != REGNO (operands[0])))"
9457 "str%?b\\t%2, [%0], %1"
9458)
9c08d1fa 9459
9460(define_peephole
9461 [(set (match_operand:QI 0 "s_register_operand" "=r")
9462 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9463 (set (match_dup 1)
9464 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
fc40f3ac 9465 "TARGET_ARM
9466 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 9467 && (GET_CODE (operands[2]) != REG
9468 || REGNO(operands[0]) != REGNO (operands[2]))"
9469 "ldr%?b\\t%0, [%1], %2"
9470)
9c08d1fa 9471
9472(define_peephole
9473 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9474 (match_operand:SI 2 "s_register_operand" "r"))
9475 (set (match_dup 0)
9476 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
fc40f3ac 9477 "TARGET_ARM
9478 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9479 && (GET_CODE (operands[1]) != REG
9480 || (REGNO (operands[1]) != REGNO (operands[0])))"
9481 "str%?\\t%2, [%0], %1"
9482)
9c08d1fa 9483
9c08d1fa 9484(define_peephole
9485 [(set (match_operand:SI 0 "s_register_operand" "=r")
9486 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9487 (set (match_dup 1)
9488 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
cffb2a26 9489 "TARGET_ARM
fc40f3ac 9490 && REGNO (operands[0]) != REGNO(operands[1])
215b30b3 9491 && (GET_CODE (operands[2]) != REG
9492 || REGNO(operands[0]) != REGNO (operands[2]))"
9493 "ldr%?\\t%0, [%1], %2"
9494)
9c08d1fa 9495
c7597b5d 9496(define_peephole
9497 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9498 (match_operand:SI 1 "index_operand" "rJ")))
9499 (match_operand:QI 2 "s_register_operand" "r"))
9500 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
fc40f3ac 9501 "TARGET_ARM
9502 && (REGNO (operands[2]) != REGNO (operands[0]))
215b30b3 9503 && (GET_CODE (operands[1]) != REG
9504 || (REGNO (operands[1]) != REGNO (operands[0])))"
9505 "str%?b\\t%2, [%0, %1]!"
9506)
c7597b5d 9507
9508(define_peephole
9509 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9510 [(match_operand:SI 0 "s_register_operand" "r")
87b22bf7 9511 (match_operand:SI 1 "const_int_operand" "n")])
c7597b5d 9512 (match_operand:SI 2 "s_register_operand" "+r")))
9513 (match_operand:QI 3 "s_register_operand" "r"))
9514 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9515 (match_dup 2)))]
fc40f3ac 9516 "TARGET_ARM
9517 && (REGNO (operands[3]) != REGNO (operands[2]))
9518 && (REGNO (operands[0]) != REGNO (operands[2]))"
215b30b3 9519 "str%?b\\t%3, [%2, %0%S4]!"
9520)
c7597b5d 9521
9c08d1fa 9522; This pattern is never tried by combine, so do it as a peephole
9523
a0f94409 9524(define_peephole2
372575c7 9525 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9526 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9527 (set (reg:CC CC_REGNUM)
aea4c774 9528 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9529 "TARGET_ARM"
a0f94409 9530 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9531 (set (match_dup 0) (match_dup 1))])]
9532 ""
0d66636f 9533)
9c08d1fa 9534
675d848d 9535; Peepholes to spot possible load- and store-multiples, if the ordering is
9536; reversed, check that the memory references aren't volatile.
9c08d1fa 9537
9538(define_peephole
9539 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9540 (match_operand:SI 4 "memory_operand" "m"))
9541 (set (match_operand:SI 1 "s_register_operand" "=r")
9542 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 9543 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9544 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 9545 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 9546 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 9547 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9548 "*
9549 return emit_ldm_seq (operands, 4);
215b30b3 9550 "
9551)
9c08d1fa 9552
9553(define_peephole
9554 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9555 (match_operand:SI 3 "memory_operand" "m"))
9556 (set (match_operand:SI 1 "s_register_operand" "=r")
9557 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 9558 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9559 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 9560 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9561 "*
9562 return emit_ldm_seq (operands, 3);
215b30b3 9563 "
9564)
9c08d1fa 9565
9566(define_peephole
9567 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9568 (match_operand:SI 2 "memory_operand" "m"))
9569 (set (match_operand:SI 1 "s_register_operand" "=r")
9570 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 9571 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9572 "*
9573 return emit_ldm_seq (operands, 2);
215b30b3 9574 "
9575)
9c08d1fa 9576
9577(define_peephole
aea4c774 9578 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 9579 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9580 (set (match_operand:SI 5 "memory_operand" "=m")
9581 (match_operand:SI 1 "s_register_operand" "r"))
9582 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 9583 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 9584 (set (match_operand:SI 7 "memory_operand" "=m")
9585 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 9586 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9587 "*
9588 return emit_stm_seq (operands, 4);
215b30b3 9589 "
9590)
9c08d1fa 9591
9592(define_peephole
aea4c774 9593 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 9594 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9595 (set (match_operand:SI 4 "memory_operand" "=m")
9596 (match_operand:SI 1 "s_register_operand" "r"))
9597 (set (match_operand:SI 5 "memory_operand" "=m")
9598 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 9599 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9600 "*
9601 return emit_stm_seq (operands, 3);
215b30b3 9602 "
9603)
9c08d1fa 9604
9605(define_peephole
aea4c774 9606 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 9607 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9608 (set (match_operand:SI 3 "memory_operand" "=m")
9609 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 9610 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9611 "*
9612 return emit_stm_seq (operands, 2);
215b30b3 9613 "
9614)
9c08d1fa 9615
9c08d1fa 9616(define_split
9617 [(set (match_operand:SI 0 "s_register_operand" "")
9618 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9619 (const_int 0))
8fa3ba89 9620 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9621 [(match_operand:SI 3 "s_register_operand" "")
9622 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9623 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9624 "TARGET_ARM"
9c08d1fa 9625 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9626 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9627 (match_dup 5)))]
215b30b3 9628 ""
9629)
9c08d1fa 9630
aea4c774 9631;; This split can be used because CC_Z mode implies that the following
9632;; branch will be an equality, or an unsigned inequality, so the sign
9633;; extension is not needed.
9c08d1fa 9634
aea4c774 9635(define_split
bd5b4116 9636 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9637 (compare:CC_Z
9638 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9639 (const_int 24))
aea4c774 9640 (match_operand 1 "const_int_operand" "")))
9641 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9642 "TARGET_ARM
9643 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9644 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9645 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9646 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9647 "
9c08d1fa 9648 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9649 "
9650)
9c08d1fa 9651
87b22bf7 9652(define_expand "prologue"
9653 [(clobber (const_int 0))]
cffb2a26 9654 "TARGET_EITHER"
9655 "if (TARGET_ARM)
9656 arm_expand_prologue ();
9657 else
9658 thumb_expand_prologue ();
87b22bf7 9659 DONE;
cffb2a26 9660 "
9661)
87b22bf7 9662
56d27660 9663(define_expand "epilogue"
e1159bbe 9664 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9665 "TARGET_EITHER"
56d27660 9666 "
cffb2a26 9667 if (TARGET_THUMB)
9668 thumb_expand_epilogue ();
9669 else if (USE_RETURN_INSN (FALSE))
56d27660 9670 {
9671 emit_jump_insn (gen_return ());
9672 DONE;
9673 }
cffb2a26 9674 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9675 gen_rtvec (1,
9676 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9677 VUNSPEC_EPILOGUE));
cffb2a26 9678 DONE;
9679 "
9680)
56d27660 9681
ef5651d0 9682;; Note - although unspec_volatile's USE all hard registers,
9683;; USEs are ignored after relaod has completed. Thus we need
9684;; to add an unspec of the link register to ensure that flow
9685;; does not think that it is unused by the sibcall branch that
9686;; will replace the standard function epilogue.
1c494086 9687(define_insn "sibcall_epilogue"
ef5651d0 9688 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9689 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
1c494086 9690 "TARGET_ARM"
9691 "*
ffc9d00c 9692 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9693 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9694 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9695 "
9696;; Length is absolute worst case
9697 [(set_attr "length" "44")
defc47cf 9698 (set_attr "type" "block")
9699 ;; We don't clobber the conditions, but the potential length of this
9700 ;; operation is sufficient to make conditionalizing the sequence
9701 ;; unlikely to be profitable.
9702 (set_attr "conds" "clob")]
1c494086 9703)
9704
cffb2a26 9705(define_insn "*epilogue_insns"
e1159bbe 9706 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9707 "TARGET_EITHER"
56d27660 9708 "*
cffb2a26 9709 if (TARGET_ARM)
ffc9d00c 9710 return arm_output_epilogue (NULL);
cffb2a26 9711 else /* TARGET_THUMB */
9712 return thumb_unexpanded_epilogue ();
9713 "
215b30b3 9714 ; Length is absolute worst case
cffb2a26 9715 [(set_attr "length" "44")
defc47cf 9716 (set_attr "type" "block")
9717 ;; We don't clobber the conditions, but the potential length of this
9718 ;; operation is sufficient to make conditionalizing the sequence
9719 ;; unlikely to be profitable.
9720 (set_attr "conds" "clob")]
cffb2a26 9721)
9722
9723(define_expand "eh_epilogue"
7db9af5d 9724 [(use (match_operand:SI 0 "register_operand" ""))
9725 (use (match_operand:SI 1 "register_operand" ""))
9726 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 9727 "TARGET_EITHER"
9728 "
215b30b3 9729 {
9730 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9731 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9732 {
9733 rtx ra = gen_rtx_REG (Pmode, 2);
9734
9735 emit_move_insn (ra, operands[2]);
9736 operands[2] = ra;
9737 }
5cf3595a 9738 /* This is a hack -- we may have crystalized the function type too
9739 early. */
9740 cfun->machine->func_type = 0;
215b30b3 9741 }"
9742)
56d27660 9743
9c08d1fa 9744;; This split is only used during output to reduce the number of patterns
9745;; that need assembler instructions adding to them. We allowed the setting
9746;; of the conditions to be implicit during rtl generation so that
9747;; the conditional compare patterns would work. However this conflicts to
8a18b90c 9748;; some extent with the conditional data operations, so we have to split them
9c08d1fa 9749;; up again here.
9750
9751(define_split
9752 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 9753 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9754 [(match_operand 2 "" "") (match_operand 3 "" "")])
9755 (match_dup 0)
9756 (match_operand 4 "" "")))
bd5b4116 9757 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9758 "TARGET_ARM && reload_completed"
8fa3ba89 9759 [(set (match_dup 5) (match_dup 6))
9760 (cond_exec (match_dup 7)
9761 (set (match_dup 0) (match_dup 4)))]
9762 "
9763 {
9764 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9765 operands[2], operands[3]);
9766 enum rtx_code rc = GET_CODE (operands[1]);
9767
bd5b4116 9768 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9769 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9770 if (mode == CCFPmode || mode == CCFPEmode)
9771 rc = reverse_condition_maybe_unordered (rc);
9772 else
9773 rc = reverse_condition (rc);
9774
9775 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9776 }"
9777)
9778
9779(define_split
9780 [(set (match_operand:SI 0 "s_register_operand" "")
9781 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9782 [(match_operand 2 "" "") (match_operand 3 "" "")])
9783 (match_operand 4 "" "")
9784 (match_dup 0)))
bd5b4116 9785 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9786 "TARGET_ARM && reload_completed"
8fa3ba89 9787 [(set (match_dup 5) (match_dup 6))
9788 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9789 (set (match_dup 0) (match_dup 4)))]
9790 "
9791 {
9792 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9793 operands[2], operands[3]);
9794
bd5b4116 9795 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9796 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9797 }"
9798)
9799
9800(define_split
9801 [(set (match_operand:SI 0 "s_register_operand" "")
9802 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 9803 [(match_operand 2 "" "") (match_operand 3 "" "")])
9804 (match_operand 4 "" "")
9805 (match_operand 5 "" "")))
bd5b4116 9806 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9807 "TARGET_ARM && reload_completed"
8fa3ba89 9808 [(set (match_dup 6) (match_dup 7))
9809 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9810 (set (match_dup 0) (match_dup 4)))
9811 (cond_exec (match_dup 8)
9812 (set (match_dup 0) (match_dup 5)))]
9813 "
9814 {
9815 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9816 operands[2], operands[3]);
9817 enum rtx_code rc = GET_CODE (operands[1]);
9818
bd5b4116 9819 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9820 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9821 if (mode == CCFPmode || mode == CCFPEmode)
9822 rc = reverse_condition_maybe_unordered (rc);
9823 else
9824 rc = reverse_condition (rc);
9825
9826 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9827 }"
9828)
9829
cffb2a26 9830(define_split
9831 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 9832 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 9833 [(match_operand:SI 2 "s_register_operand" "")
9834 (match_operand:SI 3 "arm_add_operand" "")])
9835 (match_operand:SI 4 "arm_rhs_operand" "")
9836 (not:SI
9837 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 9838 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9839 "TARGET_ARM && reload_completed"
cffb2a26 9840 [(set (match_dup 6) (match_dup 7))
f6c53574 9841 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9842 (set (match_dup 0) (match_dup 4)))
9843 (cond_exec (match_dup 8)
9844 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 9845 "
215b30b3 9846 {
9847 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9848 operands[2], operands[3]);
f6c53574 9849 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 9850
bd5b4116 9851 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 9852 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 9853 if (mode == CCFPmode || mode == CCFPEmode)
9854 rc = reverse_condition_maybe_unordered (rc);
9855 else
9856 rc = reverse_condition (rc);
9857
9858 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 9859 }"
9860)
cffb2a26 9861
9862(define_insn "*cond_move_not"
9863 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9864 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 9865 [(match_operand 3 "cc_register" "") (const_int 0)])
9866 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9867 (not:SI
9868 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9869 "TARGET_ARM"
9870 "@
9871 mvn%D4\\t%0, %2
9872 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 9873 [(set_attr "conds" "use")
9874 (set_attr "length" "4,8")]
9875)
cffb2a26 9876
9c08d1fa 9877;; The next two patterns occur when an AND operation is followed by a
9878;; scc insn sequence
9879
f7fbdd4a 9880(define_insn "*sign_extract_onebit"
9c08d1fa 9881 [(set (match_operand:SI 0 "s_register_operand" "=r")
9882 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9883 (const_int 1)
ed750274 9884 (match_operand:SI 2 "const_int_operand" "n")))
9885 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9886 "TARGET_ARM"
9c08d1fa 9887 "*
0d66636f 9888 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9889 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9890 return \"mvnne\\t%0, #0\";
9891 "
9892 [(set_attr "conds" "clob")
9893 (set_attr "length" "8")]
9894)
9c08d1fa 9895
f7fbdd4a 9896(define_insn "*not_signextract_onebit"
9c08d1fa 9897 [(set (match_operand:SI 0 "s_register_operand" "=r")
9898 (not:SI
9899 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9900 (const_int 1)
ed750274 9901 (match_operand:SI 2 "const_int_operand" "n"))))
9902 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9903 "TARGET_ARM"
9c08d1fa 9904 "*
0d66636f 9905 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9906 output_asm_insn (\"tst\\t%1, %2\", operands);
9907 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9908 return \"movne\\t%0, #0\";
9909 "
9910 [(set_attr "conds" "clob")
9911 (set_attr "length" "12")]
9912)
87b22bf7 9913
0d66636f 9914;; Push multiple registers to the stack. Registers are in parallel (use ...)
9915;; expressions. For simplicity, the first register is also in the unspec
9916;; part.
f7fbdd4a 9917(define_insn "*push_multi"
87b22bf7 9918 [(match_parallel 2 "multi_register_push"
9919 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 9920 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9921 UNSPEC_PUSH_MULT))])]
cffb2a26 9922 "TARGET_ARM"
87b22bf7 9923 "*
215b30b3 9924 {
9925 int num_saves = XVECLEN (operands[2], 0);
ed593f11 9926
215b30b3 9927 /* For the StrongARM at least it is faster to
9928 use STR to store only a single register. */
6079f055 9929 if (num_saves == 1)
215b30b3 9930 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9931 else
9932 {
9933 int i;
9934 char pattern[100];
ed593f11 9935
215b30b3 9936 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9937
6079f055 9938 for (i = 1; i < num_saves; i++)
215b30b3 9939 {
9940 strcat (pattern, \", %|\");
9941 strcat (pattern,
9942 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9943 }
9944
9945 strcat (pattern, \"}\");
9946 output_asm_insn (pattern, operands);
9947 }
9948
9949 return \"\";
9950 }"
9951 [(set_attr "type" "store4")]
9952)
f7fbdd4a 9953
4c58c898 9954(define_insn "stack_tie"
9955 [(set (mem:BLK (scratch))
9956 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9957 (match_operand:SI 1 "s_register_operand" "r")]
9958 UNSPEC_PRLG_STK))]
9959 ""
9960 ""
9961 [(set_attr "length" "0")]
9962)
9963
3398e91d 9964;; Similarly for the floating point registers
7b1d2fc4 9965(define_insn "*push_fp_multi"
9966 [(match_parallel 2 "multi_register_push"
9967 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 9968 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9969 UNSPEC_PUSH_MULT))])]
a2cd141b 9970 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 9971 "*
215b30b3 9972 {
9973 char pattern[100];
7b1d2fc4 9974
215b30b3 9975 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9976 output_asm_insn (pattern, operands);
9977 return \"\";
9978 }"
9979 [(set_attr "type" "f_store")]
9980)
7b1d2fc4 9981
f7fbdd4a 9982;; Special patterns for dealing with the constant pool
9983
cffb2a26 9984(define_insn "align_4"
e1159bbe 9985 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 9986 "TARGET_EITHER"
f7fbdd4a 9987 "*
cffb2a26 9988 assemble_align (32);
f7fbdd4a 9989 return \"\";
cffb2a26 9990 "
9991)
f7fbdd4a 9992
755eb2b4 9993(define_insn "align_8"
9994 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 9995 "TARGET_EITHER"
755eb2b4 9996 "*
9997 assemble_align (64);
9998 return \"\";
9999 "
10000)
10001
cffb2a26 10002(define_insn "consttable_end"
e1159bbe 10003 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 10004 "TARGET_EITHER"
f7fbdd4a 10005 "*
cffb2a26 10006 making_const_table = FALSE;
f7fbdd4a 10007 return \"\";
cffb2a26 10008 "
10009)
f7fbdd4a 10010
cffb2a26 10011(define_insn "consttable_1"
e1159bbe 10012 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
cffb2a26 10013 "TARGET_THUMB"
f7fbdd4a 10014 "*
cffb2a26 10015 making_const_table = TRUE;
09d688ff 10016 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 10017 assemble_zeros (3);
f7fbdd4a 10018 return \"\";
cffb2a26 10019 "
10020 [(set_attr "length" "4")]
10021)
f7fbdd4a 10022
cffb2a26 10023(define_insn "consttable_2"
e1159bbe 10024 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
cffb2a26 10025 "TARGET_THUMB"
f7fbdd4a 10026 "*
cffb2a26 10027 making_const_table = TRUE;
09d688ff 10028 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 10029 assemble_zeros (2);
f7fbdd4a 10030 return \"\";
cffb2a26 10031 "
10032 [(set_attr "length" "4")]
10033)
10034
10035(define_insn "consttable_4"
e1159bbe 10036 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 10037 "TARGET_EITHER"
10038 "*
10039 {
10040 making_const_table = TRUE;
10041 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10042 {
10043 case MODE_FLOAT:
10044 {
badfe841 10045 REAL_VALUE_TYPE r;
10046 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10047 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10048 break;
10049 }
10050 default:
09d688ff 10051 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 10052 break;
10053 }
10054 return \"\";
10055 }"
10056 [(set_attr "length" "4")]
10057)
10058
10059(define_insn "consttable_8"
e1159bbe 10060 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 10061 "TARGET_EITHER"
10062 "*
10063 {
10064 making_const_table = TRUE;
10065 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10066 {
10067 case MODE_FLOAT:
10068 {
badfe841 10069 REAL_VALUE_TYPE r;
10070 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10071 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 10072 break;
10073 }
10074 default:
09d688ff 10075 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10076 break;
10077 }
10078 return \"\";
10079 }"
10080 [(set_attr "length" "8")]
10081)
10082
10083;; Miscellaneous Thumb patterns
10084
fd957ef3 10085(define_expand "tablejump"
7db9af5d 10086 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10087 (use (label_ref (match_operand 1 "" "")))])]
10088 "TARGET_THUMB"
10089 "
10090 if (flag_pic)
10091 {
10092 /* Hopefully, CSE will eliminate this copy. */
10093 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10094 rtx reg2 = gen_reg_rtx (SImode);
10095
10096 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10097 operands[0] = reg2;
10098 }
10099 "
10100)
10101
10102(define_insn "*thumb_tablejump"
cffb2a26 10103 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10104 (use (label_ref (match_operand 1 "" "")))]
10105 "TARGET_THUMB"
fd957ef3 10106 "mov\\t%|pc, %0"
cffb2a26 10107 [(set_attr "length" "2")]
10108)
0d66636f 10109
331beb1a 10110;; V5 Instructions,
10111
8f4be2be 10112(define_insn "clzsi2"
10113 [(set (match_operand:SI 0 "s_register_operand" "=r")
10114 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
e1159bbe 10115 "TARGET_ARM && arm_arch5"
ee7cbe0e 10116 "clz%?\\t%0, %1"
10117 [(set_attr "predicable" "yes")])
331beb1a 10118
e1159bbe 10119(define_expand "ffssi2"
10120 [(set (match_operand:SI 0 "s_register_operand" "")
10121 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10122 "TARGET_ARM && arm_arch5"
10123 "
10124 {
10125 rtx t1, t2, t3;
10126
10127 t1 = gen_reg_rtx (SImode);
10128 t2 = gen_reg_rtx (SImode);
10129 t3 = gen_reg_rtx (SImode);
10130
10131 emit_insn (gen_negsi2 (t1, operands[1]));
10132 emit_insn (gen_andsi3 (t2, operands[1], t1));
8f4be2be 10133 emit_insn (gen_clzsi2 (t3, t2));
e1159bbe 10134 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10135 DONE;
10136 }"
10137)
10138
8f4be2be 10139(define_expand "ctzsi2"
10140 [(set (match_operand:SI 0 "s_register_operand" "")
10141 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10142 "TARGET_ARM && arm_arch5"
10143 "
10144 {
10145 rtx t1, t2, t3;
10146
10147 t1 = gen_reg_rtx (SImode);
10148 t2 = gen_reg_rtx (SImode);
10149 t3 = gen_reg_rtx (SImode);
10150
10151 emit_insn (gen_negsi2 (t1, operands[1]));
10152 emit_insn (gen_andsi3 (t2, operands[1], t1));
10153 emit_insn (gen_clzsi2 (t3, t2));
10154 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10155 DONE;
10156 }"
10157)
10158
e1159bbe 10159;; V5E instructions.
331beb1a 10160
10161(define_insn "prefetch"
f4e79814 10162 [(prefetch (match_operand:SI 0 "address_operand" "p")
10163 (match_operand:SI 1 "" "")
10164 (match_operand:SI 2 "" ""))]
e1159bbe 10165 "TARGET_ARM && arm_arch5e"
bcb7a8f6 10166 "pld\\t%a0")
331beb1a 10167
0d66636f 10168;; General predication pattern
10169
10170(define_cond_exec
10171 [(match_operator 0 "arm_comparison_operator"
10172 [(match_operand 1 "cc_register" "")
10173 (const_int 0)])]
10174 "TARGET_ARM"
10175 ""
10176)
10177
063a05c7 10178(define_insn "prologue_use"
10179 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10180 ""
10181 "%@ %0 needed for prologue"
10182)
7db9af5d 10183
10184;; Load the FPA co-processor patterns
10185(include "fpa.md")
10186;; Load the Maverick co-processor patterns
10187(include "cirrus.md")
755eb2b4 10188;; Load the Intel Wireless Multimedia Extension patterns
10189(include "iwmmxt.md")
a2cd141b 10190;; Load the VFP co-processor patterns
10191(include "vfp.md")
10192