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