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