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