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