]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
2006-01-26 Paul Brook <paul@codesourcery.com>
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
129a2fe4 1;;- Machine description for ARM for GNU compiler
063a05c7 2;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
2cb7d577 3;; 2001, 2002, 2003, 2004, 2005, 2006 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
dbddc6c4 22;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23;; Boston, MA 02110-1301, 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
ccd90aaa 33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
e1159bbe 35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
ccd90aaa 39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
e1159bbe 42 ]
43)
3c5afce6 44;; 3rd operand to select_dominance_cc_mode
45(define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50)
e1159bbe 51
9c08d1fa 52;; UNSPEC Usage:
8a18b90c 53;; Note: sin and cos are no-longer used.
e1159bbe 54
55(define_constants
56 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
60 ; operand 0 is the result,
61 ; operand 1 the parameter.
62 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63 ; operand 0 is the first register,
64 ; subsequent registers are in parallel (use ...)
65 ; expressions.
66 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
67 ; usage, that is, we will add the pic_register
68 ; value to it before trying to dereference it.
2c96dc5a 69 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
70 ; GLOBAL_OFFSET_TABLE. The operation is fully
71 ; described by the RTL but must be wrapped to
72 ; prevent combine from trying to rip it apart.
73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
e1159bbe 74 ; being scheduled before the stack adjustment insn.
063a05c7 75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
79 ; register to "use".
68121397 80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
8d232dc7 81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
f655717d 93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
6cdcb15c 94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95 ; instruction stream.
e1159bbe 96 ]
97)
98
215b30b3 99;; UNSPEC_VOLATILE Usage:
e1159bbe 100
101(define_constants
102 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
103 ; insn in the code.
104 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
105 ; instruction epilogue sequence that isn't expanded
106 ; into normal RTL. Used for both normal and sibcall
107 ; epilogues.
108 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
109 ; for inlined constants.
110 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
111 ; table.
112 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
113 ; an 8-bit object.
114 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
115 ; a 16-bit object.
116 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
117 ; a 32-bit object.
118 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
119 ; a 64-bit object.
755eb2b4 120 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
121 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
122 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
123 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
124 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
125 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
84cbcde5 126 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
4c44712e 127 ; handling.
e1159bbe 128 ]
129)
b11cae9e 130\f
e1159bbe 131;;---------------------------------------------------------------------------
9c08d1fa 132;; Attributes
133
215b30b3 134; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
135; generating ARM code. This is used to control the length of some insn
136; patterns that share the same RTL in both ARM and Thumb code.
1c494086 137(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
cffb2a26 138
215b30b3 139; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
140; scheduling decisions for the load unit and the multiplier.
74a71f7d 141(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
9c08d1fa 142
5ecb8da7 143; IS_XSCALE is set to 'yes' when compiling for XScale.
144(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
145
331beb1a 146;; Operand number of an input operand that is shifted. Zero if the
147;; given instruction does not shift one of its input operands.
331beb1a 148(define_attr "shift" "" (const_int 0))
149
3d91c5d6 150; Floating Point Unit. If we only have floating point emulation, then there
151; is no point in scheduling the floating point insns. (Well, for best
152; performance we should try and group them together).
a2cd141b 153(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
c7f506fd 154 (const (symbol_ref "arm_fpu_attr")))
3d91c5d6 155
094e994f 156; LENGTH of an instruction (in bytes)
157(define_attr "length" "" (const_int 4))
9c08d1fa 158
56d27660 159; POOL_RANGE is how far away from a constant pool entry that this insn
160; can be placed. If the distance is zero, then this insn will never
161; reference the pool.
cffb2a26 162; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
163; before its address.
56d27660 164(define_attr "pool_range" "" (const_int 0))
cffb2a26 165(define_attr "neg_pool_range" "" (const_int 0))
56d27660 166
215b30b3 167; An assembler sequence may clobber the condition codes without us knowing.
4d7a8451 168; If such an insn references the pool, then we have no way of knowing how,
169; so use the most conservative value for pool_range.
9c08d1fa 170(define_asm_attributes
4d7a8451 171 [(set_attr "conds" "clob")
172 (set_attr "length" "4")
173 (set_attr "pool_range" "250")])
9c08d1fa 174
a2cd141b 175;; The instruction used to implement a particular pattern. This
176;; information is used by pipeline descriptions to provide accurate
177;; scheduling information.
178
179(define_attr "insn"
180 "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"
181 (const_string "other"))
182
9c08d1fa 183; TYPE attribute is used to detect floating point instructions which, if
184; running on a co-processor can run in parallel with other, basic instructions
185; If write-buffer scheduling is enabled then it can also be used in the
186; scheduling of writes.
187
188; Classification of each insn
a2cd141b 189; alu any alu instruction that doesn't hit memory or fp
190; regs or have a shifted source operand
191; alu_shift any data instruction that doesn't hit memory or fp
192; regs, but has a source operand shifted by a constant
193; alu_shift_reg any data instruction that doesn't hit memory or fp
194; regs, but has a source operand shifted by a register value
f7fbdd4a 195; mult a multiply instruction
9c08d1fa 196; block blockage insn, this blocks all functional units
197; float a floating point arithmetic operation (subject to expansion)
3d91c5d6 198; fdivd DFmode floating point division
199; fdivs SFmode floating point division
200; fmul Floating point multiply
201; ffmul Fast floating point multiply
202; farith Floating point arithmetic (4 cycle)
203; ffarith Fast floating point arithmetic (2 cycle)
9c08d1fa 204; float_em a floating point arithmetic operation that is normally emulated
3d91c5d6 205; even on a machine with an fpa.
9c08d1fa 206; f_load a floating point load from memory
207; f_store a floating point store to memory
9aff9709 208; f_load[sd] single/double load from memory
209; f_store[sd] single/double store to memory
c0e1af52 210; f_flag a transfer of co-processor flags to the CPSR
9c08d1fa 211; f_mem_r a transfer of a floating point register to a real reg via mem
212; r_mem_f the reverse of f_mem_r
213; f_2_r fast transfer float to arm (no memory needed)
214; r_2_f fast transfer arm to float
c0e1af52 215; f_cvt convert floating<->integral
a2cd141b 216; branch a branch
9c08d1fa 217; call a subroutine call
a2cd141b 218; load_byte load byte(s) from memory to arm registers
219; load1 load 1 word from memory to arm registers
220; load2 load 2 words from memory to arm registers
221; load3 load 3 words from memory to arm registers
222; load4 load 4 words from memory to arm registers
223; store store 1 word to memory from arm registers
9c08d1fa 224; store2 store 2 words
225; store3 store 3 words
a2cd141b 226; store4 store 4 (or more) words
2c6c7d8b 227; Additions for Cirrus Maverick co-processor:
228; mav_farith Floating point arithmetic (4 cycle)
229; mav_dmult Double multiplies (7 cycle)
9c08d1fa 230;
231(define_attr "type"
c0e1af52 232 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
a2cd141b 233 (if_then_else
234 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
235 (const_string "mult")
236 (const_string "alu")))
9c08d1fa 237
9888ad6d 238; Load scheduling, set from the arm_ld_sched variable
457275b6 239; initialized by arm_override_options()
9888ad6d 240(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
849170fd 241
f7fbdd4a 242; condition codes: this one is used by final_prescan_insn to speed up
243; conditionalizing instructions. It saves having to scan the rtl to see if
244; it uses or alters the condition codes.
215b30b3 245;
f7fbdd4a 246; USE means that the condition codes are used by the insn in the process of
215b30b3 247; outputting code, this means (at present) that we can't use the insn in
248; inlined branches
249;
f7fbdd4a 250; SET means that the purpose of the insn is to set the condition codes in a
215b30b3 251; well defined manner.
252;
f7fbdd4a 253; CLOB means that the condition codes are altered in an undefined manner, if
215b30b3 254; they are altered at all
255;
8fa3ba89 256; JUMP_CLOB is used when the condition cannot be represented by a single
215b30b3 257; instruction (UNEQ and LTGT). These cannot be predicated.
258;
f7fbdd4a 259; NOCOND means that the condition codes are neither altered nor affect the
215b30b3 260; output of this insn
f7fbdd4a 261
262(define_attr "conds" "use,set,clob,jump_clob,nocond"
263 (if_then_else (eq_attr "type" "call")
c1a66faf 264 (const_string "clob")
f7fbdd4a 265 (const_string "nocond")))
266
215b30b3 267; Predicable means that the insn can be conditionally executed based on
268; an automatically added predicate (additional patterns are generated by
269; gen...). We default to 'no' because no Thumb patterns match this rule
270; and not all ARM patterns do.
0d66636f 271(define_attr "predicable" "no,yes" (const_string "no"))
272
129a2fe4 273; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
274; have one. Later ones, such as StrongARM, have write-back caches, so don't
8d232dc7 275; suffer blockages enough to warrant modelling this (and it can adversely
129a2fe4 276; affect the schedule).
74a71f7d 277(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
129a2fe4 278
215b30b3 279; WRITE_CONFLICT implies that a read following an unrelated write is likely
280; to stall the processor. Used with model_wbuf above.
9c08d1fa 281(define_attr "write_conflict" "no,yes"
282 (if_then_else (eq_attr "type"
a2cd141b 283 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
9c08d1fa 284 (const_string "yes")
285 (const_string "no")))
286
215b30b3 287; Classify the insns into those that take one cycle and those that take more
288; than one on the main cpu execution unit.
f7fbdd4a 289(define_attr "core_cycles" "single,multi"
290 (if_then_else (eq_attr "type"
a2cd141b 291 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
f7fbdd4a 292 (const_string "single")
293 (const_string "multi")))
294
cffb2a26 295;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
215b30b3 296;; distant label. Only applicable to Thumb code.
cffb2a26 297(define_attr "far_jump" "yes,no" (const_string "no"))
298
d51f92df 299
300;;---------------------------------------------------------------------------
301;; Mode macros
302
303; A list of modes that are exactly 64 bits in size. We use this to expand
304; some splits that are the same for all modes when operating on ARM
305; registers.
306(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
307
308;;---------------------------------------------------------------------------
309;; Predicates
310
9c9db025 311(include "predicates.md")
312
a2cd141b 313;;---------------------------------------------------------------------------
314;; Pipeline descriptions
215b30b3 315
06469f9e 316;; Processor type. This is created automatically from arm-cores.def.
317(include "arm-tune.md")
331beb1a 318
a2cd141b 319;; True if the generic scheduling description should be used.
320
321(define_attr "generic_sched" "yes,no"
4d5cb40d 322 (const (if_then_else
c0e1af52 323 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
4d5cb40d 324 (const_string "no")
325 (const_string "yes"))))
326
c0e1af52 327(define_attr "generic_vfp" "yes,no"
328 (const (if_then_else
329 (and (eq_attr "fpu" "vfp")
330 (eq_attr "tune" "!arm1020e,arm1022e"))
331 (const_string "yes")
332 (const_string "no"))))
333
a2cd141b 334(include "arm-generic.md")
335(include "arm926ejs.md")
c0e1af52 336(include "arm1020e.md")
a2cd141b 337(include "arm1026ejs.md")
338(include "arm1136jfs.md")
3586df96 339
9c08d1fa 340\f
215b30b3 341;;---------------------------------------------------------------------------
e1159bbe 342;; Insn patterns
343;;
a0f94409 344;; Addition insns.
215b30b3 345
9c08d1fa 346;; Note: For DImode insns, there is normally no reason why operands should
347;; not be in the same register, what we don't want is for something being
348;; written to partially overlap something that is an input.
7d57ec45 349;; Cirrus 64bit additions should not be split because we have a native
350;; 64bit addition instructions.
9c08d1fa 351
cffb2a26 352(define_expand "adddi3"
353 [(parallel
215b30b3 354 [(set (match_operand:DI 0 "s_register_operand" "")
cffb2a26 355 (plus:DI (match_operand:DI 1 "s_register_operand" "")
356 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 357 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 358 "TARGET_EITHER"
359 "
a2cd141b 360 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
7d57ec45 361 {
362 if (!cirrus_fp_register (operands[0], DImode))
363 operands[0] = force_reg (DImode, operands[0]);
364 if (!cirrus_fp_register (operands[1], DImode))
365 operands[1] = force_reg (DImode, operands[1]);
366 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
367 DONE;
368 }
369
cffb2a26 370 if (TARGET_THUMB)
371 {
372 if (GET_CODE (operands[1]) != REG)
373 operands[1] = force_reg (SImode, operands[1]);
374 if (GET_CODE (operands[2]) != REG)
375 operands[2] = force_reg (SImode, operands[2]);
376 }
377 "
378)
379
380(define_insn "*thumb_adddi3"
381 [(set (match_operand:DI 0 "register_operand" "=l")
382 (plus:DI (match_operand:DI 1 "register_operand" "%0")
215b30b3 383 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 384 (clobber (reg:CC CC_REGNUM))
cffb2a26 385 ]
386 "TARGET_THUMB"
387 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388 [(set_attr "length" "4")]
389)
390
a0f94409 391(define_insn_and_split "*arm_adddi3"
cffb2a26 392 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
215b30b3 393 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394 (match_operand:DI 2 "s_register_operand" "r, 0")))
bd5b4116 395 (clobber (reg:CC CC_REGNUM))]
a2cd141b 396 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 397 "#"
a0f94409 398 "TARGET_ARM && reload_completed"
399 [(parallel [(set (reg:CC_C CC_REGNUM)
400 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
401 (match_dup 1)))
402 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404 (plus:SI (match_dup 4) (match_dup 5))))]
405 "
406 {
407 operands[3] = gen_highpart (SImode, operands[0]);
408 operands[0] = gen_lowpart (SImode, operands[0]);
409 operands[4] = gen_highpart (SImode, operands[1]);
410 operands[1] = gen_lowpart (SImode, operands[1]);
411 operands[5] = gen_highpart (SImode, operands[2]);
412 operands[2] = gen_lowpart (SImode, operands[2]);
413 }"
cffb2a26 414 [(set_attr "conds" "clob")
415 (set_attr "length" "8")]
416)
9c08d1fa 417
a0f94409 418(define_insn_and_split "*adddi_sesidi_di"
9c08d1fa 419 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420 (plus:DI (sign_extend:DI
97499065 421 (match_operand:SI 2 "s_register_operand" "r,r"))
422 (match_operand:DI 1 "s_register_operand" "r,0")))
bd5b4116 423 (clobber (reg:CC CC_REGNUM))]
a2cd141b 424 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 425 "#"
a0f94409 426 "TARGET_ARM && reload_completed"
427 [(parallel [(set (reg:CC_C CC_REGNUM)
428 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
429 (match_dup 1)))
430 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432 (plus:SI (ashiftrt:SI (match_dup 2)
433 (const_int 31))
434 (match_dup 4))))]
435 "
436 {
437 operands[3] = gen_highpart (SImode, operands[0]);
438 operands[0] = gen_lowpart (SImode, operands[0]);
439 operands[4] = gen_highpart (SImode, operands[1]);
440 operands[1] = gen_lowpart (SImode, operands[1]);
441 operands[2] = gen_lowpart (SImode, operands[2]);
442 }"
215b30b3 443 [(set_attr "conds" "clob")
444 (set_attr "length" "8")]
445)
9c08d1fa 446
a0f94409 447(define_insn_and_split "*adddi_zesidi_di"
9c08d1fa 448 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449 (plus:DI (zero_extend:DI
97499065 450 (match_operand:SI 2 "s_register_operand" "r,r"))
451 (match_operand:DI 1 "s_register_operand" "r,0")))
a0f94409 452 (clobber (reg:CC CC_REGNUM))]
a2cd141b 453 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
33782ec7 454 "#"
a0f94409 455 "TARGET_ARM && reload_completed"
456 [(parallel [(set (reg:CC_C CC_REGNUM)
457 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
458 (match_dup 1)))
459 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461 (plus:SI (match_dup 4) (const_int 0))))]
462 "
463 {
464 operands[3] = gen_highpart (SImode, operands[0]);
465 operands[0] = gen_lowpart (SImode, operands[0]);
466 operands[4] = gen_highpart (SImode, operands[1]);
467 operands[1] = gen_lowpart (SImode, operands[1]);
468 operands[2] = gen_lowpart (SImode, operands[2]);
469 }"
cffb2a26 470 [(set_attr "conds" "clob")
471 (set_attr "length" "8")]
472)
b11cae9e 473
87b22bf7 474(define_expand "addsi3"
cffb2a26 475 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 476 (plus:SI (match_operand:SI 1 "s_register_operand" "")
477 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 478 "TARGET_EITHER"
87b22bf7 479 "
cffb2a26 480 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
87b22bf7 481 {
96f57e36 482 arm_split_constant (PLUS, SImode, NULL_RTX,
483 INTVAL (operands[2]), operands[0], operands[1],
615caa51 484 optimize && !no_new_pseudos);
87b22bf7 485 DONE;
486 }
cffb2a26 487 "
488)
87b22bf7 489
5bd751ff 490; If there is a scratch available, this will be faster than synthesizing the
a0f94409 491; addition.
492(define_peephole2
493 [(match_scratch:SI 3 "r")
372575c7 494 (set (match_operand:SI 0 "arm_general_register_operand" "")
495 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
cffb2a26 496 (match_operand:SI 2 "const_int_operand" "")))]
497 "TARGET_ARM &&
a0f94409 498 !(const_ok_for_arm (INTVAL (operands[2]))
499 || const_ok_for_arm (-INTVAL (operands[2])))
500 && const_ok_for_arm (~INTVAL (operands[2]))"
501 [(set (match_dup 3) (match_dup 2))
502 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503 ""
504)
87b22bf7 505
a0f94409 506(define_insn_and_split "*arm_addsi3"
cffb2a26 507 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
a0f94409 508 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
87b22bf7 509 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
cffb2a26 510 "TARGET_ARM"
5565501b 511 "@
512 add%?\\t%0, %1, %2
87b22bf7 513 sub%?\\t%0, %1, #%n2
514 #"
a0f94409 515 "TARGET_ARM &&
516 GET_CODE (operands[2]) == CONST_INT
517 && !(const_ok_for_arm (INTVAL (operands[2]))
518 || const_ok_for_arm (-INTVAL (operands[2])))"
519 [(clobber (const_int 0))]
520 "
96f57e36 521 arm_split_constant (PLUS, SImode, curr_insn,
522 INTVAL (operands[2]), operands[0],
a0f94409 523 operands[1], 0);
524 DONE;
525 "
0d66636f 526 [(set_attr "length" "4,4,16")
527 (set_attr "predicable" "yes")]
cffb2a26 528)
529
530;; Register group 'k' is a single register group containing only the stack
531;; register. Trying to reload it will always fail catastrophically,
532;; so never allow those alternatives to match if reloading is needed.
533
534(define_insn "*thumb_addsi3"
535 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
536 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
538 "TARGET_THUMB"
539 "*
0d66636f 540 static const char * const asms[] =
cffb2a26 541 {
542 \"add\\t%0, %0, %2\",
543 \"sub\\t%0, %0, #%n2\",
544 \"add\\t%0, %1, %2\",
545 \"add\\t%0, %0, %2\",
546 \"add\\t%0, %0, %2\",
547 \"add\\t%0, %1, %2\",
548 \"add\\t%0, %1, %2\"
549 };
550 if ((which_alternative == 2 || which_alternative == 6)
551 && GET_CODE (operands[2]) == CONST_INT
552 && INTVAL (operands[2]) < 0)
553 return \"sub\\t%0, %1, #%n2\";
554 return asms[which_alternative];
555 "
556 [(set_attr "length" "2")]
557)
558
559;; Reloading and elimination of the frame pointer can
560;; sometimes cause this optimization to be missed.
a0f94409 561(define_peephole2
372575c7 562 [(set (match_operand:SI 0 "arm_general_register_operand" "")
a058e94a 563 (match_operand:SI 1 "const_int_operand" ""))
cffb2a26 564 (set (match_dup 0)
372575c7 565 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
cffb2a26 566 "TARGET_THUMB
cffb2a26 567 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568 && (INTVAL (operands[1]) & 3) == 0"
372575c7 569 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
a0f94409 570 ""
cffb2a26 571)
b11cae9e 572
f7fbdd4a 573(define_insn "*addsi3_compare0"
bd5b4116 574 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 575 (compare:CC_NOOV
215b30b3 576 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577 (match_operand:SI 2 "arm_add_operand" "rI,L"))
5565501b 578 (const_int 0)))
579 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 580 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 581 "TARGET_ARM"
5565501b 582 "@
583 add%?s\\t%0, %1, %2
584 sub%?s\\t%0, %1, #%n2"
cffb2a26 585 [(set_attr "conds" "set")]
586)
9c08d1fa 587
aea4c774 588(define_insn "*addsi3_compare0_scratch"
bd5b4116 589 [(set (reg:CC_NOOV CC_REGNUM)
aea4c774 590 (compare:CC_NOOV
215b30b3 591 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592 (match_operand:SI 1 "arm_add_operand" "rI,L"))
aea4c774 593 (const_int 0)))]
cffb2a26 594 "TARGET_ARM"
595 "@
596 cmn%?\\t%0, %1
597 cmp%?\\t%0, #%n1"
0d66636f 598 [(set_attr "conds" "set")]
599)
cffb2a26 600
aed179ae 601(define_insn "*compare_negsi_si"
602 [(set (reg:CC_Z CC_REGNUM)
603 (compare:CC_Z
604 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 606 "TARGET_ARM"
aed179ae 607 "cmn%?\\t%1, %0"
0d66636f 608 [(set_attr "conds" "set")]
609)
aea4c774 610
203c488f 611;; This is the canonicalization of addsi3_compare0_for_combiner when the
612;; addend is a constant.
613(define_insn "*cmpsi2_addneg"
614 [(set (reg:CC CC_REGNUM)
615 (compare:CC
616 (match_operand:SI 1 "s_register_operand" "r,r")
617 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618 (set (match_operand:SI 0 "s_register_operand" "=r,r")
619 (plus:SI (match_dup 1)
620 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
622 "@
623 sub%?s\\t%0, %1, %2
624 add%?s\\t%0, %1, #%n2"
625 [(set_attr "conds" "set")]
626)
627
628;; Convert the sequence
629;; sub rd, rn, #1
630;; cmn rd, #1 (equivalent to cmp rd, #-1)
631;; bne dest
632;; into
633;; subs rd, rn, #1
634;; bcs dest ((unsigned)rn >= 1)
635;; similarly for the beq variant using bcc.
636;; This is a common looping idiom (while (n--))
637(define_peephole2
372575c7 638 [(set (match_operand:SI 0 "arm_general_register_operand" "")
639 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
203c488f 640 (const_int -1)))
641 (set (match_operand 2 "cc_register" "")
642 (compare (match_dup 0) (const_int -1)))
643 (set (pc)
644 (if_then_else (match_operator 3 "equality_operator"
645 [(match_dup 2) (const_int 0)])
646 (match_operand 4 "" "")
647 (match_operand 5 "" "")))]
648 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
649 [(parallel[
650 (set (match_dup 2)
651 (compare:CC
652 (match_dup 1) (const_int 1)))
653 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
654 (set (pc)
655 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
656 (match_dup 4)
657 (match_dup 5)))]
658 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
660 ? GEU : LTU),
661 VOIDmode,
662 operands[2], const0_rtx);"
663)
664
ebcc79bc 665;; The next four insns work because they compare the result with one of
666;; the operands, and we know that the use of the condition code is
667;; either GEU or LTU, so we can use the carry flag from the addition
668;; instead of doing the compare a second time.
669(define_insn "*addsi3_compare_op1"
bd5b4116 670 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 671 (compare:CC_C
672 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673 (match_operand:SI 2 "arm_add_operand" "rI,L"))
674 (match_dup 1)))
675 (set (match_operand:SI 0 "s_register_operand" "=r,r")
676 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 677 "TARGET_ARM"
ebcc79bc 678 "@
679 add%?s\\t%0, %1, %2
680 sub%?s\\t%0, %1, #%n2"
0d66636f 681 [(set_attr "conds" "set")]
682)
ebcc79bc 683
684(define_insn "*addsi3_compare_op2"
bd5b4116 685 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 686 (compare:CC_C
687 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688 (match_operand:SI 2 "arm_add_operand" "rI,L"))
689 (match_dup 2)))
5565501b 690 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 691 (plus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 692 "TARGET_ARM"
5565501b 693 "@
694 add%?s\\t%0, %1, %2
695 sub%?s\\t%0, %1, #%n2"
0d66636f 696 [(set_attr "conds" "set")]
697)
9c08d1fa 698
ebcc79bc 699(define_insn "*compare_addsi2_op0"
bd5b4116 700 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 701 (compare:CC_C
702 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703 (match_operand:SI 1 "arm_add_operand" "rI,L"))
704 (match_dup 0)))]
cffb2a26 705 "TARGET_ARM"
ebcc79bc 706 "@
707 cmn%?\\t%0, %1
708 cmp%?\\t%0, #%n1"
0d66636f 709 [(set_attr "conds" "set")]
710)
ebcc79bc 711
712(define_insn "*compare_addsi2_op1"
bd5b4116 713 [(set (reg:CC_C CC_REGNUM)
ebcc79bc 714 (compare:CC_C
715 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716 (match_operand:SI 1 "arm_add_operand" "rI,L"))
717 (match_dup 1)))]
cffb2a26 718 "TARGET_ARM"
ebcc79bc 719 "@
720 cmn%?\\t%0, %1
721 cmp%?\\t%0, #%n1"
0d66636f 722 [(set_attr "conds" "set")]
723)
ebcc79bc 724
725(define_insn "*addsi3_carryin"
726 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 727 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 728 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
cffb2a26 730 "TARGET_ARM"
ebcc79bc 731 "adc%?\\t%0, %1, %2"
cffb2a26 732 [(set_attr "conds" "use")]
733)
ebcc79bc 734
33782ec7 735(define_insn "*addsi3_carryin_shift"
7b63a8dd 736 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 737 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
33782ec7 738 (plus:SI
739 (match_operator:SI 2 "shift_operator"
7b63a8dd 740 [(match_operand:SI 3 "s_register_operand" "r")
741 (match_operand:SI 4 "reg_or_int_operand" "rM")])
742 (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 743 "TARGET_ARM"
33782ec7 744 "adc%?\\t%0, %1, %3%S2"
a2cd141b 745 [(set_attr "conds" "use")
746 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747 (const_string "alu_shift")
748 (const_string "alu_shift_reg")))]
33782ec7 749)
750
ebcc79bc 751(define_insn "*addsi3_carryin_alt1"
752 [(set (match_operand:SI 0 "s_register_operand" "=r")
753 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754 (match_operand:SI 2 "arm_rhs_operand" "rI"))
bd5b4116 755 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
cffb2a26 756 "TARGET_ARM"
ebcc79bc 757 "adc%?\\t%0, %1, %2"
cffb2a26 758 [(set_attr "conds" "use")]
759)
ebcc79bc 760
761(define_insn "*addsi3_carryin_alt2"
762 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 763 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 764 (match_operand:SI 1 "s_register_operand" "r"))
765 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 766 "TARGET_ARM"
ebcc79bc 767 "adc%?\\t%0, %1, %2"
0d66636f 768 [(set_attr "conds" "use")]
769)
ebcc79bc 770
771(define_insn "*addsi3_carryin_alt3"
772 [(set (match_operand:SI 0 "s_register_operand" "=r")
bd5b4116 773 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
ebcc79bc 774 (match_operand:SI 2 "arm_rhs_operand" "rI"))
775 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 776 "TARGET_ARM"
ebcc79bc 777 "adc%?\\t%0, %1, %2"
cffb2a26 778 [(set_attr "conds" "use")]
779)
ebcc79bc 780
9c08d1fa 781(define_insn "incscc"
782 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 783 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 784 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
9c08d1fa 785 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 786 "TARGET_ARM"
5565501b 787 "@
788 add%d2\\t%0, %1, #1
789 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
8fa3ba89 790 [(set_attr "conds" "use")
215b30b3 791 (set_attr "length" "4,8")]
792)
9c08d1fa 793
d795fb69 794; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
795(define_split
796 [(set (match_operand:SI 0 "s_register_operand" "")
797 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798 (match_operand:SI 2 "s_register_operand" ""))
799 (const_int -1)))
800 (clobber (match_operand:SI 3 "s_register_operand" ""))]
801 "TARGET_ARM"
802 [(set (match_dup 3) (match_dup 1))
803 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
804 "
805 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
806")
807
604f3a0a 808(define_expand "addsf3"
809 [(set (match_operand:SF 0 "s_register_operand" "")
810 (plus:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 811 (match_operand:SF 2 "arm_float_add_operand" "")))]
812 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 813 "
a2cd141b 814 if (TARGET_MAVERICK
604f3a0a 815 && !cirrus_fp_register (operands[2], SFmode))
816 operands[2] = force_reg (SFmode, operands[2]);
817")
818
604f3a0a 819(define_expand "adddf3"
820 [(set (match_operand:DF 0 "s_register_operand" "")
821 (plus:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 822 (match_operand:DF 2 "arm_float_add_operand" "")))]
823 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 824 "
a2cd141b 825 if (TARGET_MAVERICK
604f3a0a 826 && !cirrus_fp_register (operands[2], DFmode))
827 operands[2] = force_reg (DFmode, operands[2]);
828")
829
cffb2a26 830(define_expand "subdi3"
831 [(parallel
832 [(set (match_operand:DI 0 "s_register_operand" "")
833 (minus:DI (match_operand:DI 1 "s_register_operand" "")
834 (match_operand:DI 2 "s_register_operand" "")))
bd5b4116 835 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 836 "TARGET_EITHER"
837 "
a2cd141b 838 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
7d57ec45 839 && TARGET_ARM
840 && cirrus_fp_register (operands[0], DImode)
841 && cirrus_fp_register (operands[1], DImode))
842 {
843 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
844 DONE;
845 }
846
cffb2a26 847 if (TARGET_THUMB)
848 {
849 if (GET_CODE (operands[1]) != REG)
850 operands[1] = force_reg (SImode, operands[1]);
851 if (GET_CODE (operands[2]) != REG)
852 operands[2] = force_reg (SImode, operands[2]);
853 }
854 "
855)
856
857(define_insn "*arm_subdi3"
858 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
9c08d1fa 859 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860 (match_operand:DI 2 "s_register_operand" "r,0,0")))
bd5b4116 861 (clobber (reg:CC CC_REGNUM))]
cffb2a26 862 "TARGET_ARM"
97499065 863 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
cffb2a26 864 [(set_attr "conds" "clob")
865 (set_attr "length" "8")]
866)
867
868(define_insn "*thumb_subdi3"
869 [(set (match_operand:DI 0 "register_operand" "=l")
870 (minus:DI (match_operand:DI 1 "register_operand" "0")
871 (match_operand:DI 2 "register_operand" "l")))
bd5b4116 872 (clobber (reg:CC CC_REGNUM))]
cffb2a26 873 "TARGET_THUMB"
874 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875 [(set_attr "length" "4")]
876)
9c08d1fa 877
f7fbdd4a 878(define_insn "*subdi_di_zesidi"
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 (zero_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, #0"
cffb2a26 886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
888)
9c08d1fa 889
f7fbdd4a 890(define_insn "*subdi_di_sesidi"
cffb2a26 891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
892 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
9c08d1fa 893 (sign_extend:DI
cffb2a26 894 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 895 (clobber (reg:CC CC_REGNUM))]
cffb2a26 896 "TARGET_ARM"
97499065 897 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
cffb2a26 898 [(set_attr "conds" "clob")
899 (set_attr "length" "8")]
900)
9c08d1fa 901
f7fbdd4a 902(define_insn "*subdi_zesidi_di"
cffb2a26 903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 904 (minus:DI (zero_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, #0"
cffb2a26 910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
912)
9c08d1fa 913
f7fbdd4a 914(define_insn "*subdi_sesidi_di"
cffb2a26 915 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 916 (minus:DI (sign_extend:DI
cffb2a26 917 (match_operand:SI 2 "s_register_operand" "r,r"))
918 (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 919 (clobber (reg:CC CC_REGNUM))]
cffb2a26 920 "TARGET_ARM"
97499065 921 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
cffb2a26 922 [(set_attr "conds" "clob")
923 (set_attr "length" "8")]
924)
9c08d1fa 925
f7fbdd4a 926(define_insn "*subdi_zesidi_zesidi"
cffb2a26 927 [(set (match_operand:DI 0 "s_register_operand" "=r")
9c08d1fa 928 (minus:DI (zero_extend:DI
cffb2a26 929 (match_operand:SI 1 "s_register_operand" "r"))
9c08d1fa 930 (zero_extend:DI
cffb2a26 931 (match_operand:SI 2 "s_register_operand" "r"))))
bd5b4116 932 (clobber (reg:CC CC_REGNUM))]
cffb2a26 933 "TARGET_ARM"
97499065 934 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
cffb2a26 935 [(set_attr "conds" "clob")
936 (set_attr "length" "8")]
937)
b11cae9e 938
87b22bf7 939(define_expand "subsi3"
cffb2a26 940 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 941 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942 (match_operand:SI 2 "s_register_operand" "")))]
cffb2a26 943 "TARGET_EITHER"
87b22bf7 944 "
945 if (GET_CODE (operands[1]) == CONST_INT)
946 {
cffb2a26 947 if (TARGET_ARM)
948 {
96f57e36 949 arm_split_constant (MINUS, SImode, NULL_RTX,
950 INTVAL (operands[1]), operands[0],
615caa51 951 operands[2], optimize && !no_new_pseudos);
cffb2a26 952 DONE;
953 }
954 else /* TARGET_THUMB */
955 operands[1] = force_reg (SImode, operands[1]);
87b22bf7 956 }
cffb2a26 957 "
958)
87b22bf7 959
cffb2a26 960(define_insn "*thumb_subsi3_insn"
961 [(set (match_operand:SI 0 "register_operand" "=l")
962 (minus:SI (match_operand:SI 1 "register_operand" "l")
963 (match_operand:SI 2 "register_operand" "l")))]
964 "TARGET_THUMB"
965 "sub\\t%0, %1, %2"
966 [(set_attr "length" "2")]
967)
968
a0f94409 969(define_insn_and_split "*arm_subsi3_insn"
cffb2a26 970 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 971 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972 (match_operand:SI 2 "s_register_operand" "r,r")))]
cffb2a26 973 "TARGET_ARM"
e2348bcb 974 "@
87b22bf7 975 rsb%?\\t%0, %2, %1
976 #"
a0f94409 977 "TARGET_ARM
978 && GET_CODE (operands[1]) == CONST_INT
979 && !const_ok_for_arm (INTVAL (operands[1]))"
87b22bf7 980 [(clobber (const_int 0))]
981 "
96f57e36 982 arm_split_constant (MINUS, SImode, curr_insn,
983 INTVAL (operands[1]), operands[0], operands[2], 0);
87b22bf7 984 DONE;
cffb2a26 985 "
a0f94409 986 [(set_attr "length" "4,16")
987 (set_attr "predicable" "yes")]
988)
989
990(define_peephole2
991 [(match_scratch:SI 3 "r")
372575c7 992 (set (match_operand:SI 0 "arm_general_register_operand" "")
a0f94409 993 (minus:SI (match_operand:SI 1 "const_int_operand" "")
372575c7 994 (match_operand:SI 2 "arm_general_register_operand" "")))]
a0f94409 995 "TARGET_ARM
996 && !const_ok_for_arm (INTVAL (operands[1]))
997 && const_ok_for_arm (~INTVAL (operands[1]))"
998 [(set (match_dup 3) (match_dup 1))
999 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1000 ""
cffb2a26 1001)
b11cae9e 1002
f7fbdd4a 1003(define_insn "*subsi3_compare0"
bd5b4116 1004 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1005 (compare:CC_NOOV
1006 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1008 (const_int 0)))
9c08d1fa 1009 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010 (minus:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1011 "TARGET_ARM"
e2348bcb 1012 "@
40dbec34 1013 sub%?s\\t%0, %1, %2
1014 rsb%?s\\t%0, %2, %1"
cffb2a26 1015 [(set_attr "conds" "set")]
1016)
9c08d1fa 1017
1018(define_insn "decscc"
cffb2a26 1019 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1020 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 1021 (match_operator:SI 2 "arm_comparison_operator"
cffb2a26 1022 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1023 "TARGET_ARM"
e2348bcb 1024 "@
215b30b3 1025 sub%d2\\t%0, %1, #1
1026 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
cffb2a26 1027 [(set_attr "conds" "use")
1028 (set_attr "length" "*,8")]
1029)
9c08d1fa 1030
604f3a0a 1031(define_expand "subsf3"
1032 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1033 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1036 "
a2cd141b 1037 if (TARGET_MAVERICK)
604f3a0a 1038 {
1039 if (!cirrus_fp_register (operands[1], SFmode))
1040 operands[1] = force_reg (SFmode, operands[1]);
1041 if (!cirrus_fp_register (operands[2], SFmode))
1042 operands[2] = force_reg (SFmode, operands[2]);
1043 }
1044")
1045
604f3a0a 1046(define_expand "subdf3"
1047 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1048 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1051 "
a2cd141b 1052 if (TARGET_MAVERICK)
604f3a0a 1053 {
1054 if (!cirrus_fp_register (operands[1], DFmode))
1055 operands[1] = force_reg (DFmode, operands[1]);
1056 if (!cirrus_fp_register (operands[2], DFmode))
1057 operands[2] = force_reg (DFmode, operands[2]);
1058 }
1059")
1060
b11cae9e 1061\f
1062;; Multiplication insns
1063
cffb2a26 1064(define_expand "mulsi3"
1065 [(set (match_operand:SI 0 "s_register_operand" "")
1066 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067 (match_operand:SI 1 "s_register_operand" "")))]
1068 "TARGET_EITHER"
1069 ""
1070)
1071
9c08d1fa 1072;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
cffb2a26 1073(define_insn "*arm_mulsi3"
1074 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1075 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
cffb2a26 1077 "TARGET_ARM"
f7fbdd4a 1078 "mul%?\\t%0, %2, %1"
a2cd141b 1079 [(set_attr "insn" "mul")
0d66636f 1080 (set_attr "predicable" "yes")]
cffb2a26 1081)
1082
215b30b3 1083; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1084; 1 and 2; are the same, because reload will make operand 0 match
1085; operand 1 without realizing that this conflicts with operand 2. We fix
1086; this by adding another alternative to match this case, and then `reload'
1087; it ourselves. This alternative must come first.
cffb2a26 1088(define_insn "*thumb_mulsi3"
1089 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1090 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091 (match_operand:SI 2 "register_operand" "l,l,l")))]
1092 "TARGET_THUMB"
1093 "*
1094 if (which_alternative < 2)
20c4e896 1095 return \"mov\\t%0, %1\;mul\\t%0, %2\";
cffb2a26 1096 else
20c4e896 1097 return \"mul\\t%0, %2\";
cffb2a26 1098 "
1099 [(set_attr "length" "4,4,2")
a2cd141b 1100 (set_attr "insn" "mul")]
cffb2a26 1101)
b11cae9e 1102
f7fbdd4a 1103(define_insn "*mulsi3_compare0"
bd5b4116 1104 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1105 (compare:CC_NOOV (mult:SI
1106 (match_operand:SI 2 "s_register_operand" "r,r")
1107 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1108 (const_int 0)))
1109 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110 (mult:SI (match_dup 2) (match_dup 1)))]
e8a4aa75 1111 "TARGET_ARM"
40dbec34 1112 "mul%?s\\t%0, %2, %1"
cffb2a26 1113 [(set_attr "conds" "set")
a2cd141b 1114 (set_attr "insn" "muls")]
cffb2a26 1115)
9c08d1fa 1116
f7fbdd4a 1117(define_insn "*mulsi_compare0_scratch"
bd5b4116 1118 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1119 (compare:CC_NOOV (mult:SI
1120 (match_operand:SI 2 "s_register_operand" "r,r")
1121 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1122 (const_int 0)))
1123 (clobber (match_scratch:SI 0 "=&r,&r"))]
e8a4aa75 1124 "TARGET_ARM"
40dbec34 1125 "mul%?s\\t%0, %2, %1"
cffb2a26 1126 [(set_attr "conds" "set")
a2cd141b 1127 (set_attr "insn" "muls")]
cffb2a26 1128)
9c08d1fa 1129
b11cae9e 1130;; Unnamed templates to match MLA instruction.
1131
f7fbdd4a 1132(define_insn "*mulsi3addsi"
9c08d1fa 1133 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
c8f69309 1134 (plus:SI
9c08d1fa 1135 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
cffb2a26 1138 "TARGET_ARM"
f7fbdd4a 1139 "mla%?\\t%0, %2, %1, %3"
a2cd141b 1140 [(set_attr "insn" "mla")
0d66636f 1141 (set_attr "predicable" "yes")]
1142)
b11cae9e 1143
f7fbdd4a 1144(define_insn "*mulsi3addsi_compare0"
bd5b4116 1145 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1146 (compare:CC_NOOV
1147 (plus:SI (mult:SI
1148 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1151 (const_int 0)))
9c08d1fa 1152 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1154 (match_dup 3)))]
e8a4aa75 1155 "TARGET_ARM"
40dbec34 1156 "mla%?s\\t%0, %2, %1, %3"
0d66636f 1157 [(set_attr "conds" "set")
a2cd141b 1158 (set_attr "insn" "mlas")]
0d66636f 1159)
9c08d1fa 1160
f7fbdd4a 1161(define_insn "*mulsi3addsi_compare0_scratch"
bd5b4116 1162 [(set (reg:CC_NOOV CC_REGNUM)
215b30b3 1163 (compare:CC_NOOV
1164 (plus:SI (mult:SI
1165 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1168 (const_int 0)))
9c08d1fa 1169 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
e8a4aa75 1170 "TARGET_ARM"
40dbec34 1171 "mla%?s\\t%0, %2, %1, %3"
cffb2a26 1172 [(set_attr "conds" "set")
a2cd141b 1173 (set_attr "insn" "mlas")]
cffb2a26 1174)
f7fbdd4a 1175
efee20da 1176;; Unnamed template to match long long multiply-accumulate (smlal)
82b85d08 1177
1178(define_insn "*mulsidi3adddi"
fe8dbf85 1179 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1180 (plus:DI
215b30b3 1181 (mult:DI
fe8dbf85 1182 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1185 "TARGET_ARM && arm_arch3m"
fe8dbf85 1186 "smlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1187 [(set_attr "insn" "smlal")
0d66636f 1188 (set_attr "predicable" "yes")]
1189)
82b85d08 1190
f7fbdd4a 1191(define_insn "mulsidi3"
1192 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1193 (mult:DI
1194 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1196 "TARGET_ARM && arm_arch3m"
97499065 1197 "smull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1198 [(set_attr "insn" "smull")
0d66636f 1199 (set_attr "predicable" "yes")]
1200)
f7fbdd4a 1201
1202(define_insn "umulsidi3"
1203 [(set (match_operand:DI 0 "s_register_operand" "=&r")
215b30b3 1204 (mult:DI
1205 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
a2cd141b 1207 "TARGET_ARM && arm_arch3m"
97499065 1208 "umull%?\\t%Q0, %R0, %1, %2"
a2cd141b 1209 [(set_attr "insn" "umull")
0d66636f 1210 (set_attr "predicable" "yes")]
1211)
b11cae9e 1212
efee20da 1213;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
82b85d08 1214
1215(define_insn "*umulsidi3adddi"
8ead09f9 1216 [(set (match_operand:DI 0 "s_register_operand" "=&r")
82b85d08 1217 (plus:DI
215b30b3 1218 (mult:DI
fe8dbf85 1219 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221 (match_operand:DI 1 "s_register_operand" "0")))]
a2cd141b 1222 "TARGET_ARM && arm_arch3m"
fe8dbf85 1223 "umlal%?\\t%Q0, %R0, %3, %2"
a2cd141b 1224 [(set_attr "insn" "umlal")
0d66636f 1225 (set_attr "predicable" "yes")]
1226)
82b85d08 1227
f082f1c4 1228(define_insn "smulsi3_highpart"
1229 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230 (truncate:SI
1231 (lshiftrt:DI
215b30b3 1232 (mult:DI
1233 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1235 (const_int 32))))
1236 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1237 "TARGET_ARM && arm_arch3m"
f082f1c4 1238 "smull%?\\t%3, %0, %2, %1"
a2cd141b 1239 [(set_attr "insn" "smull")
0d66636f 1240 (set_attr "predicable" "yes")]
cffb2a26 1241)
f082f1c4 1242
1243(define_insn "umulsi3_highpart"
1244 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1245 (truncate:SI
1246 (lshiftrt:DI
215b30b3 1247 (mult:DI
1248 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
f082f1c4 1250 (const_int 32))))
1251 (clobber (match_scratch:SI 3 "=&r,&r"))]
a2cd141b 1252 "TARGET_ARM && arm_arch3m"
f082f1c4 1253 "umull%?\\t%3, %0, %2, %1"
a2cd141b 1254 [(set_attr "insn" "umull")
0d66636f 1255 (set_attr "predicable" "yes")]
cffb2a26 1256)
f082f1c4 1257
331beb1a 1258(define_insn "mulhisi3"
1259 [(set (match_operand:SI 0 "s_register_operand" "=r")
1260 (mult:SI (sign_extend:SI
1261 (match_operand:HI 1 "s_register_operand" "%r"))
1262 (sign_extend:SI
1263 (match_operand:HI 2 "s_register_operand" "r"))))]
fec538d9 1264 "TARGET_ARM && arm_arch5e"
61a2d04c 1265 "smulbb%?\\t%0, %1, %2"
a2cd141b 1266 [(set_attr "insn" "smulxy")
fec538d9 1267 (set_attr "predicable" "yes")]
1268)
1269
1270(define_insn "*mulhisi3tb"
1271 [(set (match_operand:SI 0 "s_register_operand" "=r")
1272 (mult:SI (ashiftrt:SI
1273 (match_operand:SI 1 "s_register_operand" "r")
1274 (const_int 16))
1275 (sign_extend:SI
1276 (match_operand:HI 2 "s_register_operand" "r"))))]
1277 "TARGET_ARM && arm_arch5e"
1278 "smultb%?\\t%0, %1, %2"
a2cd141b 1279 [(set_attr "insn" "smulxy")
fec538d9 1280 (set_attr "predicable" "yes")]
1281)
1282
1283(define_insn "*mulhisi3bt"
1284 [(set (match_operand:SI 0 "s_register_operand" "=r")
1285 (mult:SI (sign_extend:SI
1286 (match_operand:HI 1 "s_register_operand" "r"))
1287 (ashiftrt:SI
1288 (match_operand:SI 2 "s_register_operand" "r")
1289 (const_int 16))))]
1290 "TARGET_ARM && arm_arch5e"
1291 "smulbt%?\\t%0, %1, %2"
a2cd141b 1292 [(set_attr "insn" "smulxy")
fec538d9 1293 (set_attr "predicable" "yes")]
1294)
1295
1296(define_insn "*mulhisi3tt"
1297 [(set (match_operand:SI 0 "s_register_operand" "=r")
1298 (mult:SI (ashiftrt:SI
1299 (match_operand:SI 1 "s_register_operand" "r")
1300 (const_int 16))
1301 (ashiftrt:SI
1302 (match_operand:SI 2 "s_register_operand" "r")
1303 (const_int 16))))]
1304 "TARGET_ARM && arm_arch5e"
1305 "smultt%?\\t%0, %1, %2"
a2cd141b 1306 [(set_attr "insn" "smulxy")
fec538d9 1307 (set_attr "predicable" "yes")]
331beb1a 1308)
1309
1310(define_insn "*mulhisi3addsi"
1311 [(set (match_operand:SI 0 "s_register_operand" "=r")
1312 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313 (mult:SI (sign_extend:SI
1314 (match_operand:HI 2 "s_register_operand" "%r"))
1315 (sign_extend:SI
1316 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1317 "TARGET_ARM && arm_arch5e"
61a2d04c 1318 "smlabb%?\\t%0, %2, %3, %1"
a2cd141b 1319 [(set_attr "insn" "smlaxy")
fec538d9 1320 (set_attr "predicable" "yes")]
331beb1a 1321)
1322
1323(define_insn "*mulhidi3adddi"
1324 [(set (match_operand:DI 0 "s_register_operand" "=r")
1325 (plus:DI
1326 (match_operand:DI 1 "s_register_operand" "0")
1327 (mult:DI (sign_extend:DI
1328 (match_operand:HI 2 "s_register_operand" "%r"))
1329 (sign_extend:DI
1330 (match_operand:HI 3 "s_register_operand" "r")))))]
fec538d9 1331 "TARGET_ARM && arm_arch5e"
331beb1a 1332 "smlalbb%?\\t%Q0, %R0, %2, %3"
a2cd141b 1333 [(set_attr "insn" "smlalxy")
fec538d9 1334 (set_attr "predicable" "yes")])
331beb1a 1335
604f3a0a 1336(define_expand "mulsf3"
1337 [(set (match_operand:SF 0 "s_register_operand" "")
1338 (mult:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1339 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1341 "
a2cd141b 1342 if (TARGET_MAVERICK
604f3a0a 1343 && !cirrus_fp_register (operands[2], SFmode))
1344 operands[2] = force_reg (SFmode, operands[2]);
1345")
1346
604f3a0a 1347(define_expand "muldf3"
1348 [(set (match_operand:DF 0 "s_register_operand" "")
1349 (mult:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1350 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 1352 "
a2cd141b 1353 if (TARGET_MAVERICK
604f3a0a 1354 && !cirrus_fp_register (operands[2], DFmode))
1355 operands[2] = force_reg (DFmode, operands[2]);
1356")
b11cae9e 1357\f
1358;; Division insns
1359
7db9af5d 1360(define_expand "divsf3"
1361 [(set (match_operand:SF 0 "s_register_operand" "")
a2cd141b 1362 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1365 "")
9c08d1fa 1366
7db9af5d 1367(define_expand "divdf3"
1368 [(set (match_operand:DF 0 "s_register_operand" "")
a2cd141b 1369 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 1372 "")
b11cae9e 1373\f
1374;; Modulo insns
1375
7db9af5d 1376(define_expand "modsf3"
1377 [(set (match_operand:SF 0 "s_register_operand" "")
1378 (mod:SF (match_operand:SF 1 "s_register_operand" "")
a2cd141b 1379 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1381 "")
9c08d1fa 1382
7db9af5d 1383(define_expand "moddf3"
1384 [(set (match_operand:DF 0 "s_register_operand" "")
1385 (mod:DF (match_operand:DF 1 "s_register_operand" "")
a2cd141b 1386 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7db9af5d 1388 "")
b11cae9e 1389\f
1390;; Boolean and,ior,xor insns
1391
f6ebffac 1392;; Split up double word logical operations
1393
1394;; Split up simple DImode logical operations. Simply perform the logical
1395;; operation on the upper and lower halves of the registers.
1396(define_split
1397 [(set (match_operand:DI 0 "s_register_operand" "")
1398 (match_operator:DI 6 "logical_binary_operator"
1399 [(match_operand:DI 1 "s_register_operand" "")
1400 (match_operand:DI 2 "s_register_operand" "")]))]
755eb2b4 1401 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
f6ebffac 1402 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1404 "
215b30b3 1405 {
1406 operands[3] = gen_highpart (SImode, operands[0]);
1407 operands[0] = gen_lowpart (SImode, operands[0]);
1408 operands[4] = gen_highpart (SImode, operands[1]);
1409 operands[1] = gen_lowpart (SImode, operands[1]);
1410 operands[5] = gen_highpart (SImode, operands[2]);
1411 operands[2] = gen_lowpart (SImode, operands[2]);
1412 }"
1413)
f6ebffac 1414
f6ebffac 1415(define_split
1416 [(set (match_operand:DI 0 "s_register_operand" "")
1417 (match_operator:DI 6 "logical_binary_operator"
1418 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419 (match_operand:DI 1 "s_register_operand" "")]))]
cffb2a26 1420 "TARGET_ARM && reload_completed"
f6ebffac 1421 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422 (set (match_dup 3) (match_op_dup:SI 6
1423 [(ashiftrt:SI (match_dup 2) (const_int 31))
1424 (match_dup 4)]))]
1425 "
215b30b3 1426 {
1427 operands[3] = gen_highpart (SImode, operands[0]);
1428 operands[0] = gen_lowpart (SImode, operands[0]);
1429 operands[4] = gen_highpart (SImode, operands[1]);
1430 operands[1] = gen_lowpart (SImode, operands[1]);
1431 operands[5] = gen_highpart (SImode, operands[2]);
1432 operands[2] = gen_lowpart (SImode, operands[2]);
1433 }"
1434)
f6ebffac 1435
f6ebffac 1436;; The zero extend of operand 2 means we can just copy the high part of
1437;; operand1 into operand0.
1438(define_split
1439 [(set (match_operand:DI 0 "s_register_operand" "")
1440 (ior:DI
1441 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1443 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1444 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445 (set (match_dup 3) (match_dup 4))]
1446 "
215b30b3 1447 {
1448 operands[4] = gen_highpart (SImode, operands[1]);
1449 operands[3] = gen_highpart (SImode, operands[0]);
1450 operands[0] = gen_lowpart (SImode, operands[0]);
1451 operands[1] = gen_lowpart (SImode, operands[1]);
1452 }"
1453)
f6ebffac 1454
1455;; The zero extend of operand 2 means we can just copy the high part of
1456;; operand1 into operand0.
1457(define_split
1458 [(set (match_operand:DI 0 "s_register_operand" "")
1459 (xor:DI
1460 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461 (match_operand:DI 1 "s_register_operand" "")))]
cffb2a26 1462 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
f6ebffac 1463 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464 (set (match_dup 3) (match_dup 4))]
1465 "
215b30b3 1466 {
1467 operands[4] = gen_highpart (SImode, operands[1]);
1468 operands[3] = gen_highpart (SImode, operands[0]);
1469 operands[0] = gen_lowpart (SImode, operands[0]);
1470 operands[1] = gen_lowpart (SImode, operands[1]);
1471 }"
1472)
f6ebffac 1473
b11cae9e 1474(define_insn "anddi3"
cffb2a26 1475 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1476 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1477 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 1478 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 1479 "#"
215b30b3 1480 [(set_attr "length" "8")]
1481)
b11cae9e 1482
a0f94409 1483(define_insn_and_split "*anddi_zesidi_di"
9c08d1fa 1484 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485 (and:DI (zero_extend:DI
1486 (match_operand:SI 2 "s_register_operand" "r,r"))
1487 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 1488 "TARGET_ARM"
f6ebffac 1489 "#"
a0f94409 1490 "TARGET_ARM && reload_completed"
1491 ; The zero extend of operand 2 clears the high word of the output
1492 ; operand.
1493 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494 (set (match_dup 3) (const_int 0))]
1495 "
1496 {
1497 operands[3] = gen_highpart (SImode, operands[0]);
1498 operands[0] = gen_lowpart (SImode, operands[0]);
1499 operands[1] = gen_lowpart (SImode, operands[1]);
1500 }"
215b30b3 1501 [(set_attr "length" "8")]
1502)
b11cae9e 1503
f7fbdd4a 1504(define_insn "*anddi_sesdi_di"
cffb2a26 1505 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
9c08d1fa 1506 (and:DI (sign_extend:DI
1507 (match_operand:SI 2 "s_register_operand" "r,r"))
cffb2a26 1508 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1509 "TARGET_ARM"
f6ebffac 1510 "#"
cffb2a26 1511 [(set_attr "length" "8")]
1512)
b11cae9e 1513
87b22bf7 1514(define_expand "andsi3"
cffb2a26 1515 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 1516 (and:SI (match_operand:SI 1 "s_register_operand" "")
1517 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 1518 "TARGET_EITHER"
87b22bf7 1519 "
cffb2a26 1520 if (TARGET_ARM)
87b22bf7 1521 {
cffb2a26 1522 if (GET_CODE (operands[2]) == CONST_INT)
1523 {
96f57e36 1524 arm_split_constant (AND, SImode, NULL_RTX,
1525 INTVAL (operands[2]), operands[0],
615caa51 1526 operands[1], optimize && !no_new_pseudos);
1527
cffb2a26 1528 DONE;
1529 }
87b22bf7 1530 }
cffb2a26 1531 else /* TARGET_THUMB */
1532 {
1533 if (GET_CODE (operands[2]) != CONST_INT)
1534 operands[2] = force_reg (SImode, operands[2]);
1535 else
1536 {
1537 int i;
1538
215b30b3 1539 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
cffb2a26 1540 {
215b30b3 1541 operands[2] = force_reg (SImode,
1542 GEN_INT (~INTVAL (operands[2])));
cffb2a26 1543
1544 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1545
1546 DONE;
1547 }
87b22bf7 1548
cffb2a26 1549 for (i = 9; i <= 31; i++)
1550 {
1551 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1552 {
1553 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1554 const0_rtx));
1555 DONE;
1556 }
215b30b3 1557 else if ((((HOST_WIDE_INT) 1) << i) - 1
1558 == ~INTVAL (operands[2]))
cffb2a26 1559 {
1560 rtx shift = GEN_INT (i);
1561 rtx reg = gen_reg_rtx (SImode);
1562
1563 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1565
1566 DONE;
1567 }
1568 }
1569
1570 operands[2] = force_reg (SImode, operands[2]);
1571 }
215b30b3 1572 }
1573 "
cffb2a26 1574)
1575
a0f94409 1576(define_insn_and_split "*arm_andsi3_insn"
cffb2a26 1577 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87b22bf7 1578 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
cffb2a26 1580 "TARGET_ARM"
5565501b 1581 "@
1582 and%?\\t%0, %1, %2
87b22bf7 1583 bic%?\\t%0, %1, #%B2
1584 #"
a0f94409 1585 "TARGET_ARM
1586 && GET_CODE (operands[2]) == CONST_INT
1587 && !(const_ok_for_arm (INTVAL (operands[2]))
1588 || const_ok_for_arm (~INTVAL (operands[2])))"
1589 [(clobber (const_int 0))]
1590 "
96f57e36 1591 arm_split_constant (AND, SImode, curr_insn,
1592 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 1593 DONE;
1594 "
0d66636f 1595 [(set_attr "length" "4,4,16")
1596 (set_attr "predicable" "yes")]
cffb2a26 1597)
1598
1599(define_insn "*thumb_andsi3_insn"
1600 [(set (match_operand:SI 0 "register_operand" "=l")
1601 (and:SI (match_operand:SI 1 "register_operand" "%0")
1602 (match_operand:SI 2 "register_operand" "l")))]
1603 "TARGET_THUMB"
1604 "and\\t%0, %0, %2"
1605 [(set_attr "length" "2")]
1606)
87b22bf7 1607
f7fbdd4a 1608(define_insn "*andsi3_compare0"
bd5b4116 1609 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1610 (compare:CC_NOOV
1611 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1613 (const_int 0)))
cffb2a26 1614 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9c08d1fa 1615 (and:SI (match_dup 1) (match_dup 2)))]
cffb2a26 1616 "TARGET_ARM"
5565501b 1617 "@
1618 and%?s\\t%0, %1, %2
1619 bic%?s\\t%0, %1, #%B2"
cffb2a26 1620 [(set_attr "conds" "set")]
1621)
9c08d1fa 1622
f7fbdd4a 1623(define_insn "*andsi3_compare0_scratch"
bd5b4116 1624 [(set (reg:CC_NOOV CC_REGNUM)
5565501b 1625 (compare:CC_NOOV
1626 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1628 (const_int 0)))
dd193d7c 1629 (clobber (match_scratch:SI 2 "=X,r"))]
cffb2a26 1630 "TARGET_ARM"
5565501b 1631 "@
1632 tst%?\\t%0, %1
dd193d7c 1633 bic%?s\\t%2, %0, #%B1"
0d66636f 1634 [(set_attr "conds" "set")]
1635)
9c08d1fa 1636
f7fbdd4a 1637(define_insn "*zeroextractsi_compare0_scratch"
bd5b4116 1638 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 1639 (compare:CC_NOOV (zero_extract:SI
1640 (match_operand:SI 0 "s_register_operand" "r")
206ee9a2 1641 (match_operand 1 "const_int_operand" "n")
1642 (match_operand 2 "const_int_operand" "n"))
9c08d1fa 1643 (const_int 0)))]
cffb2a26 1644 "TARGET_ARM
1645 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646 && INTVAL (operands[1]) > 0
1647 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
9c08d1fa 1649 "*
5c49a439 1650 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651 << INTVAL (operands[2]));
40dbec34 1652 output_asm_insn (\"tst%?\\t%0, %1\", operands);
e2348bcb 1653 return \"\";
0d66636f 1654 "
1655 [(set_attr "conds" "set")]
1656)
9c08d1fa 1657
f4462328 1658(define_insn_and_split "*ne_zeroextractsi"
c4034607 1659 [(set (match_operand:SI 0 "s_register_operand" "=r")
1660 (ne:SI (zero_extract:SI
1661 (match_operand:SI 1 "s_register_operand" "r")
1662 (match_operand:SI 2 "const_int_operand" "n")
1663 (match_operand:SI 3 "const_int_operand" "n"))
3b8c7f7a 1664 (const_int 0)))
1665 (clobber (reg:CC CC_REGNUM))]
cffb2a26 1666 "TARGET_ARM
1667 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668 && INTVAL (operands[2]) > 0
1669 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
f4462328 1671 "#"
1672 "TARGET_ARM
1673 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674 && INTVAL (operands[2]) > 0
1675 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1679 (const_int 0)))
1680 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1681 (set (match_dup 0)
1682 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683 (match_dup 0) (const_int 1)))]
1684 "
1685 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686 << INTVAL (operands[3]));
1687 "
1688 [(set_attr "conds" "clob")
1689 (set_attr "length" "8")]
1690)
1691
1692(define_insn_and_split "*ne_zeroextractsi_shifted"
1693 [(set (match_operand:SI 0 "s_register_operand" "=r")
1694 (ne:SI (zero_extract:SI
1695 (match_operand:SI 1 "s_register_operand" "r")
1696 (match_operand:SI 2 "const_int_operand" "n")
1697 (const_int 0))
1698 (const_int 0)))
1699 (clobber (reg:CC CC_REGNUM))]
1700 "TARGET_ARM"
1701 "#"
1702 "TARGET_ARM"
1703 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1705 (const_int 0)))
1706 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1707 (set (match_dup 0)
1708 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709 (match_dup 0) (const_int 1)))]
1710 "
1711 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1712 "
1713 [(set_attr "conds" "clob")
1714 (set_attr "length" "8")]
1715)
1716
1717(define_insn_and_split "*ite_ne_zeroextractsi"
1718 [(set (match_operand:SI 0 "s_register_operand" "=r")
1719 (if_then_else:SI (ne (zero_extract:SI
1720 (match_operand:SI 1 "s_register_operand" "r")
1721 (match_operand:SI 2 "const_int_operand" "n")
1722 (match_operand:SI 3 "const_int_operand" "n"))
1723 (const_int 0))
1724 (match_operand:SI 4 "arm_not_operand" "rIK")
1725 (const_int 0)))
1726 (clobber (reg:CC CC_REGNUM))]
1727 "TARGET_ARM
1728 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729 && INTVAL (operands[2]) > 0
1730 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1731 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1733 "#"
1734 "TARGET_ARM
1735 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736 && INTVAL (operands[2]) > 0
1737 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
f8d7bf2f 1738 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739 && !reg_overlap_mentioned_p (operands[0], operands[4])"
f4462328 1740 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1742 (const_int 0)))
1743 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1744 (set (match_dup 0)
1745 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746 (match_dup 0) (match_dup 4)))]
1747 "
c4034607 1748 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
f4462328 1749 << INTVAL (operands[3]));
1750 "
1751 [(set_attr "conds" "clob")
1752 (set_attr "length" "8")]
1753)
1754
1755(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756 [(set (match_operand:SI 0 "s_register_operand" "=r")
1757 (if_then_else:SI (ne (zero_extract:SI
1758 (match_operand:SI 1 "s_register_operand" "r")
1759 (match_operand:SI 2 "const_int_operand" "n")
1760 (const_int 0))
1761 (const_int 0))
1762 (match_operand:SI 3 "arm_not_operand" "rIK")
1763 (const_int 0)))
1764 (clobber (reg:CC CC_REGNUM))]
f8d7bf2f 1765 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1766 "#"
f8d7bf2f 1767 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
f4462328 1768 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1770 (const_int 0)))
1771 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1772 (set (match_dup 0)
1773 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774 (match_dup 0) (match_dup 3)))]
1775 "
1776 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
0d66636f 1777 "
1778 [(set_attr "conds" "clob")
215b30b3 1779 (set_attr "length" "8")]
1780)
9c08d1fa 1781
58d6528b 1782(define_split
1783 [(set (match_operand:SI 0 "s_register_operand" "")
1784 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785 (match_operand:SI 2 "const_int_operand" "")
1786 (match_operand:SI 3 "const_int_operand" "")))
1787 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1788 "TARGET_THUMB"
1789 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1791 "{
1792 HOST_WIDE_INT temp = INTVAL (operands[2]);
1793
1794 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795 operands[3] = GEN_INT (32 - temp);
1796 }"
1797)
1798
d7863cfe 1799(define_split
1800 [(set (match_operand:SI 0 "s_register_operand" "")
1801 (match_operator:SI 1 "shiftable_operator"
1802 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803 (match_operand:SI 3 "const_int_operand" "")
1804 (match_operand:SI 4 "const_int_operand" ""))
1805 (match_operand:SI 5 "s_register_operand" "")]))
1806 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1807 "TARGET_ARM"
1808 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1809 (set (match_dup 0)
1810 (match_op_dup 1
1811 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1812 (match_dup 5)]))]
1813 "{
1814 HOST_WIDE_INT temp = INTVAL (operands[3]);
1815
1816 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817 operands[4] = GEN_INT (32 - temp);
1818 }"
1819)
1820
58d6528b 1821(define_split
1822 [(set (match_operand:SI 0 "s_register_operand" "")
1823 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824 (match_operand:SI 2 "const_int_operand" "")
1825 (match_operand:SI 3 "const_int_operand" "")))]
1826 "TARGET_THUMB"
1827 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1829 "{
1830 HOST_WIDE_INT temp = INTVAL (operands[2]);
1831
1832 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833 operands[3] = GEN_INT (32 - temp);
1834 }"
1835)
1836
d7863cfe 1837(define_split
1838 [(set (match_operand:SI 0 "s_register_operand" "")
1839 (match_operator:SI 1 "shiftable_operator"
1840 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841 (match_operand:SI 3 "const_int_operand" "")
1842 (match_operand:SI 4 "const_int_operand" ""))
1843 (match_operand:SI 5 "s_register_operand" "")]))
1844 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1845 "TARGET_ARM"
1846 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1847 (set (match_dup 0)
1848 (match_op_dup 1
1849 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1850 (match_dup 5)]))]
1851 "{
1852 HOST_WIDE_INT temp = INTVAL (operands[3]);
1853
1854 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855 operands[4] = GEN_INT (32 - temp);
1856 }"
1857)
1858
a42059fd 1859;;; ??? This pattern is bogus. If operand3 has bits outside the range
1860;;; represented by the bitfield, then this will produce incorrect results.
1861;;; Somewhere, the value needs to be truncated. On targets like the m68k,
ceb2fe0f 1862;;; which have a real bit-field insert instruction, the truncation happens
1863;;; in the bit-field insert instruction itself. Since arm does not have a
1864;;; bit-field insert instruction, we would have to emit code here to truncate
a42059fd 1865;;; the value before we insert. This loses some of the advantage of having
1866;;; this insv pattern, so this pattern needs to be reevalutated.
1867
8a18b90c 1868(define_expand "insv"
1869 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870 (match_operand:SI 1 "general_operand" "")
1871 (match_operand:SI 2 "general_operand" ""))
19335226 1872 (match_operand:SI 3 "reg_or_int_operand" ""))]
cffb2a26 1873 "TARGET_ARM"
8a18b90c 1874 "
215b30b3 1875 {
1876 int start_bit = INTVAL (operands[2]);
1877 int width = INTVAL (operands[1]);
1878 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879 rtx target, subtarget;
1880
1881 target = operands[0];
1882 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1883 subreg as the final target. */
1884 if (GET_CODE (target) == SUBREG)
1885 {
1886 subtarget = gen_reg_rtx (SImode);
1887 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888 < GET_MODE_SIZE (SImode))
1889 target = SUBREG_REG (target);
1890 }
1891 else
1892 subtarget = target;
8a18b90c 1893
215b30b3 1894 if (GET_CODE (operands[3]) == CONST_INT)
1895 {
1896 /* Since we are inserting a known constant, we may be able to
1897 reduce the number of bits that we have to clear so that
1898 the mask becomes simple. */
1899 /* ??? This code does not check to see if the new mask is actually
1900 simpler. It may not be. */
1901 rtx op1 = gen_reg_rtx (SImode);
1902 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1903 start of this pattern. */
1904 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1906
c5b3a71b 1907 emit_insn (gen_andsi3 (op1, operands[0],
1908 gen_int_mode (~mask2, SImode)));
215b30b3 1909 emit_insn (gen_iorsi3 (subtarget, op1,
4292ca6b 1910 gen_int_mode (op3_value << start_bit, SImode)));
215b30b3 1911 }
1912 else if (start_bit == 0
1913 && !(const_ok_for_arm (mask)
1914 || const_ok_for_arm (~mask)))
1915 {
1916 /* A Trick, since we are setting the bottom bits in the word,
1917 we can shift operand[3] up, operand[0] down, OR them together
1918 and rotate the result back again. This takes 3 insns, and
5910bb95 1919 the third might be mergeable into another op. */
215b30b3 1920 /* The shift up copes with the possibility that operand[3] is
1921 wider than the bitfield. */
1922 rtx op0 = gen_reg_rtx (SImode);
1923 rtx op1 = gen_reg_rtx (SImode);
1924
1925 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1927 emit_insn (gen_iorsi3 (op1, op1, op0));
1928 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1929 }
1930 else if ((width + start_bit == 32)
1931 && !(const_ok_for_arm (mask)
1932 || const_ok_for_arm (~mask)))
1933 {
1934 /* Similar trick, but slightly less efficient. */
8a18b90c 1935
215b30b3 1936 rtx op0 = gen_reg_rtx (SImode);
1937 rtx op1 = gen_reg_rtx (SImode);
8a18b90c 1938
215b30b3 1939 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1943 }
1944 else
1945 {
c5b3a71b 1946 rtx op0 = gen_int_mode (mask, SImode);
215b30b3 1947 rtx op1 = gen_reg_rtx (SImode);
1948 rtx op2 = gen_reg_rtx (SImode);
8a18b90c 1949
215b30b3 1950 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1951 {
1952 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1953
215b30b3 1954 emit_insn (gen_movsi (tmp, op0));
1955 op0 = tmp;
1956 }
8a18b90c 1957
215b30b3 1958 /* Mask out any bits in operand[3] that are not needed. */
1959 emit_insn (gen_andsi3 (op1, operands[3], op0));
8a18b90c 1960
215b30b3 1961 if (GET_CODE (op0) == CONST_INT
1962 && (const_ok_for_arm (mask << start_bit)
1963 || const_ok_for_arm (~(mask << start_bit))))
1964 {
c5b3a71b 1965 op0 = gen_int_mode (~(mask << start_bit), SImode);
215b30b3 1966 emit_insn (gen_andsi3 (op2, operands[0], op0));
1967 }
1968 else
1969 {
1970 if (GET_CODE (op0) == CONST_INT)
1971 {
1972 rtx tmp = gen_reg_rtx (SImode);
8a18b90c 1973
215b30b3 1974 emit_insn (gen_movsi (tmp, op0));
1975 op0 = tmp;
1976 }
1977
1978 if (start_bit != 0)
1979 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
a42059fd 1980
215b30b3 1981 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1982 }
8a18b90c 1983
215b30b3 1984 if (start_bit != 0)
1985 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
8a18b90c 1986
215b30b3 1987 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988 }
f082f1c4 1989
215b30b3 1990 if (subtarget != target)
1991 {
1992 /* If TARGET is still a SUBREG, then it must be wider than a word,
1993 so we must be careful only to set the subword we were asked to. */
1994 if (GET_CODE (target) == SUBREG)
1995 emit_move_insn (target, subtarget);
1996 else
1997 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1998 }
8a18b90c 1999
215b30b3 2000 DONE;
2001 }"
2002)
8a18b90c 2003
215b30b3 2004; constants for op 2 will never be given to these patterns.
a0f94409 2005(define_insn_and_split "*anddi_notdi_di"
9c08d1fa 2006 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
a0f94409 2007 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008 (match_operand:DI 2 "s_register_operand" "0,r")))]
cffb2a26 2009 "TARGET_ARM"
f6ebffac 2010 "#"
755eb2b4 2011 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
a0f94409 2012 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014 "
2015 {
2016 operands[3] = gen_highpart (SImode, operands[0]);
2017 operands[0] = gen_lowpart (SImode, operands[0]);
2018 operands[4] = gen_highpart (SImode, operands[1]);
2019 operands[1] = gen_lowpart (SImode, operands[1]);
2020 operands[5] = gen_highpart (SImode, operands[2]);
2021 operands[2] = gen_lowpart (SImode, operands[2]);
2022 }"
0d66636f 2023 [(set_attr "length" "8")
2024 (set_attr "predicable" "yes")]
2025)
9c08d1fa 2026
a0f94409 2027(define_insn_and_split "*anddi_notzesidi_di"
9c08d1fa 2028 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029 (and:DI (not:DI (zero_extend:DI
2030 (match_operand:SI 2 "s_register_operand" "r,r")))
e2348bcb 2031 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2032 "TARGET_ARM"
e2348bcb 2033 "@
97499065 2034 bic%?\\t%Q0, %Q1, %2
f6ebffac 2035 #"
a0f94409 2036 ; (not (zero_extend ...)) allows us to just copy the high word from
2037 ; operand1 to operand0.
2038 "TARGET_ARM
2039 && reload_completed
2040 && operands[0] != operands[1]"
5a097f7d 2041 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2042 (set (match_dup 3) (match_dup 4))]
2043 "
2044 {
2045 operands[3] = gen_highpart (SImode, operands[0]);
2046 operands[0] = gen_lowpart (SImode, operands[0]);
2047 operands[4] = gen_highpart (SImode, operands[1]);
2048 operands[1] = gen_lowpart (SImode, operands[1]);
2049 }"
0d66636f 2050 [(set_attr "length" "4,8")
2051 (set_attr "predicable" "yes")]
2052)
9c08d1fa 2053
a0f94409 2054(define_insn_and_split "*anddi_notsesidi_di"
9c08d1fa 2055 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056 (and:DI (not:DI (sign_extend:DI
2057 (match_operand:SI 2 "s_register_operand" "r,r")))
5a097f7d 2058 (match_operand:DI 1 "s_register_operand" "0,r")))]
cffb2a26 2059 "TARGET_ARM"
f6ebffac 2060 "#"
a0f94409 2061 "TARGET_ARM && reload_completed"
5a097f7d 2062 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
a0f94409 2063 (set (match_dup 3) (and:SI (not:SI
2064 (ashiftrt:SI (match_dup 2) (const_int 31)))
2065 (match_dup 4)))]
2066 "
2067 {
2068 operands[3] = gen_highpart (SImode, operands[0]);
2069 operands[0] = gen_lowpart (SImode, operands[0]);
2070 operands[4] = gen_highpart (SImode, operands[1]);
2071 operands[1] = gen_lowpart (SImode, operands[1]);
2072 }"
0d66636f 2073 [(set_attr "length" "8")
2074 (set_attr "predicable" "yes")]
2075)
9c08d1fa 2076
8a18b90c 2077(define_insn "andsi_notsi_si"
9c08d1fa 2078 [(set (match_operand:SI 0 "s_register_operand" "=r")
2079 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2081 "TARGET_ARM"
0d66636f 2082 "bic%?\\t%0, %1, %2"
2083 [(set_attr "predicable" "yes")]
2084)
b11cae9e 2085
cffb2a26 2086(define_insn "bicsi3"
2087 [(set (match_operand:SI 0 "register_operand" "=l")
2088 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089 (match_operand:SI 2 "register_operand" "0")))]
2090 "TARGET_THUMB"
2091 "bic\\t%0, %0, %1"
2092 [(set_attr "length" "2")]
2093)
2094
8a18b90c 2095(define_insn "andsi_not_shiftsi_si"
a2cd141b 2096 [(set (match_operand:SI 0 "s_register_operand" "=r")
2097 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098 [(match_operand:SI 2 "s_register_operand" "r")
2099 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100 (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 2101 "TARGET_ARM"
6c4c2133 2102 "bic%?\\t%0, %1, %2%S4"
344495ea 2103 [(set_attr "predicable" "yes")
331beb1a 2104 (set_attr "shift" "2")
a2cd141b 2105 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106 (const_string "alu_shift")
2107 (const_string "alu_shift_reg")))]
6c4c2133 2108)
8a18b90c 2109
f7fbdd4a 2110(define_insn "*andsi_notsi_si_compare0"
bd5b4116 2111 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2112 (compare:CC_NOOV
2113 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114 (match_operand:SI 1 "s_register_operand" "r"))
2115 (const_int 0)))
9c08d1fa 2116 (set (match_operand:SI 0 "s_register_operand" "=r")
2117 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
cffb2a26 2118 "TARGET_ARM"
40dbec34 2119 "bic%?s\\t%0, %1, %2"
0d66636f 2120 [(set_attr "conds" "set")]
2121)
9c08d1fa 2122
f7fbdd4a 2123(define_insn "*andsi_notsi_si_compare0_scratch"
bd5b4116 2124 [(set (reg:CC_NOOV CC_REGNUM)
e2348bcb 2125 (compare:CC_NOOV
2126 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127 (match_operand:SI 1 "s_register_operand" "r"))
2128 (const_int 0)))
9c08d1fa 2129 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2130 "TARGET_ARM"
40dbec34 2131 "bic%?s\\t%0, %1, %2"
0d66636f 2132 [(set_attr "conds" "set")]
2133)
9c08d1fa 2134
2135(define_insn "iordi3"
cffb2a26 2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2138 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2139 "TARGET_ARM && ! TARGET_IWMMXT"
f6ebffac 2140 "#"
0d66636f 2141 [(set_attr "length" "8")
2142 (set_attr "predicable" "yes")]
cffb2a26 2143)
9c08d1fa 2144
f7fbdd4a 2145(define_insn "*iordi_zesidi_di"
9c08d1fa 2146 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147 (ior:DI (zero_extend:DI
2148 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2149 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2150 "TARGET_ARM"
e2348bcb 2151 "@
97499065 2152 orr%?\\t%Q0, %Q1, %2
f6ebffac 2153 #"
0d66636f 2154 [(set_attr "length" "4,8")
2155 (set_attr "predicable" "yes")]
cffb2a26 2156)
9c08d1fa 2157
f7fbdd4a 2158(define_insn "*iordi_sesidi_di"
9c08d1fa 2159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160 (ior:DI (sign_extend:DI
2161 (match_operand:SI 2 "s_register_operand" "r,r"))
2162 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2163 "TARGET_ARM"
f6ebffac 2164 "#"
0d66636f 2165 [(set_attr "length" "8")
2166 (set_attr "predicable" "yes")]
cffb2a26 2167)
9c08d1fa 2168
87b22bf7 2169(define_expand "iorsi3"
cffb2a26 2170 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2171 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2173 "TARGET_EITHER"
87b22bf7 2174 "
2175 if (GET_CODE (operands[2]) == CONST_INT)
2176 {
cffb2a26 2177 if (TARGET_ARM)
2178 {
96f57e36 2179 arm_split_constant (IOR, SImode, NULL_RTX,
2180 INTVAL (operands[2]), operands[0], operands[1],
615caa51 2181 optimize && !no_new_pseudos);
cffb2a26 2182 DONE;
2183 }
2184 else /* TARGET_THUMB */
2185 operands [2] = force_reg (SImode, operands [2]);
87b22bf7 2186 }
cffb2a26 2187 "
2188)
87b22bf7 2189
a0f94409 2190(define_insn_and_split "*arm_iorsi3"
cffb2a26 2191 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
87b22bf7 2192 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
cffb2a26 2194 "TARGET_ARM"
87b22bf7 2195 "@
2196 orr%?\\t%0, %1, %2
2197 #"
a0f94409 2198 "TARGET_ARM
2199 && GET_CODE (operands[2]) == CONST_INT
2200 && !const_ok_for_arm (INTVAL (operands[2]))"
2201 [(clobber (const_int 0))]
2202 "
96f57e36 2203 arm_split_constant (IOR, SImode, curr_insn,
2204 INTVAL (operands[2]), operands[0], operands[1], 0);
a0f94409 2205 DONE;
2206 "
0d66636f 2207 [(set_attr "length" "4,16")
2208 (set_attr "predicable" "yes")]
cffb2a26 2209)
2210
2211(define_insn "*thumb_iorsi3"
2212 [(set (match_operand:SI 0 "register_operand" "=l")
2213 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214 (match_operand:SI 2 "register_operand" "l")))]
2215 "TARGET_THUMB"
2216 "orr\\t%0, %0, %2"
2217 [(set_attr "length" "2")]
2218)
9c08d1fa 2219
a0f94409 2220(define_peephole2
2221 [(match_scratch:SI 3 "r")
372575c7 2222 (set (match_operand:SI 0 "arm_general_register_operand" "")
2223 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
87b22bf7 2224 (match_operand:SI 2 "const_int_operand" "")))]
a0f94409 2225 "TARGET_ARM
2226 && !const_ok_for_arm (INTVAL (operands[2]))
2227 && const_ok_for_arm (~INTVAL (operands[2]))"
2228 [(set (match_dup 3) (match_dup 2))
2229 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2230 ""
215b30b3 2231)
a0f94409 2232
f7fbdd4a 2233(define_insn "*iorsi3_compare0"
bd5b4116 2234 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2235 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237 (const_int 0)))
2238 (set (match_operand:SI 0 "s_register_operand" "=r")
2239 (ior:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2240 "TARGET_ARM"
40dbec34 2241 "orr%?s\\t%0, %1, %2"
cffb2a26 2242 [(set_attr "conds" "set")]
2243)
9c08d1fa 2244
f7fbdd4a 2245(define_insn "*iorsi3_compare0_scratch"
bd5b4116 2246 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2247 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2249 (const_int 0)))
2250 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2251 "TARGET_ARM"
40dbec34 2252 "orr%?s\\t%0, %1, %2"
0d66636f 2253 [(set_attr "conds" "set")]
2254)
9c08d1fa 2255
2256(define_insn "xordi3"
cffb2a26 2257 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2258 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2259 (match_operand:DI 2 "s_register_operand" "r,r")))]
755eb2b4 2260 "TARGET_ARM && !TARGET_IWMMXT"
f6ebffac 2261 "#"
0d66636f 2262 [(set_attr "length" "8")
2263 (set_attr "predicable" "yes")]
cffb2a26 2264)
9c08d1fa 2265
f7fbdd4a 2266(define_insn "*xordi_zesidi_di"
9c08d1fa 2267 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268 (xor:DI (zero_extend:DI
2269 (match_operand:SI 2 "s_register_operand" "r,r"))
e2348bcb 2270 (match_operand:DI 1 "s_register_operand" "0,?r")))]
cffb2a26 2271 "TARGET_ARM"
e2348bcb 2272 "@
97499065 2273 eor%?\\t%Q0, %Q1, %2
f6ebffac 2274 #"
0d66636f 2275 [(set_attr "length" "4,8")
2276 (set_attr "predicable" "yes")]
cffb2a26 2277)
9c08d1fa 2278
f7fbdd4a 2279(define_insn "*xordi_sesidi_di"
9c08d1fa 2280 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281 (xor:DI (sign_extend:DI
2282 (match_operand:SI 2 "s_register_operand" "r,r"))
2283 (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 2284 "TARGET_ARM"
f6ebffac 2285 "#"
0d66636f 2286 [(set_attr "length" "8")
2287 (set_attr "predicable" "yes")]
cffb2a26 2288)
9c08d1fa 2289
cffb2a26 2290(define_expand "xorsi3"
2291 [(set (match_operand:SI 0 "s_register_operand" "")
2292 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293 (match_operand:SI 2 "arm_rhs_operand" "")))]
2294 "TARGET_EITHER"
2295 "if (TARGET_THUMB)
2296 if (GET_CODE (operands[2]) == CONST_INT)
2297 operands[2] = force_reg (SImode, operands[2]);
2298 "
2299)
2300
2301(define_insn "*arm_xorsi3"
2302 [(set (match_operand:SI 0 "s_register_operand" "=r")
9c08d1fa 2303 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
cffb2a26 2305 "TARGET_ARM"
2306 "eor%?\\t%0, %1, %2"
0d66636f 2307 [(set_attr "predicable" "yes")]
cffb2a26 2308)
2309
2310(define_insn "*thumb_xorsi3"
2311 [(set (match_operand:SI 0 "register_operand" "=l")
2312 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313 (match_operand:SI 2 "register_operand" "l")))]
2314 "TARGET_THUMB"
2315 "eor\\t%0, %0, %2"
2316 [(set_attr "length" "2")]
2317)
9c08d1fa 2318
f7fbdd4a 2319(define_insn "*xorsi3_compare0"
bd5b4116 2320 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2321 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2323 (const_int 0)))
2324 (set (match_operand:SI 0 "s_register_operand" "=r")
2325 (xor:SI (match_dup 1) (match_dup 2)))]
cffb2a26 2326 "TARGET_ARM"
40dbec34 2327 "eor%?s\\t%0, %1, %2"
0d66636f 2328 [(set_attr "conds" "set")]
2329)
9c08d1fa 2330
f7fbdd4a 2331(define_insn "*xorsi3_compare0_scratch"
bd5b4116 2332 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 2333 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2335 (const_int 0)))]
cffb2a26 2336 "TARGET_ARM"
40dbec34 2337 "teq%?\\t%0, %1"
cffb2a26 2338 [(set_attr "conds" "set")]
2339)
9c08d1fa 2340
215b30b3 2341; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2342; (NOT D) we can sometimes merge the final NOT into one of the following
2343; insns.
9c08d1fa 2344
2345(define_split
a058e94a 2346 [(set (match_operand:SI 0 "s_register_operand" "")
2347 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349 (match_operand:SI 3 "arm_rhs_operand" "")))
2350 (clobber (match_operand:SI 4 "s_register_operand" ""))]
cffb2a26 2351 "TARGET_ARM"
9c08d1fa 2352 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353 (not:SI (match_dup 3))))
2354 (set (match_dup 0) (not:SI (match_dup 4)))]
2355 ""
2356)
2357
f7fbdd4a 2358(define_insn "*andsi_iorsi3_notsi"
9c08d1fa 2359 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
cffb2a26 2363 "TARGET_ARM"
40dbec34 2364 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
0d66636f 2365 [(set_attr "length" "8")
2366 (set_attr "predicable" "yes")]
cffb2a26 2367)
9c08d1fa 2368
d7863cfe 2369(define_split
2370 [(set (match_operand:SI 0 "s_register_operand" "")
2371 (match_operator:SI 1 "logical_binary_operator"
2372 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373 (match_operand:SI 3 "const_int_operand" "")
2374 (match_operand:SI 4 "const_int_operand" ""))
2375 (match_operator:SI 9 "logical_binary_operator"
2376 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377 (match_operand:SI 6 "const_int_operand" ""))
2378 (match_operand:SI 7 "s_register_operand" "")])]))
2379 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2380 "TARGET_ARM
2381 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2383 [(set (match_dup 8)
2384 (match_op_dup 1
2385 [(ashift:SI (match_dup 2) (match_dup 4))
2386 (match_dup 5)]))
2387 (set (match_dup 0)
2388 (match_op_dup 1
2389 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2390 (match_dup 7)]))]
2391 "
2392 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2393")
2394
2395(define_split
2396 [(set (match_operand:SI 0 "s_register_operand" "")
2397 (match_operator:SI 1 "logical_binary_operator"
2398 [(match_operator:SI 9 "logical_binary_operator"
2399 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400 (match_operand:SI 6 "const_int_operand" ""))
2401 (match_operand:SI 7 "s_register_operand" "")])
2402 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403 (match_operand:SI 3 "const_int_operand" "")
2404 (match_operand:SI 4 "const_int_operand" ""))]))
2405 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2406 "TARGET_ARM
2407 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2409 [(set (match_dup 8)
2410 (match_op_dup 1
2411 [(ashift:SI (match_dup 2) (match_dup 4))
2412 (match_dup 5)]))
2413 (set (match_dup 0)
2414 (match_op_dup 1
2415 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2416 (match_dup 7)]))]
2417 "
2418 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2419")
2420
2421(define_split
2422 [(set (match_operand:SI 0 "s_register_operand" "")
2423 (match_operator:SI 1 "logical_binary_operator"
2424 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425 (match_operand:SI 3 "const_int_operand" "")
2426 (match_operand:SI 4 "const_int_operand" ""))
2427 (match_operator:SI 9 "logical_binary_operator"
2428 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429 (match_operand:SI 6 "const_int_operand" ""))
2430 (match_operand:SI 7 "s_register_operand" "")])]))
2431 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2432 "TARGET_ARM
2433 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2435 [(set (match_dup 8)
2436 (match_op_dup 1
2437 [(ashift:SI (match_dup 2) (match_dup 4))
2438 (match_dup 5)]))
2439 (set (match_dup 0)
2440 (match_op_dup 1
2441 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2442 (match_dup 7)]))]
2443 "
2444 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2445")
2446
2447(define_split
2448 [(set (match_operand:SI 0 "s_register_operand" "")
2449 (match_operator:SI 1 "logical_binary_operator"
2450 [(match_operator:SI 9 "logical_binary_operator"
2451 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452 (match_operand:SI 6 "const_int_operand" ""))
2453 (match_operand:SI 7 "s_register_operand" "")])
2454 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455 (match_operand:SI 3 "const_int_operand" "")
2456 (match_operand:SI 4 "const_int_operand" ""))]))
2457 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2458 "TARGET_ARM
2459 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2461 [(set (match_dup 8)
2462 (match_op_dup 1
2463 [(ashift:SI (match_dup 2) (match_dup 4))
2464 (match_dup 5)]))
2465 (set (match_dup 0)
2466 (match_op_dup 1
2467 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2468 (match_dup 7)]))]
2469 "
2470 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2471")
9c08d1fa 2472\f
2473
2474;; Minimum and maximum insns
2475
2476(define_insn "smaxsi3"
cffb2a26 2477 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2478 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2479 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2480 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2481 "TARGET_ARM"
e2348bcb 2482 "@
2483 cmp\\t%1, %2\;movlt\\t%0, %2
2484 cmp\\t%1, %2\;movge\\t%0, %1
2485 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
cffb2a26 2486 [(set_attr "conds" "clob")
2487 (set_attr "length" "8,8,12")]
2488)
9c08d1fa 2489
2490(define_insn "sminsi3"
2491 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2492 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2493 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2494 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2495 "TARGET_ARM"
e2348bcb 2496 "@
2497 cmp\\t%1, %2\;movge\\t%0, %2
2498 cmp\\t%1, %2\;movlt\\t%0, %1
2499 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
0d66636f 2500 [(set_attr "conds" "clob")
2501 (set_attr "length" "8,8,12")]
2502)
9c08d1fa 2503
2504(define_insn "umaxsi3"
2505 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2506 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2507 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2508 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2509 "TARGET_ARM"
e2348bcb 2510 "@
2511 cmp\\t%1, %2\;movcc\\t%0, %2
2512 cmp\\t%1, %2\;movcs\\t%0, %1
2513 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
0d66636f 2514 [(set_attr "conds" "clob")
2515 (set_attr "length" "8,8,12")]
2516)
9c08d1fa 2517
2518(define_insn "uminsi3"
2519 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2520 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2521 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 2522 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2523 "TARGET_ARM"
e2348bcb 2524 "@
2525 cmp\\t%1, %2\;movcs\\t%0, %2
2526 cmp\\t%1, %2\;movcc\\t%0, %1
2527 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
0d66636f 2528 [(set_attr "conds" "clob")
2529 (set_attr "length" "8,8,12")]
2530)
9c08d1fa 2531
8a18b90c 2532(define_insn "*store_minmaxsi"
9c08d1fa 2533 [(set (match_operand:SI 0 "memory_operand" "=m")
2534 (match_operator:SI 3 "minmax_operator"
2535 [(match_operand:SI 1 "s_register_operand" "r")
2536 (match_operand:SI 2 "s_register_operand" "r")]))
bd5b4116 2537 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2538 "TARGET_ARM"
9c08d1fa 2539 "*
dc55b8a9 2540 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2541 operands[1], operands[2]);
e2348bcb 2542 output_asm_insn (\"cmp\\t%1, %2\", operands);
2543 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2544 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2545 return \"\";
0d66636f 2546 "
2547 [(set_attr "conds" "clob")
2548 (set_attr "length" "12")
2549 (set_attr "type" "store1")]
2550)
9c08d1fa 2551
8a18b90c 2552; Reject the frame pointer in operand[1], since reloading this after
2553; it has been eliminated can cause carnage.
f7fbdd4a 2554(define_insn "*minmax_arithsi"
9c08d1fa 2555 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2556 (match_operator:SI 4 "shiftable_operator"
2557 [(match_operator:SI 5 "minmax_operator"
2558 [(match_operand:SI 2 "s_register_operand" "r,r")
2559 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2560 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 2561 (clobber (reg:CC CC_REGNUM))]
da45ccee 2562 "TARGET_ARM && !arm_eliminable_register (operands[1])"
9c08d1fa 2563 "*
0d66636f 2564 {
2565 enum rtx_code code = GET_CODE (operands[4]);
2566
dc55b8a9 2567 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2568 operands[2], operands[3]);
0d66636f 2569 output_asm_insn (\"cmp\\t%2, %3\", operands);
2570 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2571 if (which_alternative != 0 || operands[3] != const0_rtx
2572 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2573 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2574 return \"\";
215b30b3 2575 }"
0d66636f 2576 [(set_attr "conds" "clob")
2577 (set_attr "length" "12")]
2578)
9c08d1fa 2579
b11cae9e 2580\f
2581;; Shift and rotation insns
2582
a2cd141b 2583(define_expand "ashldi3"
2584 [(set (match_operand:DI 0 "s_register_operand" "")
2585 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2586 (match_operand:SI 2 "reg_or_int_operand" "")))]
2587 "TARGET_ARM"
2588 "
2589 if (GET_CODE (operands[2]) == CONST_INT)
2590 {
2591 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2592 {
2593 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2594 DONE;
2595 }
2596 /* Ideally we shouldn't fail here if we could know that operands[1]
2597 ends up already living in an iwmmxt register. Otherwise it's
2598 cheaper to have the alternate code being generated than moving
1d60d981 2599 values to iwmmxt regs and back. */
a2cd141b 2600 FAIL;
2601 }
2602 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2603 FAIL;
2604 "
2605)
2606
2607(define_insn "arm_ashldi3_1bit"
2608 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2609 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2610 (const_int 1)))
2611 (clobber (reg:CC CC_REGNUM))]
2612 "TARGET_ARM"
2613 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2614 [(set_attr "conds" "clob")
2615 (set_attr "length" "8")]
2616)
2617
87b22bf7 2618(define_expand "ashlsi3"
cffb2a26 2619 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2620 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2621 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2622 "TARGET_EITHER"
87b22bf7 2623 "
2624 if (GET_CODE (operands[2]) == CONST_INT
2625 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2626 {
2627 emit_insn (gen_movsi (operands[0], const0_rtx));
2628 DONE;
2629 }
cffb2a26 2630 "
2631)
2632
2633(define_insn "*thumb_ashlsi3"
2634 [(set (match_operand:SI 0 "register_operand" "=l,l")
2635 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2636 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2637 "TARGET_THUMB"
2638 "lsl\\t%0, %1, %2"
2639 [(set_attr "length" "2")]
2640)
b11cae9e 2641
a2cd141b 2642(define_expand "ashrdi3"
2643 [(set (match_operand:DI 0 "s_register_operand" "")
2644 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2645 (match_operand:SI 2 "reg_or_int_operand" "")))]
2646 "TARGET_ARM"
2647 "
2648 if (GET_CODE (operands[2]) == CONST_INT)
2649 {
2650 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2651 {
2652 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2653 DONE;
2654 }
2655 /* Ideally we shouldn't fail here if we could know that operands[1]
2656 ends up already living in an iwmmxt register. Otherwise it's
2657 cheaper to have the alternate code being generated than moving
1d60d981 2658 values to iwmmxt regs and back. */
a2cd141b 2659 FAIL;
2660 }
2661 else if (!TARGET_REALLY_IWMMXT)
2662 FAIL;
2663 "
2664)
2665
2666(define_insn "arm_ashrdi3_1bit"
2667 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2668 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2669 (const_int 1)))
2670 (clobber (reg:CC CC_REGNUM))]
2671 "TARGET_ARM"
2672 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2673 [(set_attr "conds" "clob")
2674 (set_attr "length" "8")]
2675)
2676
87b22bf7 2677(define_expand "ashrsi3"
cffb2a26 2678 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2679 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2680 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2681 "TARGET_EITHER"
87b22bf7 2682 "
2683 if (GET_CODE (operands[2]) == CONST_INT
2684 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2685 operands[2] = GEN_INT (31);
cffb2a26 2686 "
2687)
2688
2689(define_insn "*thumb_ashrsi3"
2690 [(set (match_operand:SI 0 "register_operand" "=l,l")
2691 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2692 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2693 "TARGET_THUMB"
2694 "asr\\t%0, %1, %2"
2695 [(set_attr "length" "2")]
2696)
b11cae9e 2697
a2cd141b 2698(define_expand "lshrdi3"
2699 [(set (match_operand:DI 0 "s_register_operand" "")
2700 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2701 (match_operand:SI 2 "reg_or_int_operand" "")))]
2702 "TARGET_ARM"
2703 "
2704 if (GET_CODE (operands[2]) == CONST_INT)
2705 {
2706 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2707 {
2708 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2709 DONE;
2710 }
2711 /* Ideally we shouldn't fail here if we could know that operands[1]
2712 ends up already living in an iwmmxt register. Otherwise it's
2713 cheaper to have the alternate code being generated than moving
1d60d981 2714 values to iwmmxt regs and back. */
a2cd141b 2715 FAIL;
2716 }
2717 else if (!TARGET_REALLY_IWMMXT)
2718 FAIL;
2719 "
2720)
2721
2722(define_insn "arm_lshrdi3_1bit"
2723 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2724 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2725 (const_int 1)))
2726 (clobber (reg:CC CC_REGNUM))]
2727 "TARGET_ARM"
2728 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2729 [(set_attr "conds" "clob")
2730 (set_attr "length" "8")]
2731)
2732
87b22bf7 2733(define_expand "lshrsi3"
cffb2a26 2734 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2735 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2736 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2737 "TARGET_EITHER"
87b22bf7 2738 "
2739 if (GET_CODE (operands[2]) == CONST_INT
2740 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2741 {
2742 emit_insn (gen_movsi (operands[0], const0_rtx));
2743 DONE;
2744 }
cffb2a26 2745 "
2746)
2747
2748(define_insn "*thumb_lshrsi3"
2749 [(set (match_operand:SI 0 "register_operand" "=l,l")
2750 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2751 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2752 "TARGET_THUMB"
2753 "lsr\\t%0, %1, %2"
2754 [(set_attr "length" "2")]
2755)
b11cae9e 2756
87b22bf7 2757(define_expand "rotlsi3"
cffb2a26 2758 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2759 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2760 (match_operand:SI 2 "reg_or_int_operand" "")))]
cffb2a26 2761 "TARGET_ARM"
87b22bf7 2762 "
2763 if (GET_CODE (operands[2]) == CONST_INT)
2764 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2765 else
b11cae9e 2766 {
87b22bf7 2767 rtx reg = gen_reg_rtx (SImode);
2768 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2769 operands[2] = reg;
b11cae9e 2770 }
cffb2a26 2771 "
2772)
9c08d1fa 2773
87b22bf7 2774(define_expand "rotrsi3"
cffb2a26 2775 [(set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 2776 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2777 (match_operand:SI 2 "arm_rhs_operand" "")))]
cffb2a26 2778 "TARGET_EITHER"
87b22bf7 2779 "
cffb2a26 2780 if (TARGET_ARM)
2781 {
2782 if (GET_CODE (operands[2]) == CONST_INT
2783 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2784 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2785 }
2786 else /* TARGET_THUMB */
2787 {
2788 if (GET_CODE (operands [2]) == CONST_INT)
2789 operands [2] = force_reg (SImode, operands[2]);
2790 }
2791 "
2792)
87b22bf7 2793
cffb2a26 2794(define_insn "*thumb_rotrsi3"
2795 [(set (match_operand:SI 0 "register_operand" "=l")
2796 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2797 (match_operand:SI 2 "register_operand" "l")))]
2798 "TARGET_THUMB"
2799 "ror\\t%0, %0, %2"
2800 [(set_attr "length" "2")]
2801)
2802
2803(define_insn "*arm_shiftsi3"
2804 [(set (match_operand:SI 0 "s_register_operand" "=r")
2805 (match_operator:SI 3 "shift_operator"
2806 [(match_operand:SI 1 "s_register_operand" "r")
87b22bf7 2807 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
cffb2a26 2808 "TARGET_ARM"
6c4c2133 2809 "mov%?\\t%0, %1%S3"
344495ea 2810 [(set_attr "predicable" "yes")
331beb1a 2811 (set_attr "shift" "1")
a2cd141b 2812 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2813 (const_string "alu_shift")
2814 (const_string "alu_shift_reg")))]
6c4c2133 2815)
87b22bf7 2816
f7fbdd4a 2817(define_insn "*shiftsi3_compare0"
bd5b4116 2818 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2819 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2820 [(match_operand:SI 1 "s_register_operand" "r")
2821 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2822 (const_int 0)))
2823 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2824 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
cffb2a26 2825 "TARGET_ARM"
87b22bf7 2826 "mov%?s\\t%0, %1%S3"
344495ea 2827 [(set_attr "conds" "set")
331beb1a 2828 (set_attr "shift" "1")
a2cd141b 2829 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2830 (const_string "alu_shift")
2831 (const_string "alu_shift_reg")))]
0d66636f 2832)
9c08d1fa 2833
f7fbdd4a 2834(define_insn "*shiftsi3_compare0_scratch"
bd5b4116 2835 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2836 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2837 [(match_operand:SI 1 "s_register_operand" "r")
2838 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9c08d1fa 2839 (const_int 0)))
2840 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2841 "TARGET_ARM"
87b22bf7 2842 "mov%?s\\t%0, %1%S3"
344495ea 2843 [(set_attr "conds" "set")
a2cd141b 2844 (set_attr "shift" "1")]
0d66636f 2845)
9c08d1fa 2846
f7fbdd4a 2847(define_insn "*notsi_shiftsi"
9c08d1fa 2848 [(set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2849 (not:SI (match_operator:SI 3 "shift_operator"
2850 [(match_operand:SI 1 "s_register_operand" "r")
2851 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
cffb2a26 2852 "TARGET_ARM"
6c4c2133 2853 "mvn%?\\t%0, %1%S3"
344495ea 2854 [(set_attr "predicable" "yes")
331beb1a 2855 (set_attr "shift" "1")
a2cd141b 2856 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2857 (const_string "alu_shift")
2858 (const_string "alu_shift_reg")))]
0d66636f 2859)
9c08d1fa 2860
f7fbdd4a 2861(define_insn "*notsi_shiftsi_compare0"
bd5b4116 2862 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2863 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2864 [(match_operand:SI 1 "s_register_operand" "r")
2865 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2866 (const_int 0)))
2867 (set (match_operand:SI 0 "s_register_operand" "=r")
87b22bf7 2868 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
cffb2a26 2869 "TARGET_ARM"
87b22bf7 2870 "mvn%?s\\t%0, %1%S3"
344495ea 2871 [(set_attr "conds" "set")
331beb1a 2872 (set_attr "shift" "1")
a2cd141b 2873 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874 (const_string "alu_shift")
2875 (const_string "alu_shift_reg")))]
0d66636f 2876)
9c08d1fa 2877
f7fbdd4a 2878(define_insn "*not_shiftsi_compare0_scratch"
bd5b4116 2879 [(set (reg:CC_NOOV CC_REGNUM)
87b22bf7 2880 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2881 [(match_operand:SI 1 "s_register_operand" "r")
2882 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
9c08d1fa 2883 (const_int 0)))
2884 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 2885 "TARGET_ARM"
87b22bf7 2886 "mvn%?s\\t%0, %1%S3"
344495ea 2887 [(set_attr "conds" "set")
331beb1a 2888 (set_attr "shift" "1")
a2cd141b 2889 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2890 (const_string "alu_shift")
2891 (const_string "alu_shift_reg")))]
0d66636f 2892)
9c08d1fa 2893
cffb2a26 2894;; We don't really have extzv, but defining this using shifts helps
2895;; to reduce register pressure later on.
2896
2897(define_expand "extzv"
2898 [(set (match_dup 4)
2899 (ashift:SI (match_operand:SI 1 "register_operand" "")
2900 (match_operand:SI 2 "const_int_operand" "")))
2901 (set (match_operand:SI 0 "register_operand" "")
2902 (lshiftrt:SI (match_dup 4)
215b30b3 2903 (match_operand:SI 3 "const_int_operand" "")))]
cffb2a26 2904 "TARGET_THUMB"
2905 "
2906 {
2907 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2908 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2909
2910 operands[3] = GEN_INT (rshift);
2911
2912 if (lshift == 0)
2913 {
2914 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2915 DONE;
2916 }
2917
2918 operands[2] = GEN_INT (lshift);
2919 operands[4] = gen_reg_rtx (SImode);
215b30b3 2920 }"
cffb2a26 2921)
2922
b11cae9e 2923\f
2924;; Unary arithmetic insns
2925
cffb2a26 2926(define_expand "negdi2"
2927 [(parallel
2928 [(set (match_operand:DI 0 "s_register_operand" "")
2929 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
bd5b4116 2930 (clobber (reg:CC CC_REGNUM))])]
cffb2a26 2931 "TARGET_EITHER"
2932 "
2933 if (TARGET_THUMB)
2934 {
2935 if (GET_CODE (operands[1]) != REG)
2936 operands[1] = force_reg (SImode, operands[1]);
2937 }
215b30b3 2938 "
cffb2a26 2939)
2940
2941;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2942;; The second alternative is to allow the common case of a *full* overlap.
2943(define_insn "*arm_negdi2"
2944 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2945 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
bd5b4116 2946 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2947 "TARGET_ARM"
97499065 2948 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
cffb2a26 2949 [(set_attr "conds" "clob")
2950 (set_attr "length" "8")]
2951)
b11cae9e 2952
cffb2a26 2953(define_insn "*thumb_negdi2"
2954 [(set (match_operand:DI 0 "register_operand" "=&l")
2955 (neg:DI (match_operand:DI 1 "register_operand" "l")))
bd5b4116 2956 (clobber (reg:CC CC_REGNUM))]
cffb2a26 2957 "TARGET_THUMB"
2958 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2959 [(set_attr "length" "6")]
2960)
2961
2962(define_expand "negsi2"
2963 [(set (match_operand:SI 0 "s_register_operand" "")
2964 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2965 "TARGET_EITHER"
b11cae9e 2966 ""
cffb2a26 2967)
2968
2969(define_insn "*arm_negsi2"
2970 [(set (match_operand:SI 0 "s_register_operand" "=r")
2971 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2972 "TARGET_ARM"
2973 "rsb%?\\t%0, %1, #0"
0d66636f 2974 [(set_attr "predicable" "yes")]
cffb2a26 2975)
2976
2977(define_insn "*thumb_negsi2"
2978 [(set (match_operand:SI 0 "register_operand" "=l")
2979 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2980 "TARGET_THUMB"
2981 "neg\\t%0, %1"
2982 [(set_attr "length" "2")]
2983)
b11cae9e 2984
604f3a0a 2985(define_expand "negsf2"
2986 [(set (match_operand:SF 0 "s_register_operand" "")
2987 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
890ab29e 2988 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 2989 ""
2990)
2991
2992(define_expand "negdf2"
2993 [(set (match_operand:DF 0 "s_register_operand" "")
2994 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
890ab29e 2995 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
604f3a0a 2996 "")
2997
9c08d1fa 2998;; abssi2 doesn't really clobber the condition codes if a different register
2999;; is being set. To keep things simple, assume during rtl manipulations that
3000;; it does, but tell the final scan operator the truth. Similarly for
3001;; (neg (abs...))
3002
604f3a0a 3003(define_expand "abssi2"
3004 [(parallel
3005 [(set (match_operand:SI 0 "s_register_operand" "")
3006 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3007 (clobber (reg:CC CC_REGNUM))])]
3008 "TARGET_ARM"
3009 "")
3010
7d57ec45 3011(define_insn "*arm_abssi2"
722f9800 3012 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
9c08d1fa 3013 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
bd5b4116 3014 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3015 "TARGET_ARM"
e2348bcb 3016 "@
3017 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
40dbec34 3018 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
cffb2a26 3019 [(set_attr "conds" "clob,*")
331beb1a 3020 (set_attr "shift" "1")
0d66636f 3021 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3022 (set_attr "length" "8")]
3023)
9c08d1fa 3024
f7fbdd4a 3025(define_insn "*neg_abssi2"
9c08d1fa 3026 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3027 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
bd5b4116 3028 (clobber (reg:CC CC_REGNUM))]
cffb2a26 3029 "TARGET_ARM"
e2348bcb 3030 "@
3031 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
40dbec34 3032 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
cffb2a26 3033 [(set_attr "conds" "clob,*")
331beb1a 3034 (set_attr "shift" "1")
0d66636f 3035 ;; predicable can't be set based on the variant, so left as no
cffb2a26 3036 (set_attr "length" "8")]
3037)
b11cae9e 3038
604f3a0a 3039(define_expand "abssf2"
3040 [(set (match_operand:SF 0 "s_register_operand" "")
3041 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3042 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3043 "")
3044
604f3a0a 3045(define_expand "absdf2"
3046 [(set (match_operand:DF 0 "s_register_operand" "")
3047 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3048 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3049 "")
3050
7db9af5d 3051(define_expand "sqrtsf2"
3052 [(set (match_operand:SF 0 "s_register_operand" "")
3053 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 3054 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3055 "")
9c08d1fa 3056
7db9af5d 3057(define_expand "sqrtdf2"
3058 [(set (match_operand:DF 0 "s_register_operand" "")
3059 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3060 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7db9af5d 3061 "")
9c08d1fa 3062
a0f94409 3063(define_insn_and_split "one_cmpldi2"
9c08d1fa 3064 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3065 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
cffb2a26 3066 "TARGET_ARM"
f6ebffac 3067 "#"
a0f94409 3068 "TARGET_ARM && reload_completed"
3069 [(set (match_dup 0) (not:SI (match_dup 1)))
3070 (set (match_dup 2) (not:SI (match_dup 3)))]
3071 "
3072 {
3073 operands[2] = gen_highpart (SImode, operands[0]);
3074 operands[0] = gen_lowpart (SImode, operands[0]);
3075 operands[3] = gen_highpart (SImode, operands[1]);
3076 operands[1] = gen_lowpart (SImode, operands[1]);
3077 }"
0d66636f 3078 [(set_attr "length" "8")
3079 (set_attr "predicable" "yes")]
cffb2a26 3080)
b11cae9e 3081
cffb2a26 3082(define_expand "one_cmplsi2"
3083 [(set (match_operand:SI 0 "s_register_operand" "")
3084 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3085 "TARGET_EITHER"
b11cae9e 3086 ""
cffb2a26 3087)
3088
3089(define_insn "*arm_one_cmplsi2"
3090 [(set (match_operand:SI 0 "s_register_operand" "=r")
3091 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3092 "TARGET_ARM"
3093 "mvn%?\\t%0, %1"
0d66636f 3094 [(set_attr "predicable" "yes")]
cffb2a26 3095)
3096
3097(define_insn "*thumb_one_cmplsi2"
3098 [(set (match_operand:SI 0 "register_operand" "=l")
3099 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3100 "TARGET_THUMB"
3101 "mvn\\t%0, %1"
3102 [(set_attr "length" "2")]
3103)
9c08d1fa 3104
f7fbdd4a 3105(define_insn "*notsi_compare0"
bd5b4116 3106 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3107 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3108 (const_int 0)))
3109 (set (match_operand:SI 0 "s_register_operand" "=r")
3110 (not:SI (match_dup 1)))]
cffb2a26 3111 "TARGET_ARM"
40dbec34 3112 "mvn%?s\\t%0, %1"
cffb2a26 3113 [(set_attr "conds" "set")]
3114)
9c08d1fa 3115
f7fbdd4a 3116(define_insn "*notsi_compare0_scratch"
bd5b4116 3117 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 3118 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3119 (const_int 0)))
3120 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 3121 "TARGET_ARM"
40dbec34 3122 "mvn%?s\\t%0, %1"
cffb2a26 3123 [(set_attr "conds" "set")]
3124)
b11cae9e 3125\f
3126;; Fixed <--> Floating conversion insns
3127
604f3a0a 3128(define_expand "floatsisf2"
3129 [(set (match_operand:SF 0 "s_register_operand" "")
3130 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3131 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3132 "
a2cd141b 3133 if (TARGET_MAVERICK)
604f3a0a 3134 {
3135 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3136 DONE;
3137 }
3138")
3139
604f3a0a 3140(define_expand "floatsidf2"
3141 [(set (match_operand:DF 0 "s_register_operand" "")
3142 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
a2cd141b 3143 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3144 "
a2cd141b 3145 if (TARGET_MAVERICK)
604f3a0a 3146 {
3147 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3148 DONE;
3149 }
3150")
3151
604f3a0a 3152(define_expand "fix_truncsfsi2"
3153 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3154 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
a2cd141b 3155 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3156 "
a2cd141b 3157 if (TARGET_MAVERICK)
604f3a0a 3158 {
3159 if (!cirrus_fp_register (operands[0], SImode))
3160 operands[0] = force_reg (SImode, operands[0]);
3161 if (!cirrus_fp_register (operands[1], SFmode))
3162 operands[1] = force_reg (SFmode, operands[0]);
3163 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3164 DONE;
3165 }
3166")
3167
604f3a0a 3168(define_expand "fix_truncdfsi2"
3169 [(set (match_operand:SI 0 "s_register_operand" "")
a33d5c9c 3170 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
a2cd141b 3171 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3172 "
a2cd141b 3173 if (TARGET_MAVERICK)
604f3a0a 3174 {
3175 if (!cirrus_fp_register (operands[1], DFmode))
3176 operands[1] = force_reg (DFmode, operands[0]);
3177 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3178 DONE;
3179 }
3180")
3181
f544c6d2 3182;; Truncation insns
b11cae9e 3183
604f3a0a 3184(define_expand "truncdfsf2"
3185 [(set (match_operand:SF 0 "s_register_operand" "")
3186 (float_truncate:SF
3187 (match_operand:DF 1 "s_register_operand" "")))]
a2cd141b 3188 "TARGET_ARM && TARGET_HARD_FLOAT"
604f3a0a 3189 ""
3190)
b11cae9e 3191\f
9c08d1fa 3192;; Zero and sign extension instructions.
b11cae9e 3193
9c08d1fa 3194(define_insn "zero_extendsidi2"
3195 [(set (match_operand:DI 0 "s_register_operand" "=r")
3196 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3197 "TARGET_ARM"
9c08d1fa 3198 "*
0d66636f 3199 if (REGNO (operands[1])
3200 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3201 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3202 return \"mov%?\\t%R0, #0\";
3203 "
3204 [(set_attr "length" "8")
3205 (set_attr "predicable" "yes")]
3206)
9c08d1fa 3207
3208(define_insn "zero_extendqidi2"
cffb2a26 3209 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
9c08d1fa 3210 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
cffb2a26 3211 "TARGET_ARM"
e2348bcb 3212 "@
97499065 3213 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3214 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
cffb2a26 3215 [(set_attr "length" "8")
0d66636f 3216 (set_attr "predicable" "yes")
a2cd141b 3217 (set_attr "type" "*,load_byte")
cffb2a26 3218 (set_attr "pool_range" "*,4092")
3219 (set_attr "neg_pool_range" "*,4084")]
3220)
9c08d1fa 3221
3222(define_insn "extendsidi2"
3223 [(set (match_operand:DI 0 "s_register_operand" "=r")
3224 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
cffb2a26 3225 "TARGET_ARM"
9c08d1fa 3226 "*
0d66636f 3227 if (REGNO (operands[1])
3228 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3229 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3230 return \"mov%?\\t%R0, %Q0, asr #31\";
cffb2a26 3231 "
3232 [(set_attr "length" "8")
331beb1a 3233 (set_attr "shift" "1")
0d66636f 3234 (set_attr "predicable" "yes")]
3235)
9c08d1fa 3236
3237(define_expand "zero_extendhisi2"
cffb2a26 3238 [(set (match_dup 2)
0d66636f 3239 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3240 (const_int 16)))
9c08d1fa 3241 (set (match_operand:SI 0 "s_register_operand" "")
87b22bf7 3242 (lshiftrt:SI (match_dup 2) (const_int 16)))]
cffb2a26 3243 "TARGET_EITHER"
9c08d1fa 3244 "
cffb2a26 3245 {
a2cd141b 3246 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3247 {
a2cd141b 3248 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250 DONE;
cffb2a26 3251 }
cffb2a26 3252
c1a66faf 3253 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
a2cd141b 3254 {
3255 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3256 DONE;
3257 }
cffb2a26 3258
a2cd141b 3259 if (!s_register_operand (operands[1], HImode))
3260 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3261
a2cd141b 3262 if (arm_arch6)
3263 {
3264 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3265 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3266 DONE;
cffb2a26 3267 }
a2cd141b 3268
3269 operands[1] = gen_lowpart (SImode, operands[1]);
3270 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3271 }"
3272)
3273
3274(define_insn "*thumb_zero_extendhisi2"
a2cd141b 3275 [(set (match_operand:SI 0 "register_operand" "=l")
3276 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3277 "TARGET_THUMB && !arm_arch6"
cffb2a26 3278 "*
3279 rtx mem = XEXP (operands[1], 0);
3280
3281 if (GET_CODE (mem) == CONST)
3282 mem = XEXP (mem, 0);
3283
3284 if (GET_CODE (mem) == LABEL_REF)
3285 return \"ldr\\t%0, %1\";
3286
3287 if (GET_CODE (mem) == PLUS)
f7fbdd4a 3288 {
cffb2a26 3289 rtx a = XEXP (mem, 0);
3290 rtx b = XEXP (mem, 1);
3291
3292 /* This can happen due to bugs in reload. */
3293 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3294 {
3295 rtx ops[2];
3296 ops[0] = operands[0];
3297 ops[1] = a;
3298
3299 output_asm_insn (\"mov %0, %1\", ops);
3300
3301 XEXP (mem, 0) = operands[0];
3302 }
3303
3304 else if ( GET_CODE (a) == LABEL_REF
3305 && GET_CODE (b) == CONST_INT)
3306 return \"ldr\\t%0, %1\";
25f7a26e 3307 }
cffb2a26 3308
3309 return \"ldrh\\t%0, %1\";
3310 "
3311 [(set_attr "length" "4")
a2cd141b 3312 (set_attr "type" "load_byte")
cffb2a26 3313 (set_attr "pool_range" "60")]
3314)
9c08d1fa 3315
a2cd141b 3316(define_insn "*thumb_zero_extendhisi2_v6"
3317 [(set (match_operand:SI 0 "register_operand" "=l,l")
3318 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3319 "TARGET_THUMB && arm_arch6"
3320 "*
3321 rtx mem;
3322
3323 if (which_alternative == 0)
3324 return \"uxth\\t%0, %1\";
3325
3326 mem = XEXP (operands[1], 0);
3327
3328 if (GET_CODE (mem) == CONST)
3329 mem = XEXP (mem, 0);
3330
3331 if (GET_CODE (mem) == LABEL_REF)
3332 return \"ldr\\t%0, %1\";
3333
3334 if (GET_CODE (mem) == PLUS)
3335 {
3336 rtx a = XEXP (mem, 0);
3337 rtx b = XEXP (mem, 1);
3338
3339 /* This can happen due to bugs in reload. */
3340 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3341 {
3342 rtx ops[2];
3343 ops[0] = operands[0];
3344 ops[1] = a;
3345
3346 output_asm_insn (\"mov %0, %1\", ops);
3347
3348 XEXP (mem, 0) = operands[0];
3349 }
3350
3351 else if ( GET_CODE (a) == LABEL_REF
3352 && GET_CODE (b) == CONST_INT)
3353 return \"ldr\\t%0, %1\";
3354 }
3355
3356 return \"ldrh\\t%0, %1\";
3357 "
3358 [(set_attr "length" "2,4")
3359 (set_attr "type" "alu_shift,load_byte")
3360 (set_attr "pool_range" "*,60")]
3361)
3362
cffb2a26 3363(define_insn "*arm_zero_extendhisi2"
a2cd141b 3364 [(set (match_operand:SI 0 "s_register_operand" "=r")
3365 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3366 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3367 "ldr%?h\\t%0, %1"
a2cd141b 3368 [(set_attr "type" "load_byte")
0d66636f 3369 (set_attr "predicable" "yes")
cffb2a26 3370 (set_attr "pool_range" "256")
3371 (set_attr "neg_pool_range" "244")]
3372)
f7fbdd4a 3373
a2cd141b 3374(define_insn "*arm_zero_extendhisi2_v6"
3375 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3376 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3377 "TARGET_ARM && arm_arch6"
3378 "@
3379 uxth%?\\t%0, %1
3380 ldr%?h\\t%0, %1"
3381 [(set_attr "type" "alu_shift,load_byte")
3382 (set_attr "predicable" "yes")
3383 (set_attr "pool_range" "*,256")
3384 (set_attr "neg_pool_range" "*,244")]
3385)
3386
3387(define_insn "*arm_zero_extendhisi2addsi"
3388 [(set (match_operand:SI 0 "s_register_operand" "=r")
3389 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3390 (match_operand:SI 2 "s_register_operand" "r")))]
3391 "TARGET_ARM && arm_arch6"
3392 "uxtah%?\\t%0, %2, %1"
3393 [(set_attr "type" "alu_shift")
3394 (set_attr "predicable" "yes")]
3395)
3396
87b22bf7 3397(define_expand "zero_extendqisi2"
cffb2a26 3398 [(set (match_operand:SI 0 "s_register_operand" "")
3399 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3400 "TARGET_EITHER"
87b22bf7 3401 "
a2cd141b 3402 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
87b22bf7 3403 {
cffb2a26 3404 if (TARGET_ARM)
3405 {
215b30b3 3406 emit_insn (gen_andsi3 (operands[0],
3407 gen_lowpart (SImode, operands[1]),
cffb2a26 3408 GEN_INT (255)));
3409 }
3410 else /* TARGET_THUMB */
3411 {
3412 rtx temp = gen_reg_rtx (SImode);
3413 rtx ops[3];
3414
3415 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3416 operands[1] = gen_lowpart (SImode, operands[1]);
3417
3418 ops[0] = temp;
3419 ops[1] = operands[1];
3420 ops[2] = GEN_INT (24);
3421
215b30b3 3422 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3423 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
cffb2a26 3424
3425 ops[0] = operands[0];
3426 ops[1] = temp;
3427 ops[2] = GEN_INT (24);
3428
215b30b3 3429 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3430 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
cffb2a26 3431 }
87b22bf7 3432 DONE;
3433 }
215b30b3 3434 "
3435)
9c08d1fa 3436
cffb2a26 3437(define_insn "*thumb_zero_extendqisi2"
a2cd141b 3438 [(set (match_operand:SI 0 "register_operand" "=l")
3439 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3440 "TARGET_THUMB && !arm_arch6"
cffb2a26 3441 "ldrb\\t%0, %1"
3442 [(set_attr "length" "2")
a2cd141b 3443 (set_attr "type" "load_byte")
cffb2a26 3444 (set_attr "pool_range" "32")]
3445)
3446
a2cd141b 3447(define_insn "*thumb_zero_extendqisi2_v6"
3448 [(set (match_operand:SI 0 "register_operand" "=l,l")
3449 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3450 "TARGET_THUMB && arm_arch6"
3451 "@
3452 uxtb\\t%0, %1
3453 ldrb\\t%0, %1"
3454 [(set_attr "length" "2,2")
3455 (set_attr "type" "alu_shift,load_byte")
3456 (set_attr "pool_range" "*,32")]
3457)
3458
cffb2a26 3459(define_insn "*arm_zero_extendqisi2"
a2cd141b 3460 [(set (match_operand:SI 0 "s_register_operand" "=r")
3461 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3462 "TARGET_ARM && !arm_arch6"
87b22bf7 3463 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
a2cd141b 3464 [(set_attr "type" "load_byte")
0d66636f 3465 (set_attr "predicable" "yes")
cffb2a26 3466 (set_attr "pool_range" "4096")
3467 (set_attr "neg_pool_range" "4084")]
3468)
87b22bf7 3469
a2cd141b 3470(define_insn "*arm_zero_extendqisi2_v6"
3471 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3472 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3473 "TARGET_ARM && arm_arch6"
3474 "@
3475 uxtb%?\\t%0, %1
3476 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3477 [(set_attr "type" "alu_shift,load_byte")
3478 (set_attr "predicable" "yes")
3479 (set_attr "pool_range" "*,4096")
3480 (set_attr "neg_pool_range" "*,4084")]
3481)
3482
3483(define_insn "*arm_zero_extendqisi2addsi"
3484 [(set (match_operand:SI 0 "s_register_operand" "=r")
3485 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3486 (match_operand:SI 2 "s_register_operand" "r")))]
3487 "TARGET_ARM && arm_arch6"
3488 "uxtab%?\\t%0, %2, %1"
3489 [(set_attr "predicable" "yes")
3490 (set_attr "type" "alu_shift")]
3491)
3492
87b22bf7 3493(define_split
3494 [(set (match_operand:SI 0 "s_register_operand" "")
3495 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3496 (clobber (match_operand:SI 2 "s_register_operand" ""))]
9e8503e6 3497 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
87b22bf7 3498 [(set (match_dup 2) (match_dup 1))
3499 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
cffb2a26 3500 ""
3501)
9c08d1fa 3502
8a4d25d6 3503(define_split
3504 [(set (match_operand:SI 0 "s_register_operand" "")
3505 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3506 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3507 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3508 [(set (match_dup 2) (match_dup 1))
3509 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3510 ""
3511)
3512
f7fbdd4a 3513(define_insn "*compareqi_eq0"
bd5b4116 3514 [(set (reg:CC_Z CC_REGNUM)
206ee9a2 3515 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
87b22bf7 3516 (const_int 0)))]
cffb2a26 3517 "TARGET_ARM"
87b22bf7 3518 "tst\\t%0, #255"
cffb2a26 3519 [(set_attr "conds" "set")]
3520)
b11cae9e 3521
b11cae9e 3522(define_expand "extendhisi2"
c8f69309 3523 [(set (match_dup 2)
25f7a26e 3524 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
b11cae9e 3525 (const_int 16)))
9c08d1fa 3526 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3527 (ashiftrt:SI (match_dup 2)
3528 (const_int 16)))]
cffb2a26 3529 "TARGET_EITHER"
b11cae9e 3530 "
cffb2a26 3531 {
a2cd141b 3532 if (GET_CODE (operands[1]) == MEM)
cffb2a26 3533 {
a2cd141b 3534 if (TARGET_THUMB)
3535 {
3536 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3537 DONE;
3538 }
3539 else if (arm_arch4)
3540 {
a2cd141b 3541 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3542 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3543 DONE;
3544 }
cffb2a26 3545 }
7bd8ccc9 3546
c1a66faf 3547 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
cffb2a26 3548 {
3549 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3550 DONE;
3551 }
a2cd141b 3552
215b30b3 3553 if (!s_register_operand (operands[1], HImode))
cffb2a26 3554 operands[1] = copy_to_mode_reg (HImode, operands[1]);
cffb2a26 3555
a2cd141b 3556 if (arm_arch6)
cffb2a26 3557 {
a2cd141b 3558 if (TARGET_THUMB)
3559 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3560 else
3561 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3562 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3563
cffb2a26 3564 DONE;
3565 }
a2cd141b 3566
3567 operands[1] = gen_lowpart (SImode, operands[1]);
3568 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3569 }"
3570)
3571
a2cd141b 3572(define_insn "thumb_extendhisi2"
3573 [(set (match_operand:SI 0 "register_operand" "=l")
3574 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3575 (clobber (match_scratch:SI 2 "=&l"))]
3576 "TARGET_THUMB && !arm_arch6"
cffb2a26 3577 "*
3578 {
3579 rtx ops[4];
3580 rtx mem = XEXP (operands[1], 0);
3581
3582 /* This code used to try to use 'V', and fix the address only if it was
3583 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3584 range of QImode offsets, and offsettable_address_p does a QImode
3585 address check. */
3586
3587 if (GET_CODE (mem) == CONST)
3588 mem = XEXP (mem, 0);
3589
3590 if (GET_CODE (mem) == LABEL_REF)
3591 return \"ldr\\t%0, %1\";
3592
3593 if (GET_CODE (mem) == PLUS)
3594 {
3595 rtx a = XEXP (mem, 0);
3596 rtx b = XEXP (mem, 1);
3597
3598 if (GET_CODE (a) == LABEL_REF
3599 && GET_CODE (b) == CONST_INT)
3600 return \"ldr\\t%0, %1\";
3601
3602 if (GET_CODE (b) == REG)
3603 return \"ldrsh\\t%0, %1\";
3604
3605 ops[1] = a;
3606 ops[2] = b;
3607 }
3608 else
3609 {
3610 ops[1] = mem;
3611 ops[2] = const0_rtx;
3612 }
ed29c566 3613
3614 gcc_assert (GET_CODE (ops[1]) == REG);
cffb2a26 3615
3616 ops[0] = operands[0];
3617 ops[3] = operands[2];
3618 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3619 return \"\";
3620 }"
3621 [(set_attr "length" "4")
a2cd141b 3622 (set_attr "type" "load_byte")
cffb2a26 3623 (set_attr "pool_range" "1020")]
3624)
25f7a26e 3625
a2cd141b 3626;; We used to have an early-clobber on the scratch register here.
3627;; However, there's a bug somewhere in reload which means that this
3628;; can be partially ignored during spill allocation if the memory
ed29c566 3629;; address also needs reloading; this causes us to die later on when
a2cd141b 3630;; we try to verify the operands. Fortunately, we don't really need
3631;; the early-clobber: we can always use operand 0 if operand 2
3632;; overlaps the address.
3633(define_insn "*thumb_extendhisi2_insn_v6"
3634 [(set (match_operand:SI 0 "register_operand" "=l,l")
3635 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3636 (clobber (match_scratch:SI 2 "=X,l"))]
3637 "TARGET_THUMB && arm_arch6"
3638 "*
3639 {
3640 rtx ops[4];
3641 rtx mem;
3642
3643 if (which_alternative == 0)
3644 return \"sxth\\t%0, %1\";
3645
3646 mem = XEXP (operands[1], 0);
3647
3648 /* This code used to try to use 'V', and fix the address only if it was
3649 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3650 range of QImode offsets, and offsettable_address_p does a QImode
3651 address check. */
3652
3653 if (GET_CODE (mem) == CONST)
3654 mem = XEXP (mem, 0);
3655
3656 if (GET_CODE (mem) == LABEL_REF)
3657 return \"ldr\\t%0, %1\";
3658
3659 if (GET_CODE (mem) == PLUS)
3660 {
3661 rtx a = XEXP (mem, 0);
3662 rtx b = XEXP (mem, 1);
3663
3664 if (GET_CODE (a) == LABEL_REF
3665 && GET_CODE (b) == CONST_INT)
3666 return \"ldr\\t%0, %1\";
3667
3668 if (GET_CODE (b) == REG)
3669 return \"ldrsh\\t%0, %1\";
3670
3671 ops[1] = a;
3672 ops[2] = b;
3673 }
3674 else
3675 {
3676 ops[1] = mem;
3677 ops[2] = const0_rtx;
3678 }
3679
ed29c566 3680 gcc_assert (GET_CODE (ops[1]) == REG);
a2cd141b 3681
3682 ops[0] = operands[0];
3683 if (reg_mentioned_p (operands[2], ops[1]))
3684 ops[3] = ops[0];
3685 else
3686 ops[3] = operands[2];
3687 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3688 return \"\";
3689 }"
3690 [(set_attr "length" "2,4")
3691 (set_attr "type" "alu_shift,load_byte")
3692 (set_attr "pool_range" "*,1020")]
3693)
3694
25f7a26e 3695(define_expand "extendhisi2_mem"
eab14235 3696 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 3697 (set (match_dup 3)
eab14235 3698 (zero_extend:SI (match_dup 7)))
25f7a26e 3699 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3700 (set (match_operand:SI 0 "" "")
3701 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
cffb2a26 3702 "TARGET_ARM"
25f7a26e 3703 "
215b30b3 3704 {
3705 rtx mem1, mem2;
3706 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3707
788fcce0 3708 mem1 = change_address (operands[1], QImode, addr);
3709 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 3710 operands[0] = gen_lowpart (SImode, operands[0]);
3711 operands[1] = mem1;
3712 operands[2] = gen_reg_rtx (SImode);
3713 operands[3] = gen_reg_rtx (SImode);
3714 operands[6] = gen_reg_rtx (SImode);
3715 operands[7] = mem2;
25f7a26e 3716
215b30b3 3717 if (BYTES_BIG_ENDIAN)
3718 {
3719 operands[4] = operands[2];
3720 operands[5] = operands[3];
3721 }
3722 else
3723 {
3724 operands[4] = operands[3];
3725 operands[5] = operands[2];
3726 }
3727 }"
3728)
b11cae9e 3729
a2cd141b 3730(define_insn "*arm_extendhisi2"
3731 [(set (match_operand:SI 0 "s_register_operand" "=r")
3732 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3733 "TARGET_ARM && arm_arch4 && !arm_arch6"
f7fbdd4a 3734 "ldr%?sh\\t%0, %1"
a2cd141b 3735 [(set_attr "type" "load_byte")
0d66636f 3736 (set_attr "predicable" "yes")
cffb2a26 3737 (set_attr "pool_range" "256")
3738 (set_attr "neg_pool_range" "244")]
3739)
f7fbdd4a 3740
a2cd141b 3741(define_insn "*arm_extendhisi2_v6"
3742 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3743 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3744 "TARGET_ARM && arm_arch6"
3745 "@
3746 sxth%?\\t%0, %1
3747 ldr%?sh\\t%0, %1"
3748 [(set_attr "type" "alu_shift,load_byte")
3749 (set_attr "predicable" "yes")
3750 (set_attr "pool_range" "*,256")
3751 (set_attr "neg_pool_range" "*,244")]
3752)
3753
3754(define_insn "*arm_extendhisi2addsi"
3755 [(set (match_operand:SI 0 "s_register_operand" "=r")
3756 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3757 (match_operand:SI 2 "s_register_operand" "r")))]
3758 "TARGET_ARM && arm_arch6"
3759 "sxtah%?\\t%0, %2, %1"
3760)
3761
c8f69309 3762(define_expand "extendqihi2"
3763 [(set (match_dup 2)
f7fbdd4a 3764 (ashift:SI (match_operand:QI 1 "general_operand" "")
c8f69309 3765 (const_int 24)))
9c08d1fa 3766 (set (match_operand:HI 0 "s_register_operand" "")
c8f69309 3767 (ashiftrt:SI (match_dup 2)
3768 (const_int 24)))]
cffb2a26 3769 "TARGET_ARM"
c8f69309 3770 "
215b30b3 3771 {
3772 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3773 {
3774 emit_insn (gen_rtx_SET (VOIDmode,
3775 operands[0],
3776 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3777 DONE;
3778 }
3779 if (!s_register_operand (operands[1], QImode))
3780 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3781 operands[0] = gen_lowpart (SImode, operands[0]);
3782 operands[1] = gen_lowpart (SImode, operands[1]);
3783 operands[2] = gen_reg_rtx (SImode);
3784 }"
3785)
f7fbdd4a 3786
3787(define_insn "*extendqihi_insn"
b4e8a300 3788 [(set (match_operand:HI 0 "s_register_operand" "=r")
3789 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
cffb2a26 3790 "TARGET_ARM && arm_arch4"
b4e8a300 3791 "ldr%?sb\\t%0, %1"
a2cd141b 3792 [(set_attr "type" "load_byte")
0d66636f 3793 (set_attr "predicable" "yes")
cffb2a26 3794 (set_attr "pool_range" "256")
3795 (set_attr "neg_pool_range" "244")]
3796)
3fc2009e 3797
b11cae9e 3798(define_expand "extendqisi2"
c8f69309 3799 [(set (match_dup 2)
3fc2009e 3800 (ashift:SI (match_operand:QI 1 "general_operand" "")
b11cae9e 3801 (const_int 24)))
9c08d1fa 3802 (set (match_operand:SI 0 "s_register_operand" "")
c8f69309 3803 (ashiftrt:SI (match_dup 2)
3804 (const_int 24)))]
cffb2a26 3805 "TARGET_EITHER"
b11cae9e 3806 "
cffb2a26 3807 {
a2cd141b 3808 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
cffb2a26 3809 {
a2cd141b 3810 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
cffb2a26 3811 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3812 DONE;
3813 }
a2cd141b 3814
215b30b3 3815 if (!s_register_operand (operands[1], QImode))
cffb2a26 3816 operands[1] = copy_to_mode_reg (QImode, operands[1]);
cffb2a26 3817
a2cd141b 3818 if (arm_arch6)
3819 {
3820 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3821 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3822 DONE;
cffb2a26 3823 }
a2cd141b 3824
3825 operands[1] = gen_lowpart (SImode, operands[1]);
3826 operands[2] = gen_reg_rtx (SImode);
cffb2a26 3827 }"
3828)
f7fbdd4a 3829
a2cd141b 3830(define_insn "*arm_extendqisi"
3831 [(set (match_operand:SI 0 "s_register_operand" "=r")
b4e8a300 3832 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
a2cd141b 3833 "TARGET_ARM && arm_arch4 && !arm_arch6"
b4e8a300 3834 "ldr%?sb\\t%0, %1"
a2cd141b 3835 [(set_attr "type" "load_byte")
0d66636f 3836 (set_attr "predicable" "yes")
cffb2a26 3837 (set_attr "pool_range" "256")
3838 (set_attr "neg_pool_range" "244")]
3839)
3fc2009e 3840
a2cd141b 3841(define_insn "*arm_extendqisi_v6"
3842 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
b4e8a300 3843 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
a2cd141b 3844 "TARGET_ARM && arm_arch6"
b4e8a300 3845 "@
3846 sxtb%?\\t%0, %1
3847 ldr%?sb\\t%0, %1"
a2cd141b 3848 [(set_attr "type" "alu_shift,load_byte")
3849 (set_attr "predicable" "yes")
a2cd141b 3850 (set_attr "pool_range" "*,256")
3851 (set_attr "neg_pool_range" "*,244")]
3852)
3853
3854(define_insn "*arm_extendqisi2addsi"
3855 [(set (match_operand:SI 0 "s_register_operand" "=r")
3856 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3857 (match_operand:SI 2 "s_register_operand" "r")))]
3858 "TARGET_ARM && arm_arch6"
3859 "sxtab%?\\t%0, %2, %1"
3860 [(set_attr "type" "alu_shift")
3861 (set_attr "predicable" "yes")]
3862)
3863
a2cd141b 3864(define_insn "*thumb_extendqisi2"
3865 [(set (match_operand:SI 0 "register_operand" "=l,l")
3866 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3867 "TARGET_THUMB && !arm_arch6"
cffb2a26 3868 "*
3869 {
3870 rtx ops[3];
3871 rtx mem = XEXP (operands[1], 0);
3872
3873 if (GET_CODE (mem) == CONST)
3874 mem = XEXP (mem, 0);
3875
3876 if (GET_CODE (mem) == LABEL_REF)
3877 return \"ldr\\t%0, %1\";
3878
3879 if (GET_CODE (mem) == PLUS
3880 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3881 return \"ldr\\t%0, %1\";
3882
3883 if (which_alternative == 0)
3884 return \"ldrsb\\t%0, %1\";
3885
3886 ops[0] = operands[0];
3887
3888 if (GET_CODE (mem) == PLUS)
3889 {
3890 rtx a = XEXP (mem, 0);
3891 rtx b = XEXP (mem, 1);
3892
3893 ops[1] = a;
3894 ops[2] = b;
3895
3896 if (GET_CODE (a) == REG)
3897 {
3898 if (GET_CODE (b) == REG)
3899 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3900 else if (REGNO (a) == REGNO (ops[0]))
215b30b3 3901 {
3902 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3903 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3904 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3905 }
cffb2a26 3906 else
3907 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3908 }
cffb2a26 3909 else
3910 {
ed29c566 3911 gcc_assert (GET_CODE (b) == REG);
cffb2a26 3912 if (REGNO (b) == REGNO (ops[0]))
215b30b3 3913 {
3914 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3915 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3916 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3917 }
cffb2a26 3918 else
3919 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3920 }
3921 }
3922 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3923 {
215b30b3 3924 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3925 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3926 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
cffb2a26 3927 }
3928 else
3929 {
3930 ops[1] = mem;
3931 ops[2] = const0_rtx;
3932
3933 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3934 }
3935 return \"\";
3936 }"
3937 [(set_attr "length" "2,6")
a2cd141b 3938 (set_attr "type" "load_byte,load_byte")
cffb2a26 3939 (set_attr "pool_range" "32,32")]
3940)
3941
a2cd141b 3942(define_insn "*thumb_extendqisi2_v6"
3943 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3944 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3945 "TARGET_THUMB && arm_arch6"
3946 "*
3947 {
3948 rtx ops[3];
3949 rtx mem;
3950
3951 if (which_alternative == 0)
3952 return \"sxtb\\t%0, %1\";
3953
3954 mem = XEXP (operands[1], 0);
3955
3956 if (GET_CODE (mem) == CONST)
3957 mem = XEXP (mem, 0);
3958
3959 if (GET_CODE (mem) == LABEL_REF)
3960 return \"ldr\\t%0, %1\";
3961
3962 if (GET_CODE (mem) == PLUS
3963 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3964 return \"ldr\\t%0, %1\";
3965
3966 if (which_alternative == 0)
3967 return \"ldrsb\\t%0, %1\";
3968
3969 ops[0] = operands[0];
3970
3971 if (GET_CODE (mem) == PLUS)
3972 {
3973 rtx a = XEXP (mem, 0);
3974 rtx b = XEXP (mem, 1);
3975
3976 ops[1] = a;
3977 ops[2] = b;
3978
3979 if (GET_CODE (a) == REG)
3980 {
3981 if (GET_CODE (b) == REG)
3982 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3983 else if (REGNO (a) == REGNO (ops[0]))
3984 {
3985 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3986 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3987 }
3988 else
3989 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3990 }
a2cd141b 3991 else
3992 {
ed29c566 3993 gcc_assert (GET_CODE (b) == REG);
a2cd141b 3994 if (REGNO (b) == REGNO (ops[0]))
3995 {
3996 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3997 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3998 }
3999 else
4000 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4001 }
4002 }
4003 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4004 {
4005 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4006 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4007 }
4008 else
4009 {
4010 ops[1] = mem;
4011 ops[2] = const0_rtx;
4012
4013 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4014 }
4015 return \"\";
4016 }"
4017 [(set_attr "length" "2,2,4")
4018 (set_attr "type" "alu_shift,load_byte,load_byte")
4019 (set_attr "pool_range" "*,32,32")]
4020)
4021
caedf871 4022(define_expand "extendsfdf2"
4023 [(set (match_operand:DF 0 "s_register_operand" "")
4024 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
a2cd141b 4025 "TARGET_ARM && TARGET_HARD_FLOAT"
caedf871 4026 ""
4027)
b11cae9e 4028\f
4029;; Move insns (including loads and stores)
4030
4031;; XXX Just some ideas about movti.
9c08d1fa 4032;; I don't think these are a good idea on the arm, there just aren't enough
4033;; registers
b11cae9e 4034;;(define_expand "loadti"
9c08d1fa 4035;; [(set (match_operand:TI 0 "s_register_operand" "")
b11cae9e 4036;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4037;; "" "")
4038
4039;;(define_expand "storeti"
4040;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
9c08d1fa 4041;; (match_operand:TI 1 "s_register_operand" ""))]
b11cae9e 4042;; "" "")
4043
4044;;(define_expand "movti"
4045;; [(set (match_operand:TI 0 "general_operand" "")
4046;; (match_operand:TI 1 "general_operand" ""))]
4047;; ""
4048;; "
4049;;{
4050;; rtx insn;
4051;;
4052;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4053;; operands[1] = copy_to_reg (operands[1]);
4054;; if (GET_CODE (operands[0]) == MEM)
4055;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4056;; else if (GET_CODE (operands[1]) == MEM)
4057;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4058;; else
4059;; FAIL;
4060;;
4061;; emit_insn (insn);
4062;; DONE;
4063;;}")
4064
a2f10574 4065;; Recognize garbage generated above.
b11cae9e 4066
4067;;(define_insn ""
4068;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4069;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4070;; ""
4071;; "*
4072;; {
4073;; register mem = (which_alternative < 3);
0d66636f 4074;; register const char *template;
b11cae9e 4075;;
4076;; operands[mem] = XEXP (operands[mem], 0);
4077;; switch (which_alternative)
4078;; {
4079;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4080;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4081;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4082;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4083;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4084;; case 5: template = \"stmia\\t%0, %M1\"; break;
4085;; }
e2348bcb 4086;; output_asm_insn (template, operands);
4087;; return \"\";
b11cae9e 4088;; }")
4089
cffb2a26 4090(define_expand "movdi"
4091 [(set (match_operand:DI 0 "general_operand" "")
4092 (match_operand:DI 1 "general_operand" ""))]
4093 "TARGET_EITHER"
4094 "
b2778788 4095 if (!no_new_pseudos)
cffb2a26 4096 {
b2778788 4097 if (GET_CODE (operands[0]) != REG)
4098 operands[1] = force_reg (DImode, operands[1]);
cffb2a26 4099 }
4100 "
4101)
b11cae9e 4102
cffb2a26 4103(define_insn "*arm_movdi"
d51f92df 4104 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4105 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
a2cd141b 4106 "TARGET_ARM
b2778788 4107 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4108 && !TARGET_IWMMXT
4109 && ( register_operand (operands[0], DImode)
4110 || register_operand (operands[1], DImode))"
b11cae9e 4111 "*
d51f92df 4112 switch (which_alternative)
4113 {
4114 case 0:
4115 case 1:
4116 case 2:
4117 return \"#\";
4118 default:
4119 return output_move_double (operands);
4120 }
cffb2a26 4121 "
359a6e9f 4122 [(set_attr "length" "8,12,16,8,8")
4123 (set_attr "type" "*,*,*,load2,store2")
4124 (set_attr "pool_range" "*,*,*,1020,*")
4125 (set_attr "neg_pool_range" "*,*,*,1008,*")]
cffb2a26 4126)
4127
d51f92df 4128(define_split
4129 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4130 (match_operand:ANY64 1 "const_double_operand" ""))]
4131 "TARGET_ARM
4132 && reload_completed
4133 && (arm_const_double_inline_cost (operands[1])
4134 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4135 [(const_int 0)]
4136 "
4137 arm_split_constant (SET, SImode, curr_insn,
4138 INTVAL (gen_lowpart (SImode, operands[1])),
4139 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4140 arm_split_constant (SET, SImode, curr_insn,
4141 INTVAL (gen_highpart_mode (SImode,
4142 GET_MODE (operands[0]),
4143 operands[1])),
4144 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4145 DONE;
4146 "
4147)
4148
e5ba9289 4149; If optimizing for size, or if we have load delay slots, then
4150; we want to split the constant into two separate operations.
4151; In both cases this may split a trivial part into a single data op
4152; leaving a single complex constant to load. We can also get longer
4153; offsets in a LDR which means we get better chances of sharing the pool
4154; entries. Finally, we can normally do a better job of scheduling
4155; LDR instructions than we can with LDM.
4156; This pattern will only match if the one above did not.
4157(define_split
4158 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4159 (match_operand:ANY64 1 "const_double_operand" ""))]
4160 "TARGET_ARM && reload_completed
4161 && arm_const_double_by_parts (operands[1])"
4162 [(set (match_dup 0) (match_dup 1))
4163 (set (match_dup 2) (match_dup 3))]
4164 "
4165 operands[2] = gen_highpart (SImode, operands[0]);
4166 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4167 operands[1]);
4168 operands[0] = gen_lowpart (SImode, operands[0]);
4169 operands[1] = gen_lowpart (SImode, operands[1]);
4170 "
4171)
4172
d51f92df 4173(define_split
4174 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4175 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4176 "TARGET_EITHER && reload_completed"
4177 [(set (match_dup 0) (match_dup 1))
4178 (set (match_dup 2) (match_dup 3))]
4179 "
4180 operands[2] = gen_highpart (SImode, operands[0]);
4181 operands[3] = gen_highpart (SImode, operands[1]);
4182 operands[0] = gen_lowpart (SImode, operands[0]);
4183 operands[1] = gen_lowpart (SImode, operands[1]);
4184
4185 /* Handle a partial overlap. */
4186 if (rtx_equal_p (operands[0], operands[3]))
4187 {
4188 rtx tmp0 = operands[0];
4189 rtx tmp1 = operands[1];
4190
4191 operands[0] = operands[2];
4192 operands[1] = operands[3];
4193 operands[2] = tmp0;
4194 operands[3] = tmp1;
4195 }
4196 "
4197)
4198
a8a3b539 4199;; We can't actually do base+index doubleword loads if the index and
4200;; destination overlap. Split here so that we at least have chance to
4201;; schedule.
4202(define_split
4203 [(set (match_operand:DI 0 "s_register_operand" "")
4204 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4205 (match_operand:SI 2 "s_register_operand" ""))))]
4206 "TARGET_LDRD
4207 && reg_overlap_mentioned_p (operands[0], operands[1])
4208 && reg_overlap_mentioned_p (operands[0], operands[2])"
4209 [(set (match_dup 4)
4210 (plus:SI (match_dup 1)
4211 (match_dup 2)))
4212 (set (match_dup 0)
4213 (mem:DI (match_dup 4)))]
4214 "
4215 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4216 "
4217)
4218
cffb2a26 4219;;; ??? This should have alternatives for constants.
4220;;; ??? This was originally identical to the movdf_insn pattern.
4221;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4222;;; thumb_reorg with a memory reference.
4223(define_insn "*thumb_movdi_insn"
215b30b3 4224 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4225 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
cffb2a26 4226 "TARGET_THUMB
a2cd141b 4227 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
cffb2a26 4228 && ( register_operand (operands[0], DImode)
4229 || register_operand (operands[1], DImode))"
4230 "*
4231 {
4232 switch (which_alternative)
4233 {
4234 default:
4235 case 0:
4236 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4237 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4238 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4239 case 1:
4240 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4241 case 2:
4242 operands[1] = GEN_INT (- INTVAL (operands[1]));
4243 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4244 case 3:
4245 return \"ldmia\\t%1, {%0, %H0}\";
4246 case 4:
4247 return \"stmia\\t%0, {%1, %H1}\";
4248 case 5:
4249 return thumb_load_double_from_address (operands);
4250 case 6:
1a83b3ff 4251 operands[2] = gen_rtx_MEM (SImode,
215b30b3 4252 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 4253 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4254 return \"\";
4255 case 7:
4256 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4257 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4258 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4259 }
4260 }"
4261 [(set_attr "length" "4,4,6,2,2,6,4,4")
a2cd141b 4262 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
cffb2a26 4263 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4264)
b11cae9e 4265
9c08d1fa 4266(define_expand "movsi"
4267 [(set (match_operand:SI 0 "general_operand" "")
4268 (match_operand:SI 1 "general_operand" ""))]
cffb2a26 4269 "TARGET_EITHER"
9c08d1fa 4270 "
cffb2a26 4271 if (TARGET_ARM)
9c08d1fa 4272 {
674a8f0b 4273 /* Everything except mem = const or mem = mem can be done easily. */
cffb2a26 4274 if (GET_CODE (operands[0]) == MEM)
4275 operands[1] = force_reg (SImode, operands[1]);
a2cd141b 4276 if (arm_general_register_operand (operands[0], SImode)
4277 && GET_CODE (operands[1]) == CONST_INT
cffb2a26 4278 && !(const_ok_for_arm (INTVAL (operands[1]))
4279 || const_ok_for_arm (~INTVAL (operands[1]))))
4280 {
96f57e36 4281 arm_split_constant (SET, SImode, NULL_RTX,
4282 INTVAL (operands[1]), operands[0], NULL_RTX,
615caa51 4283 optimize && !no_new_pseudos);
cffb2a26 4284 DONE;
4285 }
4286 }
674a8f0b 4287 else /* TARGET_THUMB.... */
cffb2a26 4288 {
215b30b3 4289 if (!no_new_pseudos)
cffb2a26 4290 {
4291 if (GET_CODE (operands[0]) != REG)
4292 operands[1] = force_reg (SImode, operands[1]);
4293 }
9c08d1fa 4294 }
f655717d 4295
4296 /* Recognize the case where operand[1] is a reference to thread-local
4297 data and load its address to a register. */
4298 if (arm_tls_referenced_p (operands[1]))
4299 {
4300 rtx tmp = operands[1];
4301 rtx addend = NULL;
4302
4303 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4304 {
4305 addend = XEXP (XEXP (tmp, 0), 1);
4306 tmp = XEXP (XEXP (tmp, 0), 0);
4307 }
4308
4309 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4310 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4311
4312 tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4313 if (addend)
4314 {
4315 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4316 tmp = force_operand (tmp, operands[0]);
4317 }
4318 operands[1] = tmp;
4319 }
4320 else if (flag_pic
4321 && (CONSTANT_P (operands[1])
4322 || symbol_mentioned_p (operands[1])
4323 || label_mentioned_p (operands[1])))
4324 operands[1] = legitimize_pic_address (operands[1], SImode,
4325 (no_new_pseudos ? operands[0] : 0));
215b30b3 4326 "
4327)
9c08d1fa 4328
cffb2a26 4329(define_insn "*arm_movsi_insn"
215b30b3 4330 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4331 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
755eb2b4 4332 "TARGET_ARM && ! TARGET_IWMMXT
a2cd141b 4333 && !(TARGET_HARD_FLOAT && TARGET_VFP)
cffb2a26 4334 && ( register_operand (operands[0], SImode)
4335 || register_operand (operands[1], SImode))"
f7fbdd4a 4336 "@
4337 mov%?\\t%0, %1
4338 mvn%?\\t%0, #%B1
4339 ldr%?\\t%0, %1
4340 str%?\\t%1, %0"
a2cd141b 4341 [(set_attr "type" "*,*,load1,store1")
0d66636f 4342 (set_attr "predicable" "yes")
cffb2a26 4343 (set_attr "pool_range" "*,*,4096,*")
4344 (set_attr "neg_pool_range" "*,*,4084,*")]
4345)
87b22bf7 4346
4347(define_split
a2cd141b 4348 [(set (match_operand:SI 0 "arm_general_register_operand" "")
87b22bf7 4349 (match_operand:SI 1 "const_int_operand" ""))]
cffb2a26 4350 "TARGET_ARM
215b30b3 4351 && (!(const_ok_for_arm (INTVAL (operands[1]))
4352 || const_ok_for_arm (~INTVAL (operands[1]))))"
87b22bf7 4353 [(clobber (const_int 0))]
4354 "
96f57e36 4355 arm_split_constant (SET, SImode, NULL_RTX,
4356 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
87b22bf7 4357 DONE;
215b30b3 4358 "
4359)
9c08d1fa 4360
cffb2a26 4361(define_insn "*thumb_movsi_insn"
215b30b3 4362 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4363 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
cffb2a26 4364 "TARGET_THUMB
4365 && ( register_operand (operands[0], SImode)
4366 || register_operand (operands[1], SImode))"
4367 "@
4368 mov %0, %1
4369 mov %0, %1
4370 #
4371 #
4372 ldmia\\t%1, {%0}
4373 stmia\\t%0, {%1}
4374 ldr\\t%0, %1
4375 str\\t%1, %0
4376 mov\\t%0, %1"
4377 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
a2cd141b 4378 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
cffb2a26 4379 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4380)
4381
4382(define_split
4383 [(set (match_operand:SI 0 "register_operand" "")
4384 (match_operand:SI 1 "const_int_operand" ""))]
4385 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4386 [(set (match_dup 0) (match_dup 1))
4387 (set (match_dup 0) (neg:SI (match_dup 0)))]
4388 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4389)
4390
4391(define_split
4392 [(set (match_operand:SI 0 "register_operand" "")
4393 (match_operand:SI 1 "const_int_operand" ""))]
4394 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4395 [(set (match_dup 0) (match_dup 1))
4396 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4397 "
4398 {
4399 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4400 unsigned HOST_WIDE_INT mask = 0xff;
4401 int i;
4402
4403 for (i = 0; i < 25; i++)
4404 if ((val & (mask << i)) == val)
4405 break;
4406
f5b3169c 4407 /* Shouldn't happen, but we don't want to split if the shift is zero. */
cffb2a26 4408 if (i == 0)
4409 FAIL;
4410
4411 operands[1] = GEN_INT (val >> i);
4412 operands[2] = GEN_INT (i);
4413 }"
4414)
4415
67336bcf 4416;; When generating pic, we need to load the symbol offset into a register.
4417;; So that the optimizer does not confuse this with a normal symbol load
4418;; we use an unspec. The offset will be loaded from a constant pool entry,
4419;; since that is the only type of relocation we can use.
4420
4421;; The rather odd constraints on the following are to force reload to leave
4422;; the insn alone, and to force the minipool generation pass to then move
4423;; the GOT symbol to memory.
849170fd 4424
8c4d8060 4425(define_insn "pic_load_addr_arm"
849170fd 4426 [(set (match_operand:SI 0 "s_register_operand" "=r")
e1159bbe 4427 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4428 "TARGET_ARM && flag_pic"
67336bcf 4429 "ldr%?\\t%0, %1"
a2cd141b 4430 [(set_attr "type" "load1")
8c4d8060 4431 (set (attr "pool_range") (const_int 4096))
4432 (set (attr "neg_pool_range") (const_int 4084))]
4433)
4434
4435(define_insn "pic_load_addr_thumb"
4436 [(set (match_operand:SI 0 "s_register_operand" "=l")
e1159bbe 4437 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
8c4d8060 4438 "TARGET_THUMB && flag_pic"
4439 "ldr\\t%0, %1"
a2cd141b 4440 [(set_attr "type" "load1")
8c4d8060 4441 (set (attr "pool_range") (const_int 1024))]
cffb2a26 4442)
849170fd 4443
4444;; This variant is used for AOF assembly, since it needs to mention the
4445;; pic register in the rtl.
4446(define_expand "pic_load_addr_based"
7db9af5d 4447 [(set (match_operand:SI 0 "s_register_operand" "")
e1159bbe 4448 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
cffb2a26 4449 "TARGET_ARM && flag_pic"
2cb7d577 4450 "operands[2] = cfun->machine->pic_reg;"
cffb2a26 4451)
849170fd 4452
4453(define_insn "*pic_load_addr_based_insn"
4454 [(set (match_operand:SI 0 "s_register_operand" "=r")
4455 (unspec:SI [(match_operand 1 "" "")
e1159bbe 4456 (match_operand 2 "s_register_operand" "r")]
4457 UNSPEC_PIC_SYM))]
2cb7d577 4458 "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
849170fd 4459 "*
4460#ifdef AOF_ASSEMBLER
4461 operands[1] = aof_pic_entry (operands[1]);
4462#endif
4463 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4464 return \"\";
cffb2a26 4465 "
a2cd141b 4466 [(set_attr "type" "load1")
cffb2a26 4467 (set (attr "pool_range")
4468 (if_then_else (eq_attr "is_thumb" "yes")
4469 (const_int 1024)
4470 (const_int 4096)))
4471 (set (attr "neg_pool_range")
4472 (if_then_else (eq_attr "is_thumb" "yes")
4473 (const_int 0)
4474 (const_int 4084)))]
4475)
4476
4477(define_insn "pic_add_dot_plus_four"
15d5d060 4478 [(set (match_operand:SI 0 "register_operand" "=r")
4479 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
2c96dc5a 4480 (const (plus:SI (pc) (const_int 4))))]
4481 UNSPEC_PIC_BASE))
6cdcb15c 4482 (use (match_operand 2 "" ""))]
f655717d 4483 "TARGET_THUMB"
cffb2a26 4484 "*
6cdcb15c 4485 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4486 INTVAL (operands[2]));
cffb2a26 4487 return \"add\\t%0, %|pc\";
4488 "
4489 [(set_attr "length" "2")]
4490)
849170fd 4491
4492(define_insn "pic_add_dot_plus_eight"
15d5d060 4493 [(set (match_operand:SI 0 "register_operand" "=r")
4494 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
2c96dc5a 4495 (const (plus:SI (pc) (const_int 8))))]
4496 UNSPEC_PIC_BASE))
6cdcb15c 4497 (use (match_operand 2 "" ""))]
f655717d 4498 "TARGET_ARM"
c4034607 4499 "*
6cdcb15c 4500 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4501 INTVAL (operands[2]));
15d5d060 4502 return \"add%?\\t%0, %|pc, %1\";
cffb2a26 4503 "
0d66636f 4504 [(set_attr "predicable" "yes")]
cffb2a26 4505)
849170fd 4506
f655717d 4507(define_insn "tls_load_dot_plus_eight"
4508 [(set (match_operand:SI 0 "register_operand" "+r")
4509 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4510 (const (plus:SI (pc) (const_int 8))))]
4511 UNSPEC_PIC_BASE)))
6cdcb15c 4512 (use (match_operand 2 "" ""))]
f655717d 4513 "TARGET_ARM"
4514 "*
6cdcb15c 4515 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4516 INTVAL (operands[2]));
f655717d 4517 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4518 "
4519 [(set_attr "predicable" "yes")]
4520)
4521
4522;; PIC references to local variables can generate pic_add_dot_plus_eight
4523;; followed by a load. These sequences can be crunched down to
4524;; tls_load_dot_plus_eight by a peephole.
4525
4526(define_peephole2
4527 [(parallel [(set (match_operand:SI 0 "register_operand" "")
15d5d060 4528 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
f655717d 4529 (const (plus:SI (pc) (const_int 8))))]
4530 UNSPEC_PIC_BASE))
4531 (use (label_ref (match_operand 1 "" "")))])
4532 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4533 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
15d5d060 4534 [(parallel [(set (match_dup 2)
4535 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
f655717d 4536 (const (plus:SI (pc) (const_int 8))))]
4537 UNSPEC_PIC_BASE)))
15d5d060 4538 (use (label_ref (match_dup 1)))])]
f655717d 4539 ""
4540)
4541
95373f08 4542(define_expand "builtin_setjmp_receiver"
4543 [(label_ref (match_operand 0 "" ""))]
4544 "flag_pic"
4545 "
4546{
b935b306 4547 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4548 register. */
2cb7d577 4549 if (arm_pic_register != INVALID_REGNUM)
4550 arm_load_pic_register (1UL << 3);
95373f08 4551 DONE;
4552}")
4553
9c08d1fa 4554;; If copying one reg to another we can set the condition codes according to
4555;; its value. Such a move is common after a return from subroutine and the
4556;; result is being tested against zero.
4557
f7fbdd4a 4558(define_insn "*movsi_compare0"
bd5b4116 4559 [(set (reg:CC CC_REGNUM)
cffb2a26 4560 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4561 (const_int 0)))
4562 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4563 (match_dup 1))]
4564 "TARGET_ARM"
e2348bcb 4565 "@
40dbec34 4566 cmp%?\\t%0, #0
4567 sub%?s\\t%0, %1, #0"
cffb2a26 4568 [(set_attr "conds" "set")]
4569)
b11cae9e 4570
b11cae9e 4571;; Subroutine to store a half word from a register into memory.
4572;; Operand 0 is the source register (HImode)
c8f69309 4573;; Operand 1 is the destination address in a register (SImode)
b11cae9e 4574
9c08d1fa 4575;; In both this routine and the next, we must be careful not to spill
01cc3b75 4576;; a memory address of reg+large_const into a separate PLUS insn, since this
9c08d1fa 4577;; can generate unrecognizable rtl.
4578
b11cae9e 4579(define_expand "storehi"
c8f69309 4580 [;; store the low byte
f082f1c4 4581 (set (match_operand 1 "" "") (match_dup 3))
b11cae9e 4582 ;; extract the high byte
c8f69309 4583 (set (match_dup 2)
4584 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
b11cae9e 4585 ;; store the high byte
787f8210 4586 (set (match_dup 4) (match_dup 5))]
cffb2a26 4587 "TARGET_ARM"
b11cae9e 4588 "
215b30b3 4589 {
537ffcfc 4590 rtx op1 = operands[1];
4591 rtx addr = XEXP (op1, 0);
215b30b3 4592 enum rtx_code code = GET_CODE (addr);
4593
4594 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4595 || code == MINUS)
537ffcfc 4596 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
215b30b3 4597
537ffcfc 4598 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4599 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4600 operands[3] = gen_lowpart (QImode, operands[0]);
4601 operands[0] = gen_lowpart (SImode, operands[0]);
787f8210 4602 operands[2] = gen_reg_rtx (SImode);
4603 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4604 }"
4605)
b11cae9e 4606
c7597b5d 4607(define_expand "storehi_bigend"
f082f1c4 4608 [(set (match_dup 4) (match_dup 3))
c7597b5d 4609 (set (match_dup 2)
4610 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
787f8210 4611 (set (match_operand 1 "" "") (match_dup 5))]
cffb2a26 4612 "TARGET_ARM"
b11cae9e 4613 "
215b30b3 4614 {
537ffcfc 4615 rtx op1 = operands[1];
4616 rtx addr = XEXP (op1, 0);
215b30b3 4617 enum rtx_code code = GET_CODE (addr);
4618
4619 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4620 || code == MINUS)
537ffcfc 4621 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
215b30b3 4622
537ffcfc 4623 operands[4] = adjust_address (op1, QImode, 1);
e513d163 4624 operands[1] = adjust_address (operands[1], QImode, 0);
215b30b3 4625 operands[3] = gen_lowpart (QImode, operands[0]);
4626 operands[0] = gen_lowpart (SImode, operands[0]);
4627 operands[2] = gen_reg_rtx (SImode);
787f8210 4628 operands[5] = gen_lowpart (QImode, operands[2]);
215b30b3 4629 }"
4630)
c7597b5d 4631
4632;; Subroutine to store a half word integer constant into memory.
4633(define_expand "storeinthi"
f082f1c4 4634 [(set (match_operand 0 "" "")
787f8210 4635 (match_operand 1 "" ""))
9e8503e6 4636 (set (match_dup 3) (match_dup 2))]
cffb2a26 4637 "TARGET_ARM"
c7597b5d 4638 "
215b30b3 4639 {
4640 HOST_WIDE_INT value = INTVAL (operands[1]);
4641 rtx addr = XEXP (operands[0], 0);
537ffcfc 4642 rtx op0 = operands[0];
215b30b3 4643 enum rtx_code code = GET_CODE (addr);
c7597b5d 4644
215b30b3 4645 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4646 || code == MINUS)
537ffcfc 4647 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
c7597b5d 4648
215b30b3 4649 operands[1] = gen_reg_rtx (SImode);
4650 if (BYTES_BIG_ENDIAN)
4651 {
4652 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4653 if ((value & 255) == ((value >> 8) & 255))
4654 operands[2] = operands[1];
4655 else
4656 {
4657 operands[2] = gen_reg_rtx (SImode);
4658 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4659 }
4660 }
4661 else
4662 {
4663 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4664 if ((value & 255) == ((value >> 8) & 255))
4665 operands[2] = operands[1];
4666 else
4667 {
4668 operands[2] = gen_reg_rtx (SImode);
4669 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4670 }
4671 }
c7597b5d 4672
537ffcfc 4673 operands[3] = adjust_address (op0, QImode, 1);
e513d163 4674 operands[0] = adjust_address (operands[0], QImode, 0);
9e8503e6 4675 operands[2] = gen_lowpart (QImode, operands[2]);
787f8210 4676 operands[1] = gen_lowpart (QImode, operands[1]);
215b30b3 4677 }"
4678)
b11cae9e 4679
f7fbdd4a 4680(define_expand "storehi_single_op"
4681 [(set (match_operand:HI 0 "memory_operand" "")
4682 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4683 "TARGET_ARM && arm_arch4"
f7fbdd4a 4684 "
215b30b3 4685 if (!s_register_operand (operands[1], HImode))
f7fbdd4a 4686 operands[1] = copy_to_mode_reg (HImode, operands[1]);
215b30b3 4687 "
4688)
f7fbdd4a 4689
b11cae9e 4690(define_expand "movhi"
4691 [(set (match_operand:HI 0 "general_operand" "")
c8f69309 4692 (match_operand:HI 1 "general_operand" ""))]
cffb2a26 4693 "TARGET_EITHER"
b11cae9e 4694 "
cffb2a26 4695 if (TARGET_ARM)
b11cae9e 4696 {
215b30b3 4697 if (!no_new_pseudos)
cffb2a26 4698 {
4699 if (GET_CODE (operands[0]) == MEM)
b11cae9e 4700 {
cffb2a26 4701 if (arm_arch4)
4702 {
4703 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4704 DONE;
4705 }
4706 if (GET_CODE (operands[1]) == CONST_INT)
4707 emit_insn (gen_storeinthi (operands[0], operands[1]));
c7597b5d 4708 else
cffb2a26 4709 {
4710 if (GET_CODE (operands[1]) == MEM)
4711 operands[1] = force_reg (HImode, operands[1]);
4712 if (BYTES_BIG_ENDIAN)
4713 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4714 else
4715 emit_insn (gen_storehi (operands[1], operands[0]));
4716 }
4717 DONE;
b11cae9e 4718 }
cffb2a26 4719 /* Sign extend a constant, and keep it in an SImode reg. */
4720 else if (GET_CODE (operands[1]) == CONST_INT)
9c08d1fa 4721 {
cffb2a26 4722 rtx reg = gen_reg_rtx (SImode);
4723 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4724
4725 /* If the constant is already valid, leave it alone. */
215b30b3 4726 if (!const_ok_for_arm (val))
cffb2a26 4727 {
4728 /* If setting all the top bits will make the constant
4729 loadable in a single instruction, then set them.
4730 Otherwise, sign extend the number. */
4731
215b30b3 4732 if (const_ok_for_arm (~(val | ~0xffff)))
cffb2a26 4733 val |= ~0xffff;
4734 else if (val & 0x8000)
4735 val |= ~0xffff;
4736 }
4737
4738 emit_insn (gen_movsi (reg, GEN_INT (val)));
9e8503e6 4739 operands[1] = gen_lowpart (HImode, reg);
9c08d1fa 4740 }
615caa51 4741 else if (arm_arch4 && optimize && !no_new_pseudos
0045890a 4742 && GET_CODE (operands[1]) == MEM)
4743 {
4744 rtx reg = gen_reg_rtx (SImode);
4745
4746 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4747 operands[1] = gen_lowpart (HImode, reg);
4748 }
215b30b3 4749 else if (!arm_arch4)
f7fbdd4a 4750 {
cffb2a26 4751 if (GET_CODE (operands[1]) == MEM)
4752 {
c1a66faf 4753 rtx base;
4754 rtx offset = const0_rtx;
4755 rtx reg = gen_reg_rtx (SImode);
4756
4757 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4758 || (GET_CODE (base) == PLUS
4759 && (GET_CODE (offset = XEXP (base, 1))
4760 == CONST_INT)
4761 && ((INTVAL(offset) & 1) != 1)
4762 && GET_CODE (base = XEXP (base, 0)) == REG))
4763 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
206ee9a2 4764 {
c1a66faf 4765 rtx new;
4766
788fcce0 4767 new = widen_memory_access (operands[1], SImode,
4768 ((INTVAL (offset) & ~3)
4769 - INTVAL (offset)));
c1a66faf 4770 emit_insn (gen_movsi (reg, new));
4771 if (((INTVAL (offset) & 2) != 0)
4772 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4773 {
4774 rtx reg2 = gen_reg_rtx (SImode);
4775
4776 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4777 reg = reg2;
4778 }
206ee9a2 4779 }
c1a66faf 4780 else
4781 emit_insn (gen_movhi_bytes (reg, operands[1]));
4782
4783 operands[1] = gen_lowpart (HImode, reg);
cffb2a26 4784 }
4785 }
4786 }
674a8f0b 4787 /* Handle loading a large integer during reload. */
cffb2a26 4788 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4789 && !const_ok_for_arm (INTVAL (operands[1]))
4790 && !const_ok_for_arm (~INTVAL (operands[1])))
cffb2a26 4791 {
4792 /* Writing a constant to memory needs a scratch, which should
4793 be handled with SECONDARY_RELOADs. */
ed29c566 4794 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 4795
4796 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4797 emit_insn (gen_movsi (operands[0], operands[1]));
4798 DONE;
4799 }
4800 }
4801 else /* TARGET_THUMB */
4802 {
215b30b3 4803 if (!no_new_pseudos)
cffb2a26 4804 {
6cffc037 4805 if (GET_CODE (operands[1]) == CONST_INT)
4806 {
4807 rtx reg = gen_reg_rtx (SImode);
4808
4809 emit_insn (gen_movsi (reg, operands[1]));
4810 operands[1] = gen_lowpart (HImode, reg);
4811 }
cffb2a26 4812
4813 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 4814 happen if we are passed a SP (never OK for HImode/QImode) or
4815 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4816 HImode/QImode) relative address. */
cffb2a26 4817 /* ??? This should perhaps be fixed elsewhere, for instance, in
4818 fixup_stack_1, by checking for other kinds of invalid addresses,
4819 e.g. a bare reference to a virtual register. This may confuse the
4820 alpha though, which must handle this case differently. */
4821 if (GET_CODE (operands[0]) == MEM
215b30b3 4822 && !memory_address_p (GET_MODE (operands[0]),
4823 XEXP (operands[0], 0)))
537ffcfc 4824 operands[0]
4825 = replace_equiv_address (operands[0],
4826 copy_to_reg (XEXP (operands[0], 0)));
cffb2a26 4827
4828 if (GET_CODE (operands[1]) == MEM
215b30b3 4829 && !memory_address_p (GET_MODE (operands[1]),
4830 XEXP (operands[1], 0)))
537ffcfc 4831 operands[1]
4832 = replace_equiv_address (operands[1],
4833 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 4834
4835 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4836 {
4837 rtx reg = gen_reg_rtx (SImode);
4838
4839 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4840 operands[1] = gen_lowpart (HImode, reg);
4841 }
4842
4843 if (GET_CODE (operands[0]) == MEM)
4844 operands[1] = force_reg (HImode, operands[1]);
cffb2a26 4845 }
cffb2a26 4846 else if (GET_CODE (operands[1]) == CONST_INT
215b30b3 4847 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
cffb2a26 4848 {
6cffc037 4849 /* Handle loading a large integer during reload. */
4850
cffb2a26 4851 /* Writing a constant to memory needs a scratch, which should
4852 be handled with SECONDARY_RELOADs. */
ed29c566 4853 gcc_assert (GET_CODE (operands[0]) == REG);
cffb2a26 4854
1a83b3ff 4855 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
cffb2a26 4856 emit_insn (gen_movsi (operands[0], operands[1]));
4857 DONE;
4858 }
b11cae9e 4859 }
cffb2a26 4860 "
4861)
4862
4863(define_insn "*thumb_movhi_insn"
a941568e 4864 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4865 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
cffb2a26 4866 "TARGET_THUMB
4867 && ( register_operand (operands[0], HImode)
4868 || register_operand (operands[1], HImode))"
4869 "*
4870 switch (which_alternative)
d79300ac 4871 {
cffb2a26 4872 case 0: return \"add %0, %1, #0\";
4873 case 2: return \"strh %1, %0\";
4874 case 3: return \"mov %0, %1\";
4875 case 4: return \"mov %0, %1\";
4876 case 5: return \"mov %0, %1\";
ed29c566 4877 default: gcc_unreachable ();
cffb2a26 4878 case 1:
4879 /* The stack pointer can end up being taken as an index register.
4880 Catch this case here and deal with it. */
4881 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4882 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4883 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4884 {
4885 rtx ops[2];
4886 ops[0] = operands[0];
4887 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4888
4889 output_asm_insn (\"mov %0, %1\", ops);
4890
4891 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4892
4893 }
4894 return \"ldrh %0, %1\";
4895 }"
4896 [(set_attr "length" "2,4,2,2,2,2")
a2cd141b 4897 (set_attr "type" "*,load1,store1,*,*,*")]
cffb2a26 4898)
d79300ac 4899
b11cae9e 4900
25f7a26e 4901(define_expand "movhi_bytes"
eab14235 4902 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
25f7a26e 4903 (set (match_dup 3)
eab14235 4904 (zero_extend:SI (match_dup 6)))
25f7a26e 4905 (set (match_operand:SI 0 "" "")
4906 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
cffb2a26 4907 "TARGET_ARM"
25f7a26e 4908 "
215b30b3 4909 {
4910 rtx mem1, mem2;
4911 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4912
788fcce0 4913 mem1 = change_address (operands[1], QImode, addr);
4914 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
215b30b3 4915 operands[0] = gen_lowpart (SImode, operands[0]);
4916 operands[1] = mem1;
4917 operands[2] = gen_reg_rtx (SImode);
4918 operands[3] = gen_reg_rtx (SImode);
4919 operands[6] = mem2;
25f7a26e 4920
215b30b3 4921 if (BYTES_BIG_ENDIAN)
4922 {
4923 operands[4] = operands[2];
4924 operands[5] = operands[3];
4925 }
4926 else
4927 {
4928 operands[4] = operands[3];
4929 operands[5] = operands[2];
4930 }
4931 }"
4932)
25f7a26e 4933
c7597b5d 4934(define_expand "movhi_bigend"
4935 [(set (match_dup 2)
4936 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4937 (const_int 16)))
4938 (set (match_dup 3)
4939 (ashiftrt:SI (match_dup 2) (const_int 16)))
4940 (set (match_operand:HI 0 "s_register_operand" "")
787f8210 4941 (match_dup 4))]
cffb2a26 4942 "TARGET_ARM"
c7597b5d 4943 "
4944 operands[2] = gen_reg_rtx (SImode);
4945 operands[3] = gen_reg_rtx (SImode);
787f8210 4946 operands[4] = gen_lowpart (HImode, operands[3]);
215b30b3 4947 "
4948)
b11cae9e 4949
a2f10574 4950;; Pattern to recognize insn generated default case above
f7fbdd4a 4951(define_insn "*movhi_insn_arch4"
cffb2a26 4952 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
215b30b3 4953 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
cffb2a26 4954 "TARGET_ARM
4955 && arm_arch4
f7fbdd4a 4956 && (GET_CODE (operands[1]) != CONST_INT
4957 || const_ok_for_arm (INTVAL (operands[1]))
4958 || const_ok_for_arm (~INTVAL (operands[1])))"
4959 "@
4960 mov%?\\t%0, %1\\t%@ movhi
4961 mvn%?\\t%0, #%B1\\t%@ movhi
aed179ae 4962 str%?h\\t%1, %0\\t%@ movhi
cffb2a26 4963 ldr%?h\\t%0, %1\\t%@ movhi"
a2cd141b 4964 [(set_attr "type" "*,*,store1,load1")
0d66636f 4965 (set_attr "predicable" "yes")
cffb2a26 4966 (set_attr "pool_range" "*,*,*,256")
4967 (set_attr "neg_pool_range" "*,*,*,244")]
4968)
f7fbdd4a 4969
f7fbdd4a 4970(define_insn "*movhi_bytes"
25f7a26e 4971 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4972 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
c1a66faf 4973 "TARGET_ARM"
25f7a26e 4974 "@
4975 mov%?\\t%0, %1\\t%@ movhi
0d66636f 4976 mvn%?\\t%0, #%B1\\t%@ movhi"
4977 [(set_attr "predicable" "yes")]
4978)
25f7a26e 4979
f90b51f1 4980(define_expand "thumb_movhi_clobber"
4981 [(set (match_operand:HI 0 "memory_operand" "")
4982 (match_operand:HI 1 "register_operand" ""))
4983 (clobber (match_operand:DI 2 "register_operand" ""))]
cffb2a26 4984 "TARGET_THUMB"
f90b51f1 4985 "
4986 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4987 && REGNO (operands[1]) <= LAST_LO_REGNUM)
4988 {
4989 emit_insn (gen_movhi (operands[0], operands[1]));
4990 DONE;
4991 }
4992 /* XXX Fixme, need to handle other cases here as well. */
4993 gcc_unreachable ();
4994 "
cffb2a26 4995)
4996
bc5c7e08 4997;; We use a DImode scratch because we may occasionally need an additional
4998;; temporary if the address isn't offsettable -- push_reload doesn't seem
4999;; to take any notice of the "o" constraints on reload_memory_operand operand.
d3373b54 5000(define_expand "reload_outhi"
cffb2a26 5001 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
215b30b3 5002 (match_operand:HI 1 "s_register_operand" "r")
5003 (match_operand:DI 2 "s_register_operand" "=&l")])]
cffb2a26 5004 "TARGET_EITHER"
5005 "if (TARGET_ARM)
5006 arm_reload_out_hi (operands);
5007 else
5008 thumb_reload_out_hi (operands);
d3373b54 5009 DONE;
cffb2a26 5010 "
5011)
d3373b54 5012
25f7a26e 5013(define_expand "reload_inhi"
5014 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
cffb2a26 5015 (match_operand:HI 1 "arm_reload_memory_operand" "o")
bc5c7e08 5016 (match_operand:DI 2 "s_register_operand" "=&r")])]
c1a66faf 5017 "TARGET_EITHER"
25f7a26e 5018 "
cffb2a26 5019 if (TARGET_ARM)
5020 arm_reload_in_hi (operands);
5021 else
5022 thumb_reload_out_hi (operands);
25f7a26e 5023 DONE;
5024")
5025
9c08d1fa 5026(define_expand "movqi"
5027 [(set (match_operand:QI 0 "general_operand" "")
5028 (match_operand:QI 1 "general_operand" ""))]
cffb2a26 5029 "TARGET_EITHER"
9c08d1fa 5030 "
6cffc037 5031 /* Everything except mem = const or mem = mem can be done easily */
0045890a 5032
6cffc037 5033 if (!no_new_pseudos)
cffb2a26 5034 {
6cffc037 5035 if (GET_CODE (operands[1]) == CONST_INT)
5036 {
5037 rtx reg = gen_reg_rtx (SImode);
5038
5039 emit_insn (gen_movsi (reg, operands[1]));
5040 operands[1] = gen_lowpart (QImode, reg);
5041 }
cffb2a26 5042
6cffc037 5043 if (TARGET_THUMB)
5044 {
cffb2a26 5045 /* ??? We shouldn't really get invalid addresses here, but this can
215b30b3 5046 happen if we are passed a SP (never OK for HImode/QImode) or
5047 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5048 HImode/QImode) relative address. */
cffb2a26 5049 /* ??? This should perhaps be fixed elsewhere, for instance, in
5050 fixup_stack_1, by checking for other kinds of invalid addresses,
5051 e.g. a bare reference to a virtual register. This may confuse the
5052 alpha though, which must handle this case differently. */
5053 if (GET_CODE (operands[0]) == MEM
215b30b3 5054 && !memory_address_p (GET_MODE (operands[0]),
cffb2a26 5055 XEXP (operands[0], 0)))
537ffcfc 5056 operands[0]
5057 = replace_equiv_address (operands[0],
5058 copy_to_reg (XEXP (operands[0], 0)));
215b30b3 5059 if (GET_CODE (operands[1]) == MEM
5060 && !memory_address_p (GET_MODE (operands[1]),
cffb2a26 5061 XEXP (operands[1], 0)))
537ffcfc 5062 operands[1]
5063 = replace_equiv_address (operands[1],
5064 copy_to_reg (XEXP (operands[1], 0)));
6cffc037 5065 }
5066
5067 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5068 {
5069 rtx reg = gen_reg_rtx (SImode);
5070
5071 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5072 operands[1] = gen_lowpart (QImode, reg);
5073 }
5074
5075 if (GET_CODE (operands[0]) == MEM)
5076 operands[1] = force_reg (QImode, operands[1]);
5077 }
5078 else if (TARGET_THUMB
5079 && GET_CODE (operands[1]) == CONST_INT
5080 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5081 {
674a8f0b 5082 /* Handle loading a large integer during reload. */
cffb2a26 5083
6cffc037 5084 /* Writing a constant to memory needs a scratch, which should
5085 be handled with SECONDARY_RELOADs. */
5086 gcc_assert (GET_CODE (operands[0]) == REG);
5087
5088 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5089 emit_insn (gen_movsi (operands[0], operands[1]));
5090 DONE;
cffb2a26 5091 }
5092 "
5093)
b11cae9e 5094
9c08d1fa 5095
cffb2a26 5096(define_insn "*arm_movqi_insn"
5097 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5565501b 5098 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
cffb2a26 5099 "TARGET_ARM
5100 && ( register_operand (operands[0], QImode)
5101 || register_operand (operands[1], QImode))"
5565501b 5102 "@
5103 mov%?\\t%0, %1
5104 mvn%?\\t%0, #%B1
5105 ldr%?b\\t%0, %1
5106 str%?b\\t%1, %0"
a2cd141b 5107 [(set_attr "type" "*,*,load1,store1")
0d66636f 5108 (set_attr "predicable" "yes")]
cffb2a26 5109)
5110
5111(define_insn "*thumb_movqi_insn"
5112 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
215b30b3 5113 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
cffb2a26 5114 "TARGET_THUMB
5115 && ( register_operand (operands[0], QImode)
5116 || register_operand (operands[1], QImode))"
5117 "@
5118 add\\t%0, %1, #0
5119 ldrb\\t%0, %1
5120 strb\\t%1, %0
5121 mov\\t%0, %1
5122 mov\\t%0, %1
5123 mov\\t%0, %1"
5124 [(set_attr "length" "2")
a2cd141b 5125 (set_attr "type" "*,load1,store1,*,*,*")
cffb2a26 5126 (set_attr "pool_range" "*,32,*,*,*,*")]
5127)
b11cae9e 5128
87b22bf7 5129(define_expand "movsf"
5130 [(set (match_operand:SF 0 "general_operand" "")
5131 (match_operand:SF 1 "general_operand" ""))]
cffb2a26 5132 "TARGET_EITHER"
87b22bf7 5133 "
cffb2a26 5134 if (TARGET_ARM)
5135 {
5136 if (GET_CODE (operands[0]) == MEM)
5137 operands[1] = force_reg (SFmode, operands[1]);
5138 }
5139 else /* TARGET_THUMB */
5140 {
215b30b3 5141 if (!no_new_pseudos)
cffb2a26 5142 {
5143 if (GET_CODE (operands[0]) != REG)
5144 operands[1] = force_reg (SFmode, operands[1]);
5145 }
5146 }
5147 "
5148)
5149
03d440a6 5150;; Transform a floating-point move of a constant into a core register into
5151;; an SImode operation.
cffb2a26 5152(define_split
03d440a6 5153 [(set (match_operand:SF 0 "arm_general_register_operand" "")
cffb2a26 5154 (match_operand:SF 1 "immediate_operand" ""))]
5155 "TARGET_ARM
cffb2a26 5156 && reload_completed
5157 && GET_CODE (operands[1]) == CONST_DOUBLE"
5158 [(set (match_dup 2) (match_dup 3))]
5159 "
5160 operands[2] = gen_lowpart (SImode, operands[0]);
5161 operands[3] = gen_lowpart (SImode, operands[1]);
5162 if (operands[2] == 0 || operands[3] == 0)
5163 FAIL;
215b30b3 5164 "
5165)
87b22bf7 5166
cffb2a26 5167(define_insn "*arm_movsf_soft_insn"
5168 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5169 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5170 "TARGET_ARM
5171 && TARGET_SOFT_FLOAT
215b30b3 5172 && (GET_CODE (operands[0]) != MEM
5173 || register_operand (operands[1], SFmode))"
9a1112d7 5174 "@
5175 mov%?\\t%0, %1
5176 ldr%?\\t%0, %1\\t%@ float
5177 str%?\\t%1, %0\\t%@ float"
cffb2a26 5178 [(set_attr "length" "4,4,4")
0d66636f 5179 (set_attr "predicable" "yes")
a2cd141b 5180 (set_attr "type" "*,load1,store1")
cffb2a26 5181 (set_attr "pool_range" "*,4096,*")
5182 (set_attr "neg_pool_range" "*,4084,*")]
5183)
5184
5185;;; ??? This should have alternatives for constants.
5186(define_insn "*thumb_movsf_insn"
215b30b3 5187 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5188 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
cffb2a26 5189 "TARGET_THUMB
5190 && ( register_operand (operands[0], SFmode)
5191 || register_operand (operands[1], SFmode))"
5192 "@
5193 add\\t%0, %1, #0
5194 ldmia\\t%1, {%0}
5195 stmia\\t%0, {%1}
5196 ldr\\t%0, %1
5197 str\\t%1, %0
5198 mov\\t%0, %1
5199 mov\\t%0, %1"
5200 [(set_attr "length" "2")
a2cd141b 5201 (set_attr "type" "*,load1,store1,load1,store1,*,*")
cffb2a26 5202 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5203)
9a1112d7 5204
9c08d1fa 5205(define_expand "movdf"
87b22bf7 5206 [(set (match_operand:DF 0 "general_operand" "")
5207 (match_operand:DF 1 "general_operand" ""))]
cffb2a26 5208 "TARGET_EITHER"
9c08d1fa 5209 "
cffb2a26 5210 if (TARGET_ARM)
5211 {
5212 if (GET_CODE (operands[0]) == MEM)
5213 operands[1] = force_reg (DFmode, operands[1]);
5214 }
5215 else /* TARGET_THUMB */
5216 {
215b30b3 5217 if (!no_new_pseudos)
cffb2a26 5218 {
5219 if (GET_CODE (operands[0]) != REG)
5220 operands[1] = force_reg (DFmode, operands[1]);
5221 }
5222 }
5223 "
5224)
b11cae9e 5225
9c08d1fa 5226;; Reloading a df mode value stored in integer regs to memory can require a
5227;; scratch reg.
5228(define_expand "reload_outdf"
cffb2a26 5229 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
87b22bf7 5230 (match_operand:DF 1 "s_register_operand" "r")
5231 (match_operand:SI 2 "s_register_operand" "=&r")]
cffb2a26 5232 "TARGET_ARM"
87b22bf7 5233 "
215b30b3 5234 {
5235 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
f7fbdd4a 5236
215b30b3 5237 if (code == REG)
5238 operands[2] = XEXP (operands[0], 0);
5239 else if (code == POST_INC || code == PRE_DEC)
5240 {
5241 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5242 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5243 emit_insn (gen_movdi (operands[0], operands[1]));
5244 DONE;
5245 }
5246 else if (code == PRE_INC)
5247 {
5248 rtx reg = XEXP (XEXP (operands[0], 0), 0);
f7fbdd4a 5249
215b30b3 5250 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5251 operands[2] = reg;
5252 }
5253 else if (code == POST_DEC)
5254 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5255 else
5256 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5257 XEXP (XEXP (operands[0], 0), 1)));
f7fbdd4a 5258
788fcce0 5259 emit_insn (gen_rtx_SET (VOIDmode,
5260 replace_equiv_address (operands[0], operands[2]),
215b30b3 5261 operands[1]));
f7fbdd4a 5262
215b30b3 5263 if (code == POST_DEC)
5264 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5265
5266 DONE;
5267 }"
5268)
9c08d1fa 5269
9a1112d7 5270(define_insn "*movdf_soft_insn"
359a6e9f 5271 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5272 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
344495ea 5273 "TARGET_ARM && TARGET_SOFT_FLOAT
b2778788 5274 && ( register_operand (operands[0], DFmode)
5275 || register_operand (operands[1], DFmode))"
d51f92df 5276 "*
5277 switch (which_alternative)
5278 {
5279 case 0:
5280 case 1:
5281 case 2:
5282 return \"#\";
5283 default:
5284 return output_move_double (operands);
5285 }
5286 "
359a6e9f 5287 [(set_attr "length" "8,12,16,8,8")
5288 (set_attr "type" "*,*,*,load2,store2")
dd080cc9 5289 (set_attr "pool_range" "1020")
5290 (set_attr "neg_pool_range" "1008")]
cffb2a26 5291)
5292
5293;;; ??? This should have alternatives for constants.
5294;;; ??? This was originally identical to the movdi_insn pattern.
5295;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5296;;; thumb_reorg with a memory reference.
5297(define_insn "*thumb_movdf_insn"
215b30b3 5298 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5299 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
cffb2a26 5300 "TARGET_THUMB
5301 && ( register_operand (operands[0], DFmode)
5302 || register_operand (operands[1], DFmode))"
5303 "*
5304 switch (which_alternative)
5305 {
5306 default:
5307 case 0:
5308 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5309 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5310 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5311 case 1:
5312 return \"ldmia\\t%1, {%0, %H0}\";
5313 case 2:
5314 return \"stmia\\t%0, {%1, %H1}\";
5315 case 3:
5316 return thumb_load_double_from_address (operands);
5317 case 4:
1a83b3ff 5318 operands[2] = gen_rtx_MEM (SImode,
5319 plus_constant (XEXP (operands[0], 0), 4));
cffb2a26 5320 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5321 return \"\";
5322 case 5:
5323 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5324 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5325 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5326 }
5327 "
5328 [(set_attr "length" "4,2,2,6,4,4")
a2cd141b 5329 (set_attr "type" "*,load2,store2,load2,store2,*")
cffb2a26 5330 (set_attr "pool_range" "*,*,*,1020,*,*")]
5331)
755eb2b4 5332
ccd90aaa 5333(define_expand "movxf"
5334 [(set (match_operand:XF 0 "general_operand" "")
5335 (match_operand:XF 1 "general_operand" ""))]
5336 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5337 "
5338 if (GET_CODE (operands[0]) == MEM)
5339 operands[1] = force_reg (XFmode, operands[1]);
5340 "
5341)
5342
755eb2b4 5343;; Vector Moves
5344(define_expand "movv2si"
5345 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5346 (match_operand:V2SI 1 "general_operand" ""))]
5347 "TARGET_REALLY_IWMMXT"
5348{
5349})
5350
5351(define_expand "movv4hi"
5352 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5353 (match_operand:V4HI 1 "general_operand" ""))]
5354 "TARGET_REALLY_IWMMXT"
5355{
5356})
5357
5358(define_expand "movv8qi"
5359 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5360 (match_operand:V8QI 1 "general_operand" ""))]
5361 "TARGET_REALLY_IWMMXT"
5362{
5363})
b11cae9e 5364\f
b11cae9e 5365
9c08d1fa 5366;; load- and store-multiple insns
5367;; The arm can load/store any set of registers, provided that they are in
5368;; ascending order; but that is beyond GCC so stick with what it knows.
b11cae9e 5369
9c08d1fa 5370(define_expand "load_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"
9580c25f 5375{
5376 HOST_WIDE_INT offset = 0;
5377
bd5b4116 5378 /* Support only fixed point registers. */
9c08d1fa 5379 if (GET_CODE (operands[2]) != CONST_INT
5380 || INTVAL (operands[2]) > 14
5381 || INTVAL (operands[2]) < 2
5382 || GET_CODE (operands[1]) != MEM
5383 || GET_CODE (operands[0]) != REG
bd5b4116 5384 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5385 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5386 FAIL;
5387
5388 operands[3]
f082f1c4 5389 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5390 force_reg (SImode, XEXP (operands[1], 0)),
9580c25f 5391 TRUE, FALSE, operands[1], &offset);
5392})
b11cae9e 5393
9c08d1fa 5394;; Load multiple with write-back
5395
2162064c 5396(define_insn "*ldmsi_postinc4"
9c08d1fa 5397 [(match_parallel 0 "load_multiple_operation"
13e9316a 5398 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5399 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5400 (const_int 16)))
5401 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5402 (mem:SI (match_dup 2)))
a0a72ac3 5403 (set (match_operand:SI 4 "arm_hard_register_operand" "")
2162064c 5404 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5405 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5406 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5407 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5408 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5409 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5410 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
a2cd141b 5411 [(set_attr "type" "load4")
2162064c 5412 (set_attr "predicable" "yes")]
5413)
b11cae9e 5414
ccd90aaa 5415(define_insn "*ldmsi_postinc4_thumb"
5416 [(match_parallel 0 "load_multiple_operation"
5417 [(set (match_operand:SI 1 "s_register_operand" "=l")
5418 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5419 (const_int 16)))
5420 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5421 (mem:SI (match_dup 2)))
5422 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5423 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5424 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5425 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5426 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5427 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5428 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5429 "ldmia\\t%1!, {%3, %4, %5, %6}"
5430 [(set_attr "type" "load4")]
5431)
5432
2162064c 5433(define_insn "*ldmsi_postinc3"
5434 [(match_parallel 0 "load_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 12)))
5438 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5439 (mem:SI (match_dup 2)))
5440 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5441 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5442 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5443 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5444 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5445 "ldm%?ia\\t%1!, {%3, %4, %5}"
a2cd141b 5446 [(set_attr "type" "load3")
2162064c 5447 (set_attr "predicable" "yes")]
5448)
b11cae9e 5449
2162064c 5450(define_insn "*ldmsi_postinc2"
5451 [(match_parallel 0 "load_multiple_operation"
13e9316a 5452 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5453 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5454 (const_int 8)))
5455 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5456 (mem:SI (match_dup 2)))
5457 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5458 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5459 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5460 "ldm%?ia\\t%1!, {%3, %4}"
a2cd141b 5461 [(set_attr "type" "load2")
0d66636f 5462 (set_attr "predicable" "yes")]
5463)
b11cae9e 5464
9c08d1fa 5465;; Ordinary load multiple
b11cae9e 5466
2162064c 5467(define_insn "*ldmsi4"
9c08d1fa 5468 [(match_parallel 0 "load_multiple_operation"
2162064c 5469 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5470 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5471 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5472 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5473 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5474 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5475 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5476 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5477 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5478 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
a2cd141b 5479 [(set_attr "type" "load4")
2162064c 5480 (set_attr "predicable" "yes")]
5481)
9c08d1fa 5482
2162064c 5483(define_insn "*ldmsi3"
5484 [(match_parallel 0 "load_multiple_operation"
5485 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5486 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5487 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5488 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5489 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5490 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5491 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5492 "ldm%?ia\\t%1, {%2, %3, %4}"
a2cd141b 5493 [(set_attr "type" "load3")
2162064c 5494 (set_attr "predicable" "yes")]
5495)
9c08d1fa 5496
2162064c 5497(define_insn "*ldmsi2"
5498 [(match_parallel 0 "load_multiple_operation"
5499 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5500 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5501 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5502 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5503 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5504 "ldm%?ia\\t%1, {%2, %3}"
a2cd141b 5505 [(set_attr "type" "load2")
0d66636f 5506 (set_attr "predicable" "yes")]
5507)
9c08d1fa 5508
5509(define_expand "store_multiple"
5510 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5511 (match_operand:SI 1 "" ""))
5512 (use (match_operand:SI 2 "" ""))])]
cffb2a26 5513 "TARGET_ARM"
9580c25f 5514{
5515 HOST_WIDE_INT offset = 0;
5516
674a8f0b 5517 /* Support only fixed point registers. */
9c08d1fa 5518 if (GET_CODE (operands[2]) != CONST_INT
5519 || INTVAL (operands[2]) > 14
5520 || INTVAL (operands[2]) < 2
5521 || GET_CODE (operands[1]) != REG
5522 || GET_CODE (operands[0]) != MEM
bd5b4116 5523 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5524 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
9c08d1fa 5525 FAIL;
5526
5527 operands[3]
f082f1c4 5528 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5529 force_reg (SImode, XEXP (operands[0], 0)),
9580c25f 5530 TRUE, FALSE, operands[0], &offset);
5531})
b11cae9e 5532
9c08d1fa 5533;; Store multiple with write-back
5534
2162064c 5535(define_insn "*stmsi_postinc4"
9c08d1fa 5536 [(match_parallel 0 "store_multiple_operation"
13e9316a 5537 [(set (match_operand:SI 1 "s_register_operand" "=r")
a0a72ac3 5538 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
2162064c 5539 (const_int 16)))
a0a72ac3 5540 (set (mem:SI (match_dup 2))
2162064c 5541 (match_operand:SI 3 "arm_hard_register_operand" ""))
5542 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543 (match_operand:SI 4 "arm_hard_register_operand" ""))
5544 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5545 (match_operand:SI 5 "arm_hard_register_operand" ""))
5546 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5547 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5548 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5549 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5550 [(set_attr "predicable" "yes")
5551 (set_attr "type" "store4")]
5552)
b11cae9e 5553
ccd90aaa 5554(define_insn "*stmsi_postinc4_thumb"
5555 [(match_parallel 0 "store_multiple_operation"
5556 [(set (match_operand:SI 1 "s_register_operand" "=l")
5557 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5558 (const_int 16)))
5559 (set (mem:SI (match_dup 2))
5560 (match_operand:SI 3 "arm_hard_register_operand" ""))
5561 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5562 (match_operand:SI 4 "arm_hard_register_operand" ""))
5563 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5564 (match_operand:SI 5 "arm_hard_register_operand" ""))
5565 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5566 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5567 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5568 "stmia\\t%1!, {%3, %4, %5, %6}"
5569 [(set_attr "type" "store4")]
5570)
5571
2162064c 5572(define_insn "*stmsi_postinc3"
5573 [(match_parallel 0 "store_multiple_operation"
13e9316a 5574 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5575 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5576 (const_int 12)))
5577 (set (mem:SI (match_dup 2))
5578 (match_operand:SI 3 "arm_hard_register_operand" ""))
5579 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5580 (match_operand:SI 4 "arm_hard_register_operand" ""))
5581 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5582 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5583 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5584 "stm%?ia\\t%1!, {%3, %4, %5}"
5585 [(set_attr "predicable" "yes")
5586 (set_attr "type" "store3")]
5587)
9c08d1fa 5588
2162064c 5589(define_insn "*stmsi_postinc2"
5590 [(match_parallel 0 "store_multiple_operation"
13e9316a 5591 [(set (match_operand:SI 1 "s_register_operand" "=r")
2162064c 5592 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5593 (const_int 8)))
5594 (set (mem:SI (match_dup 2))
5595 (match_operand:SI 3 "arm_hard_register_operand" ""))
5596 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5597 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5598 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5599 "stm%?ia\\t%1!, {%3, %4}"
0d66636f 5600 [(set_attr "predicable" "yes")
2162064c 5601 (set_attr "type" "store2")]
cffb2a26 5602)
9c08d1fa 5603
5604;; Ordinary store multiple
5605
2162064c 5606(define_insn "*stmsi4"
9c08d1fa 5607 [(match_parallel 0 "store_multiple_operation"
a0a72ac3 5608 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
2162064c 5609 (match_operand:SI 2 "arm_hard_register_operand" ""))
5610 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5611 (match_operand:SI 3 "arm_hard_register_operand" ""))
5612 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5613 (match_operand:SI 4 "arm_hard_register_operand" ""))
5614 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5615 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5616 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5617 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5618 [(set_attr "predicable" "yes")
5619 (set_attr "type" "store4")]
5620)
9c08d1fa 5621
2162064c 5622(define_insn "*stmsi3"
5623 [(match_parallel 0 "store_multiple_operation"
5624 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5625 (match_operand:SI 2 "arm_hard_register_operand" ""))
5626 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5627 (match_operand:SI 3 "arm_hard_register_operand" ""))
5628 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5629 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5630 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5631 "stm%?ia\\t%1, {%2, %3, %4}"
5632 [(set_attr "predicable" "yes")
5633 (set_attr "type" "store3")]
5634)
9c08d1fa 5635
2162064c 5636(define_insn "*stmsi2"
5637 [(match_parallel 0 "store_multiple_operation"
5638 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5639 (match_operand:SI 2 "arm_hard_register_operand" ""))
5640 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5641 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5642 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5643 "stm%?ia\\t%1, {%2, %3}"
0d66636f 5644 [(set_attr "predicable" "yes")
2162064c 5645 (set_attr "type" "store2")]
cffb2a26 5646)
9c08d1fa 5647
5648;; Move a block of memory if it is word aligned and MORE than 2 words long.
5649;; We could let this apply for blocks of less than this, but it clobbers so
5650;; many registers that there is then probably a better way.
5651
008c057d 5652(define_expand "movmemqi"
34191dd1 5653 [(match_operand:BLK 0 "general_operand" "")
5654 (match_operand:BLK 1 "general_operand" "")
5655 (match_operand:SI 2 "const_int_operand" "")
5656 (match_operand:SI 3 "const_int_operand" "")]
cffb2a26 5657 "TARGET_EITHER"
9c08d1fa 5658 "
cffb2a26 5659 if (TARGET_ARM)
5660 {
008c057d 5661 if (arm_gen_movmemqi (operands))
cffb2a26 5662 DONE;
5663 FAIL;
5664 }
5665 else /* TARGET_THUMB */
5666 {
5667 if ( INTVAL (operands[3]) != 4
5668 || INTVAL (operands[2]) > 48)
5669 FAIL;
5670
008c057d 5671 thumb_expand_movmemqi (operands);
cffb2a26 5672 DONE;
5673 }
5674 "
5675)
5676
2162064c 5677;; Thumb block-move insns
cffb2a26 5678
5679(define_insn "movmem12b"
960f3acf 5680 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5681 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5682 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5683 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5684 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5685 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5686 (set (match_operand:SI 0 "register_operand" "=l")
5687 (plus:SI (match_dup 2) (const_int 12)))
5688 (set (match_operand:SI 1 "register_operand" "=l")
5689 (plus:SI (match_dup 3) (const_int 12)))
5690 (clobber (match_scratch:SI 4 "=&l"))
5691 (clobber (match_scratch:SI 5 "=&l"))
5692 (clobber (match_scratch:SI 6 "=&l"))]
cffb2a26 5693 "TARGET_THUMB"
5694 "* return thumb_output_move_mem_multiple (3, operands);"
5695 [(set_attr "length" "4")
215b30b3 5696 ; This isn't entirely accurate... It loads as well, but in terms of
5697 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5698 (set_attr "type" "store3")]
5699)
5700
5701(define_insn "movmem8b"
960f3acf 5702 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5703 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5704 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5705 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5706 (set (match_operand:SI 0 "register_operand" "=l")
5707 (plus:SI (match_dup 2) (const_int 8)))
5708 (set (match_operand:SI 1 "register_operand" "=l")
5709 (plus:SI (match_dup 3) (const_int 8)))
5710 (clobber (match_scratch:SI 4 "=&l"))
5711 (clobber (match_scratch:SI 5 "=&l"))]
cffb2a26 5712 "TARGET_THUMB"
5713 "* return thumb_output_move_mem_multiple (2, operands);"
5714 [(set_attr "length" "4")
215b30b3 5715 ; This isn't entirely accurate... It loads as well, but in terms of
5716 ; scheduling the following insn it is better to consider it as a store
cffb2a26 5717 (set_attr "type" "store2")]
5718)
5719
9c08d1fa 5720\f
b11cae9e 5721
341940e8 5722;; Compare & branch insns
8d232dc7 5723;; The range calculations are based as follows:
341940e8 5724;; For forward branches, the address calculation returns the address of
5725;; the next instruction. This is 2 beyond the branch instruction.
5726;; For backward branches, the address calculation returns the address of
5727;; the first instruction in this pattern (cmp). This is 2 before the branch
5728;; instruction for the shortest sequence, and 4 before the branch instruction
5729;; if we have to jump around an unconditional branch.
5730;; To the basic branch range the PC offset must be added (this is +4).
5731;; So for forward branches we have
5732;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5733;; And for backward branches we have
5734;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5735;;
5736;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5737;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
cffb2a26 5738
aeac46d4 5739(define_expand "cbranchsi4"
5740 [(set (pc) (if_then_else
5741 (match_operator 0 "arm_comparison_operator"
5742 [(match_operand:SI 1 "s_register_operand" "")
5743 (match_operand:SI 2 "nonmemory_operand" "")])
5744 (label_ref (match_operand 3 "" ""))
5745 (pc)))]
5746 "TARGET_THUMB"
5747 "
5748 if (thumb_cmpneg_operand (operands[2], SImode))
5749 {
5750 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5751 operands[3], operands[0]));
5752 DONE;
5753 }
5754 if (!thumb_cmp_operand (operands[2], SImode))
5755 operands[2] = force_reg (SImode, operands[2]);
5756 ")
5757
5758(define_insn "*cbranchsi4_insn"
5759 [(set (pc) (if_then_else
5760 (match_operator 0 "arm_comparison_operator"
5761 [(match_operand:SI 1 "s_register_operand" "l,*h")
5762 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5763 (label_ref (match_operand 3 "" ""))
5764 (pc)))]
cffb2a26 5765 "TARGET_THUMB"
5766 "*
5767 output_asm_insn (\"cmp\\t%1, %2\", operands);
aeac46d4 5768
cffb2a26 5769 switch (get_attr_length (insn))
5770 {
5771 case 4: return \"b%d0\\t%l3\";
5772 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5773 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5774 }
5775 "
5776 [(set (attr "far_jump")
5777 (if_then_else
5778 (eq_attr "length" "8")
5779 (const_string "yes")
5780 (const_string "no")))
5781 (set (attr "length")
5782 (if_then_else
5783 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5784 (le (minus (match_dup 3) (pc)) (const_int 256)))
5785 (const_int 4)
5786 (if_then_else
5787 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
341940e8 5788 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5789 (const_int 6)
5790 (const_int 8))))]
5791)
5792
aeac46d4 5793(define_insn "cbranchsi4_scratch"
5794 [(set (pc) (if_then_else
5795 (match_operator 4 "arm_comparison_operator"
5796 [(match_operand:SI 1 "s_register_operand" "l,0")
5797 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5798 (label_ref (match_operand 3 "" ""))
5799 (pc)))
5800 (clobber (match_scratch:SI 0 "=l,l"))]
5801 "TARGET_THUMB"
5802 "*
5803 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5804
5805 switch (get_attr_length (insn))
5806 {
5807 case 4: return \"b%d4\\t%l3\";
5808 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5809 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5810 }
5811 "
5812 [(set (attr "far_jump")
5813 (if_then_else
5814 (eq_attr "length" "8")
5815 (const_string "yes")
5816 (const_string "no")))
5817 (set (attr "length")
5818 (if_then_else
5819 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5820 (le (minus (match_dup 3) (pc)) (const_int 256)))
5821 (const_int 4)
5822 (if_then_else
5823 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5824 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5825 (const_int 6)
5826 (const_int 8))))]
5827)
5828(define_insn "*movsi_cbranchsi4"
5829 [(set (pc)
5830 (if_then_else
5831 (match_operator 3 "arm_comparison_operator"
5832 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5833 (const_int 0)])
5834 (label_ref (match_operand 2 "" ""))
5835 (pc)))
5836 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5837 (match_dup 1))]
5838 "TARGET_THUMB"
5839 "*{
5840 if (which_alternative == 0)
5841 output_asm_insn (\"cmp\t%0, #0\", operands);
5842 else if (which_alternative == 1)
5843 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5844 else
5845 {
5846 output_asm_insn (\"cmp\t%1, #0\", operands);
5847 if (which_alternative == 2)
5848 output_asm_insn (\"mov\t%0, %1\", operands);
5849 else
5850 output_asm_insn (\"str\t%1, %0\", operands);
5851 }
5852 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5853 {
5854 case 4: return \"b%d3\\t%l2\";
5855 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5856 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5857 }
5858 }"
5859 [(set (attr "far_jump")
5860 (if_then_else
5861 (ior (and (gt (symbol_ref ("which_alternative"))
5862 (const_int 1))
5863 (eq_attr "length" "8"))
5864 (eq_attr "length" "10"))
5865 (const_string "yes")
5866 (const_string "no")))
5867 (set (attr "length")
5868 (if_then_else
5869 (le (symbol_ref ("which_alternative"))
5870 (const_int 1))
5871 (if_then_else
5872 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5873 (le (minus (match_dup 2) (pc)) (const_int 256)))
5874 (const_int 4)
5875 (if_then_else
5876 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5877 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5878 (const_int 6)
5879 (const_int 8)))
5880 (if_then_else
5881 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5882 (le (minus (match_dup 2) (pc)) (const_int 256)))
5883 (const_int 6)
5884 (if_then_else
5885 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5886 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5887 (const_int 8)
5888 (const_int 10)))))]
5889)
5890
cffb2a26 5891(define_insn "*negated_cbranchsi4"
5892 [(set (pc)
5893 (if_then_else
aed179ae 5894 (match_operator 0 "equality_operator"
aeac46d4 5895 [(match_operand:SI 1 "s_register_operand" "l")
5896 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5897 (label_ref (match_operand 3 "" ""))
215b30b3 5898 (pc)))]
cffb2a26 5899 "TARGET_THUMB"
5900 "*
5901 output_asm_insn (\"cmn\\t%1, %2\", operands);
5902 switch (get_attr_length (insn))
5903 {
5904 case 4: return \"b%d0\\t%l3\";
5905 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5906 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5907 }
5908 "
5909 [(set (attr "far_jump")
5910 (if_then_else
5911 (eq_attr "length" "8")
5912 (const_string "yes")
5913 (const_string "no")))
5914 (set (attr "length")
5915 (if_then_else
5916 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
341940e8 5917 (le (minus (match_dup 3) (pc)) (const_int 256)))
cffb2a26 5918 (const_int 4)
5919 (if_then_else
341940e8 5920 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5921 (le (minus (match_dup 3) (pc)) (const_int 2048)))
cffb2a26 5922 (const_int 6)
5923 (const_int 8))))]
5924)
5925
58d6528b 5926(define_insn "*tbit_cbranch"
5927 [(set (pc)
5928 (if_then_else
5929 (match_operator 0 "equality_operator"
5930 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5931 (const_int 1)
5932 (match_operand:SI 2 "const_int_operand" "i"))
5933 (const_int 0)])
5934 (label_ref (match_operand 3 "" ""))
5935 (pc)))
5936 (clobber (match_scratch:SI 4 "=l"))]
5937 "TARGET_THUMB"
5938 "*
5939 {
5940 rtx op[3];
5941 op[0] = operands[4];
5942 op[1] = operands[1];
5943 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5944
5945 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5946 switch (get_attr_length (insn))
5947 {
5948 case 4: return \"b%d0\\t%l3\";
5949 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5950 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5951 }
5952 }"
5953 [(set (attr "far_jump")
5954 (if_then_else
5955 (eq_attr "length" "8")
5956 (const_string "yes")
5957 (const_string "no")))
5958 (set (attr "length")
5959 (if_then_else
5960 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5961 (le (minus (match_dup 3) (pc)) (const_int 256)))
5962 (const_int 4)
5963 (if_then_else
5964 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5965 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5966 (const_int 6)
5967 (const_int 8))))]
5968)
5969
aeac46d4 5970(define_insn "*tstsi3_cbranch"
58d6528b 5971 [(set (pc)
5972 (if_then_else
aeac46d4 5973 (match_operator 3 "equality_operator"
5974 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5975 (match_operand:SI 1 "s_register_operand" "l"))
58d6528b 5976 (const_int 0)])
aeac46d4 5977 (label_ref (match_operand 2 "" ""))
5978 (pc)))]
58d6528b 5979 "TARGET_THUMB"
5980 "*
5981 {
aeac46d4 5982 output_asm_insn (\"tst\\t%0, %1\", operands);
58d6528b 5983 switch (get_attr_length (insn))
5984 {
aeac46d4 5985 case 4: return \"b%d3\\t%l2\";
5986 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5987 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
58d6528b 5988 }
5989 }"
5990 [(set (attr "far_jump")
5991 (if_then_else
5992 (eq_attr "length" "8")
5993 (const_string "yes")
5994 (const_string "no")))
5995 (set (attr "length")
5996 (if_then_else
aeac46d4 5997 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5998 (le (minus (match_dup 2) (pc)) (const_int 256)))
58d6528b 5999 (const_int 4)
6000 (if_then_else
aeac46d4 6001 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6002 (le (minus (match_dup 2) (pc)) (const_int 2048)))
58d6528b 6003 (const_int 6)
6004 (const_int 8))))]
6005)
6006
6007(define_insn "*andsi3_cbranch"
6008 [(set (pc)
6009 (if_then_else
6010 (match_operator 5 "equality_operator"
6011 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6012 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6013 (const_int 0)])
6014 (label_ref (match_operand 4 "" ""))
6015 (pc)))
aeac46d4 6016 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6017 (and:SI (match_dup 2) (match_dup 3)))
6018 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6019 "TARGET_THUMB"
6020 "*
6021 {
6022 if (which_alternative == 0)
6023 output_asm_insn (\"and\\t%0, %3\", operands);
6024 else if (which_alternative == 1)
6025 {
6026 output_asm_insn (\"and\\t%1, %3\", operands);
6027 output_asm_insn (\"mov\\t%0, %1\", operands);
6028 }
6029 else
6030 {
6031 output_asm_insn (\"and\\t%1, %3\", operands);
6032 output_asm_insn (\"str\\t%1, %0\", operands);
6033 }
6034
6035 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6036 {
6037 case 4: return \"b%d5\\t%l4\";
6038 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6039 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6040 }
6041 }"
6042 [(set (attr "far_jump")
6043 (if_then_else
6044 (ior (and (eq (symbol_ref ("which_alternative"))
6045 (const_int 0))
6046 (eq_attr "length" "8"))
6047 (eq_attr "length" "10"))
6048 (const_string "yes")
6049 (const_string "no")))
6050 (set (attr "length")
6051 (if_then_else
6052 (eq (symbol_ref ("which_alternative"))
6053 (const_int 0))
6054 (if_then_else
6055 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6056 (le (minus (match_dup 4) (pc)) (const_int 256)))
6057 (const_int 4)
6058 (if_then_else
6059 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6060 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6061 (const_int 6)
6062 (const_int 8)))
6063 (if_then_else
6064 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6065 (le (minus (match_dup 4) (pc)) (const_int 256)))
6066 (const_int 6)
6067 (if_then_else
6068 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6069 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6070 (const_int 8)
6071 (const_int 10)))))]
6072)
6073
6074(define_insn "*orrsi3_cbranch_scratch"
6075 [(set (pc)
6076 (if_then_else
6077 (match_operator 4 "equality_operator"
6078 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6079 (match_operand:SI 2 "s_register_operand" "l"))
6080 (const_int 0)])
6081 (label_ref (match_operand 3 "" ""))
6082 (pc)))
6083 (clobber (match_scratch:SI 0 "=l"))]
6084 "TARGET_THUMB"
6085 "*
6086 {
6087 output_asm_insn (\"orr\\t%0, %2\", operands);
6088 switch (get_attr_length (insn))
6089 {
6090 case 4: return \"b%d4\\t%l3\";
6091 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6092 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6093 }
6094 }"
6095 [(set (attr "far_jump")
6096 (if_then_else
6097 (eq_attr "length" "8")
6098 (const_string "yes")
6099 (const_string "no")))
6100 (set (attr "length")
6101 (if_then_else
6102 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6103 (le (minus (match_dup 3) (pc)) (const_int 256)))
6104 (const_int 4)
6105 (if_then_else
6106 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6107 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6108 (const_int 6)
6109 (const_int 8))))]
6110)
6111
6112(define_insn "*orrsi3_cbranch"
6113 [(set (pc)
6114 (if_then_else
6115 (match_operator 5 "equality_operator"
6116 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6117 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6118 (const_int 0)])
6119 (label_ref (match_operand 4 "" ""))
6120 (pc)))
aeac46d4 6121 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6122 (ior:SI (match_dup 2) (match_dup 3)))
6123 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6124 "TARGET_THUMB"
6125 "*
6126 {
6127 if (which_alternative == 0)
6128 output_asm_insn (\"orr\\t%0, %3\", operands);
6129 else if (which_alternative == 1)
6130 {
6131 output_asm_insn (\"orr\\t%1, %3\", operands);
6132 output_asm_insn (\"mov\\t%0, %1\", operands);
6133 }
6134 else
6135 {
6136 output_asm_insn (\"orr\\t%1, %3\", operands);
6137 output_asm_insn (\"str\\t%1, %0\", operands);
6138 }
6139
6140 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6141 {
6142 case 4: return \"b%d5\\t%l4\";
6143 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6144 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6145 }
6146 }"
6147 [(set (attr "far_jump")
6148 (if_then_else
6149 (ior (and (eq (symbol_ref ("which_alternative"))
6150 (const_int 0))
6151 (eq_attr "length" "8"))
6152 (eq_attr "length" "10"))
6153 (const_string "yes")
6154 (const_string "no")))
6155 (set (attr "length")
6156 (if_then_else
6157 (eq (symbol_ref ("which_alternative"))
6158 (const_int 0))
6159 (if_then_else
6160 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6161 (le (minus (match_dup 4) (pc)) (const_int 256)))
6162 (const_int 4)
6163 (if_then_else
6164 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6165 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6166 (const_int 6)
6167 (const_int 8)))
6168 (if_then_else
6169 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6170 (le (minus (match_dup 4) (pc)) (const_int 256)))
6171 (const_int 6)
6172 (if_then_else
6173 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6174 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6175 (const_int 8)
6176 (const_int 10)))))]
6177)
6178
6179(define_insn "*xorsi3_cbranch_scratch"
6180 [(set (pc)
6181 (if_then_else
6182 (match_operator 4 "equality_operator"
6183 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6184 (match_operand:SI 2 "s_register_operand" "l"))
6185 (const_int 0)])
6186 (label_ref (match_operand 3 "" ""))
6187 (pc)))
6188 (clobber (match_scratch:SI 0 "=l"))]
6189 "TARGET_THUMB"
6190 "*
6191 {
6192 output_asm_insn (\"eor\\t%0, %2\", operands);
6193 switch (get_attr_length (insn))
6194 {
6195 case 4: return \"b%d4\\t%l3\";
6196 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6197 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6198 }
6199 }"
6200 [(set (attr "far_jump")
6201 (if_then_else
6202 (eq_attr "length" "8")
6203 (const_string "yes")
6204 (const_string "no")))
6205 (set (attr "length")
6206 (if_then_else
6207 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6208 (le (minus (match_dup 3) (pc)) (const_int 256)))
6209 (const_int 4)
6210 (if_then_else
6211 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6212 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6213 (const_int 6)
6214 (const_int 8))))]
6215)
6216
6217(define_insn "*xorsi3_cbranch"
6218 [(set (pc)
6219 (if_then_else
6220 (match_operator 5 "equality_operator"
6221 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6222 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6223 (const_int 0)])
6224 (label_ref (match_operand 4 "" ""))
6225 (pc)))
aeac46d4 6226 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6227 (xor:SI (match_dup 2) (match_dup 3)))
6228 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6229 "TARGET_THUMB"
6230 "*
6231 {
6232 if (which_alternative == 0)
6233 output_asm_insn (\"eor\\t%0, %3\", operands);
6234 else if (which_alternative == 1)
6235 {
6236 output_asm_insn (\"eor\\t%1, %3\", operands);
6237 output_asm_insn (\"mov\\t%0, %1\", operands);
6238 }
6239 else
6240 {
6241 output_asm_insn (\"eor\\t%1, %3\", operands);
6242 output_asm_insn (\"str\\t%1, %0\", operands);
6243 }
6244
6245 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6246 {
6247 case 4: return \"b%d5\\t%l4\";
6248 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6249 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6250 }
6251 }"
6252 [(set (attr "far_jump")
6253 (if_then_else
6254 (ior (and (eq (symbol_ref ("which_alternative"))
6255 (const_int 0))
6256 (eq_attr "length" "8"))
6257 (eq_attr "length" "10"))
6258 (const_string "yes")
6259 (const_string "no")))
6260 (set (attr "length")
6261 (if_then_else
6262 (eq (symbol_ref ("which_alternative"))
6263 (const_int 0))
6264 (if_then_else
6265 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6266 (le (minus (match_dup 4) (pc)) (const_int 256)))
6267 (const_int 4)
6268 (if_then_else
6269 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6270 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6271 (const_int 6)
6272 (const_int 8)))
6273 (if_then_else
6274 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6275 (le (minus (match_dup 4) (pc)) (const_int 256)))
6276 (const_int 6)
6277 (if_then_else
6278 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6279 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6280 (const_int 8)
6281 (const_int 10)))))]
6282)
6283
aeac46d4 6284(define_insn "*bicsi3_cbranch_scratch"
6285 [(set (pc)
6286 (if_then_else
6287 (match_operator 4 "equality_operator"
6288 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6289 (match_operand:SI 1 "s_register_operand" "0"))
6290 (const_int 0)])
6291 (label_ref (match_operand 3 "" ""))
6292 (pc)))
6293 (clobber (match_scratch:SI 0 "=l"))]
6294 "TARGET_THUMB"
6295 "*
6296 {
6297 output_asm_insn (\"bic\\t%0, %2\", operands);
6298 switch (get_attr_length (insn))
6299 {
6300 case 4: return \"b%d4\\t%l3\";
6301 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6302 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6303 }
6304 }"
6305 [(set (attr "far_jump")
6306 (if_then_else
6307 (eq_attr "length" "8")
6308 (const_string "yes")
6309 (const_string "no")))
6310 (set (attr "length")
6311 (if_then_else
6312 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6313 (le (minus (match_dup 3) (pc)) (const_int 256)))
6314 (const_int 4)
6315 (if_then_else
6316 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6317 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6318 (const_int 6)
6319 (const_int 8))))]
6320)
6321
6322(define_insn "*bicsi3_cbranch"
6323 [(set (pc)
6324 (if_then_else
6325 (match_operator 5 "equality_operator"
01145ae6 6326 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6327 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
aeac46d4 6328 (const_int 0)])
6329 (label_ref (match_operand 4 "" ""))
6330 (pc)))
01145ae6 6331 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
aeac46d4 6332 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
01145ae6 6333 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
aeac46d4 6334 "TARGET_THUMB"
6335 "*
6336 {
6337 if (which_alternative == 0)
6338 output_asm_insn (\"bic\\t%0, %3\", operands);
01145ae6 6339 else if (which_alternative <= 2)
aeac46d4 6340 {
6341 output_asm_insn (\"bic\\t%1, %3\", operands);
01145ae6 6342 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6343 conditions again, since we're only testing for equality. */
aeac46d4 6344 output_asm_insn (\"mov\\t%0, %1\", operands);
6345 }
6346 else
6347 {
6348 output_asm_insn (\"bic\\t%1, %3\", operands);
6349 output_asm_insn (\"str\\t%1, %0\", operands);
6350 }
6351
6352 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6353 {
6354 case 4: return \"b%d5\\t%l4\";
6355 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6356 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6357 }
6358 }"
6359 [(set (attr "far_jump")
6360 (if_then_else
6361 (ior (and (eq (symbol_ref ("which_alternative"))
6362 (const_int 0))
6363 (eq_attr "length" "8"))
6364 (eq_attr "length" "10"))
6365 (const_string "yes")
6366 (const_string "no")))
6367 (set (attr "length")
6368 (if_then_else
6369 (eq (symbol_ref ("which_alternative"))
6370 (const_int 0))
6371 (if_then_else
6372 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6373 (le (minus (match_dup 4) (pc)) (const_int 256)))
6374 (const_int 4)
6375 (if_then_else
6376 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6377 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6378 (const_int 6)
6379 (const_int 8)))
6380 (if_then_else
6381 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6382 (le (minus (match_dup 4) (pc)) (const_int 256)))
6383 (const_int 6)
6384 (if_then_else
6385 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6386 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6387 (const_int 8)
6388 (const_int 10)))))]
6389)
6390
203c488f 6391(define_insn "*cbranchne_decr1"
6392 [(set (pc)
6393 (if_then_else (match_operator 3 "equality_operator"
6394 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6395 (const_int 0)])
6396 (label_ref (match_operand 4 "" ""))
6397 (pc)))
aeac46d4 6398 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
203c488f 6399 (plus:SI (match_dup 2) (const_int -1)))
6400 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6401 "TARGET_THUMB"
6402 "*
6403 {
6404 rtx cond[2];
6405 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6406 ? GEU : LTU),
58d6528b 6407 VOIDmode, operands[2], const1_rtx);
203c488f 6408 cond[1] = operands[4];
6409
6410 if (which_alternative == 0)
6411 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6412 else if (which_alternative == 1)
6413 {
6414 /* We must provide an alternative for a hi reg because reload
6415 cannot handle output reloads on a jump instruction, but we
6416 can't subtract into that. Fortunately a mov from lo to hi
6417 does not clobber the condition codes. */
6418 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6419 output_asm_insn (\"mov\\t%0, %1\", operands);
6420 }
6421 else
6422 {
6423 /* Similarly, but the target is memory. */
6424 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6425 output_asm_insn (\"str\\t%1, %0\", operands);
6426 }
6427
6428 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6429 {
6430 case 4:
8aea555f 6431 output_asm_insn (\"b%d0\\t%l1\", cond);
203c488f 6432 return \"\";
6433 case 6:
8aea555f 6434 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6435 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6436 default:
8aea555f 6437 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
203c488f 6438 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6439 }
6440 }
6441 "
6442 [(set (attr "far_jump")
6443 (if_then_else
6444 (ior (and (eq (symbol_ref ("which_alternative"))
6445 (const_int 0))
6446 (eq_attr "length" "8"))
6447 (eq_attr "length" "10"))
6448 (const_string "yes")
6449 (const_string "no")))
6450 (set_attr_alternative "length"
6451 [
6452 ;; Alternative 0
6453 (if_then_else
6454 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6455 (le (minus (match_dup 4) (pc)) (const_int 256)))
6456 (const_int 4)
6457 (if_then_else
6458 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6459 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6460 (const_int 6)
6461 (const_int 8)))
6462 ;; Alternative 1
6463 (if_then_else
6464 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6465 (le (minus (match_dup 4) (pc)) (const_int 256)))
6466 (const_int 6)
6467 (if_then_else
6468 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6469 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6470 (const_int 8)
6471 (const_int 10)))
6472 ;; Alternative 2
6473 (if_then_else
6474 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6475 (le (minus (match_dup 4) (pc)) (const_int 256)))
6476 (const_int 6)
6477 (if_then_else
6478 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6479 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6480 (const_int 8)
6481 (const_int 10)))
6482 ;; Alternative 3
6483 (if_then_else
6484 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6485 (le (minus (match_dup 4) (pc)) (const_int 256)))
6486 (const_int 6)
6487 (if_then_else
6488 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6489 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6490 (const_int 8)
6491 (const_int 10)))])]
6492)
cffb2a26 6493
58d6528b 6494(define_insn "*addsi3_cbranch"
6495 [(set (pc)
6496 (if_then_else
6497 (match_operator 4 "comparison_operator"
6498 [(plus:SI
6499 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6500 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6501 (const_int 0)])
6502 (label_ref (match_operand 5 "" ""))
6503 (pc)))
aeac46d4 6504 (set
6505 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6506 (plus:SI (match_dup 2) (match_dup 3)))
58d6528b 6507 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6508 "TARGET_THUMB
6509 && (GET_CODE (operands[4]) == EQ
6510 || GET_CODE (operands[4]) == NE
6511 || GET_CODE (operands[4]) == GE
6512 || GET_CODE (operands[4]) == LT)"
6513 "*
6514 {
6515 rtx cond[3];
6516
6517
6518 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6519 cond[1] = operands[2];
6520 cond[2] = operands[3];
6521
6522 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6523 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6524 else
6525 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6526
6527 if (which_alternative >= 3
6528 && which_alternative < 4)
6529 output_asm_insn (\"mov\\t%0, %1\", operands);
6530 else if (which_alternative >= 4)
6531 output_asm_insn (\"str\\t%1, %0\", operands);
6532
6533 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6534 {
6535 case 4:
6536 return \"b%d4\\t%l5\";
6537 case 6:
6538 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6539 default:
6540 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6541 }
6542 }
6543 "
6544 [(set (attr "far_jump")
6545 (if_then_else
6546 (ior (and (lt (symbol_ref ("which_alternative"))
6547 (const_int 3))
6548 (eq_attr "length" "8"))
6549 (eq_attr "length" "10"))
6550 (const_string "yes")
6551 (const_string "no")))
6552 (set (attr "length")
6553 (if_then_else
6554 (lt (symbol_ref ("which_alternative"))
6555 (const_int 3))
6556 (if_then_else
6557 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6558 (le (minus (match_dup 5) (pc)) (const_int 256)))
6559 (const_int 4)
6560 (if_then_else
6561 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6562 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6563 (const_int 6)
6564 (const_int 8)))
6565 (if_then_else
6566 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6567 (le (minus (match_dup 5) (pc)) (const_int 256)))
6568 (const_int 6)
6569 (if_then_else
6570 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6571 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6572 (const_int 8)
6573 (const_int 10)))))]
6574)
6575
6576(define_insn "*addsi3_cbranch_scratch"
6577 [(set (pc)
6578 (if_then_else
6579 (match_operator 3 "comparison_operator"
6580 [(plus:SI
6581 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
3a445a04 6582 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
58d6528b 6583 (const_int 0)])
6584 (label_ref (match_operand 4 "" ""))
6585 (pc)))
6586 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6587 "TARGET_THUMB
6588 && (GET_CODE (operands[3]) == EQ
6589 || GET_CODE (operands[3]) == NE
6590 || GET_CODE (operands[3]) == GE
6591 || GET_CODE (operands[3]) == LT)"
6592 "*
6593 {
6594 switch (which_alternative)
6595 {
6596 case 0:
6597 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6598 break;
6599 case 1:
6600 output_asm_insn (\"cmn\t%1, %2\", operands);
6601 break;
0f5e9701 6602 case 2:
3a445a04 6603 if (INTVAL (operands[2]) < 0)
6604 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6605 else
6606 output_asm_insn (\"add\t%0, %1, %2\", operands);
58d6528b 6607 break;
0f5e9701 6608 case 3:
3a445a04 6609 if (INTVAL (operands[2]) < 0)
6610 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6611 else
6612 output_asm_insn (\"add\t%0, %0, %2\", operands);
58d6528b 6613 break;
6614 }
6615
6616 switch (get_attr_length (insn))
6617 {
6618 case 4:
6619 return \"b%d3\\t%l4\";
6620 case 6:
6621 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6622 default:
6623 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6624 }
6625 }
6626 "
6627 [(set (attr "far_jump")
6628 (if_then_else
6629 (eq_attr "length" "8")
6630 (const_string "yes")
6631 (const_string "no")))
6632 (set (attr "length")
6633 (if_then_else
6634 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6635 (le (minus (match_dup 4) (pc)) (const_int 256)))
6636 (const_int 4)
6637 (if_then_else
6638 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6639 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6640 (const_int 6)
6641 (const_int 8))))]
6642)
6643
6644(define_insn "*subsi3_cbranch"
6645 [(set (pc)
6646 (if_then_else
6647 (match_operator 4 "comparison_operator"
6648 [(minus:SI
6649 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6650 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6651 (const_int 0)])
6652 (label_ref (match_operand 5 "" ""))
6653 (pc)))
aeac46d4 6654 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
58d6528b 6655 (minus:SI (match_dup 2) (match_dup 3)))
6656 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6657 "TARGET_THUMB
6658 && (GET_CODE (operands[4]) == EQ
6659 || GET_CODE (operands[4]) == NE
6660 || GET_CODE (operands[4]) == GE
6661 || GET_CODE (operands[4]) == LT)"
6662 "*
6663 {
6664 if (which_alternative == 0)
6665 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6666 else if (which_alternative == 1)
6667 {
6668 /* We must provide an alternative for a hi reg because reload
6669 cannot handle output reloads on a jump instruction, but we
6670 can't subtract into that. Fortunately a mov from lo to hi
6671 does not clobber the condition codes. */
6672 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6673 output_asm_insn (\"mov\\t%0, %1\", operands);
6674 }
6675 else
6676 {
6677 /* Similarly, but the target is memory. */
6678 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6679 output_asm_insn (\"str\\t%1, %0\", operands);
6680 }
6681
6682 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6683 {
6684 case 4:
6685 return \"b%d4\\t%l5\";
6686 case 6:
6687 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6688 default:
6689 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6690 }
6691 }
6692 "
6693 [(set (attr "far_jump")
6694 (if_then_else
6695 (ior (and (eq (symbol_ref ("which_alternative"))
6696 (const_int 0))
6697 (eq_attr "length" "8"))
6698 (eq_attr "length" "10"))
6699 (const_string "yes")
6700 (const_string "no")))
6701 (set (attr "length")
6702 (if_then_else
6703 (eq (symbol_ref ("which_alternative"))
6704 (const_int 0))
6705 (if_then_else
6706 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6707 (le (minus (match_dup 5) (pc)) (const_int 256)))
6708 (const_int 4)
6709 (if_then_else
6710 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6711 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6712 (const_int 6)
6713 (const_int 8)))
6714 (if_then_else
6715 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6716 (le (minus (match_dup 5) (pc)) (const_int 256)))
6717 (const_int 6)
6718 (if_then_else
6719 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6720 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6721 (const_int 8)
6722 (const_int 10)))))]
6723)
6724
6725(define_insn "*subsi3_cbranch_scratch"
6726 [(set (pc)
6727 (if_then_else
6728 (match_operator 0 "arm_comparison_operator"
6729 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6730 (match_operand:SI 2 "nonmemory_operand" "l"))
6731 (const_int 0)])
6732 (label_ref (match_operand 3 "" ""))
6733 (pc)))]
6734 "TARGET_THUMB
6735 && (GET_CODE (operands[0]) == EQ
6736 || GET_CODE (operands[0]) == NE
6737 || GET_CODE (operands[0]) == GE
6738 || GET_CODE (operands[0]) == LT)"
6739 "*
6740 output_asm_insn (\"cmp\\t%1, %2\", operands);
6741 switch (get_attr_length (insn))
6742 {
6743 case 4: return \"b%d0\\t%l3\";
6744 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6745 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6746 }
6747 "
6748 [(set (attr "far_jump")
6749 (if_then_else
6750 (eq_attr "length" "8")
6751 (const_string "yes")
6752 (const_string "no")))
6753 (set (attr "length")
6754 (if_then_else
6755 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6756 (le (minus (match_dup 3) (pc)) (const_int 256)))
6757 (const_int 4)
6758 (if_then_else
6759 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6760 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6761 (const_int 6)
6762 (const_int 8))))]
6763)
6764
9c08d1fa 6765;; Comparison and test insns
6766
6767(define_expand "cmpsi"
aea4c774 6768 [(match_operand:SI 0 "s_register_operand" "")
6769 (match_operand:SI 1 "arm_add_operand" "")]
cffb2a26 6770 "TARGET_ARM"
6771 "{
6772 arm_compare_op0 = operands[0];
6773 arm_compare_op1 = operands[1];
6774 DONE;
6775 }"
6776)
b11cae9e 6777
9c08d1fa 6778(define_expand "cmpsf"
aea4c774 6779 [(match_operand:SF 0 "s_register_operand" "")
a2cd141b 6780 (match_operand:SF 1 "arm_float_compare_operand" "")]
6781 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6782 "
9c08d1fa 6783 arm_compare_op0 = operands[0];
6784 arm_compare_op1 = operands[1];
9c08d1fa 6785 DONE;
215b30b3 6786 "
6787)
b11cae9e 6788
9c08d1fa 6789(define_expand "cmpdf"
aea4c774 6790 [(match_operand:DF 0 "s_register_operand" "")
a2cd141b 6791 (match_operand:DF 1 "arm_float_compare_operand" "")]
6792 "TARGET_ARM && TARGET_HARD_FLOAT"
9c08d1fa 6793 "
9c08d1fa 6794 arm_compare_op0 = operands[0];
6795 arm_compare_op1 = operands[1];
9c08d1fa 6796 DONE;
215b30b3 6797 "
6798)
b11cae9e 6799
cffb2a26 6800(define_insn "*arm_cmpsi_insn"
bd5b4116 6801 [(set (reg:CC CC_REGNUM)
aea4c774 6802 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
cffb2a26 6803 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6804 "TARGET_ARM"
5565501b 6805 "@
aea4c774 6806 cmp%?\\t%0, %1
6807 cmn%?\\t%0, #%n1"
cffb2a26 6808 [(set_attr "conds" "set")]
6809)
b11cae9e 6810
aea4c774 6811(define_insn "*cmpsi_shiftsi"
bd5b4116 6812 [(set (reg:CC CC_REGNUM)
cffb2a26 6813 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6814 (match_operator:SI 3 "shift_operator"
aea4c774 6815 [(match_operand:SI 1 "s_register_operand" "r")
cffb2a26 6816 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6817 "TARGET_ARM"
aea4c774 6818 "cmp%?\\t%0, %1%S3"
344495ea 6819 [(set_attr "conds" "set")
331beb1a 6820 (set_attr "shift" "1")
a2cd141b 6821 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6822 (const_string "alu_shift")
6823 (const_string "alu_shift_reg")))]
0d66636f 6824)
b11cae9e 6825
aea4c774 6826(define_insn "*cmpsi_shiftsi_swp"
bd5b4116 6827 [(set (reg:CC_SWP CC_REGNUM)
aea4c774 6828 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6829 [(match_operand:SI 1 "s_register_operand" "r")
6830 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6831 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6832 "TARGET_ARM"
aea4c774 6833 "cmp%?\\t%0, %1%S3"
344495ea 6834 [(set_attr "conds" "set")
331beb1a 6835 (set_attr "shift" "1")
a2cd141b 6836 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6837 (const_string "alu_shift")
6838 (const_string "alu_shift_reg")))]
0d66636f 6839)
b11cae9e 6840
aed179ae 6841(define_insn "*cmpsi_negshiftsi_si"
6842 [(set (reg:CC_Z CC_REGNUM)
6843 (compare:CC_Z
6844 (neg:SI (match_operator:SI 1 "shift_operator"
6845 [(match_operand:SI 2 "s_register_operand" "r")
6846 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6847 (match_operand:SI 0 "s_register_operand" "r")))]
cffb2a26 6848 "TARGET_ARM"
aed179ae 6849 "cmn%?\\t%0, %2%S1"
344495ea 6850 [(set_attr "conds" "set")
aed179ae 6851 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6852 (const_string "alu_shift")
6853 (const_string "alu_shift_reg")))]
0d66636f 6854)
b11cae9e 6855
7d57ec45 6856;; Cirrus SF compare instruction
6857(define_insn "*cirrus_cmpsf"
6858 [(set (reg:CCFP CC_REGNUM)
6859 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6860 (match_operand:SF 1 "cirrus_fp_register" "v")))]
a2cd141b 6861 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6862 "cfcmps%?\\tr15, %V0, %V1"
2c6c7d8b 6863 [(set_attr "type" "mav_farith")
7d57ec45 6864 (set_attr "cirrus" "compare")]
6865)
6866
6867;; Cirrus DF compare instruction
6868(define_insn "*cirrus_cmpdf"
6869 [(set (reg:CCFP CC_REGNUM)
6870 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6871 (match_operand:DF 1 "cirrus_fp_register" "v")))]
a2cd141b 6872 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6873 "cfcmpd%?\\tr15, %V0, %V1"
2c6c7d8b 6874 [(set_attr "type" "mav_farith")
7d57ec45 6875 (set_attr "cirrus" "compare")]
6876)
6877
6878;; Cirrus DI compare instruction
6879(define_expand "cmpdi"
6880 [(match_operand:DI 0 "cirrus_fp_register" "")
6881 (match_operand:DI 1 "cirrus_fp_register" "")]
a2cd141b 6882 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6883 "{
6884 arm_compare_op0 = operands[0];
6885 arm_compare_op1 = operands[1];
6886 DONE;
6887 }")
6888
6889(define_insn "*cirrus_cmpdi"
6890 [(set (reg:CC CC_REGNUM)
6891 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6892 (match_operand:DI 1 "cirrus_fp_register" "v")))]
a2cd141b 6893 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7d57ec45 6894 "cfcmp64%?\\tr15, %V0, %V1"
2c6c7d8b 6895 [(set_attr "type" "mav_farith")
7d57ec45 6896 (set_attr "cirrus" "compare")]
6897)
6898
9c08d1fa 6899; This insn allows redundant compares to be removed by cse, nothing should
6900; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6901; is deleted later on. The match_dup will match the mode here, so that
6902; mode changes of the condition codes aren't lost by this even though we don't
6903; specify what they are.
6904
8a18b90c 6905(define_insn "*deleted_compare"
9c08d1fa 6906 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
cffb2a26 6907 "TARGET_ARM"
40dbec34 6908 "\\t%@ deleted compare"
cffb2a26 6909 [(set_attr "conds" "set")
6910 (set_attr "length" "0")]
6911)
9c08d1fa 6912
6913\f
6914;; Conditional branch insns
6915
6916(define_expand "beq"
6917 [(set (pc)
6918 (if_then_else (eq (match_dup 1) (const_int 0))
6919 (label_ref (match_operand 0 "" ""))
6920 (pc)))]
cffb2a26 6921 "TARGET_ARM"
6922 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6923)
5c951228 6924
9c08d1fa 6925(define_expand "bne"
6926 [(set (pc)
6927 (if_then_else (ne (match_dup 1) (const_int 0))
6928 (label_ref (match_operand 0 "" ""))
6929 (pc)))]
cffb2a26 6930 "TARGET_ARM"
6931 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6932)
5c951228 6933
9c08d1fa 6934(define_expand "bgt"
6935 [(set (pc)
6936 (if_then_else (gt (match_dup 1) (const_int 0))
6937 (label_ref (match_operand 0 "" ""))
6938 (pc)))]
cffb2a26 6939 "TARGET_ARM"
6940 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6941)
5c951228 6942
9c08d1fa 6943(define_expand "ble"
6944 [(set (pc)
6945 (if_then_else (le (match_dup 1) (const_int 0))
6946 (label_ref (match_operand 0 "" ""))
6947 (pc)))]
cffb2a26 6948 "TARGET_ARM"
6949 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6950)
5c951228 6951
9c08d1fa 6952(define_expand "bge"
6953 [(set (pc)
6954 (if_then_else (ge (match_dup 1) (const_int 0))
6955 (label_ref (match_operand 0 "" ""))
6956 (pc)))]
cffb2a26 6957 "TARGET_ARM"
6958 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6959)
5c951228 6960
9c08d1fa 6961(define_expand "blt"
6962 [(set (pc)
6963 (if_then_else (lt (match_dup 1) (const_int 0))
6964 (label_ref (match_operand 0 "" ""))
6965 (pc)))]
cffb2a26 6966 "TARGET_ARM"
6967 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6968)
5c951228 6969
9c08d1fa 6970(define_expand "bgtu"
6971 [(set (pc)
6972 (if_then_else (gtu (match_dup 1) (const_int 0))
6973 (label_ref (match_operand 0 "" ""))
6974 (pc)))]
cffb2a26 6975 "TARGET_ARM"
6976 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6977)
5c951228 6978
9c08d1fa 6979(define_expand "bleu"
b11cae9e 6980 [(set (pc)
9c08d1fa 6981 (if_then_else (leu (match_dup 1) (const_int 0))
6982 (label_ref (match_operand 0 "" ""))
6983 (pc)))]
cffb2a26 6984 "TARGET_ARM"
6985 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6986)
b11cae9e 6987
9c08d1fa 6988(define_expand "bgeu"
b11cae9e 6989 [(set (pc)
9c08d1fa 6990 (if_then_else (geu (match_dup 1) (const_int 0))
6991 (label_ref (match_operand 0 "" ""))
6992 (pc)))]
cffb2a26 6993 "TARGET_ARM"
6994 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6995)
b11cae9e 6996
9c08d1fa 6997(define_expand "bltu"
6998 [(set (pc)
6999 (if_then_else (ltu (match_dup 1) (const_int 0))
7000 (label_ref (match_operand 0 "" ""))
7001 (pc)))]
cffb2a26 7002 "TARGET_ARM"
7003 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7004)
b11cae9e 7005
8fa3ba89 7006(define_expand "bunordered"
7007 [(set (pc)
7008 (if_then_else (unordered (match_dup 1) (const_int 0))
7009 (label_ref (match_operand 0 "" ""))
7010 (pc)))]
c0e1af52 7011 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7012 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7013 arm_compare_op1);"
7014)
7015
7016(define_expand "bordered"
7017 [(set (pc)
7018 (if_then_else (ordered (match_dup 1) (const_int 0))
7019 (label_ref (match_operand 0 "" ""))
7020 (pc)))]
c0e1af52 7021 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7022 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7023 arm_compare_op1);"
7024)
7025
7026(define_expand "bungt"
7027 [(set (pc)
7028 (if_then_else (ungt (match_dup 1) (const_int 0))
7029 (label_ref (match_operand 0 "" ""))
7030 (pc)))]
c0e1af52 7031 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7032 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7033)
7034
7035(define_expand "bunlt"
7036 [(set (pc)
7037 (if_then_else (unlt (match_dup 1) (const_int 0))
7038 (label_ref (match_operand 0 "" ""))
7039 (pc)))]
c0e1af52 7040 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7041 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7042)
7043
7044(define_expand "bunge"
7045 [(set (pc)
7046 (if_then_else (unge (match_dup 1) (const_int 0))
7047 (label_ref (match_operand 0 "" ""))
7048 (pc)))]
c0e1af52 7049 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7050 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7051)
7052
7053(define_expand "bunle"
7054 [(set (pc)
7055 (if_then_else (unle (match_dup 1) (const_int 0))
7056 (label_ref (match_operand 0 "" ""))
7057 (pc)))]
c0e1af52 7058 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7059 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7060)
7061
7062;; The following two patterns need two branch instructions, since there is
7063;; no single instruction that will handle all cases.
7064(define_expand "buneq"
7065 [(set (pc)
7066 (if_then_else (uneq (match_dup 1) (const_int 0))
7067 (label_ref (match_operand 0 "" ""))
7068 (pc)))]
c0e1af52 7069 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7070 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7071)
7072
7073(define_expand "bltgt"
7074 [(set (pc)
7075 (if_then_else (ltgt (match_dup 1) (const_int 0))
7076 (label_ref (match_operand 0 "" ""))
7077 (pc)))]
c0e1af52 7078 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7079 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7080)
7081
7082;;
7083;; Patterns to match conditional branch insns.
7084;;
7085
7086; Special pattern to match UNEQ.
7087(define_insn "*arm_buneq"
7088 [(set (pc)
7089 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7090 (label_ref (match_operand 0 "" ""))
7091 (pc)))]
c0e1af52 7092 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7093 "*
ed29c566 7094 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7095
278b301d 7096 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7097 "
7098 [(set_attr "conds" "jump_clob")
7099 (set_attr "length" "8")]
7100)
7101
7102; Special pattern to match LTGT.
7103(define_insn "*arm_bltgt"
7104 [(set (pc)
7105 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7106 (label_ref (match_operand 0 "" ""))
7107 (pc)))]
c0e1af52 7108 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7109 "*
ed29c566 7110 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7111
278b301d 7112 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7113 "
7114 [(set_attr "conds" "jump_clob")
7115 (set_attr "length" "8")]
7116)
9c08d1fa 7117
cffb2a26 7118(define_insn "*arm_cond_branch"
9c08d1fa 7119 [(set (pc)
8fa3ba89 7120 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7121 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7122 (label_ref (match_operand 0 "" ""))
7123 (pc)))]
cffb2a26 7124 "TARGET_ARM"
d75350ce 7125 "*
9c08d1fa 7126 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7127 {
7128 arm_ccfsm_state += 2;
7129 return \"\";
7130 }
e2348bcb 7131 return \"b%d1\\t%l0\";
cffb2a26 7132 "
a2cd141b 7133 [(set_attr "conds" "use")
7134 (set_attr "type" "branch")]
cffb2a26 7135)
d75350ce 7136
8fa3ba89 7137; Special pattern to match reversed UNEQ.
7138(define_insn "*arm_buneq_reversed"
7139 [(set (pc)
7140 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7141 (pc)
7142 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7143 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7144 "*
ed29c566 7145 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7146
278b301d 7147 return \"bmi\\t%l0\;bgt\\t%l0\";
8fa3ba89 7148 "
7149 [(set_attr "conds" "jump_clob")
7150 (set_attr "length" "8")]
7151)
7152
7153; Special pattern to match reversed LTGT.
7154(define_insn "*arm_bltgt_reversed"
7155 [(set (pc)
7156 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7157 (pc)
7158 (label_ref (match_operand 0 "" ""))))]
c0e1af52 7159 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7160 "*
ed29c566 7161 gcc_assert (!arm_ccfsm_state);
8fa3ba89 7162
278b301d 7163 return \"bvs\\t%l0\;beq\\t%l0\";
8fa3ba89 7164 "
7165 [(set_attr "conds" "jump_clob")
7166 (set_attr "length" "8")]
7167)
7168
cffb2a26 7169(define_insn "*arm_cond_branch_reversed"
9c08d1fa 7170 [(set (pc)
8fa3ba89 7171 (if_then_else (match_operator 1 "arm_comparison_operator"
8a18b90c 7172 [(match_operand 2 "cc_register" "") (const_int 0)])
9c08d1fa 7173 (pc)
7174 (label_ref (match_operand 0 "" ""))))]
cffb2a26 7175 "TARGET_ARM"
d75350ce 7176 "*
9c08d1fa 7177 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
cffb2a26 7178 {
7179 arm_ccfsm_state += 2;
7180 return \"\";
7181 }
e2348bcb 7182 return \"b%D1\\t%l0\";
cffb2a26 7183 "
a2cd141b 7184 [(set_attr "conds" "use")
7185 (set_attr "type" "branch")]
cffb2a26 7186)
7187
b11cae9e 7188\f
9c08d1fa 7189
7190; scc insns
7191
7192(define_expand "seq"
7db9af5d 7193 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7194 (eq:SI (match_dup 1) (const_int 0)))]
cffb2a26 7195 "TARGET_ARM"
7196 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7197)
9c08d1fa 7198
7199(define_expand "sne"
7db9af5d 7200 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7201 (ne:SI (match_dup 1) (const_int 0)))]
cffb2a26 7202 "TARGET_ARM"
7203 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7204)
9c08d1fa 7205
7206(define_expand "sgt"
7db9af5d 7207 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7208 (gt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7209 "TARGET_ARM"
7210 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7211)
9c08d1fa 7212
7213(define_expand "sle"
7db9af5d 7214 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7215 (le:SI (match_dup 1) (const_int 0)))]
cffb2a26 7216 "TARGET_ARM"
7217 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7218)
9c08d1fa 7219
7220(define_expand "sge"
7db9af5d 7221 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7222 (ge:SI (match_dup 1) (const_int 0)))]
cffb2a26 7223 "TARGET_ARM"
7224 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7225)
9c08d1fa 7226
7227(define_expand "slt"
7db9af5d 7228 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7229 (lt:SI (match_dup 1) (const_int 0)))]
cffb2a26 7230 "TARGET_ARM"
7231 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7232)
9c08d1fa 7233
7234(define_expand "sgtu"
7db9af5d 7235 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7236 (gtu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7237 "TARGET_ARM"
7238 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7239)
9c08d1fa 7240
7241(define_expand "sleu"
7db9af5d 7242 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7243 (leu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7244 "TARGET_ARM"
7245 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7246)
9c08d1fa 7247
7248(define_expand "sgeu"
7db9af5d 7249 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7250 (geu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7251 "TARGET_ARM"
7252 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7253)
9c08d1fa 7254
7255(define_expand "sltu"
7db9af5d 7256 [(set (match_operand:SI 0 "s_register_operand" "")
9c08d1fa 7257 (ltu:SI (match_dup 1) (const_int 0)))]
cffb2a26 7258 "TARGET_ARM"
7259 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7260)
9c08d1fa 7261
8fa3ba89 7262(define_expand "sunordered"
7db9af5d 7263 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7264 (unordered:SI (match_dup 1) (const_int 0)))]
c0e1af52 7265 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7266 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7267 arm_compare_op1);"
7268)
7269
7270(define_expand "sordered"
7db9af5d 7271 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7272 (ordered:SI (match_dup 1) (const_int 0)))]
c0e1af52 7273 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7274 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7275 arm_compare_op1);"
7276)
7277
7278(define_expand "sungt"
7db9af5d 7279 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7280 (ungt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7281 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7282 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7283 arm_compare_op1);"
7284)
7285
7286(define_expand "sunge"
7db9af5d 7287 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7288 (unge:SI (match_dup 1) (const_int 0)))]
c0e1af52 7289 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7290 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7291 arm_compare_op1);"
7292)
7293
7294(define_expand "sunlt"
7db9af5d 7295 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7296 (unlt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7297 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7298 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7299 arm_compare_op1);"
7300)
7301
7302(define_expand "sunle"
7db9af5d 7303 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7304 (unle:SI (match_dup 1) (const_int 0)))]
c0e1af52 7305 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
8fa3ba89 7306 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7307 arm_compare_op1);"
7308)
7309
7310;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7311;;; simple ARM instructions.
7312;
7313; (define_expand "suneq"
7db9af5d 7314; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7315; (uneq:SI (match_dup 1) (const_int 0)))]
c0e1af52 7316; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7317; "gcc_unreachable ();"
8fa3ba89 7318; )
7319;
7320; (define_expand "sltgt"
7db9af5d 7321; [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7322; (ltgt:SI (match_dup 1) (const_int 0)))]
c0e1af52 7323; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
ed29c566 7324; "gcc_unreachable ();"
8fa3ba89 7325; )
7326
f7fbdd4a 7327(define_insn "*mov_scc"
9c08d1fa 7328 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7329 (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7330 [(match_operand 2 "cc_register" "") (const_int 0)]))]
cffb2a26 7331 "TARGET_ARM"
4d61e570 7332 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
cffb2a26 7333 [(set_attr "conds" "use")
7334 (set_attr "length" "8")]
7335)
9c08d1fa 7336
f7fbdd4a 7337(define_insn "*mov_negscc"
9c08d1fa 7338 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7339 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7340 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7341 "TARGET_ARM"
4d61e570 7342 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
cffb2a26 7343 [(set_attr "conds" "use")
7344 (set_attr "length" "8")]
7345)
9c08d1fa 7346
f7fbdd4a 7347(define_insn "*mov_notscc"
9c08d1fa 7348 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 7349 (not:SI (match_operator:SI 1 "arm_comparison_operator"
8a18b90c 7350 [(match_operand 2 "cc_register" "") (const_int 0)])))]
cffb2a26 7351 "TARGET_ARM"
4d61e570 7352 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
cffb2a26 7353 [(set_attr "conds" "use")
7354 (set_attr "length" "8")]
7355)
9c08d1fa 7356
7357\f
39b5e676 7358;; Conditional move insns
7359
7360(define_expand "movsicc"
8a18b90c 7361 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 7362 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
aea4c774 7363 (match_operand:SI 2 "arm_not_operand" "")
8a18b90c 7364 (match_operand:SI 3 "arm_not_operand" "")))]
cffb2a26 7365 "TARGET_ARM"
39b5e676 7366 "
215b30b3 7367 {
7368 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7369 rtx ccreg;
7370
7371 if (code == UNEQ || code == LTGT)
7372 FAIL;
39b5e676 7373
278b301d 7374 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7375 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7376 }"
7377)
39b5e676 7378
7379(define_expand "movsfcc"
8a18b90c 7380 [(set (match_operand:SF 0 "s_register_operand" "")
8fa3ba89 7381 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7382 (match_operand:SF 2 "s_register_operand" "")
7383 (match_operand:SF 3 "nonmemory_operand" "")))]
cffb2a26 7384 "TARGET_ARM"
39b5e676 7385 "
215b30b3 7386 {
7387 enum rtx_code code = GET_CODE (operands[1]);
7388 rtx ccreg;
f082f1c4 7389
278b301d 7390 if (code == UNEQ || code == LTGT)
7391 FAIL;
7392
215b30b3 7393 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
a2cd141b 7394 Otherwise, ensure it is a valid FP add operand */
7395 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7396 || (!arm_float_add_operand (operands[3], SFmode)))
215b30b3 7397 operands[3] = force_reg (SFmode, operands[3]);
39b5e676 7398
215b30b3 7399 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7400 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7401 }"
7402)
39b5e676 7403
7404(define_expand "movdfcc"
8a18b90c 7405 [(set (match_operand:DF 0 "s_register_operand" "")
8fa3ba89 7406 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
8a18b90c 7407 (match_operand:DF 2 "s_register_operand" "")
a2cd141b 7408 (match_operand:DF 3 "arm_float_add_operand" "")))]
7409 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
39b5e676 7410 "
215b30b3 7411 {
7412 enum rtx_code code = GET_CODE (operands[1]);
278b301d 7413 rtx ccreg;
39b5e676 7414
278b301d 7415 if (code == UNEQ || code == LTGT)
7416 FAIL;
7417
7418 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
29bb088d 7419 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
215b30b3 7420 }"
7421)
39b5e676 7422
7423(define_insn "*movsicc_insn"
f082f1c4 7424 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8a18b90c 7425 (if_then_else:SI
8fa3ba89 7426 (match_operator 3 "arm_comparison_operator"
8a18b90c 7427 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7428 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7429 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
cffb2a26 7430 "TARGET_ARM"
39b5e676 7431 "@
8a18b90c 7432 mov%D3\\t%0, %2
7433 mvn%D3\\t%0, #%B2
f082f1c4 7434 mov%d3\\t%0, %1
7435 mvn%d3\\t%0, #%B1
8a18b90c 7436 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7437 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7438 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7439 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
f082f1c4 7440 [(set_attr "length" "4,4,4,4,8,8,8,8")
215b30b3 7441 (set_attr "conds" "use")]
7442)
39b5e676 7443
39b5e676 7444(define_insn "*movsfcc_soft_insn"
f082f1c4 7445 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8fa3ba89 7446 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8a18b90c 7447 [(match_operand 4 "cc_register" "") (const_int 0)])
f082f1c4 7448 (match_operand:SF 1 "s_register_operand" "0,r")
7449 (match_operand:SF 2 "s_register_operand" "r,0")))]
cffb2a26 7450 "TARGET_ARM && TARGET_SOFT_FLOAT"
f082f1c4 7451 "@
7452 mov%D3\\t%0, %2
7453 mov%d3\\t%0, %1"
8fa3ba89 7454 [(set_attr "conds" "use")]
7455)
39b5e676 7456
39b5e676 7457\f
9c08d1fa 7458;; Jump and linkage insns
7459
cffb2a26 7460(define_expand "jump"
9c08d1fa 7461 [(set (pc)
7462 (label_ref (match_operand 0 "" "")))]
cffb2a26 7463 "TARGET_EITHER"
9c08d1fa 7464 ""
cffb2a26 7465)
7466
7467(define_insn "*arm_jump"
7468 [(set (pc)
7469 (label_ref (match_operand 0 "" "")))]
7470 "TARGET_ARM"
9c08d1fa 7471 "*
0d66636f 7472 {
7473 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7474 {
7475 arm_ccfsm_state += 2;
7476 return \"\";
7477 }
7478 return \"b%?\\t%l0\";
7479 }
7480 "
7481 [(set_attr "predicable" "yes")]
7482)
9c08d1fa 7483
cffb2a26 7484(define_insn "*thumb_jump"
7485 [(set (pc)
7486 (label_ref (match_operand 0 "" "")))]
7487 "TARGET_THUMB"
7488 "*
7489 if (get_attr_length (insn) == 2)
7490 return \"b\\t%l0\";
7491 return \"bl\\t%l0\\t%@ far jump\";
7492 "
7493 [(set (attr "far_jump")
7494 (if_then_else
7495 (eq_attr "length" "4")
7496 (const_string "yes")
7497 (const_string "no")))
7498 (set (attr "length")
7499 (if_then_else
911ed8af 7500 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7501 (le (minus (match_dup 0) (pc)) (const_int 2048)))
cffb2a26 7502 (const_int 2)
7503 (const_int 4)))]
7504)
7505
d3373b54 7506(define_expand "call"
7507 [(parallel [(call (match_operand 0 "memory_operand" "")
7508 (match_operand 1 "general_operand" ""))
cffb2a26 7509 (use (match_operand 2 "" ""))
bd5b4116 7510 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7511 "TARGET_EITHER"
6c4c2133 7512 "
7513 {
78fe751b 7514 rtx callee;
bbe777ea 7515
bbe777ea 7516 /* In an untyped call, we can get NULL for operand 2. */
7517 if (operands[2] == NULL_RTX)
7518 operands[2] = const0_rtx;
7519
78fe751b 7520 /* This is to decide if we should generate indirect calls by loading the
7521 32 bit address of the callee into a register before performing the
7522 branch and link. operand[2] encodes the long_call/short_call
7523 attribute of the function being called. This attribute is set whenever
7524 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7525 is used, and the short_call attribute can also be set if function is
7526 declared as static or if it has already been defined in the current
7527 compilation unit. See arm.c and arm.h for info about this. The third
7528 parameter to arm_is_longcall_p is used to tell it which pattern
7529 invoked it. */
7530 callee = XEXP (operands[0], 0);
7531
e44b56b6 7532 if ((GET_CODE (callee) == SYMBOL_REF
7533 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7534 || (GET_CODE (callee) != SYMBOL_REF
7535 && GET_CODE (callee) != REG))
bbe777ea 7536 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6c4c2133 7537 }"
7538)
d3373b54 7539
f1039640 7540(define_insn "*call_reg_armv5"
d3373b54 7541 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
cffb2a26 7542 (match_operand 1 "" ""))
7543 (use (match_operand 2 "" ""))
bd5b4116 7544 (clobber (reg:SI LR_REGNUM))]
f1039640 7545 "TARGET_ARM && arm_arch5"
7546 "blx%?\\t%0"
7547 [(set_attr "type" "call")]
7548)
7549
7550(define_insn "*call_reg_arm"
7551 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7552 (match_operand 1 "" ""))
7553 (use (match_operand 2 "" ""))
7554 (clobber (reg:SI LR_REGNUM))]
7555 "TARGET_ARM && !arm_arch5"
9c08d1fa 7556 "*
5565501b 7557 return output_call (operands);
cffb2a26 7558 "
7559 ;; length is worst case, normally it is only two
7560 [(set_attr "length" "12")
7561 (set_attr "type" "call")]
7562)
9c08d1fa 7563
f7fbdd4a 7564(define_insn "*call_mem"
a3c63a9d 7565 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
cffb2a26 7566 (match_operand 1 "" ""))
7567 (use (match_operand 2 "" ""))
bd5b4116 7568 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7569 "TARGET_ARM"
9c08d1fa 7570 "*
5565501b 7571 return output_call_mem (operands);
cffb2a26 7572 "
7573 [(set_attr "length" "12")
7574 (set_attr "type" "call")]
7575)
7576
f1039640 7577(define_insn "*call_reg_thumb_v5"
cffb2a26 7578 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7579 (match_operand 1 "" ""))
7580 (use (match_operand 2 "" ""))
bd5b4116 7581 (clobber (reg:SI LR_REGNUM))]
f1039640 7582 "TARGET_THUMB && arm_arch5"
7583 "blx\\t%0"
7584 [(set_attr "length" "2")
7585 (set_attr "type" "call")]
cffb2a26 7586)
7587
f1039640 7588(define_insn "*call_reg_thumb"
7589 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7590 (match_operand 1 "" ""))
7591 (use (match_operand 2 "" ""))
bd5b4116 7592 (clobber (reg:SI LR_REGNUM))]
f1039640 7593 "TARGET_THUMB && !arm_arch5"
cffb2a26 7594 "*
7595 {
150502c9 7596 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7597 return thumb_call_via_reg (operands[0]);
150502c9 7598 else if (operands[1] == const0_rtx)
f1039640 7599 return \"bl\\t%__interwork_call_via_%0\";
150502c9 7600 else if (frame_pointer_needed)
7601 return \"bl\\t%__interwork_r7_call_via_%0\";
cffb2a26 7602 else
150502c9 7603 return \"bl\\t%__interwork_r11_call_via_%0\";
cffb2a26 7604 }"
7605 [(set_attr "type" "call")]
7606)
9c08d1fa 7607
d3373b54 7608(define_expand "call_value"
e0698af7 7609 [(parallel [(set (match_operand 0 "" "")
7610 (call (match_operand 1 "memory_operand" "")
7611 (match_operand 2 "general_operand" "")))
cffb2a26 7612 (use (match_operand 3 "" ""))
bd5b4116 7613 (clobber (reg:SI LR_REGNUM))])]
cffb2a26 7614 "TARGET_EITHER"
6c4c2133 7615 "
7616 {
bbe777ea 7617 rtx callee = XEXP (operands[1], 0);
7618
7619 /* In an untyped call, we can get NULL for operand 2. */
7620 if (operands[3] == 0)
7621 operands[3] = const0_rtx;
7622
7623 /* See the comment in define_expand \"call\". */
e44b56b6 7624 if ((GET_CODE (callee) == SYMBOL_REF
7625 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7626 || (GET_CODE (callee) != SYMBOL_REF
7627 && GET_CODE (callee) != REG))
78fe751b 7628 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6c4c2133 7629 }"
7630)
d3373b54 7631
f1039640 7632(define_insn "*call_value_reg_armv5"
27ed6835 7633 [(set (match_operand 0 "" "")
755eb2b4 7634 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
cffb2a26 7635 (match_operand 2 "" "")))
bbe777ea 7636 (use (match_operand 3 "" ""))
bd5b4116 7637 (clobber (reg:SI LR_REGNUM))]
f1039640 7638 "TARGET_ARM && arm_arch5"
7639 "blx%?\\t%1"
7640 [(set_attr "type" "call")]
7641)
7642
7643(define_insn "*call_value_reg_arm"
7644 [(set (match_operand 0 "" "")
7645 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7646 (match_operand 2 "" "")))
7647 (use (match_operand 3 "" ""))
7648 (clobber (reg:SI LR_REGNUM))]
7649 "TARGET_ARM && !arm_arch5"
9c08d1fa 7650 "*
215b30b3 7651 return output_call (&operands[1]);
cffb2a26 7652 "
7653 [(set_attr "length" "12")
7654 (set_attr "type" "call")]
7655)
9c08d1fa 7656
f7fbdd4a 7657(define_insn "*call_value_mem"
27ed6835 7658 [(set (match_operand 0 "" "")
a3c63a9d 7659 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
cffb2a26 7660 (match_operand 2 "" "")))
bbe777ea 7661 (use (match_operand 3 "" ""))
bd5b4116 7662 (clobber (reg:SI LR_REGNUM))]
215b30b3 7663 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
9c08d1fa 7664 "*
215b30b3 7665 return output_call_mem (&operands[1]);
cffb2a26 7666 "
7667 [(set_attr "length" "12")
7668 (set_attr "type" "call")]
7669)
9c08d1fa 7670
f1039640 7671(define_insn "*call_value_reg_thumb_v5"
7672 [(set (match_operand 0 "" "")
7673 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7674 (match_operand 2 "" "")))
7675 (use (match_operand 3 "" ""))
7676 (clobber (reg:SI LR_REGNUM))]
7677 "TARGET_THUMB && arm_arch5"
7678 "blx\\t%1"
7679 [(set_attr "length" "2")
7680 (set_attr "type" "call")]
7681)
7682
7683(define_insn "*call_value_reg_thumb"
7684 [(set (match_operand 0 "" "")
7685 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7686 (match_operand 2 "" "")))
7687 (use (match_operand 3 "" ""))
7688 (clobber (reg:SI LR_REGNUM))]
7689 "TARGET_THUMB && !arm_arch5"
7690 "*
7691 {
150502c9 7692 if (!TARGET_CALLER_INTERWORKING)
afe27f3b 7693 return thumb_call_via_reg (operands[1]);
150502c9 7694 else if (operands[2] == const0_rtx)
f1039640 7695 return \"bl\\t%__interwork_call_via_%1\";
150502c9 7696 else if (frame_pointer_needed)
7697 return \"bl\\t%__interwork_r7_call_via_%1\";
f1039640 7698 else
150502c9 7699 return \"bl\\t%__interwork_r11_call_via_%1\";
f1039640 7700 }"
7701 [(set_attr "type" "call")]
7702)
7703
9c08d1fa 7704;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7705;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7706
f7fbdd4a 7707(define_insn "*call_symbol"
27ed6835 7708 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7709 (match_operand 1 "" ""))
bbe777ea 7710 (use (match_operand 2 "" ""))
bd5b4116 7711 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7712 "TARGET_ARM
7713 && (GET_CODE (operands[0]) == SYMBOL_REF)
215b30b3 7714 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6ebaa29d 7715 "*
7716 {
55c1e470 7717 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6ebaa29d 7718 }"
cffb2a26 7719 [(set_attr "type" "call")]
7720)
9c08d1fa 7721
f7fbdd4a 7722(define_insn "*call_value_symbol"
ccd90aaa 7723 [(set (match_operand 0 "" "")
27ed6835 7724 (call (mem:SI (match_operand:SI 1 "" ""))
dd6d7504 7725 (match_operand:SI 2 "" "")))
bbe777ea 7726 (use (match_operand 3 "" ""))
bd5b4116 7727 (clobber (reg:SI LR_REGNUM))]
cffb2a26 7728 "TARGET_ARM
7729 && (GET_CODE (operands[1]) == SYMBOL_REF)
215b30b3 7730 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6ebaa29d 7731 "*
7732 {
55c1e470 7733 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6ebaa29d 7734 }"
cffb2a26 7735 [(set_attr "type" "call")]
7736)
7737
7738(define_insn "*call_insn"
27ed6835 7739 [(call (mem:SI (match_operand:SI 0 "" ""))
cffb2a26 7740 (match_operand:SI 1 "" ""))
7741 (use (match_operand 2 "" ""))
bd5b4116 7742 (clobber (reg:SI LR_REGNUM))]
1c494086 7743 "TARGET_THUMB
1675c6e9 7744 && GET_CODE (operands[0]) == SYMBOL_REF
7745 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
cffb2a26 7746 "bl\\t%a0"
7747 [(set_attr "length" "4")
7748 (set_attr "type" "call")]
7749)
7750
7751(define_insn "*call_value_insn"
ccd90aaa 7752 [(set (match_operand 0 "" "")
27ed6835 7753 (call (mem:SI (match_operand 1 "" ""))
cffb2a26 7754 (match_operand 2 "" "")))
7755 (use (match_operand 3 "" ""))
bd5b4116 7756 (clobber (reg:SI LR_REGNUM))]
1c494086 7757 "TARGET_THUMB
1675c6e9 7758 && GET_CODE (operands[1]) == SYMBOL_REF
7759 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
cffb2a26 7760 "bl\\t%a1"
7761 [(set_attr "length" "4")
7762 (set_attr "type" "call")]
7763)
9c08d1fa 7764
1c494086 7765;; We may also be able to do sibcalls for Thumb, but it's much harder...
7766(define_expand "sibcall"
7767 [(parallel [(call (match_operand 0 "memory_operand" "")
7768 (match_operand 1 "general_operand" ""))
2ba80634 7769 (return)
7770 (use (match_operand 2 "" ""))])]
1c494086 7771 "TARGET_ARM"
7772 "
7773 {
7774 if (operands[2] == NULL_RTX)
7775 operands[2] = const0_rtx;
1c494086 7776 }"
7777)
7778
7779(define_expand "sibcall_value"
ccd90aaa 7780 [(parallel [(set (match_operand 0 "" "")
1c494086 7781 (call (match_operand 1 "memory_operand" "")
7782 (match_operand 2 "general_operand" "")))
2ba80634 7783 (return)
7784 (use (match_operand 3 "" ""))])]
1c494086 7785 "TARGET_ARM"
7786 "
7787 {
7788 if (operands[3] == NULL_RTX)
7789 operands[3] = const0_rtx;
1c494086 7790 }"
7791)
7792
7793(define_insn "*sibcall_insn"
7794 [(call (mem:SI (match_operand:SI 0 "" "X"))
7795 (match_operand 1 "" ""))
2ba80634 7796 (return)
7797 (use (match_operand 2 "" ""))]
1c494086 7798 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7799 "*
7800 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7801 "
7802 [(set_attr "type" "call")]
7803)
7804
7805(define_insn "*sibcall_value_insn"
ccd90aaa 7806 [(set (match_operand 0 "" "")
755eb2b4 7807 (call (mem:SI (match_operand:SI 1 "" "X"))
1c494086 7808 (match_operand 2 "" "")))
2ba80634 7809 (return)
7810 (use (match_operand 3 "" ""))]
1c494086 7811 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7812 "*
7813 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7814 "
7815 [(set_attr "type" "call")]
7816)
7817
9c08d1fa 7818;; Often the return insn will be the same as loading from memory, so set attr
7819(define_insn "return"
7820 [(return)]
cffb2a26 7821 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
9c08d1fa 7822 "*
9c08d1fa 7823 {
cffb2a26 7824 if (arm_ccfsm_state == 2)
7825 {
7826 arm_ccfsm_state += 2;
7827 return \"\";
7828 }
5db468b7 7829 return output_return_instruction (const_true_rtx, TRUE, FALSE);
cffb2a26 7830 }"
a2cd141b 7831 [(set_attr "type" "load1")
755eb2b4 7832 (set_attr "length" "12")
0d66636f 7833 (set_attr "predicable" "yes")]
cffb2a26 7834)
9c08d1fa 7835
f7fbdd4a 7836(define_insn "*cond_return"
9c08d1fa 7837 [(set (pc)
8fa3ba89 7838 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7839 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7840 (return)
7841 (pc)))]
cffb2a26 7842 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7843 "*
8fa3ba89 7844 {
7845 if (arm_ccfsm_state == 2)
7846 {
7847 arm_ccfsm_state += 2;
7848 return \"\";
7849 }
7850 return output_return_instruction (operands[0], TRUE, FALSE);
7851 }"
7852 [(set_attr "conds" "use")
755eb2b4 7853 (set_attr "length" "12")
a2cd141b 7854 (set_attr "type" "load1")]
8fa3ba89 7855)
9c08d1fa 7856
f7fbdd4a 7857(define_insn "*cond_return_inverted"
9c08d1fa 7858 [(set (pc)
8fa3ba89 7859 (if_then_else (match_operator 0 "arm_comparison_operator"
8a18b90c 7860 [(match_operand 1 "cc_register" "") (const_int 0)])
9c08d1fa 7861 (pc)
7862 (return)))]
cffb2a26 7863 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
9c08d1fa 7864 "*
8fa3ba89 7865 {
7866 if (arm_ccfsm_state == 2)
7867 {
7868 arm_ccfsm_state += 2;
7869 return \"\";
7870 }
7871 return output_return_instruction (operands[0], TRUE, TRUE);
7872 }"
7873 [(set_attr "conds" "use")
37a1317b 7874 (set_attr "length" "12")
a2cd141b 7875 (set_attr "type" "load1")]
8fa3ba89 7876)
9c08d1fa 7877
68121397 7878;; Generate a sequence of instructions to determine if the processor is
7879;; in 26-bit or 32-bit mode, and return the appropriate return address
7880;; mask.
7881
7882(define_expand "return_addr_mask"
7883 [(set (match_dup 1)
7884 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7885 (const_int 0)))
7886 (set (match_operand:SI 0 "s_register_operand" "")
7887 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7888 (const_int -1)
7889 (const_int 67108860)))] ; 0x03fffffc
7890 "TARGET_ARM"
7891 "
62eddbd4 7892 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
68121397 7893 ")
7894
7895(define_insn "*check_arch2"
7896 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7897 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7898 (const_int 0)))]
7899 "TARGET_ARM"
7900 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7901 [(set_attr "length" "8")
7902 (set_attr "conds" "set")]
7903)
7904
9c08d1fa 7905;; Call subroutine returning any type.
7906
7907(define_expand "untyped_call"
7908 [(parallel [(call (match_operand 0 "" "")
7909 (const_int 0))
7910 (match_operand 1 "" "")
7911 (match_operand 2 "" "")])]
ccd90aaa 7912 "TARGET_EITHER"
9c08d1fa 7913 "
215b30b3 7914 {
7915 int i;
ccd90aaa 7916 rtx par = gen_rtx_PARALLEL (VOIDmode,
7917 rtvec_alloc (XVECLEN (operands[2], 0)));
7918 rtx addr = gen_reg_rtx (Pmode);
7919 rtx mem;
7920 int size = 0;
9c08d1fa 7921
ccd90aaa 7922 emit_move_insn (addr, XEXP (operands[1], 0));
7923 mem = change_address (operands[1], BLKmode, addr);
9c08d1fa 7924
215b30b3 7925 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7926 {
ccd90aaa 7927 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
9c08d1fa 7928
ccd90aaa 7929 /* Default code only uses r0 as a return value, but we could
7930 be using anything up to 4 registers. */
7931 if (REGNO (src) == R0_REGNUM)
7932 src = gen_rtx_REG (TImode, R0_REGNUM);
7933
7934 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7935 GEN_INT (size));
7936 size += GET_MODE_SIZE (GET_MODE (src));
7937 }
7938
7939 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7940 const0_rtx));
7941
7942 size = 0;
7943
7944 for (i = 0; i < XVECLEN (par, 0); i++)
7945 {
7946 HOST_WIDE_INT offset = 0;
7947 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7948
7949 if (size != 0)
7950 emit_move_insn (addr, plus_constant (addr, size));
7951
7952 mem = change_address (mem, GET_MODE (reg), NULL);
7953 if (REGNO (reg) == R0_REGNUM)
7954 {
7955 /* On thumb we have to use a write-back instruction. */
7956 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7957 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7958 size = TARGET_ARM ? 16 : 0;
7959 }
7960 else
7961 {
7962 emit_move_insn (mem, reg);
7963 size = GET_MODE_SIZE (GET_MODE (reg));
7964 }
215b30b3 7965 }
9c08d1fa 7966
215b30b3 7967 /* The optimizer does not know that the call sets the function value
7968 registers we stored in the result block. We avoid problems by
7969 claiming that all hard registers are used and clobbered at this
7970 point. */
7971 emit_insn (gen_blockage ());
7972
7973 DONE;
7974 }"
7975)
9c08d1fa 7976
ccd90aaa 7977(define_expand "untyped_return"
7978 [(match_operand:BLK 0 "memory_operand" "")
7979 (match_operand 1 "" "")]
7980 "TARGET_EITHER"
7981 "
7982 {
7983 int i;
7984 rtx addr = gen_reg_rtx (Pmode);
7985 rtx mem;
7986 int size = 0;
7987
7988 emit_move_insn (addr, XEXP (operands[0], 0));
7989 mem = change_address (operands[0], BLKmode, addr);
7990
7991 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7992 {
7993 HOST_WIDE_INT offset = 0;
7994 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7995
7996 if (size != 0)
7997 emit_move_insn (addr, plus_constant (addr, size));
7998
7999 mem = change_address (mem, GET_MODE (reg), NULL);
8000 if (REGNO (reg) == R0_REGNUM)
8001 {
8002 /* On thumb we have to use a write-back instruction. */
8003 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8004 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8005 size = TARGET_ARM ? 16 : 0;
8006 }
8007 else
8008 {
8009 emit_move_insn (reg, mem);
8010 size = GET_MODE_SIZE (GET_MODE (reg));
8011 }
8012 }
8013
8014 /* Emit USE insns before the return. */
8015 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8016 emit_insn (gen_rtx_USE (VOIDmode,
8017 SET_DEST (XVECEXP (operands[1], 0, i))));
8018
8019 /* Construct the return. */
8020 expand_naked_return ();
8021
8022 DONE;
8023 }"
8024)
8025
9c08d1fa 8026;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8027;; all of memory. This blocks insns from being moved across this point.
8028
8029(define_insn "blockage"
e1159bbe 8030 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
cffb2a26 8031 "TARGET_EITHER"
9c08d1fa 8032 ""
cffb2a26 8033 [(set_attr "length" "0")
8034 (set_attr "type" "block")]
8035)
9c08d1fa 8036
f7fbdd4a 8037(define_expand "casesi"
8038 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
aea4c774 8039 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8040 (match_operand:SI 2 "const_int_operand" "") ; total range
f7fbdd4a 8041 (match_operand:SI 3 "" "") ; table label
8042 (match_operand:SI 4 "" "")] ; Out of range label
cffb2a26 8043 "TARGET_ARM"
f7fbdd4a 8044 "
215b30b3 8045 {
8046 rtx reg;
8047 if (operands[1] != const0_rtx)
8048 {
8049 reg = gen_reg_rtx (SImode);
f7fbdd4a 8050
215b30b3 8051 emit_insn (gen_addsi3 (reg, operands[0],
8052 GEN_INT (-INTVAL (operands[1]))));
8053 operands[0] = reg;
8054 }
9c08d1fa 8055
215b30b3 8056 if (!const_ok_for_arm (INTVAL (operands[2])))
8057 operands[2] = force_reg (SImode, operands[2]);
8058
8059 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8060 operands[4]));
8061 DONE;
8062 }"
8063)
f7fbdd4a 8064
f082f1c4 8065;; The USE in this pattern is needed to tell flow analysis that this is
8066;; a CASESI insn. It has no other purpose.
f7fbdd4a 8067(define_insn "casesi_internal"
f082f1c4 8068 [(parallel [(set (pc)
8069 (if_then_else
8070 (leu (match_operand:SI 0 "s_register_operand" "r")
8071 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8072 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8073 (label_ref (match_operand 2 "" ""))))
8074 (label_ref (match_operand 3 "" ""))))
bd5b4116 8075 (clobber (reg:CC CC_REGNUM))
f082f1c4 8076 (use (label_ref (match_dup 2)))])]
cffb2a26 8077 "TARGET_ARM"
f7fbdd4a 8078 "*
0d66636f 8079 if (flag_pic)
8080 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8081 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8082 "
8083 [(set_attr "conds" "clob")
8084 (set_attr "length" "12")]
8085)
9c08d1fa 8086
cffb2a26 8087(define_expand "indirect_jump"
9c08d1fa 8088 [(set (pc)
cffb2a26 8089 (match_operand:SI 0 "s_register_operand" ""))]
8090 "TARGET_EITHER"
9c08d1fa 8091 ""
cffb2a26 8092)
8093
f1039640 8094;; NB Never uses BX.
cffb2a26 8095(define_insn "*arm_indirect_jump"
8096 [(set (pc)
8097 (match_operand:SI 0 "s_register_operand" "r"))]
8098 "TARGET_ARM"
8099 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
0d66636f 8100 [(set_attr "predicable" "yes")]
cffb2a26 8101)
9c08d1fa 8102
f7fbdd4a 8103(define_insn "*load_indirect_jump"
9c08d1fa 8104 [(set (pc)
8105 (match_operand:SI 0 "memory_operand" "m"))]
cffb2a26 8106 "TARGET_ARM"
8107 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
a2cd141b 8108 [(set_attr "type" "load1")
61a2d04c 8109 (set_attr "pool_range" "4096")
8110 (set_attr "neg_pool_range" "4084")
0d66636f 8111 (set_attr "predicable" "yes")]
cffb2a26 8112)
8113
f1039640 8114;; NB Never uses BX.
cffb2a26 8115(define_insn "*thumb_indirect_jump"
8116 [(set (pc)
8117 (match_operand:SI 0 "register_operand" "l*r"))]
8118 "TARGET_THUMB"
8119 "mov\\tpc, %0"
8120 [(set_attr "conds" "clob")
8121 (set_attr "length" "2")]
8122)
8123
9c08d1fa 8124\f
8125;; Misc insns
8126
8127(define_insn "nop"
8128 [(const_int 0)]
cffb2a26 8129 "TARGET_EITHER"
8130 "*
8131 if (TARGET_ARM)
8132 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8133 return \"mov\\tr8, r8\";
8134 "
8135 [(set (attr "length")
8136 (if_then_else (eq_attr "is_thumb" "yes")
8137 (const_int 2)
8138 (const_int 4)))]
8139)
8140
9c08d1fa 8141\f
8142;; Patterns to allow combination of arithmetic, cond code and shifts
8143
f7fbdd4a 8144(define_insn "*arith_shiftsi"
9c08d1fa 8145 [(set (match_operand:SI 0 "s_register_operand" "=r")
8146 (match_operator:SI 1 "shiftable_operator"
8147 [(match_operator:SI 3 "shift_operator"
8148 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8149 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8150 (match_operand:SI 2 "s_register_operand" "r")]))]
cffb2a26 8151 "TARGET_ARM"
6c4c2133 8152 "%i1%?\\t%0, %2, %4%S3"
344495ea 8153 [(set_attr "predicable" "yes")
331beb1a 8154 (set_attr "shift" "4")
a2cd141b 8155 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8156 (const_string "alu_shift")
8157 (const_string "alu_shift_reg")))]
6c4c2133 8158)
9c08d1fa 8159
d7863cfe 8160(define_split
8161 [(set (match_operand:SI 0 "s_register_operand" "")
8162 (match_operator:SI 1 "shiftable_operator"
8163 [(match_operator:SI 2 "shiftable_operator"
8164 [(match_operator:SI 3 "shift_operator"
8165 [(match_operand:SI 4 "s_register_operand" "")
8166 (match_operand:SI 5 "reg_or_int_operand" "")])
8167 (match_operand:SI 6 "s_register_operand" "")])
8168 (match_operand:SI 7 "arm_rhs_operand" "")]))
8169 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8170 "TARGET_ARM"
8171 [(set (match_dup 8)
8172 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8173 (match_dup 6)]))
8174 (set (match_dup 0)
8175 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8176 "")
8177
f7fbdd4a 8178(define_insn "*arith_shiftsi_compare0"
bd5b4116 8179 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8180 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8181 [(match_operator:SI 3 "shift_operator"
8182 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8183 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8184 (match_operand:SI 2 "s_register_operand" "r")])
8185 (const_int 0)))
8186 (set (match_operand:SI 0 "s_register_operand" "=r")
8187 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8188 (match_dup 2)]))]
cffb2a26 8189 "TARGET_ARM"
87b22bf7 8190 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8191 [(set_attr "conds" "set")
331beb1a 8192 (set_attr "shift" "4")
a2cd141b 8193 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8194 (const_string "alu_shift")
8195 (const_string "alu_shift_reg")))]
0d66636f 8196)
9c08d1fa 8197
f7fbdd4a 8198(define_insn "*arith_shiftsi_compare0_scratch"
bd5b4116 8199 [(set (reg:CC_NOOV CC_REGNUM)
9c08d1fa 8200 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8201 [(match_operator:SI 3 "shift_operator"
8202 [(match_operand:SI 4 "s_register_operand" "r")
87b22bf7 8203 (match_operand:SI 5 "reg_or_int_operand" "rI")])
9c08d1fa 8204 (match_operand:SI 2 "s_register_operand" "r")])
8205 (const_int 0)))
8206 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8207 "TARGET_ARM"
87b22bf7 8208 "%i1%?s\\t%0, %2, %4%S3"
344495ea 8209 [(set_attr "conds" "set")
331beb1a 8210 (set_attr "shift" "4")
a2cd141b 8211 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8212 (const_string "alu_shift")
8213 (const_string "alu_shift_reg")))]
0d66636f 8214)
9c08d1fa 8215
f7fbdd4a 8216(define_insn "*sub_shiftsi"
9c08d1fa 8217 [(set (match_operand:SI 0 "s_register_operand" "=r")
8218 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8219 (match_operator:SI 2 "shift_operator"
8220 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8221 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
cffb2a26 8222 "TARGET_ARM"
6c4c2133 8223 "sub%?\\t%0, %1, %3%S2"
344495ea 8224 [(set_attr "predicable" "yes")
331beb1a 8225 (set_attr "shift" "3")
a2cd141b 8226 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8227 (const_string "alu_shift")
8228 (const_string "alu_shift_reg")))]
6c4c2133 8229)
9c08d1fa 8230
f7fbdd4a 8231(define_insn "*sub_shiftsi_compare0"
bd5b4116 8232 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8233 (compare:CC_NOOV
8234 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8235 (match_operator:SI 2 "shift_operator"
8236 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8237 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8238 (const_int 0)))
9c08d1fa 8239 (set (match_operand:SI 0 "s_register_operand" "=r")
8240 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8241 (match_dup 4)])))]
cffb2a26 8242 "TARGET_ARM"
87b22bf7 8243 "sub%?s\\t%0, %1, %3%S2"
344495ea 8244 [(set_attr "conds" "set")
a2cd141b 8245 (set_attr "shift" "3")
8246 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8247 (const_string "alu_shift")
8248 (const_string "alu_shift_reg")))]
0d66636f 8249)
9c08d1fa 8250
f7fbdd4a 8251(define_insn "*sub_shiftsi_compare0_scratch"
bd5b4116 8252 [(set (reg:CC_NOOV CC_REGNUM)
40dbec34 8253 (compare:CC_NOOV
8254 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8255 (match_operator:SI 2 "shift_operator"
8256 [(match_operand:SI 3 "s_register_operand" "r")
87b22bf7 8257 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
40dbec34 8258 (const_int 0)))
9c08d1fa 8259 (clobber (match_scratch:SI 0 "=r"))]
cffb2a26 8260 "TARGET_ARM"
87b22bf7 8261 "sub%?s\\t%0, %1, %3%S2"
344495ea 8262 [(set_attr "conds" "set")
a2cd141b 8263 (set_attr "shift" "3")
8264 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8265 (const_string "alu_shift")
8266 (const_string "alu_shift_reg")))]
0d66636f 8267)
9c08d1fa 8268
9c08d1fa 8269\f
8270
f7fbdd4a 8271(define_insn "*and_scc"
9c08d1fa 8272 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8273 (and:SI (match_operator:SI 1 "arm_comparison_operator"
aea4c774 8274 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8275 (match_operand:SI 2 "s_register_operand" "r")))]
cffb2a26 8276 "TARGET_ARM"
e2348bcb 8277 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8fa3ba89 8278 [(set_attr "conds" "use")
8279 (set_attr "length" "8")]
8280)
9c08d1fa 8281
f7fbdd4a 8282(define_insn "*ior_scc"
9c08d1fa 8283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8284 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8a18b90c 8285 [(match_operand 3 "cc_register" "") (const_int 0)])
9c08d1fa 8286 (match_operand:SI 1 "s_register_operand" "0,?r")))]
cffb2a26 8287 "TARGET_ARM"
e2348bcb 8288 "@
899850b0 8289 orr%d2\\t%0, %1, #1
8290 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8fa3ba89 8291 [(set_attr "conds" "use")
8292 (set_attr "length" "4,8")]
8293)
9c08d1fa 8294
f7fbdd4a 8295(define_insn "*compare_scc"
5565501b 8296 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8297 (match_operator:SI 1 "arm_comparison_operator"
5565501b 8298 [(match_operand:SI 2 "s_register_operand" "r,r")
8299 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
bd5b4116 8300 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8301 "TARGET_ARM"
9c08d1fa 8302 "*
601f584c 8303 if (operands[3] == const0_rtx)
8304 {
8305 if (GET_CODE (operands[1]) == LT)
8306 return \"mov\\t%0, %2, lsr #31\";
8307
8308 if (GET_CODE (operands[1]) == GE)
8309 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
e2348bcb 8310
601f584c 8311 if (GET_CODE (operands[1]) == EQ)
8312 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8313 }
e2348bcb 8314
8fa3ba89 8315 if (GET_CODE (operands[1]) == NE)
8316 {
8317 if (which_alternative == 1)
8318 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8319 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8320 }
8321 if (which_alternative == 1)
8322 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8323 else
8324 output_asm_insn (\"cmp\\t%2, %3\", operands);
8325 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8326 "
8327 [(set_attr "conds" "clob")
8328 (set_attr "length" "12")]
8329)
9c08d1fa 8330
f7fbdd4a 8331(define_insn "*cond_move"
9c08d1fa 8332 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
aea4c774 8333 (if_then_else:SI (match_operator 3 "equality_operator"
8fa3ba89 8334 [(match_operator 4 "arm_comparison_operator"
8a18b90c 8335 [(match_operand 5 "cc_register" "") (const_int 0)])
aea4c774 8336 (const_int 0)])
8337 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8338 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
cffb2a26 8339 "TARGET_ARM"
9c08d1fa 8340 "*
8fa3ba89 8341 if (GET_CODE (operands[3]) == NE)
8342 {
8343 if (which_alternative != 1)
8344 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8345 if (which_alternative != 0)
8346 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8347 return \"\";
8348 }
8349 if (which_alternative != 0)
8350 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8351 if (which_alternative != 1)
8352 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8353 return \"\";
8354 "
8355 [(set_attr "conds" "use")
8356 (set_attr "length" "4,4,8")]
8357)
9c08d1fa 8358
f7fbdd4a 8359(define_insn "*cond_arith"
9c08d1fa 8360 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8361 (match_operator:SI 5 "shiftable_operator"
8fa3ba89 8362 [(match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8363 [(match_operand:SI 2 "s_register_operand" "r,r")
8364 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8365 (match_operand:SI 1 "s_register_operand" "0,?r")]))
bd5b4116 8366 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8367 "TARGET_ARM"
9c08d1fa 8368 "*
8fa3ba89 8369 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8370 return \"%i5\\t%0, %1, %2, lsr #31\";
40dbec34 8371
8fa3ba89 8372 output_asm_insn (\"cmp\\t%2, %3\", operands);
8373 if (GET_CODE (operands[5]) == AND)
8374 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8375 else if (GET_CODE (operands[5]) == MINUS)
8376 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8377 else if (which_alternative != 0)
8378 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8379 return \"%i5%d4\\t%0, %1, #1\";
8380 "
8381 [(set_attr "conds" "clob")
8382 (set_attr "length" "12")]
8383)
9c08d1fa 8384
f7fbdd4a 8385(define_insn "*cond_sub"
9c08d1fa 8386 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8387 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8fa3ba89 8388 (match_operator:SI 4 "arm_comparison_operator"
9c08d1fa 8389 [(match_operand:SI 2 "s_register_operand" "r,r")
8390 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8391 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8392 "TARGET_ARM"
9c08d1fa 8393 "*
8fa3ba89 8394 output_asm_insn (\"cmp\\t%2, %3\", operands);
8395 if (which_alternative != 0)
8396 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8397 return \"sub%d4\\t%0, %1, #1\";
8398 "
8399 [(set_attr "conds" "clob")
8400 (set_attr "length" "8,12")]
8401)
9c08d1fa 8402
aea4c774 8403(define_insn "*cmp_ite0"
cffb2a26 8404 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8405 (compare
8406 (if_then_else:SI
8fa3ba89 8407 (match_operator 4 "arm_comparison_operator"
aea4c774 8408 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8409 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8410 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8411 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8412 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8413 (const_int 0))
8414 (const_int 0)))]
cffb2a26 8415 "TARGET_ARM"
9c08d1fa 8416 "*
aea4c774 8417 {
8fa3ba89 8418 static const char * const opcodes[4][2] =
8419 {
8420 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8421 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8422 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8423 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8424 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8425 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8426 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8427 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8428 };
8429 int swap =
8430 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8431
8432 return opcodes[which_alternative][swap];
8433 }"
8434 [(set_attr "conds" "set")
8435 (set_attr "length" "8")]
8436)
9c08d1fa 8437
aea4c774 8438(define_insn "*cmp_ite1"
cffb2a26 8439 [(set (match_operand 6 "dominant_cc_register" "")
aea4c774 8440 (compare
8441 (if_then_else:SI
8fa3ba89 8442 (match_operator 4 "arm_comparison_operator"
aea4c774 8443 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
ebcc79bc 8444 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8fa3ba89 8445 (match_operator:SI 5 "arm_comparison_operator"
aea4c774 8446 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
ebcc79bc 8447 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
aea4c774 8448 (const_int 1))
8449 (const_int 0)))]
cffb2a26 8450 "TARGET_ARM"
9c08d1fa 8451 "*
9c08d1fa 8452 {
215b30b3 8453 static const char * const opcodes[4][2] =
8454 {
8455 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8456 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8457 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8458 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8459 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8460 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8461 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8462 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8463 };
8464 int swap =
8465 comparison_dominates_p (GET_CODE (operands[5]),
8466 reverse_condition (GET_CODE (operands[4])));
8467
8468 return opcodes[which_alternative][swap];
8469 }"
8fa3ba89 8470 [(set_attr "conds" "set")
8471 (set_attr "length" "8")]
8472)
9c08d1fa 8473
f6c53574 8474(define_insn "*cmp_and"
8475 [(set (match_operand 6 "dominant_cc_register" "")
8476 (compare
8477 (and:SI
8478 (match_operator 4 "arm_comparison_operator"
8479 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8480 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8481 (match_operator:SI 5 "arm_comparison_operator"
8482 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8483 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8484 (const_int 0)))]
8485 "TARGET_ARM"
8486 "*
8487 {
35823b64 8488 static const char *const opcodes[4][2] =
f6c53574 8489 {
8490 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8491 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8492 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8493 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8494 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8495 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8496 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8497 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8498 };
8499 int swap =
8500 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8501
8502 return opcodes[which_alternative][swap];
8503 }"
8504 [(set_attr "conds" "set")
8505 (set_attr "predicable" "no")
8506 (set_attr "length" "8")]
8507)
8508
8509(define_insn "*cmp_ior"
8510 [(set (match_operand 6 "dominant_cc_register" "")
8511 (compare
8512 (ior:SI
8513 (match_operator 4 "arm_comparison_operator"
8514 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8515 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8516 (match_operator:SI 5 "arm_comparison_operator"
8517 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8518 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8519 (const_int 0)))]
8520 "TARGET_ARM"
8521 "*
8522{
35823b64 8523 static const char *const opcodes[4][2] =
f6c53574 8524 {
8525 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8526 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8527 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8528 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8529 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8530 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8531 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8532 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8533 };
8534 int swap =
8535 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8536
8537 return opcodes[which_alternative][swap];
8538}
8539"
8540 [(set_attr "conds" "set")
8541 (set_attr "length" "8")]
8542)
8543
3c5afce6 8544(define_insn_and_split "*ior_scc_scc"
8545 [(set (match_operand:SI 0 "s_register_operand" "=r")
8546 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8547 [(match_operand:SI 1 "s_register_operand" "r")
8548 (match_operand:SI 2 "arm_add_operand" "rIL")])
8549 (match_operator:SI 6 "arm_comparison_operator"
8550 [(match_operand:SI 4 "s_register_operand" "r")
8551 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8552 (clobber (reg:CC CC_REGNUM))]
8553 "TARGET_ARM
8554 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8555 != CCmode)"
8556 "#"
8557 "TARGET_ARM && reload_completed"
8558 [(set (match_dup 7)
8559 (compare
8560 (ior:SI
8561 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8562 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8563 (const_int 0)))
8564 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8565 "operands[7]
8566 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8567 DOM_CC_X_OR_Y),
601f584c 8568 CC_REGNUM);"
8569 [(set_attr "conds" "clob")
8570 (set_attr "length" "16")])
8571
8572; If the above pattern is followed by a CMP insn, then the compare is
8573; redundant, since we can rework the conditional instruction that follows.
8574(define_insn_and_split "*ior_scc_scc_cmp"
8575 [(set (match_operand 0 "dominant_cc_register" "")
8576 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8577 [(match_operand:SI 1 "s_register_operand" "r")
8578 (match_operand:SI 2 "arm_add_operand" "rIL")])
8579 (match_operator:SI 6 "arm_comparison_operator"
8580 [(match_operand:SI 4 "s_register_operand" "r")
8581 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8582 (const_int 0)))
8583 (set (match_operand:SI 7 "s_register_operand" "=r")
8584 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8585 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8586 "TARGET_ARM"
8587 "#"
8588 "TARGET_ARM && reload_completed"
8589 [(set (match_dup 0)
8590 (compare
8591 (ior:SI
8592 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8593 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8594 (const_int 0)))
8595 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8596 ""
8597 [(set_attr "conds" "set")
8598 (set_attr "length" "16")])
3c5afce6 8599
8600(define_insn_and_split "*and_scc_scc"
8601 [(set (match_operand:SI 0 "s_register_operand" "=r")
8602 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8603 [(match_operand:SI 1 "s_register_operand" "r")
8604 (match_operand:SI 2 "arm_add_operand" "rIL")])
8605 (match_operator:SI 6 "arm_comparison_operator"
8606 [(match_operand:SI 4 "s_register_operand" "r")
8607 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8608 (clobber (reg:CC CC_REGNUM))]
8609 "TARGET_ARM
8610 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8611 != CCmode)"
8612 "#"
601f584c 8613 "TARGET_ARM && reload_completed
8614 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8615 != CCmode)"
3c5afce6 8616 [(set (match_dup 7)
8617 (compare
8618 (and:SI
8619 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8620 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8621 (const_int 0)))
8622 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8623 "operands[7]
8624 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8625 DOM_CC_X_AND_Y),
601f584c 8626 CC_REGNUM);"
8627 [(set_attr "conds" "clob")
8628 (set_attr "length" "16")])
8629
8630; If the above pattern is followed by a CMP insn, then the compare is
8631; redundant, since we can rework the conditional instruction that follows.
8632(define_insn_and_split "*and_scc_scc_cmp"
8633 [(set (match_operand 0 "dominant_cc_register" "")
8634 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8635 [(match_operand:SI 1 "s_register_operand" "r")
8636 (match_operand:SI 2 "arm_add_operand" "rIL")])
8637 (match_operator:SI 6 "arm_comparison_operator"
8638 [(match_operand:SI 4 "s_register_operand" "r")
8639 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8640 (const_int 0)))
8641 (set (match_operand:SI 7 "s_register_operand" "=r")
8642 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8643 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8644 "TARGET_ARM"
8645 "#"
8646 "TARGET_ARM && reload_completed"
8647 [(set (match_dup 0)
8648 (compare
8649 (and:SI
8650 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8651 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8652 (const_int 0)))
8653 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8654 ""
8655 [(set_attr "conds" "set")
8656 (set_attr "length" "16")])
8657
8658;; If there is no dominance in the comparison, then we can still save an
8659;; instruction in the AND case, since we can know that the second compare
8660;; need only zero the value if false (if true, then the value is already
8661;; correct).
8662(define_insn_and_split "*and_scc_scc_nodom"
8663 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8664 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8665 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8666 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8667 (match_operator:SI 6 "arm_comparison_operator"
8668 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8669 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8670 (clobber (reg:CC CC_REGNUM))]
8671 "TARGET_ARM
8672 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8673 == CCmode)"
8674 "#"
8675 "TARGET_ARM && reload_completed"
8676 [(parallel [(set (match_dup 0)
8677 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8678 (clobber (reg:CC CC_REGNUM))])
8679 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8680 (set (match_dup 0)
8681 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8682 (match_dup 0)
8683 (const_int 0)))]
8684 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8685 operands[4], operands[5]),
8686 CC_REGNUM);
8687 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8688 operands[5]);"
8689 [(set_attr "conds" "clob")
8690 (set_attr "length" "20")])
3c5afce6 8691
3a0bdee0 8692(define_split
8693 [(set (reg:CC_NOOV CC_REGNUM)
8694 (compare:CC_NOOV (ior:SI
8695 (and:SI (match_operand:SI 0 "s_register_operand" "")
8696 (const_int 1))
8697 (match_operator:SI 1 "comparison_operator"
8698 [(match_operand:SI 2 "s_register_operand" "")
8699 (match_operand:SI 3 "arm_add_operand" "")]))
8700 (const_int 0)))
8701 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8702 "TARGET_ARM"
8703 [(set (match_dup 4)
8704 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8705 (match_dup 0)))
8706 (set (reg:CC_NOOV CC_REGNUM)
8707 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8708 (const_int 0)))]
8709 "")
8710
8711(define_split
8712 [(set (reg:CC_NOOV CC_REGNUM)
8713 (compare:CC_NOOV (ior:SI
8714 (match_operator:SI 1 "comparison_operator"
8715 [(match_operand:SI 2 "s_register_operand" "")
8716 (match_operand:SI 3 "arm_add_operand" "")])
8717 (and:SI (match_operand:SI 0 "s_register_operand" "")
8718 (const_int 1)))
8719 (const_int 0)))
8720 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8721 "TARGET_ARM"
8722 [(set (match_dup 4)
8723 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8724 (match_dup 0)))
8725 (set (reg:CC_NOOV CC_REGNUM)
8726 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8727 (const_int 0)))]
8728 "")
8729
f7fbdd4a 8730(define_insn "*negscc"
9c08d1fa 8731 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8732 (neg:SI (match_operator 3 "arm_comparison_operator"
9c08d1fa 8733 [(match_operand:SI 1 "s_register_operand" "r")
8734 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
bd5b4116 8735 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8736 "TARGET_ARM"
9c08d1fa 8737 "*
f0e75574 8738 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
e2348bcb 8739 return \"mov\\t%0, %1, asr #31\";
8740
9c08d1fa 8741 if (GET_CODE (operands[3]) == NE)
e2348bcb 8742 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8743
9c08d1fa 8744 if (GET_CODE (operands[3]) == GT)
e2348bcb 8745 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8746
8747 output_asm_insn (\"cmp\\t%1, %2\", operands);
8748 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8749 return \"mvn%d3\\t%0, #0\";
215b30b3 8750 "
8fa3ba89 8751 [(set_attr "conds" "clob")
8752 (set_attr "length" "12")]
8753)
9c08d1fa 8754
8755(define_insn "movcond"
8756 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 8757 (if_then_else:SI
8fa3ba89 8758 (match_operator 5 "arm_comparison_operator"
5565501b 8759 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8760 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8761 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8762 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
bd5b4116 8763 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8764 "TARGET_ARM"
9c08d1fa 8765 "*
8766 if (GET_CODE (operands[5]) == LT
8767 && (operands[4] == const0_rtx))
8768 {
5565501b 8769 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9c08d1fa 8770 {
9c08d1fa 8771 if (operands[2] == const0_rtx)
e2348bcb 8772 return \"and\\t%0, %1, %3, asr #31\";
8773 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9c08d1fa 8774 }
8775 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8776 {
9c08d1fa 8777 if (operands[1] == const0_rtx)
e2348bcb 8778 return \"bic\\t%0, %2, %3, asr #31\";
8779 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9c08d1fa 8780 }
8781 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8782 are constants. */
9c08d1fa 8783 }
e2348bcb 8784
9c08d1fa 8785 if (GET_CODE (operands[5]) == GE
8786 && (operands[4] == const0_rtx))
8787 {
8788 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8789 {
9c08d1fa 8790 if (operands[2] == const0_rtx)
e2348bcb 8791 return \"bic\\t%0, %1, %3, asr #31\";
8792 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9c08d1fa 8793 }
8794 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8795 {
9c08d1fa 8796 if (operands[1] == const0_rtx)
e2348bcb 8797 return \"and\\t%0, %2, %3, asr #31\";
8798 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9c08d1fa 8799 }
8800 /* The only case that falls through to here is when both ops 1 & 2
674a8f0b 8801 are constants. */
9c08d1fa 8802 }
8803 if (GET_CODE (operands[4]) == CONST_INT
8804 && !const_ok_for_arm (INTVAL (operands[4])))
e2348bcb 8805 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9c08d1fa 8806 else
e2348bcb 8807 output_asm_insn (\"cmp\\t%3, %4\", operands);
9c08d1fa 8808 if (which_alternative != 0)
e2348bcb 8809 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9c08d1fa 8810 if (which_alternative != 1)
e2348bcb 8811 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9c08d1fa 8812 return \"\";
215b30b3 8813 "
8fa3ba89 8814 [(set_attr "conds" "clob")
8815 (set_attr "length" "8,8,12")]
8816)
9c08d1fa 8817
8a18b90c 8818(define_insn "*ifcompare_plus_move"
8819 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8820 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8821 [(match_operand:SI 4 "s_register_operand" "r,r")
8822 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8823 (plus:SI
8824 (match_operand:SI 2 "s_register_operand" "r,r")
8825 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
129a2fe4 8826 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8827 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8828 "TARGET_ARM"
8a18b90c 8829 "#"
8fa3ba89 8830 [(set_attr "conds" "clob")
8831 (set_attr "length" "8,12")]
8832)
8a18b90c 8833
8834(define_insn "*if_plus_move"
129a2fe4 8835 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8836 (if_then_else:SI
8fa3ba89 8837 (match_operator 4 "arm_comparison_operator"
8a18b90c 8838 [(match_operand 5 "cc_register" "") (const_int 0)])
8839 (plus:SI
129a2fe4 8840 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8842 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
cffb2a26 8843 "TARGET_ARM"
8a18b90c 8844 "@
8845 add%d4\\t%0, %2, %3
8846 sub%d4\\t%0, %2, #%n3
8847 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
129a2fe4 8848 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8fa3ba89 8849 [(set_attr "conds" "use")
8850 (set_attr "length" "4,4,8,8")
8851 (set_attr "type" "*,*,*,*")]
8852)
8a18b90c 8853
8854(define_insn "*ifcompare_move_plus"
5565501b 8855 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8856 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8a18b90c 8857 [(match_operand:SI 4 "s_register_operand" "r,r")
8858 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8859 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 8860 (plus:SI
8861 (match_operand:SI 2 "s_register_operand" "r,r")
8862 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
bd5b4116 8863 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8864 "TARGET_ARM"
8a18b90c 8865 "#"
8fa3ba89 8866 [(set_attr "conds" "clob")
8867 (set_attr "length" "8,12")]
8868)
8a18b90c 8869
8870(define_insn "*if_move_plus"
129a2fe4 8871 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8a18b90c 8872 (if_then_else:SI
8fa3ba89 8873 (match_operator 4 "arm_comparison_operator"
8a18b90c 8874 [(match_operand 5 "cc_register" "") (const_int 0)])
129a2fe4 8875 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8a18b90c 8876 (plus:SI
129a2fe4 8877 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8878 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
cffb2a26 8879 "TARGET_ARM"
8a18b90c 8880 "@
8881 add%D4\\t%0, %2, %3
8882 sub%D4\\t%0, %2, #%n3
8883 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
129a2fe4 8884 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8fa3ba89 8885 [(set_attr "conds" "use")
8886 (set_attr "length" "4,4,8,8")
8887 (set_attr "type" "*,*,*,*")]
8888)
8a18b90c 8889
8890(define_insn "*ifcompare_arith_arith"
8891 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8892 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8a18b90c 8893 [(match_operand:SI 5 "s_register_operand" "r")
8894 (match_operand:SI 6 "arm_add_operand" "rIL")])
9c08d1fa 8895 (match_operator:SI 8 "shiftable_operator"
8a18b90c 8896 [(match_operand:SI 1 "s_register_operand" "r")
8897 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9c08d1fa 8898 (match_operator:SI 7 "shiftable_operator"
8a18b90c 8899 [(match_operand:SI 3 "s_register_operand" "r")
8900 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
bd5b4116 8901 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8902 "TARGET_ARM"
8a18b90c 8903 "#"
8fa3ba89 8904 [(set_attr "conds" "clob")
8905 (set_attr "length" "12")]
8906)
9c08d1fa 8907
8a18b90c 8908(define_insn "*if_arith_arith"
8909 [(set (match_operand:SI 0 "s_register_operand" "=r")
8fa3ba89 8910 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8a18b90c 8911 [(match_operand 8 "cc_register" "") (const_int 0)])
8912 (match_operator:SI 6 "shiftable_operator"
8913 [(match_operand:SI 1 "s_register_operand" "r")
8914 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8915 (match_operator:SI 7 "shiftable_operator"
8916 [(match_operand:SI 3 "s_register_operand" "r")
8917 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
cffb2a26 8918 "TARGET_ARM"
8a18b90c 8919 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8fa3ba89 8920 [(set_attr "conds" "use")
8921 (set_attr "length" "8")]
8922)
8a18b90c 8923
f7fbdd4a 8924(define_insn "*ifcompare_arith_move"
9c08d1fa 8925 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8926 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8927 [(match_operand:SI 2 "s_register_operand" "r,r")
5565501b 8928 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9c08d1fa 8929 (match_operator:SI 7 "shiftable_operator"
8930 [(match_operand:SI 4 "s_register_operand" "r,r")
8931 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
129a2fe4 8932 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
bd5b4116 8933 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8934 "TARGET_ARM"
9c08d1fa 8935 "*
9c08d1fa 8936 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8937 the conditional operator is LT or GE and we are comparing against zero and
674a8f0b 8938 everything is in registers then we can do this in two instructions. */
9c08d1fa 8939 if (operands[3] == const0_rtx
8940 && GET_CODE (operands[7]) != AND
8941 && GET_CODE (operands[5]) == REG
8942 && GET_CODE (operands[1]) == REG
8943 && REGNO (operands[1]) == REGNO (operands[4])
8944 && REGNO (operands[4]) != REGNO (operands[0]))
8945 {
8946 if (GET_CODE (operands[6]) == LT)
40dbec34 8947 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8948 else if (GET_CODE (operands[6]) == GE)
40dbec34 8949 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9c08d1fa 8950 }
8951 if (GET_CODE (operands[3]) == CONST_INT
8952 && !const_ok_for_arm (INTVAL (operands[3])))
e2348bcb 8953 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9c08d1fa 8954 else
e2348bcb 8955 output_asm_insn (\"cmp\\t%2, %3\", operands);
40dbec34 8956 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9c08d1fa 8957 if (which_alternative != 0)
129a2fe4 8958 return \"mov%D6\\t%0, %1\";
9c08d1fa 8959 return \"\";
215b30b3 8960 "
8fa3ba89 8961 [(set_attr "conds" "clob")
8962 (set_attr "length" "8,12")]
8963)
9c08d1fa 8964
8a18b90c 8965(define_insn "*if_arith_move"
129a2fe4 8966 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8967 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8a18b90c 8968 [(match_operand 6 "cc_register" "") (const_int 0)])
8969 (match_operator:SI 5 "shiftable_operator"
129a2fe4 8970 [(match_operand:SI 2 "s_register_operand" "r,r")
8971 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8972 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
cffb2a26 8973 "TARGET_ARM"
8a18b90c 8974 "@
8975 %I5%d4\\t%0, %2, %3
129a2fe4 8976 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8fa3ba89 8977 [(set_attr "conds" "use")
8978 (set_attr "length" "4,8")
8979 (set_attr "type" "*,*")]
8980)
8a18b90c 8981
f7fbdd4a 8982(define_insn "*ifcompare_move_arith"
9c08d1fa 8983 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 8984 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9c08d1fa 8985 [(match_operand:SI 4 "s_register_operand" "r,r")
5565501b 8986 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
129a2fe4 8987 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9c08d1fa 8988 (match_operator:SI 7 "shiftable_operator"
8989 [(match_operand:SI 2 "s_register_operand" "r,r")
8990 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
bd5b4116 8991 (clobber (reg:CC CC_REGNUM))]
cffb2a26 8992 "TARGET_ARM"
9c08d1fa 8993 "*
9c08d1fa 8994 /* If we have an operation where (op x 0) is the identity operation and
01cc3b75 8995 the conditional operator is LT or GE and we are comparing against zero and
9c08d1fa 8996 everything is in registers then we can do this in two instructions */
8997 if (operands[5] == const0_rtx
8998 && GET_CODE (operands[7]) != AND
8999 && GET_CODE (operands[3]) == REG
9000 && GET_CODE (operands[1]) == REG
9001 && REGNO (operands[1]) == REGNO (operands[2])
9002 && REGNO (operands[2]) != REGNO (operands[0]))
9003 {
9004 if (GET_CODE (operands[6]) == GE)
40dbec34 9005 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9006 else if (GET_CODE (operands[6]) == LT)
40dbec34 9007 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9c08d1fa 9008 }
40dbec34 9009
9c08d1fa 9010 if (GET_CODE (operands[5]) == CONST_INT
9011 && !const_ok_for_arm (INTVAL (operands[5])))
e2348bcb 9012 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9c08d1fa 9013 else
e2348bcb 9014 output_asm_insn (\"cmp\\t%4, %5\", operands);
40dbec34 9015
9c08d1fa 9016 if (which_alternative != 0)
129a2fe4 9017 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
40dbec34 9018 return \"%I7%D6\\t%0, %2, %3\";
215b30b3 9019 "
8fa3ba89 9020 [(set_attr "conds" "clob")
9021 (set_attr "length" "8,12")]
9022)
9c08d1fa 9023
8a18b90c 9024(define_insn "*if_move_arith"
129a2fe4 9025 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9026 (if_then_else:SI
8fa3ba89 9027 (match_operator 4 "arm_comparison_operator"
8a18b90c 9028 [(match_operand 6 "cc_register" "") (const_int 0)])
129a2fe4 9029 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8a18b90c 9030 (match_operator:SI 5 "shiftable_operator"
129a2fe4 9031 [(match_operand:SI 2 "s_register_operand" "r,r")
9032 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
cffb2a26 9033 "TARGET_ARM"
8a18b90c 9034 "@
9035 %I5%D4\\t%0, %2, %3
129a2fe4 9036 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8fa3ba89 9037 [(set_attr "conds" "use")
9038 (set_attr "length" "4,8")
9039 (set_attr "type" "*,*")]
9040)
8a18b90c 9041
9042(define_insn "*ifcompare_move_not"
9c08d1fa 9043 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9044 (if_then_else:SI
8fa3ba89 9045 (match_operator 5 "arm_comparison_operator"
8a18b90c 9046 [(match_operand:SI 3 "s_register_operand" "r,r")
9047 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9048 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9049 (not:SI
9050 (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9051 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9052 "TARGET_ARM"
8a18b90c 9053 "#"
8fa3ba89 9054 [(set_attr "conds" "clob")
9055 (set_attr "length" "8,12")]
9056)
9c08d1fa 9057
8a18b90c 9058(define_insn "*if_move_not"
9059 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9060 (if_then_else:SI
8fa3ba89 9061 (match_operator 4 "arm_comparison_operator"
8a18b90c 9062 [(match_operand 3 "cc_register" "") (const_int 0)])
9063 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9064 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9065 "TARGET_ARM"
8a18b90c 9066 "@
9067 mvn%D4\\t%0, %2
9068 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9069 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8fa3ba89 9070 [(set_attr "conds" "use")
9071 (set_attr "length" "4,8,8")]
9072)
8a18b90c 9073
9074(define_insn "*ifcompare_not_move"
9c08d1fa 9075 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9076 (if_then_else:SI
8fa3ba89 9077 (match_operator 5 "arm_comparison_operator"
8a18b90c 9078 [(match_operand:SI 3 "s_register_operand" "r,r")
9079 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9080 (not:SI
9081 (match_operand:SI 2 "s_register_operand" "r,r"))
9082 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9083 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9084 "TARGET_ARM"
8a18b90c 9085 "#"
8fa3ba89 9086 [(set_attr "conds" "clob")
9087 (set_attr "length" "8,12")]
9088)
9c08d1fa 9089
8a18b90c 9090(define_insn "*if_not_move"
9091 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9092 (if_then_else:SI
8fa3ba89 9093 (match_operator 4 "arm_comparison_operator"
8a18b90c 9094 [(match_operand 3 "cc_register" "") (const_int 0)])
9095 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9096 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9097 "TARGET_ARM"
8a18b90c 9098 "@
9099 mvn%d4\\t%0, %2
9100 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9101 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8fa3ba89 9102 [(set_attr "conds" "use")
9103 (set_attr "length" "4,8,8")]
9104)
8a18b90c 9105
9106(define_insn "*ifcompare_shift_move"
9c08d1fa 9107 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8a18b90c 9108 (if_then_else:SI
8fa3ba89 9109 (match_operator 6 "arm_comparison_operator"
8a18b90c 9110 [(match_operand:SI 4 "s_register_operand" "r,r")
9111 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9112 (match_operator:SI 7 "shift_operator"
9113 [(match_operand:SI 2 "s_register_operand" "r,r")
9114 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9115 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9116 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9117 "TARGET_ARM"
9c08d1fa 9118 "#"
8fa3ba89 9119 [(set_attr "conds" "clob")
9120 (set_attr "length" "8,12")]
9121)
9c08d1fa 9122
8a18b90c 9123(define_insn "*if_shift_move"
9124 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9125 (if_then_else:SI
8fa3ba89 9126 (match_operator 5 "arm_comparison_operator"
8a18b90c 9127 [(match_operand 6 "cc_register" "") (const_int 0)])
9128 (match_operator:SI 4 "shift_operator"
9129 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9130 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9131 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9132 "TARGET_ARM"
5565501b 9133 "@
8a18b90c 9134 mov%d5\\t%0, %2%S4
9135 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9136 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8fa3ba89 9137 [(set_attr "conds" "use")
331beb1a 9138 (set_attr "shift" "2")
a2cd141b 9139 (set_attr "length" "4,8,8")
9140 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9141 (const_string "alu_shift")
9142 (const_string "alu_shift_reg")))]
8fa3ba89 9143)
5565501b 9144
8a18b90c 9145(define_insn "*ifcompare_move_shift"
9146 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9147 (if_then_else:SI
8fa3ba89 9148 (match_operator 6 "arm_comparison_operator"
8a18b90c 9149 [(match_operand:SI 4 "s_register_operand" "r,r")
9150 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9151 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5565501b 9152 (match_operator:SI 7 "shift_operator"
8a18b90c 9153 [(match_operand:SI 2 "s_register_operand" "r,r")
9154 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
bd5b4116 9155 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9156 "TARGET_ARM"
8a18b90c 9157 "#"
8fa3ba89 9158 [(set_attr "conds" "clob")
9159 (set_attr "length" "8,12")]
9160)
5565501b 9161
8a18b90c 9162(define_insn "*if_move_shift"
9163 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5565501b 9164 (if_then_else:SI
8fa3ba89 9165 (match_operator 5 "arm_comparison_operator"
8a18b90c 9166 [(match_operand 6 "cc_register" "") (const_int 0)])
9167 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9168 (match_operator:SI 4 "shift_operator"
9169 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9170 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
cffb2a26 9171 "TARGET_ARM"
5565501b 9172 "@
8a18b90c 9173 mov%D5\\t%0, %2%S4
9174 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9175 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8fa3ba89 9176 [(set_attr "conds" "use")
331beb1a 9177 (set_attr "shift" "2")
a2cd141b 9178 (set_attr "length" "4,8,8")
9179 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9180 (const_string "alu_shift")
9181 (const_string "alu_shift_reg")))]
8fa3ba89 9182)
9c08d1fa 9183
f7fbdd4a 9184(define_insn "*ifcompare_shift_shift"
8a18b90c 9185 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9186 (if_then_else:SI
8fa3ba89 9187 (match_operator 7 "arm_comparison_operator"
8a18b90c 9188 [(match_operand:SI 5 "s_register_operand" "r")
9189 (match_operand:SI 6 "arm_add_operand" "rIL")])
5565501b 9190 (match_operator:SI 8 "shift_operator"
8a18b90c 9191 [(match_operand:SI 1 "s_register_operand" "r")
9192 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5565501b 9193 (match_operator:SI 9 "shift_operator"
8a18b90c 9194 [(match_operand:SI 3 "s_register_operand" "r")
9195 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
bd5b4116 9196 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9197 "TARGET_ARM"
8a18b90c 9198 "#"
8fa3ba89 9199 [(set_attr "conds" "clob")
9200 (set_attr "length" "12")]
9201)
9c08d1fa 9202
8a18b90c 9203(define_insn "*if_shift_shift"
9204 [(set (match_operand:SI 0 "s_register_operand" "=r")
9205 (if_then_else:SI
8fa3ba89 9206 (match_operator 5 "arm_comparison_operator"
8a18b90c 9207 [(match_operand 8 "cc_register" "") (const_int 0)])
9208 (match_operator:SI 6 "shift_operator"
9209 [(match_operand:SI 1 "s_register_operand" "r")
9210 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9211 (match_operator:SI 7 "shift_operator"
9212 [(match_operand:SI 3 "s_register_operand" "r")
9213 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
cffb2a26 9214 "TARGET_ARM"
8a18b90c 9215 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8fa3ba89 9216 [(set_attr "conds" "use")
331beb1a 9217 (set_attr "shift" "1")
a2cd141b 9218 (set_attr "length" "8")
9219 (set (attr "type") (if_then_else
9220 (and (match_operand 2 "const_int_operand" "")
9221 (match_operand 4 "const_int_operand" ""))
9222 (const_string "alu_shift")
9223 (const_string "alu_shift_reg")))]
8fa3ba89 9224)
8a18b90c 9225
f7fbdd4a 9226(define_insn "*ifcompare_not_arith"
8a18b90c 9227 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9228 (if_then_else:SI
8fa3ba89 9229 (match_operator 6 "arm_comparison_operator"
8a18b90c 9230 [(match_operand:SI 4 "s_register_operand" "r")
9231 (match_operand:SI 5 "arm_add_operand" "rIL")])
9232 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5565501b 9233 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9234 [(match_operand:SI 2 "s_register_operand" "r")
9235 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
bd5b4116 9236 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9237 "TARGET_ARM"
8a18b90c 9238 "#"
8fa3ba89 9239 [(set_attr "conds" "clob")
9240 (set_attr "length" "12")]
9241)
9c08d1fa 9242
8a18b90c 9243(define_insn "*if_not_arith"
9244 [(set (match_operand:SI 0 "s_register_operand" "=r")
9245 (if_then_else:SI
8fa3ba89 9246 (match_operator 5 "arm_comparison_operator"
8a18b90c 9247 [(match_operand 4 "cc_register" "") (const_int 0)])
9248 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9249 (match_operator:SI 6 "shiftable_operator"
9250 [(match_operand:SI 2 "s_register_operand" "r")
9251 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
cffb2a26 9252 "TARGET_ARM"
8a18b90c 9253 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8fa3ba89 9254 [(set_attr "conds" "use")
9255 (set_attr "length" "8")]
9256)
8a18b90c 9257
9258(define_insn "*ifcompare_arith_not"
9259 [(set (match_operand:SI 0 "s_register_operand" "=r")
5565501b 9260 (if_then_else:SI
8fa3ba89 9261 (match_operator 6 "arm_comparison_operator"
8a18b90c 9262 [(match_operand:SI 4 "s_register_operand" "r")
9263 (match_operand:SI 5 "arm_add_operand" "rIL")])
5565501b 9264 (match_operator:SI 7 "shiftable_operator"
8a18b90c 9265 [(match_operand:SI 2 "s_register_operand" "r")
9266 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9267 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
bd5b4116 9268 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9269 "TARGET_ARM"
8a18b90c 9270 "#"
8fa3ba89 9271 [(set_attr "conds" "clob")
9272 (set_attr "length" "12")]
9273)
9c08d1fa 9274
8a18b90c 9275(define_insn "*if_arith_not"
9276 [(set (match_operand:SI 0 "s_register_operand" "=r")
9277 (if_then_else:SI
8fa3ba89 9278 (match_operator 5 "arm_comparison_operator"
8a18b90c 9279 [(match_operand 4 "cc_register" "") (const_int 0)])
9280 (match_operator:SI 6 "shiftable_operator"
9281 [(match_operand:SI 2 "s_register_operand" "r")
9282 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9283 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
cffb2a26 9284 "TARGET_ARM"
8a18b90c 9285 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8fa3ba89 9286 [(set_attr "conds" "use")
9287 (set_attr "length" "8")]
9288)
8a18b90c 9289
f7fbdd4a 9290(define_insn "*ifcompare_neg_move"
8a18b90c 9291 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9292 (if_then_else:SI
8fa3ba89 9293 (match_operator 5 "arm_comparison_operator"
8a18b90c 9294 [(match_operand:SI 3 "s_register_operand" "r,r")
9295 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9296 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9297 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
bd5b4116 9298 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9299 "TARGET_ARM"
8a18b90c 9300 "#"
8fa3ba89 9301 [(set_attr "conds" "clob")
9302 (set_attr "length" "8,12")]
9303)
8a18b90c 9304
9305(define_insn "*if_neg_move"
9306 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9307 (if_then_else:SI
8fa3ba89 9308 (match_operator 4 "arm_comparison_operator"
8a18b90c 9309 [(match_operand 3 "cc_register" "") (const_int 0)])
9310 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9311 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
cffb2a26 9312 "TARGET_ARM"
8a18b90c 9313 "@
9314 rsb%d4\\t%0, %2, #0
9315 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9316 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8fa3ba89 9317 [(set_attr "conds" "use")
9318 (set_attr "length" "4,8,8")]
9319)
9c08d1fa 9320
f7fbdd4a 9321(define_insn "*ifcompare_move_neg"
8a18b90c 9322 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565501b 9323 (if_then_else:SI
8fa3ba89 9324 (match_operator 5 "arm_comparison_operator"
8a18b90c 9325 [(match_operand:SI 3 "s_register_operand" "r,r")
9326 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9327 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9328 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
bd5b4116 9329 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9330 "TARGET_ARM"
8a18b90c 9331 "#"
8fa3ba89 9332 [(set_attr "conds" "clob")
9333 (set_attr "length" "8,12")]
9334)
8a18b90c 9335
9336(define_insn "*if_move_neg"
9337 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9338 (if_then_else:SI
8fa3ba89 9339 (match_operator 4 "arm_comparison_operator"
8a18b90c 9340 [(match_operand 3 "cc_register" "") (const_int 0)])
9341 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9342 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
cffb2a26 9343 "TARGET_ARM"
8a18b90c 9344 "@
9345 rsb%D4\\t%0, %2, #0
9346 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9347 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
0d66636f 9348 [(set_attr "conds" "use")
9349 (set_attr "length" "4,8,8")]
9350)
9c08d1fa 9351
f7fbdd4a 9352(define_insn "*arith_adjacentmem"
9c08d1fa 9353 [(set (match_operand:SI 0 "s_register_operand" "=r")
9354 (match_operator:SI 1 "shiftable_operator"
9355 [(match_operand:SI 2 "memory_operand" "m")
9356 (match_operand:SI 3 "memory_operand" "m")]))
9357 (clobber (match_scratch:SI 4 "=r"))]
cffb2a26 9358 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9c08d1fa 9359 "*
215b30b3 9360 {
9361 rtx ldm[3];
9362 rtx arith[4];
94dee231 9363 rtx base_reg;
9364 HOST_WIDE_INT val1 = 0, val2 = 0;
9c08d1fa 9365
215b30b3 9366 if (REGNO (operands[0]) > REGNO (operands[4]))
9367 {
9368 ldm[1] = operands[4];
9369 ldm[2] = operands[0];
9370 }
9371 else
9372 {
9373 ldm[1] = operands[0];
9374 ldm[2] = operands[4];
9375 }
94dee231 9376
9377 base_reg = XEXP (operands[2], 0);
9378
9379 if (!REG_P (base_reg))
9380 {
9381 val1 = INTVAL (XEXP (base_reg, 1));
9382 base_reg = XEXP (base_reg, 0);
9383 }
9384
9385 if (!REG_P (XEXP (operands[3], 0)))
215b30b3 9386 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
94dee231 9387
215b30b3 9388 arith[0] = operands[0];
9389 arith[3] = operands[1];
94dee231 9390
215b30b3 9391 if (val1 < val2)
9392 {
9393 arith[1] = ldm[1];
9394 arith[2] = ldm[2];
9395 }
9396 else
9397 {
9398 arith[1] = ldm[2];
9399 arith[2] = ldm[1];
9400 }
94dee231 9401
9402 ldm[0] = base_reg;
9403 if (val1 !=0 && val2 != 0)
215b30b3 9404 {
94dee231 9405 if (val1 == 4 || val2 == 4)
9406 /* Other val must be 8, since we know they are adjacent and neither
9407 is zero. */
9408 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
215b30b3 9409 else
94dee231 9410 {
9411 rtx ops[3];
9412
9413 ldm[0] = ops[0] = operands[4];
9414 ops[1] = base_reg;
9415 ops[2] = GEN_INT (val1);
9416 output_add_immediate (ops);
9417 if (val1 < val2)
9418 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9419 else
9420 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9421 }
215b30b3 9422 }
94dee231 9423 else if (val1 != 0)
215b30b3 9424 {
215b30b3 9425 if (val1 < val2)
9426 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9427 else
9428 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9429 }
9430 else
9431 {
215b30b3 9432 if (val1 < val2)
9433 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9434 else
9435 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9436 }
9437 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9438 return \"\";
9439 }"
9440 [(set_attr "length" "12")
9441 (set_attr "predicable" "yes")
a2cd141b 9442 (set_attr "type" "load1")]
215b30b3 9443)
9c08d1fa 9444
9c08d1fa 9445; This pattern is never tried by combine, so do it as a peephole
9446
a0f94409 9447(define_peephole2
372575c7 9448 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9449 (match_operand:SI 1 "arm_general_register_operand" ""))
bd5b4116 9450 (set (reg:CC CC_REGNUM)
aea4c774 9451 (compare:CC (match_dup 1) (const_int 0)))]
372575c7 9452 "TARGET_ARM"
a0f94409 9453 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9454 (set (match_dup 0) (match_dup 1))])]
9455 ""
0d66636f 9456)
9c08d1fa 9457
675d848d 9458; Peepholes to spot possible load- and store-multiples, if the ordering is
9459; reversed, check that the memory references aren't volatile.
9c08d1fa 9460
9461(define_peephole
9462 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9463 (match_operand:SI 4 "memory_operand" "m"))
9464 (set (match_operand:SI 1 "s_register_operand" "=r")
9465 (match_operand:SI 5 "memory_operand" "m"))
9c08d1fa 9466 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9467 (match_operand:SI 6 "memory_operand" "m"))
9c08d1fa 9468 (set (match_operand:SI 3 "s_register_operand" "=r")
aea4c774 9469 (match_operand:SI 7 "memory_operand" "m"))]
cffb2a26 9470 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9471 "*
9472 return emit_ldm_seq (operands, 4);
215b30b3 9473 "
9474)
9c08d1fa 9475
9476(define_peephole
9477 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9478 (match_operand:SI 3 "memory_operand" "m"))
9479 (set (match_operand:SI 1 "s_register_operand" "=r")
9480 (match_operand:SI 4 "memory_operand" "m"))
9c08d1fa 9481 (set (match_operand:SI 2 "s_register_operand" "=r")
aea4c774 9482 (match_operand:SI 5 "memory_operand" "m"))]
cffb2a26 9483 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9484 "*
9485 return emit_ldm_seq (operands, 3);
215b30b3 9486 "
9487)
9c08d1fa 9488
9489(define_peephole
9490 [(set (match_operand:SI 0 "s_register_operand" "=r")
aea4c774 9491 (match_operand:SI 2 "memory_operand" "m"))
9492 (set (match_operand:SI 1 "s_register_operand" "=r")
9493 (match_operand:SI 3 "memory_operand" "m"))]
cffb2a26 9494 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9495 "*
9496 return emit_ldm_seq (operands, 2);
215b30b3 9497 "
9498)
9c08d1fa 9499
9500(define_peephole
aea4c774 9501 [(set (match_operand:SI 4 "memory_operand" "=m")
9c08d1fa 9502 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9503 (set (match_operand:SI 5 "memory_operand" "=m")
9504 (match_operand:SI 1 "s_register_operand" "r"))
9505 (set (match_operand:SI 6 "memory_operand" "=m")
9c08d1fa 9506 (match_operand:SI 2 "s_register_operand" "r"))
aea4c774 9507 (set (match_operand:SI 7 "memory_operand" "=m")
9508 (match_operand:SI 3 "s_register_operand" "r"))]
cffb2a26 9509 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
aea4c774 9510 "*
9511 return emit_stm_seq (operands, 4);
215b30b3 9512 "
9513)
9c08d1fa 9514
9515(define_peephole
aea4c774 9516 [(set (match_operand:SI 3 "memory_operand" "=m")
9c08d1fa 9517 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9518 (set (match_operand:SI 4 "memory_operand" "=m")
9519 (match_operand:SI 1 "s_register_operand" "r"))
9520 (set (match_operand:SI 5 "memory_operand" "=m")
9521 (match_operand:SI 2 "s_register_operand" "r"))]
cffb2a26 9522 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
aea4c774 9523 "*
9524 return emit_stm_seq (operands, 3);
215b30b3 9525 "
9526)
9c08d1fa 9527
9528(define_peephole
aea4c774 9529 [(set (match_operand:SI 2 "memory_operand" "=m")
9c08d1fa 9530 (match_operand:SI 0 "s_register_operand" "r"))
aea4c774 9531 (set (match_operand:SI 3 "memory_operand" "=m")
9532 (match_operand:SI 1 "s_register_operand" "r"))]
cffb2a26 9533 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
aea4c774 9534 "*
9535 return emit_stm_seq (operands, 2);
215b30b3 9536 "
9537)
9c08d1fa 9538
9c08d1fa 9539(define_split
9540 [(set (match_operand:SI 0 "s_register_operand" "")
9541 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9542 (const_int 0))
8fa3ba89 9543 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9c08d1fa 9544 [(match_operand:SI 3 "s_register_operand" "")
9545 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9546 (clobber (match_operand:SI 5 "s_register_operand" ""))]
cffb2a26 9547 "TARGET_ARM"
9c08d1fa 9548 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9549 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9550 (match_dup 5)))]
215b30b3 9551 ""
9552)
9c08d1fa 9553
aea4c774 9554;; This split can be used because CC_Z mode implies that the following
9555;; branch will be an equality, or an unsigned inequality, so the sign
9556;; extension is not needed.
9c08d1fa 9557
aea4c774 9558(define_split
bd5b4116 9559 [(set (reg:CC_Z CC_REGNUM)
aea4c774 9560 (compare:CC_Z
9561 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9c08d1fa 9562 (const_int 24))
aea4c774 9563 (match_operand 1 "const_int_operand" "")))
9564 (clobber (match_scratch:SI 2 ""))]
cffb2a26 9565 "TARGET_ARM
9566 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9567 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
aea4c774 9568 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
bd5b4116 9569 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
aea4c774 9570 "
9c08d1fa 9571 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
215b30b3 9572 "
9573)
9c08d1fa 9574
87b22bf7 9575(define_expand "prologue"
9576 [(clobber (const_int 0))]
cffb2a26 9577 "TARGET_EITHER"
9578 "if (TARGET_ARM)
9579 arm_expand_prologue ();
9580 else
9581 thumb_expand_prologue ();
87b22bf7 9582 DONE;
cffb2a26 9583 "
9584)
87b22bf7 9585
56d27660 9586(define_expand "epilogue"
4c44712e 9587 [(clobber (const_int 0))]
cffb2a26 9588 "TARGET_EITHER"
56d27660 9589 "
4c44712e 9590 if (current_function_calls_eh_return)
9591 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
cffb2a26 9592 if (TARGET_THUMB)
9593 thumb_expand_epilogue ();
9594 else if (USE_RETURN_INSN (FALSE))
56d27660 9595 {
9596 emit_jump_insn (gen_return ());
9597 DONE;
9598 }
cffb2a26 9599 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9600 gen_rtvec (1,
9601 gen_rtx_RETURN (VOIDmode)),
e1159bbe 9602 VUNSPEC_EPILOGUE));
cffb2a26 9603 DONE;
9604 "
9605)
56d27660 9606
ef5651d0 9607;; Note - although unspec_volatile's USE all hard registers,
9608;; USEs are ignored after relaod has completed. Thus we need
9609;; to add an unspec of the link register to ensure that flow
9610;; does not think that it is unused by the sibcall branch that
9611;; will replace the standard function epilogue.
1c494086 9612(define_insn "sibcall_epilogue"
ef5651d0 9613 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9614 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
1c494086 9615 "TARGET_ARM"
9616 "*
ffc9d00c 9617 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
5db468b7 9618 return output_return_instruction (const_true_rtx, FALSE, FALSE);
ffc9d00c 9619 return arm_output_epilogue (next_nonnote_insn (insn));
1c494086 9620 "
9621;; Length is absolute worst case
9622 [(set_attr "length" "44")
defc47cf 9623 (set_attr "type" "block")
9624 ;; We don't clobber the conditions, but the potential length of this
9625 ;; operation is sufficient to make conditionalizing the sequence
9626 ;; unlikely to be profitable.
9627 (set_attr "conds" "clob")]
1c494086 9628)
9629
cffb2a26 9630(define_insn "*epilogue_insns"
e1159bbe 9631 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
cffb2a26 9632 "TARGET_EITHER"
56d27660 9633 "*
cffb2a26 9634 if (TARGET_ARM)
ffc9d00c 9635 return arm_output_epilogue (NULL);
cffb2a26 9636 else /* TARGET_THUMB */
9637 return thumb_unexpanded_epilogue ();
9638 "
215b30b3 9639 ; Length is absolute worst case
cffb2a26 9640 [(set_attr "length" "44")
defc47cf 9641 (set_attr "type" "block")
9642 ;; We don't clobber the conditions, but the potential length of this
9643 ;; operation is sufficient to make conditionalizing the sequence
9644 ;; unlikely to be profitable.
9645 (set_attr "conds" "clob")]
cffb2a26 9646)
9647
9648(define_expand "eh_epilogue"
7db9af5d 9649 [(use (match_operand:SI 0 "register_operand" ""))
9650 (use (match_operand:SI 1 "register_operand" ""))
9651 (use (match_operand:SI 2 "register_operand" ""))]
cffb2a26 9652 "TARGET_EITHER"
9653 "
215b30b3 9654 {
9655 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9656 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9657 {
9658 rtx ra = gen_rtx_REG (Pmode, 2);
9659
9660 emit_move_insn (ra, operands[2]);
9661 operands[2] = ra;
9662 }
5cf3595a 9663 /* This is a hack -- we may have crystalized the function type too
9664 early. */
9665 cfun->machine->func_type = 0;
215b30b3 9666 }"
9667)
56d27660 9668
9c08d1fa 9669;; This split is only used during output to reduce the number of patterns
9670;; that need assembler instructions adding to them. We allowed the setting
9671;; of the conditions to be implicit during rtl generation so that
9672;; the conditional compare patterns would work. However this conflicts to
8a18b90c 9673;; some extent with the conditional data operations, so we have to split them
9c08d1fa 9674;; up again here.
9675
9676(define_split
9677 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 9678 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9679 [(match_operand 2 "" "") (match_operand 3 "" "")])
9680 (match_dup 0)
9681 (match_operand 4 "" "")))
bd5b4116 9682 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9683 "TARGET_ARM && reload_completed"
8fa3ba89 9684 [(set (match_dup 5) (match_dup 6))
9685 (cond_exec (match_dup 7)
9686 (set (match_dup 0) (match_dup 4)))]
9687 "
9688 {
9689 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9690 operands[2], operands[3]);
9691 enum rtx_code rc = GET_CODE (operands[1]);
9692
bd5b4116 9693 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9694 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9695 if (mode == CCFPmode || mode == CCFPEmode)
9696 rc = reverse_condition_maybe_unordered (rc);
9697 else
9698 rc = reverse_condition (rc);
9699
9700 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9701 }"
9702)
9703
9704(define_split
9705 [(set (match_operand:SI 0 "s_register_operand" "")
9706 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9707 [(match_operand 2 "" "") (match_operand 3 "" "")])
9708 (match_operand 4 "" "")
9709 (match_dup 0)))
bd5b4116 9710 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9711 "TARGET_ARM && reload_completed"
8fa3ba89 9712 [(set (match_dup 5) (match_dup 6))
9713 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9714 (set (match_dup 0) (match_dup 4)))]
9715 "
9716 {
9717 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9718 operands[2], operands[3]);
9719
bd5b4116 9720 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9721 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9722 }"
9723)
9724
9725(define_split
9726 [(set (match_operand:SI 0 "s_register_operand" "")
9727 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9c08d1fa 9728 [(match_operand 2 "" "") (match_operand 3 "" "")])
9729 (match_operand 4 "" "")
9730 (match_operand 5 "" "")))
bd5b4116 9731 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9732 "TARGET_ARM && reload_completed"
8fa3ba89 9733 [(set (match_dup 6) (match_dup 7))
9734 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9735 (set (match_dup 0) (match_dup 4)))
9736 (cond_exec (match_dup 8)
9737 (set (match_dup 0) (match_dup 5)))]
9738 "
9739 {
9740 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9741 operands[2], operands[3]);
9742 enum rtx_code rc = GET_CODE (operands[1]);
9743
bd5b4116 9744 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8fa3ba89 9745 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9746 if (mode == CCFPmode || mode == CCFPEmode)
9747 rc = reverse_condition_maybe_unordered (rc);
9748 else
9749 rc = reverse_condition (rc);
9750
9751 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9752 }"
9753)
9754
cffb2a26 9755(define_split
9756 [(set (match_operand:SI 0 "s_register_operand" "")
8fa3ba89 9757 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
cffb2a26 9758 [(match_operand:SI 2 "s_register_operand" "")
9759 (match_operand:SI 3 "arm_add_operand" "")])
9760 (match_operand:SI 4 "arm_rhs_operand" "")
9761 (not:SI
9762 (match_operand:SI 5 "s_register_operand" ""))))
bd5b4116 9763 (clobber (reg:CC CC_REGNUM))]
ac8b093b 9764 "TARGET_ARM && reload_completed"
cffb2a26 9765 [(set (match_dup 6) (match_dup 7))
f6c53574 9766 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9767 (set (match_dup 0) (match_dup 4)))
9768 (cond_exec (match_dup 8)
9769 (set (match_dup 0) (not:SI (match_dup 5))))]
cffb2a26 9770 "
215b30b3 9771 {
9772 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9773 operands[2], operands[3]);
f6c53574 9774 enum rtx_code rc = GET_CODE (operands[1]);
cffb2a26 9775
bd5b4116 9776 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
1a83b3ff 9777 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
f6c53574 9778 if (mode == CCFPmode || mode == CCFPEmode)
9779 rc = reverse_condition_maybe_unordered (rc);
9780 else
9781 rc = reverse_condition (rc);
9782
9783 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
215b30b3 9784 }"
9785)
cffb2a26 9786
9787(define_insn "*cond_move_not"
9788 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8fa3ba89 9789 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
cffb2a26 9790 [(match_operand 3 "cc_register" "") (const_int 0)])
9791 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9792 (not:SI
9793 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9794 "TARGET_ARM"
9795 "@
9796 mvn%D4\\t%0, %2
9797 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
0d66636f 9798 [(set_attr "conds" "use")
9799 (set_attr "length" "4,8")]
9800)
cffb2a26 9801
9c08d1fa 9802;; The next two patterns occur when an AND operation is followed by a
9803;; scc insn sequence
9804
f7fbdd4a 9805(define_insn "*sign_extract_onebit"
9c08d1fa 9806 [(set (match_operand:SI 0 "s_register_operand" "=r")
9807 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9808 (const_int 1)
ed750274 9809 (match_operand:SI 2 "const_int_operand" "n")))
9810 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9811 "TARGET_ARM"
9c08d1fa 9812 "*
0d66636f 9813 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9814 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9815 return \"mvnne\\t%0, #0\";
9816 "
9817 [(set_attr "conds" "clob")
9818 (set_attr "length" "8")]
9819)
9c08d1fa 9820
f7fbdd4a 9821(define_insn "*not_signextract_onebit"
9c08d1fa 9822 [(set (match_operand:SI 0 "s_register_operand" "=r")
9823 (not:SI
9824 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9825 (const_int 1)
ed750274 9826 (match_operand:SI 2 "const_int_operand" "n"))))
9827 (clobber (reg:CC CC_REGNUM))]
cffb2a26 9828 "TARGET_ARM"
9c08d1fa 9829 "*
0d66636f 9830 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9831 output_asm_insn (\"tst\\t%1, %2\", operands);
9832 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9833 return \"movne\\t%0, #0\";
9834 "
9835 [(set_attr "conds" "clob")
9836 (set_attr "length" "12")]
9837)
87b22bf7 9838
0d66636f 9839;; Push multiple registers to the stack. Registers are in parallel (use ...)
9840;; expressions. For simplicity, the first register is also in the unspec
9841;; part.
f7fbdd4a 9842(define_insn "*push_multi"
87b22bf7 9843 [(match_parallel 2 "multi_register_push"
9844 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 9845 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9846 UNSPEC_PUSH_MULT))])]
cffb2a26 9847 "TARGET_ARM"
87b22bf7 9848 "*
215b30b3 9849 {
9850 int num_saves = XVECLEN (operands[2], 0);
ed593f11 9851
215b30b3 9852 /* For the StrongARM at least it is faster to
9853 use STR to store only a single register. */
6079f055 9854 if (num_saves == 1)
215b30b3 9855 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9856 else
9857 {
9858 int i;
9859 char pattern[100];
ed593f11 9860
215b30b3 9861 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9862
6079f055 9863 for (i = 1; i < num_saves; i++)
215b30b3 9864 {
9865 strcat (pattern, \", %|\");
9866 strcat (pattern,
9867 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9868 }
9869
9870 strcat (pattern, \"}\");
9871 output_asm_insn (pattern, operands);
9872 }
9873
9874 return \"\";
9875 }"
9876 [(set_attr "type" "store4")]
9877)
f7fbdd4a 9878
4c58c898 9879(define_insn "stack_tie"
9880 [(set (mem:BLK (scratch))
9881 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9882 (match_operand:SI 1 "s_register_operand" "r")]
9883 UNSPEC_PRLG_STK))]
9884 ""
9885 ""
9886 [(set_attr "length" "0")]
9887)
9888
3398e91d 9889;; Similarly for the floating point registers
7b1d2fc4 9890(define_insn "*push_fp_multi"
9891 [(match_parallel 2 "multi_register_push"
9892 [(set (match_operand:BLK 0 "memory_operand" "=m")
e1159bbe 9893 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9894 UNSPEC_PUSH_MULT))])]
a2cd141b 9895 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7b1d2fc4 9896 "*
215b30b3 9897 {
9898 char pattern[100];
7b1d2fc4 9899
215b30b3 9900 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9901 output_asm_insn (pattern, operands);
9902 return \"\";
9903 }"
9904 [(set_attr "type" "f_store")]
9905)
7b1d2fc4 9906
f7fbdd4a 9907;; Special patterns for dealing with the constant pool
9908
cffb2a26 9909(define_insn "align_4"
e1159bbe 9910 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
cffb2a26 9911 "TARGET_EITHER"
f7fbdd4a 9912 "*
cffb2a26 9913 assemble_align (32);
f7fbdd4a 9914 return \"\";
cffb2a26 9915 "
9916)
f7fbdd4a 9917
755eb2b4 9918(define_insn "align_8"
9919 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
f9273c43 9920 "TARGET_EITHER"
755eb2b4 9921 "*
9922 assemble_align (64);
9923 return \"\";
9924 "
9925)
9926
cffb2a26 9927(define_insn "consttable_end"
e1159bbe 9928 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
cffb2a26 9929 "TARGET_EITHER"
f7fbdd4a 9930 "*
cffb2a26 9931 making_const_table = FALSE;
f7fbdd4a 9932 return \"\";
cffb2a26 9933 "
9934)
f7fbdd4a 9935
cffb2a26 9936(define_insn "consttable_1"
e1159bbe 9937 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
cffb2a26 9938 "TARGET_THUMB"
f7fbdd4a 9939 "*
cffb2a26 9940 making_const_table = TRUE;
09d688ff 9941 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
cffb2a26 9942 assemble_zeros (3);
f7fbdd4a 9943 return \"\";
cffb2a26 9944 "
9945 [(set_attr "length" "4")]
9946)
f7fbdd4a 9947
cffb2a26 9948(define_insn "consttable_2"
e1159bbe 9949 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
cffb2a26 9950 "TARGET_THUMB"
f7fbdd4a 9951 "*
cffb2a26 9952 making_const_table = TRUE;
09d688ff 9953 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
cffb2a26 9954 assemble_zeros (2);
f7fbdd4a 9955 return \"\";
cffb2a26 9956 "
9957 [(set_attr "length" "4")]
9958)
9959
9960(define_insn "consttable_4"
e1159bbe 9961 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
cffb2a26 9962 "TARGET_EITHER"
9963 "*
9964 {
9965 making_const_table = TRUE;
9966 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9967 {
9968 case MODE_FLOAT:
9969 {
badfe841 9970 REAL_VALUE_TYPE r;
9971 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9972 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 9973 break;
9974 }
9975 default:
09d688ff 9976 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
cffb2a26 9977 break;
9978 }
9979 return \"\";
9980 }"
9981 [(set_attr "length" "4")]
9982)
9983
9984(define_insn "consttable_8"
e1159bbe 9985 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
cffb2a26 9986 "TARGET_EITHER"
9987 "*
9988 {
9989 making_const_table = TRUE;
9990 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9991 {
9992 case MODE_FLOAT:
9993 {
badfe841 9994 REAL_VALUE_TYPE r;
9995 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9996 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
cffb2a26 9997 break;
9998 }
9999 default:
09d688ff 10000 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
cffb2a26 10001 break;
10002 }
10003 return \"\";
10004 }"
10005 [(set_attr "length" "8")]
10006)
10007
10008;; Miscellaneous Thumb patterns
10009
fd957ef3 10010(define_expand "tablejump"
7db9af5d 10011 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
fd957ef3 10012 (use (label_ref (match_operand 1 "" "")))])]
10013 "TARGET_THUMB"
10014 "
10015 if (flag_pic)
10016 {
10017 /* Hopefully, CSE will eliminate this copy. */
10018 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10019 rtx reg2 = gen_reg_rtx (SImode);
10020
10021 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10022 operands[0] = reg2;
10023 }
10024 "
10025)
10026
f1039640 10027;; NB never uses BX.
fd957ef3 10028(define_insn "*thumb_tablejump"
cffb2a26 10029 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10030 (use (label_ref (match_operand 1 "" "")))]
10031 "TARGET_THUMB"
fd957ef3 10032 "mov\\t%|pc, %0"
cffb2a26 10033 [(set_attr "length" "2")]
10034)
0d66636f 10035
331beb1a 10036;; V5 Instructions,
10037
8f4be2be 10038(define_insn "clzsi2"
10039 [(set (match_operand:SI 0 "s_register_operand" "=r")
10040 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
e1159bbe 10041 "TARGET_ARM && arm_arch5"
ee7cbe0e 10042 "clz%?\\t%0, %1"
10043 [(set_attr "predicable" "yes")])
331beb1a 10044
e1159bbe 10045(define_expand "ffssi2"
10046 [(set (match_operand:SI 0 "s_register_operand" "")
10047 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10048 "TARGET_ARM && arm_arch5"
10049 "
10050 {
10051 rtx t1, t2, t3;
10052
10053 t1 = gen_reg_rtx (SImode);
10054 t2 = gen_reg_rtx (SImode);
10055 t3 = gen_reg_rtx (SImode);
10056
10057 emit_insn (gen_negsi2 (t1, operands[1]));
10058 emit_insn (gen_andsi3 (t2, operands[1], t1));
8f4be2be 10059 emit_insn (gen_clzsi2 (t3, t2));
e1159bbe 10060 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10061 DONE;
10062 }"
10063)
10064
8f4be2be 10065(define_expand "ctzsi2"
10066 [(set (match_operand:SI 0 "s_register_operand" "")
10067 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10068 "TARGET_ARM && arm_arch5"
10069 "
10070 {
10071 rtx t1, t2, t3;
10072
10073 t1 = gen_reg_rtx (SImode);
10074 t2 = gen_reg_rtx (SImode);
10075 t3 = gen_reg_rtx (SImode);
10076
10077 emit_insn (gen_negsi2 (t1, operands[1]));
10078 emit_insn (gen_andsi3 (t2, operands[1], t1));
10079 emit_insn (gen_clzsi2 (t3, t2));
10080 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10081 DONE;
10082 }"
10083)
10084
e1159bbe 10085;; V5E instructions.
331beb1a 10086
10087(define_insn "prefetch"
f4e79814 10088 [(prefetch (match_operand:SI 0 "address_operand" "p")
10089 (match_operand:SI 1 "" "")
10090 (match_operand:SI 2 "" ""))]
e1159bbe 10091 "TARGET_ARM && arm_arch5e"
bcb7a8f6 10092 "pld\\t%a0")
331beb1a 10093
0d66636f 10094;; General predication pattern
10095
10096(define_cond_exec
10097 [(match_operator 0 "arm_comparison_operator"
10098 [(match_operand 1 "cc_register" "")
10099 (const_int 0)])]
10100 "TARGET_ARM"
10101 ""
10102)
10103
063a05c7 10104(define_insn "prologue_use"
10105 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10106 ""
10107 "%@ %0 needed for prologue"
10108)
7db9af5d 10109
4c44712e 10110
10111;; Patterns for exception handling
10112
10113(define_expand "eh_return"
10114 [(use (match_operand 0 "general_operand" ""))]
10115 "TARGET_EITHER"
10116 "
10117 {
10118 if (TARGET_ARM)
10119 emit_insn (gen_arm_eh_return (operands[0]));
10120 else
10121 emit_insn (gen_thumb_eh_return (operands[0]));
10122 DONE;
10123 }"
10124)
10125
10126;; We can't expand this before we know where the link register is stored.
10127(define_insn_and_split "arm_eh_return"
10128 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10129 VUNSPEC_EH_RETURN)
10130 (clobber (match_scratch:SI 1 "=&r"))]
10131 "TARGET_ARM"
10132 "#"
10133 "&& reload_completed"
10134 [(const_int 0)]
10135 "
10136 {
10137 arm_set_return_address (operands[0], operands[1]);
10138 DONE;
10139 }"
10140)
10141
10142(define_insn_and_split "thumb_eh_return"
10143 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10144 VUNSPEC_EH_RETURN)
10145 (clobber (match_scratch:SI 1 "=&l"))]
10146 "TARGET_THUMB"
10147 "#"
10148 "&& reload_completed"
10149 [(const_int 0)]
10150 "
10151 {
10152 thumb_set_return_address (operands[0], operands[1]);
10153 DONE;
10154 }"
10155)
10156
f655717d 10157\f
10158;; TLS support
10159
10160(define_insn "load_tp_hard"
10161 [(set (match_operand:SI 0 "register_operand" "=r")
10162 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10163 "TARGET_HARD_TP"
10164 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10165 [(set_attr "predicable" "yes")]
10166)
10167
10168;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10169(define_insn "load_tp_soft"
10170 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10171 (clobber (reg:SI LR_REGNUM))
10172 (clobber (reg:SI IP_REGNUM))
10173 (clobber (reg:CC CC_REGNUM))]
10174 "TARGET_SOFT_TP"
10175 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10176 [(set_attr "conds" "clob")]
10177)
10178
7db9af5d 10179;; Load the FPA co-processor patterns
10180(include "fpa.md")
10181;; Load the Maverick co-processor patterns
10182(include "cirrus.md")
755eb2b4 10183;; Load the Intel Wireless Multimedia Extension patterns
10184(include "iwmmxt.md")
a2cd141b 10185;; Load the VFP co-processor patterns
10186(include "vfp.md")
10187