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